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 | |
| 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)
| -rw-r--r-- | AUTHORS | 1 | ||||
| -rw-r--r-- | package/deps.mak | 9 | ||||
| -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 |
7 files changed, 83 insertions, 58 deletions
@@ -35,3 +35,4 @@ Thanks to: Michael Zuo <muh.muhten@gmail.com> Casper Ti. Vector <caspervector@gmail.com> Johannes Nixdorf <mixi@shadowice.org> + Alyssa Ross <hi@alyssa.is> diff --git a/package/deps.mak b/package/deps.mak index dca197b..a1ef3ab 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -66,6 +66,7 @@ src/libexecline/el_parse_from_string.o src/libexecline/el_parse_from_string.lo: 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 +src/libexecline/el_semicolon_nostrict.o src/libexecline/el_semicolon_nostrict.lo: src/libexecline/el_semicolon_nostrict.c src/include/execline/execline.h src/libexecline/el_spawn0.o src/libexecline/el_spawn0.lo: src/libexecline/el_spawn0.c src/include/execline/config.h src/include/execline/execline.h src/libexecline/el_substandrun.o src/libexecline/el_substandrun.lo: src/libexecline/el_substandrun.c src/include-local/exlsn.h src/libexecline/el_substandrun_str.o src/libexecline/el_substandrun_str.lo: src/libexecline/el_substandrun_str.c src/include/execline/execline.h src/include-local/exlsn.h @@ -185,15 +186,15 @@ wait: src/execline/wait.o ${LIBEXECLINE} -lskarnet withstdinas: EXTRA_LIBS := withstdinas: src/execline/withstdinas.o ${LIBEXECLINE} -lskarnet ifeq ($(strip $(STATIC_LIBS_ARE_PIC)),) -libexecline.a.xyzzy: src/libexecline/el_execsequence.o src/libexecline/el_forx_pidinfo.o src/libexecline/el_getstrict.o src/libexecline/el_modif_and_exec.o src/libexecline/el_modif_and_spawn.o src/libexecline/el_modifs_and_exec.o src/libexecline/el_parse.o src/libexecline/el_parse_from_buffer.o src/libexecline/el_parse_from_string.o src/libexecline/el_popenv.o src/libexecline/el_pushenv.o src/libexecline/el_semicolon.o src/libexecline/el_spawn0.o src/libexecline/el_gspawn0.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_trueargv.o src/libexecline/el_vardupl.o src/libexecline/exlsn_define.o src/libexecline/exlsn_elglob.o src/libexecline/exlsn_importas.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.a.xyzzy: src/libexecline/el_execsequence.o src/libexecline/el_forx_pidinfo.o src/libexecline/el_getstrict.o src/libexecline/el_modif_and_exec.o src/libexecline/el_modif_and_spawn.o src/libexecline/el_modifs_and_exec.o src/libexecline/el_parse.o src/libexecline/el_parse_from_buffer.o src/libexecline/el_parse_from_string.o src/libexecline/el_popenv.o src/libexecline/el_pushenv.o src/libexecline/el_semicolon.o src/libexecline/el_semicolon_nostrict.o src/libexecline/el_spawn0.o src/libexecline/el_gspawn0.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_trueargv.o src/libexecline/el_vardupl.o src/libexecline/exlsn_define.o src/libexecline/exlsn_elglob.o src/libexecline/exlsn_importas.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 else -libexecline.a.xyzzy:src/libexecline/el_execsequence.lo src/libexecline/el_forx_pidinfo.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_modifs_and_exec.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.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_trueargv.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.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.xyzzy:src/libexecline/el_execsequence.lo src/libexecline/el_forx_pidinfo.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_modifs_and_exec.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_semicolon_nostrict.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.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_trueargv.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.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 endif libexecline.pc: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} libexecline.so.xyzzy: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} -libexecline.so.xyzzy:src/libexecline/el_execsequence.lo src/libexecline/el_forx_pidinfo.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_modifs_and_exec.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.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_trueargv.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.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.so.xyzzy:src/libexecline/el_execsequence.lo src/libexecline/el_forx_pidinfo.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_modifs_and_exec.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_semicolon_nostrict.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.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_trueargv.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.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.dylib.xyzzy: EXTRA_LIBS := -lskarnet ${SPAWN_LIB} -libexecline.dylib.xyzzy:src/libexecline/el_execsequence.lo src/libexecline/el_forx_pidinfo.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_modifs_and_exec.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.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_trueargv.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.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.dylib.xyzzy:src/libexecline/el_execsequence.lo src/libexecline/el_forx_pidinfo.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.lo src/libexecline/el_modifs_and_exec.lo src/libexecline/el_parse.lo src/libexecline/el_parse_from_buffer.lo src/libexecline/el_parse_from_string.lo src/libexecline/el_popenv.lo src/libexecline/el_pushenv.lo src/libexecline/el_semicolon.lo src/libexecline/el_semicolon_nostrict.lo src/libexecline/el_spawn0.lo src/libexecline/el_gspawn0.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_trueargv.lo src/libexecline/el_vardupl.lo src/libexecline/exlsn_define.lo src/libexecline/exlsn_elglob.lo src/libexecline/exlsn_importas.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 execline: EXTRA_LIBS := ${SPAWN_LIB} ${MAYBEPTHREAD_LIB} execline: src/multicall/execline.o ${LIBEXECLINE} ${LIBNSSS} -lskarnet INTERNAL_LIBS := 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 ; +} |
