aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--doc/dollarsharp.html46
-rw-r--r--doc/index.html12
-rw-r--r--doc/upgrade.html4
-rw-r--r--doc/wait.html49
-rw-r--r--package/deps.mak5
-rw-r--r--package/modes1
-rw-r--r--src/execline/deps-exe/dollarsharp1
-rw-r--r--src/execline/dollarsharp.c23
-rw-r--r--src/execline/wait.c257
10 files changed, 252 insertions, 149 deletions
diff --git a/NEWS b/NEWS
index a69510f..a30deb9 100644
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,9 @@ In 2.10.0.0
- execline-umask and posix-cd removed.
- loopwhilex -n option removed.
- loopwhilex -x "" now loops forever.
+ - wait has been rewritten, its options and behaviour have changed a bit.
+In particular, it does not reap unlisted zombies anymore (that was the
+point of the rewrite).
In 2.9.9.2
diff --git a/doc/dollarsharp.html b/doc/dollarsharp.html
new file mode 100644
index 0000000..4643775
--- /dev/null
+++ b/doc/dollarsharp.html
@@ -0,0 +1,46 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta name="color-scheme" content="dark light" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>execline: the dollarsharp command</title>
+ <meta name="Description" content="execline: the dollarsharp command" />
+ <meta name="Keywords" content="execline command dollarsharp" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+</head>
+<body>
+
+<p>
+<a href="index.html">execline</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>dollarsharp</tt> program </h1>
+
+<p>
+<tt>dollarsharp</tt> prints the number of arguments it is called with.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ dollarsharp [ args ]
+</pre>
+
+<ul>
+ <li> <tt>dollarsharp</tt> reads the number of arguments it is given,
+then prints this number on stdout. </li>
+ <li> It then exits 0. </li>
+
+<h2> Notes </h2>
+
+<ul>
+ <li> A use case for <tt>dollarsharp</tt> is e.g. after calling an
+<a href="elglob.html"><tt>elglob -0</tt></a> command, to check how
+many results the globbing returned. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/index.html b/doc/index.html
index 075fcf9..3ed48b7 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -194,6 +194,7 @@ the previous versions of execline and the current one. </li>
<li><a href="elgetopt.html">The <tt>elgetopt</tt> program</a></li>
<li><a href="shift.html">The <tt>shift</tt> program</a></li>
<li><a href="dollarat.html">The <tt>dollarat</tt> program</a></li>
+<li><a href="dollarsharp.html">The <tt>dollarsharp</tt> program</a></li>
</ul>
<p>
(Miscellaneous)
@@ -252,5 +253,16 @@ the execline documentation as a
<a href="//skarnet.org/lists/#skaware">skaware</a> mailing-list. </li>
</ul>
+<h2> Support this work </h2>
+
+<p>
+ If you like this skarnet.org project, you can donate to the author via Liberapay,
+by clicking the following button:
+<script src="https://liberapay.com/skarnet/widgets/button.js"></script>
+<noscript>
+<a href="https://liberapay.com/skarnet/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a>
+</noscript>
+</p>
+
</body>
</html>
diff --git a/doc/upgrade.html b/doc/upgrade.html
index 31de4b9..de3fbf4 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -27,6 +27,10 @@ been removed, due to POSIX relaxing requirements on intrinsic utilities. </li>
<li> The <a href="cd.html">cd</a> binary is now what was previously <tt>execline-cd</tt>. </li>
<li> The <a href="umask.html">umask</a> binary is now what was previously <tt>posix-umask</tt>,
(without locale support, not that it had much to start with) </li>
+ <li> <a href="loopwhilex"><tt>loopwhilex -x ""</tt></a> now loops forever. The <tt>-n</tt>
+option has been removed. </li>
+ <li> <a href="wait.html"><tt>wait</tt></a> has slightly different options. When given a
+non-empty list of pids, it <em>only</em> waits for these pids and doesn't touch the others. </li>
</ul>
<h2> in 2.9.9.2 </h2>
diff --git a/doc/wait.html b/doc/wait.html
index 44197a0..d38b06a 100644
--- a/doc/wait.html
+++ b/doc/wait.html
@@ -30,7 +30,7 @@
</p>
<pre>
- wait [ -I | -i ] [ -a | -o ] [ -r | -t <em>timeout</em> ] { [ <em>pids...</em> ] } <em>prog...</em>
+ wait [ -a | -o ] [ -u ] [ -t <em>timeout</em> ] { [ <em>pids...</em> ] } <em>prog...</em>
</pre>
<ul>
@@ -40,36 +40,49 @@ and unquotes it. </li>
<li> <tt>wait</tt> waits for every child whose pid is
listed in <em>pids...</em>. If <em>pids...</em> is an
empty list, it waits for every child process it has. </li>
- <li><tt>wait</tt> then execs into <em>prog...</em>. </li>
+ <li> <tt>wait</tt> then execs into <em>prog...</em>. </li>
</ul>
<h2> Options </h2>
<ul>
- <li> <tt>-r</tt>&nbsp;: equivalent to <tt>-t&nbsp;0</tt>. Do not
-pause: only reap processes that are already dead when <tt>wait</tt>
-is invoked. </li>
<li> <tt>-t</tt>&nbsp;<em>timeout</em>&nbsp;: wait for a maximum
of <em>timeout</em> milliseconds. If there still are living processes
among <em>pids...</em> (or among <tt>wait</tt>'s children if
<em>pids...</em> is an empty list), after <em>timeout</em>
-milliseconds, they will not be reaped. </li>
- <li> <tt>-I</tt>&nbsp;: loose. If <tt>wait</tt> times out while
-waiting for children to die, it will still
-exec into <em>prog...</em>. This is the default. </li>
- <li> <tt>-i</tt>&nbsp;: strict. If <tt>wait</tt> times out, it
-will print an error message and exit 99. </li>
+milliseconds, they will not be waited for. In particular, <tt>-t0</tt>
+tells <tt>wait</tt> to perform a single reaping pass on current zombies
+and immediately exec into <em>prog...</em>. </li>
<li> <tt>-o</tt>&nbsp;: wait for <em>one</em> of the listed
<em>pids</em> &mdash; exec into <em>prog</em> as soon as one of the
listed children dies. (If no pid is listed, wait for one child to die.)
-The <tt>!</tt> environment variable will be set to the
-pid that died, and the <tt>?</tt> environment variable will contain an
-<a href="exitcodes.html">approximation</a> of its exit code. If no
-listed child has died before <tt>wait</tt> has to exec (either because
-it timed out or it has no suitable children left), the <tt>?</tt> and
-<tt>!</tt> environment variables are unset. </li>
<li> <tt>-a</tt>&nbsp;: wait for <em>all</em> of the listed <em>pids</em>.
-Do not touch the <tt>!</tt> or <tt>?</tt> variables. This is the default. </li>
+This is the default. </li>
+ <li> <tt>-u</tt>&nbsp;: do not export the result in the environment,
+even if <tt>wait</tt> succeeds. </li>
+</ul>
+
+<h2> Environment variables </h2>
+
+<p>
+ If the <tt>-u</tt> option has been given, <tt>wait</tt> execs into <em>prog...</em>
+with the <tt>!</tt> and <tt>?</tt> environment variables unset. Same thing if an
+error occurred before <tt>wait</tt> could successfully reap a zombie.
+</p>
+
+<p>
+ Otherwise, the <tt>!</tt> environment variable is set to the pid of a reapt zombie,
+and the <tt>?</tt> environment variable is set to its exit code. Here is how <tt>wait</tt>
+decides what pid to report:
+</p>
+
+<ul>
+ <li> If the <tt>-o</tt> option has been given, <tt>!</tt> is set to the pid of <em>the<em>
+one zombie that has just been reapt. </li>
+ <li> Otherwise, if <tt>wait</tt> has been given an empty list of pids (meaning it should
+wait for all of its children), then <tt>!</tt> is set to the pid of the last child it has
+waited for. If there were no children, <tt>!</tt> and <tt>?</tt> are unset. </li>
+ <li> Otherwise, <tt>!</tt> is set to the <em>last</em> pid in the list provided to <tt>wait</tt>. </li>
</ul>
<h2> Notes </h2>
diff --git a/package/deps.mak b/package/deps.mak
index d03a1d8..b37a626 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -8,6 +8,7 @@ src/execline/case.o src/execline/case.lo: src/execline/case.c src/include/execli
src/execline/cd.o src/execline/cd.lo: src/execline/cd.c
src/execline/define.o src/execline/define.lo: src/execline/define.c src/include-local/exlsn.h
src/execline/dollarat.o src/execline/dollarat.lo: src/execline/dollarat.c
+src/execline/dollarsharp.o src/execline/dollarsharp.lo: src/execline/dollarsharp.c
src/execline/elgetopt.o src/execline/elgetopt.lo: src/execline/elgetopt.c src/include/execline/execline.h
src/execline/elgetpositionals.o src/execline/elgetpositionals.lo: src/execline/elgetpositionals.c src/include-local/exlsn.h
src/execline/elglob.o src/execline/elglob.lo: src/execline/elglob.c src/include-local/exlsn.h
@@ -49,7 +50,7 @@ src/execline/trap.o src/execline/trap.lo: src/execline/trap.c src/include/execli
src/execline/tryexec.o src/execline/tryexec.lo: src/execline/tryexec.c src/include/execline/execline.h
src/execline/umask.o src/execline/umask.lo: src/execline/umask.c
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/config.h src/include/execline/execline.h
+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/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_forx_pidinfo.o src/libexecline/el_forx_pidinfo.lo: src/libexecline/el_forx_pidinfo.c src/include/execline/execline.h
@@ -93,6 +94,8 @@ define: EXTRA_LIBS :=
define: src/execline/define.o ${LIBEXECLINE} -lskarnet
dollarat: EXTRA_LIBS :=
dollarat: src/execline/dollarat.o -lskarnet
+dollarsharp: EXTRA_LIBS :=
+dollarsharp: src/execline/dollarsharp.o -lskarnet
elgetopt: EXTRA_LIBS :=
elgetopt: src/execline/elgetopt.o ${LIBEXECLINE} -lskarnet
elgetpositionals: EXTRA_LIBS :=
diff --git a/package/modes b/package/modes
index 025602e..6e7c23f 100644
--- a/package/modes
+++ b/package/modes
@@ -4,6 +4,7 @@ case 0755
cd 0755
define 0755
dollarat 0755
+dollarsharp 0755
elgetopt 0755
elgetpositionals 0755
elglob 0755
diff --git a/src/execline/deps-exe/dollarsharp b/src/execline/deps-exe/dollarsharp
new file mode 100644
index 0000000..e7187fe
--- /dev/null
+++ b/src/execline/deps-exe/dollarsharp
@@ -0,0 +1 @@
+-lskarnet
diff --git a/src/execline/dollarsharp.c b/src/execline/dollarsharp.c
new file mode 100644
index 0000000..b382061
--- /dev/null
+++ b/src/execline/dollarsharp.c
@@ -0,0 +1,23 @@
+/* ISC license. */
+
+#include <unistd.h>
+
+#include <skalibs/types.h>
+#include <skalibs/buffer.h>
+#include <skalibs/prog.h>
+#include <skalibs/strerr.h>
+
+#define USAGE "dollarsharp [ args ]"
+
+int main (int argc, char const *const *argv)
+{
+ size_t len ;
+ char fmt[UINT_FMT] ;
+ PROG = "dollarsharp" ;
+ if (argc-- <= 0) strerr_dieusage(100, USAGE) ;
+ len = uint_fmt(fmt, argc) ;
+ fmt[len++] = '\n' ;
+ if (buffer_putflush(buffer_1small, fmt, len) == -1)
+ strerr_diefu1sys(111, "write to stdout") ;
+ _exit(0) ;
+}
diff --git a/src/execline/wait.c b/src/execline/wait.c
index d320d54..2715344 100644
--- a/src/execline/wait.c
+++ b/src/execline/wait.c
@@ -1,10 +1,10 @@
/* ISC license. */
#include <unistd.h>
-
#include <sys/wait.h>
#include <errno.h>
+#include <skalibs/uint64.h>
#include <skalibs/types.h>
#include <skalibs/envexec.h>
#include <skalibs/tai.h>
@@ -12,167 +12,167 @@
#include <skalibs/selfpipe.h>
#include <skalibs/iopause.h>
-#include <execline/config.h>
#include <execline/execline.h>
-#define USAGE "wait [ -I | -i ] [ -a | -o ] [ -r | -t timeout ] { pids... } [ prog... ]"
+#define USAGE "wait [ -u ] [ -a | -o ] [ -t timeout ] { [ pids... ] } [ prog... ]"
#define dieusage() strerr_dieusage(100, USAGE)
-typedef int ac_func (pid_t *, unsigned int *, int *) ;
-typedef ac_func *ac_func_ref ;
+typedef pid_t wait_ac_func (void *, int *) ;
+typedef wait_ac_func *wait_ac_func_ref ;
-static int wait_all (void)
+enum wait_golb_e
{
- errno = 0 ;
- while (wait_nointr(0) > 0) ;
- if (errno != ECHILD) strerr_diefu1sys(111, "wait") ;
- return 0 ;
-}
+ WAIT_GOLB_JUSTONE = 0x01,
+ WAIT_GOLB_NOEXPORT = 0x02,
+} ;
-static int wait_from_list (pid_t *pids, unsigned int n)
+enum wait_gola_e
{
- int wstat = -1 ;
- if (!waitn_posix(pids, n, &wstat) && errno != ECHILD)
- strerr_diefu1sys(111, "wait") ;
- return wstat == -1 ? -1 : wait_estatus(wstat) ;
-}
+ WAIT_GOLA_TIMEOUT,
+ WAIT_GOLA_N
+} ;
-static int wait_one (pid_t *pid)
+struct wait_pidlist_s
{
- int wstat = 0 ;
- *pid = wait(&wstat) ;
- if (*pid == -1)
- {
- if (errno != ECHILD) strerr_diefu1sys(111, "wait") ;
- else return -1 ;
- }
- return wait_estatus(wstat) ;
-}
+ pid_t *pids ;
+ size_t n ;
+ pid_t last ;
+ int lastwstat ;
+} ;
-static int wait_one_from_list (pid_t *pids, unsigned int n, pid_t *pid)
+static inline pid_t wait_hang_nolist_all (int *wstat)
{
+ pid_t pid = -1 ;
+ int w ;
for (;;)
{
- int wstat ;
- pid_t r = wait(&wstat) ;
- unsigned int i = 0 ;
- if (r == -1)
- {
- if (errno != ECHILD) strerr_diefu1sys(111, "wait") ;
- else return -1 ;
- }
- for (; i < n ; i++) if (r == pids[i]) break ;
- if (i < n)
- {
- *pid = r ;
- pids[i] = pids[n-1] ;
- return wait_estatus(wstat) ;
- }
+ pid_t r = wait_nointr(&w) ;
+ if (r == -1) break ;
+ pid = r ;
}
+ if (errno != ECHILD) strerr_diefusys(111, "wait") ;
+ if (pid > 0) *wstat = w ;
+ return pid ;
}
-static int wait_one_nohang (pid_t *pids, unsigned int *n, int *wstat)
+static pid_t wait_nohang_nolist_one (void *data, int *wstat)
{
pid_t r = wait_nohang(wstat) ;
- if (r == -1 && errno != ECHILD) strerr_diefu1sys(111, "wait") ;
- (void)pids ;
- (void)n ;
+ if (r == -1 && errno != ECHILD)
+ strerr_diefusys(111, "wait_nohang") ;
+ (void)data ;
return r ;
}
-static int wait_one_from_list_nohang (pid_t *pids, unsigned int *n, int *wstat)
+static pid_t wait_nohang_nolist_all (void *data, int *wstat)
{
+ pid_t *last = data ;
for (;;)
{
pid_t r = wait_nohang(wstat) ;
- unsigned int i = 0 ;
- if (r <= 0)
+ if (r == -1) break ;
+ else if (!r) return 0 ;
+ else *last = r ;
+ }
+ if (errno != ECHILD) strerr_diefusys(111, "wait_nohang") ;
+ return *last ;
+}
+
+static pid_t wait_nohang_list_one (void *data, int *wstat)
+{
+ struct wait_pidlist_s *p = data ;
+ while (p->n)
+ {
+ size_t i ;
+ int r = waitpids_nohang(p->pids, p->n, wstat, &i) ;
+ if (!r) return 0 ;
+ else if (r == -1)
+ {
+ char fmt[PID_FMT] ;
+ fmt[pid_fmt(fmt, p->pids[i])] = 0 ;
+ if (errno != ECHILD) strerr_diefusys(111, "wait for pid", fmt) ;
+ strerr_warnwusys("wait for pid ", fmt) ;
+ p->pids[i] = p->pids[--p->n] ;
+ }
+ else return p->pids[i] ;
+ }
+ return -1 ;
+}
+
+static pid_t wait_nohang_list_all (void *data, int *wstat)
+{
+ struct wait_pidlist_s *p = data ;
+ while (p->n)
+ {
+ size_t i ;
+ int w ;
+ int r = waitpids_nohang(p->pids, p->n, &w, &i) ;
+ if (!r) return 0 ;
+ else if (r == -1)
{
- if (r == -1 && errno != ECHILD) strerr_diefu1sys(111, "wait") ;
- else return r ;
+ char fmt[PID_FMT] ;
+ fmt[pid_fmt(fmt, p->pids[i])] = 0 ;
+ if (errno != ECHILD) strerr_diefusys(111, "wait for pid ", fmt) ;
+ else strerr_warnwusys("wait for pid ", fmt) ;
}
- for (; i < *n ; i++) if (r == pids[i]) break ;
- if (i < *n)
+ if (p->pids[i] == p->last)
{
- pids[i] = pids[--*n] ;
- return r ;
+ if (r == -1) p->last = 0 ;
+ else p->lastwstat = w ;
}
+ p->pids[i] = p->pids[--p->n] ;
}
+ *wstat = p->lastwstat ;
+ return p->last ;
}
-static inline void empty_selfpipe (void)
+static inline void wait_empty_selfpipe (void)
{
for (;;) switch (selfpipe_read())
{
case -1 : strerr_diefu1sys(111, "read selfpipe") ;
case 0 : return ;
case SIGCHLD : break ;
- default: strerr_dief1x(101, "internal inconsistency. Please submit a bug-report.") ;
+ default: strerr_dief(101, "internal inconsistency. Please submit a bug-report.") ;
}
}
-static int wait_with_timeout (pid_t *pids, unsigned int n, pid_t *returned, ac_func_ref f, tain *tto, int justone, int strict)
+static pid_t wait_with_timeout (wait_ac_func_ref f, void *data, int *wstat, tain *tto)
{
+ pid_t pid ;
iopause_fd x = { .fd = selfpipe_init(), .events = IOPAUSE_READ } ;
- pid_t special = pids[n-1] ;
- int e = special ? -1 : 0 ;
- if (x.fd == -1) strerr_diefu1sys(111, "create selfpipe") ;
- if (!selfpipe_trap(SIGCHLD)) strerr_diefu1sys(111, "trap SIGCHLD") ;
+ if (x.fd == -1) strerr_diefusys(111, "create selfpipe") ;
+ if (!selfpipe_trap(SIGCHLD)) strerr_diefusys(111, "trap SIGCHLD") ;
tain_now_set_stopwatch_g() ;
tain_add_g(tto, tto) ;
+
for (;;)
{
int r ;
- for (;;)
- {
- int wstat ;
- pid_t pid = (*f)(pids, &n, &wstat) ;
- if (!pid) break ;
- if (pid < 0) goto endloop ;
- if (justone || pid == special)
- {
- *returned = pid ;
- e = wait_estatus(wstat) ;
- }
- if (justone || !n) goto endloop ;
- }
+ pid = (*f)(data, wstat) ;
+ if (pid) break ;
r = iopause_g(&x, 1, tto) ;
- if (r == -1) strerr_diefu1sys(111, "iopause") ;
+ if (r == -1) strerr_diefusys(111, "iopause") ;
else if (!r)
{
- if (!strict) { e = -1 ; break ; }
- errno = ETIMEDOUT ;
- strerr_diefu1sys(99, "wait") ;
+ pid = -1 ;
+ break ;
}
- else empty_selfpipe() ;
+ else wait_empty_selfpipe() ;
}
- endloop:
+
selfpipe_finish() ;
- return e ;
+ return pid ;
}
-enum wait_golb_e
-{
- WAIT_GOLB_INSIST = 0x01,
- WAIT_GOLB_JUSTONE = 0x02,
- WAIT_GOLB_REAP = 0x04,
-} ;
-
-enum wait_gola_e
-{
- WAIT_GOLA_TIMEOUT,
- WAIT_GOLA_N
-} ;
-
int main (int argc, char const **argv)
{
static gol_bool const rgolb[] =
{
- { .so = 'I', .lo = "no-insist", .clear = WAIT_GOLB_INSIST, .set = 0 },
- { .so = 'i', .lo = "insist", .clear = 0, .set = WAIT_GOLB_INSIST },
{ .so = 'a', .lo = "all", .clear = WAIT_GOLB_JUSTONE, .set = 0 },
{ .so = 'o', .lo = "one", .clear = 0, .set = WAIT_GOLB_JUSTONE },
- { .so = 'r', .lo = "reap", .clear = 0, .set = WAIT_GOLB_REAP },
+ { .so = 0, .lo = "export", .clear = WAIT_GOLB_NOEXPORT, .set = 0 },
+ { .so = 'u', .lo = "no-export", .clear = 0, .set = WAIT_GOLB_NOEXPORT },
} ;
static gol_arg const rgola[] =
{
@@ -180,17 +180,18 @@ int main (int argc, char const **argv)
} ;
tain tto = TAIN_INFINITE_RELATIVE ;
int argc1 ;
- int hasblock = 1 ;
- int e ;
+ int posixcompat = 0 ;
+ pid_t pid ;
+ int wstat ;
uint64_t wgolb = 0 ;
char const *wgola[WAIT_GOLA_N] = { 0 } ;
- unsigned int golc ;
- pid_t pid = -1 ;
PROG = "wait" ;
- golc = GOL_main(argc, argv, rgolb, rgola, &wgolb, wgola) ;
- argc -= golc ; argv += golc ;
- if (wgolb & WAIT_GOLB_REAP) wgola[WAIT_GOLA_TIMEOUT] = "0" ;
+ {
+ unsigned int golc = GOL_main(argc, argv, rgolb, rgola, &wgolb, wgola) ;
+ argc -= golc ; argv += golc ;
+ }
+
if (wgola[WAIT_GOLA_TIMEOUT])
{
unsigned int t = 0 ;
@@ -201,41 +202,37 @@ int main (int argc, char const **argv)
argc1 = el_semicolon_nostrict(argv) ;
if (argc1 > argc)
{
- hasblock = 0 ;
+ posixcompat = 1 ;
argc1 = argc ;
}
+ if (argc1)
{
- unsigned int n = argc1 ? argc1 : 1 ;
- pid_t pids[n] ;
- if (argc1)
- {
- unsigned int i = 0 ;
- for (; i < n ; i++)
- if (!pid0_scan(argv[i], pids + i)) strerr_dieusage(100, USAGE) ;
- }
- else pids[0] = 0 ;
-
- e = wgola[WAIT_GOLA_TIMEOUT] ? /* wait -t30000 whatever */
- wait_with_timeout(pids, n, &pid, argc1 ? &wait_one_from_list_nohang : &wait_one_nohang, &tto, !!(wgolb & WAIT_GOLB_JUSTONE), !!(wgolb & WAIT_GOLB_INSIST)) :
- wgolb & WAIT_GOLB_JUSTONE ?
- argc1 ?
- wait_one_from_list(pids, n, &pid) : /* wait -o -- 2 3 4 / wait -o -- { 2 3 4 } */
- wait_one(&pid) : /* wait -o / wait -o { } */
- argc1 ?
- wait_from_list(pids, n) : /* wait 2 3 4 / wait { 2 3 4 }*/
- wait_all() ; /* wait / wait { } */
+ pid_t pids[argc1] ;
+ struct wait_pidlist_s info = { .pids = pids, .n = argc1 } ;
+ for (unsigned int i = 0 ; i < argc1 ; i++)
+ if (!pid0_scan(argv[i], pids + i))
+ strerr_dief(100, "pids must be numerical") ;
+ info.last = pids[argc1 - 1] ;
+ pid = wait_with_timeout(wgolb & WAIT_GOLB_JUSTONE ? &wait_nohang_list_one : &wait_nohang_list_all, &info, &wstat, &tto) ;
}
- if (!hasblock) _exit(e >= 0 ? e : 127) ;
- if (!(wgolb & WAIT_GOLB_JUSTONE)) xexec0(argv + argc1 + 1) ;
- if (e == -1) xmexec0_n(argv + argc1 + 1, "?\0!", 4, 2) ;
+ else if (wgola[WAIT_GOLA_TIMEOUT])
+ {
+ pid_t saved = -1 ;
+ pid = wait_with_timeout(wgolb & WAIT_GOLB_JUSTONE ? &wait_nohang_nolist_one : &wait_nohang_nolist_all, &saved, &wstat, &tto) ;
+ }
+ else pid = wgolb & WAIT_GOLB_JUSTONE ? wait_nointr(&wstat) : wait_hang_nolist_all(&wstat) ;
+
+ if (posixcompat) _exit(pid == -1 ? 1 : argc1 ? wait_estatus(wstat) : 0) ;
+ if (pid > 0 && !(wgolb & WAIT_GOLB_NOEXPORT))
{
char fmt[4 + UINT_FMT + PID_FMT] = "?=" ;
size_t m = 2 ;
- m += uint_fmt(fmt + m, (unsigned int)e) ; fmt[m++] = 0 ;
+ m += uint_fmt(fmt + m, wait_estatus(wstat)) ; fmt[m++] = 0 ;
fmt[m++] = '!' ; fmt[m++] = '=' ;
m += pid_fmt(fmt + m, pid) ; fmt[m++] = 0 ;
xmexec0_n(argv + argc1 + 1, fmt, m, 2) ;
}
+ else xmexec0_n(argv + argc1 + 1, "?\0!", 4, 2) ;
}