summary refs log tree commit diff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2024-04-06 17:54:13 +0000
committerLaurent Bercot <ska@appnovation.com>2024-04-06 17:54:13 +0000
commita5b7a319fb558f5df599de286318029d455ed193 (patch)
treeb468c6b2620613aa5f29d793feecb22c94dfedbf
parentdb852ecd93afc9f893886a132ee58b23579fc79d (diff)
downloadexecline-a5b7a319fb558f5df599de286318029d455ed193.tar.gz
execline-a5b7a319fb558f5df599de286318029d455ed193.tar.xz
execline-a5b7a319fb558f5df599de286318029d455ed193.zip
Prepare for 2.9.5.0; add ? support in backtick
Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r--COPYING2
-rw-r--r--INSTALL2
-rw-r--r--NEWS3
-rw-r--r--doc/backtick.html21
-rw-r--r--doc/index.html4
-rw-r--r--doc/upgrade.html6
-rw-r--r--package/deps.mak7
-rw-r--r--package/info2
-rw-r--r--src/execline/backtick.c23
-rw-r--r--src/include/execline/execline.h1
-rw-r--r--src/libexecline/deps-lib/execline1
-rw-r--r--src/libexecline/el_modifs_and_exec.c72
12 files changed, 119 insertions, 25 deletions
diff --git a/COPYING b/COPYING
index 08c9298..2ea7ac0 100644
--- a/COPYING
+++ b/COPYING
@@ -1,4 +1,4 @@
-Copyright (c) 2011-2023 Laurent Bercot <ska-skaware@skarnet.org>
+Copyright (c) 2011-2024 Laurent Bercot <ska-skaware@skarnet.org>
 
 Permission to use, copy, modify, and distribute this software for any
 purpose with or without fee is hereby granted, provided that the above
diff --git a/INSTALL b/INSTALL
index d9bdcde..adaaf3d 100644
--- a/INSTALL
+++ b/INSTALL
@@ -6,7 +6,7 @@ Build Instructions
 
   - A POSIX-compliant C development environment
   - GNU make version 3.81 or later
-  - skalibs version 2.14.1.0 or later: https://skarnet.org/software/skalibs/
+  - skalibs version 2.14.1.1 or later: https://skarnet.org/software/skalibs/
   - Optional: nsss version 0.2.0.4 or later: https://skarnet.org/software/nsss/
 
  This software will run on any operating system that implements
diff --git a/NEWS b/NEWS
index c481396..328c2d4 100644
--- a/NEWS
+++ b/NEWS
@@ -1,9 +1,10 @@
 Changelog for execline.
 
-In 2.9.4.1
+In 2.9.5.0
 ----------
 
  - Bugfixes.
+ - backtick now sets ? when it can be nonzero.
 
 
 In 2.9.4.0
diff --git a/doc/backtick.html b/doc/backtick.html
index 14cc031..38c02a2 100644
--- a/doc/backtick.html
+++ b/doc/backtick.html
@@ -49,10 +49,15 @@ output as a value. </li>
  <li> <tt>-N</tt>&nbsp;: store <em>prog1...</em>'s output as is, including the last newline, if any. </li>
  <li> <tt>-n</tt>&nbsp;: chomp an ending newline off <em>prog1...</em>'s output. This is the default. </li>
  <li> <tt>-e</tt>&nbsp;: no autoimport. This is the default. </li>
- <li> <tt>-E</tt>&nbsp;: autoimport. Instead of exec'ing into
-<em>prog2...</em>, exec into <tt>importas -ui <em>variable</em> <em>variable</em>
-<em>prog2...</em></tt>. This substitutes <em>variable</em> into the command
-line instead of putting it into the environment. </li>
+ <li> <tt>-E</tt>&nbsp;: autoimport. Before exec'ing into
+<em>prog2...</em>, perform a
+<a href="https://skarnet.org/software/execline/el_substitute.html">substitution</a>
+so that <tt>$?</tt> is replaced with <em>prog1...</em>'s exitcode (if
+applicable, see below), and
+<tt>${<em>variable</em>}</tt> is replaced with <em>prog1...</em>'s output,
+instead of keeping the results in the environment. The variables will not
+appear in the environment; if they preexisted in <tt>backtick</tt>'s
+environment, they will be removed. </li>
 </ul>
 
 <p>
@@ -76,5 +81,13 @@ the environment, and execution proceeds. </li>
 is set to <em>default</em>, and execution proceeds. </li>
 </ul>
 
+<p>
+ If the command line can keep running after <em>prog1</em> crashes or exits
+nonzero, i.e. if one of the <tt>-I</tt>, <tt>-x</tt> -or <tt>-D</tt> has been
+given, then <tt>backtick</tt> also adds the <tt>?</tt> variable to the
+environment; it then contains an <a href="exitcodes.html">approximation</a>
+of <em>prog1</em>'s exit code.
+</p>
+
 </body>
 </html>
diff --git a/doc/index.html b/doc/index.html
index 0a226ab..73b7867 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -51,7 +51,7 @@ shell's syntax, and has no security issues.
  <li> A POSIX-compliant system with a standard C development environment </li>
  <li> GNU make, version 3.81 or later. </li>
  <li> <a href="//skarnet.org/software/skalibs/">skalibs</a> version
-2.14.1.0 or later. It's a build-time requirement. It's also a run-time
+2.14.1.1 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>
@@ -77,7 +77,7 @@ want nsswitch-like functionality:
 <h3> Download </h3>
 
 <ul>
- <li> The current released version of execline is <a href="execline-2.9.4.1.tar.gz">2.9.4.1</a>. </li>
+ <li> The current released version of execline is <a href="execline-2.9.5.0.tar.gz">2.9.5.0</a>. </li>
  <li> Alternatively, you can checkout a copy of the
 <a href="//git.skarnet.org/cgi-bin/cgit.cgi/execline/">execline
 git repository</a>:
diff --git a/doc/upgrade.html b/doc/upgrade.html
index 6511fe5..262c1e4 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -18,11 +18,13 @@
 
 <h1> What has changed in execline </h1>
 
-<h2> in 2.9.4.1 </h2>
+<h2> in 2.9.5.0 </h2>
 
 <ul>
  <li> <a href="//skarnet.org/software/skalibs/">skalibs</a>
-dependency bumped to 2.14.1.0. </li>
+dependency bumped to 2.14.1.1. </li>
+ <li> <a href="backtick.html">backtick</a> now sets the ?
+environment variable when it can be nonzero. </li>
 </ul>
 
 <h2> in 2.9.4.0 </h2>
diff --git a/package/deps.mak b/package/deps.mak
index c76a4cc..a8acd4d 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -57,6 +57,7 @@ src/libexecline/el_getstrict.o src/libexecline/el_getstrict.lo: src/libexecline/
 src/libexecline/el_gspawn0.o src/libexecline/el_gspawn0.lo: src/libexecline/el_gspawn0.c src/include/execline/config.h src/include/execline/execline.h
 src/libexecline/el_modif_and_exec.o src/libexecline/el_modif_and_exec.lo: src/libexecline/el_modif_and_exec.c src/include/execline/config.h src/include/execline/execline.h
 src/libexecline/el_modif_and_spawn.o src/libexecline/el_modif_and_spawn.lo: src/libexecline/el_modif_and_spawn.c src/include/execline/config.h src/include/execline/execline.h
+src/libexecline/el_modifs_and_exec.o src/libexecline/el_modifs_and_exec.lo: src/libexecline/el_modifs_and_exec.c src/include/execline/config.h src/include/execline/execline.h
 src/libexecline/el_parse.o src/libexecline/el_parse.lo: src/libexecline/el_parse.c src/include/execline/execline.h
 src/libexecline/el_parse_from_buffer.o src/libexecline/el_parse_from_buffer.lo: src/libexecline/el_parse_from_buffer.c src/include/execline/execline.h
 src/libexecline/el_parse_from_string.o src/libexecline/el_parse_from_string.lo: src/libexecline/el_parse_from_string.c src/include/execline/execline.h
@@ -179,12 +180,12 @@ wait: src/execline/wait.o ${LIBEXECLINE}
 withstdinas: EXTRA_LIBS := -lskarnet
 withstdinas: src/execline/withstdinas.o ${LIBEXECLINE}
 ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),)
-libexecline.a.xyzzy: src/libexecline/el_execsequence.o src/libexecline/el_getstrict.o src/libexecline/el_modif_and_exec.o src/libexecline/el_modif_and_spawn.o src/libexecline/el_parse.o src/libexecline/el_parse_from_buffer.o src/libexecline/el_parse_from_string.o src/libexecline/el_popenv.o src/libexecline/el_pushenv.o src/libexecline/el_semicolon.o src/libexecline/el_spawn0.o src/libexecline/el_gspawn0.o src/libexecline/el_substandrun.o src/libexecline/el_substandrun_str.o src/libexecline/el_substitute.o src/libexecline/el_transform.o src/libexecline/el_vardupl.o src/libexecline/exlsn_define.o src/libexecline/exlsn_elglob.o src/libexecline/exlsn_importas.o src/libexecline/exlsn_multidefine.o src/libexecline/exlsn_exlp.o src/libexecline/exlsn_main.o src/libexecline/exlsn_free.o src/libexecline/exlp.o
+libexecline.a.xyzzy: src/libexecline/el_execsequence.o src/libexecline/el_getstrict.o src/libexecline/el_modif_and_exec.o src/libexecline/el_modif_and_spawn.o src/libexecline/el_modifs_and_exec.o src/libexecline/el_parse.o src/libexecline/el_parse_from_buffer.o src/libexecline/el_parse_from_string.o src/libexecline/el_popenv.o src/libexecline/el_pushenv.o src/libexecline/el_semicolon.o src/libexecline/el_spawn0.o src/libexecline/el_gspawn0.o src/libexecline/el_substandrun.o src/libexecline/el_substandrun_str.o src/libexecline/el_substitute.o src/libexecline/el_transform.o src/libexecline/el_vardupl.o src/libexecline/exlsn_define.o src/libexecline/exlsn_elglob.o src/libexecline/exlsn_importas.o src/libexecline/exlsn_multidefine.o src/libexecline/exlsn_exlp.o src/libexecline/exlsn_main.o src/libexecline/exlsn_free.o src/libexecline/exlp.o
 else
-libexecline.a.xyzzy: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.lo src/libexecline/el_substandrun.lo src/libexecline/el_substandrun_str.lo src/libexecline/el_substitute.lo src/libexecline/el_transform.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.lo src/libexecline/exlsn_multidefine.lo src/libexecline/exlsn_exlp.lo src/libexecline/exlsn_main.lo src/libexecline/exlsn_free.lo src/libexecline/exlp.lo
+libexecline.a.xyzzy: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_modifs_and_exec.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.lo src/libexecline/el_substandrun.lo src/libexecline/el_substandrun_str.lo src/libexecline/el_substitute.lo src/libexecline/el_transform.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.lo src/libexecline/exlsn_multidefine.lo src/libexecline/exlsn_exlp.lo src/libexecline/exlsn_main.lo src/libexecline/exlsn_free.lo src/libexecline/exlp.lo
 endif
 libexecline.so.xyzzy: EXTRA_LIBS := -lskarnet ${SPAWN_LIB}
-libexecline.so.xyzzy: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.lo src/libexecline/el_substandrun.lo src/libexecline/el_substandrun_str.lo src/libexecline/el_substitute.lo src/libexecline/el_transform.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.lo src/libexecline/exlsn_multidefine.lo src/libexecline/exlsn_exlp.lo src/libexecline/exlsn_main.lo src/libexecline/exlsn_free.lo src/libexecline/exlp.lo
+libexecline.so.xyzzy: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_modifs_and_exec.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.lo src/libexecline/el_substandrun.lo src/libexecline/el_substandrun_str.lo src/libexecline/el_substitute.lo src/libexecline/el_transform.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.lo src/libexecline/exlsn_multidefine.lo src/libexecline/exlsn_exlp.lo src/libexecline/exlsn_main.lo src/libexecline/exlsn_free.lo src/libexecline/exlp.lo
 execline: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} ${MAYBEPTHREAD_LIB}
 execline: src/multicall/execline.o ${LIBEXECLINE} ${LIBNSSS}
 INTERNAL_LIBS :=
diff --git a/package/info b/package/info
index 1268414..6815b32 100644
--- a/package/info
+++ b/package/info
@@ -1,4 +1,4 @@
 package=execline
-version=2.9.4.1
+version=2.9.5.0
 category=admin
 package_macro_name=EXECLINE
diff --git a/src/execline/backtick.c b/src/execline/backtick.c
index 06996bb..b921d7e 100644
--- a/src/execline/backtick.c
+++ b/src/execline/backtick.c
@@ -4,6 +4,7 @@
 #include <sys/wait.h>
 #include <unistd.h>
 
+#include <skalibs/types.h>
 #include <skalibs/sgetopt.h>
 #include <skalibs/strerr.h>
 #include <skalibs/stralloc.h>
@@ -21,9 +22,10 @@ int main (int argc, char const **argv, char const *const *envp)
   subgetopt localopt = SUBGETOPT_ZERO ;
   int argc1, fdwstat ;
   stralloc value = STRALLOC_ZERO ;
-  char const *var ;
-  char const *val ;
-  int insist = 2, chomp = 1, doimport = 0 ;
+  char val1[UINT_FMT] ;
+  char const *var[2] = { [1] = "?" } ;
+  char const *val[2] = { [1] = val1 } ;
+  int insist = 2, chomp = 1, doimport = 0, allgood = 0 ;
   char const *def = 0 ;
   PROG = "backtick" ;
   for (;;)
@@ -47,7 +49,7 @@ int main (int argc, char const **argv, char const *const *envp)
 
   if (argc < 2) dieusage() ;
   if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ;
-  argc-- ; var = *argv++ ;
+  argc-- ; var[0] = *argv++ ;
   argc1 = el_semicolon(argv) ;
   if (!argc1) strerr_dief1x(100, "empty block") ;
   if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ;
@@ -62,12 +64,12 @@ int main (int argc, char const **argv, char const *const *envp)
     if (wait_pid(pid, &fdwstat) < 0) strerr_diefu1sys(111, "wait_pid") ;
   }
 
-  val = value.s ;
+  val[0] = value.s ;
   if (wait_status(fdwstat))
   {
     if (insist >= 2)
       strerr_dief1x(wait_estatus(fdwstat), WIFSIGNALED(fdwstat) ? "child process crashed" : "child process exited non-zero") ;
-    else if (insist) val = def ;
+    else if (insist) val[0] = def ;
   }
   else if (strlen(value.s) < value.len - 1)
   {
@@ -75,13 +77,14 @@ int main (int argc, char const **argv, char const *const *envp)
       strerr_dief1x(124, "child process output contained a null character") ;
     else if (insist)
     {
-      val = def ;
+      val[0] = def ;
       strerr_warnw1x("child process output contained a null character") ;
     }
     else value.len = strlen(value.s) + 1 ;
   }
-  else insist = 0 ;
-  if (!insist && chomp && (value.s[value.len - 2] == '\n'))
+  else allgood = 1 ;
+  if ((!insist || allgood) && chomp && (value.s[value.len - 2] == '\n'))
     value.s[--value.len - 1] = 0 ;
-  el_modif_and_exec(argv + argc1 + 1, var, val, doimport) ;
+  val1[uint_fmt(val1, wait_estatus(fdwstat))] = 0 ; 
+  el_modifs_and_exec(argv + argc1 + 1, var, val, insist < 2 ? 2 : 1, doimport) ;
 }
diff --git a/src/include/execline/execline.h b/src/include/execline/execline.h
index a6fc114..8a204d8 100644
--- a/src/include/execline/execline.h
+++ b/src/include/execline/execline.h
@@ -82,5 +82,6 @@ extern int el_substitute (stralloc *, char const *, size_t, char const *, char c
 
 extern void el_modif_and_exec (char const *const *, char const *, char const *, int) gccattr_noreturn ;
 extern pid_t el_modif_and_spawn (char const *const *, char const *, char const *, int) ;
+extern void el_modifs_and_exec (char const *const *, char const *const *, char const *const *, size_t, int) gccattr_noreturn ;
 
 #endif
diff --git a/src/libexecline/deps-lib/execline b/src/libexecline/deps-lib/execline
index a1f7c74..608fa7f 100644
--- a/src/libexecline/deps-lib/execline
+++ b/src/libexecline/deps-lib/execline
@@ -2,6 +2,7 @@ el_execsequence.o
 el_getstrict.o
 el_modif_and_exec.o
 el_modif_and_spawn.o
+el_modifs_and_exec.o
 el_parse.o
 el_parse_from_buffer.o
 el_parse_from_string.o
diff --git a/src/libexecline/el_modifs_and_exec.c b/src/libexecline/el_modifs_and_exec.c
new file mode 100644
index 0000000..fe0117c
--- /dev/null
+++ b/src/libexecline/el_modifs_and_exec.c
@@ -0,0 +1,72 @@
+/* ISC license. */
+
+#include <string.h>
+
+#include <skalibs/env.h>
+#include <skalibs/exec.h>
+
+#include <execline/config.h>
+#include <execline/execline.h>
+
+void el_modifs_and_exec (char const *const *argv, char const *const *vars, char const *const *values, size_t n, int doimport)
+{
+  size_t pos = 0 ;
+  size_t yeslen = 0 ;
+  size_t yesn = 0 ;
+  size_t modiflen = 0 ;
+  for (size_t i = 0 ; i < n ; i++)
+  {
+    size_t len = strlen(vars[i]) + 1 ;
+    modiflen += len ;
+    if (values[i])
+    {
+      yesn++ ;
+      yeslen += len ;
+      modiflen += 1 + strlen(values[i]) ;
+    }
+  }
+
+  char modifs[modiflen ? modiflen : 1] ;
+
+  for (size_t i = 0 ; i < n ; i++)
+  {
+    size_t len = strlen(vars[i]) ;
+    memcpy(modifs + pos, vars[i], len) ;
+    pos += len ;
+    if (values[i])
+    {
+      modifs[pos++] = '=' ;
+      len = strlen(values[i]) ;
+      memcpy(modifs + pos, values[i], len) ;
+      pos += len ;
+    }
+    modifs[pos++] = 0 ;
+  }
+
+  if (doimport && yesn)
+  {
+    size_t m = 0 ;
+    size_t ypos = 0 ;
+    char const *newargv[env_len(argv) + 3 + 5 * yesn] ;
+    char yesvars[yeslen ? yeslen : 1] ;
+    newargv[m++] = EXECLINE_BINPREFIX "multisubstitute" ;
+    for (size_t i = 0 ; i < n ; i++) if (values[i])
+    {
+      size_t len = strlen(vars[i]) + 1 ;
+      char *p = yesvars + ypos ;
+      newargv[m++] = " importas" ;
+      newargv[m++] = " -ui" ;
+      newargv[m++] = " --" ;
+      newargv[m++] = p ;
+      newargv[m++] = p ;
+      yesvars[ypos++] = ' ' ;
+      memcpy(yesvars + ypos, vars[i], len) ;
+      ypos += len ;
+    }
+    newargv[m++] = "" ;
+    while (*argv) newargv[m++] = *argv++ ;
+    newargv[m++] = 0 ;
+    xmexec0_n(newargv, modifs, modiflen, n) ;
+  }
+  else xmexec0_n(argv, modifs, modiflen, n) ;
+}