diff options
-rw-r--r-- | doc/backtick.html | 12 | ||||
-rw-r--r-- | doc/forbacktickx.html | 2 | ||||
-rw-r--r-- | doc/forx.html | 2 | ||||
-rw-r--r-- | doc/index.html | 7 | ||||
-rw-r--r-- | src/execline/backtick.c | 52 |
5 files changed, 45 insertions, 30 deletions
diff --git a/doc/backtick.html b/doc/backtick.html index 7bdc037..bdcd785 100644 --- a/doc/backtick.html +++ b/doc/backtick.html @@ -29,7 +29,7 @@ another program. </p> <pre> - backtick [ -i ] [ -n ] <em>variable</em> { <em>prog1...</em> } <em>prog2...</em> + backtick [ -i | -D <em>default</em> ] [ -n ] <em>variable</em> { <em>prog1...</em> } <em>prog2...</em> </pre> <ul> @@ -45,9 +45,13 @@ output as a value. </li> <h2> Options </h2> <ul> - <li> <tt>-i</tt> : insist. If <em>prog1</em> exits non-zero, + <li> <tt>-i</tt> : insist. If <em>prog1</em> crashes or exits non-zero, <tt>backtick</tt> exits with the same exit code (or 111 if <em>prog1</em> -crashed for some reason). Without this option, <tt>backtick</tt> execs into +crashed). </li> + <li> <tt>-D <em>default</em></tt> : default value. If +<em>prog1</em> crashes or exits non-zero, <em>default</em> is used as +<em>variable</em>'s value. If neither the <tt>-i</tt> nor the <tt>-D</tt> +option have been given, <tt>backtick</tt> execs into <em>prog2...</em> no matter what <em>prog1</em> does, with the null word as <em>variable</em>'s value if <em>prog1</em> didn't write anything before dying. </li> @@ -58,7 +62,7 @@ output. </li> <h2> Notes </h2> <ul> - <li> You can start <em>prog2...</em> with "import <em>variable</em> unexport <em>variable</em>" + <li> You can start <em>prog2...</em> with "import -u <em>variable</em>" to perform variable substitution. </li> </ul> diff --git a/doc/forbacktickx.html b/doc/forbacktickx.html index 9e09c81..d40799a 100644 --- a/doc/forbacktickx.html +++ b/doc/forbacktickx.html @@ -69,7 +69,7 @@ split <em>x</em>. </li> <h2> Notes </h2> <ul> - <li> You can start <em>loop...</em> with "import <em>variable</em> unexport <em>variable</em>" + <li> You can start <em>loop...</em> with "import -u <em>variable</em>" to perform variable substitution. </ul> diff --git a/doc/forx.html b/doc/forx.html index 86729b8..0349a85 100644 --- a/doc/forx.html +++ b/doc/forx.html @@ -58,7 +58,7 @@ same exit code. </li> <h2> Notes </h2> <ul> - <li> You can start <em>loop</em> with "import <em>variable</em> unexport <em>variable</em>" + <li> You can start <em>loop</em> with "import -u <em>variable</em>" if you want variable substitution. </li> </ul> diff --git a/doc/index.html b/doc/index.html index 851a0c5..a847509 100644 --- a/doc/index.html +++ b/doc/index.html @@ -48,9 +48,12 @@ shell's syntax, and has no security issues. <ul> <li> A POSIX-compliant system with a standard C development environment </li> - <li> GNU make, version 4.0 or later </li> + <li> GNU make, version 4.0 or later. Please be aware that execline will +not build with an earlier version. </li> <li> <a href="http://skarnet.org/software/skalibs/">skalibs</a> version -2.2.1.0 or later </li> +2.2.1.0 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> <h3> Licensing </h3> diff --git a/src/execline/backtick.c b/src/execline/backtick.c index d0f74e4..3928f90 100644 --- a/src/execline/backtick.c +++ b/src/execline/backtick.c @@ -1,6 +1,7 @@ /* ISC license. */ #include <sys/types.h> +#include <sys/wait.h> #include <unistd.h> #include <skalibs/bytestr.h> #include <skalibs/sgetopt.h> @@ -9,25 +10,29 @@ #include <skalibs/djbunix.h> #include <execline/execline.h> -#define USAGE "backtick [ -i ] [ -n ] var { prog... } remainder..." +#define USAGE "backtick [ -i | -D default ] [ -n ] var { prog... } remainder..." #define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const **argv, char const *const *envp) { subgetopt_t localopt = SUBGETOPT_ZERO ; - int argc1 ; + pid_t pid ; + int argc1, fdwstat ; stralloc modif = STRALLOC_ZERO ; + unsigned int modifstart ; int insist = 0, chomp = 0 ; + char const *def = 0 ; PROG = "backtick" ; for (;;) { - register int opt = subgetopt_r(argc, argv, "ein", &localopt) ; + register int opt = subgetopt_r(argc, argv, "einD:", &localopt) ; if (opt < 0) break ; switch (opt) { case 'i' : insist = 1 ; break ; case 'n' : chomp = 1 ; break ; case 'e' : break ; /* compat */ + case 'D' : def = localopt.arg ; break ; default : dieusage() ; } } @@ -37,33 +42,29 @@ int main (int argc, char const **argv, char const *const *envp) if (!*argv[0]) strerr_dief1x(100, "empty variable not accepted") ; if (!stralloc_cats(&modif, argv[0]) || !stralloc_catb(&modif, "=", 1)) strerr_diefu1sys(111, "stralloc_catb") ; + modifstart = modif.len ; argc-- ; argv++ ; argc1 = el_semicolon(argv) ; if (!argc1) strerr_dief1x(100, "empty block") ; if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; + argv[argc1] = 0 ; + pid = child_spawn1_pipe(argv[0], argv, envp, &fdwstat, 1) ; + if (!pid) strerr_diefu2sys(111, "spawn ", argv[0]) ; + if (!slurp(&modif, fdwstat)) strerr_diefu1sys(111, "slurp") ; + close(fdwstat) ; + if (wait_pid(pid, &fdwstat) < 0) strerr_diefu1sys(111, "wait_pid") ; + + if (WIFSIGNALED(fdwstat) || WEXITSTATUS(fdwstat)) { - int p[2] ; - pid_t pid ; - if (pipe(p) < 0) strerr_diefu1sys(111, "pipe") ; - pid = fork() ; - switch (pid) + if (insist) + if (WIFSIGNALED(fdwstat)) strerr_dief1x(111, "child process crashed") ; + else strerr_dief1x(WEXITSTATUS(fdwstat), "child process exited non-zero") ; + else if (def) { - case -1: strerr_diefu1sys(111, "fork") ; - case 0: - argv[argc1] = 0 ; - fd_close(p[0]) ; - PROG = "backtick (child)" ; - if (fd_move(1, p[1]) < 0) strerr_diefu1sys(111, "fd_move") ; - pathexec_run(argv[0], argv, envp) ; - strerr_dieexec(111, argv[0]) ; + modif.len = modifstart ; + if (!stralloc_cats(&modif, def)) strerr_diefu1sys(111, "stralloc_catb") ; } - fd_close(p[1]) ; - if (!slurp(&modif, p[0])) strerr_diefu1sys(111, "slurp") ; - fd_close(p[0]) ; - if (wait_pid(pid, &p[0]) < 0) strerr_diefu1sys(111, "wait_pid") ; - if (insist && wait_status(p[0])) - strerr_dief1x(wait_status(p[0]), "child process exited non-zero") ; } if (argc == argc1 - 1) return 0 ; if (!stralloc_0(&modif)) strerr_diefu1sys(111, "stralloc_catb") ; @@ -73,6 +74,13 @@ int main (int argc, char const **argv, char const *const *envp) { if (insist) strerr_dief1x(1, "child process output contained a null character") ; + else if (def) + { + modif.len = modifstart ; + if (!stralloc_catb(&modif, def, str_len(def)+1)) + strerr_diefu1sys(111, "stralloc_catb") ; + strerr_warnw2x("child process output contained a null character", " - using default instead") ; + } else modif.len = reallen + 1 ; } |