Compare commits

..

33 Commits

Author SHA1 Message Date
Jonas 'Sortie' Termansen 3730c07330 Aurora procedural wallpaper. 2023-05-14 23:14:16 +02:00
Jonas 'Sortie' Termansen 3b2685931b Work around pty deadlock. 2023-05-14 23:14:16 +02:00
Jonas 'Sortie' Termansen 86acd95309 Add cdrom mounting live environment. 2023-05-14 23:14:16 +02:00
Jonas 'Sortie' Termansen 64c65ddba0 Revert "Parallelize driver initialization."
This reverts commit 0fef08bbc4.
2023-05-14 23:14:16 +02:00
Jonas 'Sortie' Termansen 4552947ac9 Parallelize driver initialization. 2023-05-14 23:14:16 +02:00
Jonas 'Sortie' Termansen d22b3ddd15 Speed up ata(4) 400 ns waits.
Waiting for any non-zero duration currently waits for at least one timer
cycle (10 ms), which is especially expensive during early boot.

The current workaround of simply reading the status 14 times seems really
suspicious although the osdev wiki documents it, but let's see how well it
works on real hardware, it's probably good enough.

Try to determine the initial selected drive to save one drive selection.
2023-05-14 23:14:16 +02:00
Jonas 'Sortie' Termansen 0c82f0236a Decrease PS/2 timeouts. 2023-05-14 23:14:16 +02:00
Jonas 'Sortie' Termansen fa53637420 Add uptime(1) -pr options. 2023-05-14 23:14:16 +02:00
Jonas 'Sortie' Termansen 9c27584adf Add iso9660 filesystem implementation. 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen b93ce9f6d0 Add kernel virtual address space usage debug information. 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen ba51698db2 Revert "Update to bison-3.8.2."
This reverts commit b82fae810b42c5426d21c4dc153b32f086dd7fde.
2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen be9d4bdf36 Update to bison-3.8.2. 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen f57ad489b6 Debug TCP socket state listing. 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen 956ec4355d Add kernel heap allocation tracing debug facility. 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen 76cf62062b Add m4, perl, and texinfo to the basic ports set. 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen eab3628b2d Trianglix 4. 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen 74569706a5 Add tix-check(8). 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen 27b7ad2fab Volatile release. 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen 77ac43ea39 Add tix-upgrade(8). 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen 80054fe389 Add display server. 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen 348e89d5be Add pty(1). 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen 5aa7e56123 Add signify port. 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen 26284dec59 Add irc(1).
Co-authored-by: Juhani Krekelä <juhani@krekelä.fi>
2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen 3462079741 Add getaddrinfo(1). 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen 3a72e024de Add host(1). 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen c6f2dd602f Add automatic installer and upgrader. 2023-05-14 23:14:15 +02:00
Jonas 'Sortie' Termansen eaee5c4838 Enable stack smash protection by default. 2023-04-23 23:35:08 +02:00
Jonas 'Sortie' Termansen 2abdecf59a Enable undefined behavior sanitization by default. 2023-04-23 23:35:08 +02:00
Jonas 'Sortie' Termansen e9d9eabb6e Add non-interactive mode to disked(8). 2023-04-23 23:35:08 +02:00
Jonas 'Sortie' Termansen b029127df5 Add passwd(1) -H option. 2023-04-23 23:35:08 +02:00
Jonas 'Sortie' Termansen c77745e447 Change chvidemode(1) to set requested mode instead of running command. 2023-04-22 19:54:40 +02:00
Juhani Krekelä adcf11944f Update to libressl-3.7.2. 2023-04-21 23:00:33 +03:00
Juhani Krekelä 4657132716 Fix tix-port(8) diffs on non-English locales.
tix-port(8) parses the diff(1) output, to remove the "Only in …"
informational messages. As they are meant to be human-readable, not
machine-readable, they are translated to different languages, which
causes tix-port(8) to miss them. This patch sets LC_ALL=C for the diff
invocation, so that the messages are always in English.
2023-04-12 14:01:11 +03:00
21 changed files with 977 additions and 179 deletions

View File

@ -203,6 +203,9 @@ else
fi
set base_menu_title="Sortix \$version for \$machine"
set menu_title="\$base_menu_title"
set title_single_user='live environment'
set title_sysinstall='new installation'
set title_sysupgrade='upgrade existing installation'
set timeout=10
set default="0"
if [ -e /boot/random.seed ]; then
@ -223,6 +226,9 @@ export mount
export chain
export base_menu_title
export menu_title
export title_single_user
export title_sysinstall
export title_sysupgrade
export timeout
export default
export no_random_seed
@ -436,9 +442,9 @@ menu_title="\$base_menu_title"
hook_menu_pre
EOF
menuentry "live environment" '-- /sbin/init --target=single-user'
menuentry "new installation" '-- /sbin/init --target=sysinstall'
menuentry "upgrade existing installation" '-- /sbin/init --target=sysupgrade'
menuentry "\$title_single_user" '-- /sbin/init --target=single-user'
menuentry "\$title_sysinstall" '-- /sbin/init --target=sysinstall'
menuentry "\$title_sysupgrade" '-- /sbin/init --target=sysupgrade'
cat << EOF

View File

@ -6,7 +6,10 @@
.Nd disk editor
.Sh SYNOPSIS
.Nm disked
.Op Fl in
.Op Fl \-fstab Ns "=" Ns Ar path
.Op Ar device
.Op Ar command ...
.Sh DESCRIPTION
.Nm
is an interactive program that manages partition tables.
@ -19,17 +22,22 @@ supports the Master Boot Record and GUID Partition Table partitioning schemes.
.Pp
.Nm
provides an interactive command line.
Its prompt shows the currently selected device (defaulting to the first device
alphabetically) or
Its prompt shows the currently selected
.Ar device
(defaulting to the first device alphabetically if any) or
.Li (disked)
if none is selected.
If a
.Ar command
is specified on the command line, then that command is run with its arguments
non-interactively instead of reading from the standard input.
.Pp
Commands perform their actions when run rather than waiting for the user to
write out changes.
.Nm
only creates partitions aligned to 1 MiB boundaries whose size is a multiple of
1 MiB.
Unused regions are aligned and those smaller than the alignment are not shown.
.Pp
The options are as follows:
.Bl -tag -width "12345678"
.It Fl \-fstab Ns "=" Ns Ar path
@ -39,6 +47,17 @@ instead of
.Pa /etc/fstab
as
.Xr fstab 5 .
.It Fl i
Run in interactive mode with prompt with line editing.
Commands will ask for missing parameters.
This is the default if the standard input and output are terminals and a
.Ar command
is not specified on the command line.
.It Fl n
Run in non-interactive mode reading commands from the standard input.
Commands will not ask for missing parameters and
.Nm
will immediately exit unsuccessfully if any command fail.
.El
.Pp
The following commands are supported:
@ -78,14 +97,19 @@ Partitions are counted from 1.
Display this manual page if no operands are given, otherwise run
.Xr man 1
with the given command line.
.It Sy mkpart
.It Sy mkpart Ar hole Ar offset Ar length Ar filesystem Ar mountpoint
Create a partition on the current device.
If the partition table has multiple unused regions
.Pq holes ,
.Nm
asks you which one to use.
You need to specify the offset into the hole where the partition is created and
then the length of the partition.
asks you which
.Ar hole
(counting from 1) to use.
You need to specify the
.Ar offset
into the hole where the partition is created and
then the
.Ar length of the partition.
See
.Sx QUANTITIES
below on the possible partition offset and length values.
@ -106,7 +130,9 @@ Use the existing disk data.
.El
.Pp
If you format a mountable filesystem, then you will be asked if you want to
create a mountpoint for the partition, which will be added to
create a
.Ar mountpoint
for the partition, which will be added to
.Xr fstab 5 .
.It Sy mktable Oo mbr "|" gpt Oc
Create a partition table on the current device of the specified type.

View File

@ -240,6 +240,8 @@ static const char* device_name(const char* name)
return name;
}
static bool interactive;
static void display_rows_columns(char* (*format)(void*, size_t, size_t),
void* ctx, size_t rows, size_t columns)
{
@ -395,6 +397,8 @@ static void prompt(char* buffer,
const char* question,
const char* answer)
{
if ( !interactive )
errx(1, "Cannot ask question in non-interactive mode: %s", question);
while ( true )
{
printf("\e[1m");
@ -599,7 +603,6 @@ bool rewrite_finish(struct rewrite* rewr)
return true;
}
static bool interactive;
static bool quitting;
static struct harddisk** hds;
static size_t hds_count;
@ -1132,6 +1135,25 @@ static void switch_device(struct harddisk* hd)
scan_device();
}
static bool lookup_harddisk_by_string(struct harddisk** out,
const char* argv0,
const char* name)
{
for ( size_t i = 0; i < hds_count; i++ )
{
char buf[sizeof(i) * 3];
snprintf(buf, sizeof(buf), "%zu", i);
if ( strcmp(name, hds[i]->path) != 0 &&
strcmp(name, device_name(hds[i]->path)) != 0 &&
strcmp(name, buf) != 0 )
continue;
*out = hds[i];
return true;
}
command_errorx("%s: No such device `%s'", argv0, name);
return false;
}
static bool lookup_partition_by_string(struct partition** out,
const char* argv0,
const char* numstr)
@ -1573,8 +1595,6 @@ static char* display_hole_format(void* ctx, size_t row, size_t column)
static void on_mkpart(size_t argc, char** argv)
{
(void) argc;
(void) argv;
size_t num_holes = 0;
struct device_area* hole = NULL;
for ( size_t i = 0; i < current_areas_count; i++ )
@ -1598,8 +1618,11 @@ static void on_mkpart(size_t argc, char** argv)
char answer[sizeof(size_t) * 3];
while ( true )
{
prompt(answer, sizeof(answer),
"Which hole to create the partition inside?", "1");
if ( 2 <= argc )
strlcpy(answer, argv[1], sizeof(answer));
else
prompt(answer, sizeof(answer),
"Which hole to create the partition inside?", "1");
char* end;
unsigned long num = strtoul(answer, &end, 10);
if ( *end || num_holes < num )
@ -1618,7 +1641,8 @@ static void on_mkpart(size_t argc, char** argv)
}
break;
}
printf("\n");
if ( argc < 2 )
printf("\n");
}
unsigned int slot = 0;
if ( current_pt_type == PARTITION_TABLE_TYPE_MBR && hole->inside_extended )
@ -1678,54 +1702,68 @@ static void on_mkpart(size_t argc, char** argv)
assert(start_str); // TODO: Error handling.
char* length_str = format_bytes_amount((uintmax_t) hole->length);
assert(length_str); // TODO: Error handling.
printf("Creating partition inside hole at %s of length %s (100%%)\n",
start_str, length_str);
if ( argc < 3 )
printf("Creating partition inside hole at %s of length %s (100%%)\n",
start_str, length_str);
free(start_str);
free(length_str);
off_t start;
while ( true )
{
char answer[256];
prompt(answer, sizeof(answer),
"Free space before partition? (42%/15G/...)", "0%");
if ( 3 <= argc )
strlcpy(answer, argv[2], sizeof(answer));
else
prompt(answer, sizeof(answer),
"Free space before partition? (42%/15G/...)", "0%");
if ( !parse_disk_quantity(&start, answer, hole->length) )
{
fprintf(stderr, "Invalid quantity `%s'.\n", answer);
command_errorx("%s: %s: Invalid quantity: %s",
argv[0], device_name(current_hd->path), answer);
continue;
}
if ( start == hole->length )
{
fprintf(stderr, "Answer was all free space, but need space for the "
"partition itself.\n");
command_errorx("%s: %s: Answer was all free space, but need space "
"for the partition itself",
argv[0], device_name(current_hd->path));
continue;
}
break;
}
printf("\n");
if ( argc < 3 )
printf("\n");
off_t max_length = hole->length - start;
off_t length;
length_str = format_bytes_amount((uintmax_t) max_length);
assert(length_str);
printf("Partition size can be at most %s (100%%).\n", length_str);
if ( argc < 4 )
printf("Partition size can be at most %s (100%%).\n", length_str);
free(length_str);
while ( true )
{
char answer[256];
prompt(answer, sizeof(answer),
"Partition size? (42%/15G/...)", "100%");
if ( 4 <= argc )
strlcpy(answer, argv[3], sizeof(answer));
else
prompt(answer, sizeof(answer),
"Partition size? (42%/15G/...)", "100%");
if ( !parse_disk_quantity(&length, answer, max_length) )
{
fprintf(stderr, "Invalid quantity `%s'.\n", answer);
command_errorx("%s: %s: Invalid quantity: %s",
argv[0], device_name(current_hd->path), answer);
continue;
}
if ( length == 0 )
{
fprintf(stderr, "Answer was zero (or rounded down to zero).\n");
command_errorx("%s: %s: Length was zero (or rounded down to zero)",
argv[0], device_name(current_hd->path));
continue;
}
break;
}
printf("\n");
if ( argc < 4 )
printf("\n");
char fstype[256];
while ( true )
{
@ -1736,13 +1774,17 @@ static void on_mkpart(size_t argc, char** argv)
question = "Format a filesystem? (no/ext2/extended)";
else if ( is_gpt )
question = "Format a filesystem? (no/ext2/biosboot)";
prompt(fstype, sizeof(fstype), question, "ext2");
if ( 5 <= argc )
strlcpy(fstype, argv[4], sizeof(fstype));
else
prompt(fstype, sizeof(fstype), question, "ext2");
if ( strcmp(fstype, "no") != 0 &&
strcmp(fstype, "ext2") != 0 &&
(!is_mbr || strcmp(fstype, "extended") != 0) &&
(!is_gpt || strcmp(fstype, "biosboot") != 0) )
{
fprintf(stderr, "Invalid filesystem choice `%s'.\n", fstype);
command_errorx("%s: %s: Invalid filesystem choice: %s",
argv[0], device_name(current_hd->path), fstype);
continue;
}
if ( !strcmp(fstype, "extended") )
@ -1762,27 +1804,27 @@ static void on_mkpart(size_t argc, char** argv)
bool mountable = !strcmp(fstype, "ext2");
while ( mountable )
{
prompt(mountpoint, sizeof(mountpoint),
"Where to mount partition? (mountpoint or 'no')", "no");
if ( 6 <= argc )
strlcpy(mountpoint, argv[5], sizeof(mountpoint));
else
prompt(mountpoint, sizeof(mountpoint),
"Where to mount partition? (mountpoint or 'no')", "no");
if ( !strcmp(mountpoint, "no") )
{
mountpoint[0] = '\0';
break;
}
if ( !strcmp(mountpoint, "mountpoint") )
{
printf("Then answer which mountpoint.\n");
continue;
}
if ( !verify_mountpoint(mountpoint) )
{
fprintf(stderr, "Invalid mountpoint `%s'.\n", fstype);
command_errorx("%s: %s: Invalid mountpoint: %s",
argv[0], device_name(current_hd->path), mountpoint);
continue;
}
simplify_mountpoint(mountpoint);
break;
}
printf("\n");
if ( mountable && argc < 6 )
printf("\n");
size_t renumbered_partitions = 0;
if ( current_pt_type == PARTITION_TABLE_TYPE_MBR && hole->inside_extended )
{
@ -2696,14 +2738,8 @@ static const struct command commands[] =
};
static const size_t commands_count = sizeof(commands) / sizeof(commands[0]);
void execute(char* cmd)
static void execute_argv(int argc, char** argv)
{
size_t argc = 0;
char* argv[256];
split_arguments(cmd, &argc, argv, 255);
if ( argc < 1 )
return;
argv[argc] = NULL;
for ( size_t i = 0; i < commands_count; i++ )
{
if ( strcmp(argv[0], commands[i].name) != 0 )
@ -2738,6 +2774,17 @@ void execute(char* cmd)
"Try `help' for more information.\n", argv[0]);
}
static void execute(char* cmd)
{
size_t argc = 0;
char* argv[256];
split_arguments(cmd, &argc, argv, 255);
if ( argc < 1 )
return;
argv[argc] = NULL;
execute_argv(argc, argv);
}
static void compact_arguments(int* argc, char*** argv)
{
for ( int i = 0; i < *argc; i++ )
@ -2766,6 +2813,8 @@ int main(int argc, char* argv[])
{
setlocale(LC_ALL, "");
bool set_interactive = false;
const char* argv0 = argv[0];
for ( int i = 1; i < argc; i++ )
{
@ -2780,6 +2829,8 @@ int main(int argc, char* argv[])
char c;
while ( (c = *++arg) ) switch ( c )
{
case 'i': interactive = true; set_interactive = true; break;
case 'n': interactive = false; set_interactive = true; break;
default:
fprintf(stderr, "%s: unknown option -- '%c'\n", argv0, c);
help(stderr, argv0);
@ -2813,20 +2864,30 @@ int main(int argc, char* argv[])
compact_arguments(&argc, &argv);
interactive = isatty(0) && isatty(1);
if ( !set_interactive )
interactive = isatty(0) && isatty(1) && argc < 3;
if ( !devices_open_all(&hds, &hds_count) )
err(1, "iterating devices");
qsort(hds, hds_count, sizeof(struct harddisk*), harddisk_compare_path);
if ( 1 <= hds_count )
if ( 2 <= argc )
{
struct harddisk* hd;
if ( !lookup_harddisk_by_string(&hd, argv[0], argv[1]) )
exit(1);
switch_device(hd);
}
else if ( 1 <= hds_count )
switch_device(hds[0]);
char* line = NULL;
size_t line_size = 0;
ssize_t line_length;
while ( !quitting )
if ( 3 <= argc )
execute_argv(argc - 2, argv + 2);
else while ( !quitting )
{
if ( interactive )
{
@ -2855,4 +2916,6 @@ int main(int argc, char* argv[])
for ( size_t i = 0; i < hds_count; i++ )
harddisk_close(hds[i]);
free(hds);
return 0;
}

View File

@ -217,7 +217,7 @@ diff -Paur --no-dereference -- libssl.upstream/apps/openssl/s_socket.c libssl/ap
diff -Paur --no-dereference -- libssl.upstream/configure libssl/configure
--- libssl.upstream/configure
+++ libssl/configure
@@ -11775,6 +11775,10 @@
@@ -11779,6 +11779,10 @@
HOST_OS=midipix
CPPFLAGS="$CPPFLAGS -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_POSIX_SOURCE -D_GNU_SOURCE"
;;

View File

@ -1,10 +1,10 @@
NAME=libssl
BUILD_LIBRARIES=
VERSION=3.7.1
VERSION=3.7.2
DISTNAME=libressl-$VERSION
COMPRESSION=tar.gz
ARCHIVE=$DISTNAME.$COMPRESSION
SHA256SUM=98086961a2b8b657ed0fea3056fb2db14294b6bfa193c15a5236a0a35c843ded
SHA256SUM=b06aa538fefc9c6b33c4db4931a09a5f52d9d2357219afcbff7d93fe12ebf6f7
UPSTREAM_SITE=https://ftp.openbsd.org/pub/OpenBSD/LibreSSL
UPSTREAM_ARCHIVE=$ARCHIVE
LICENSE=OpenSSL

View File

@ -0,0 +1 @@
rm -rf -- 'include/openssl/opensslconf.h'

View File

@ -1,4 +1,4 @@
.Dd April 9, 2023
.Dd April 23, 2023
.Dt AUTOINSTALL.CONF 5
.Os
.Sh NAME
@ -45,19 +45,31 @@ ask the question normally.
Installations can be made fully non-interactive using
.Sy accept_defaults .
.Pp
Each question has a counterpart question suffixed with
.Sq "!"
which contains a
.Xr sh 1
script that is executed before the question is asked.
If the original question isn't answered, then the script's standard output
is used as the answer to the original question.
The installation aborts if the script exits unsuccessfully.
These scripts are useful to customize the installation with arbitrary code.
.Pp
The questions in chronological order are as follows:
.Bl -tag -width "12345678"
.It Sy accept_defaults Ns "=" Ns Oo Sy no "|" yes Oc ( default Sy no )
Accept the default answer (if any) to questions that were not
configured in
.Nm .
.Nm ?
This feature makes installations entirely automated even if unexpected questions
are asked, although the essential questions must be answered.
.It Sy countdown Ns "=" Ns Ar seconds No ( default Li 10 )
Count down for this many
.Ar seconds
with a warning that an automated installation is about to happen.
The countdown happens if the
with a warning that an automated installation is about to happen?
The countdown happens if
.Sy accept_defaults=yes
or if the
.Sy ready
question is answered and either the
.Sy disked
@ -65,28 +77,234 @@ or
.Sy confirm_install
questions are answered.
.It Sy ignore_missing_programs Ns "=" Ns Oo Sy no "|" yes Oc ( default Sy no )
Ignore if the installer environment does not have the needed ports installed.
Ignore if the installer environment does not have the needed ports installed?
This situation ordinarily does not happen.
ready
.It Sy ready Ns "=" Ns Ar affirmation
A human readable positive affirmation of your choice that you're ready to
install, useful for fully automated installations.
Are you ready to begin the installation process?
This is a human readable positive affirmation of your choice that you're ready
to install, useful for fully automated installations.
Not answering this question is useful for semi-automated installations where one
would acknowledge the installation before it's begun.
It also provides the opportunity to escape to a shell before installing.
.Pp
The
.Sy "ready!"
question is convenient for running shell commands before the installation
begins.
.It Sy kblayout Ns "=" Ns Oo Sy default "|" Ar layout Oc ( default Sy default )
Switch to this keyboard
.Ar layout
using
.Xr chkblayout 1 .
The choice is set as the system default in
.Xr kblayout 5 .
.Xr chkblayout 1 ?
The choice is remembered as the
.Xr kblayout 5
system default.
.It Sy videomode Ns "=" Ns Oo Sy no "|" Sy yes "|" Ar WIDTH Ns x Ns Ar HEIGHT Ns x Ns Ar BPP Oc ( default Sy yes )
Interactively select a graphics resolution using
.Xr chvideomode 1
or non-interactively set it to the specified resolution.
The choice is set as the system default in
.Xr videomode 5 .
or non-interactively set it to the specified resolution?
The choice is remembered as the
.Xr videomode 5
system default.
.Pp
If the installation is non-interactive with
.Sy accept_defaults=true ,
then the default is instead
.Sy no .
.It Sy grub Ns "=" Ns Oo Sy no "|" Sy yes Oc
Install the GRUB bootloader onto the device containing the
.Pa /boot
filesystem (if it exists, otherwise the root filesystem)?
The default is
.Sy yes
if any existing installations are found with GRUB enabled or if no filesystems
were found, otherwise the default is
.Sy no .
.Pp
This is an essential question that must be answered for automatic installations.
.It Sy grub_password Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy yes )
Protect the bootloader with a password to avoid unauthorized root access via the
advanced bootloader features?
The standard bootloader menu options don't require a password.
The password is set in the
.Sy grub_password_hash
question.
.Pp
If the installation is non-interactive with
.Sy accept_defaults=true ,
then the default is instead
.Sy no
if the
.Sy grub_password_hash
question is not answered.
.It Sy grub_password_hash Ns "=" Ns Ar hash
The bootloader password as hashed by the
.Xr grub-mkpasswd-pbkdf2 1
program?
The password is asked interactively if this question is not answered.
The choice is remembered in
.Xr grubpw 5 .
.Pp
Although it's discouraged to place unhashed passwords in
.Nm ,
the
.Sy "grub_password!"
question could be answered with
.Li "grub-mkpasswd-pbkdf2 -p password"
to dynamically hash the bootloader password.
.It Sy grub_password_empty Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy no )
Allow an insecure empty bootloader password typed interactively?
.It Sy disked Ns "=" Ns Ar commands
Commands to create partitions and filesystems with
.Xr disked 8 ?
The
.Li ++=
syntax is useful to append multiple lines to the
.Sy disked
answer.
A root filesystem must be mounted in order to install the operating system.
The mountpoints are remembered in
.Xr fstab 5 .
.Pp
This is an essential question that must be answered for automatic installations.
.Pp
The
.Sy "disked!"
question is convenient for running shell commands before the partitioning step,
or to generate dynamic partitioning commands on the standard output if the
original
.Sy disked
question is unanswered.
.It Sy missing_bios_boot_partition Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy yes )
Attempt
.Xr disked 8
again if the GRUB bootloader is installed but the
.Pa /boot
directory's filesystem is inside a GPT partition table that doesn't have a
biosboot partition?
.It Sy confirm_install Ns "=" Ns Oo Sy no "|" Sy yes "|" Sy exit "|" Sy poweroff "|" Sy reboot "|" Sy halt Oc ( default Sy yes )
Install the operating system or abort the installation?
This is the final confirmation before the operating system is installed, after
the partitioning has taken place.
.Pp
The
.Sy "confirm_install!"
question is convenient for running shell commands before the installation step,
after partitioning has happened, but before the filesystems are mounted.
.It Sy hostname Ns "=" Ns Ar hostname
Hostname for the installation?
The choice is remembered in
.Xr hostname 5 .
.Pp
This is an essential question that must be answered for automatic installations.
If it isn't answered and
.Sy accept_defaults=yes ,
then the current (and likely default) hostname is used.
.It Sy password_hash_root Ns "=" Ns Ar hash
Password for the root user as hashed with
.Xr crypt_newhash 2 ?
The empty string sets the password to the empty string (insecure) and a literal
.Sy x
disables password login for root.
The choice is remembered in
.Xr passwd 5 .
.Pp
This is an essential question that must be answered for automatic installations.
If it isn't answered and
.Sy accept_defaults=yes ,
then password login is disabled for root.
.Pp
Although it's discouraged to place unhashed passwords in
.Nm ,
the
.Sy "password_hash_root!"
question could be answered with
.Li "echo password | passwd -H"
to dynamically hash the root password.
.It Sy password_hash_root Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy no )
Allow an insecure empty root password typed interactively?
.It Sy copy_ssh_authorized_keys_root Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy yes )
Copy the
.Pa /root/.ssh/authorized_keys
file (if it exists) into the installation?
.It Sy copy_ssh_config_root Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy yes )
Copy the
.Pa /root/.ssh/config
file (if it exists) into the installation?
.It Sy copy_ssh_id_rsa_root Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy yes )
Copy the
.Pa /root/.ssh/id_rsa
file (if it exists) into the installation?
.It Sy copy_ssh_known_hosts_root Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy yes )
Copy the
.Pa /root/.ssh/known_hosts
file (if it exists) into the installation?
.It Sy empty_password Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy no )
Allow insecure empty passwords for regular users?
.It Sy enable_gui Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy yes )
Enable the
.Xr display 1
graphical user interface?
The choice is remembered in
.Xr session 5 .
.It Sy enable_ntpd Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy no )
Automatically get time from the network using
.Xr ntpd 8 ?
Note this choice has privacy implications as the servers in
.Xr ntpd.conf 5
file will be contacted in the background.
The choice is remembered in
.Pa /etc/init/local
per
.Xr init 5 .
.It Sy enable_sshd Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy no )
Enable the
.Xr sshd 8
secure shell server?
The choice is remembered in
.Pa /etc/init/local
per
.Xr init 5 .
.It Sy copy_sshd_config Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy no )
Copy the
.Pa /etc/sshd_config
file (if it exists) into the installation?
.It Sy enable_sshd_password Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy no )
Enable password authentication in the local
.Xr sshd 8 ?
The choice is remembered in
.Xr sshd_config 5 .
.Pp
It's strongly encouraged to answer
.Sy no
and instead use public key authentication.
The installation environment can be seeded with the ssh keys using the
.Xr release-iso-modification 7
procedure and the default answers will copy the keys into the installation.
.It Sy enable_sshd_root_password Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy no )
Enable ssh to the root user with password authentication?
.It Sy copy_sshd_private_keys Ns "=" Ns Oo Sy no "|" Sy yes Oc ( default Sy yes )
Copy the sshd private keys (if they exist) into the installation?
These are
.Pa /etc/ssh_host_ecdsa_key ,
.Pa /etc/ssh_host_ed25519_key ,
.Pa /etc/ssh_host_rsa_key .
.It Sy finally Ns "=" Ns Oo Sy exit "|" Sy poweroff "|" Sy reboot "|" Sy halt "|" Sy boot Oc ( default Sy boot )
What action should be taken when the installation is finished?
.Pp
The
.Sy "finally!"
question is convenient for running shell commands once the installation is
complete to customize the installation.
The working directory is the root filesystem of the installation with all
filesystems mounted.
The
.Li "chroot -d ."
command is useful to
.Xr chroot 8
into the new root filesystem to run commands with the
.Pa /dev
filesystem mounted.
.El
.Sh FILES
.Bl -tag -width "/etc/autoinstall.conf" -compact
@ -94,23 +312,133 @@ The choice is set as the system default in
Automatic installation configuration.
.El
.Sh EXAMPLES
.Bd -literal
.Ss Fully automated installation
To perform a fully automated installation with root login disabled, create
.Pa autoinstall.conf :
.Bd -literal -offset indentq
accept_defaults=yes
ready=Automatically
kblayout=us
videomode=1280x720x32
grub=yes
grub_password=no
disked++=mktable mbr
disked++=mkpart
disked++=0%
disked++=100%
disked++=ext2
disked++=/
confirm_install=yes
disked++=mkpart 1 0% 100% ext2 /
hostname=dragon
password_hash_root=
finally=reboot
password_hash_root=x
.Ed
.Pp
Then follow
.Xr release-iso-modification 7
to configure the installation medium:
.Bd -literal -offset indent
tix-iso-liveconfig --autoinstall=autoinstall.conf liveconfig
tix-iso-bootconfig \\
--liveconfig=liveconfig --default=1 --random-seed \\
bootconfig
tix-iso-add sortix.iso bootconfig -o autosortix.iso
.Ed
.Pp
The resulting
.Pa autosortix.iso
image will then automatically format the harddisk and install the operating
system on whatever machine it is booted on.
Take care.
.Ss Setting passwords
The
.Xr grub-mkpasswd-pbkdf2 1
command can be used to hash a GRUB password and
.Xr passwd 1
can be used to hash a user password:
.Bd -literal -offset indent
grub-mkpasswd-pbkdf2 -p bootloader-password
echo root-password | passwd -H
.Ed
.Pp
The hashes can then be inserted in
.Nm :
.Bd -literal -offset indent
grub_password_hash=grub.pbkdf2.sha512.10000.68DA[...]
password_hash_root=$2b$10$d/9pP1[...]
.Ed
.Pp
Alternatively the passwords could be embedded in
.Nm ,
however beware that your
.Nm
file and the installation medium could leak:
.Bd -literal -offset indent
grub_password_hash!=grub-mkpasswd-pbkdf2 -p bootloader-password
password_hash_root!=echo root-password | passwd -H
.Ed
.Ss Automatically install with sshd
To automatically install the operating system with sshd enabled with keys and
authorizations set up ahead of time, first create
.Pa autoinstall.conf :
.Bd -literal -offset indent
accept_defaults=yes
grub=yes
disked++=mktable mbr
disked++=mkpart 1 0% 100% ext2 /
hostname=example.com
password_hash_root=x
enable_sshd=yes
.Ed
.Pp
Then follow
.Xr release-iso-modification 7
to configure the installation medium with automated installation and sshd:
.Bd -literal -offset indent
tix-iso-liveconfig \\
--autoinstall=autoinstall.conf \\
--root-ssh-authorized-keys="$HOME/.ssh/id_rsa.pub" \\
--sshd-keygen \\
--sshd-key-known-hosts-file="$HOME/.ssh/known_hosts" \\
--sshd-key-known-hosts-hosts="example.com example.com,192.0.2.1 192.0.2.1" \\
liveconfig
tix-iso-bootconfig \\
--liveconfig=liveconfig --default=1 --random-seed \\
bootconfig
tix-iso-add sortix.iso bootconfig -o autosortix.iso
.Ed
.Pp
To ssh into the installation after it has finished:
.Bd -literal -offset indent
ssh root@example.com
.Ed
.Pp
The connection will be immediately trusted because the just-generated server
keys were associated with the hostname in the
.Pa $HOME/.ssh/known_hosts
file.
This step assumes the hostname (example.com in this example) resolves to the
installation's IP address, otherwise the IP address can be used directly.
If the IP address is known ahead of time, it should be inserted into the
space delimited
.Fl \-sshd-key-known-hosts-hosts
list of host aliases.
.Ss Automatically install into a virtual machine with sshd
To automatically install into a qemu virtual machine, follow the above example
but instead associate the server keys with your localhost and optionally use a
.Pa known_hosts
file per virtual machine.
.Bd -literal -offset indent
...
--sshd-key-known-hosts-file="sortix.hdd.known_hosts" \\
--sshd-key-known-hosts-hosts=127.0.0.1 \\
...
.Ed
.Pp
Create the harddisk and spawn the virtual machine and forward the local port
2222 to the virtual machine's port 22.
.Bd -literal -offset indent
qemu-img create -f qcow2 sortix.hdd 1G
qemu-system-x86_64 \\
-vga std -m 1024 \\
-hda sortix.hdd -cdrom autosortix.iso \\
-device e1000,netdev=net0 \\
-netdev user,id=net0,hostfwd=tcp:127.0.0.1:2222-:22
.Ed
.Pp
To ssh into the installation after it has finished:
.Bd -literal -offset indent
ssh -oUserKnownHostsFile=sortix.hdd.known_hosts -p 2222 root@127.0.0.1
.Ed
.Sh SEE ALSO
.Xr autoupgrade.conf 5 ,

View File

@ -0,0 +1,203 @@
.Dd April 23, 2023
.Dt AUTOUPGRADE.CONF 5
.Os
.Sh NAME
.Nm autoupgrade.conf
.Nd automatic upgrade configuration
.Sh SYNOPSIS
.Nm /etc/autoupgrade.conf
.Sh DESCRIPTION
.Nm
configures
.Xr sysupgrade 8
to do an automatic operating system
.Xr upgrade 7 .
.Pp
The system administrator can automate operating system upgrades by
following
.Xr release-iso-modification 7
to embed the
.Pa /etc/autoupgrade.conf
file into the release cdrom filesystem.
New installations can similarly be automatically installed using
.Xr autoinstall.conf 5 .
.Pp
Each line is formatted as
.Ar question Ns = Ns Ar answer
which provides an
.Ar answer
to a
.Ar question
asked during upgrading.
Alternatively
.Ar question Ns += Ns Ar answer
appends to an existing answer (if any) separated by a space, and
.Ar question Ns ++= Ns Ar answer
appends another line to an existing answer (if any).
Empty lines and lines starting with
.Sq #
are comments and are ignored.
Otherwise whitespace is significant.
The empty answer accepts the default answer (if any) and is different from no
answer, which makes
.Xr sysupgrade 8
ask the question normally.
Upgrades can be made fully non-interactive using
.Sy accept_defaults .
.Pp
Each question has a counterpart question suffixed with
.Sq "!"
which contains a
.Xr sh 1
script that is executed before the question is asked.
If the original question isn't answered, then the script's standard output
is used as the answer to the original question.
The upgrade aborts if the script exits unsuccessfully.
These scripts are useful to customize the upgrades with arbitrary code.
.Pp
The questions in chronological order are as follows:
.Bl -tag -width "12345678"
.It Sy accept_defaults Ns "=" Ns Oo Sy no "|" yes Oc ( default Sy no )
Accept the default answer (if any) to questions that were not
configured in
.Nm ?
This feature makes upgrades entirely automated even if unexpected questions
are asked, although the essential questions must be answered.
.It Sy countdown Ns "=" Ns Ar seconds No ( default Li 10 )
Count down for this many
.Ar seconds
with a warning that an automated upgrade is about to happen?
The countdown happens if
.Sy accept_defaults=yes
or if the
.Sy ready
and
.Sy confirm_upgrrade
questions are answered.
.It Sy ignore_missing_programs Ns "=" Ns Oo Sy no "|" yes Oc ( default Sy no )
Ignore if the upgrader environment does not have the needed ports installed?
This situation ordinarily does not happen.
.It Sy ready Ns "=" Ns Ar affirmation
Are you ready to begin the upgrade process?
This is a human readable positive affirmation of your choice that you're ready
to upgrade, useful for fully automated upgrades.
Not answering this question is useful for semi-automated upgrades where one
would acknowledge the upgrades before it's begun.
It also provides the opportunity to escape to a shell before upgrading.
.Pp
The
.Sy "ready!"
question is convenient for running shell commands before the upgrade begins.
.It Sy kblayout Ns "=" Ns Oo Sy default "|" Ar layout Oc ( default Sy default )
Switch to this keyboard
.Ar layout
using
.Xr chkblayout 1 ?
.It Sy videomode Ns "=" Ns Oo Sy no "|" Sy yes "|" Ar WIDTH Ns x Ns Ar HEIGHT Ns x Ns Ar BPP Oc ( default Sy yes )
Interactively select a graphics resolution using
.Xr chvideomode 1
or non-interactively set it to the specified resolution?
.Pp
If the upgrade is non-interactive with
.Sy accept_defaults=true ,
then the default is instead
.Sy no .
.It Sy run_installer_instead Ns "=" Ns Oo Sy no "|" yes Oc ( default Sy yes )
Run the
.Xr sysinstall 8
installer instead if no installations were found?
.Pp
This answer is useful combined with
.Xr autoinstall.conf 5
to either install or upgrade the operating system, regardless of what is already
installed on the machine.
.It Sy which_installaton Ns "=" Ns Ar block-device
The name of the
.Ar block-device
containing the root filesystem to upgrade?
This question is only asked if multiple installations were found.
.It Sy switch_architecture Ns "=" Ns Oo Sy no "|" yes Oc ( default Sy no )
Switch the installation to another architecture?
.Pp
Such upgrades are not supported and may corrupt the installation.
.It Sy downgrade_release Ns "=" Ns Oo Sy no "|" yes Oc ( default Sy no )
Downgrade the installation to an earlier release?
.Pp
Such upgrades are not supported and may corrupt the installation.
.It Sy skip_release Ns "=" Ns Oo Sy no "|" yes Oc ( default Sy no )
Skip upgrading to a release that ordinarily must be upgraded to first?
.Pp
Such upgrades are not supported and may corrupt the installation.
.It Sy downgrade_abi Ns "=" Ns Oo Sy no "|" yes Oc ( default Sy no )
Downgrade the installation to an earlier ABI?
.Pp
Such upgrades are not supported and may corrupt the installation.
.It Sy cancel_pending_sysmerge Ns "=" Ns Oo Sy no "|" yes Oc ( default Sy yes )
Cancel an existing pending
.Xr sysmerge 8
upgrade?
.It Sy confirm_upgrade Ns "=" Ns Oo Sy no "|" Sy yes "|" Sy exit "|" Sy poweroff "|" Sy reboot "|" Sy halt Oc ( default Sy yes )
Upgrade the operating system or abort the upgrade?
This is the final confirmation before the operating system is upgraded.
.Pp
The
.Sy "confirm_upgrade!"
question is convenient for running shell commands before the upgrade step.
The working directory is the root filesystem of the installation with all
filesystems mounted.
Note how
.Xr chroot 8
command may not work as intended at this point since the ABI may have
incompatibly changed.
.It Sy finally Ns "=" Ns Oo Sy exit "|" Sy poweroff "|" Sy reboot "|" Sy halt "|" Sy boot Oc ( default Sy boot )
What action should be taken when the upgrade is finished?
.Pp
The
.Sy "finally!"
question is convenient for running shell commands once the upgrade is
complete to customize the upgraded installation.
The working directory is the root filesystem of the installation with all
filesystems mounted.
The
.Li "chroot -d ."
command is useful to
.Xr chroot 8
into the root filesystem to run commands with the
.Pa /dev
filesystem mounted.
.El
.Sh FILES
.Bl -tag -width "/etc/autoupgrade.conf" -compact
.It Pa /etc/autoupgrade.conf
Automatic upgrade configuration.
.El
.Sh EXAMPLES
.Ss Fully automated upgrade
To perform a fully automated upgrade with, create
.Pa autoupgrade.conf :
.Bd -literal -offset indent
accept_defaults=yes
.Ed
.Pp
Then follow
.Xr release-iso-modification 7
to configure the upgrade medium:
.Bd -literal -offset indent
tix-iso-liveconfig --autoupgrade=autoupgrade.conf liveconfig
tix-iso-bootconfig \\
--liveconfig=liveconfig --default=1 --random-seed \\
bootconfig
tix-iso-add sortix.iso bootconfig -o autosortix.iso
.Ed
.Pp
The resulting
.Pa autosortix.iso
image will then automatically upgrade the operating system on whatever machine
it is booted on.
.Sh SEE ALSO
.Xr autoinstall.conf 5 ,
.Xr upgrade.conf 5 ,
.Xr release-iso-modification 7 ,
.Xr upgrade 7 ,
.Xr sysupgrade 8 ,
.Xr tix 8

View File

@ -319,6 +319,15 @@ variable) is automatically selected.
If set to 0, the default menu entry is loaded instantaneously.
The timeout is disabled if set to -1.
(Default: 10)
.It Sy title_single_user
The menu title for the single-user selection.
(Default: live environment)
.It Sy title_sysinstall
The menu title for the sysinstall selection.
(Default: new installation)
.It Sy title_sysupgrade
The menu title for the sysupgrade selection.
(Default: upgrade existing installation)
.It Sy tix_ Ns Ar $port
A copy of the binary package is stored in
.Pa /repository

View File

@ -74,7 +74,7 @@ sysupgrade: $(SYSUPGRADE_OBJS)
sysinstall.o: $(SYSINSTALL_DEPS:=.h)
sysmerge.o: $(SYSMERGE_DEPS:=.h)
sysupgrade.o: $(SYSUPGRADE_DEPS:=.h)
autoconf.o: autoconf.h
autoconf.o: autoconf.h execute.h
conf.o: conf.h
devices.o: devices.h
execute.o: execute.h

View File

@ -27,6 +27,7 @@
#include <string.h>
#include "autoconf.h"
#include "execute.h"
static char** keyvalues = NULL;
static size_t keyvalues_used = 0;
@ -34,6 +35,23 @@ static size_t keyvalues_length = 0;
bool has_autoconf = false;
bool autoconf_has(const char* name)
{
if ( !name )
return false;
size_t len = strlen(name);
for ( size_t i = 0; i < keyvalues_used; i++ )
{
if ( strncmp(keyvalues[i], name, len) )
continue;
if ( keyvalues[i][len] == '=' )
return true;
if ( keyvalues[i][len] == '!' && keyvalues[i][len + 1] == '=' )
return true;
}
return false;
}
const char* autoconf_get(const char* name)
{
if ( !name )
@ -45,6 +63,36 @@ const char* autoconf_get(const char* name)
return NULL;
}
char* autoconf_eval(const char* name)
{
if ( !name )
return NULL;
char* shname;
if ( asprintf(&shname, "%s!", name) < 0 )
err(1, "malloc");
const char* script;
char* output = NULL;
if ( (script = autoconf_get(shname)) )
{
char** out_ptr = autoconf_get(name) ? NULL : &output;
execute((const char*[]) { "sh", "-c", script, NULL }, "efo", out_ptr);
if ( out_ptr )
{
size_t len = strlen(output);
if ( len && output[len - 1] == '\n' )
output[len - 1] = '\0';
}
}
free(shname);
if ( autoconf_get(name) )
{
free(output);
if ( !(output = strdup(autoconf_get(name))) )
err(1, "malloc");
}
return output;
}
bool autoconf_set(const char* name, const char* value)
{
char* keyvalue;

View File

@ -22,7 +22,9 @@
extern bool has_autoconf;
bool autoconf_has(const char* name);
const char* autoconf_get(const char* name);
char* autoconf_eval(const char* name);
bool autoconf_set(const char* name, const char* value);
void autoconf_load(const char* path);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2016, 2017, 2021 Jonas 'Sortie' Termansen.
* Copyright (c) 2015, 2016, 2017, 2021, 2023 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 <stdarg.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
@ -36,6 +37,7 @@ int execute(const char* const* argv, const char* flags, ...)
bool foreground = false;
bool gid_set = false;
const char* input = NULL;
char** output = NULL;
bool raw_exit_code = false;
bool uid_set = false;
bool quiet = false;
@ -53,6 +55,7 @@ int execute(const char* const* argv, const char* flags, ...)
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 'o': output = va_arg(ap, 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;
@ -66,6 +69,15 @@ int execute(const char* const* argv, const char* flags, ...)
sigemptyset(&sigttou);
sigaddset(&sigttou, SIGTTOU);
}
int output_pipes[2] = {-1, -1};
if ( output && pipe(output_pipes) < 0 )
{
if ( !quiet_stderr )
warn("pipe: %s", argv[0]);
if ( exit_on_failure )
(_exit_instead ? _exit : exit)(2);
return -1;
}
pid_t child_pid = fork();
if ( child_pid < 0 )
{
@ -95,8 +107,8 @@ int execute(const char* const* argv, const char* flags, ...)
}
if ( input )
{
int pipes[2];
if ( pipe(pipes) < 0 )
int input_pipes[2];
if ( pipe(input_pipes) < 0 )
{
if ( !quiet_stderr )
warn("pipe: %s", argv[0]);
@ -111,11 +123,11 @@ int execute(const char* const* argv, const char* flags, ...)
}
else if ( input_pid == 0 )
{
close(pipes[0]);
close(input_pipes[0]);
size_t left = strlen(input);
while ( *input )
{
ssize_t written = write(pipes[1], input, left);
ssize_t written = write(input_pipes[1], input, left);
if ( written <= 0 )
break;
input += written;
@ -123,10 +135,17 @@ int execute(const char* const* argv, const char* flags, ...)
}
_exit(0);
}
close(pipes[1]);
close(input_pipes[1]);
close(0);
dup2(pipes[0], 0);
close(pipes[0]);
dup2(input_pipes[0], 0);
close(input_pipes[0]);
}
if ( output )
{
close(output_pipes[0]);
close(1);
dup2(output_pipes[1], 1);
close(output_pipes[1]);
}
if ( quiet )
{
@ -148,6 +167,49 @@ int execute(const char* const* argv, const char* flags, ...)
warn("%s", argv[0]);
_exit(127);
}
bool success = true;
if ( output )
{
close(output_pipes[1]);
char* out;
size_t out_size;
FILE* out_fp = open_memstream(&out, &out_size);
if ( out_fp )
{
char buf[4096];
ssize_t amount = 0;
while ( 0 < (amount = read(output_pipes[0], buf, sizeof(buf))) )
{
if ( fwrite(buf, 1, amount, out_fp) != (size_t) amount )
{
if ( !quiet_stderr )
warn("fwrite to memstream");
success = false;
break;
}
}
if ( success && fclose(out_fp) == EOF )
{
if ( !quiet_stderr )
warn("fclose of memstream");
success = false;
}
close(output_pipes[0]);
if ( !success )
{
free(out);
*output = NULL;
}
else
*output = out;
}
else
{
success = false;
if ( !quiet_stderr )
warn("open_memstream");
}
}
int code;
waitpid(child_pid, &code, 0);
if ( foreground )
@ -158,11 +220,13 @@ int execute(const char* const* argv, const char* flags, ...)
}
if ( exit_on_failure )
{
if ( !WIFEXITED(code) || WEXITSTATUS(code) != 0 )
if ( !success || !WIFEXITED(code) || WEXITSTATUS(code) != 0 )
(_exit_instead ? _exit : exit)(2);
}
int exit_status;
if ( WIFEXITED(code) )
if ( !success )
exit_status = 2;
else if ( WIFEXITED(code) )
exit_status = WEXITSTATUS(code);
else
exit_status = 128 + WTERMSIG(code);

View File

@ -161,6 +161,7 @@ void promptx(char* buffer,
const char* answer,
bool catch_if_shell)
{
char* autoconf_answer = autoconf_eval(autoconf_name);
while ( true )
{
printf("\e[1m");
@ -171,12 +172,11 @@ 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 )
if ( autoconf_answer )
{
automatic_answer = autoconf_value;
automatic_answer = autoconf_answer;
if ( !automatic_answer[0] )
automatic_answer = answer;
}
@ -184,10 +184,12 @@ void promptx(char* buffer,
automatic_answer = answer;
if ( automatic_answer )
{
printf("\e[93m");
printf("%s\n", automatic_answer);
printf("\e[22m");
printf("\e[m");
fflush(stdout);
strlcpy(buffer, automatic_answer, buffer_size);
free(autoconf_answer);
return;
}
fgets(buffer, buffer_size, stdin);
@ -221,6 +223,7 @@ void promptx(char* buffer,
}
break;
}
free(autoconf_answer);
}
void password(char* buffer,

View File

@ -432,17 +432,27 @@ int main(void)
autoconf_load("/etc/autoinstall.conf");
char* accepts_defaults = autoconf_eval("accept_defaults");
bool non_interactive = accepts_defaults &&
!strcasecmp(accepts_defaults, "yes");
free(accepts_defaults);
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("disked") || autoconf_get("confirm_install")) )
if ( non_interactive ||
(autoconf_has("ready") &&
(autoconf_has("disked") || autoconf_has("confirm_install"))) )
{
int countdown = 10;
if ( autoconf_get("countdown") )
countdown = atoi(autoconf_get("countdown"));
if ( autoconf_has("countdown") )
{
char* string = autoconf_eval("countdown");
countdown = atoi(string);
free(string);
}
sigset_t old_set;
sigset_t new_set;
sigemptyset(&new_set);
@ -519,11 +529,10 @@ int main(void)
};
size_t num_readies = sizeof(readies) / sizeof(readies[0]);
const char* ready = readies[arc4random_uniform(num_readies)];
if ( autoconf_get("disked") )
if ( autoconf_has("disked") )
text("Warning: This installer will perform automatic harddisk "
"partitioning!\n");
if ( autoconf_get("confirm_install") &&
!strcasecmp(autoconf_get("confirm_install"), "yes") )
if ( autoconf_has("confirm_install") )
text("Warning: This installer will automatically install an operating "
"system!\n");
prompt(input, sizeof(input), "ready", "Ready?", ready);
@ -647,7 +656,7 @@ int main(void)
good = true;
}
}
const char* def = good ? "no" : "yes";
const char* def = non_interactive || good ? "no" : "yes";
while ( true )
{
prompt(input, sizeof(input), "videomode",
@ -729,17 +738,21 @@ int main(void)
text("\n");
while ( true )
{
const char* def =
non_interactive &&
!autoconf_has("grub_password_hash") ? "no" : "yes";
prompt(accept_grub_password, sizeof(accept_grub_password),
"grub_password",
"Password protect interactive bootloader? (yes/no)", "yes");
"Password protect interactive bootloader? (yes/no)", def);
if ( strcasecmp(accept_grub_password, "no") == 0 ||
strcasecmp(accept_grub_password, "yes") == 0 )
break;
}
if ( autoconf_get("grub_password_hash") )
if ( autoconf_has("grub_password_hash") )
{
const char* hash = autoconf_get("grub_password_hash");
char* hash = autoconf_eval("grub_password_hash");
install_configurationf("grubpw", "w", "%s\n", hash);
free(hash);
}
else while ( !strcasecmp(accept_grub_password, "yes") )
{
@ -810,15 +823,17 @@ int main(void)
text("Type man to display the disked(8) man page.\n");
not_first = true;
const char* argv[] = { "disked", "--fstab=fstab", NULL };
const char* disked_input = autoconf_get("disked");
char* disked_input = autoconf_eval("disked");
if ( execute(argv, "fi", disked_input) != 0 )
{
free(disked_input);
// TODO: We also end up here on SIGINT.
// TODO: Offer a shell here instead of failing?
warnx("partitioning failed");
sleep(1);
continue;
}
free(disked_input);
free_mountpoints(mountpoints, mountpoints_used);
mountpoints = NULL;
mountpoints_used = 0;
@ -1052,6 +1067,8 @@ int main(void)
else while ( true )
{
char defhost[HOST_NAME_MAX + 1] = "";
if ( non_interactive )
gethostname(defhost, sizeof(defhost));
FILE* defhost_fp = fopen("etc/hostname", "r");
if ( defhost_fp )
{
@ -1086,9 +1103,11 @@ int main(void)
{
textf("Root account already exists, skipping creating it.\n");
}
else if ( autoconf_get("password_hash_root") )
else if ( non_interactive || autoconf_has("password_hash_root") )
{
const char* hash = autoconf_get("password_hash_root");
char* hash = autoconf_eval("password_hash_root");
if ( !hash && !(hash = strdup("x")) )
err(2, "malloc");
if ( !install_configurationf("etc/passwd", "a",
"root:%s:0:0:root:/root:sh\n"
"include /etc/default/passwd.d/*\n", hash) )
@ -1100,6 +1119,7 @@ int main(void)
err(2, "etc/passwd");
install_skel("/root", 0, 0);
textf("Group '%s' added to /etc/group.\n", "root");
free(hash);
}
else while ( true )
{

View File

@ -368,6 +368,11 @@ int main(void)
autoconf_load("/etc/autoupgrade.conf");
char* accepts_defaults = autoconf_eval("accept_defaults");
bool non_interactive = accepts_defaults &&
!strcasecmp(accepts_defaults, "yes");
free(accepts_defaults);
struct utsname uts;
uname(&uts);
@ -376,12 +381,16 @@ 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_upgrade") )
if ( autoconf_has("ready") ||
autoconf_has("confirm_upgrade") )
{
int countdown = 10;
if ( autoconf_get("countdown") )
countdown = atoi(autoconf_get("countdown"));
if ( autoconf_has("countdown") )
{
char* string = autoconf_eval("countdown");
countdown = atoi(string);
free(string);
}
sigset_t old_set;
sigset_t new_set;
sigemptyset(&new_set);
@ -451,7 +460,7 @@ 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") )
if ( autoconf_has("confirm_upgrade") )
text("Warning: This upgrader will automatically upgrade an operating "
"system!\n");
prompt(input, sizeof(input), "ready", "Ready?", ready);
@ -532,7 +541,7 @@ int main(void)
good = true;
}
}
const char* def = good ? "no" : "yes";
const char* def = non_interactive || good ? "no" : "yes";
while ( true )
{
prompt(input, sizeof(input), "videomode",
@ -592,7 +601,7 @@ int main(void)
execlp("sysinstall", "sysinstall", (const char*) NULL);
err(2, "sysinstall");
}
continue;
errx(2, "Upgrade aborted since no installations were found");
}
while ( true )

View File

@ -133,7 +133,15 @@ if $random_seed; then
fi
fi
has_autoinstall=false
has_autoupgrade=false
if [ -n "$liveconfig" ]; then
if [ -e "$liveconfig/etc/autoinstall.conf" ]; then
has_autoinstall=true
fi
if [ -e "$liveconfig/etc/autoupgrade.conf" ]; then
has_autoupgrade=true
fi
mkdir -p -- "$directory/boot"
(cd "$liveconfig" && tar -c -f- -- *) > "$directory/boot/liveconfig.tar"
rm -f -- "$directory/boot/liveconfig.tar.xz"
@ -150,6 +158,12 @@ mkdir -p -- "$directory/boot/grub"
if [ -n "$timeout" ]; then
printf 'timeout="%s"\n' "$timeout"
fi
if $has_autoinstall; then
echo "title_sysinstall='***AUTOMATIC INSTALLATION***'"
fi
if $has_autoupgrade; then
echo "title_sysupgrade='***AUTOMATIC UPGRADE***'"
fi
print_enable_default_bool "$enable_dhclient" dhclient dhclient
print_enable_default_bool "$enable_gui" gui gui
print_enable_default "$enable_network_drivers" network_drivers network-drivers

View File

@ -238,6 +238,13 @@ GRUB module is loaded and an
hook is emitted that loads
.Pa output-directory/boot/liveconfig.tar.xz
as a multiboot module.
.Pp
If the liveconfig contains
.Xr autoinstall.conf 5
or
.Xr autoupgrade.conf 5 ,
the menu titles are modified to loudly warn they will automatically
install/upgrade the operating system.
.It Fl \-random-seed
Copy 256 bytes of randomness from
.Pa /dev/urandom

View File

@ -317,7 +317,7 @@ diff_package() {(
base=$(basename -- "$port")
if [ -e "$base.upstream" ]; then
announce "diff $base.upstream $base"
diff -Paur --no-dereference -- "$base.upstream" "$base" |
LC_ALL=C diff -Paur --no-dereference -- "$base.upstream" "$base" |
sed -E -e '/^Only in.*$/d' -e 's/^((---|\+\+\+)[^\t]+)\t.*/\1/' \
> "$base.patch"
if [ ! -s "$base.patch" ]; then rm "$base.patch"; fi

View File

@ -6,6 +6,7 @@
.Nd change user password
.Sh SYNOPSIS
.Nm
.Op Fl H
.Op Fl c Ar cipher
.Op Ar user
.Sh DESCRIPTION
@ -19,6 +20,11 @@ The options are as follows:
.It Fl c Ar cipher
Hash the password using the specified
.Ar cipher .
.It Fl H
Read a password from the standard input and write the
.Xr crypt_newpass 3
hash to the standard output.
The password database is unchanged.
.El
.Sh FILES
.Bl -tag -width "/etc/passwd" -compact

View File

@ -34,79 +34,67 @@
static void password(char* buffer,
size_t buffer_size,
const char* whose,
const char* question)
const char* question,
bool require_tty)
{
if ( !isatty(0) )
bool is_tty = isatty(0);
if ( !require_tty && is_tty )
errx(1, "Input is not a terminal");
unsigned int termmode;
gettermmode(0, &termmode);
settermmode(0, termmode & ~TERMMODE_ECHO);
if ( whose )
printf("%s's ", whose);
printf("%s ", question);
fflush(stdout);
fflush(stdin);
unsigned int termmode = 0;
if ( is_tty )
{
gettermmode(0, &termmode);
settermmode(0, termmode & ~TERMMODE_ECHO);
if ( whose )
printf("%s's ", whose);
printf("%s ", question);
fflush(stdout);
fflush(stdin);
}
// TODO: This may leave a copy of the password in the stdio buffer.
fgets(buffer, buffer_size, stdin);
fflush(stdin);
printf("\n");
if ( is_tty )
{
fflush(stdin);
printf("\n");
settermmode(0, termmode);
}
size_t buffer_length = strlen(buffer);
if ( buffer_length && buffer[buffer_length-1] == '\n' )
buffer[--buffer_length] = '\0';
settermmode(0, termmode);
}
static void compact_arguments(int* argc, char*** argv)
{
for ( int i = 0; i < *argc; i++ )
{
while ( i < *argc && !(*argv)[i] )
{
for ( int n = i; n < *argc; n++ )
(*argv)[n] = (*argv)[n+1];
(*argc)--;
}
}
}
int main(int argc, char* argv[])
{
const char* cipher = "blowfish,a";
bool hash_password = false;
for ( int i = 1; i < argc; i++ )
int opt;
while ( (opt = getopt(argc, argv, "c:H")) != -1 )
{
const char* arg = argv[i];
if ( arg[0] != '-' || !arg[1] )
continue;
argv[i] = NULL;
if ( !strcmp(arg, "--") )
break;
if ( arg[1] != '-' )
switch ( opt )
{
char c;
while ( (c = *++arg) ) switch ( c )
{
case 'c':
if ( !*(cipher = arg + 1) )
{
if ( i + 1 == argc )
errx(125, "option requires an argument -- 'c'");
cipher = argv[i+1];
argv[++i] = NULL;
}
arg = "c";
break;
default:
errx(1, "unknown option -- '%c'", c);
}
}
else
{
errx(1, "unrecognized option: %s", arg);
case 'c': cipher = optarg; break;
case 'H': hash_password = true; break;
default: return 1;
}
}
compact_arguments(&argc, &argv);
if ( hash_password )
{
if ( argc - optind )
errx(1, "Unexpected extra operand");
char pass[128];
password(pass, sizeof(pass), NULL, "Enter password (will not echo)",
false);
fgets(pass, sizeof(pass), stdin);
char newhash[128];
if ( crypt_newhash(pass, cipher, newhash, sizeof(newhash)) < 0 )
err(1, "crypt_newhash");
if ( printf("%s\n", newhash) < 0 || fflush(stdout) == EOF )
err(1, "stdout");
return 0;
}
uid_t my_uid = getuid();
char* my_username = getlogin();
@ -116,9 +104,9 @@ int main(int argc, char* argv[])
err(1, "stdup");
const char* username;
if ( argc <= 1 )
if ( argc - optind <= 1 )
username = my_username;
else if ( argc <= 2 )
else if ( argc - optind <= 2 )
username = argv[1];
else
errx(1, "Unexpected extra operand");
@ -139,16 +127,17 @@ int main(int argc, char* argv[])
{
char current[128];
password(current, sizeof(current), pwd->pw_name,
"current password (will not echo)");
"current password (will not echo)", true);
if ( crypt_checkpass(current, pwd->pw_passwd) < 0 )
errx(1, "Wrong password for '%s'", pwd->pw_name);
explicit_bzero(current, sizeof(current));
}
char first[128];
password(first, sizeof(first), NULL, "Enter new password (will not echo)");
password(first, sizeof(first), NULL, "Enter new password (will not echo)",
true);
char second[128];
password(second, sizeof(second), NULL, "Enter new password (again)");
password(second, sizeof(second), NULL, "Enter new password (again)", true);
if ( strcmp(first, second) != 0 )
errx(1, "Passwords don't match");
explicit_bzero(second, sizeof(second));