From 81a89c9e45518a7c52c1f8ece756a9f46b77a2f3 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 5 May 2024 16:29:48 +0200 Subject: init: make it possible to execute commands inline with -z When the program is not called as PID 1, as "linuxrc" nor with a "rebuild" argument, then the first argument will be checked for "-z". If it matches, then the subsequent arguments will constitute a command to be executed inline. For example, "init -z help" will show the help, and "init -z rd" will enter interactive mode. This can be useful from scripts which need to benefit from embedded commands, as well as to test new commands during development. --- init/README | 7 +++++++ init/init.c | 35 +++++++++++++++++++++++++++++------ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/init/README b/init/README index 7bde4d9..90a1096 100644 --- a/init/README +++ b/init/README @@ -216,3 +216,10 @@ Example of configuration file : #comment => ignore this line } # end of the conditional commands in /sbin/init-std # the following init will be this /sbin/init-std + +When the program is not called as PID 1, as "linuxrc" nor with a "rebuild" +argument, then the first argument will be checked for "-z". If it matches, then +the subsequent arguments will constitute a command to be executed inline. For +example, "init -z help" will show the help, and "init -z rd" will enter +interactive mode. This can be useful from scripts which need to benefit from +embedded commands. diff --git a/init/init.c b/init/init.c index 1dbb83b..0bfb64c 100644 --- a/init/init.c +++ b/init/init.c @@ -1873,6 +1873,7 @@ int main(int argc, char **argv, char **envp) int pid1, err; int cfg_ok; int rebuild; + int single_cmd = 0; int token; int cmd_input = INPUT_FILE; char cmd_line[256]; /* one line of config from the prompt */ @@ -1943,12 +1944,13 @@ int main(int argc, char **argv, char **envp) } old_umask = umask(0); - cfg_ok = (read_cfg(cfg_file) == 0); - - chdir("/"); /* be sure not to stay under /dev ! */ + cfg_ok = 0; /* do nothing if we're not called as the first process */ if (pid1 || linuxrc || rebuild) { + cfg_ok = (read_cfg(cfg_file) == 0); + chdir("/"); /* be sure not to stay under /dev ! */ + /* check if /dev is already populated : /dev/console should exist. We * can safely ignore and overwrite /dev in case of linuxrc, reason why * we don't test the presence of /dev/console. @@ -1997,6 +1999,27 @@ int main(int argc, char **argv, char **envp) } } } + else { + /* We weren't called as linuxrc, pid1 nor rebuild. If passed + * "-z" followed by at least one word, it will be processed as + * a single command to be executed as if read from a file. + */ + if (argc > 2 && streq(argv[1], "-z")) { + int i; + + cfg_line = cfg_data; + for (i = 2; i < argc; i++) { + cfg_line += my_strlcpy(cfg_line, argv[i], cfg_data + sizeof(cfg_data) - cfg_line); + if (cfg_line + 1 < cfg_data + sizeof(cfg_data)) + *(cfg_line++) = i + 1 < argc ? ' ' : '\n'; + *cfg_line = 0; + } + /* now the config is made of this unique line */ + cfg_line = cfg_data; + cfg_ok = 1; + single_cmd = 1; + } + } /* here, the cwd is still "/" */ if (cfg_ok) { @@ -2229,7 +2252,7 @@ int main(int argc, char **argv, char **envp) } /* other options are reserved for pid 1/linuxrc/rebuild and prompt mode */ - if (!pid1 && !linuxrc && !rebuild && cmd_input != INPUT_KBD) { + if (!pid1 && !linuxrc && !rebuild && !single_cmd && cmd_input != INPUT_KBD) { debug("Command ignored since pid not 1\n"); error = context[brace_level].error; continue; @@ -2744,8 +2767,8 @@ int main(int argc, char **argv, char **envp) debug(cfg_file); debug("\n"); } - if (rebuild) { - debug("end of rebuild\n"); + if (rebuild || single_cmd) { + debug("end of rebuild or single_cmd\n"); /* nothing more to do */ return 0; } -- 2.17.5