summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/execline/backtick.c52
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 ;
}