diff options
-rw-r--r-- | COPYING | 2 | ||||
-rw-r--r-- | INSTALL | 2 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | doc/backtick.html | 21 | ||||
-rw-r--r-- | doc/index.html | 4 | ||||
-rw-r--r-- | doc/upgrade.html | 6 | ||||
-rw-r--r-- | package/deps.mak | 7 | ||||
-rw-r--r-- | package/info | 2 | ||||
-rw-r--r-- | src/execline/backtick.c | 23 | ||||
-rw-r--r-- | src/include/execline/execline.h | 1 | ||||
-rw-r--r-- | src/libexecline/deps-lib/execline | 1 | ||||
-rw-r--r-- | src/libexecline/el_modifs_and_exec.c | 72 |
12 files changed, 119 insertions, 25 deletions
@@ -1,4 +1,4 @@ -Copyright (c) 2011-2023 Laurent Bercot <ska-skaware@skarnet.org> +Copyright (c) 2011-2024 Laurent Bercot <ska-skaware@skarnet.org> Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -6,7 +6,7 @@ Build Instructions - A POSIX-compliant C development environment - GNU make version 3.81 or later - - skalibs version 2.14.1.0 or later: https://skarnet.org/software/skalibs/ + - skalibs version 2.14.1.1 or later: https://skarnet.org/software/skalibs/ - Optional: nsss version 0.2.0.4 or later: https://skarnet.org/software/nsss/ This software will run on any operating system that implements @@ -1,9 +1,10 @@ Changelog for execline. -In 2.9.4.1 +In 2.9.5.0 ---------- - Bugfixes. + - backtick now sets ? when it can be nonzero. In 2.9.4.0 diff --git a/doc/backtick.html b/doc/backtick.html index 14cc031..38c02a2 100644 --- a/doc/backtick.html +++ b/doc/backtick.html @@ -49,10 +49,15 @@ output as a value. </li> <li> <tt>-N</tt> : store <em>prog1...</em>'s output as is, including the last newline, if any. </li> <li> <tt>-n</tt> : chomp an ending newline off <em>prog1...</em>'s output. This is the default. </li> <li> <tt>-e</tt> : no autoimport. This is the default. </li> - <li> <tt>-E</tt> : autoimport. Instead of exec'ing into -<em>prog2...</em>, exec into <tt>importas -ui <em>variable</em> <em>variable</em> -<em>prog2...</em></tt>. This substitutes <em>variable</em> into the command -line instead of putting it into the environment. </li> + <li> <tt>-E</tt> : autoimport. Before exec'ing into +<em>prog2...</em>, perform a +<a href="https://skarnet.org/software/execline/el_substitute.html">substitution</a> +so that <tt>$?</tt> is replaced with <em>prog1...</em>'s exitcode (if +applicable, see below), and +<tt>${<em>variable</em>}</tt> is replaced with <em>prog1...</em>'s output, +instead of keeping the results in the environment. The variables will not +appear in the environment; if they preexisted in <tt>backtick</tt>'s +environment, they will be removed. </li> </ul> <p> @@ -76,5 +81,13 @@ the environment, and execution proceeds. </li> is set to <em>default</em>, and execution proceeds. </li> </ul> +<p> + If the command line can keep running after <em>prog1</em> crashes or exits +nonzero, i.e. if one of the <tt>-I</tt>, <tt>-x</tt> -or <tt>-D</tt> has been +given, then <tt>backtick</tt> also adds the <tt>?</tt> variable to the +environment; it then contains an <a href="exitcodes.html">approximation</a> +of <em>prog1</em>'s exit code. +</p> + </body> </html> diff --git a/doc/index.html b/doc/index.html index 0a226ab..73b7867 100644 --- a/doc/index.html +++ b/doc/index.html @@ -51,7 +51,7 @@ shell's syntax, and has no security issues. <li> A POSIX-compliant system with a standard C development environment </li> <li> GNU make, version 3.81 or later. </li> <li> <a href="//skarnet.org/software/skalibs/">skalibs</a> version -2.14.1.0 or later. It's a build-time requirement. It's also a run-time +2.14.1.1 or later. It's a build-time requirement. It's also a run-time requirement if you link against the shared version of the skalibs library. </li> </ul> @@ -77,7 +77,7 @@ want nsswitch-like functionality: <h3> Download </h3> <ul> - <li> The current released version of execline is <a href="execline-2.9.4.1.tar.gz">2.9.4.1</a>. </li> + <li> The current released version of execline is <a href="execline-2.9.5.0.tar.gz">2.9.5.0</a>. </li> <li> Alternatively, you can checkout a copy of the <a href="//git.skarnet.org/cgi-bin/cgit.cgi/execline/">execline git repository</a>: diff --git a/doc/upgrade.html b/doc/upgrade.html index 6511fe5..262c1e4 100644 --- a/doc/upgrade.html +++ b/doc/upgrade.html @@ -18,11 +18,13 @@ <h1> What has changed in execline </h1> -<h2> in 2.9.4.1 </h2> +<h2> in 2.9.5.0 </h2> <ul> <li> <a href="//skarnet.org/software/skalibs/">skalibs</a> -dependency bumped to 2.14.1.0. </li> +dependency bumped to 2.14.1.1. </li> + <li> <a href="backtick.html">backtick</a> now sets the ? +environment variable when it can be nonzero. </li> </ul> <h2> in 2.9.4.0 </h2> diff --git a/package/deps.mak b/package/deps.mak index c76a4cc..a8acd4d 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -57,6 +57,7 @@ src/libexecline/el_getstrict.o src/libexecline/el_getstrict.lo: src/libexecline/ src/libexecline/el_gspawn0.o src/libexecline/el_gspawn0.lo: src/libexecline/el_gspawn0.c src/include/execline/config.h src/include/execline/execline.h src/libexecline/el_modif_and_exec.o src/libexecline/el_modif_and_exec.lo: src/libexecline/el_modif_and_exec.c src/include/execline/config.h src/include/execline/execline.h src/libexecline/el_modif_and_spawn.o src/libexecline/el_modif_and_spawn.lo: src/libexecline/el_modif_and_spawn.c src/include/execline/config.h src/include/execline/execline.h +src/libexecline/el_modifs_and_exec.o src/libexecline/el_modifs_and_exec.lo: src/libexecline/el_modifs_and_exec.c src/include/execline/config.h src/include/execline/execline.h src/libexecline/el_parse.o src/libexecline/el_parse.lo: src/libexecline/el_parse.c src/include/execline/execline.h src/libexecline/el_parse_from_buffer.o src/libexecline/el_parse_from_buffer.lo: src/libexecline/el_parse_from_buffer.c src/include/execline/execline.h src/libexecline/el_parse_from_string.o src/libexecline/el_parse_from_string.lo: src/libexecline/el_parse_from_string.c src/include/execline/execline.h @@ -179,12 +180,12 @@ wait: src/execline/wait.o ${LIBEXECLINE} withstdinas: EXTRA_LIBS := -lskarnet withstdinas: src/execline/withstdinas.o ${LIBEXECLINE} ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) -libexecline.a.xyzzy: src/libexecline/el_execsequence.o src/libexecline/el_getstrict.o src/libexecline/el_modif_and_exec.o src/libexecline/el_modif_and_spawn.o src/libexecline/el_parse.o src/libexecline/el_parse_from_buffer.o src/libexecline/el_parse_from_string.o src/libexecline/el_popenv.o src/libexecline/el_pushenv.o src/libexecline/el_semicolon.o src/libexecline/el_spawn0.o src/libexecline/el_gspawn0.o src/libexecline/el_substandrun.o src/libexecline/el_substandrun_str.o src/libexecline/el_substitute.o src/libexecline/el_transform.o src/libexecline/el_vardupl.o src/libexecline/exlsn_define.o src/libexecline/exlsn_elglob.o src/libexecline/exlsn_importas.o src/libexecline/exlsn_multidefine.o src/libexecline/exlsn_exlp.o src/libexecline/exlsn_main.o src/libexecline/exlsn_free.o src/libexecline/exlp.o +libexecline.a.xyzzy: src/libexecline/el_execsequence.o src/libexecline/el_getstrict.o src/libexecline/el_modif_and_exec.o src/libexecline/el_modif_and_spawn.o src/libexecline/el_modifs_and_exec.o src/libexecline/el_parse.o src/libexecline/el_parse_from_buffer.o src/libexecline/el_parse_from_string.o src/libexecline/el_popenv.o src/libexecline/el_pushenv.o src/libexecline/el_semicolon.o src/libexecline/el_spawn0.o src/libexecline/el_gspawn0.o src/libexecline/el_substandrun.o src/libexecline/el_substandrun_str.o src/libexecline/el_substitute.o src/libexecline/el_transform.o src/libexecline/el_vardupl.o src/libexecline/exlsn_define.o src/libexecline/exlsn_elglob.o src/libexecline/exlsn_importas.o src/libexecline/exlsn_multidefine.o src/libexecline/exlsn_exlp.o src/libexecline/exlsn_main.o src/libexecline/exlsn_free.o src/libexecline/exlp.o else -libexecline.a.xyzzy: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.lo src/libexecline/el_substandrun.lo src/libexecline/el_substandrun_str.lo src/libexecline/el_substitute.lo src/libexecline/el_transform.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.lo src/libexecline/exlsn_multidefine.lo src/libexecline/exlsn_exlp.lo src/libexecline/exlsn_main.lo src/libexecline/exlsn_free.lo src/libexecline/exlp.lo +libexecline.a.xyzzy: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_modifs_and_exec.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.lo src/libexecline/el_substandrun.lo src/libexecline/el_substandrun_str.lo src/libexecline/el_substitute.lo src/libexecline/el_transform.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.lo src/libexecline/exlsn_multidefine.lo src/libexecline/exlsn_exlp.lo src/libexecline/exlsn_main.lo src/libexecline/exlsn_free.lo src/libexecline/exlp.lo endif libexecline.so.xyzzy: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} -libexecline.so.xyzzy: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.lo src/libexecline/el_substandrun.lo src/libexecline/el_substandrun_str.lo src/libexecline/el_substitute.lo src/libexecline/el_transform.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.lo src/libexecline/exlsn_multidefine.lo src/libexecline/exlsn_exlp.lo src/libexecline/exlsn_main.lo src/libexecline/exlsn_free.lo src/libexecline/exlp.lo +libexecline.so.xyzzy: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_modifs_and_exec.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.lo src/libexecline/el_substandrun.lo src/libexecline/el_substandrun_str.lo src/libexecline/el_substitute.lo src/libexecline/el_transform.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.lo src/libexecline/exlsn_multidefine.lo src/libexecline/exlsn_exlp.lo src/libexecline/exlsn_main.lo src/libexecline/exlsn_free.lo src/libexecline/exlp.lo execline: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} ${MAYBEPTHREAD_LIB} execline: src/multicall/execline.o ${LIBEXECLINE} ${LIBNSSS} INTERNAL_LIBS := diff --git a/package/info b/package/info index 1268414..6815b32 100644 --- a/package/info +++ b/package/info @@ -1,4 +1,4 @@ package=execline -version=2.9.4.1 +version=2.9.5.0 category=admin package_macro_name=EXECLINE diff --git a/src/execline/backtick.c b/src/execline/backtick.c index 06996bb..b921d7e 100644 --- a/src/execline/backtick.c +++ b/src/execline/backtick.c @@ -4,6 +4,7 @@ #include <sys/wait.h> #include <unistd.h> +#include <skalibs/types.h> #include <skalibs/sgetopt.h> #include <skalibs/strerr.h> #include <skalibs/stralloc.h> @@ -21,9 +22,10 @@ int main (int argc, char const **argv, char const *const *envp) subgetopt localopt = SUBGETOPT_ZERO ; int argc1, fdwstat ; stralloc value = STRALLOC_ZERO ; - char const *var ; - char const *val ; - int insist = 2, chomp = 1, doimport = 0 ; + char val1[UINT_FMT] ; + char const *var[2] = { [1] = "?" } ; + char const *val[2] = { [1] = val1 } ; + int insist = 2, chomp = 1, doimport = 0, allgood = 0 ; char const *def = 0 ; PROG = "backtick" ; for (;;) @@ -47,7 +49,7 @@ int main (int argc, char const **argv, char const *const *envp) if (argc < 2) dieusage() ; if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; - argc-- ; var = *argv++ ; + argc-- ; var[0] = *argv++ ; argc1 = el_semicolon(argv) ; if (!argc1) strerr_dief1x(100, "empty block") ; if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; @@ -62,12 +64,12 @@ int main (int argc, char const **argv, char const *const *envp) if (wait_pid(pid, &fdwstat) < 0) strerr_diefu1sys(111, "wait_pid") ; } - val = value.s ; + val[0] = value.s ; if (wait_status(fdwstat)) { if (insist >= 2) strerr_dief1x(wait_estatus(fdwstat), WIFSIGNALED(fdwstat) ? "child process crashed" : "child process exited non-zero") ; - else if (insist) val = def ; + else if (insist) val[0] = def ; } else if (strlen(value.s) < value.len - 1) { @@ -75,13 +77,14 @@ int main (int argc, char const **argv, char const *const *envp) strerr_dief1x(124, "child process output contained a null character") ; else if (insist) { - val = def ; + val[0] = def ; strerr_warnw1x("child process output contained a null character") ; } else value.len = strlen(value.s) + 1 ; } - else insist = 0 ; - if (!insist && chomp && (value.s[value.len - 2] == '\n')) + else allgood = 1 ; + if ((!insist || allgood) && chomp && (value.s[value.len - 2] == '\n')) value.s[--value.len - 1] = 0 ; - el_modif_and_exec(argv + argc1 + 1, var, val, doimport) ; + val1[uint_fmt(val1, wait_estatus(fdwstat))] = 0 ; + el_modifs_and_exec(argv + argc1 + 1, var, val, insist < 2 ? 2 : 1, doimport) ; } diff --git a/src/include/execline/execline.h b/src/include/execline/execline.h index a6fc114..8a204d8 100644 --- a/src/include/execline/execline.h +++ b/src/include/execline/execline.h @@ -82,5 +82,6 @@ extern int el_substitute (stralloc *, char const *, size_t, char const *, char c extern void el_modif_and_exec (char const *const *, char const *, char const *, int) gccattr_noreturn ; extern pid_t el_modif_and_spawn (char const *const *, char const *, char const *, int) ; +extern void el_modifs_and_exec (char const *const *, char const *const *, char const *const *, size_t, int) gccattr_noreturn ; #endif diff --git a/src/libexecline/deps-lib/execline b/src/libexecline/deps-lib/execline index a1f7c74..608fa7f 100644 --- a/src/libexecline/deps-lib/execline +++ b/src/libexecline/deps-lib/execline @@ -2,6 +2,7 @@ el_execsequence.o el_getstrict.o el_modif_and_exec.o el_modif_and_spawn.o +el_modifs_and_exec.o el_parse.o el_parse_from_buffer.o el_parse_from_string.o diff --git a/src/libexecline/el_modifs_and_exec.c b/src/libexecline/el_modifs_and_exec.c new file mode 100644 index 0000000..fe0117c --- /dev/null +++ b/src/libexecline/el_modifs_and_exec.c @@ -0,0 +1,72 @@ +/* ISC license. */ + +#include <string.h> + +#include <skalibs/env.h> +#include <skalibs/exec.h> + +#include <execline/config.h> +#include <execline/execline.h> + +void el_modifs_and_exec (char const *const *argv, char const *const *vars, char const *const *values, size_t n, int doimport) +{ + size_t pos = 0 ; + size_t yeslen = 0 ; + size_t yesn = 0 ; + size_t modiflen = 0 ; + for (size_t i = 0 ; i < n ; i++) + { + size_t len = strlen(vars[i]) + 1 ; + modiflen += len ; + if (values[i]) + { + yesn++ ; + yeslen += len ; + modiflen += 1 + strlen(values[i]) ; + } + } + + char modifs[modiflen ? modiflen : 1] ; + + for (size_t i = 0 ; i < n ; i++) + { + size_t len = strlen(vars[i]) ; + memcpy(modifs + pos, vars[i], len) ; + pos += len ; + if (values[i]) + { + modifs[pos++] = '=' ; + len = strlen(values[i]) ; + memcpy(modifs + pos, values[i], len) ; + pos += len ; + } + modifs[pos++] = 0 ; + } + + if (doimport && yesn) + { + size_t m = 0 ; + size_t ypos = 0 ; + char const *newargv[env_len(argv) + 3 + 5 * yesn] ; + char yesvars[yeslen ? yeslen : 1] ; + newargv[m++] = EXECLINE_BINPREFIX "multisubstitute" ; + for (size_t i = 0 ; i < n ; i++) if (values[i]) + { + size_t len = strlen(vars[i]) + 1 ; + char *p = yesvars + ypos ; + newargv[m++] = " importas" ; + newargv[m++] = " -ui" ; + newargv[m++] = " --" ; + newargv[m++] = p ; + newargv[m++] = p ; + yesvars[ypos++] = ' ' ; + memcpy(yesvars + ypos, vars[i], len) ; + ypos += len ; + } + newargv[m++] = "" ; + while (*argv) newargv[m++] = *argv++ ; + newargv[m++] = 0 ; + xmexec0_n(newargv, modifs, modiflen, n) ; + } + else xmexec0_n(argv, modifs, modiflen, n) ; +} |