From 4448842bb141430e23498d5a969b5cefe8786e57 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Thu, 14 Apr 2016 13:21:19 +0000 Subject: - make s6-linux-init-maker write stage1 to dir/init instead of stdout - version: 0.1.0.0 --- COPYING | 2 +- INSTALL | 12 +-- doc/index.html | 19 +++-- doc/quickstart.html | 5 +- doc/s6-linux-init-maker.html | 50 +++++++------ doc/upgrade.html | 18 +++++ package/info | 2 +- src/init/s6-linux-init-maker.c | 165 ++++++++++++++++++++--------------------- 8 files changed, 151 insertions(+), 122 deletions(-) diff --git a/COPYING b/COPYING index 463bc49..fabed3c 100644 --- a/COPYING +++ b/COPYING @@ -1,4 +1,4 @@ -Copyright (c) 2015 Laurent Bercot +Copyright (c) 2015-2016 Laurent Bercot Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/INSTALL b/INSTALL index 548872b..5d89f43 100644 --- a/INSTALL +++ b/INSTALL @@ -6,15 +6,15 @@ Build Instructions - A Linux-based system with a standard C development environment - GNU make version 3.81 or later - - skalibs version 2.3.8.0 or later: http://skarnet.org/software/skalibs/ + - skalibs version 2.3.10.0 or later: http://skarnet.org/software/skalibs/ - The binaries generated by the s6-linux-init-maker tool have some + The scripts generated by the s6-linux-init-maker program have some additional dependencies: - - execline version 2.1.4.2 or later: http://skarnet.org/software/execline/ - - s6-portable-utils version 2.0.5.3 or later: http://skarnet.org/software/s6-portable-utils/ - - s6-linux-utils version 2.0.2.3 or later: http://skarnet.org/software/s6-linux-utils/ - - s6 version 2.2.2.0 or later: http://skarnet.org/software/s6/ + - execline version 2.1.5.0 or later: http://skarnet.org/software/execline/ + - s6-portable-utils version 2.0.6.0 or later: http://skarnet.org/software/s6-portable-utils/ + - s6-linux-utils version 2.1.0.0 or later: http://skarnet.org/software/s6-linux-utils/ + - s6 version 2.3.0.0 or later: http://skarnet.org/software/s6/ This software is Linux-specific. It will run on a Linux kernel, version 2.6.32 or later. However, it should not be too hard to port to diff --git a/doc/index.html b/doc/index.html index efcd308..9906135 100644 --- a/doc/index.html +++ b/doc/index.html @@ -50,15 +50,15 @@ a small FAQ.
  • A Linux-based system with a standard C development environment
  • GNU make, version 3.81 or later
  • skalibs version -2.3.8.0 or later
  • +2.3.10.0 or later
  • execline version -2.1.4.2 or later
  • +2.1.5.0 or later
  • s6-portable-utils version -2.0.5.3 or later
  • +2.0.6.0 or later
  • s6-linux-utils version -2.0.2.3 or later
  • +2.1.0.0 or later
  • s6 version -2.2.2.0 or later
  • +2.3.0.0 or later

    @@ -86,9 +86,14 @@ against the shared version of the skalibs library, it also becomes a

    • The current released version of s6-linux-init is -0.0.1.4.
    • -
    • Alternatively, you can checkout a copy of the s6-linux-init git repository: +0.1.0.0.
    • +
    • Alternatively, you can checkout a copy of the +s6-linux-init +git repository:
       git clone git://git.skarnet.org/s6-linux-init 
    • +
    • There's also a +GitHub mirror +of the s6-linux-init git repository.

    Compilation

    diff --git a/doc/quickstart.html b/doc/quickstart.html index da47334..bd758b1 100644 --- a/doc/quickstart.html +++ b/doc/quickstart.html @@ -39,10 +39,9 @@ add the -d 1 option to the s6-linux-init-maker command line below.
  • As root, run:
          rm -rf /tmp/s6-linux-init /tmp/init
    -     s6-linux-init-maker /tmp/s6-linux-init > /tmp/init
    -     chmod 0700 /tmp/init
    +     s6-linux-init-maker /tmp/s6-linux-init
          mv /tmp/s6-linux-init /etc/
    -     mv /tmp/init /sbin/ 
  • + ln -sf /etc/s6-linux-init/init /sbin/init
  • Reboot.
  • Congratulations! your machine is now running a s6-based init system.
  • diff --git a/doc/s6-linux-init-maker.html b/doc/s6-linux-init-maker.html index e2e0b2b..e82ce40 100644 --- a/doc/s6-linux-init-maker.html +++ b/doc/s6-linux-init-maker.html @@ -21,7 +21,12 @@

    s6-linux-init-maker reads configuration options on the command line, and outputs a directory to place in the -root filesystem as well as a script suitable as an init program. +root filesystem. That directory contains a script suitable +as an init program, as well as support file hierarchies to +get a complete +s6 +infrastructure running when the system is booted on that +script.

    @@ -58,7 +63,7 @@ machine - else the scripts will crash. [ -d dev_style ] \ [ -s env_store ] \ [ -e initial_envvar ] ... \ - dir > stage1 + dir

      @@ -66,9 +71,9 @@ machine - else the scripts will crash.
    • s6-linux-init-maker parses options on its command line.
    • It writes data into a directory dir, which must not exist beforehand.
    • -
    • It then prints a script to its standard output.
    • It exits 0 if everything went well, 100 if a user error occurred, -and 111 if a problem occurred during the directory or script creation.
    • +and 111 if a problem occurred during the creation of the directory +or its contents.

    @@ -81,35 +86,37 @@ tool can do it, as well as the GNU or busybox cp -a or mv comm

    - The stage1 script printed by s6-linux-init-maker on its -stdout is then suitable as an init program. The administrator should -copy it to /sbin/init and make it executable. + The basedir/init script +is then suitable as a "stage 1" init program, i.e. the first program +run by the kernel. The administrator should make a symbolic link +from /sbin/init to basedir/init; the +machine will then be ready to boot

    Boot sequence

    - When the kernel boots, it runs the stage1 script, and this is -what happens: + When the kernel boots, it runs the basedir/init script, +also known as stage 1. and this is what happens:

      -
    • stage1 is an +
    • stage 1 is an execline script, so the first process run by the kernel is the execlineb program launcher.
    • -
    • stage1 mounts a +
    • stage 1 mounts a tmpfs filesystem on tmpfsdir.
    • -
    • stage1 copies basedir/run-image verbatim to +
    • stage 1 copies basedir/run-image verbatim to tmpfsdir.
    • -
    • stage1 empties its environment, then reads a global set of environment variables from the +
    • stage 1 empties its environment, then reads a global set of environment variables from the basedir/env environment directory.
    • -
    • stage1 forks a child that will block until +
    • stage 1 forks a child that will block until s6-svscan is running.
    • -
    • stage1 executes, as process 1, into +
    • stage 1 executes, as process 1, into s6-svscan, with tmpfsdir/service as a scan directory.
    • @@ -122,7 +129,7 @@ instead of clogging the system console.
    • If the -g option has been given to s6-linux-init-maker, the scan directory will also contain a service for an early getty.
    • s6-svscan starts all the services defined in the scan directory, -and unblocks the child forked by stage1.
    • +and unblocks the child forked by stage 1.
    • This child executes into stage2.
    @@ -158,7 +165,7 @@ getty is essentially to make it easier to debug if stage2 fails. There is nothing else. In particular, no filesystem has been mounted yet, including /proc and /sys; and no one-time initialization -has been performed. The point of stage1 is only to make it +has been performed. The point of stage 1 is only to make it possible to run stage2 with a logging infrastructure and a supervision infrastructure already available, and all the real machine and service initialization should happen in stage2. @@ -222,7 +229,8 @@ service manager.

    s6-linux-init-maker options

      -
    • -c basedir : at boot time, stage1 +
    • -c basedir : at boot time, stage 1, +which should be accessible as basedir/init, will read its read-only data from basedir. After running s6-linux-init-maker, the administrator should make sure to copy the created directory dir to basedir. basedir @@ -282,7 +290,7 @@ It must be absolute. Default is
    • -p initial_path : the value to set the PATH environment variable to, for all the starting processes. -This will be done as early as possible in stage1. It is +This will be done as early as possible in stage 1. It is absolutely necessary for execline, s6, @@ -314,13 +322,13 @@ devtmpfs but not automounted by the kernel at boot time, and 2 means devtmpfs automounted by the kernel at boot time. Default is 2.
    • -

    • -s env_store : stage1 init sometimes +
    • -s env_store : stage 1 init sometimes inherits a few environment variables from the kernel. It empties its environment before spawning stage2 and executing into s6-svscan, in order to prevent those "kernel" environment variables from leaking into the whole process tree. However, sometimes those variables are needed at a later time; in that case, giving the -s option -to s6-linux-init-maker makes stage1 init dump the "kernel" environment +to s6-linux-init-maker makes stage 1 init dump the "kernel" environment variables into the env_store directory, via the s6-dumpenv program, before erasing them. env_store should obviously be diff --git a/doc/upgrade.html b/doc/upgrade.html index 2d8e90f..393b13a 100644 --- a/doc/upgrade.html +++ b/doc/upgrade.html @@ -18,6 +18,24 @@

      What has changed in s6-linux-init

      +

      in 0.1.0.0

      + + +

      in 0.0.1.4

        diff --git a/package/info b/package/info index 95854c2..e0f642e 100644 --- a/package/info +++ b/package/info @@ -1,4 +1,4 @@ package=s6-linux-init -version=0.0.1.4 +version=0.1.0.0 category=admin package_macro_name=S6_LINUX_INIT diff --git a/src/init/s6-linux-init-maker.c b/src/init/s6-linux-init-maker.c index fe890e9..c37b67c 100644 --- a/src/init/s6-linux-init-maker.c +++ b/src/init/s6-linux-init-maker.c @@ -170,6 +170,68 @@ static int sigusr2_script (buffer *b) return sig_script(b, '0') ; } +static inline int stage1_script (buffer *b) +{ + unsigned int sabase = satmp.len, pos, pos2 ; + char fmt[UINT_OFMT] ; + if (!put_shebang(b) + || buffer_puts(b, bindir) < 0 + || buffer_puts(b, "/export PATH ") < 0 + || !string_quote(&satmp, initial_path, str_len(initial_path))) return 0 ; + if (buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0) goto err ; + satmp.len = sabase ; + if (buffer_put(b, "\n", 1) < 0 + || buffer_puts(b, bindir) < 0 + || buffer_puts(b, "/cd /\ns6-setsid -qb --\numask 0") < 0 + || buffer_put(b, fmt, uint_ofmt(fmt, initial_umask)) < 0 + || buffer_puts(b, "\nif { s6-echo -- ") < 0 + || !string_quote(&satmp, BANNER, sizeof(BANNER) - 1)) return 0 ; + if (buffer_put(b, satmp.s, satmp.len) < 0) goto err ; + satmp.len = sabase ; + if (buffer_puts(b, " }\nif { s6-mount -nwt tmpfs -o mode=0755 tmpfs ") < 0 + || !string_quote(&satmp, slashrun, str_len(slashrun))) return 0 ; + pos = satmp.len ; + if (buffer_put(b, satmp.s + sabase, pos - sabase) < 0 + || buffer_puts(b, " }\nif { s6-hiercopy ") < 0 + || !string_quote(&satmp, robase, str_len(robase))) return 0 ; + pos2 = satmp.len ; + if (buffer_put(b, satmp.s + pos, pos2 - pos) < 0 + || buffer_puts(b, "/run-image ") < 0 + || buffer_put(b, satmp.s + sabase, pos - sabase) < 0 + || buffer_puts(b, " }\n") < 0) goto err ; + if (slashdev_style == 1) + { + if (buffer_puts(b, "if { s6-mount -nt devtmpfs dev /dev }\n") < 0) goto err ; + } + if (env_store) + { + unsigned int base = satmp.len ; + if (!string_quote(&satmp, env_store, str_len(env_store))) return 0 ; + if (buffer_puts(b, "if { unexport PATH s6-dumpenv -- ") < 0 + || buffer_put(b, satmp.s + base, satmp.len - base) < 0 + || buffer_puts(b, " }\n") < 0) goto err ; + satmp.len = base ; + } + if (buffer_puts(b, "emptyenv -p\ns6-envdir -I -- ") < 0 + || buffer_put(b, satmp.s + pos, pos2 - pos) < 0 + || buffer_puts(b, "/env\nredirfd -r 0 /dev/null\nredirfd -wnb 1 ") < 0 + || buffer_put(b, satmp.s + sabase, pos - sabase) < 0 + || buffer_puts(b, "/service/s6-svscan-log/fifo\nbackground\n{\n s6-setsid --\n redirfd -w 1 ") < 0 + || buffer_put(b, satmp.s + sabase, pos - sabase) < 0 + || buffer_puts(b, "/service/s6-svscan-log/fifo\n fdmove -c ") < 0 + || buffer_puts(b, redirect_stage2 ? "2 1" : "1 2") < 0 + || buffer_puts(b, "\n ") < 0 + || !string_quote(&satmp, init_script, str_len(init_script)) + || buffer_put(b, satmp.s + pos2, satmp.len - pos2) < 0 + || buffer_puts(b, "\n}\nunexport !\ncd ") < 0 + || buffer_put(b, satmp.s + sabase, pos - sabase) < 0 + || buffer_puts(b, "/service\nfdmove -c 2 1\ns6-svscan -st0\n") < 0) goto err ; + return 1 ; + err: + satmp.len = sabase ; + return 0 ; +} + static void cleanup (char const *base) { int e = errno ; @@ -250,30 +312,6 @@ static void auto_script (char const *base, char const *file, writetobuf_func_t_r close(fd) ; } -static inline void make_image (char const *base) -{ - auto_dir(base, "run-image", 0, 0, 0755) ; - auto_dir(base, "run-image/uncaught-logs", uncaught_logs_uid, uncaught_logs_gid, 02700) ; - auto_dir(base, "run-image/service", 0, 0, 0755) ; - auto_dir(base, "run-image/service/.s6-svscan", 0, 0, 0755) ; - auto_script(base, "run-image/service/.s6-svscan/crash", &crash_script) ; - auto_script(base, "run-image/service/.s6-svscan/finish", &finish_script) ; - auto_script(base, "run-image/service/.s6-svscan/SIGTERM", &sigterm_script) ; - auto_script(base, "run-image/service/.s6-svscan/SIGHUP", &sighup_script) ; - auto_script(base, "run-image/service/.s6-svscan/SIGQUIT", &sigquit_script) ; - auto_script(base, "run-image/service/.s6-svscan/SIGINT", &sigint_script) ; - auto_script(base, "run-image/service/.s6-svscan/SIGUSR1", &sigusr1_script) ; - auto_script(base, "run-image/service/.s6-svscan/SIGUSR2", &sigusr2_script) ; - auto_dir(base, "run-image/service/s6-svscan-log", 0, 0, 0755) ; - auto_fifo(base, "run-image/service/s6-svscan-log/fifo") ; - auto_script(base, "run-image/service/s6-svscan-log/run", &s6_svscan_log_script) ; - if (early_getty) - { - auto_dir(base, "run-image/service/s6-linux-init-early-getty", 0, 0, 0755) ; - auto_script(base, "run-image/service/s6-linux-init-early-getty/run", &early_getty_script) ; - } -} - static inline void make_env (char const *base, char const *modif, unsigned int modiflen) { auto_dir(base, "env", 0, 0, 0755) ; @@ -293,66 +331,29 @@ static inline void make_env (char const *base, char const *modif, unsigned int m } } -static inline int make_init_script (buffer *b) +static inline void make_image (char const *base) { - unsigned int sabase = satmp.len, pos, pos2 ; - char fmt[UINT_OFMT] ; - if (!put_shebang(b) - || buffer_puts(b, bindir) < 0 - || buffer_puts(b, "/export PATH ") < 0 - || !string_quote(&satmp, initial_path, str_len(initial_path))) return 0 ; - if (buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0) goto err ; - satmp.len = sabase ; - if (buffer_put(b, "\n", 1) < 0 - || buffer_puts(b, bindir) < 0 - || buffer_puts(b, "/cd /\ns6-setsid -qb --\numask 0") < 0 - || buffer_put(b, fmt, uint_ofmt(fmt, initial_umask)) < 0 - || buffer_puts(b, "\nif { s6-echo -- ") < 0 - || !string_quote(&satmp, BANNER, sizeof(BANNER) - 1)) return 0 ; - if (buffer_put(b, satmp.s, satmp.len) < 0) goto err ; - satmp.len = sabase ; - if (buffer_puts(b, " }\nif { s6-mount -nwt tmpfs -o mode=0755 tmpfs ") < 0 - || !string_quote(&satmp, slashrun, str_len(slashrun))) return 0 ; - pos = satmp.len ; - if (buffer_put(b, satmp.s + sabase, pos - sabase) < 0 - || buffer_puts(b, " }\nif { s6-hiercopy ") < 0 - || !string_quote(&satmp, robase, str_len(robase))) return 0 ; - pos2 = satmp.len ; - if (buffer_put(b, satmp.s + pos, pos2 - pos) < 0 - || buffer_puts(b, "/run-image ") < 0 - || buffer_put(b, satmp.s + sabase, pos - sabase) < 0 - || buffer_puts(b, " }\n") < 0) goto err ; - if (slashdev_style == 1) - { - if (buffer_puts(b, "if { s6-mount -nt devtmpfs dev /dev }\n") < 0) goto err ; - } - if (env_store) + auto_dir(base, "run-image", 0, 0, 0755) ; + auto_dir(base, "run-image/uncaught-logs", uncaught_logs_uid, uncaught_logs_gid, 02700) ; + auto_dir(base, "run-image/service", 0, 0, 0755) ; + auto_dir(base, "run-image/service/.s6-svscan", 0, 0, 0755) ; + auto_script(base, "run-image/service/.s6-svscan/crash", &crash_script) ; + auto_script(base, "run-image/service/.s6-svscan/finish", &finish_script) ; + auto_script(base, "run-image/service/.s6-svscan/SIGTERM", &sigterm_script) ; + auto_script(base, "run-image/service/.s6-svscan/SIGHUP", &sighup_script) ; + auto_script(base, "run-image/service/.s6-svscan/SIGQUIT", &sigquit_script) ; + auto_script(base, "run-image/service/.s6-svscan/SIGINT", &sigint_script) ; + auto_script(base, "run-image/service/.s6-svscan/SIGUSR1", &sigusr1_script) ; + auto_script(base, "run-image/service/.s6-svscan/SIGUSR2", &sigusr2_script) ; + auto_dir(base, "run-image/service/s6-svscan-log", 0, 0, 0755) ; + auto_fifo(base, "run-image/service/s6-svscan-log/fifo") ; + auto_script(base, "run-image/service/s6-svscan-log/run", &s6_svscan_log_script) ; + if (early_getty) { - unsigned int base = satmp.len ; - if (!string_quote(&satmp, env_store, str_len(env_store))) return 0 ; - if (buffer_puts(b, "if { unexport PATH s6-dumpenv -- ") < 0 - || buffer_put(b, satmp.s + base, satmp.len - base) < 0 - || buffer_puts(b, " }\n") < 0) goto err ; - satmp.len = base ; + auto_dir(base, "run-image/service/s6-linux-init-early-getty", 0, 0, 0755) ; + auto_script(base, "run-image/service/s6-linux-init-early-getty/run", &early_getty_script) ; } - if (buffer_puts(b, "emptyenv -p\ns6-envdir -I -- ") < 0 - || buffer_put(b, satmp.s + pos, pos2 - pos) < 0 - || buffer_puts(b, "/env\nredirfd -r 0 /dev/null\nredirfd -wnb 1 ") < 0 - || buffer_put(b, satmp.s + sabase, pos - sabase) < 0 - || buffer_puts(b, "/service/s6-svscan-log/fifo\nbackground\n{\n s6-setsid --\n redirfd -w 1 ") < 0 - || buffer_put(b, satmp.s + sabase, pos - sabase) < 0 - || buffer_puts(b, "/service/s6-svscan-log/fifo\n fdmove -c ") < 0 - || buffer_puts(b, redirect_stage2 ? "2 1" : "1 2") < 0 - || buffer_puts(b, "\n ") < 0 - || !string_quote(&satmp, init_script, str_len(init_script)) - || buffer_put(b, satmp.s + pos2, satmp.len - pos2) < 0 - || buffer_puts(b, "\n}\nunexport !\ncd ") < 0 - || buffer_put(b, satmp.s + sabase, pos - sabase) < 0 - || buffer_puts(b, "/service\nfdmove -c 2 1\ns6-svscan -st0\n") < 0) goto err ; - return 1 ; - err: - satmp.len = sabase ; - return 0 ; + auto_script(base, "init", &stage1_script) ; } int main (int argc, char const *const *argv) @@ -425,7 +426,5 @@ int main (int argc, char const *const *argv) make_env(argv[0], satmp.s, satmp.len) ; satmp.len = 0 ; make_image(argv[0]) ; - if (!make_init_script(buffer_1) || !buffer_flush(buffer_1)) - strerr_diefu1sys(111, "write to stdout") ; return 0 ; } -- cgit v1.3.1