summary refs log tree commit diff
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
parent86aa8c6429885ecde3c4cbbb9528fc82f024f40a (diff)
downloadexecline-a1f847eae994d665d01b85b0fd1a69492455f3ec.tar.gz
execline-a1f847eae994d665d01b85b0fd1a69492455f3ec.tar.xz
execline-a1f847eae994d665d01b85b0fd1a69492455f3ec.zip
- Added -D option to backtick
 - Doc updated
-rw-r--r--doc/backtick.html12
-rw-r--r--doc/forbacktickx.html2
-rw-r--r--doc/forx.html2
-rw-r--r--doc/index.html7
-rw-r--r--src/execline/backtick.c52
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>&nbsp;: insist. If <em>prog1</em> exits non-zero,
+ <li> <tt>-i</tt>&nbsp;: 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&nbsp;<em>default</em></tt>&nbsp;: 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 ;
     }