diff options
| author | Laurent Bercot <ska-skaware@skarnet.org> | 2026-03-09 19:03:37 +0000 |
|---|---|---|
| committer | Laurent Bercot <ska-skaware@skarnet.org> | 2026-03-09 19:03:37 +0000 |
| commit | 6c756905574a019df52ad865a81cf97b6e2b6c58 (patch) | |
| tree | 54bb9ff91422a6de7606c1a9be6c29e080d7d994 /src | |
| parent | 26fa9d9d3fef9684e9e4d5cd0bcd4336fee8d749 (diff) | |
| download | execline-6c756905574a019df52ad865a81cf97b6e2b6c58.tar.gz | |
Fix wait command interaction with EXECLINE_STRICT
el_semicolon() hardcodes failure on EXECLINE_STRICT=2, but we
want to accept a no-block interface for wait, so write a separate
el_semicolon_nostrict() function and use it in wait.
Also use gol in wait, and prepare deprecation of quote chars
other than space and null (we can hardcode this np)
Diffstat (limited to 'src')
| -rw-r--r-- | src/execline/wait.c | 79 | ||||
| -rw-r--r-- | src/include/execline/execline.h | 1 | ||||
| -rw-r--r-- | src/libexecline/deps-lib/execline | 1 | ||||
| -rw-r--r-- | src/libexecline/el_semicolon.c | 36 | ||||
| -rw-r--r-- | src/libexecline/el_semicolon_nostrict.c | 14 |
5 files changed, 77 insertions, 54 deletions
diff --git a/src/execline/wait.c b/src/execline/wait.c index 5b9b93d..d30ae68 100644 --- a/src/execline/wait.c +++ b/src/execline/wait.c @@ -9,13 +9,11 @@ #endif #include <skalibs/types.h> -#include <skalibs/sgetopt.h> -#include <skalibs/strerr.h> +#include <skalibs/envexec.h> #include <skalibs/tai.h> #include <skalibs/djbunix.h> #include <skalibs/selfpipe.h> #include <skalibs/iopause.h> -#include <skalibs/exec.h> #include <execline/execline.h> @@ -155,49 +153,62 @@ static int wait_with_timeout (pid_t *pids, unsigned int n, pid_t *returned, ac_f return e ; } +enum wait_golb_e +{ + GOLB_INSIST = 0x01, + GOLB_JUSTONE = 0x02, + GOLB_REAP = 0x04, +} ; + +enum wait_gola_e +{ + GOLA_TIMEOUT, + GOLA_N +} ; + int main (int argc, char const **argv) { - tain tto ; + static gol_bool const rgolb[] = + { + { .so = 'I', .lo = "no-insist", .clear = GOLB_INSIST, .set = 0 }, + { .so = 'i', .lo = "insist", .clear = 0, .set = GOLB_INSIST }, + { .so = 'a', .lo = "all", .clear = GOLB_JUSTONE, .set = 0 }, + { .so = 'o', .lo = "one", .clear = 0, .set = GOLB_JUSTONE }, + { .so = 'r', .lo = "reap", .clear = 0, .set = GOLB_REAP }, + } ; + static gol_arg const rgola[] = + { + { .so = 't', .lo = "timeout", .i = GOLA_TIMEOUT }, + } ; + tain tto = TAIN_INFINITE_RELATIVE ; int argc1 ; - int hastimeout = 0 ; - int insist = 0 ; - int justone = 0 ; - int hasblock ; + int hasblock = 1 ; int e ; + uint64_t wgolb = 0 ; + char const *wgola[GOLA_N] = { 0 } ; + unsigned int golc ; pid_t pid = -1 ; PROG = "wait" ; #ifdef EXECLINE_PEDANTIC_POSIX setlocale(LC_ALL, "") ; /* but of course, dear POSIX */ #endif + golc = GOL_main(argc, argv, rgolb, rgola, &wgolb, wgola) ; + argc -= golc ; argv += golc ; + + if (wgolb & GOLB_REAP) wgola[GOLA_TIMEOUT] = "0" ; + if (wgola[GOLA_TIMEOUT]) { - subgetopt l = SUBGETOPT_ZERO ; unsigned int t = 0 ; - for (;;) - { - int opt = subgetopt_r(argc, argv, "iIaort:", &l) ; - if (opt == -1) break ; - switch (opt) - { - case 'i' : insist = 1 ; break ; - case 'I' : insist = 0 ; break ; - case 'a' : justone = 0 ; break ; - case 'o' : justone = 1 ; break ; - case 'r' : t = 0 ; hastimeout = 1 ; break ; - case 't' : if (!uint0_scan(l.arg, &t)) dieusage() ; hastimeout = 1 ; break ; - default : dieusage() ; - } - } - argc -= l.ind ; argv += l.ind ; - if (hastimeout) tain_from_millisecs(&tto, t) ; - else tto = tain_infinite_relative ; + if (!uint0_scan(wgola[GOLA_TIMEOUT], &t)) dieusage() ; + tain_from_millisecs(&tto, t) ; } - argc1 = el_semicolon(argv) ; - if (argc1 >= argc) + + argc1 = el_semicolon_nostrict(argv) ; + if (argc1 > argc) { hasblock = 0 ; argc1 = argc ; } - else hasblock = 1 ; { unsigned int n = argc1 ? argc1 : 1 ; @@ -210,9 +221,9 @@ int main (int argc, char const **argv) } else pids[0] = 0 ; - e = hastimeout ? /* wait -t30000 whatever */ - wait_with_timeout(pids, n, &pid, argc1 ? &wait_one_from_list_nohang : &wait_one_nohang, &tto, justone, insist) : - justone ? + e = wgola[GOLA_TIMEOUT] ? /* wait -t30000 whatever */ + wait_with_timeout(pids, n, &pid, argc1 ? &wait_one_from_list_nohang : &wait_one_nohang, &tto, !!(wgolb & GOLB_JUSTONE), !!(wgolb & GOLB_INSIST)) : + wgolb & 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 { } */ @@ -221,7 +232,7 @@ int main (int argc, char const **argv) wait_all() ; /* wait / wait { } */ } if (!hasblock) return e >= 0 ? e : 127 ; - if (!justone) xexec0(argv + argc1 + 1) ; + if (!(wgolb & GOLB_JUSTONE)) xexec0(argv + argc1 + 1) ; if (e < 0) xmexec0_n(argv + argc1 + 1, "?\0!", 4, 2) ; { diff --git a/src/include/execline/execline.h b/src/include/execline/execline.h index 7fdef51..498dbbc 100644 --- a/src/include/execline/execline.h +++ b/src/include/execline/execline.h @@ -47,6 +47,7 @@ extern void el_execsequence (char const *const *, char const *const *, char cons /* Block unquoting */ extern int el_semicolon (char const **) ; +extern unsigned int el_semicolon_nostrict (char const **) ; /* Value transformation */ diff --git a/src/libexecline/deps-lib/execline b/src/libexecline/deps-lib/execline index d5888c0..86dabd2 100644 --- a/src/libexecline/deps-lib/execline +++ b/src/libexecline/deps-lib/execline @@ -10,6 +10,7 @@ el_parse_from_string.o el_popenv.o el_pushenv.o el_semicolon.o +el_semicolon_nostrict.o el_spawn0.o el_gspawn0.o el_substandrun.o diff --git a/src/libexecline/el_semicolon.c b/src/libexecline/el_semicolon.c index 735fe9a..dc6b938 100644 --- a/src/libexecline/el_semicolon.c +++ b/src/libexecline/el_semicolon.c @@ -1,35 +1,31 @@ /* ISC license. */ -#include <skalibs/env.h> #include <skalibs/strerr.h> #include <skalibs/types.h> + #include <execline/execline.h> int el_semicolon (char const **argv) { static unsigned int nblock = 0 ; - int argc1 = 0 ; + unsigned int strict = el_getstrict() ; nblock++ ; - for (;; argc1++, argv++) + unsigned int i = 0 ; + for (; argv[i] ; i++) { - char const *arg = *argv ; - if (!arg) return argc1 + 1 ; - if ((arg[0] == EXECLINE_BLOCK_END_CHAR) && (!EXECLINE_BLOCK_END_CHAR || !arg[1])) return argc1 ; - else if (arg[0] == EXECLINE_BLOCK_QUOTE_CHAR) ++*argv ; - else + if (!argv[i][0]) return i ; + else if (argv[i][0] == ' ') argv[i]++ ; + else if (strict) { - unsigned int strict = el_getstrict() ; - if (strict) - { - char fmt1[UINT_FMT] ; - char fmt2[UINT_FMT] ; - fmt1[uint_fmt(fmt1, nblock)] = 0 ; - fmt2[uint_fmt(fmt2, (unsigned int)argc1)] = 0 ; - if (strict >= 2) - strerr_dief6x(100, "unquoted argument ", arg, " at block ", fmt1, " position ", fmt2) ; - else - strerr_warnw6x("unquoted argument ", arg, " at block ", fmt1, " position ", fmt2) ; - } + char fmt1[UINT_FMT] ; + char fmt2[UINT_FMT] ; + fmt1[uint_fmt(fmt1, nblock)] = 0 ; + fmt2[uint_fmt(fmt2, i)] = 0 ; + if (strict >= 2) + strerr_dief6x(100, "unquoted argument ", argv[i], " at block ", fmt1, " position ", fmt2) ; + else + strerr_warnw6x("unquoted argument ", argv[i], " at block ", fmt1, " position ", fmt2) ; } } + return i + 1 ; } diff --git a/src/libexecline/el_semicolon_nostrict.c b/src/libexecline/el_semicolon_nostrict.c new file mode 100644 index 0000000..8fb770c --- /dev/null +++ b/src/libexecline/el_semicolon_nostrict.c @@ -0,0 +1,14 @@ +/* ISC license. */ + +#include <execline/execline.h> + +unsigned int el_semicolon_nostrict (char const **argv) +{ + unsigned int i = 0 ; + for (; argv[i] ; i++) + { + if (!argv[i][0]) return i ; + else if (argv[i][0] == ' ') argv[i]++ ; + } + return i + 1 ; +} |
