diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/execline/backtick.c | 52 |
1 files changed, 30 insertions, 22 deletions
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 ; } |