diff options
| -rw-r--r-- | NEWS | 3 | ||||
| -rw-r--r-- | doc/dollarsharp.html | 46 | ||||
| -rw-r--r-- | doc/index.html | 12 | ||||
| -rw-r--r-- | doc/upgrade.html | 4 | ||||
| -rw-r--r-- | doc/wait.html | 49 | ||||
| -rw-r--r-- | package/deps.mak | 5 | ||||
| -rw-r--r-- | package/modes | 1 | ||||
| -rw-r--r-- | src/execline/deps-exe/dollarsharp | 1 | ||||
| -rw-r--r-- | src/execline/dollarsharp.c | 23 | ||||
| -rw-r--r-- | src/execline/wait.c | 257 |
10 files changed, 252 insertions, 149 deletions
@@ -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> : equivalent to <tt>-t 0</tt>. Do not -pause: only reap processes that are already dead when <tt>wait</tt> -is invoked. </li> <li> <tt>-t</tt> <em>timeout</em> : 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> : 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> : 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> : wait for <em>one</em> of the listed <em>pids</em> — 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> : 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> : 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) ; } |
