Add automatic installer and upgrader.
This commit is contained in:
parent
80bdac32ec
commit
08cc3b4b6f
|
@ -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
|
keyboard layout, the default graphics resolution, adding files of your choice to
|
||||||
the live environment, control which drivers are loaded by default, control which
|
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
|
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
|
.Pp
|
||||||
Warning: The live environment does not come with any random entropy and entropy
|
Warning: The live environment does not come with any random entropy and entropy
|
||||||
gathering is not yet implemented.
|
gathering is not yet implemented.
|
||||||
|
|
|
@ -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
|
keyboard layout, the default graphics resolution, adding files of your choice to
|
||||||
the live environment, control which drivers are loaded by default, control which
|
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
|
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
|
.Ss Prerequisites
|
||||||
.Bl -bullet -compact
|
.Bl -bullet -compact
|
||||||
.It
|
.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-bootconfig --disable-gui bootconfig
|
||||||
tix-iso-add sortix.iso bootconfig
|
tix-iso-add sortix.iso bootconfig
|
||||||
.Ed
|
.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
|
.Sh SEE ALSO
|
||||||
.Xr xorriso 1 ,
|
.Xr xorriso 1 ,
|
||||||
.Xr development 7 ,
|
.Xr development 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
|
keyboard layout, the default graphics resolution, adding files of your choice to
|
||||||
the live environment, control which drivers are loaded by default, control which
|
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
|
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
|
.Pp
|
||||||
Warning: The live environment does not come with any random entropy and entropy
|
Warning: The live environment does not come with any random entropy and entropy
|
||||||
gathering is not yet implemented.
|
gathering is not yet implemented.
|
||||||
|
|
|
@ -16,6 +16,7 @@ sysmerge.o \
|
||||||
sysupgrade.o \
|
sysupgrade.o \
|
||||||
|
|
||||||
UTIL_OBJS=\
|
UTIL_OBJS=\
|
||||||
|
autoconf.o \
|
||||||
conf.o \
|
conf.o \
|
||||||
devices.o \
|
devices.o \
|
||||||
execute.o \
|
execute.o \
|
||||||
|
@ -28,9 +29,9 @@ string_array.o \
|
||||||
|
|
||||||
OBJS=$(MAIN_OBJS) $(UTIL_OBJS)
|
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
|
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)
|
SYSINSTALL_OBJS:=sysinstall.o $(SYSINSTALL_DEPS:=.o)
|
||||||
SYSMERGE_OBJS:=sysmerge.o $(SYSMERGE_DEPS:=.o)
|
SYSMERGE_OBJS:=sysmerge.o $(SYSMERGE_DEPS:=.o)
|
||||||
|
@ -73,13 +74,14 @@ sysupgrade: $(SYSUPGRADE_OBJS)
|
||||||
sysinstall.o: $(SYSINSTALL_DEPS:=.h)
|
sysinstall.o: $(SYSINSTALL_DEPS:=.h)
|
||||||
sysmerge.o: $(SYSMERGE_DEPS:=.h)
|
sysmerge.o: $(SYSMERGE_DEPS:=.h)
|
||||||
sysupgrade.o: $(SYSUPGRADE_DEPS:=.h)
|
sysupgrade.o: $(SYSUPGRADE_DEPS:=.h)
|
||||||
|
autoconf.o: autoconf.h
|
||||||
conf.o: conf.h
|
conf.o: conf.h
|
||||||
devices.o: devices.h
|
devices.o: devices.h
|
||||||
execute.o: execute.h
|
execute.o: execute.h
|
||||||
fileops.o: fileops.h string_array.h
|
fileops.o: fileops.h string_array.h
|
||||||
string_array.o: string_array.h
|
string_array.o: string_array.h
|
||||||
hooks.o: fileops.h manifest.h release.h 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
|
manifest.o: manifest.h fileops.h string_array.h
|
||||||
release.o: release.h
|
release.o: release.h
|
||||||
|
|
||||||
|
|
|
@ -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 <ctype.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "execute.h"
|
#include "execute.h"
|
||||||
|
@ -34,6 +35,7 @@ int execute(const char* const* argv, const char* flags, ...)
|
||||||
bool exit_on_failure = false;
|
bool exit_on_failure = false;
|
||||||
bool foreground = false;
|
bool foreground = false;
|
||||||
bool gid_set = false;
|
bool gid_set = false;
|
||||||
|
const char* input = NULL;
|
||||||
bool raw_exit_code = false;
|
bool raw_exit_code = false;
|
||||||
bool uid_set = false;
|
bool uid_set = false;
|
||||||
bool quiet = 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 'e': exit_on_failure = true; break;
|
||||||
case 'f': foreground = true; break;
|
case 'f': foreground = true; break;
|
||||||
case 'g': gid_set = true; gid = va_arg(ap, gid_t); 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 'r': raw_exit_code = true; break;
|
||||||
case 'u': uid_set = true; uid = va_arg(ap, uid_t); break;
|
case 'u': uid_set = true; uid = va_arg(ap, uid_t); break;
|
||||||
case 'q': quiet = true; break;
|
case 'q': quiet = true; break;
|
||||||
|
@ -90,15 +93,56 @@ int execute(const char* const* argv, const char* flags, ...)
|
||||||
tcsetpgrp(0, getpgid(0));
|
tcsetpgrp(0, getpgid(0));
|
||||||
sigprocmask(SIG_SETMASK, &oldset, NULL);
|
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 )
|
if ( quiet )
|
||||||
{
|
{
|
||||||
close(1);
|
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 )
|
if ( quiet_stderr )
|
||||||
{
|
{
|
||||||
close(2);
|
close(2);
|
||||||
open("/dev/null", O_WRONLY);
|
if ( open("/dev/null", O_WRONLY) < 0 )
|
||||||
|
_exit(2);
|
||||||
}
|
}
|
||||||
execvp(argv[0], (char* const*) argv);
|
execvp(argv[0], (char* const*) argv);
|
||||||
warn("%s", argv[0]);
|
warn("%s", argv[0]);
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
|
|
||||||
#include <display.h>
|
#include <display.h>
|
||||||
|
|
||||||
|
#include "autoconf.h"
|
||||||
#include "execute.h"
|
#include "execute.h"
|
||||||
#include "interactive.h"
|
#include "interactive.h"
|
||||||
|
|
||||||
|
@ -160,7 +161,6 @@ void promptx(char* buffer,
|
||||||
const char* answer,
|
const char* answer,
|
||||||
bool catch_if_shell)
|
bool catch_if_shell)
|
||||||
{
|
{
|
||||||
(void) autoconf_name;
|
|
||||||
while ( true )
|
while ( true )
|
||||||
{
|
{
|
||||||
printf("\e[1m");
|
printf("\e[1m");
|
||||||
|
@ -171,6 +171,21 @@ void promptx(char* buffer,
|
||||||
else
|
else
|
||||||
printf(" ");
|
printf(" ");
|
||||||
fflush(stdout);
|
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);
|
fgets(buffer, buffer_size, stdin);
|
||||||
printf("\e[22m");
|
printf("\e[22m");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <fstab.h>
|
#include <fstab.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -53,6 +54,7 @@
|
||||||
#include <mount/partition.h>
|
#include <mount/partition.h>
|
||||||
#include <mount/uuid.h>
|
#include <mount/uuid.h>
|
||||||
|
|
||||||
|
#include "autoconf.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "devices.h"
|
#include "devices.h"
|
||||||
#include "execute.h"
|
#include "execute.h"
|
||||||
|
@ -385,6 +387,12 @@ void exit_gui(int code)
|
||||||
exit(code);
|
exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cancel_on_sigint(int signum)
|
||||||
|
{
|
||||||
|
(void) signum;
|
||||||
|
errx(2, "fatal: Installation canceled");
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
shlvl();
|
shlvl();
|
||||||
|
@ -422,11 +430,46 @@ int main(void)
|
||||||
if ( !conf_load(&conf, "/etc/upgrade.conf") && errno != ENOENT )
|
if ( !conf_load(&conf, "/etc/upgrade.conf") && errno != ENOENT )
|
||||||
warn("/etc/upgrade.conf");
|
warn("/etc/upgrade.conf");
|
||||||
|
|
||||||
|
autoconf_load("/etc/autoinstall.conf");
|
||||||
|
|
||||||
static char input[256];
|
static char input[256];
|
||||||
|
|
||||||
textf("Hello and welcome to the " BRAND_DISTRIBUTION_NAME " " VERSIONSTR ""
|
textf("Hello and welcome to the " BRAND_DISTRIBUTION_NAME " " VERSIONSTR ""
|
||||||
" installer for %s.\n\n", uts.machine);
|
" 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.
|
// '|' rather than '||' is to ensure side effects.
|
||||||
if ( missing_program("cut") |
|
if ( missing_program("cut") |
|
||||||
missing_program("dash") |
|
missing_program("dash") |
|
||||||
|
@ -478,6 +521,13 @@ int main(void)
|
||||||
};
|
};
|
||||||
size_t num_readies = sizeof(readies) / sizeof(readies[0]);
|
size_t num_readies = sizeof(readies) / sizeof(readies[0]);
|
||||||
const char* ready = readies[arc4random_uniform(num_readies)];
|
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);
|
prompt(input, sizeof(input), "ready", "Ready?", ready);
|
||||||
text("\n");
|
text("\n");
|
||||||
|
|
||||||
|
@ -686,7 +736,12 @@ int main(void)
|
||||||
strcasecmp(accept_grub_password, "yes") == 0 )
|
strcasecmp(accept_grub_password, "yes") == 0 )
|
||||||
break;
|
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 first[128];
|
||||||
char second[128];
|
char second[128];
|
||||||
|
@ -755,7 +810,8 @@ int main(void)
|
||||||
text("Type man to display the disked(8) man page.\n");
|
text("Type man to display the disked(8) man page.\n");
|
||||||
not_first = true;
|
not_first = true;
|
||||||
const char* argv[] = { "disked", "--fstab=fstab", NULL };
|
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: We also end up here on SIGINT.
|
||||||
// TODO: Offer a shell here instead of failing?
|
// TODO: Offer a shell here instead of failing?
|
||||||
|
@ -1030,6 +1086,21 @@ int main(void)
|
||||||
{
|
{
|
||||||
textf("Root account already exists, skipping creating it.\n");
|
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 )
|
else while ( true )
|
||||||
{
|
{
|
||||||
char first[128];
|
char first[128];
|
||||||
|
@ -1139,8 +1210,9 @@ int main(void)
|
||||||
text("Congratulations, the system is now functional! This is a good time "
|
text("Congratulations, the system is now functional! This is a good time "
|
||||||
"to do further customization of the system.\n\n");
|
"to do further customization of the system.\n\n");
|
||||||
|
|
||||||
|
// TODO: autoconf users support.
|
||||||
bool made_user = false;
|
bool made_user = false;
|
||||||
for ( uid_t uid = 1000; true; )
|
for ( uid_t uid = 1000; !has_autoconf; )
|
||||||
{
|
{
|
||||||
while ( passwd_has_uid("etc/passwd", uid) )
|
while ( passwd_has_uid("etc/passwd", uid) )
|
||||||
uid++;
|
uid++;
|
||||||
|
@ -1222,7 +1294,9 @@ int main(void)
|
||||||
uid++;
|
uid++;
|
||||||
made_user = true;
|
made_user = true;
|
||||||
}
|
}
|
||||||
text("\n");
|
// TODO: autoconf support.
|
||||||
|
if ( !has_autoconf )
|
||||||
|
text("\n");
|
||||||
|
|
||||||
// TODO: Ask if networking should be disabled / enabled.
|
// TODO: Ask if networking should be disabled / enabled.
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fstab.h>
|
#include <fstab.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -42,6 +43,7 @@
|
||||||
#include <mount/harddisk.h>
|
#include <mount/harddisk.h>
|
||||||
#include <mount/partition.h>
|
#include <mount/partition.h>
|
||||||
|
|
||||||
|
#include "autoconf.h"
|
||||||
#include "conf.h"
|
#include "conf.h"
|
||||||
#include "devices.h"
|
#include "devices.h"
|
||||||
#include "execute.h"
|
#include "execute.h"
|
||||||
|
@ -338,6 +340,12 @@ void exit_gui(int code)
|
||||||
exit(code);
|
exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cancel_on_sigint(int signum)
|
||||||
|
{
|
||||||
|
(void) signum;
|
||||||
|
errx(2, "fatal: Upgrade canceled");
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
shlvl();
|
shlvl();
|
||||||
|
@ -358,6 +366,8 @@ int main(void)
|
||||||
if ( atexit(exit_handler) != 0 )
|
if ( atexit(exit_handler) != 0 )
|
||||||
err(2, "atexit");
|
err(2, "atexit");
|
||||||
|
|
||||||
|
autoconf_load("/etc/autoupgrade.conf");
|
||||||
|
|
||||||
struct utsname uts;
|
struct utsname uts;
|
||||||
uname(&uts);
|
uname(&uts);
|
||||||
|
|
||||||
|
@ -366,6 +376,39 @@ int main(void)
|
||||||
textf("Hello and welcome to the " BRAND_DISTRIBUTION_NAME " " VERSIONSTR ""
|
textf("Hello and welcome to the " BRAND_DISTRIBUTION_NAME " " VERSIONSTR ""
|
||||||
" upgrader for %s.\n\n", uts.machine);
|
" 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.
|
// '|' rather than '||' is to ensure side effects.
|
||||||
if ( missing_program("cut") |
|
if ( missing_program("cut") |
|
||||||
missing_program("dash") |
|
missing_program("dash") |
|
||||||
|
@ -410,6 +453,10 @@ int main(void)
|
||||||
};
|
};
|
||||||
size_t num_readies = sizeof(readies) / sizeof(readies[0]);
|
size_t num_readies = sizeof(readies) / sizeof(readies[0]);
|
||||||
const char* ready = readies[arc4random_uniform(num_readies)];
|
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);
|
prompt(input, sizeof(input), "ready", "Ready?", ready);
|
||||||
text("\n");
|
text("\n");
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
autoinstall=
|
||||||
|
autoupgrade=
|
||||||
daemons=
|
daemons=
|
||||||
directory=
|
directory=
|
||||||
hostname=
|
hostname=
|
||||||
|
@ -51,6 +53,10 @@ for argument do
|
||||||
|
|
||||||
case $dashdash$argument in
|
case $dashdash$argument in
|
||||||
--) dashdash=yes ;;
|
--) dashdash=yes ;;
|
||||||
|
--autoinstall=*) autoinstall=$parameter ;;
|
||||||
|
--autoinstall) previous_option=autoinstall ;;
|
||||||
|
--autoupgrade=*) autoupgrade=$parameter ;;
|
||||||
|
--autoupgrade) previous_option=autoupgrade ;;
|
||||||
--daemons=*) daemons=$parameter ;;
|
--daemons=*) daemons=$parameter ;;
|
||||||
--daemons) previous_option=daemons ;;
|
--daemons) previous_option=daemons ;;
|
||||||
--hostname=*) hostname=$parameter ;;
|
--hostname=*) hostname=$parameter ;;
|
||||||
|
@ -101,6 +107,15 @@ fi
|
||||||
|
|
||||||
mkdir -p "$directory"
|
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
|
if [ -n "$daemons" ]; then
|
||||||
mkdir -p -- "$directory/etc/init"
|
mkdir -p -- "$directory/etc/init"
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
.Nd generate additional live environment configuration for Sortix .iso releases
|
.Nd generate additional live environment configuration for Sortix .iso releases
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
|
.Op Fl \-autoinstall Ns = Ns Ar file
|
||||||
|
.Op Fl \-autoupgrade Ns = Ns Ar file
|
||||||
.Op Fl \-daemons Ns = Ns Ar daemons
|
.Op Fl \-daemons Ns = Ns Ar daemons
|
||||||
.Op Fl \-hostname Ns = Ns Ar hostname
|
.Op Fl \-hostname Ns = Ns Ar hostname
|
||||||
.Op Fl \-kblayout Ns = Ns Ar kblayout
|
.Op Fl \-kblayout Ns = Ns Ar kblayout
|
||||||
|
@ -53,6 +55,20 @@ installations made from inside it.
|
||||||
.Pp
|
.Pp
|
||||||
The options are as follows:
|
The options are as follows:
|
||||||
.Bl -tag -width "12345678"
|
.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
|
.It Fl \-daemons Ns = Ns Ar daemons
|
||||||
Configures the
|
Configures the
|
||||||
.Sy local
|
.Sy local
|
||||||
|
@ -286,9 +302,32 @@ rm -f bootconfig/boot/liveconfig.xz # When no longer useful.
|
||||||
rm -f sortix.iso # When no longer useful.
|
rm -f sortix.iso # When no longer useful.
|
||||||
# And erase any media made from sortix.iso when no longer useful.
|
# And erase any media made from sortix.iso when no longer useful.
|
||||||
.Ed
|
.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
|
.Sh SEE ALSO
|
||||||
.Xr ssh-keygen 1 ,
|
.Xr ssh-keygen 1 ,
|
||||||
.Xr xorriso 1 ,
|
.Xr xorriso 1 ,
|
||||||
|
.Xr autoinstall.conf 5 ,
|
||||||
|
.Xr autoupgrade.conf 5 ,
|
||||||
.Xr hostname 5 ,
|
.Xr hostname 5 ,
|
||||||
.Xr kblayout 5 ,
|
.Xr kblayout 5 ,
|
||||||
.Xr ssh_config 5 ,
|
.Xr ssh_config 5 ,
|
||||||
|
|
Loading…
Reference in New Issue