summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2015-02-26 01:48:50 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2015-02-26 01:48:50 +0000
commit4d067b3020104a8b19a34fa4d3b6e5e8f3eb036a (patch)
tree5c5752681d5fef7837d22a5d8fb590d4b6003d1d
parente1fe79a9e705e3cab8f632cdbe8e1774cdef2761 (diff)
downloadexecline-4d067b3020104a8b19a34fa4d3b6e5e8f3eb036a.tar.xz
- added forstdinv2.1.1.0
- rewrote forbacktickx as a wrapper around forstdin - removed el_obsolescent - version: rc for 2.1.1.0
-rw-r--r--doc/forbacktickx.html5
-rw-r--r--doc/forstdin.html78
-rw-r--r--doc/index.html3
-rw-r--r--doc/upgrade.html7
-rw-r--r--package/deps.mak10
-rw-r--r--package/info2
-rw-r--r--package/modes3
-rw-r--r--package/targets.mak1
-rw-r--r--src/execline/deps-exe/forbacktickx1
-rw-r--r--src/execline/deps-exe/forstdin2
-rw-r--r--src/execline/forbacktickx.c155
-rw-r--r--src/execline/forstdin.c157
-rw-r--r--src/include/execline/execline.h1
-rw-r--r--src/libexecline/deps-lib/execline1
-rw-r--r--src/libexecline/el_obsolescent.c10
15 files changed, 312 insertions, 124 deletions
diff --git a/doc/forbacktickx.html b/doc/forbacktickx.html
index 0780f3d..979a483 100644
--- a/doc/forbacktickx.html
+++ b/doc/forbacktickx.html
@@ -76,7 +76,10 @@ split <em>x</em>. </li>
<ul>
<li> You can start <em>loop...</em> with "import -u <em>variable</em>"
-to perform variable substitution.
+to perform variable substitution. </li>
+ <li> forbacktickx is now implemented as a trivial wrapper around the
+<a href="pipeline.html">pipeline</a> and
+<a href="forstdin.html">forstdin</a> commands. </li>
</ul>
</body>
diff --git a/doc/forstdin.html b/doc/forstdin.html
new file mode 100644
index 0000000..e4c5534
--- /dev/null
+++ b/doc/forstdin.html
@@ -0,0 +1,78 @@
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>execline: the forstdin command</title>
+ <meta name="Description" content="execline: the forstdin command" />
+ <meta name="Keywords" content="execline command forstdin" />
+ <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">execline</a><br />
+<a href="http://skarnet.org/software/">Software</a><br />
+<a href="http://skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>forstdin</tt> program </h1>
+
+<p>
+<tt>forstdin</tt> uses its input as loop elements to
+run another program.
+</p>
+
+<h2> Interface </h2>
+
+<p>
+ In an <a href="execlineb.html">execlineb</a> script:
+</p>
+
+<pre>
+ forstdin [ -p | -o <em>okcodes</em> | -x <em>breakcodes</em> ] [ -n ] [ -C | -c ] [ -0 | -d <em>delim</em> ] <em>variable</em> <em>loop...</em>
+</pre>
+
+<ul>
+ <li> <tt>forstdin</tt> reads its standard input as it becomes available,
+<a href="el_transform.html#split">splitting</a> it automatically. </li>
+ <li> For every argument <em>x</em> in the split output,
+<tt>forstdin</tt> runs <em>loop...</em> as a child process, with
+<em>variable</em>=<em>x</em> added to its environment. </li>
+ <li><tt>forstdin</tt> then exits 0.
+</ul>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-p</tt>&nbsp;: parallel mode. Do not wait for a <em>loop...</em>
+instance to finish before spawning the next one. <em>forbacktickx</em> will
+still wait for all instances of <em>loop</em> to terminate before
+exiting, though. </li>
+ <li> <tt>-0</tt>&nbsp;: accept null characters on its stdin,
+using them as delimiters. If this option and a <tt>-d</tt> option are
+used simultaneously, the rightmost one wins. </li>
+ <li> <tt>-o</tt>&nbsp;<em>okcodes</em>&nbsp;: <em>okcodes</em> must
+be a comma-separated list of exit codes. If the <tt>-p</tt> flag
+hasn't been given and <em>loop</em> exits with one of the codes in
+<em>okcodes</em>,
+forstdin will run the following instances of the loop, but if the exit code is
+not listed in <em>okcodes</em>, forstdin will exit immediately with an
+<a href="exitcodes.html">approximation</a> of the same exit code. </li>
+ <li> <tt>-x</tt>&nbsp;<em>breakcodes</em>&nbsp;: like the previous
+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> Other options are used to <a href="el_transform.html">control
+the substitution mechanism</a> for every <em>x</em>. Of course, you can't
+split <em>x</em>. </li>
+</ul>
+
+<h2> Notes </h2>
+
+<ul>
+ <li> You can start <em>loop...</em> with "import -u <em>variable</em>"
+to perform variable substitution. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/index.html b/doc/index.html
index 5b19477..bc2e020 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -66,7 +66,7 @@ library. </li>
<h3> Download </h3>
<ul>
- <li> The current released version of execline is <a href="execline-2.1.0.0.tar.gz">2.1.0.0</a>. </li>
+ <li> The current released version of execline is <a href="execline-2.1.1.0.tar.gz">2.1.1.0</a>. </li>
<li> Alternatively, you can checkout a copy of the execline git repository:
<pre> git clone git://git.skarnet.org/execline </pre> </li>
</ul>
@@ -167,6 +167,7 @@ to your installation: the shebang lines for your system might be something like
</p>
<ul>
<li><a href="forx.html">The <tt>forx</tt> program</a></li>
+<li><a href="forstdin.html">The <tt>forstdin</tt> program</a></li>
<li><a href="forbacktickx.html">The <tt>forbacktickx</tt> program</a></li>
<li><a href="loopwhilex.html">The <tt>loopwhilex</tt> program</a></li>
</ul>
diff --git a/doc/upgrade.html b/doc/upgrade.html
index b66a215..ce0e74f 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -17,6 +17,13 @@
<h1> What has changed in execline </h1>
+<h2> in 2.1.1.0 </h2>
+
+<ul>
+ <li> <a href="forstdin.html">forstdin</a> added </li>
+ <li> forbacktickx rewritten as a wrapper around pipeline and forstdin </li>
+</ul>
+
<h2> in 2.1.0.0 </h2>
<ul>
diff --git a/package/deps.mak b/package/deps.mak
index 4bf3d89..5c77ee5 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -22,6 +22,7 @@ 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/forx.o src/execline/forx.lo: src/execline/forx.c src/include/execline/config.h src/include/execline/execline.h
src/execline/getpid.o src/execline/getpid.lo: src/execline/getpid.c
src/execline/heredoc.o src/execline/heredoc.lo: src/execline/heredoc.c
@@ -46,7 +47,6 @@ 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/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_obsolescent.o src/libexecline/el_obsolescent.lo: src/libexecline/el_obsolescent.c src/include/execline/execline.h
src/libexecline/el_popenv.o src/libexecline/el_popenv.lo: src/libexecline/el_popenv.c src/include/execline/execline.h
src/libexecline/el_pushenv.o src/libexecline/el_pushenv.lo: src/libexecline/el_pushenv.c src/include/execline/execline.h
src/libexecline/el_semicolon.o src/libexecline/el_semicolon.lo: src/libexecline/el_semicolon.c src/include/execline/execline.h
@@ -103,9 +103,11 @@ fdreserve: src/execline/fdreserve.o -lskarnet
fdswap: private EXTRA_LIBS :=
fdswap: src/execline/fdswap.o -lskarnet
forbacktickx: private EXTRA_LIBS :=
-forbacktickx: src/execline/forbacktickx.o ${LIBEXECLINE} -lskarnet
+forbacktickx: src/execline/forbacktickx.o -lskarnet
foreground: private EXTRA_LIBS :=
foreground: src/execline/foreground.o ${LIBEXECLINE} -lskarnet
+forstdin: private EXTRA_LIBS :=
+forstdin: src/execline/forstdin.o ${LIBEXECLINE} -lskarnet
forx: private EXTRA_LIBS :=
forx: src/execline/forx.o ${LIBEXECLINE} -lskarnet
getpid: private EXTRA_LIBS :=
@@ -150,5 +152,5 @@ unexport: private EXTRA_LIBS :=
unexport: src/execline/unexport.o -lskarnet
wait: private EXTRA_LIBS :=
wait: src/execline/wait.o ${LIBEXECLINE} -lskarnet
-libexecline.a: src/libexecline/el_execsequence.o src/libexecline/el_getstrict.o src/libexecline/el_obsolescent.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_import.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.so: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.lo src/libexecline/el_obsolescent.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_import.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: src/libexecline/el_execsequence.o src/libexecline/el_getstrict.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_import.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.so: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.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_import.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
diff --git a/package/info b/package/info
index 54dedf4..f57cc18 100644
--- a/package/info
+++ b/package/info
@@ -1,4 +1,4 @@
package=execline
-version=2.1.0.0
+version=2.1.1.0
category=admin
package_macro_name=EXECLINE
diff --git a/package/modes b/package/modes
index 332d2c0..8519ef5 100644
--- a/package/modes
+++ b/package/modes
@@ -18,9 +18,10 @@ fdclose 0755
fdreserve 0755
fdmove 0755
fdswap 0755
-forx 0755
forbacktickx 0755
foreground 0755
+forstdin 0755
+forx 0755
getpid 0755
heredoc 0755
homeof 0755
diff --git a/package/targets.mak b/package/targets.mak
index 2b1c0f4..9601f69 100644
--- a/package/targets.mak
+++ b/package/targets.mak
@@ -19,6 +19,7 @@ fdswap \
fdreserve \
forbacktickx \
foreground \
+forstdin \
forx \
getpid \
heredoc \
diff --git a/src/execline/deps-exe/forbacktickx b/src/execline/deps-exe/forbacktickx
index 97021b5..e7187fe 100644
--- a/src/execline/deps-exe/forbacktickx
+++ b/src/execline/deps-exe/forbacktickx
@@ -1,2 +1 @@
-${LIBEXECLINE}
-lskarnet
diff --git a/src/execline/deps-exe/forstdin b/src/execline/deps-exe/forstdin
new file mode 100644
index 0000000..97021b5
--- /dev/null
+++ b/src/execline/deps-exe/forstdin
@@ -0,0 +1,2 @@
+${LIBEXECLINE}
+-lskarnet
diff --git a/src/execline/forbacktickx.c b/src/execline/forbacktickx.c
index 51f308e..0e58106 100644
--- a/src/execline/forbacktickx.c
+++ b/src/execline/forbacktickx.c
@@ -1,43 +1,23 @@
/* ISC license. */
-#include <sys/types.h>
-#include <errno.h>
-#include <skalibs/sgetopt.h>
+#include <skalibs/ushort.h>
#include <skalibs/bytestr.h>
-#include <skalibs/buffer.h>
-#include <skalibs/fmtscan.h>
+#include <skalibs/sgetopt.h>
#include <skalibs/strerr2.h>
-#include <skalibs/stralloc.h>
-#include <skalibs/genalloc.h>
-#include <skalibs/env.h>
#include <skalibs/djbunix.h>
-#include <skalibs/skamisc.h>
-#include <skalibs/netstring.h>
-#include <skalibs/ushort.h>
#include <execline/config.h>
#include <execline/execline.h>
#define USAGE "forbacktickx [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -n ] [ -C | -c ] [ -0 | -d delim ] var { backtickcmd... } command..."
#define dieusage() strerr_dieusage(100, USAGE)
-static int isok (unsigned short *tab, unsigned int n, int code)
-{
- register unsigned int i = 0 ;
- for (; i < n ; i++) if ((unsigned short)code == tab[i]) break ;
- return i < n ;
-}
+#define DELIM_DEFAULT " \n\r\t"
int main (int argc, char const **argv, char const *const *envp)
{
- genalloc pids = GENALLOC_ZERO ; /* pid_t */
- char const *delim = " \n\r\t" ;
- unsigned int delimlen = 4 ;
- char const *x ;
- pid_t pidw ;
- int fd, argc1 ;
- unsigned short okcodes[256] ;
- unsigned int nbc = 0 ;
- int crunch = 0, chomp = 0, not = 1 ;
+ char const *delim = DELIM_DEFAULT ;
+ char const *codes = 0 ;
+ int crunch = 0, chomp = 0, not = 1, par = 0 ;
PROG = "forbacktickx" ;
{
subgetopt_t l = SUBGETOPT_ZERO ;
@@ -48,100 +28,69 @@ int main (int argc, char const **argv, char const *const *envp)
switch (opt)
{
case 'e' : break ; /* compat */
- case 'p' :
- {
- if (!genalloc_ready(pid_t, &pids, 2))
- strerr_diefu1sys(111, "genalloc_ready") ;
- break ;
- }
+ case 'p' : par = 1 ; break ;
case 'n' : chomp = 1 ; break ;
case 'C' : crunch = 1 ; break ;
case 'c' : crunch = 0 ; break ;
- case '0' : delim = "" ; delimlen = 1 ; break ;
- case 'd' : delim = l.arg ; delimlen = str_len(delim) ; break ;
+ case '0' : delim = 0 ; break ;
+ case 'd' : delim = l.arg ; break ;
case 'o' :
- not = 0 ;
+ {
+ unsigned short okcodes[256] ;
+ unsigned int nbc ;
if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ;
+ codes = l.arg ;
+ not = 0 ;
break ;
+ }
case 'x' :
- not = 1 ;
+ {
+ unsigned short okcodes[256] ;
+ unsigned int nbc ;
if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ;
+ codes = l.arg ;
+ not = 1 ;
break ;
+ }
default : dieusage() ;
}
}
argc -= l.ind ; argv += l.ind ;
}
if (argc < 2) dieusage() ;
- x = argv[0] ; if (!*x) dieusage() ;
- argv++ ; argc-- ;
- argc1 = el_semicolon(argv) ;
- if (!argc1) strerr_dief1x(100, "empty block") ;
- if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ;
- argv[argc1] = 0 ;
- pidw = el_spawn1(argv[0], argv, envp, &fd, 1) ;
- if (!pidw) strerr_diefu2sys(111, "spawn ", argv[0]) ;
+ if (!argv[0][0]) dieusage() ;
+ if (!argv[1][0]) strerr_dief1x(100, "empty block") ;
{
- char buf[BUFFER_INSIZE] ;
- buffer b = BUFFER_INIT(&buffer_read, fd, buf, BUFFER_INSIZE) ;
- stralloc modif = STRALLOC_ZERO ;
- unsigned int envlen = env_len(envp) ;
- unsigned int modifstart = str_len(x)+1 ;
- char const *newenv[envlen + 2] ;
- if (!stralloc_ready(&modif, modifstart+1))
- strerr_diefu1sys(111, "stralloc_ready") ;
- byte_copy(modif.s, modifstart-1, x) ;
- modif.s[modifstart-1] = '=' ;
- for (;;)
+ unsigned int m = 0, i = 1 ;
+ char const *newargv[argc + 15] ;
+ newargv[m++] = EXECLINE_BINPREFIX "pipeline" ;
+ newargv[m++] = "--" ;
+ while (argv[i] && argv[i][0] != EXECLINE_BLOCK_END_CHAR && (!EXECLINE_BLOCK_END_CHAR || (argv[i][0] && argv[i][1])))
+ newargv[m++] = argv[i++] ;
+ if (!argv[i]) strerr_dief1x(100, "unterminated block") ;
+ newargv[m++] = "" ; i++ ;
+ newargv[m++] = EXECLINE_BINPREFIX "unexport" ;
+ newargv[m++] = "!" ;
+ newargv[m++] = EXECLINE_BINPREFIX "forstdin" ;
+ if (par) newargv[m++] = "-p" ;
+ if (chomp) newargv[m++] = "-n" ;
+ if (crunch) newargv[m++] = "-C" ;
+ if (!delim) newargv[m++] = "-0" ;
+ else if (str_diff(delim, DELIM_DEFAULT))
{
- pid_t pid ;
- modif.len = modifstart ;
- if (delimlen)
- {
- register int r = skagetlnsep(&b, &modif, delim, delimlen) ;
- if (!r) break ;
- else if (r < 0)
- {
- if (errno != EPIPE) strerr_diefu1sys(111, "skagetlnsep") ;
- if (chomp) break ;
- }
- else modif.len-- ;
- if ((modif.len == modifstart) && crunch) continue ;
- }
- else
- {
- unsigned int unread = 0 ;
- if (netstring_get(&b, &modif, &unread) <= 0)
- {
- if (netstring_okeof(&b, unread)) break ;
- else strerr_diefu1sys(111, "netstring_get") ;
- }
- }
- if (!stralloc_0(&modif)) strerr_diefu1sys(111, "stralloc_0") ;
- if (!env_merge(newenv, envlen+2, envp, envlen, modif.s, modif.len))
- strerr_diefu1sys(111, "merge environment") ;
- pid = el_spawn0(argv[argc1 + 1], argv + argc1 + 1, newenv) ;
- if (!pid) strerr_diefu2sys(111, "spawn ", argv[argc1+1]) ;
- if (pids.s)
- {
- if (!genalloc_append(pid_t, &pids, &pid))
- strerr_diefu1sys(111, "genalloc_append") ;
- }
- else
- {
- int wstat ;
- if (wait_pid(pid, &wstat) < 0)
- strerr_diefu2sys(111, "wait for ", argv[argc1 + 1]) ;
- if (not == isok(okcodes, nbc, wait_estatus(wstat)))
- return wait_estatus(wstat) ;
- }
+ newargv[m++] = "-d" ;
+ newargv[m++] = delim ;
+ }
+ if (codes)
+ {
+ newargv[m++] = not ? "-x" : "-o" ;
+ newargv[m++] = codes ;
}
- stralloc_free(&modif) ;
+ newargv[m++] = "--" ;
+ newargv[m++] = argv[0] ;
+ while (argv[i]) newargv[m++] = argv[i++] ;
+ newargv[m++] = 0 ;
+ pathexec_run(newargv[0], newargv, envp) ;
+ strerr_dieexec(111, newargv[0]) ;
}
- fd_close(fd) ;
- if (!genalloc_append(pid_t, &pids, &pidw))
- strerr_diefu1sys(111, "genalloc_append") ;
- if (!waitn(genalloc_s(pid_t, &pids), genalloc_len(pid_t, &pids)))
- strerr_diefu1sys(111, "waitn") ;
- return 0 ;
}
diff --git a/src/execline/forstdin.c b/src/execline/forstdin.c
new file mode 100644
index 0000000..1e9d5e6
--- /dev/null
+++ b/src/execline/forstdin.c
@@ -0,0 +1,157 @@
+/* ISC license. */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <skalibs/sgetopt.h>
+#include <skalibs/bytestr.h>
+#include <skalibs/buffer.h>
+#include <skalibs/fmtscan.h>
+#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 <skalibs/ushort.h>
+#include <execline/config.h>
+#include <execline/execline.h>
+
+#define USAGE "forstdin [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -n ] [ -C | -c ] [ -0 | -d delim ] var command..."
+#define dieusage() strerr_dieusage(100, USAGE)
+
+static genalloc pids = GENALLOC_ZERO ; /* pid_t */
+
+static int isok (unsigned short *tab, unsigned int n, int code)
+{
+ register unsigned int i = 0 ;
+ for (; i < n ; i++) if ((unsigned short)code == tab[i]) break ;
+ return i < n ;
+}
+
+static void parallel_sigchld_handler (int sig)
+{
+ pid_t *tab = genalloc_s(pid_t, &pids) ;
+ unsigned int len = genalloc_len(pid_t, &pids) ;
+ int wstat ;
+ for (;;)
+ {
+ register int r = wait_pids_nohang(tab, len, &wstat) ;
+ if (r <= 0) break ;
+ tab[r-1] = tab[--len] ;
+ }
+ genalloc_setlen(pid_t, &pids, len) ;
+ (void)sig ;
+}
+
+int main (int argc, char const **argv, char const *const *envp)
+{
+ char const *delim = " \n\r\t" ;
+ unsigned int delimlen = 4 ;
+ unsigned short okcodes[256] ;
+ unsigned int nbc = 0 ;
+ int crunch = 0, chomp = 0, not = 1 ;
+ PROG = "forstdin" ;
+ {
+ subgetopt_t l = SUBGETOPT_ZERO ;
+ for (;;)
+ {
+ register int opt = subgetopt_r(argc, argv, "pnCc0d:o:x:", &l) ;
+ if (opt == -1) break ;
+ switch (opt)
+ {
+ case 'p' :
+ {
+ if (!genalloc_ready(pid_t, &pids, 1))
+ strerr_diefu1sys(111, "genalloc_ready") ;
+ break ;
+ }
+ case 'n' : chomp = 1 ; break ;
+ case 'C' : crunch = 1 ; break ;
+ case 'c' : crunch = 0 ; break ;
+ case '0' : delim = "" ; delimlen = 1 ; break ;
+ case 'd' : delim = l.arg ; delimlen = str_len(delim) ; break ;
+ case 'o' :
+ not = 0 ;
+ if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ;
+ break ;
+ case 'x' :
+ not = 1 ;
+ if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ;
+ break ;
+ default : dieusage() ;
+ }
+ }
+ argc -= l.ind ; argv += l.ind ;
+ }
+ if (argc < 2) dieusage() ;
+ {
+ stralloc modif = STRALLOC_ZERO ;
+ unsigned int envlen = env_len(envp) ;
+ unsigned int modifstart = str_len(argv[0])+1 ;
+ char const *newenv[envlen + 2] ;
+ if (!stralloc_ready(&modif, modifstart+1))
+ strerr_diefu1sys(111, "stralloc_ready") ;
+ byte_copy(modif.s, modifstart-1, argv[0]) ;
+ modif.s[modifstart-1] = '=' ;
+ if (pids.s)
+ {
+ if (sig_catch(SIGCHLD, &parallel_sigchld_handler) < 0)
+ strerr_diefu2sys(111, "install", " SIGCHLD handler") ;
+ }
+ for (;;)
+ {
+ pid_t pid ;
+ modif.len = modifstart ;
+ if (delimlen)
+ {
+ register 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 ;
+ }
+ else modif.len-- ;
+ if ((modif.len == modifstart) && crunch) continue ;
+ }
+ else
+ {
+ unsigned int unread = 0 ;
+ if (netstring_get(buffer_0, &modif, &unread) <= 0)
+ {
+ if (netstring_okeof(buffer_0, unread)) break ;
+ else strerr_diefu1sys(111, "netstring_get") ;
+ }
+ }
+ if (!stralloc_0(&modif)) strerr_diefu1sys(111, "stralloc_0") ;
+ if (!env_merge(newenv, envlen+2, envp, envlen, modif.s, modif.len))
+ strerr_diefu1sys(111, "merge environment") ;
+ 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") ;
+ }
+ 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) ;
+ }
+ }
+ stralloc_free(&modif) ;
+ }
+ if (pids.s)
+ {
+ if (sig_restore(SIGCHLD) < 0)
+ strerr_diefu2sys(111, "restore", " SIGCHLD handler") ;
+ if (!waitn(genalloc_s(pid_t, &pids), genalloc_len(pid_t, &pids)))
+ strerr_diefu1sys(111, "waitn") ;
+ }
+ return 0 ;
+}
diff --git a/src/include/execline/execline.h b/src/include/execline/execline.h
index a5c16ad..1f1ec68 100644
--- a/src/include/execline/execline.h
+++ b/src/include/execline/execline.h
@@ -15,7 +15,6 @@
extern int el_vardupl (char const *, char const *, unsigned int) gccattr_pure ;
extern unsigned int el_getstrict (void) gccattr_const ;
-extern void el_obsolescent (void) ;
/* Environment shifting */
diff --git a/src/libexecline/deps-lib/execline b/src/libexecline/deps-lib/execline
index 69d483d..f3e4e49 100644
--- a/src/libexecline/deps-lib/execline
+++ b/src/libexecline/deps-lib/execline
@@ -1,6 +1,5 @@
el_execsequence.o
el_getstrict.o
-el_obsolescent.o
el_popenv.o
el_pushenv.o
el_semicolon.o
diff --git a/src/libexecline/el_obsolescent.c b/src/libexecline/el_obsolescent.c
deleted file mode 100644
index 42b8a11..0000000
--- a/src/libexecline/el_obsolescent.c
+++ /dev/null
@@ -1,10 +0,0 @@
-/* ISC license. */
-
-#include <skalibs/strerr2.h>
-#include <execline/execline.h>
-
-void el_obsolescent (void)
-{
- if (el_getstrict())
- strerr_warnw3x("this command is marked as obsolescent. Please update your script to use the ", PROG, "x command instead.") ;
-}