aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/execline/deps-exe/dollarsharp1
-rw-r--r--src/execline/dollarsharp.c23
-rw-r--r--src/execline/wait.c257
3 files changed, 151 insertions, 130 deletions
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) ;
}