From f021f61f10c566fcae2f77b1a4b095869076062b Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Wed, 30 Dec 2020 23:06:31 +0000 Subject: Add -E option for variable autoimport --- src/execline/backtick.c | 82 ++++++++++--------------- src/execline/deps-exe/getcwd | 1 + src/execline/deps-exe/getpid | 1 + src/execline/deps-exe/withstdinas | 1 + src/execline/forbacktickx.c | 11 ++-- src/execline/forstdin.c | 114 ++++++++++++++++------------------- src/execline/forx.c | 39 ++++-------- src/execline/getcwd.c | 36 ++++++++--- src/execline/getpid.c | 38 ++++++++---- src/execline/withstdinas.c | 59 ++++++++---------- src/include/execline/execline.h | 7 +++ src/libexecline/deps-lib/execline | 2 + src/libexecline/el_modif_and_exec.c | 36 +++++++++++ src/libexecline/el_modif_and_spawn.c | 39 ++++++++++++ src/libexecline/el_spawn0.c | 1 + 15 files changed, 268 insertions(+), 199 deletions(-) create mode 100644 src/libexecline/el_modif_and_exec.c create mode 100644 src/libexecline/el_modif_and_spawn.c (limited to 'src') diff --git a/src/execline/backtick.c b/src/execline/backtick.c index fa7403f..9394456 100644 --- a/src/execline/backtick.c +++ b/src/execline/backtick.c @@ -12,22 +12,22 @@ #include -#define USAGE "backtick [ -i | -I | -D default ] [ -N | -n ] var { prog... } remainder..." +#define USAGE "backtick [ -i | -I | -D default ] [ -N | -n ] [ -E | -e ] var { prog... } remainder..." #define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const **argv, char const *const *envp) { subgetopt_t localopt = SUBGETOPT_ZERO ; - pid_t pid ; int argc1, fdwstat ; - stralloc modif = STRALLOC_ZERO ; - size_t modifstart ; - int insist = 0, chomp = 1 ; + stralloc value = STRALLOC_ZERO ; + char const *var ; + char const *val ; + int insist = 0, chomp = 1, doimport = 0 ; char const *def = 0 ; PROG = "backtick" ; for (;;) { - int opt = subgetopt_r(argc, argv, "iINnD:", &localopt) ; + int opt = subgetopt_r(argc, argv, "iINnD:Ee", &localopt) ; if (opt < 0) break ; switch (opt) { @@ -36,69 +36,51 @@ int main (int argc, char const **argv, char const *const *envp) case 'N' : chomp = 0 ; break ; case 'n' : chomp = 1 ; break ; case 'D' : def = localopt.arg ; break ; + case 'E' : doimport = 1 ; break ; + case 'e' : doimport = 0 ; break ; default : dieusage() ; } } argc -= localopt.ind ; argv += localopt.ind ; if (argc < 2) dieusage() ; - if (!*argv[0]) strerr_dief1x(100, "empty variable not accepted") ; - if (!stralloc_cats(&modif, argv[0]) || !stralloc_catb(&modif, "=", 1)) - strerr_diefu1sys(111, "stralloc_catb") ; - modifstart = modif.len ; - argc-- ; argv++ ; + if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; + argc-- ; var = *argv++ ; argc1 = el_semicolon(argv) ; if (!argc1) strerr_dief1x(100, "empty block") ; if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; - argv[argc1] = 0 ; - pid = child_spawn1_pipe(argv[0], argv, envp, &fdwstat, 1) ; - if (!pid) strerr_diefu2sys(111, "spawn ", argv[0]) ; - if (!slurp(&modif, fdwstat)) strerr_diefu1sys(111, "slurp") ; - close(fdwstat) ; - if (wait_pid(pid, &fdwstat) < 0) strerr_diefu1sys(111, "wait_pid") ; + { + pid_t pid = child_spawn1_pipe(argv[0], argv, envp, &fdwstat, 1) ; + if (!pid) strerr_diefu2sys(111, "spawn ", argv[0]) ; + if (!slurp(&value, fdwstat) || !stralloc_0(&value)) + strerr_diefu1sys(111, "slurp") ; + close(fdwstat) ; + if (wait_pid(pid, &fdwstat) < 0) strerr_diefu1sys(111, "wait_pid") ; + } + + val = value.s ; if (wait_status(fdwstat)) { if (insist >= 2) if (WIFSIGNALED(fdwstat)) strerr_dief1x(111, "child process crashed") ; else strerr_dief1x(WEXITSTATUS(fdwstat), "child process exited non-zero") ; - else if (insist) - { - modif.len = modifstart - 1 ; - chomp = 0 ; - } - else if (def) - { - modif.len = modifstart ; - if (!stralloc_cats(&modif, def)) strerr_diefu1sys(111, "stralloc_catb") ; - } + else if (insist) val = 0 ; + else if (def) val = def ; } - if (argc1 == argc - 1) return 0 ; - if (!stralloc_0(&modif)) strerr_diefu1sys(111, "stralloc_catb") ; + else if (strlen(value.s) < value.len - 1) { - size_t reallen = strlen(modif.s) ; - if (reallen < modif.len - 1) + if (insist >= 2) + strerr_dief1x(1, "child process output contained a null character") ; + else if (insist) val = 0 ; + else if (def) { - if (insist >= 2) - strerr_dief1x(1, "child process output contained a null character") ; - else if (insist) - { - modif.len = modifstart ; - modif.s[modif.len - 1] = 0 ; - chomp = 0 ; - } - else if (def) - { - modif.len = modifstart ; - if (!stralloc_catb(&modif, def, strlen(def)+1)) - strerr_diefu1sys(111, "stralloc_catb") ; - strerr_warnw2x("child process output contained a null character", " - using default instead") ; - } - else modif.len = reallen + 1 ; + val = def ; + strerr_warnw2x("child process output contained a null character", " - using default instead") ; } - if (chomp && (modif.s[modif.len - 2] == '\n')) - modif.s[--modif.len - 1] = 0 ; } - xmexec_en(argv + argc1 + 1, envp, modif.s, modif.len, 1) ; + else if (chomp && (value.s[value.len - 2] == '\n')) + value.s[--value.len - 1] = 0 ; + el_modif_and_exec(argv + argc1 + 1, var, val, doimport) ; } diff --git a/src/execline/deps-exe/getcwd b/src/execline/deps-exe/getcwd index e7187fe..97021b5 100644 --- a/src/execline/deps-exe/getcwd +++ b/src/execline/deps-exe/getcwd @@ -1 +1,2 @@ +${LIBEXECLINE} -lskarnet diff --git a/src/execline/deps-exe/getpid b/src/execline/deps-exe/getpid index e7187fe..97021b5 100644 --- a/src/execline/deps-exe/getpid +++ b/src/execline/deps-exe/getpid @@ -1 +1,2 @@ +${LIBEXECLINE} -lskarnet diff --git a/src/execline/deps-exe/withstdinas b/src/execline/deps-exe/withstdinas index e7187fe..97021b5 100644 --- a/src/execline/deps-exe/withstdinas +++ b/src/execline/deps-exe/withstdinas @@ -1 +1,2 @@ +${LIBEXECLINE} -lskarnet diff --git a/src/execline/forbacktickx.c b/src/execline/forbacktickx.c index 1f3a0f1..2fc8bb8 100644 --- a/src/execline/forbacktickx.c +++ b/src/execline/forbacktickx.c @@ -12,20 +12,20 @@ #include #include -#define USAGE "forbacktickx [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -N | -n ] [ -C | -c ] [ -0 | -d delim ] var { backtickcmd... } command..." +#define USAGE "forbacktickx [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -E | -e ] [ -N | -n ] [ -C | -c ] [ -0 | -d delim ] var { backtickcmd... } command..." #define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const *const *argv) { char const *delim = "\n" ; char const *codes = 0 ; - int crunch = 0, chomp = 1, not = 1, par = 0 ; + int crunch = 0, chomp = 1, not = 1, par = 0, doimport = 0 ; PROG = "forbacktickx" ; { subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { - int opt = subgetopt_r(argc, argv, "pNnCc0d:o:x:", &l) ; + int opt = subgetopt_r(argc, argv, "pNnCc0d:o:x:Ee", &l) ; if (opt == -1) break ; switch (opt) { @@ -54,6 +54,8 @@ int main (int argc, char const *const *argv) not = 1 ; break ; } + case 'E' : doimport = 1 ; break ; + case 'e' : doimport = 0 ; break ; default : dieusage() ; } } @@ -65,7 +67,7 @@ int main (int argc, char const *const *argv) { unsigned int m = 0, i = 1 ; int fd = dup(0) ; - char const *newargv[argc + 18] ; + char const *newargv[argc + 19] ; char fmt[UINT_FMT] ; if (fd < 0) { @@ -81,6 +83,7 @@ int main (int argc, char const *const *argv) newargv[m++] = EXECLINE_BINPREFIX "unexport" ; newargv[m++] = "!" ; newargv[m++] = EXECLINE_BINPREFIX "forstdin" ; + newargv[m++] = doimport ? "-E" : "-e" ; if (par) newargv[m++] = "-p" ; newargv[m++] = chomp ? "-n" : "-N" ; if (crunch) newargv[m++] = "-C" ; diff --git a/src/execline/forstdin.c b/src/execline/forstdin.c index 336aaa4..bacb1ae 100644 --- a/src/execline/forstdin.c +++ b/src/execline/forstdin.c @@ -9,16 +9,14 @@ #include #include #include -#include #include #include #include #include -#include #include -#define USAGE "forstdin [ -p | -o okcode,okcode,... | -x breakcode,breakcode,... ] [ -N | -n ] [ -C | -c ] [ -0 | -d delim ] var command..." +#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 */ @@ -45,19 +43,20 @@ static void parallel_sigchld_handler (int sig) (void)sig ; } -int main (int argc, char const **argv, char const *const *envp) +int main (int argc, char const **argv) { + stralloc value = STRALLOC_ZERO ; char const *delim = "\n" ; size_t delimlen = 1 ; size_t nbc = 0 ; unsigned short okcodes[256] ; - int crunch = 0, chomp = 1, not = 1, eofcode = 1 ; + int crunch = 0, chomp = 1, not = 1, eofcode = 1, doimport = 0 ; PROG = "forstdin" ; { subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { - int opt = subgetopt_r(argc, argv, "pNnCc0d:o:x:", &l) ; + int opt = subgetopt_r(argc, argv, "pNnCc0d:o:x:Ee", &l) ; if (opt == -1) break ; switch (opt) { @@ -81,81 +80,74 @@ int main (int argc, char const **argv, char const *const *envp) not = 1 ; if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ; break ; + case 'E' : doimport = 1 ; break ; + case 'e' : doimport = 0 ; break ; default : dieusage() ; } } argc -= l.ind ; argv += l.ind ; } if (argc < 2) dieusage() ; + if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; + + if (pids.s) { - stralloc modif = STRALLOC_ZERO ; - size_t envlen = env_len(envp) ; - size_t modifstart = strlen(argv[0]) + 1 ; - char const *newenv[envlen + 2] ; - if (!stralloc_ready(&modif, modifstart+1)) - strerr_diefu1sys(111, "stralloc_ready") ; - memcpy(modif.s, argv[0], modifstart - 1) ; - modif.s[modifstart-1] = '=' ; - if (pids.s) - { - if (sig_catch(SIGCHLD, ¶llel_sigchld_handler) < 0) - strerr_diefu1sys(111, "install SIGCHLD handler") ; - } - for (;;) + if (sig_catch(SIGCHLD, ¶llel_sigchld_handler) < 0) + strerr_diefu1sys(111, "install SIGCHLD handler") ; + } + for (;;) + { + pid_t pid ; + value.len = 0 ; + if (delimlen) { - pid_t pid ; - modif.len = modifstart ; - if (delimlen) - { - int r = skagetlnsep(buffer_0, &modif, delim, delimlen) ; - if (!r) break ; - else if (r < 0) - { - if (errno != EPIPE) strerr_diefu1sys(111, "skagetlnsep") ; - if (chomp) break ; - } - if (crunch && modif.len == modifstart + 1) continue ; - if (chomp) modif.len-- ; - } - else + int r = skagetlnsep(buffer_0, &value, delim, delimlen) ; + if (!r) break ; + else if (r < 0) { - size_t unread = 0 ; - if (netstring_get(buffer_0, &modif, &unread) <= 0) - { - if (netstring_okeof(buffer_0, unread)) break ; - else strerr_diefu1sys(111, "netstring_get") ; - } - } - eofcode = 0 ; - if (!stralloc_0(&modif)) strerr_diefu1sys(111, "stralloc_0") ; - if (!env_mergen(newenv, envlen+2, envp, envlen, modif.s, modif.len, 1)) - strerr_diefu1sys(111, "merge environment") ; - if (pids.s) sig_block(SIGCHLD) ; - pid = el_spawn0(argv[1], argv + 1, newenv) ; - if (!pid) strerr_diefu2sys(111, "spawn ", argv[1]) ; - if (pids.s) - { - if (!genalloc_append(pid_t, &pids, &pid)) - strerr_diefu1sys(111, "genalloc_append") ; - sig_unblock(SIGCHLD) ; + if (errno != EPIPE) strerr_diefu1sys(111, "skagetlnsep") ; + if (chomp) break ; } - else + if (crunch && value.len == 1) continue ; + if (chomp) value.len-- ; + } + else + { + size_t unread = 0 ; + if (netstring_get(buffer_0, &value, &unread) <= 0) { - int wstat ; - if (wait_pid(pid, &wstat) < 0) - strerr_diefu2sys(111, "wait for ", argv[1]) ; - if (not == isok(okcodes, nbc, wait_estatus(wstat))) - return wait_estatus(wstat) ; + if (netstring_okeof(buffer_0, unread)) break ; + else strerr_diefu1sys(111, "netstring_get") ; } } - stralloc_free(&modif) ; + eofcode = 0 ; + if (!stralloc_0(&value)) strerr_diefu1sys(111, "stralloc_0") ; + if (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 (!genalloc_append(pid_t, &pids, &pid)) + strerr_diefu1sys(111, "genalloc_append") ; + sig_unblock(SIGCHLD) ; + } + else + { + int wstat ; + if (wait_pid(pid, &wstat) < 0) + strerr_diefu2sys(111, "wait for ", argv[1]) ; + if (not == isok(okcodes, nbc, wait_estatus(wstat))) + return wait_estatus(wstat) ; + } } if (pids.s) + { for (;;) { sig_block(SIGCHLD) ; if (!pids.len) break ; sig_pause() ; } + } return eofcode ; } diff --git a/src/execline/forx.c b/src/execline/forx.c index be03794..8e6659b 100644 --- a/src/execline/forx.c +++ b/src/execline/forx.c @@ -13,7 +13,7 @@ #include #include -#define USAGE "forx [ -p ] [ -o okcode,okcode,... | -x breakcode,breakcode,... ] var { values... } command..." +#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) @@ -42,19 +42,19 @@ static int waitn_code (unsigned short const *tab, unsigned int nbc, pid_t *pids, return ok ; } -int main (int argc, char const **argv, char const *const *envp) +int main (int argc, char const **argv) { - char const *x ; - int argc1 ; + char const *var ; unsigned short okcodes[256] ; size_t nbc = 0 ; - int flagpar = 0, not = 1 ; + int flagpar = 0, not = 1, doimport = 0 ; + unsigned int argc1 ; PROG = "forx" ; { subgetopt_t l = SUBGETOPT_ZERO ; for (;;) { - int opt = subgetopt_r(argc, argv, "po:x:", &l) ; + int opt = subgetopt_r(argc, argv, "po:x:Ee", &l) ; if (opt == -1) break ; switch (opt) { @@ -67,6 +67,8 @@ int main (int argc, char const **argv, char const *const *envp) not = 1 ; if (!ushort_scanlist(okcodes, 256, l.arg, &nbc)) dieusage() ; break ; + case 'E' : doimport = 1 ; break ; + case 'e' : doimport = 0 ; break ; default : dieusage() ; } } @@ -74,32 +76,17 @@ int main (int argc, char const **argv, char const *const *envp) } if (argc < 2) dieusage() ; - x = argv[0] ; if (!*x) dieusage() ; - if (x[0] == EXECLINE_BLOCK_QUOTE_CHAR) - strerr_warnw3x("variable ", x, " starts with a block quoting character") ; - argv++ ; argc-- ; + if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; + var = *argv++ ; argc-- ; argc1 = el_semicolon(argv) ; if (argc1 >= argc) strerr_dief1x(100, "unterminated block") ; if (!argc1 || (argc1 + 1 == argc)) return 0 ; + { - size_t envlen = env_len(envp) ; - size_t varlen = strlen(x) ; - unsigned int i = 0 ; pid_t pids[flagpar ? argc1 : 1] ; - char const *newenv[envlen + 2] ; - - for (; i < (unsigned int)argc1 ; i++) + for (unsigned int i = 0 ; i < argc1 ; i++) { - pid_t pid ; - size_t vallen = strlen(argv[i]) ; - char modif[varlen + vallen + 2] ; - memcpy(modif, x, varlen) ; - modif[varlen] = '=' ; - memcpy(modif + varlen + 1, argv[i], vallen) ; - modif[varlen + vallen + 1] = 0 ; - if (!env_mergen(newenv, envlen + 2, envp, envlen, modif, varlen + vallen + 2, 1)) - strerr_diefu1sys(111, "build new environment") ; - pid = el_spawn0(argv[argc1+1], argv + argc1 + 1, newenv) ; + pid_t pid = el_modif_and_spawn(argv + argc1 + 1, var, argv[i], doimport) ; if (!pid) strerr_diefu2sys(111, "spawn ", argv[argc1+1]) ; if (flagpar) pids[i] = pid ; else diff --git a/src/execline/getcwd.c b/src/execline/getcwd.c index d41bd5a..2a82924 100644 --- a/src/execline/getcwd.c +++ b/src/execline/getcwd.c @@ -2,23 +2,39 @@ #include +#include #include #include #include -#include -#define USAGE "getcwd variable prog..." +#include + +#define USAGE "getcwd [ -E | -e ] variable prog..." +#define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const *const *argv) { + int doimport = 0 ; stralloc sa = STRALLOC_ZERO ; PROG = "getcwd" ; - if (argc < 3) strerr_dieusage(100, USAGE) ; - if (strchr(argv[1], '=')) - strerr_dief2x(100, "invalid variable name: ", argv[1]) ; - if (!stralloc_cats(&sa, argv[1]) || !stralloc_catb(&sa, "=", 1)) - strerr_diefu1sys(111, "stralloc_catb") ; - if (sagetcwd(&sa) < 0) strerr_diefu1sys(111, "getcwd") ; - if (!stralloc_0(&sa)) strerr_diefu1sys(111, "stralloc_catb") ; - xmexec_n(argv + 2, sa.s, sa.len, 1) ; + { + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "Ee", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'E' : doimport = 1 ; break ; + case 'e' : doimport = 0 ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (argc < 2) dieusage() ; + if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; + + if (sagetcwd(&sa) < 0 || !stralloc_0(&sa)) strerr_diefu1sys(111, "getcwd") ; + el_modif_and_exec(argv + 1, argv[0], sa.s, doimport) ; } diff --git a/src/execline/getpid.c b/src/execline/getpid.c index 06c4aaf..64866de 100644 --- a/src/execline/getpid.c +++ b/src/execline/getpid.c @@ -4,25 +4,37 @@ #include #include +#include #include -#include -#define USAGE "getpid variable prog..." +#include + +#define USAGE "getpid [ -E | -e ] variable prog..." +#define dieusage() strerr_dieusage(100, USAGE) int main (int argc, char const *const *argv) { - size_t len ; + int doimport = 0 ; + char fmt[PID_FMT] ; PROG = "getpid" ; - if (argc < 3) strerr_dieusage(100, USAGE) ; - len = strlen(argv[1]) ; - if (memchr(argv[1], '=', len)) - strerr_dief2x(100, "invalid variable name: ", argv[1]) ; { - size_t i = len+1 ; - char fmt[PID_FMT + len + 2] ; - memcpy(fmt, argv[1], len) ; - fmt[len] = '=' ; - i += pid_fmt(fmt+i, getpid()) ; fmt[i++] = 0 ; - xmexec_n(argv+2, fmt, i, 1) ; + subgetopt_t l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "Ee", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'E' : doimport = 1 ; break ; + case 'e' : doimport = 0 ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; } + if (argc < 2) dieusage() ; + if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; + + fmt[pid_fmt(fmt, getpid())] = 0 ; + el_modif_and_exec(argv + 1, argv[0], fmt, doimport) ; } diff --git a/src/execline/withstdinas.c b/src/execline/withstdinas.c index 467b68b..cd025bf 100644 --- a/src/execline/withstdinas.c +++ b/src/execline/withstdinas.c @@ -6,22 +6,23 @@ #include #include #include -#include -#define USAGE "withstdinas [ -i | -I | -D default ] [ -N | -n ] var remainder..." +#include + +#define USAGE "withstdinas [ -i | -I | -D default ] [ -N | -n ] [ -E | -e ] var remainder..." #define dieusage() strerr_dieusage(100, USAGE) -int main (int argc, char const **argv) +int main (int argc, char const *const *argv) { subgetopt_t localopt = SUBGETOPT_ZERO ; - stralloc modif = STRALLOC_ZERO ; - size_t modifstart ; - int insist = 0, chomp = 1 ; + stralloc value = STRALLOC_ZERO ; + int insist = 0, chomp = 1, doimport = 0 ; char const *def = 0 ; + char const *val ; PROG = "withstdinas" ; for (;;) { - int opt = subgetopt_r(argc, argv, "iINnD:", &localopt) ; + int opt = subgetopt_r(argc, argv, "iINnD:Ee", &localopt) ; if (opt < 0) break ; switch (opt) { @@ -30,41 +31,29 @@ int main (int argc, char const **argv) case 'N' : chomp = 0 ; break ; case 'n' : chomp = 1 ; break ; case 'D' : def = localopt.arg ; break ; + case 'E' : doimport = 1 ; break ; + case 'e' : doimport = 0 ; break ; default : dieusage() ; } } argc -= localopt.ind ; argv += localopt.ind ; - if (!argc) dieusage() ; - if (!*argv[0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; - if (!stralloc_cats(&modif, argv[0]) || !stralloc_catb(&modif, "=", 1)) - strerr_diefu1sys(111, "stralloc_catb") ; - modifstart = modif.len ; - if (!slurp(&modif, 0)) strerr_diefu1sys(111, "slurp") ; - if (!stralloc_0(&modif)) strerr_diefu1sys(111, "stralloc_catb") ; + if (!argv[0][0] || strchr(argv[0], '=')) strerr_dief1x(100, "invalid variable name") ; + + if (!slurp(&value, 0) || !stralloc_0(&value)) strerr_diefu1sys(111, "slurp") ; + val = value.s ; + if (strlen(value.s) < value.len - 1) { - size_t reallen = strlen(modif.s) ; - if (reallen < modif.len - 1) + if (insist >= 2) + strerr_dief1x(1, "stdin contained a null character") ; + else if (insist) val = 0 ; + else if (def) { - if (insist >= 2) - strerr_dief1x(1, "stdin contained a null character") ; - else if (insist) - { - modif.len = modifstart ; - modif.s[modif.len - 1] = 0 ; - chomp = 0 ; - } - else if (def) - { - modif.len = modifstart ; - if (!stralloc_catb(&modif, def, strlen(def)+1)) - strerr_diefu1sys(111, "stralloc_catb") ; - strerr_warnw2x("stdin contained a null character", " - using default instead") ; - } - else modif.len = reallen + 1 ; + val = def ; + strerr_warnw2x("stdin contained a null character", " - using default instead") ; } - if (chomp && (modif.s[modif.len - 2] == '\n')) - modif.s[--modif.len - 1] = 0 ; } - xmexec0_n(argv + 1, modif.s, modif.len, 1) ; + else if (chomp && (value.s[value.len - 2] == '\n')) + value.s[--value.len - 1] = 0 ; + el_modif_and_exec(argv + 1, argv[0], val, doimport) ; } diff --git a/src/include/execline/execline.h b/src/include/execline/execline.h index bbe4db9..144283d 100644 --- a/src/include/execline/execline.h +++ b/src/include/execline/execline.h @@ -4,6 +4,7 @@ #define EXECLINE_H #include + #include #include #include @@ -76,4 +77,10 @@ struct elsubst_s extern int el_substitute (stralloc *, char const *, size_t, char const *, char const *, elsubst_t const *, unsigned int) ; + +/* Execution with or without substitution */ + +extern void el_modif_and_exec (char const *const *, char const *, char const *, int) gccattr_noreturn ; +extern pid_t el_modif_and_spawn (char const *const *, char const *, char const *, int) ; + #endif diff --git a/src/libexecline/deps-lib/execline b/src/libexecline/deps-lib/execline index 96d4e18..e896f2f 100644 --- a/src/libexecline/deps-lib/execline +++ b/src/libexecline/deps-lib/execline @@ -1,5 +1,7 @@ el_execsequence.o el_getstrict.o +el_modif_and_exec.o +el_modif_and_spawn.o el_parse.o el_parse_from_buffer.o el_parse_from_string.o diff --git a/src/libexecline/el_modif_and_exec.c b/src/libexecline/el_modif_and_exec.c new file mode 100644 index 0000000..e2a3618 --- /dev/null +++ b/src/libexecline/el_modif_and_exec.c @@ -0,0 +1,36 @@ +/* ISC license. */ + +#include + +#include +#include + +#include +#include + +void el_modif_and_exec (char const *const *argv, char const *var, char const *value, int doimport) +{ + size_t varlen = strlen(var) ; + size_t modiflen = value ? varlen + strlen(value) + 2 : 1 ; + char modifs[modiflen] ; + if (value) + { + memcpy(modifs, var, varlen) ; + modifs[varlen] = '=' ; + memcpy(modifs + varlen + 1, value, modiflen - varlen - 1) ; + } + if (doimport) + { + size_t m = 0 ; + char const *newargv[env_len(argv) + 6] ; + newargv[m++] = EXECLINE_BINPREFIX "importas" ; + newargv[m++] = "-ui" ; + newargv[m++] = "--" ; + newargv[m++] = var ; + newargv[m++] = var ; + while (*argv) newargv[m++] = *argv++ ; + newargv[m++] = 0 ; + xmexec0_n(newargv, value ? modifs : var, value ? modiflen : varlen + 1, 1) ; + } + else xmexec0_n(argv, value ? modifs : var, value ? modiflen : varlen + 1, 1) ; +} diff --git a/src/libexecline/el_modif_and_spawn.c b/src/libexecline/el_modif_and_spawn.c new file mode 100644 index 0000000..0070052 --- /dev/null +++ b/src/libexecline/el_modif_and_spawn.c @@ -0,0 +1,39 @@ +/* ISC license. */ + +#include + +#include +#include + +#include +#include + +pid_t el_modif_and_spawn (char const *const *argv, char const *var, char const *value, int doimport) +{ + size_t varlen = strlen(var) ; + size_t modiflen = value ? varlen + strlen(value) + 2 : 1 ; + size_t envlen = env_len((char const *const *)environ) ; + char const *newenv[envlen + 2] ; + char modifs[modiflen] ; + if (value) + { + memcpy(modifs, var, varlen) ; + modifs[varlen] = '=' ; + memcpy(modifs + varlen + 1, value, modiflen - varlen - 1) ; + } + if (!env_mergen(newenv, envlen + 2, (char const *const *)environ, envlen, value ? modifs : var, value ? modiflen : varlen + 1, 1)) return 0 ; + if (doimport) + { + size_t m = 0 ; + char const *newargv[env_len(argv) + 6] ; + newargv[m++] = EXECLINE_BINPREFIX "importas" ; + newargv[m++] = "-ui" ; + newargv[m++] = "--" ; + newargv[m++] = var ; + newargv[m++] = var ; + while (*argv) newargv[m++] = *argv++ ; + newargv[m++] = 0 ; + return el_spawn0(newargv[0], newargv, newenv) ; + } + else return el_spawn0(argv[0], argv, newenv) ; +} diff --git a/src/libexecline/el_spawn0.c b/src/libexecline/el_spawn0.c index 7e10902..0cfe017 100644 --- a/src/libexecline/el_spawn0.c +++ b/src/libexecline/el_spawn0.c @@ -1,6 +1,7 @@ /* ISC license. */ #include + #include #include -- cgit v1.2.3