summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/backtick.html14
-rw-r--r--doc/forbacktickx.html7
-rw-r--r--doc/forstdin.html7
-rw-r--r--doc/forx.html7
-rw-r--r--doc/getcwd.html12
-rw-r--r--doc/getpid.html12
-rw-r--r--doc/withstdinas.html7
-rw-r--r--package/deps.mak24
-rw-r--r--src/execline/backtick.c82
-rw-r--r--src/execline/deps-exe/getcwd1
-rw-r--r--src/execline/deps-exe/getpid1
-rw-r--r--src/execline/deps-exe/withstdinas1
-rw-r--r--src/execline/forbacktickx.c11
-rw-r--r--src/execline/forstdin.c114
-rw-r--r--src/execline/forx.c39
-rw-r--r--src/execline/getcwd.c36
-rw-r--r--src/execline/getpid.c38
-rw-r--r--src/execline/withstdinas.c59
-rw-r--r--src/include/execline/execline.h7
-rw-r--r--src/libexecline/deps-lib/execline2
-rw-r--r--src/libexecline/el_modif_and_exec.c36
-rw-r--r--src/libexecline/el_modif_and_spawn.c39
-rw-r--r--src/libexecline/el_spawn0.c1
23 files changed, 333 insertions, 224 deletions
diff --git a/doc/backtick.html b/doc/backtick.html
index 1f77432..91e963a 100644
--- a/doc/backtick.html
+++ b/doc/backtick.html
@@ -30,7 +30,7 @@ environment variable, then executes another program.
</p>
<pre>
- backtick [ -i | -I | -D <em>default</em> ] [ -N | -n ] <em>variable</em> { <em>prog1...</em> } <em>prog2...</em>
+ backtick [ -i | -I | -D <em>default</em> ] [ -N | -n ] [ -E | -e ] <em>variable</em> { <em>prog1...</em> } <em>prog2...</em>
</pre>
<ul>
@@ -48,6 +48,11 @@ output as a value. </li>
<ul>
<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>
</ul>
<p>
@@ -69,12 +74,5 @@ or to whatever <em>prog1...</em> wrote before crashing;
then execution proceeds. </li>
</ul>
-<h2> Notes </h2>
-
-<ul>
- <li> You can start <em>prog2...</em> with "importas -u <em>variable</em> <em>variable</em>"
-to perform variable substitution. </li>
-</ul>
-
</body>
</html>
diff --git a/doc/forbacktickx.html b/doc/forbacktickx.html
index d28ad0b..cbf33b5 100644
--- a/doc/forbacktickx.html
+++ b/doc/forbacktickx.html
@@ -30,7 +30,7 @@ run another program.
</p>
<pre>
- forbacktickx [ -p | -o <em>okcodes</em> | -x <em>breakcodes</em> ] [ -N | -n ] [ -C | -c ] [ -0 | -d <em>delim</em> ] <em>variable</em> { <em>gen...</em> } <em>loop...</em>
+ forbacktickx [ -E | -e ] [ -p | -o <em>okcodes</em> | -x <em>breakcodes</em> ] [ -N | -n ] [ -C | -c ] [ -0 | -d <em>delim</em> ] <em>variable</em> { <em>gen...</em> } <em>loop...</em>
</pre>
<ul>
@@ -65,6 +65,11 @@ not listed in <em>okcodes</em>, forbacktickx will exit immediately with an
option, but with inverted meaning - the listed exit codes are codes
that will make forbacktickx break the loop and exit, and the unlisted exit
codes will make it keep looping. </li>
+ <li> <tt>-e</tt>&nbsp;: no autoimport. This is the default. </li>
+ <li> <tt>-E</tt>&nbsp;: autoimport. Instead of spawning
+<em>loop...</em>, spawn <tt>importas -ui <em>variable</em> <em>variable</em>
+<em>loop...</em></tt>. This substitutes <em>variable</em> into the command
+line instead of putting it into the environment. </li>
</ul>
<p>
diff --git a/doc/forstdin.html b/doc/forstdin.html
index 74644b4..3b00d7d 100644
--- a/doc/forstdin.html
+++ b/doc/forstdin.html
@@ -30,7 +30,7 @@ run another program.
</p>
<pre>
- forstdin [ -p | -o <em>okcodes</em> | -x <em>breakcodes</em> ] [ -N | -n ] [ -C | -c ] [ -0 | -d <em>delim</em> ] <em>variable</em> <em>loop...</em>
+ forstdin [ -E | -e ] [ -p | -o <em>okcodes</em> | -x <em>breakcodes</em> ] [ -N | -n ] [ -C | -c ] [ -0 | -d <em>delim</em> ] <em>variable</em> <em>loop...</em>
</pre>
<ul>
@@ -61,6 +61,11 @@ not listed in <em>okcodes</em>, forstdin will exit immediately with an
option, but with inverted meaning - the listed exit codes are codes
that will make forstdin break the loop and exit, and the unlisted exit
codes will make it keep looping. </li>
+ <li> <tt>-e</tt>&nbsp;: no autoimport. This is the default. </li>
+ <li> <tt>-E</tt>&nbsp;: autoimport. Instead of spawning
+<em>loop...</em>, spawn <tt>importas -ui <em>variable</em> <em>variable</em>
+<em>loop...</em></tt>. This substitutes <em>variable</em> into the command
+line instead of putting it into the environment. </li>
</ul>
<p>
diff --git a/doc/forx.html b/doc/forx.html
index 1c2a61c..8f1d558 100644
--- a/doc/forx.html
+++ b/doc/forx.html
@@ -29,7 +29,7 @@
</p>
<pre>
- forx [ -p ] [ -o <em>okcodes</em> | -x <em>breakcodes</em> ] <em>variable</em> { <em>args...</em> } <em>loop...</em>
+ forx [ -E | -e ] [ -p ] [ -o <em>okcodes</em> | -x <em>breakcodes</em> ] <em>variable</em> { <em>args...</em> } <em>loop...</em>
</pre>
<ul>
@@ -63,6 +63,11 @@ will exit 0 if all of the exit codes are in the values listed in the <em>okcodes
list, else it will exit 1. If the <tt>-x</tt> option has been given,
<tt>forx</tt> will exit 0 if none of the exit codes are in the values
listed in the <em>breakcodes</em> list, else it will exit 1. </li>
+ <li> <tt>-e</tt>&nbsp;: no autoimport. This is the default. </li>
+ <li> <tt>-E</tt>&nbsp;: autoimport. Instead of spawning
+<em>loop...</em>, spawn <tt>importas -ui <em>variable</em> <em>variable</em>
+<em>loop...</em></tt>. This substitutes <em>variable</em> into the command
+line instead of putting it into the environment. </li>
</ul>
<h2> Notes </h2>
diff --git a/doc/getcwd.html b/doc/getcwd.html
index 9735630..d3e7e27 100644
--- a/doc/getcwd.html
+++ b/doc/getcwd.html
@@ -27,7 +27,7 @@ then executes a program.
<h2> Interface </h2>
<pre>
- getcwd <em>var</em> <em>prog...</em>
+ getcwd [ -E | -e ] <em>var</em> <em>prog...</em>
</pre>
<p>
@@ -37,6 +37,16 @@ into the <em>var</em> variable, then
execs into <em>prog</em> with its arguments.
</p>
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-e</tt>&nbsp;: no autoimport. This is the default. </li>
+ <li> <tt>-E</tt>&nbsp;: autoimport. Instead of exec'ing into
+<em>prog...</em>, exec into <tt>importas -ui <em>var</em> <em>var</em>
+<em>prog...</em></tt>. This substitutes <em>var</em> into the command
+line instead of putting it into the environment. </li>
+</ul>
+
<h2> Notes </h2>
<ul>
diff --git a/doc/getpid.html b/doc/getpid.html
index ca363df..5a849e8 100644
--- a/doc/getpid.html
+++ b/doc/getpid.html
@@ -26,7 +26,7 @@ then executes a program.
<h2> Interface </h2>
<pre>
- getpid <em>var</em> <em>prog...</em>
+ getpid [ -E | -e ] <em>var</em> <em>prog...</em>
</pre>
<p>
@@ -34,6 +34,16 @@ then executes a program.
execs into <em>prog</em> with its arguments.
</p>
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-e</tt>&nbsp;: no autoimport. This is the default. </li>
+ <li> <tt>-E</tt>&nbsp;: autoimport. Instead of exec'ing into
+<em>prog...</em>, exec into <tt>importas -ui <em>var</em> <em>var</em>
+<em>prog...</em></tt>. This substitutes <em>var</em> into the command
+line instead of putting it into the environment. </li>
+</ul>
+
<h2> Notes </h2>
<ul>
diff --git a/doc/withstdinas.html b/doc/withstdinas.html
index ccd69d7..5b9e653 100644
--- a/doc/withstdinas.html
+++ b/doc/withstdinas.html
@@ -31,7 +31,7 @@ environment variable.
</p>
<pre>
- withstdinas [ -i | -I | -D <em>default</em> ] [ -N | -n ] <em>variable</em> <em>prog...</em>
+ withstdinas [ -i | -I | -D <em>default</em> ] [ -N | -n ] [ -E | -e ] <em>variable</em> <em>prog...</em>
</pre>
<ul>
@@ -46,6 +46,11 @@ environment variable.
<ul>
<li> <tt>-N</tt>&nbsp;: do not chomp an ending newline off stdin. </li>
<li> <tt>-n</tt>&nbsp;: chomp an ending newline off stdin. 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>prog...</em>, exec into <tt>importas -ui <em>variable</em> <em>variable</em>
+<em>prog...</em></tt>. This substitutes <em>variable</em> into the command
+line instead of putting it into the environment. </li>
</ul>
<p>
diff --git a/package/deps.mak b/package/deps.mak
index 3aac760..6bfce8e 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -24,10 +24,10 @@ src/execline/fdreserve.o src/execline/fdreserve.lo: src/execline/fdreserve.c
src/execline/fdswap.o src/execline/fdswap.lo: src/execline/fdswap.c
src/execline/forbacktickx.o src/execline/forbacktickx.lo: src/execline/forbacktickx.c src/include/execline/config.h src/include/execline/execline.h
src/execline/foreground.o src/execline/foreground.lo: src/execline/foreground.c src/include/execline/execline.h
-src/execline/forstdin.o src/execline/forstdin.lo: src/execline/forstdin.c src/include/execline/config.h src/include/execline/execline.h
+src/execline/forstdin.o src/execline/forstdin.lo: src/execline/forstdin.c src/include/execline/execline.h
src/execline/forx.o src/execline/forx.lo: src/execline/forx.c src/include/execline/config.h src/include/execline/execline.h
-src/execline/getcwd.o src/execline/getcwd.lo: src/execline/getcwd.c
-src/execline/getpid.o src/execline/getpid.lo: src/execline/getpid.c
+src/execline/getcwd.o src/execline/getcwd.lo: src/execline/getcwd.c src/include/execline/execline.h
+src/execline/getpid.o src/execline/getpid.lo: src/execline/getpid.c src/include/execline/execline.h
src/execline/heredoc.o src/execline/heredoc.lo: src/execline/heredoc.c
src/execline/homeof.o src/execline/homeof.lo: src/execline/homeof.c
src/execline/if.o src/execline/if.lo: src/execline/if.c src/include/execline/execline.h
@@ -46,10 +46,12 @@ src/execline/shift.o src/execline/shift.lo: src/execline/shift.c src/include/exe
src/execline/trap.o src/execline/trap.lo: src/execline/trap.c src/include/execline/execline.h
src/execline/tryexec.o src/execline/tryexec.lo: src/execline/tryexec.c src/include/execline/execline.h
src/execline/unexport.o src/execline/unexport.lo: src/execline/unexport.c
-src/execline/wait.o src/execline/wait.lo: src/execline/wait.c src/include/execline/execline.h
-src/execline/withstdinas.o src/execline/withstdinas.lo: src/execline/withstdinas.c
+src/execline/wait.o src/execline/wait.lo: src/execline/wait.c src/include/execline/config.h src/include/execline/execline.h
+src/execline/withstdinas.o src/execline/withstdinas.lo: src/execline/withstdinas.c src/include/execline/execline.h
src/libexecline/el_execsequence.o src/libexecline/el_execsequence.lo: src/libexecline/el_execsequence.c src/include/execline/execline.h
src/libexecline/el_getstrict.o src/libexecline/el_getstrict.lo: src/libexecline/el_getstrict.c 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_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
@@ -123,9 +125,9 @@ forstdin: src/execline/forstdin.o ${LIBEXECLINE}
forx: EXTRA_LIBS := -lskarnet ${SPAWN_LIB}
forx: src/execline/forx.o ${LIBEXECLINE}
getcwd: EXTRA_LIBS := -lskarnet
-getcwd: src/execline/getcwd.o
+getcwd: src/execline/getcwd.o ${LIBEXECLINE}
getpid: EXTRA_LIBS := -lskarnet
-getpid: src/execline/getpid.o
+getpid: src/execline/getpid.o ${LIBEXECLINE}
heredoc: EXTRA_LIBS := -lskarnet
heredoc: src/execline/heredoc.o
homeof: EXTRA_LIBS := -lskarnet ${MAYBEPTHREAD_LIB}
@@ -165,14 +167,14 @@ unexport: src/execline/unexport.o
wait: EXTRA_LIBS := -lskarnet
wait: src/execline/wait.o ${LIBEXECLINE}
withstdinas: EXTRA_LIBS := -lskarnet
-withstdinas: src/execline/withstdinas.o
+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_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_spawn1.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_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_spawn1.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_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_spawn1.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_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_spawn1.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
-libexecline.so.xyzzy: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.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_spawn1.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_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_spawn1.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
posix-cd: EXTRA_LIBS := -lskarnet
posix-cd: src/posix/posix-cd.o
posix-umask: EXTRA_LIBS := -lskarnet
diff --git a/src/execline/backtick.c b/src/execline/backtick.c
index fa7403f..9394456 100644
--- a/src/execline/backtick.c
+++ b/src/execline/backtick.c
@@ -12,22 +12,22 @@
#include <execline/execline.h>
-#define USAGE "backtick [ -i | -I | -D default ] [ -N | -n ] var { prog... } remainder..."
+#define USAGE "backtick [ -i | -I | -D default ] [ -N | -n ] [ -E | -e ] 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 ;
- pid_t pid ;
int argc1, fdwstat ;
- stralloc modif = STRALLOC_ZERO ;
- size_t modifstart ;
- int insist = 0, chomp = 1 ;
+ stralloc value = STRALLOC_ZERO ;
+ char const *var ;
+ char const *val ;
+ int insist = 0, chomp = 1, doimport = 0 ;
char const *def = 0 ;
PROG = "backtick" ;
for (;;)
{
- int opt = subgetopt_r(argc, argv, "iINnD:", &localopt) ;
+ int opt = subgetopt_r(argc, argv, "iINnD:Ee", &localopt) ;
if (opt < 0) break ;
switch (opt)
{
@@ -36,69 +36,51 @@ int main (int argc, char const **argv, char const *const *envp)
case 'N' : chomp = 0 ; break ;
case 'n' : chomp = 1 ; break ;
case 'D' : def = localopt.arg ; break ;
+ case 'E' : doimport = 1 ; break ;
+ case 'e' : doimport = 0 ; break ;
default : dieusage() ;
}
}
argc -= localopt.ind ; argv += localopt.ind ;
if (argc < 2) dieusage() ;
- 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++ ;
+ if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ;
+ argc-- ; var = *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") ;
+ {
+ pid_t pid = child_spawn1_pipe(argv[0], argv, envp, &fdwstat, 1) ;
+ if (!pid) strerr_diefu2sys(111, "spawn ", argv[0]) ;
+ if (!slurp(&value, fdwstat) || !stralloc_0(&value))
+ strerr_diefu1sys(111, "slurp") ;
+ close(fdwstat) ;
+ if (wait_pid(pid, &fdwstat) < 0) strerr_diefu1sys(111, "wait_pid") ;
+ }
+
+ val = value.s ;
if (wait_status(fdwstat))
{
if (insist >= 2)
if (WIFSIGNALED(fdwstat)) strerr_dief1x(111, "child process crashed") ;
else strerr_dief1x(WEXITSTATUS(fdwstat), "child process exited non-zero") ;
- else if (insist)
- {
- modif.len = modifstart - 1 ;
- chomp = 0 ;
- }
- else if (def)
- {
- modif.len = modifstart ;
- if (!stralloc_cats(&modif, def)) strerr_diefu1sys(111, "stralloc_catb") ;
- }
+ else if (insist) val = 0 ;
+ else if (def) val = def ;
}
- if (argc1 == argc - 1) return 0 ;
- if (!stralloc_0(&modif)) strerr_diefu1sys(111, "stralloc_catb") ;
+ else if (strlen(value.s) < value.len - 1)
{
- size_t reallen = strlen(modif.s) ;
- if (reallen < modif.len - 1)
+ if (insist >= 2)
+ strerr_dief1x(1, "child process output contained a null character") ;
+ else if (insist) val = 0 ;
+ else if (def)
{
- if (insist >= 2)
- strerr_dief1x(1, "child process output contained a null character") ;
- else if (insist)
- {
- modif.len = modifstart ;
- modif.s[modif.len - 1] = 0 ;
- chomp = 0 ;
- }
- else if (def)
- {
- modif.len = modifstart ;
- if (!stralloc_catb(&modif, def, strlen(def)+1))
- strerr_diefu1sys(111, "stralloc_catb") ;
- strerr_warnw2x("child process output contained a null character", " - using default instead") ;
- }
- else modif.len = reallen + 1 ;
+ val = def ;
+ strerr_warnw2x("child process output contained a null character", " - using default instead") ;
}
- if (chomp && (modif.s[modif.len - 2] == '\n'))
- modif.s[--modif.len - 1] = 0 ;
}
- xmexec_en(argv + argc1 + 1, envp, modif.s, modif.len, 1) ;
+ else if (chomp && (value.s[value.len - 2] == '\n'))
+ value.s[--value.len - 1] = 0 ;
+ el_modif_and_exec(argv + argc1 + 1, var, val, doimport) ;
}
diff --git a/src/execline/deps-exe/getcwd b/src/execline/deps-exe/getcwd
index e7187fe..97021b5 100644
--- a/src/execline/deps-exe/getcwd
+++ b/src/execline/deps-exe/getcwd
@@ -1 +1,2 @@
+${LIBEXECLINE}
-lskarnet
diff --git a/src/execline/deps-exe/getpid b/src/execline/deps-exe/getpid
index e7187fe..97021b5 100644
--- a/src/execline/deps-exe/getpid
+++ b/src/execline/deps-exe/getpid
@@ -1 +1,2 @@
+${LIBEXECLINE}
-lskarnet
diff --git a/src/execline/deps-exe/withstdinas b/src/execline/deps-exe/withstdinas
index e7187fe..97021b5 100644
--- a/src/execline/deps-exe/withstdinas
+++ b/src/execline/deps-exe/withstdinas
@@ -1 +1,2 @@
+${LIBEXECLINE}
-lskarnet
diff --git a/src/execline/forbacktickx.c b/src/execline/forbacktickx.c
index 1f3a0f1..2fc8bb8 100644
--- a/src/execline/forbacktickx.c
+++ b/src/execline/forbacktickx.c
@@ -12,20 +12,20 @@
#include <execline/config.h>
#include <execline/execline.h>
-#define USAGE "forbacktickx [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -N | -n ] [ -C | -c ] [ -0 | -d delim ] var { backtickcmd... } command..."
+#define USAGE "forbacktickx [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -E | -e ] [ -N | -n ] [ -C | -c ] [ -0 | -d delim ] var { backtickcmd... } command..."
#define dieusage() strerr_dieusage(100, USAGE)
int main (int argc, char const *const *argv)
{
char const *delim = "\n" ;
char const *codes = 0 ;
- int crunch = 0, chomp = 1, not = 1, par = 0 ;
+ int crunch = 0, chomp = 1, not = 1, par = 0, doimport = 0 ;
PROG = "forbacktickx" ;
{
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
- int opt = subgetopt_r(argc, argv, "pNnCc0d:o:x:", &l) ;
+ int opt = subgetopt_r(argc, argv, "pNnCc0d:o:x:Ee", &l) ;
if (opt == -1) break ;
switch (opt)
{
@@ -54,6 +54,8 @@ int main (int argc, char const *const *argv)
not = 1 ;
break ;
}
+ case 'E' : doimport = 1 ; break ;
+ case 'e' : doimport = 0 ; break ;
default : dieusage() ;
}
}
@@ -65,7 +67,7 @@ int main (int argc, char const *const *argv)
{
unsigned int m = 0, i = 1 ;
int fd = dup(0) ;
- char const *newargv[argc + 18] ;
+ char const *newargv[argc + 19] ;
char fmt[UINT_FMT] ;
if (fd < 0)
{
@@ -81,6 +83,7 @@ int main (int argc, char const *const *argv)
newargv[m++] = EXECLINE_BINPREFIX "unexport" ;
newargv[m++] = "!" ;
newargv[m++] = EXECLINE_BINPREFIX "forstdin" ;
+ newargv[m++] = doimport ? "-E" : "-e" ;
if (par) newargv[m++] = "-p" ;
newargv[m++] = chomp ? "-n" : "-N" ;
if (crunch) newargv[m++] = "-C" ;
diff --git a/src/execline/forstdin.c b/src/execline/forstdin.c
index 336aaa4..bacb1ae 100644
--- a/src/execline/forstdin.c
+++ b/src/execline/forstdin.c
@@ -9,16 +9,14 @@
#include <skalibs/strerr2.h>
#include <skalibs/stralloc.h>
#include <skalibs/genalloc.h>
-#include <skalibs/env.h>
#include <skalibs/sig.h>
#include <skalibs/djbunix.h>
#include <skalibs/skamisc.h>
#include <skalibs/netstring.h>
-#include <execline/config.h>
#include <execline/execline.h>
-#define USAGE "forstdin [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -N | -n ] [ -C | -c ] [ -0 | -d delim ] var command..."
+#define USAGE "forstdin [ -E | -e ] [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -N | -n ] [ -C | -c ] [ -0 | -d delim ] var command..."
#define dieusage() strerr_dieusage(100, USAGE)
static genalloc pids = GENALLOC_ZERO ; /* pid_t */
@@ -45,19 +43,20 @@ static void parallel_sigchld_handler (int sig)
(void)sig ;
}
-int main (int argc, char const **argv, char const *const *envp)
+int main (int argc, char const **argv)
{
+ stralloc value = STRALLOC_ZERO ;
char const *delim = "\n" ;
size_t delimlen = 1 ;
size_t nbc = 0 ;
unsigned short okcodes[256] ;
- int crunch = 0, chomp = 1, not = 1, eofcode = 1 ;
+ int crunch = 0, chomp = 1, not = 1, eofcode = 1, doimport = 0 ;
PROG = "forstdin" ;
{
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
- int opt = subgetopt_r(argc, argv, "pNnCc0d:o:x:", &l) ;
+ int opt = subgetopt_r(argc, argv, "pNnCc0d:o:x:Ee", &l) ;
if (opt == -1) break ;
switch (opt)
{
@@ -81,81 +80,74 @@ int main (int argc, char const **argv, char const *const *envp)
not = 1 ;
if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ;
break ;
+ case 'E' : doimport = 1 ; break ;
+ case 'e' : doimport = 0 ; break ;
default : dieusage() ;
}
}
argc -= l.ind ; argv += l.ind ;
}
if (argc < 2) dieusage() ;
+ if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ;
+
+ if (pids.s)
{
- stralloc modif = STRALLOC_ZERO ;
- size_t envlen = env_len(envp) ;
- size_t modifstart = strlen(argv[0]) + 1 ;
- char const *newenv[envlen + 2] ;
- if (!stralloc_ready(&modif, modifstart+1))
- strerr_diefu1sys(111, "stralloc_ready") ;
- memcpy(modif.s, argv[0], modifstart - 1) ;
- modif.s[modifstart-1] = '=' ;
- if (pids.s)
- {
- if (sig_catch(SIGCHLD, &parallel_sigchld_handler) < 0)
- strerr_diefu1sys(111, "install SIGCHLD handler") ;
- }
- for (;;)
+ if (sig_catch(SIGCHLD, &parallel_sigchld_handler) < 0)
+ strerr_diefu1sys(111, "install SIGCHLD handler") ;
+ }
+ for (;;)
+ {
+ pid_t pid ;
+ value.len = 0 ;
+ if (delimlen)
{
- pid_t pid ;
- modif.len = modifstart ;
- if (delimlen)
- {
- int r = skagetlnsep(buffer_0, &modif, delim, delimlen) ;
- if (!r) break ;
- else if (r < 0)
- {
- if (errno != EPIPE) strerr_diefu1sys(111, "skagetlnsep") ;
- if (chomp) break ;
- }
- if (crunch && modif.len == modifstart + 1) continue ;
- if (chomp) modif.len-- ;
- }
- else
+ int r = skagetlnsep(buffer_0, &value, delim, delimlen) ;
+ if (!r) break ;
+ else if (r < 0)
{
- size_t unread = 0 ;
- if (netstring_get(buffer_0, &modif, &unread) <= 0)
- {
- if (netstring_okeof(buffer_0, unread)) break ;
- else strerr_diefu1sys(111, "netstring_get") ;
- }
- }
- eofcode = 0 ;
- if (!stralloc_0(&modif)) strerr_diefu1sys(111, "stralloc_0") ;
- if (!env_mergen(newenv, envlen+2, envp, envlen, modif.s, modif.len, 1))
- strerr_diefu1sys(111, "merge environment") ;
- if (pids.s) sig_block(SIGCHLD) ;
- pid = el_spawn0(argv[1], argv + 1, newenv) ;
- if (!pid) strerr_diefu2sys(111, "spawn ", argv[1]) ;
- if (pids.s)
- {
- if (!genalloc_append(pid_t, &pids, &pid))
- strerr_diefu1sys(111, "genalloc_append") ;
- sig_unblock(SIGCHLD) ;
+ if (errno != EPIPE) strerr_diefu1sys(111, "skagetlnsep") ;
+ if (chomp) break ;
}
- else
+ if (crunch && value.len == 1) continue ;
+ if (chomp) value.len-- ;
+ }
+ else
+ {
+ size_t unread = 0 ;
+ if (netstring_get(buffer_0, &value, &unread) <= 0)
{
- int wstat ;
- if (wait_pid(pid, &wstat) < 0)
- strerr_diefu2sys(111, "wait for ", argv[1]) ;
- if (not == isok(okcodes, nbc, wait_estatus(wstat)))
- return wait_estatus(wstat) ;
+ if (netstring_okeof(buffer_0, unread)) break ;
+ else strerr_diefu1sys(111, "netstring_get") ;
}
}
- stralloc_free(&modif) ;
+ eofcode = 0 ;
+ if (!stralloc_0(&value)) strerr_diefu1sys(111, "stralloc_0") ;
+ if (pids.s) sig_block(SIGCHLD) ;
+ pid = el_modif_and_spawn(argv + 1, argv[0], value.s, doimport) ;
+ if (!pid) strerr_diefu2sys(111, "spawn ", argv[1]) ;
+ if (pids.s)
+ {
+ if (!genalloc_append(pid_t, &pids, &pid))
+ strerr_diefu1sys(111, "genalloc_append") ;
+ sig_unblock(SIGCHLD) ;
+ }
+ else
+ {
+ int wstat ;
+ if (wait_pid(pid, &wstat) < 0)
+ strerr_diefu2sys(111, "wait for ", argv[1]) ;
+ if (not == isok(okcodes, nbc, wait_estatus(wstat)))
+ return wait_estatus(wstat) ;
+ }
}
if (pids.s)
+ {
for (;;)
{
sig_block(SIGCHLD) ;
if (!pids.len) break ;
sig_pause() ;
}
+ }
return eofcode ;
}
diff --git a/src/execline/forx.c b/src/execline/forx.c
index be03794..8e6659b 100644
--- a/src/execline/forx.c
+++ b/src/execline/forx.c
@@ -13,7 +13,7 @@
#include <execline/config.h>
#include <execline/execline.h>
-#define USAGE "forx [ -p ] [ -o okcode,okcode,... | -x breakcode,breakcode,... ] var { values... } command..."
+#define USAGE "forx [ -E | -e ] [ -p ] [ -o okcode,okcode,... | -x breakcode,breakcode,... ] var { values... } command..."
#define dieusage() strerr_dieusage(100, USAGE)
static int isok (unsigned short const *tab, unsigned int n, int code)
@@ -42,19 +42,19 @@ static int waitn_code (unsigned short const *tab, unsigned int nbc, pid_t *pids,
return ok ;
}
-int main (int argc, char const **argv, char const *const *envp)
+int main (int argc, char const **argv)
{
- char const *x ;
- int argc1 ;
+ char const *var ;
unsigned short okcodes[256] ;
size_t nbc = 0 ;
- int flagpar = 0, not = 1 ;
+ int flagpar = 0, not = 1, doimport = 0 ;
+ unsigned int argc1 ;
PROG = "forx" ;
{
subgetopt_t l = SUBGETOPT_ZERO ;
for (;;)
{
- int opt = subgetopt_r(argc, argv, "po:x:", &l) ;
+ int opt = subgetopt_r(argc, argv, "po:x:Ee", &l) ;
if (opt == -1) break ;
switch (opt)
{
@@ -67,6 +67,8 @@ int main (int argc, char const **argv, char const *const *envp)
not = 1 ;
if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ;
break ;
+ case 'E' : doimport = 1 ; break ;
+ case 'e' : doimport = 0 ; break ;
default : dieusage() ;
}
}
@@ -74,32 +76,17 @@ int main (int argc, char const **argv, char const *const *envp)
}
if (argc < 2) dieusage() ;
- x = argv[0] ; if (!*x) dieusage() ;
- if (x[0] == EXECLINE_BLOCK_QUOTE_CHAR)
- strerr_warnw3x("variable ", x, " starts with a block quoting character") ;
- argv++ ; argc-- ;
+ if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ;
+ var = *argv++ ; argc-- ;
argc1 = el_semicolon(argv) ;
if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ;
if (!argc1 || (argc1 + 1 == argc)) return 0 ;
+
{
- size_t envlen = env_len(envp) ;
- size_t varlen = strlen(x) ;
- unsigned int i = 0 ;
pid_t pids[flagpar ? argc1 : 1] ;
- char const *newenv[envlen + 2] ;
-
- for (; i < (unsigned int)argc1 ; i++)
+ for (unsigned int i = 0 ; i < argc1 ; i++)
{
- pid_t pid ;
- size_t vallen = strlen(argv[i]) ;
- char modif[varlen + vallen + 2] ;
- memcpy(modif, x, varlen) ;
- modif[varlen] = '=' ;
- memcpy(modif + varlen + 1, argv[i], vallen) ;
- modif[varlen + vallen + 1] = 0 ;
- if (!env_mergen(newenv, envlen + 2, envp, envlen, modif, varlen + vallen + 2, 1))
- strerr_diefu1sys(111, "build new environment") ;
- pid = el_spawn0(argv[argc1+1], argv + argc1 + 1, newenv) ;
+ pid_t pid = el_modif_and_spawn(argv + argc1 + 1, var, argv[i], doimport) ;
if (!pid) strerr_diefu2sys(111, "spawn ", argv[argc1+1]) ;
if (flagpar) pids[i] = pid ;
else
diff --git a/src/execline/getcwd.c b/src/execline/getcwd.c
index d41bd5a..2a82924 100644
--- a/src/execline/getcwd.c
+++ b/src/execline/getcwd.c
@@ -2,23 +2,39 @@
#include <string.h>
+#include <skalibs/sgetopt.h>
#include <skalibs/strerr2.h>
#include <skalibs/stralloc.h>
#include <skalibs/djbunix.h>
-#include <skalibs/exec.h>
-#define USAGE "getcwd variable prog..."
+#include <execline/execline.h>
+
+#define USAGE "getcwd [ -E | -e ] variable prog..."
+#define dieusage() strerr_dieusage(100, USAGE)
int main (int argc, char const *const *argv)
{
+ int doimport = 0 ;
stralloc sa = STRALLOC_ZERO ;
PROG = "getcwd" ;
- if (argc < 3) strerr_dieusage(100, USAGE) ;
- if (strchr(argv[1], '='))
- strerr_dief2x(100, "invalid variable name: ", argv[1]) ;
- if (!stralloc_cats(&sa, argv[1]) || !stralloc_catb(&sa, "=", 1))
- strerr_diefu1sys(111, "stralloc_catb") ;
- if (sagetcwd(&sa) < 0) strerr_diefu1sys(111, "getcwd") ;
- if (!stralloc_0(&sa)) strerr_diefu1sys(111, "stralloc_catb") ;
- xmexec_n(argv + 2, sa.s, sa.len, 1) ;
+ {
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "Ee", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'E' : doimport = 1 ; break ;
+ case 'e' : doimport = 0 ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (argc < 2) dieusage() ;
+ if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ;
+
+ if (sagetcwd(&sa) < 0 || !stralloc_0(&sa)) strerr_diefu1sys(111, "getcwd") ;
+ el_modif_and_exec(argv + 1, argv[0], sa.s, doimport) ;
}
diff --git a/src/execline/getpid.c b/src/execline/getpid.c
index 06c4aaf..64866de 100644
--- a/src/execline/getpid.c
+++ b/src/execline/getpid.c
@@ -4,25 +4,37 @@
#include <unistd.h>
#include <skalibs/types.h>
+#include <skalibs/sgetopt.h>
#include <skalibs/strerr2.h>
-#include <skalibs/exec.h>
-#define USAGE "getpid variable prog..."
+#include <execline/execline.h>
+
+#define USAGE "getpid [ -E | -e ] variable prog..."
+#define dieusage() strerr_dieusage(100, USAGE)
int main (int argc, char const *const *argv)
{
- size_t len ;
+ int doimport = 0 ;
+ char fmt[PID_FMT] ;
PROG = "getpid" ;
- if (argc < 3) strerr_dieusage(100, USAGE) ;
- len = strlen(argv[1]) ;
- if (memchr(argv[1], '=', len))
- strerr_dief2x(100, "invalid variable name: ", argv[1]) ;
{
- size_t i = len+1 ;
- char fmt[PID_FMT + len + 2] ;
- memcpy(fmt, argv[1], len) ;
- fmt[len] = '=' ;
- i += pid_fmt(fmt+i, getpid()) ; fmt[i++] = 0 ;
- xmexec_n(argv+2, fmt, i, 1) ;
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ int opt = subgetopt_r(argc, argv, "Ee", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'E' : doimport = 1 ; break ;
+ case 'e' : doimport = 0 ; break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
}
+ if (argc < 2) dieusage() ;
+ if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ;
+
+ fmt[pid_fmt(fmt, getpid())] = 0 ;
+ el_modif_and_exec(argv + 1, argv[0], fmt, doimport) ;
}
diff --git a/src/execline/withstdinas.c b/src/execline/withstdinas.c
index 467b68b..cd025bf 100644
--- a/src/execline/withstdinas.c
+++ b/src/execline/withstdinas.c
@@ -6,22 +6,23 @@
#include <skalibs/strerr2.h>
#include <skalibs/stralloc.h>
#include <skalibs/djbunix.h>
-#include <skalibs/exec.h>
-#define USAGE "withstdinas [ -i | -I | -D default ] [ -N | -n ] var remainder..."
+#include <execline/execline.h>
+
+#define USAGE "withstdinas [ -i | -I | -D default ] [ -N | -n ] [ -E | -e ] var remainder..."
#define dieusage() strerr_dieusage(100, USAGE)
-int main (int argc, char const **argv)
+int main (int argc, char const *const *argv)
{
subgetopt_t localopt = SUBGETOPT_ZERO ;
- stralloc modif = STRALLOC_ZERO ;
- size_t modifstart ;
- int insist = 0, chomp = 1 ;
+ stralloc value = STRALLOC_ZERO ;
+ int insist = 0, chomp = 1, doimport = 0 ;
char const *def = 0 ;
+ char const *val ;
PROG = "withstdinas" ;
for (;;)
{
- int opt = subgetopt_r(argc, argv, "iINnD:", &localopt) ;
+ int opt = subgetopt_r(argc, argv, "iINnD:Ee", &localopt) ;
if (opt < 0) break ;
switch (opt)
{
@@ -30,41 +31,29 @@ int main (int argc, char const **argv)
case 'N' : chomp = 0 ; break ;
case 'n' : chomp = 1 ; break ;
case 'D' : def = localopt.arg ; break ;
+ case 'E' : doimport = 1 ; break ;
+ case 'e' : doimport = 0 ; break ;
default : dieusage() ;
}
}
argc -= localopt.ind ; argv += localopt.ind ;
-
if (!argc) dieusage() ;
- if (!*argv[0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ;
- if (!stralloc_cats(&modif, argv[0]) || !stralloc_catb(&modif, "=", 1))
- strerr_diefu1sys(111, "stralloc_catb") ;
- modifstart = modif.len ;
- if (!slurp(&modif, 0)) strerr_diefu1sys(111, "slurp") ;
- if (!stralloc_0(&modif)) strerr_diefu1sys(111, "stralloc_catb") ;
+ if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ;
+
+ if (!slurp(&value, 0) || !stralloc_0(&value)) strerr_diefu1sys(111, "slurp") ;
+ val = value.s ;
+ if (strlen(value.s) < value.len - 1)
{
- size_t reallen = strlen(modif.s) ;
- if (reallen < modif.len - 1)
+ if (insist >= 2)
+ strerr_dief1x(1, "stdin contained a null character") ;
+ else if (insist) val = 0 ;
+ else if (def)
{
- if (insist >= 2)
- strerr_dief1x(1, "stdin contained a null character") ;
- else if (insist)
- {
- modif.len = modifstart ;
- modif.s[modif.len - 1] = 0 ;
- chomp = 0 ;
- }
- else if (def)
- {
- modif.len = modifstart ;
- if (!stralloc_catb(&modif, def, strlen(def)+1))
- strerr_diefu1sys(111, "stralloc_catb") ;
- strerr_warnw2x("stdin contained a null character", " - using default instead") ;
- }
- else modif.len = reallen + 1 ;
+ val = def ;
+ strerr_warnw2x("stdin contained a null character", " - using default instead") ;
}
- if (chomp && (modif.s[modif.len - 2] == '\n'))
- modif.s[--modif.len - 1] = 0 ;
}
- xmexec0_n(argv + 1, modif.s, modif.len, 1) ;
+ else if (chomp && (value.s[value.len - 2] == '\n'))
+ value.s[--value.len - 1] = 0 ;
+ el_modif_and_exec(argv + 1, argv[0], val, doimport) ;
}
diff --git a/src/include/execline/execline.h b/src/include/execline/execline.h
index bbe4db9..144283d 100644
--- a/src/include/execline/execline.h
+++ b/src/include/execline/execline.h
@@ -4,6 +4,7 @@
#define EXECLINE_H
#include <sys/types.h>
+
#include <skalibs/gccattributes.h>
#include <skalibs/buffer.h>
#include <skalibs/stralloc.h>
@@ -76,4 +77,10 @@ struct elsubst_s
extern int el_substitute (stralloc *, char const *, size_t, char const *, char const *, elsubst_t const *, unsigned int) ;
+
+/* Execution with or without substitution */
+
+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) ;
+
#endif
diff --git a/src/libexecline/deps-lib/execline b/src/libexecline/deps-lib/execline
index 96d4e18..e896f2f 100644
--- a/src/libexecline/deps-lib/execline
+++ b/src/libexecline/deps-lib/execline
@@ -1,5 +1,7 @@
el_execsequence.o
el_getstrict.o
+el_modif_and_exec.o
+el_modif_and_spawn.o
el_parse.o
el_parse_from_buffer.o
el_parse_from_string.o
diff --git a/src/libexecline/el_modif_and_exec.c b/src/libexecline/el_modif_and_exec.c
new file mode 100644
index 0000000..e2a3618
--- /dev/null
+++ b/src/libexecline/el_modif_and_exec.c
@@ -0,0 +1,36 @@
+/* ISC license. */
+
+#include <string.h>
+
+#include <skalibs/env.h>
+#include <skalibs/exec.h>
+
+#include <execline/config.h>
+#include <execline/execline.h>
+
+void el_modif_and_exec (char const *const *argv, char const *var, char const *value, int doimport)
+{
+ size_t varlen = strlen(var) ;
+ size_t modiflen = value ? varlen + strlen(value) + 2 : 1 ;
+ char modifs[modiflen] ;
+ if (value)
+ {
+ memcpy(modifs, var, varlen) ;
+ modifs[varlen] = '=' ;
+ memcpy(modifs + varlen + 1, value, modiflen - varlen - 1) ;
+ }
+ if (doimport)
+ {
+ size_t m = 0 ;
+ char const *newargv[env_len(argv) + 6] ;
+ newargv[m++] = EXECLINE_BINPREFIX "importas" ;
+ newargv[m++] = "-ui" ;
+ newargv[m++] = "--" ;
+ newargv[m++] = var ;
+ newargv[m++] = var ;
+ while (*argv) newargv[m++] = *argv++ ;
+ newargv[m++] = 0 ;
+ xmexec0_n(newargv, value ? modifs : var, value ? modiflen : varlen + 1, 1) ;
+ }
+ else xmexec0_n(argv, value ? modifs : var, value ? modiflen : varlen + 1, 1) ;
+}
diff --git a/src/libexecline/el_modif_and_spawn.c b/src/libexecline/el_modif_and_spawn.c
new file mode 100644
index 0000000..0070052
--- /dev/null
+++ b/src/libexecline/el_modif_and_spawn.c
@@ -0,0 +1,39 @@
+/* ISC license. */
+
+#include <string.h>
+
+#include <skalibs/posixplz.h>
+#include <skalibs/env.h>
+
+#include <execline/config.h>
+#include <execline/execline.h>
+
+pid_t el_modif_and_spawn (char const *const *argv, char const *var, char const *value, int doimport)
+{
+ size_t varlen = strlen(var) ;
+ size_t modiflen = value ? varlen + strlen(value) + 2 : 1 ;
+ size_t envlen = env_len((char const *const *)environ) ;
+ char const *newenv[envlen + 2] ;
+ char modifs[modiflen] ;
+ if (value)
+ {
+ memcpy(modifs, var, varlen) ;
+ modifs[varlen] = '=' ;
+ memcpy(modifs + varlen + 1, value, modiflen - varlen - 1) ;
+ }
+ if (!env_mergen(newenv, envlen + 2, (char const *const *)environ, envlen, value ? modifs : var, value ? modiflen : varlen + 1, 1)) return 0 ;
+ if (doimport)
+ {
+ size_t m = 0 ;
+ char const *newargv[env_len(argv) + 6] ;
+ newargv[m++] = EXECLINE_BINPREFIX "importas" ;
+ newargv[m++] = "-ui" ;
+ newargv[m++] = "--" ;
+ newargv[m++] = var ;
+ newargv[m++] = var ;
+ while (*argv) newargv[m++] = *argv++ ;
+ newargv[m++] = 0 ;
+ return el_spawn0(newargv[0], newargv, newenv) ;
+ }
+ else return el_spawn0(argv[0], argv, newenv) ;
+}
diff --git a/src/libexecline/el_spawn0.c b/src/libexecline/el_spawn0.c
index 7e10902..0cfe017 100644
--- a/src/libexecline/el_spawn0.c
+++ b/src/libexecline/el_spawn0.c
@@ -1,6 +1,7 @@
/* ISC license. */
#include <skalibs/djbunix.h>
+
#include <execline/config.h>
#include <execline/execline.h>