diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2023-02-01 18:08:26 +0000 |
---|---|---|
committer | Laurent Bercot <ska@appnovation.com> | 2023-02-01 18:08:26 +0000 |
commit | edf81b0d16322e5d49ec22f394b669d9094daac1 (patch) | |
tree | 04b1a40a5af1c8d95978e0e85d96cb8e5cb061bb | |
parent | 5b5f5e507db58c5005cd8a572f761ef2f002cb0f (diff) | |
download | execline-edf81b0d16322e5d49ec22f394b669d9094daac1.tar.xz |
Add a multicall target. If you use it, you're on your own.
Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | package/deps.mak | 2 | ||||
-rw-r--r-- | package/targets.mak | 10 | ||||
-rw-r--r-- | src/execline/case.c | 6 | ||||
-rw-r--r-- | src/execline/eltest.c | 14 | ||||
-rw-r--r-- | src/execline/forstdin.c | 26 | ||||
-rw-r--r-- | src/execline/forx.c | 6 | ||||
-rw-r--r-- | src/execline/loopwhilex.c | 4 | ||||
-rw-r--r-- | src/execline/trap.c | 36 | ||||
-rw-r--r-- | src/multicall/deps-exe/execline | 5 | ||||
-rwxr-xr-x | tools/gen-multicall.sh | 97 |
12 files changed, 167 insertions, 48 deletions
@@ -12,6 +12,7 @@ /elgetopt /elgetpositionals /elglob +/eltest /emptyenv /envfile /exec @@ -55,3 +56,5 @@ /unexport /wait /withstdinas +/src/multicall/execline.c +/execline @@ -19,6 +19,8 @@ SHARED_LIBS := INTERNAL_LIBS := EXTRA_TARGETS := LIB_DEFS := +EXTRA_BINS := +EXTRA_TEMP := define library_definition LIB$(firstword $(subst =, ,$(1))) := lib$(lastword $(subst =, ,$(1))).$(if $(DO_ALLSTATIC),a,so).xyzzy @@ -60,7 +62,7 @@ ALL_INCLUDES := $(wildcard src/include/$(package)/*.h) all: $(ALL_LIBS) $(ALL_BINS) $(ALL_INCLUDES) clean: - @exec rm -f $(ALL_LIBS) $(ALL_BINS) $(wildcard src/*/*.o src/*/*.lo) + @exec rm -f $(ALL_LIBS) $(ALL_BINS) $(EXTRA_BINS) $(EXTRA_TEMP) $(wildcard src/*/*.o src/*/*.lo) distclean: clean @exec rm -f config.mak src/include/$(package)/config.h @@ -134,7 +136,7 @@ $(DESTDIR)$(includedir)/$(package)/%.h: src/include/$(package)/%.h %.lo: %.c exec $(CC) $(CPPFLAGS_ALL) $(CFLAGS_ALL) $(CFLAGS_SHARED) -c -o $@ $< -$(ALL_BINS): +$(ALL_BINS) $(EXTRA_BINS): exec $(CC) -o $@ $(CFLAGS_ALL) $(LDFLAGS_ALL) $(LDFLAGS_NOSHARED) $^ $(EXTRA_LIBS) $(LDLIBS) lib%.a.xyzzy: diff --git a/package/deps.mak b/package/deps.mak index d9ab00a..fa81ab3 100644 --- a/package/deps.mak +++ b/package/deps.mak @@ -181,6 +181,8 @@ libexecline.a.xyzzy: src/libexecline/el_execsequence.lo src/libexecline/el_getst endif libexecline.so.xyzzy: EXTRA_LIBS := -lskarnet libexecline.so.xyzzy: src/libexecline/el_execsequence.lo src/libexecline/el_getstrict.lo src/libexecline/el_modif_and_exec.lo src/libexecline/el_modif_and_spawn.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_spawn1.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_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 := -lskarnet ${SPAWN_LIB} ${MAYBEPTHREAD_LIB} +execline: src/multicall/execline.o ${LIBEXECLINE} ${LIBNSSS} posix-cd: EXTRA_LIBS := -lskarnet posix-cd: src/posix/posix-cd.o posix-umask: EXTRA_LIBS := -lskarnet diff --git a/package/targets.mak b/package/targets.mak index 0b41b79..258ed41 100644 --- a/package/targets.mak +++ b/package/targets.mak @@ -67,3 +67,13 @@ $(DESTDIR)$(bindir)/cd: $(DESTDIR)$(bindir)/$(PEDANTIC_PREFIX)-cd $(DESTDIR)$(bindir)/umask: $(DESTDIR)$(bindir)/$(PEDANTIC_PREFIX)-umask exec ./tools/install.sh -l $(PEDANTIC_PREFIX)-umask $(DESTDIR)$(bindir)/umask + + +EXTRA_BINS := execline +EXTRA_TEMP := src/multicall/execline.c + +multicall: execline +.PHONY: multicall + +src/multicall/execline.c: tools/gen-multicall.sh src/execline/deps-exe src/include/execline/config.h src/include/execline/execline.h + ./tools/gen-multicall.sh > src/multicall/execline.c diff --git a/src/execline/case.c b/src/execline/case.c index ae5b5db..b62583c 100644 --- a/src/execline/case.c +++ b/src/execline/case.c @@ -15,8 +15,8 @@ #define USAGE "case [ -s | -S ] [ -e | -E ] [ -n | -N ] [ -i ] value { re1 { prog1... } re2 { prog2... } ... } progdefault... " #define dieusage() strerr_dieusage(100, USAGE) -static void execit (char const *const *argv, char const *expr, char const *s, regmatch_t const *pmatch, size_t n) gccattr_noreturn ; -static void execit (char const *const *argv, char const *expr, char const *s, regmatch_t const *pmatch, size_t n) +static void case_execit (char const *const *argv, char const *expr, char const *s, regmatch_t const *pmatch, size_t n) gccattr_noreturn ; +static void case_execit (char const *const *argv, char const *expr, char const *s, regmatch_t const *pmatch, size_t n) { if (n) { @@ -125,7 +125,7 @@ int main (int argc, char const **argv, char const *const *envp) if (!r) { argv[i + argc2] = 0 ; - execit(argv + i, expr, s, pmatch, flagnosub ? 0 : 1 + re.re_nsub) ; + case_execit(argv + i, expr, s, pmatch, flagnosub ? 0 : 1 + re.re_nsub) ; } if (r != REG_NOMATCH) { diff --git a/src/execline/eltest.c b/src/execline/eltest.c index b14318b..93ff0b4 100644 --- a/src/execline/eltest.c +++ b/src/execline/eltest.c @@ -74,7 +74,7 @@ struct node char const *data ; } ; -static unsigned int lex (struct node *tree, char const *const *argv) +static unsigned int eltest_lex (struct node *tree, char const *const *argv) { static struct token const tokens[46] = { @@ -149,7 +149,7 @@ static unsigned int lex (struct node *tree, char const *const *argv) return pos ; } -static unsigned int parse (struct node *tree, unsigned int n) +static unsigned int eltest_parse (struct node *tree, unsigned int n) { static char const table[9][13] = { @@ -278,16 +278,16 @@ static unsigned int parse (struct node *tree, unsigned int n) return stack[1] ; } -static int run (struct node const *tree, unsigned int root) +static int eltest_run (struct node const *tree, unsigned int root) { switch (tree[root].op) { case T_NOT : - return !run(tree, tree[root].arg1) ; + return !eltest_run(tree, tree[root].arg1) ; case T_AND : - return run(tree, tree[root].arg1) && run(tree, tree[root].arg2) ; + return eltest_run(tree, tree[root].arg1) && eltest_run(tree, tree[root].arg2) ; case T_OR : - return run(tree, tree[root].arg1) || run(tree, tree[root].arg2) ; + return eltest_run(tree, tree[root].arg1) || eltest_run(tree, tree[root].arg2) ; case T_EXIST : return access(tree[tree[root].arg1].data, F_OK) == 0 ; case T_BLOCK : @@ -501,5 +501,5 @@ int main (int argc, char const *const *argv) struct node tree[argc+2] ; if (argc <= 1) return 1 ; PROG = "eltest" ; - return !run(tree, parse(tree, lex(tree, argv+1))) ; + return !eltest_run(tree, eltest_parse(tree, eltest_lex(tree, argv+1))) ; } diff --git a/src/execline/forstdin.c b/src/execline/forstdin.c index 1714be3..e365866 100644 --- a/src/execline/forstdin.c +++ b/src/execline/forstdin.c @@ -19,9 +19,9 @@ #define USAGE "forstdin [ -E | -e ] [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -N | -n ] [ -C | -c ] [ -0 | -d delim ] var command..." #define dieusage() strerr_dieusage(100, USAGE) -static genalloc pids = GENALLOC_ZERO ; /* pid_t */ +static genalloc forstdin_pids = GENALLOC_ZERO ; /* pid_t */ -static int isok (unsigned short *tab, unsigned int n, int code) +static int fs_isok (unsigned short *tab, unsigned int n, int code) { unsigned int i = 0 ; for (; i < n ; i++) if ((unsigned short)code == tab[i]) break ; @@ -30,8 +30,8 @@ static int isok (unsigned short *tab, unsigned int n, int code) static void parallel_sigchld_handler (int sig) { - pid_t *tab = genalloc_s(pid_t, &pids) ; - size_t len = genalloc_len(pid_t, &pids) ; + pid_t *tab = genalloc_s(pid_t, &forstdin_pids) ; + size_t len = genalloc_len(pid_t, &forstdin_pids) ; int wstat ; for (;;) { @@ -39,7 +39,7 @@ static void parallel_sigchld_handler (int sig) if (r <= 0) break ; tab[r-1] = tab[--len] ; } - genalloc_setlen(pid_t, &pids, len) ; + genalloc_setlen(pid_t, &forstdin_pids, len) ; (void)sig ; } @@ -62,7 +62,7 @@ int main (int argc, char const **argv) { case 'p' : { - if (!genalloc_ready(pid_t, &pids, 1)) + if (!genalloc_ready(pid_t, &forstdin_pids, 1)) strerr_diefu1sys(111, "genalloc_ready") ; break ; } @@ -90,7 +90,7 @@ int main (int argc, char const **argv) if (argc < 2) dieusage() ; if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; - if (pids.s) + if (forstdin_pids.s) { if (!sig_catch(SIGCHLD, ¶llel_sigchld_handler)) strerr_diefu1sys(111, "install SIGCHLD handler") ; @@ -122,12 +122,12 @@ int main (int argc, char const **argv) } eofcode = 0 ; if (!stralloc_0(&value)) strerr_diefu1sys(111, "stralloc_0") ; - if (pids.s) sig_block(SIGCHLD) ; + if (forstdin_pids.s) sig_block(SIGCHLD) ; pid = el_modif_and_spawn(argv + 1, argv[0], value.s, doimport) ; if (!pid) strerr_diefu2sys(111, "spawn ", argv[1]) ; - if (pids.s) + if (forstdin_pids.s) { - if (!genalloc_append(pid_t, &pids, &pid)) + if (!genalloc_append(pid_t, &forstdin_pids, &pid)) strerr_diefu1sys(111, "genalloc_append") ; sig_unblock(SIGCHLD) ; } @@ -136,18 +136,18 @@ int main (int argc, char const **argv) int wstat ; if (wait_pid(pid, &wstat) < 0) strerr_diefu2sys(111, "wait for ", argv[1]) ; - if (not == isok(okcodes, nbc, wait_estatus(wstat))) + if (not == fs_isok(okcodes, nbc, wait_estatus(wstat))) return wait_estatus(wstat) ; } } - if (pids.s) + if (forstdin_pids.s) { sigset_t empty ; sigemptyset(&empty) ; sig_block(SIGCHLD) ; for (;;) { - if (!pids.len) break ; + if (!forstdin_pids.len) break ; sigsuspend(&empty) ; } } diff --git a/src/execline/forx.c b/src/execline/forx.c index fa6c0e3..1695c00 100644 --- a/src/execline/forx.c +++ b/src/execline/forx.c @@ -16,7 +16,7 @@ #define USAGE "forx [ -E | -e ] [ -p ] [ -o okcode,okcode,... | -x breakcode,breakcode,... ] var { values... } command..." #define dieusage() strerr_dieusage(100, USAGE) -static int isok (unsigned short const *tab, unsigned int n, int code) +static int fx_isok (unsigned short const *tab, unsigned int n, int code) { unsigned int i = 0 ; for (; i < n ; i++) if ((unsigned short)code == tab[i]) break ; @@ -35,7 +35,7 @@ static int waitn_code (unsigned short const *tab, unsigned int nbc, pid_t *pids, for (; i < n ; i++) if (pid == pids[i]) break ; if (i < n) { - if (not == isok(tab, nbc, wait_estatus(wstat))) ok = 0 ; + if (not == fx_isok(tab, nbc, wait_estatus(wstat))) ok = 0 ; pids[i] = pids[--n] ; } } @@ -94,7 +94,7 @@ int main (int argc, char const **argv) int wstat ; if (wait_pid(pid, &wstat) == -1) strerr_diefu2sys(111, "wait for ", argv[argc1+1]) ; - if (not == isok(okcodes, nbc, wait_estatus(wstat))) + if (not == fx_isok(okcodes, nbc, wait_estatus(wstat))) return wait_estatus(wstat) ; } } diff --git a/src/execline/loopwhilex.c b/src/execline/loopwhilex.c index b29d26a..acae3b3 100644 --- a/src/execline/loopwhilex.c +++ b/src/execline/loopwhilex.c @@ -12,7 +12,7 @@ #define USAGE "loopwhilex [ -n ] [ -o okcode,okcode,... | -x exitcode,exitcode,... ] prog..." #define dieusage() strerr_dieusage(100, USAGE) -static int isok (unsigned short *tab, unsigned int n, int code) +static int lw_isok (unsigned short *tab, unsigned int n, int code) { unsigned int i = 0 ; for (; i < n ; i++) if ((unsigned short)code == tab[i]) break ; @@ -67,7 +67,7 @@ int main (int argc, char const *const *argv, char const *const *envp) else strerr_diefu2sys(111, "spawn ", argv[0]) ; } if (wait_pid(pid, &wstat) < 0) strerr_diefu1sys(111, "wait_pid") ; - cont = not != isok(okcodes, nbc, wait_estatus(wstat)) ; + cont = not != lw_isok(okcodes, nbc, wait_estatus(wstat)) ; } return wait_estatus(wstat) ; } diff --git a/src/execline/trap.c b/src/execline/trap.c index cc13595..630f865 100644 --- a/src/execline/trap.c +++ b/src/execline/trap.c @@ -20,30 +20,30 @@ #define USAGE "trap [ -x ] { signal { cmdline } ... } prog..." #define dieusage() strerr_dieusage(100, USAGE) ; -static pid_t pids[SKALIBS_NSIG + 1] ; -static char const *const *argvs[SKALIBS_NSIG] ; /* initted with 0s */ +static pid_t trap_pids[SKALIBS_NSIG + 1] ; +static char const *const *trap_argvs[SKALIBS_NSIG] ; /* initted with 0s */ static inline void action (unsigned int i, char const *const *envp, size_t envlen) { - if (argvs[i]) + if (trap_argvs[i]) { - if (!pids[i]) + if (!trap_pids[i]) { char const *newenvp[envlen + 3] ; char modif[9 + PID_FMT + UINT_FMT] = "!=" ; size_t m = 2 ; - m += pid_fmt(modif + m, pids[SKALIBS_NSIG]) ; + m += pid_fmt(modif + m, trap_pids[SKALIBS_NSIG]) ; modif[m++] = 0 ; memcpy(modif + m, "SIGNAL=", 7) ; m += 7 ; m += uint_fmt(modif + m, i) ; modif[m++] = 0 ; if (!env_mergen(newenvp, envlen + 3, envp, envlen, modif, m, 2)) strerr_diefu1sys(111, "adjust environment for child") ; - pids[i] = child_spawn0(argvs[i][0], argvs[i], newenvp) ; - if (!pids[i]) strerr_diefu2sys(111, "spawn ", argvs[i][0]) ; + trap_pids[i] = child_spawn0(trap_argvs[i][0], trap_argvs[i], newenvp) ; + if (!trap_pids[i]) strerr_diefu2sys(111, "spawn ", trap_argvs[i][0]) ; } } - else kill(pids[SKALIBS_NSIG], i) ; + else kill(trap_pids[SKALIBS_NSIG], i) ; } int main (int argc, char const **argv, char const *const *envp) @@ -89,10 +89,10 @@ int main (int argc, char const **argv, char const *const *envp) argc2 = el_semicolon(argv + ++i) ; if (i + argc2 >= argc1) strerr_dief3x(100, "unterminated", " internal block for directive ", argv[i-1]) ; - if (argvs[sig]) + if (trap_argvs[sig]) strerr_dief3x(100, "duplicate", " directive: ", argv[i-1]) ; if (!sig || (sig != SIGCHLD && sigismember(&full, sig) > 0)) - argvs[sig] = argv + i ; + trap_argvs[sig] = argv + i ; else { char fmt[UINT_FMT] ; @@ -103,10 +103,10 @@ int main (int argc, char const **argv, char const *const *envp) i += argc2 + 1 ; } - if (argvs[0]) + if (trap_argvs[0]) for (i = 1 ; i < SKALIBS_NSIG ; i++) - if (!argvs[i] && sigismember(&full, i) > 0) - argvs[i] = argvs[0] ; + if (!trap_argvs[i] && sigismember(&full, i) > 0) + trap_argvs[i] = trap_argvs[0] ; if (xfersigs) set = full ; else @@ -114,7 +114,7 @@ int main (int argc, char const **argv, char const *const *envp) sigemptyset(&set) ; sigaddset(&set, SIGCHLD) ; for (i = 1 ; i < SKALIBS_NSIG ; i++) - if (argvs[i]) + if (trap_argvs[i]) sigaddset(&set, i) ; } @@ -122,8 +122,8 @@ int main (int argc, char const **argv, char const *const *envp) if (x.fd < 0) strerr_diefu1sys(111, "selfpipe_init") ; if (!selfpipe_trapset(&set)) strerr_diefu1sys(111, "trap signals") ; - pids[SKALIBS_NSIG] = child_spawn0(argv[argc1 + 1], argv + argc1 + 1, envp) ; - if (!pids[SKALIBS_NSIG]) strerr_diefu2sys(111, "spawn ", argv[argc1 + 1]) ; + trap_pids[SKALIBS_NSIG] = child_spawn0(argv[argc1 + 1], argv + argc1 + 1, envp) ; + if (!trap_pids[SKALIBS_NSIG]) strerr_diefu2sys(111, "spawn ", argv[argc1 + 1]) ; loop: if (iopause_g(&x, 1, 0) < 0) strerr_diefu1sys(111, "iopause") ; @@ -138,11 +138,11 @@ int main (int argc, char const **argv, char const *const *envp) for (;;) { int wstat ; - ssize_t id = wait_pids_nohang(pids, SKALIBS_NSIG + 1, &wstat) ; + ssize_t id = wait_pids_nohang(trap_pids, SKALIBS_NSIG + 1, &wstat) ; if (id < 0 && errno != ECHILD) strerr_diefu1sys(111, "wait") ; if (id <= 0) break ; - pids[id - 1] = 0 ; + trap_pids[id - 1] = 0 ; if (id == SKALIBS_NSIG + 1) return wait_estatus(wstat) ; } break ; diff --git a/src/multicall/deps-exe/execline b/src/multicall/deps-exe/execline new file mode 100644 index 0000000..d024a89 --- /dev/null +++ b/src/multicall/deps-exe/execline @@ -0,0 +1,5 @@ +${LIBEXECLINE} +${LIBNSSS} +-lskarnet +${SPAWN_LIB} +${MAYBEPTHREAD_LIB} diff --git a/tools/gen-multicall.sh b/tools/gen-multicall.sh new file mode 100755 index 0000000..d9b03d3 --- /dev/null +++ b/tools/gen-multicall.sh @@ -0,0 +1,97 @@ +#!/bin/sh -e + +echo '/* ISC license. */' +echo +echo '#include <skalibs/nonposix.h>' +echo +{ echo '#include <string.h>' ; echo '#include <stdlib.h>' ; cat src/execline/*.c | grep '^#include <' | grep -vF '<skalibs/' | grep -vF '<execline/' ; } | sort -u + +cat <<EOF + +#include <skalibs/nsig.h> +#include <skalibs/skalibs.h> + +#include <execline/config.h> +#include <execline/execline.h> +#include "exlsn.h" + +typedef int main_func (int, char **, char const *const *) ; +typedef main_func *main_func_ref ; + +typedef struct execline_app_s execline_app, *execline_app_ref ; +struct execline_app_s +{ + char const *name ; + main_func_ref mainf ; +} ; + +static int execline_app_cmp (void const *a, void const *b) +{ + char const *name = a ; + execline_app const *p = b ; + return strcmp(name, p->name) ; +} + +#ifdef EXECLINE_PEDANTIC_POSIX +# define CD_FUNC posix_cd_main +# define UMASK_FUNC posix_umask_main +#else +# define CD_FUNC execline_cd_main +# define UMASK_FUNC execline_umask_main +#endif + +EOF + +for i in `ls -1 src/execline/deps-exe` ; do + j=`echo $i | tr - _` + echo + grep -v '^#include ' < src/execline/${i}.c | grep -vF '/* ISC license. */' | sed -e "s/int main (int argc, char \(.*\)\*argv.*$/int ${j}_main (int argc, char \1*argv, char const *const *envp)/" + echo + echo '#undef USAGE' + echo '#undef dieusage' +done + +cat <<EOF + +static int execline_main (int, char **, char const *const *) ; + +static execline_app const execline_apps[] = +{ +EOF + +for i in `{ echo cd ; echo execline ; echo umask ; ls -1 src/execline/deps-exe ; } | sort` ; do + j=`echo $i | tr - _` + if test $i = cd ; then + echo ' { .name = "cd", .mainf = (main_func_ref)&CD_FUNC },' + elif test $i = umask ; then + echo ' { .name = "umask", .mainf = (main_func_ref)&UMASK_FUNC },' + else + echo " { .name=\"${i}\", .mainf = (main_func_ref)&${j}_main }," + fi +done + +cat <<EOF +} ; + +#define USAGE "execline subcommand [ arguments... ]" +#define dieusage() strerr_dief1x(100, USAGE) + +static int execline_main (int argc, char **argv, char const *const *envp) +{ + execline_app const *p ; + PROG = "execline" ; + if (!argc) dieusage() ; + p = bsearch(argv[1], execline_apps, sizeof(execline_apps) / sizeof(execline_app), sizeof(execline_app), &execline_app_cmp) ; + if (!p) strerr_dief2x(100, "unknown subcommand: ", argv[1]) ; + return (*(p->mainf))(argc-1, argv+1, envp) ; +} + +int main (int argc, char **argv, char const *const *envp) +{ + execline_app const *p ; + char const *name = strrchr(argv[0], '/') ; + if (name) name++ ; else name = argv[0] ; + p = bsearch(name, execline_apps, sizeof(execline_apps) / sizeof(execline_app), sizeof(execline_app), &execline_app_cmp) ; + return p ? (*(p->mainf))(argc, argv, envp) : execline_main(argc, argv, envp) ; +} +EOF |