From 884a80de758486a1be19562a5b1e6ffa3764e10e Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Sun, 20 Aug 2017 12:13:04 +0200 Subject: [PATCH] Add automatic installer and upgrader. --- share/man/man7/installation.7 | 3 +- share/man/man7/release-iso-modification.7 | 24 +++- share/man/man7/upgrade.7 | 3 +- sysinstall/Makefile | 8 +- sysinstall/autoconf.c | 132 ++++++++++++++++++++++ sysinstall/autoconf.h | 28 +++++ sysinstall/execute.c | 50 +++++++- sysinstall/interactive.c | 17 ++- sysinstall/sysinstall.c | 82 +++++++++++++- sysinstall/sysupgrade.c | 47 ++++++++ tix/tix-iso-liveconfig | 15 +++ tix/tix-iso-liveconfig.8 | 39 +++++++ 12 files changed, 434 insertions(+), 14 deletions(-) create mode 100644 sysinstall/autoconf.c create mode 100644 sysinstall/autoconf.h diff --git a/share/man/man7/installation.7 b/share/man/man7/installation.7 index c33e0e4c..bc0c3e88 100644 --- a/share/man/man7/installation.7 +++ b/share/man/man7/installation.7 @@ -88,7 +88,8 @@ default bootloader menu option and timeout, the default hostname, the default keyboard layout, the default graphics resolution, adding files of your choice to the live environment, control which drivers are loaded by default, control which live environment daemons are started by default, deploy ssh keys so secure shell -connections are trusted on the first connection, and so on. +connections are trusted on the first connection, configure automatic +installation and upgrading, and and so on. .Pp Warning: The live environment does not come with any random entropy and entropy gathering is not yet implemented. diff --git a/share/man/man7/release-iso-modification.7 b/share/man/man7/release-iso-modification.7 index 002ff5c5..b1dd1eca 100644 --- a/share/man/man7/release-iso-modification.7 +++ b/share/man/man7/release-iso-modification.7 @@ -18,7 +18,8 @@ default bootloader menu option and timeout, the default hostname, the default keyboard layout, the default graphics resolution, adding files of your choice to the live environment, control which drivers are loaded by default, control which live environment daemons are started by default, deploy ssh keys so secure shell -connections are trusted on the first connection, and so on. +connections are trusted on the first connection, configure automatic +installation and upgrading, and and so on. .Ss Prerequisites .Bl -bullet -compact .It @@ -519,6 +520,27 @@ To customize a release so it boots to a console instead of the GUI: tix-iso-bootconfig --disable-gui bootconfig tix-iso-add sortix.iso bootconfig .Ed +.Ss Automatic Installation +To customize a release so it automatically installs itself according to +.Pa autoinstall.conf +(see +.Xr autoinstall.conf 5 ) : +.Bd -literal +tix-iso-liveconfig --autoinstall=autoinstall.conf liveconfig +tix-iso-bootconfig --liveconfig=liveconfig --default=1 bootconfig +tix-iso-add sortix.iso bootconfig +.Ed +.Ss Automatic Upgrade +To customize a release so it automatically upgrades a local installation +according to +.Pa autoupgrade.conf +(see +.Xr autoupgrade.conf 5 ) : +.Bd -literal +tix-iso-liveconfig --autoinstall=autoupgrade.conf liveconfig +tix-iso-bootconfig --liveconfig=liveconfig --default=2 bootconfig +tix-iso-add sortix.iso bootconfig +.Ed .Sh SEE ALSO .Xr xorriso 1 , .Xr development 7 , diff --git a/share/man/man7/upgrade.7 b/share/man/man7/upgrade.7 index 43781ab7..bcc8528e 100644 --- a/share/man/man7/upgrade.7 +++ b/share/man/man7/upgrade.7 @@ -31,7 +31,8 @@ default bootloader menu option and timeout, the default hostname, the default keyboard layout, the default graphics resolution, adding files of your choice to the live environment, control which drivers are loaded by default, control which live environment daemons are started by default, deploy ssh keys so secure shell -connections are trusted on the first connection, and so on. +connections are trusted on the first connection, configure automatic +installation and upgrading, and and so on. .Pp Warning: The live environment does not come with any random entropy and entropy gathering is not yet implemented. diff --git a/sysinstall/Makefile b/sysinstall/Makefile index de019fbc..9a7b93fb 100644 --- a/sysinstall/Makefile +++ b/sysinstall/Makefile @@ -16,6 +16,7 @@ sysmerge.o \ sysupgrade.o \ UTIL_OBJS=\ +autoconf.o \ conf.o \ devices.o \ execute.o \ @@ -28,9 +29,9 @@ string_array.o \ OBJS=$(MAIN_OBJS) $(UTIL_OBJS) -SYSINSTALL_DEPS=conf devices execute fileops interactive manifest release string_array +SYSINSTALL_DEPS=autoconf conf devices execute fileops interactive manifest release string_array SYSMERGE_DEPS=conf fileops execute hooks manifest release string_array -SYSUPGRADE_DEPS=conf devices execute fileops hooks interactive manifest release string_array +SYSUPGRADE_DEPS=autoconf conf devices execute fileops hooks interactive manifest release string_array SYSINSTALL_OBJS:=sysinstall.o $(SYSINSTALL_DEPS:=.o) SYSMERGE_OBJS:=sysmerge.o $(SYSMERGE_DEPS:=.o) @@ -73,13 +74,14 @@ sysupgrade: $(SYSUPGRADE_OBJS) sysinstall.o: $(SYSINSTALL_DEPS:=.h) sysmerge.o: $(SYSMERGE_DEPS:=.h) sysupgrade.o: $(SYSUPGRADE_DEPS:=.h) +autoconf.o: autoconf.h conf.o: conf.h devices.o: devices.h execute.o: execute.h fileops.o: fileops.h string_array.h string_array.o: string_array.h hooks.o: fileops.h manifest.h release.h string_array.h -interactive.o: interactive.h execute.h +interactive.o: interactive.h autoconf.h execute.h manifest.o: manifest.h fileops.h string_array.h release.o: release.h diff --git a/sysinstall/autoconf.c b/sysinstall/autoconf.c new file mode 100644 index 00000000..6d44e9e9 --- /dev/null +++ b/sysinstall/autoconf.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2017 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * autoconf.c + * Parser for autoinstall.conf(5) and autoupgrade.conf(5). + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "autoconf.h" + +// TODO: This file is very unfinished draft stuff. + +bool has_autoconf = false; + +const char* autoconf_get(const char* name) +{ + if ( !name || !has_autoconf ) + return NULL; + return getenv(name); +} + +void autoconf_load(const char* path) +{ + FILE* fp = fopen(path, "r"); + if ( !fp ) + { + if ( errno != ENOENT ) + warn("%s", path); + return; + } + char* line = NULL; + size_t line_size = 0; + ssize_t line_length; + while ( 0 < (line_length = getline(&line, &line_size, fp)) ) + { + if ( line[line_length - 1] == '\n' ) + line[--line_length] = '\0'; + line_length = 0; + while ( line[line_length] && line[line_length] != '#' ) + line_length++; + line[line_length] = '\0'; + char* name = line; + if ( !*name || *name == '=' ) + continue; + size_t name_length = 1; + while ( name[name_length] && + name[name_length] != '=' && + name[name_length] != '+' ) + name_length++; + if ( name[name_length + 0] == '+' && + name[name_length + 1] == '+' && + name[name_length + 2] == '=' ) + { + name[name_length + 0] = '\0'; + char* value = name + name_length + 3; + const char* existing = getenv(name); + if ( existing ) + { + char* full; + if ( asprintf(&full, "%s\n%s", existing, value) < 0 ) + err(2, "%s: asprintf", path); + setenv(name, full, 1); + free(full); + } + else + setenv(name, value, 1); + } + else if ( name[name_length + 0] == '+' && + name[name_length + 1] == '=' ) + { + name[name_length + 0] = '\0'; + char* value = name + name_length + 2; + const char* existing = getenv(name); + if ( existing ) + { + char* full; + if ( asprintf(&full, "%s %s", existing, value) < 0 ) + err(2, "%s: asprintf", path); + setenv(name, full, 1); + free(full); + } + else + setenv(name, value, 1); + } + else if ( name[name_length + 0] == '=' ) + { + name[name_length + 0] = '\0'; + char* value = name + name_length + 1; + setenv(name, value, 1); + } + else + { + // TODO: Graceful. + errx(2, "%s: Bad line: %s", path, line); + } + char* value = name + name_length; + while ( *value && isblank((unsigned char) *value) ) + value++; + if ( *value != '=' ) + continue; + value++; + while ( *value && isblank((unsigned char) *value) ) + value++; + name[name_length] = '\0'; + } + // TODO: Graceful error. + if ( ferror(fp) ) + err(2, "%s", path); + free(line); + fclose(fp); + has_autoconf = true; +} diff --git a/sysinstall/autoconf.h b/sysinstall/autoconf.h new file mode 100644 index 00000000..54fdefaa --- /dev/null +++ b/sysinstall/autoconf.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * autoconf.h + * Parser for autoinstall.conf(5) and autoupgrade.conf(5). + */ + +#ifndef AUTOCONF_H +#define AUTOCONF_H + +extern bool has_autoconf; + +const char* autoconf_get(const char* name); +void autoconf_load(const char* path); + +#endif diff --git a/sysinstall/execute.c b/sysinstall/execute.c index 50c119b2..74f41954 100644 --- a/sysinstall/execute.c +++ b/sysinstall/execute.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016 Jonas 'Sortie' Termansen. + * Copyright (c) 2015, 2016, 2017, 2021 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "execute.h" @@ -34,6 +35,7 @@ int execute(const char* const* argv, const char* flags, ...) bool exit_on_failure = false; bool foreground = false; bool gid_set = false; + const char* input = NULL; bool raw_exit_code = false; bool uid_set = false; bool quiet = false; @@ -50,6 +52,7 @@ int execute(const char* const* argv, const char* flags, ...) case 'e': exit_on_failure = true; break; case 'f': foreground = true; break; case 'g': gid_set = true; gid = va_arg(ap, gid_t); break; + case 'i': input = va_arg(ap, const char*); break; case 'r': raw_exit_code = true; break; case 'u': uid_set = true; uid = va_arg(ap, uid_t); break; case 'q': quiet = true; break; @@ -90,15 +93,56 @@ int execute(const char* const* argv, const char* flags, ...) tcsetpgrp(0, getpgid(0)); sigprocmask(SIG_SETMASK, &oldset, NULL); } + if ( input ) + { + int pipes[2]; + if ( pipe(pipes) < 0 ) + { + if ( !quiet_stderr ) + warn("pipe: %s", argv[0]); + _exit(2); + } + pid_t input_pid = fork(); + if ( input_pid < 0 ) + { + if ( !quiet_stderr ) + warn("fork: %s", argv[0]); + _exit(2); + } + else if ( input_pid == 0 ) + { + close(pipes[0]); + size_t left = strlen(input); + while ( *input ) + { + ssize_t written = write(pipes[1], input, left); + if ( written <= 0 ) + break; + input += written; + left -= written; + } + _exit(0); + } + close(pipes[1]); + close(0); + dup2(pipes[0], 0); + close(pipes[0]); + } if ( quiet ) { close(1); - open("/dev/null", O_WRONLY); + if ( open("/dev/null", O_WRONLY) < 0 ) + { + if ( !quiet_stderr ) + warn("/dev/null"); + _exit(2); + } } if ( quiet_stderr ) { close(2); - open("/dev/null", O_WRONLY); + if ( open("/dev/null", O_WRONLY) < 0 ) + _exit(2); } execvp(argv[0], (char* const*) argv); warn("%s", argv[0]); diff --git a/sysinstall/interactive.c b/sysinstall/interactive.c index e7246b0e..597fc374 100644 --- a/sysinstall/interactive.c +++ b/sysinstall/interactive.c @@ -33,6 +33,7 @@ #include +#include "autoconf.h" #include "execute.h" #include "interactive.h" @@ -160,7 +161,6 @@ void promptx(char* buffer, const char* answer, bool catch_if_shell) { - (void) autoconf_name; while ( true ) { printf("\e[1m"); @@ -171,6 +171,21 @@ void promptx(char* buffer, else printf(" "); fflush(stdout); + const char* autoconf_value = autoconf_get(autoconf_name); + const char* accept_defaults = autoconf_get("accept_defaults"); + const char* automatic_answer = NULL; + if ( autoconf_value ) + automatic_answer = autoconf_value; + else if ( accept_defaults && !strcasecmp(accept_defaults, "yes") ) + automatic_answer = answer; + if ( automatic_answer ) + { + printf("%s\n", automatic_answer); + printf("\e[22m"); + fflush(stdout); + strlcpy(buffer, automatic_answer, buffer_size); + return; + } fgets(buffer, buffer_size, stdin); printf("\e[22m"); fflush(stdout); diff --git a/sysinstall/sysinstall.c b/sysinstall/sysinstall.c index d4d63d5c..7a3903ee 100644 --- a/sysinstall/sysinstall.c +++ b/sysinstall/sysinstall.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,7 @@ #include #include +#include "autoconf.h" #include "conf.h" #include "devices.h" #include "execute.h" @@ -385,6 +387,12 @@ void exit_gui(int code) exit(code); } +static void cancel_on_sigint(int signum) +{ + (void) signum; + errx(2, "fatal: Installation canceled"); +} + int main(void) { shlvl(); @@ -422,11 +430,46 @@ int main(void) if ( !conf_load(&conf, "/etc/upgrade.conf") && errno != ENOENT ) warn("/etc/upgrade.conf"); + autoconf_load("/etc/autoinstall.conf"); + static char input[256]; textf("Hello and welcome to the " BRAND_DISTRIBUTION_NAME " " VERSIONSTR "" " installer for %s.\n\n", uts.machine); + if ( autoconf_get("ready") && + autoconf_get("confirm_install") ) + { + int countdown = 10; + // TODO: Is atoi defined on all inputs? Use a larger integer type! + // Check for bad input! + if ( autoconf_get("countdown") ) + countdown = atoi(autoconf_get("countdown")); + sigset_t old_set; + sigset_t new_set; + sigemptyset(&new_set); + sigaddset(&new_set, SIGINT); + sigprocmask(SIG_BLOCK, &new_set, &old_set); + struct sigaction old_sa; + struct sigaction new_sa = { 0 }; + new_sa.sa_handler = cancel_on_sigint; + sigaction(SIGINT, &new_sa, &old_sa); + for ( ; 0 < countdown; countdown-- ) + { + textf("Automatically installing " BRAND_DISTRIBUTION_NAME " " + VERSIONSTR " in %i %s... (Control-C to cancel)\n", countdown, + countdown != 1 ? "seconds" : "second"); + sigprocmask(SIG_SETMASK, &old_set, NULL); + sleep(1); + sigprocmask(SIG_BLOCK, &new_set, &old_set); + } + textf("Automatically installing " BRAND_DISTRIBUTION_NAME " " + VERSIONSTR "...\n"); + text("\n"); + sigaction(SIGINT, &old_sa, NULL); + sigprocmask(SIG_SETMASK, &old_set, NULL); + } + // '|' rather than '||' is to ensure side effects. if ( missing_program("cut") | missing_program("dash") | @@ -478,6 +521,13 @@ int main(void) }; size_t num_readies = sizeof(readies) / sizeof(readies[0]); const char* ready = readies[arc4random_uniform(num_readies)]; + if ( autoconf_get("disked") ) + text("Warning: This installer will perform automatic harddisk " + "partitioning!\n"); + if ( autoconf_get("confirm_install") && + !strcasecmp(autoconf_get("confirm_install"), "yes") ) + text("Warning: This installer will automatically install an operating " + "system!\n"); prompt(input, sizeof(input), "ready", "Ready?", ready); text("\n"); @@ -686,7 +736,12 @@ int main(void) strcasecmp(accept_grub_password, "yes") == 0 ) break; } - while ( !strcasecmp(accept_grub_password, "yes") ) + if ( autoconf_get("grub_password_hash") ) + { + const char* hash = autoconf_get("grub_password_hash"); + install_configurationf("grubpw", "w", "%s\n", hash); + } + else while ( !strcasecmp(accept_grub_password, "yes") ) { char first[128]; char second[128]; @@ -755,7 +810,8 @@ int main(void) text("Type man to display the disked(8) man page.\n"); not_first = true; const char* argv[] = { "disked", "--fstab=fstab", NULL }; - if ( execute(argv, "f") != 0 ) + const char* disked_input = autoconf_get("disked"); + if ( execute(argv, "fi", disked_input) != 0 ) { // TODO: We also end up here on SIGINT. // TODO: Offer a shell here instead of failing? @@ -1030,6 +1086,21 @@ int main(void) { textf("Root account already exists, skipping creating it.\n"); } + else if ( autoconf_get("password_hash_root") ) + { + const char* hash = autoconf_get("password_hash_root"); + if ( !install_configurationf("etc/passwd", "a", + "root:%s:0:0:root:/root:sh\n" + "include /etc/default/passwd.d/*\n", hash) ) + err(2, "etc/passwd"); + textf("User '%s' added to /etc/passwd\n", "root"); + if ( !install_configurationf("etc/group", "a", + "root::0:root\n" + "include /etc/default/group.d/*\n") ) + err(2, "etc/passwd"); + install_skel("/root", 0, 0); + textf("Group '%s' added to /etc/group.\n", "root"); + } else while ( true ) { char first[128]; @@ -1139,8 +1210,9 @@ int main(void) text("Congratulations, the system is now functional! This is a good time " "to do further customization of the system.\n\n"); + // TODO: autoconf users support. bool made_user = false; - for ( uid_t uid = 1000; true; ) + for ( uid_t uid = 1000; !has_autoconf; ) { while ( passwd_has_uid("etc/passwd", uid) ) uid++; @@ -1222,7 +1294,9 @@ int main(void) uid++; made_user = true; } - text("\n"); + // TODO: autoconf support. + if ( !has_autoconf ) + text("\n"); // TODO: Ask if networking should be disabled / enabled. diff --git a/sysinstall/sysupgrade.c b/sysinstall/sysupgrade.c index 12184d70..0937f047 100644 --- a/sysinstall/sysupgrade.c +++ b/sysinstall/sysupgrade.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ #include #include +#include "autoconf.h" #include "conf.h" #include "devices.h" #include "execute.h" @@ -338,6 +340,12 @@ void exit_gui(int code) exit(code); } +static void cancel_on_sigint(int signum) +{ + (void) signum; + errx(2, "fatal: Upgrade canceled"); +} + int main(void) { shlvl(); @@ -358,6 +366,8 @@ int main(void) if ( atexit(exit_handler) != 0 ) err(2, "atexit"); + autoconf_load("/etc/autoupgrade.conf"); + struct utsname uts; uname(&uts); @@ -366,6 +376,39 @@ int main(void) textf("Hello and welcome to the " BRAND_DISTRIBUTION_NAME " " VERSIONSTR "" " upgrader for %s.\n\n", uts.machine); + if ( autoconf_get("ready") && + autoconf_get("confirm_install") ) + { + int countdown = 10; + // TODO: Is atoi defined on all inputs? Use a larger integer type! + // Check for bad input! + if ( autoconf_get("countdown") ) + countdown = atoi(autoconf_get("countdown")); + sigset_t old_set; + sigset_t new_set; + sigemptyset(&new_set); + sigaddset(&new_set, SIGINT); + sigprocmask(SIG_BLOCK, &new_set, &old_set); + struct sigaction old_sa; + struct sigaction new_sa = { 0 }; + new_sa.sa_handler = cancel_on_sigint; + sigaction(SIGINT, &new_sa, &old_sa); + for ( ; 0 < countdown; countdown-- ) + { + textf("Automatically upgrading to " BRAND_DISTRIBUTION_NAME " " + VERSIONSTR " in %i %s... (Control-C to cancel)\n", countdown, + countdown != 1 ? "seconds" : "second"); + sigprocmask(SIG_SETMASK, &old_set, NULL); + sleep(1); + sigprocmask(SIG_BLOCK, &new_set, &old_set); + } + textf("Automatically upgrading " BRAND_DISTRIBUTION_NAME " " + VERSIONSTR "...\n"); + text("\n"); + sigaction(SIGINT, &old_sa, NULL); + sigprocmask(SIG_SETMASK, &old_set, NULL); + } + // '|' rather than '||' is to ensure side effects. if ( missing_program("cut") | missing_program("dash") | @@ -410,6 +453,10 @@ int main(void) }; size_t num_readies = sizeof(readies) / sizeof(readies[0]); const char* ready = readies[arc4random_uniform(num_readies)]; + if ( autoconf_get("confirm_upgrade") && + !strcasecmp(autoconf_get("confirm_upgrade"), "yes") ) + text("Warning: This upgrader will automatically upgrade an operating " + "system!\n"); prompt(input, sizeof(input), "ready", "Ready?", ready); text("\n"); diff --git a/tix/tix-iso-liveconfig b/tix/tix-iso-liveconfig index 5b8d82a1..b6d15033 100755 --- a/tix/tix-iso-liveconfig +++ b/tix/tix-iso-liveconfig @@ -18,6 +18,8 @@ set -e +autoinstall= +autoupgrade= daemons= directory= hostname= @@ -51,6 +53,10 @@ for argument do case $dashdash$argument in --) dashdash=yes ;; + --autoinstall=*) autoinstall=$parameter ;; + --autoinstall) previous_option=autoinstall ;; + --autoupgrade=*) autoupgrade=$parameter ;; + --autoupgrade) previous_option=autoupgrade ;; --daemons=*) daemons=$parameter ;; --daemons) previous_option=daemons ;; --hostname=*) hostname=$parameter ;; @@ -101,6 +107,15 @@ fi mkdir -p "$directory" +if [ -n "$autoinstall" ]; then + mkdir -p -- "$directory/etc" + cp -- "$autoinstall" "$directory/etc/autoinstall.conf" +fi + +if [ -n "$autoupgrade" ]; then + mkdir -p "-- $directory/etc" + cp -- "$autoupgrade" "$directory/etc/autoupgrade.conf" +fi if [ -n "$daemons" ]; then mkdir -p -- "$directory/etc/init" diff --git a/tix/tix-iso-liveconfig.8 b/tix/tix-iso-liveconfig.8 index 3ff73c89..81aeac88 100644 --- a/tix/tix-iso-liveconfig.8 +++ b/tix/tix-iso-liveconfig.8 @@ -6,6 +6,8 @@ .Nd generate additional live environment configuration for Sortix .iso releases .Sh SYNOPSIS .Nm +.Op Fl \-autoinstall Ns = Ns Ar file +.Op Fl \-autoupgrade Ns = Ns Ar file .Op Fl \-daemons Ns = Ns Ar daemons .Op Fl \-hostname Ns = Ns Ar hostname .Op Fl \-kblayout Ns = Ns Ar kblayout @@ -53,6 +55,20 @@ installations made from inside it. .Pp The options are as follows: .Bl -tag -width "12345678" +.It Fl \-autoinstall Ns = Ns Ar file +Copy +.Ar file +to +.Pa output-directory/etc/autoinstall.conf . +(See +.Xr autoinstall.conf 5 ) +.It Fl \-autoupgrade Ns = Ns Ar file +Copy +.Ar file +to +.Pa output-directory/etc/autoupgrade.conf . +(See +.Xr autoupgrade.conf 5 ) .It Fl \-daemons Ns = Ns Ar daemons Configures the .Sy local @@ -286,9 +302,32 @@ rm -f bootconfig/boot/liveconfig.xz # When no longer useful. rm -f sortix.iso # When no longer useful. # And erase any media made from sortix.iso when no longer useful. .Ed +.Ss Automatic Installation +To customize a release so it automatically installs itself according to +.Pa autoinstall.conf +(see +.Xr autoinstall.conf 5 ) : +.Bd -literal +tix-iso-liveconfig --autoinstall=autoinstall.conf liveconfig +tix-iso-bootconfig --liveconfig=liveconfig --default=1 bootconfig +tix-iso-add sortix.iso bootconfig +.Ed +.Ss Automatic Upgrade +To customize a release so it automatically upgrades a local installation +according to +.Pa autoupgrade.conf +(see +.Xr autoupgrade.conf 5 ) : +.Bd -literal +tix-iso-liveconfig --autoinstall=autoupgrade.conf liveconfig +tix-iso-bootconfig --liveconfig=liveconfig --default=2 bootconfig +tix-iso-add sortix.iso bootconfig +.Ed .Sh SEE ALSO .Xr ssh-keygen 1 , .Xr xorriso 1 , +.Xr autoinstall.conf 5 , +.Xr autoupgrade.conf 5 , .Xr hostname 5 , .Xr kblayout 5 , .Xr ssh_config 5 ,