summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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) ;
+}