aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2026-03-09 19:03:37 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2026-03-09 19:03:37 +0000
commit6c756905574a019df52ad865a81cf97b6e2b6c58 (patch)
tree54bb9ff91422a6de7606c1a9be6c29e080d7d994
parent26fa9d9d3fef9684e9e4d5cd0bcd4336fee8d749 (diff)
downloadexecline-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--AUTHORS1
-rw-r--r--package/deps.mak9
-rw-r--r--src/execline/wait.c79
-rw-r--r--src/include/execline/execline.h1
-rw-r--r--src/libexecline/deps-lib/execline1
-rw-r--r--src/libexecline/el_semicolon.c36
-rw-r--r--src/libexecline/el_semicolon_nostrict.c14
7 files changed, 83 insertions, 58 deletions
diff --git a/AUTHORS b/AUTHORS
index c2e18a9..97a5512 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -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 ;
+}