about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2015-01-27 01:11:13 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2015-01-27 01:11:13 +0000
commita1f847eae994d665d01b85b0fd1a69492455f3ec (patch)
tree6e95b9da46cc0a735ef1f75ae0ad20bcbe61c915 /src
parent86aa8c6429885ecde3c4cbbb9528fc82f024f40a (diff)
downloadexecline-a1f847eae994d665d01b85b0fd1a69492455f3ec.tar.gz
execline-a1f847eae994d665d01b85b0fd1a69492455f3ec.tar.xz
execline-a1f847eae994d665d01b85b0fd1a69492455f3ec.zip
- Added -D option to backtick
 - Doc updated
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 ;
     }