From 9d55d49dad0f4cb90e6ff2f9b1c3bc46a6fcf05f Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Thu, 2 Feb 2023 05:29:17 +0000 Subject: Multicall improvements Signed-off-by: Laurent Bercot --- src/execline/deps-exe/posix-cd | 1 + src/execline/deps-exe/posix-umask | 1 + src/execline/eltest.c | 20 ++--- src/execline/envfile.c | 18 ++-- src/execline/fdreserve.c | 8 +- src/execline/forstdin.c | 25 +++--- src/execline/multisubstitute.c | 38 ++++----- src/execline/posix-cd.c | 160 +++++++++++++++++++++++++++++++++++ src/execline/posix-umask.c | 174 ++++++++++++++++++++++++++++++++++++++ src/execline/posix-umask.txt | 37 ++++++++ src/execline/trap.c | 41 +++++---- src/posix/deps-exe/posix-cd | 1 - src/posix/deps-exe/posix-umask | 1 - src/posix/posix-cd.c | 160 ----------------------------------- src/posix/posix-umask.c | 174 -------------------------------------- src/posix/posix-umask.txt | 37 -------- 16 files changed, 448 insertions(+), 448 deletions(-) create mode 100644 src/execline/deps-exe/posix-cd create mode 100644 src/execline/deps-exe/posix-umask create mode 100644 src/execline/posix-cd.c create mode 100644 src/execline/posix-umask.c create mode 100644 src/execline/posix-umask.txt delete mode 100644 src/posix/deps-exe/posix-cd delete mode 100644 src/posix/deps-exe/posix-umask delete mode 100644 src/posix/posix-cd.c delete mode 100644 src/posix/posix-umask.c delete mode 100644 src/posix/posix-umask.txt (limited to 'src') diff --git a/src/execline/deps-exe/posix-cd b/src/execline/deps-exe/posix-cd new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/execline/deps-exe/posix-cd @@ -0,0 +1 @@ +-lskarnet diff --git a/src/execline/deps-exe/posix-umask b/src/execline/deps-exe/posix-umask new file mode 100644 index 0000000..e7187fe --- /dev/null +++ b/src/execline/deps-exe/posix-umask @@ -0,0 +1 @@ +-lskarnet diff --git a/src/execline/eltest.c b/src/execline/eltest.c index 93ff0b4..34321c5 100644 --- a/src/execline/eltest.c +++ b/src/execline/eltest.c @@ -11,7 +11,7 @@ #include #include -enum opnum +enum eltest_opnum_e { T_NOT, T_AND, @@ -58,25 +58,25 @@ enum opnum T_MATCH } ; -struct token +struct eltest_token_s { char const *string ; - enum opnum op ; + enum eltest_opnum_e op ; unsigned int type ; } ; -struct node +struct eltest_node_s { - enum opnum op ; + enum eltest_opnum_e op ; unsigned int type ; unsigned int arg1 ; unsigned int arg2 ; char const *data ; } ; -static unsigned int eltest_lex (struct node *tree, char const *const *argv) +static unsigned int eltest_lex (struct eltest_node_s *tree, char const *const *argv) { - static struct token const tokens[46] = + static struct eltest_token_s const tokens[46] = { { "-n", T_NONZERO, 2 }, { "-z", T_ZERO, 2 }, @@ -149,7 +149,7 @@ static unsigned int eltest_lex (struct node *tree, char const *const *argv) return pos ; } -static unsigned int eltest_parse (struct node *tree, unsigned int n) +static unsigned int eltest_parse (struct eltest_node_s *tree, unsigned int n) { static char const table[9][13] = { @@ -278,7 +278,7 @@ static unsigned int eltest_parse (struct node *tree, unsigned int n) return stack[1] ; } -static int eltest_run (struct node const *tree, unsigned int root) +static int eltest_run (struct eltest_node_s const *tree, unsigned int root) { switch (tree[root].op) { @@ -498,7 +498,7 @@ errorint: int main (int argc, char const *const *argv) { - struct node tree[argc+2] ; + struct eltest_node_s tree[argc+2] ; if (argc <= 1) return 1 ; PROG = "eltest" ; return !eltest_run(tree, eltest_parse(tree, eltest_lex(tree, argv+1))) ; diff --git a/src/execline/envfile.c b/src/execline/envfile.c index 3b95c54..100e1ee 100644 --- a/src/execline/envfile.c +++ b/src/execline/envfile.c @@ -19,7 +19,7 @@ #define dieusage() strerr_dieusage(100, USAGE) #define dienomem() strerr_diefu1sys(111, "stralloc_catb") -static void scanoct (stralloc *sa, size_t pos) +static void envfile_scanoct (stralloc *sa, size_t pos) { unsigned int u ; if (!stralloc_0(sa)) dienomem() ; @@ -28,7 +28,7 @@ static void scanoct (stralloc *sa, size_t pos) sa->len = pos+1 ; } -static inline uint8_t cclass (char c) +static inline uint8_t envfile_cclass (char c) { switch (c) { @@ -75,7 +75,7 @@ static inline uint8_t cclass (char c) } } -static inline char next (char const *file, buffer *b) +static inline char envfile_next (char const *file, buffer *b) { char c ; ssize_t r = buffer_get(b, &c, 1) ; @@ -84,7 +84,7 @@ static inline char next (char const *file, buffer *b) return c ; } -static inline void parse_config (char const *file, buffer *b, stralloc *sa) +static inline void envfile_parse_config (char const *file, buffer *b, stralloc *sa) { static uint16_t const table[14][14] = { @@ -108,10 +108,10 @@ static inline void parse_config (char const *file, buffer *b, stralloc *sa) uint8_t state = 0 ; while (state < 14) { - char c = next(file, b) ; - uint16_t what = table[state][cclass(c)] ; + char c = envfile_next(file, b) ; + uint16_t what = table[state][envfile_cclass(c)] ; state = what & 0x0f ; - if (what & 0x0400) scanoct(sa, mark) ; + if (what & 0x0400) envfile_scanoct(sa, mark) ; if (what & 0x0100) mark = sa->len ; if (what & 0x1000) c = 7 + byte_chr("abtnvfr", 7, c) ; if (what & 0x0010) if (!stralloc_catb(sa, &c, 1)) dienomem() ; @@ -123,7 +123,7 @@ static inline void parse_config (char const *file, buffer *b, stralloc *sa) sa->s[sa->len-2] = (fmtscan_num(sa->s[sa->len-2], 16) << 4) + fmtscan_num(sa->s[sa->len-1], 16) ; sa->len-- ; } - if (what & 0x0800) scanoct(sa, mark) ; + if (what & 0x0800) envfile_scanoct(sa, mark) ; } if (state > 14) { @@ -177,7 +177,7 @@ int main (int argc, char const *const *argv) buffer b ; char buf[BUFFER_INSIZE] ; buffer_init(&b, &buffer_read, fd, buf, BUFFER_INSIZE) ; - parse_config(name, &b, &modif) ; + envfile_parse_config(name, &b, &modif) ; fd_close(fd) ; } xmexec_m(argv + 1, modif.s, modif.len) ; diff --git a/src/execline/fdreserve.c b/src/execline/fdreserve.c index 15ee25a..5d18377 100644 --- a/src/execline/fdreserve.c +++ b/src/execline/fdreserve.c @@ -12,7 +12,7 @@ #define MAXFDS 1024 -unsigned int doit (char *modif, unsigned int i, int fd) +unsigned int fdreserve_doit (char *modif, unsigned int i, int fd) { unsigned int pos = 2 ; modif[0] = 'F' ; modif[1] = 'D' ; @@ -49,14 +49,14 @@ int main (int argc, char const *const *argv) if (lastfd < 0) strerr_diefu1sys(111, "reserve last fd") ; fd_close(lastfd) ; - j += doit(modif + j, n-1, lastfd) ; + j += fdreserve_doit(modif + j, n-1, lastfd) ; } for (i = 0 ; i < (n>>1) ; i++) { fd_close(fd[i][0]) ; fd_close(fd[i][1]) ; - j += doit(modif + j, i<<1, fd[i][0]) ; - j += doit(modif + j, (i<<1)|1, fd[i][1]) ; + j += fdreserve_doit(modif + j, i<<1, fd[i][0]) ; + j += fdreserve_doit(modif + j, (i<<1)|1, fd[i][1]) ; } } xmexec_n(argv+2, modif, j, n) ; diff --git a/src/execline/forstdin.c b/src/execline/forstdin.c index e365866..b023640 100644 --- a/src/execline/forstdin.c +++ b/src/execline/forstdin.c @@ -19,7 +19,7 @@ #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 forstdin_pids = GENALLOC_ZERO ; /* pid_t */ +static genalloc *forstdin_pids_p = 0 ; /* minimize bss/data */ static int fs_isok (unsigned short *tab, unsigned int n, int code) { @@ -30,8 +30,8 @@ static int fs_isok (unsigned short *tab, unsigned int n, int code) static void parallel_sigchld_handler (int sig) { - pid_t *tab = genalloc_s(pid_t, &forstdin_pids) ; - size_t len = genalloc_len(pid_t, &forstdin_pids) ; + pid_t *tab = genalloc_s(pid_t, forstdin_pids_p) ; + size_t len = genalloc_len(pid_t, forstdin_pids_p) ; int wstat ; for (;;) { @@ -39,12 +39,13 @@ static void parallel_sigchld_handler (int sig) if (r <= 0) break ; tab[r-1] = tab[--len] ; } - genalloc_setlen(pid_t, &forstdin_pids, len) ; + genalloc_setlen(pid_t, forstdin_pids_p, len) ; (void)sig ; } int main (int argc, char const **argv) { + genalloc pids = GENALLOC_ZERO ; stralloc value = STRALLOC_ZERO ; char const *delim = "\n" ; size_t delimlen = 1 ; @@ -52,6 +53,8 @@ int main (int argc, char const **argv) unsigned short okcodes[256] ; int crunch = 0, chomp = 1, not = 1, eofcode = 1, doimport = 0 ; PROG = "forstdin" ; + forstdin_pids_p = &pids ; + { subgetopt l = SUBGETOPT_ZERO ; for (;;) @@ -62,7 +65,7 @@ int main (int argc, char const **argv) { case 'p' : { - if (!genalloc_ready(pid_t, &forstdin_pids, 1)) + if (!genalloc_ready(pid_t, &pids, 1)) strerr_diefu1sys(111, "genalloc_ready") ; break ; } @@ -90,7 +93,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 (forstdin_pids.s) + if (pids.s) { if (!sig_catch(SIGCHLD, ¶llel_sigchld_handler)) strerr_diefu1sys(111, "install SIGCHLD handler") ; @@ -122,12 +125,12 @@ int main (int argc, char const **argv) } eofcode = 0 ; if (!stralloc_0(&value)) strerr_diefu1sys(111, "stralloc_0") ; - if (forstdin_pids.s) sig_block(SIGCHLD) ; + 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 (forstdin_pids.s) + if (pids.s) { - if (!genalloc_append(pid_t, &forstdin_pids, &pid)) + if (!genalloc_append(pid_t, &pids, &pid)) strerr_diefu1sys(111, "genalloc_append") ; sig_unblock(SIGCHLD) ; } @@ -140,14 +143,14 @@ int main (int argc, char const **argv) return wait_estatus(wstat) ; } } - if (forstdin_pids.s) + if (pids.s) { sigset_t empty ; sigemptyset(&empty) ; sig_block(SIGCHLD) ; for (;;) { - if (!forstdin_pids.len) break ; + if (!pids.len) break ; sigsuspend(&empty) ; } } diff --git a/src/execline/multisubstitute.c b/src/execline/multisubstitute.c index 7e1eb91..da4e222 100644 --- a/src/execline/multisubstitute.c +++ b/src/execline/multisubstitute.c @@ -7,28 +7,26 @@ #define USAGE "see http://skarnet.org/software/execline/multisubstitute.html" -static char const *const commands[] = -{ - "define", - "importas", - "elglob", - "elgetpositionals", - "multidefine", - 0 -} ; - -static exls_func_ref const functions[] = -{ - &exlsn_define, - &exlsn_importas, - &exlsn_elglob, - &exlsn_exlp, - &exlsn_multidefine, - 0 -} ; - int main (int argc, char const **argv, char const *const *envp) { + static char const *const commands[] = + { + "define", + "importas", + "elglob", + "elgetpositionals", + "multidefine", + 0 + } ; + static exls_func_ref const functions[] = + { + &exlsn_define, + &exlsn_importas, + &exlsn_elglob, + &exlsn_exlp, + &exlsn_multidefine, + 0 + } ; exlsn_t info = EXLSN_ZERO ; int argc1 ; PROG = "multisubstitute" ; diff --git a/src/execline/posix-cd.c b/src/execline/posix-cd.c new file mode 100644 index 0000000..e9bfd35 --- /dev/null +++ b/src/execline/posix-cd.c @@ -0,0 +1,160 @@ +/* ISC license. */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "posix-cd [ -L | -P ] [ - | path ] [ prog... ]" +#define dieusage() strerr_dieusage(100, USAGE) +#define dienomem() strerr_diefu1sys(111, "stralloc_catb") + +int main (int argc, char const **argv) +{ + int phy = 0 ; + int dopwd = 0 ; + char const *where ; + int got = 0 ; + stralloc sa = STRALLOC_ZERO ; + PROG = "posix-cd" ; + setlocale(LC_ALL, "") ; /* yeah, as if */ + + { + subgetopt l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "LP", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'L' : phy = 0 ; break ; + case 'P' : phy = 1 ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) where = getenv("HOME") ; + else + { + where = *argv++ ; + if (!strcmp(where, "-")) + { + where = getenv("OLDPWD") ; + dopwd = 1 ; + } + } + if (!where || !where[0]) dieusage() ; + + if (!(where[0] == '/' || (where[0] == '.' && (!where[1] || where[1] == '/' || (where[1] == '.' && (!where[2] || where[2] == '/')))))) + { + char const *cdpath = getenv("CDPATH") ; + if (cdpath) + { + size_t pos = 0 ; + size_t len = strlen(cdpath) ; + while (pos < len) + { + struct stat st ; + size_t m = byte_chr(cdpath + pos, len - pos, ':') ; + sa.len = 0 ; + if (m) + { + if (!stralloc_catb(&sa, cdpath + pos, m)) dienomem() ; + if (cdpath[pos + m - 1] != '/' && !stralloc_catb(&sa, "/", 1)) dienomem() ; + } + else if (!stralloc_catb(&sa, "./", 2)) dienomem() ; + if (!stralloc_cats(&sa, where) || !stralloc_0(&sa)) dienomem() ; + if (!stat(sa.s, &st) && S_ISDIR(st.st_mode)) + { + got = 1 ; + dopwd = 1 ; + break ; + } + pos += m+1 ; + } + } + } + + if (!got && (!stralloc_cats(&sa, where) || !stralloc_0(&sa))) dienomem() ; + + { + size_t sabase = sa.len ; + if (sagetcwd(&sa) < 0) strerr_diefu1sys(111, "getcwd") ; + if (!stralloc_0(&sa)) dienomem() ; + if (!env_mexec("OLDPWD", sa.s + sabase)) dienomem() ; + sa.len = sabase ; + } + + if (!phy) + { + char const *x = getenv("PWD") ; + if (x && sa.s[0] != '/') + { + size_t len = strlen(x) ; + int doslash = len && x[len-1] != '/' ; + if (!stralloc_insertb(&sa, 0, x, len + doslash)) dienomem() ; + if (doslash) sa.s[len] = '/' ; + } + { + stralloc tmp = STRALLOC_ZERO ; + if (!stralloc_ready(&tmp, sa.len + 2)) dienomem() ; + tmp.len = path_canonicalize(tmp.s, sa.s, 1) ; + if (!tmp.len++) + strerr_diefu4sys(111, "canonicalize ", sa.s, ": problem with ", tmp.s) ; + stralloc_free(&sa) ; + sa = tmp ; + } + if (!env_mexec("PWD", sa.s)) dienomem() ; +#ifdef PATH_MAX + if (sa.len > PATH_MAX && strlen(where) < PATH_MAX && x && *x) + { + size_t len = strlen(x) ; + int hasslash = x[len-1] == '/' ; + if (!strncmp(sa.s, x, len)) + { + if (hasslash || (sa.len > len && sa.s[len] == '/')) + { + sa.len -= len + !hasslash ; + memmove(sa.s, sa.s + len + !hasslash, sa.len) ; + } + } + } +#endif + } + + /* fking finally */ + + if (chdir(sa.s) < 0) + strerr_diefu2sys(111, "chdir to ", where) ; + + /* and there's still more nonsense to do afterwards! */ + + if (phy) + { + sa.len = 0 ; + if (sagetcwd(&sa) < 0) strerr_diefu1sys(111, "getcwd") ; + if (!stralloc_0(&sa)) dienomem() ; + if (!env_mexec("PWD", sa.s)) dienomem() ; + } + + if (dopwd) + { + sa.s[sa.len - 1] = '\n' ; + if (allwrite(1, sa.s, sa.len) < sa.len) + strerr_diefu1sys(111, "write to stdout") ; + } + + xmexec0(argv) ; +} diff --git a/src/execline/posix-umask.c b/src/execline/posix-umask.c new file mode 100644 index 0000000..69f4b08 --- /dev/null +++ b/src/execline/posix-umask.c @@ -0,0 +1,174 @@ +/* ISC license. */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define USAGE "posix-umask [ -S ] [ mask ] [ prog... ]" +#define dieusage() strerr_dieusage(100, USAGE) +#define dieout() strerr_diefu1sys(111, "write to stdout") + + + /* well, unlike posix-cd, at least this one was fun to write */ + +static inline int pu_output (int sym) +{ + mode_t mode = umask(0) ; + size_t m = 0 ; + char fmt[18] ; + if (sym) + { + unsigned int i = 3 ; + while (i--) + { + unsigned int mask = ~(mode >> (3*i)) ; + fmt[m++] = "ogu"[i] ; fmt[m++] = '=' ; + if (mask & 4) fmt[m++] = 'r' ; + if (mask & 2) fmt[m++] = 'w' ; + if (mask & 1) fmt[m++] = 'x' ; + if (i) fmt[m++] = ',' ; + } + } + else m += uint0_ofmt(fmt, mode, 4) ; + fmt[m++] = '\n' ; + if (buffer_putflush(buffer_1, fmt, m) < 0) dieout() ; + return 0 ; +} + +static void pu_diesyntax (char const *) gccattr_noreturn ; +static void pu_diesyntax (char const *s) +{ + strerr_dief3x(101, "internal parsing error: bad ", s, ". Please submit a bug-report.") ; +} + +static inline uint8_t pu_cclass (char c) +{ + /* char tables may be more efficient, but this is way more readable */ + switch (c) + { + case 0 : return 0 ; + case ',' : return 1 ; + case '+' : + case '-' : + case '=' : return 2 ; + case 'u' : + case 'g' : + case 'o' : return 3 ; + case 'a' : return 4 ; + case 'r' : + case 'w' : + case 'x' : + case 'X' : + case 's' : + case 't' : return 5 ; + default : return 6 ; + } +} + +static inline uint8_t pu_who_value (char c) +{ + switch (c) + { + case 'u' : return 4 ; + case 'g' : return 2 ; + case 'o' : return 1 ; + case 'a' : + case '+' : /* shortcut for when who is empty */ + case '-' : + case '=' : return 7 ; + default : pu_diesyntax("who") ; + } +} + +static inline uint8_t pu_perm_value (char c) +{ + switch (c) + { + case 'r' : return 4 ; + case 'w' : return 2 ; + case 'x' : + case 'X' : return 1 ; + case 's' : + case 't' : return 0 ; + default : pu_diesyntax("perm") ; + } +} + +static inline unsigned int pu_parsemode (char const *s) +{ + static uint16_t const table[5][7] = + { + { 0x005, 0x000, 0x064, 0x021, 0x021, 0x006, 0x006 }, + { 0x005, 0x006, 0x042, 0x021, 0x021, 0x006, 0x006 }, + { 0x005, 0x200, 0x042, 0x083, 0x006, 0x104, 0x006 }, + { 0x805, 0xe00, 0xc42, 0x006, 0x006, 0x006, 0x006 }, + { 0x805, 0xe00, 0xc42, 0x006, 0x006, 0x104, 0x006 } + } ; + unsigned int oldmode = ~umask(0) ; + uint8_t modes[3] = { oldmode & 7, (oldmode >> 3) & 7, (oldmode >> 6) & 7 } ; + uint8_t who = 0 ; + uint8_t perm = 0 ; + uint8_t state = 0 ; + char op = 0 ; + while (state < 5) + { + char c = *s++ ; + uint16_t what = table[state][pu_cclass(c)] ; + state = what & 7 ; + if (what & 0x020) who |= pu_who_value(c) ; + if (what & 0x080) perm = modes[byte_chr("ogu", 3, c)] ; + if (what & 0x100) perm |= pu_perm_value(c) ; + if (what & 0x800) + { + unsigned int i = 3 ; + while (i--) if (who & (1 << i)) + switch (op) + { + case '-' : modes[i] &= ~perm ; break ; + case '+' : modes[i] |= perm ; break ; + case '=' : modes[i] = perm ; break ; + default : pu_diesyntax("op") ; + } + } + if (what & 0x040) op = c ; + if (what & 0x200) who = 0 ; + if (what & 0x400) perm = 0 ; + } + if (state > 5) strerr_dief1x(1, "invalid mode string") ; + return ((unsigned int)modes[2] << 6) | ((unsigned int)modes[1] << 3) | modes[0] ; +} + +int main (int argc, char const **argv) +{ + int sym = 0 ; + unsigned int mode ; + PROG = "posix-umask" ; + setlocale(LC_ALL, "") ; /* totally supported, I swear */ + + { + subgetopt l = SUBGETOPT_ZERO ; + for (;;) + { + int opt = subgetopt_r(argc, argv, "S", &l) ; + if (opt == -1) break ; + switch (opt) + { + case 'S' : sym = 1 ; break ; + default : dieusage() ; + } + } + argc -= l.ind ; argv += l.ind ; + } + if (!argc) return pu_output(sym) ; + if (!uint0_oscan(argv[0], &mode)) mode = ~pu_parsemode(argv[0]) ; + umask(mode & 00777) ; + xexec0(argv+1) ; +} diff --git a/src/execline/posix-umask.txt b/src/execline/posix-umask.txt new file mode 100644 index 0000000..5bf49a2 --- /dev/null +++ b/src/execline/posix-umask.txt @@ -0,0 +1,37 @@ + + parsemode() function for posix-umask + + goal: parse the "u+r,g-wx,o=u" symbolic mode string and convert it +to a numeric value suitable for umask(). + In the purest skarnet.org tradition, we implement the parser via a DFA. + +class | 0 1 2 3 4 5 6 +st\ev | \0 , +-= ugo a rwxXst other +------------------------------------------------------------------------ +START | wo w w +0 | END START OP WHO WHO X X + +WHO | o w w +1 | END X OP WHO WHO X X + +OP | r o c p +2 | END START OP PERMCPY X PERM X + +PERMCPY | ! !rR !Ro +3 | END START OP X X X X + +PERM | ! !rR !Ro p +4 | END START OP X X PERM X +------------------------------------------------------------------------ + +END=5, X=6. -> states: 3 bits +7 actions -> 10 bits total, need uint16_t + + w: 0x020: who |= c + o: 0x040: store op + c: 0x080: copy perm from c + p: 0x100: perm |= c + r: 0x200: reset who + R: 0x400: reset perm + !: 0x800: apply (who, op, perm) change + diff --git a/src/execline/trap.c b/src/execline/trap.c index 630f865..52541ca 100644 --- a/src/execline/trap.c +++ b/src/execline/trap.c @@ -20,34 +20,33 @@ #define USAGE "trap [ -x ] { signal { cmdline } ... } prog..." #define dieusage() strerr_dieusage(100, USAGE) ; -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) +static inline void trap_action (unsigned int i, char const *const *envp, size_t envlen, pid_t *pids, char const *const **argvs) { - if (trap_argvs[i]) + if (argvs[i]) { - if (!trap_pids[i]) + if (!pids[i]) { char const *newenvp[envlen + 3] ; char modif[9 + PID_FMT + UINT_FMT] = "!=" ; size_t m = 2 ; - m += pid_fmt(modif + m, trap_pids[SKALIBS_NSIG]) ; + m += pid_fmt(modif + m, 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") ; - 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]) ; + pids[i] = child_spawn0(argvs[i][0], argvs[i], newenvp) ; + if (!pids[i]) strerr_diefu2sys(111, "spawn ", argvs[i][0]) ; } } - else kill(trap_pids[SKALIBS_NSIG], i) ; + else kill(pids[SKALIBS_NSIG], i) ; } int main (int argc, char const **argv, char const *const *envp) { + pid_t pids[SKALIBS_NSIG + 1] ; + char const *const *argvs[SKALIBS_NSIG] = { 0 } ; size_t envlen = env_len(envp) ; iopause_fd x = { .events = IOPAUSE_READ } ; sigset_t full, set ; @@ -89,10 +88,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 (trap_argvs[sig]) + if (argvs[sig]) strerr_dief3x(100, "duplicate", " directive: ", argv[i-1]) ; if (!sig || (sig != SIGCHLD && sigismember(&full, sig) > 0)) - trap_argvs[sig] = argv + i ; + argvs[sig] = argv + i ; else { char fmt[UINT_FMT] ; @@ -103,10 +102,10 @@ int main (int argc, char const **argv, char const *const *envp) i += argc2 + 1 ; } - if (trap_argvs[0]) + if (argvs[0]) for (i = 1 ; i < SKALIBS_NSIG ; i++) - if (!trap_argvs[i] && sigismember(&full, i) > 0) - trap_argvs[i] = trap_argvs[0] ; + if (!argvs[i] && sigismember(&full, i) > 0) + argvs[i] = argvs[0] ; if (xfersigs) set = full ; else @@ -114,7 +113,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 (trap_argvs[i]) + if (argvs[i]) sigaddset(&set, i) ; } @@ -122,8 +121,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") ; - 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]) ; + pids[SKALIBS_NSIG] = child_spawn0(argv[argc1 + 1], argv + argc1 + 1, envp) ; + if (!pids[SKALIBS_NSIG]) strerr_diefu2sys(111, "spawn ", argv[argc1 + 1]) ; loop: if (iopause_g(&x, 1, 0) < 0) strerr_diefu1sys(111, "iopause") ; @@ -138,16 +137,16 @@ int main (int argc, char const **argv, char const *const *envp) for (;;) { int wstat ; - ssize_t id = wait_pids_nohang(trap_pids, SKALIBS_NSIG + 1, &wstat) ; + ssize_t id = wait_pids_nohang(pids, SKALIBS_NSIG + 1, &wstat) ; if (id < 0 && errno != ECHILD) strerr_diefu1sys(111, "wait") ; if (id <= 0) break ; - trap_pids[id - 1] = 0 ; + pids[id - 1] = 0 ; if (id == SKALIBS_NSIG + 1) return wait_estatus(wstat) ; } break ; default : - action(r, envp, envlen) ; + trap_action(r, envp, envlen, pids, argvs) ; } } } diff --git a/src/posix/deps-exe/posix-cd b/src/posix/deps-exe/posix-cd deleted file mode 100644 index e7187fe..0000000 --- a/src/posix/deps-exe/posix-cd +++ /dev/null @@ -1 +0,0 @@ --lskarnet diff --git a/src/posix/deps-exe/posix-umask b/src/posix/deps-exe/posix-umask deleted file mode 100644 index e7187fe..0000000 --- a/src/posix/deps-exe/posix-umask +++ /dev/null @@ -1 +0,0 @@ --lskarnet diff --git a/src/posix/posix-cd.c b/src/posix/posix-cd.c deleted file mode 100644 index e9bfd35..0000000 --- a/src/posix/posix-cd.c +++ /dev/null @@ -1,160 +0,0 @@ -/* ISC license. */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define USAGE "posix-cd [ -L | -P ] [ - | path ] [ prog... ]" -#define dieusage() strerr_dieusage(100, USAGE) -#define dienomem() strerr_diefu1sys(111, "stralloc_catb") - -int main (int argc, char const **argv) -{ - int phy = 0 ; - int dopwd = 0 ; - char const *where ; - int got = 0 ; - stralloc sa = STRALLOC_ZERO ; - PROG = "posix-cd" ; - setlocale(LC_ALL, "") ; /* yeah, as if */ - - { - subgetopt l = SUBGETOPT_ZERO ; - for (;;) - { - int opt = subgetopt_r(argc, argv, "LP", &l) ; - if (opt == -1) break ; - switch (opt) - { - case 'L' : phy = 0 ; break ; - case 'P' : phy = 1 ; break ; - default : dieusage() ; - } - } - argc -= l.ind ; argv += l.ind ; - } - if (!argc) where = getenv("HOME") ; - else - { - where = *argv++ ; - if (!strcmp(where, "-")) - { - where = getenv("OLDPWD") ; - dopwd = 1 ; - } - } - if (!where || !where[0]) dieusage() ; - - if (!(where[0] == '/' || (where[0] == '.' && (!where[1] || where[1] == '/' || (where[1] == '.' && (!where[2] || where[2] == '/')))))) - { - char const *cdpath = getenv("CDPATH") ; - if (cdpath) - { - size_t pos = 0 ; - size_t len = strlen(cdpath) ; - while (pos < len) - { - struct stat st ; - size_t m = byte_chr(cdpath + pos, len - pos, ':') ; - sa.len = 0 ; - if (m) - { - if (!stralloc_catb(&sa, cdpath + pos, m)) dienomem() ; - if (cdpath[pos + m - 1] != '/' && !stralloc_catb(&sa, "/", 1)) dienomem() ; - } - else if (!stralloc_catb(&sa, "./", 2)) dienomem() ; - if (!stralloc_cats(&sa, where) || !stralloc_0(&sa)) dienomem() ; - if (!stat(sa.s, &st) && S_ISDIR(st.st_mode)) - { - got = 1 ; - dopwd = 1 ; - break ; - } - pos += m+1 ; - } - } - } - - if (!got && (!stralloc_cats(&sa, where) || !stralloc_0(&sa))) dienomem() ; - - { - size_t sabase = sa.len ; - if (sagetcwd(&sa) < 0) strerr_diefu1sys(111, "getcwd") ; - if (!stralloc_0(&sa)) dienomem() ; - if (!env_mexec("OLDPWD", sa.s + sabase)) dienomem() ; - sa.len = sabase ; - } - - if (!phy) - { - char const *x = getenv("PWD") ; - if (x && sa.s[0] != '/') - { - size_t len = strlen(x) ; - int doslash = len && x[len-1] != '/' ; - if (!stralloc_insertb(&sa, 0, x, len + doslash)) dienomem() ; - if (doslash) sa.s[len] = '/' ; - } - { - stralloc tmp = STRALLOC_ZERO ; - if (!stralloc_ready(&tmp, sa.len + 2)) dienomem() ; - tmp.len = path_canonicalize(tmp.s, sa.s, 1) ; - if (!tmp.len++) - strerr_diefu4sys(111, "canonicalize ", sa.s, ": problem with ", tmp.s) ; - stralloc_free(&sa) ; - sa = tmp ; - } - if (!env_mexec("PWD", sa.s)) dienomem() ; -#ifdef PATH_MAX - if (sa.len > PATH_MAX && strlen(where) < PATH_MAX && x && *x) - { - size_t len = strlen(x) ; - int hasslash = x[len-1] == '/' ; - if (!strncmp(sa.s, x, len)) - { - if (hasslash || (sa.len > len && sa.s[len] == '/')) - { - sa.len -= len + !hasslash ; - memmove(sa.s, sa.s + len + !hasslash, sa.len) ; - } - } - } -#endif - } - - /* fking finally */ - - if (chdir(sa.s) < 0) - strerr_diefu2sys(111, "chdir to ", where) ; - - /* and there's still more nonsense to do afterwards! */ - - if (phy) - { - sa.len = 0 ; - if (sagetcwd(&sa) < 0) strerr_diefu1sys(111, "getcwd") ; - if (!stralloc_0(&sa)) dienomem() ; - if (!env_mexec("PWD", sa.s)) dienomem() ; - } - - if (dopwd) - { - sa.s[sa.len - 1] = '\n' ; - if (allwrite(1, sa.s, sa.len) < sa.len) - strerr_diefu1sys(111, "write to stdout") ; - } - - xmexec0(argv) ; -} diff --git a/src/posix/posix-umask.c b/src/posix/posix-umask.c deleted file mode 100644 index 8785bed..0000000 --- a/src/posix/posix-umask.c +++ /dev/null @@ -1,174 +0,0 @@ -/* ISC license. */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define USAGE "posix-umask [ -S ] [ mask ] [ prog... ]" -#define dieusage() strerr_dieusage(100, USAGE) -#define dieout() strerr_diefu1sys(111, "write to stdout") - - - /* well, unlike posix-cd, at least this one was fun to write */ - -static inline int output (int sym) -{ - mode_t mode = umask(0) ; - size_t m = 0 ; - char fmt[18] ; - if (sym) - { - unsigned int i = 3 ; - while (i--) - { - unsigned int mask = ~(mode >> (3*i)) ; - fmt[m++] = "ogu"[i] ; fmt[m++] = '=' ; - if (mask & 4) fmt[m++] = 'r' ; - if (mask & 2) fmt[m++] = 'w' ; - if (mask & 1) fmt[m++] = 'x' ; - if (i) fmt[m++] = ',' ; - } - } - else m += uint0_ofmt(fmt, mode, 4) ; - fmt[m++] = '\n' ; - if (buffer_putflush(buffer_1, fmt, m) < 0) dieout() ; - return 0 ; -} - -static void diesyntax (char const *) gccattr_noreturn ; -static void diesyntax (char const *s) -{ - strerr_dief3x(101, "internal parsing error: bad ", s, ". Please submit a bug-report.") ; -} - -static inline uint8_t cclass (char c) -{ - /* char tables may be more efficient, but this is way more readable */ - switch (c) - { - case 0 : return 0 ; - case ',' : return 1 ; - case '+' : - case '-' : - case '=' : return 2 ; - case 'u' : - case 'g' : - case 'o' : return 3 ; - case 'a' : return 4 ; - case 'r' : - case 'w' : - case 'x' : - case 'X' : - case 's' : - case 't' : return 5 ; - default : return 6 ; - } -} - -static inline uint8_t who_value (char c) -{ - switch (c) - { - case 'u' : return 4 ; - case 'g' : return 2 ; - case 'o' : return 1 ; - case 'a' : - case '+' : /* shortcut for when who is empty */ - case '-' : - case '=' : return 7 ; - default : diesyntax("who") ; - } -} - -static inline uint8_t perm_value (char c) -{ - switch (c) - { - case 'r' : return 4 ; - case 'w' : return 2 ; - case 'x' : - case 'X' : return 1 ; - case 's' : - case 't' : return 0 ; - default : diesyntax("perm") ; - } -} - -static inline unsigned int parsemode (char const *s) -{ - static uint16_t const table[5][7] = - { - { 0x005, 0x000, 0x064, 0x021, 0x021, 0x006, 0x006 }, - { 0x005, 0x006, 0x042, 0x021, 0x021, 0x006, 0x006 }, - { 0x005, 0x200, 0x042, 0x083, 0x006, 0x104, 0x006 }, - { 0x805, 0xe00, 0xc42, 0x006, 0x006, 0x006, 0x006 }, - { 0x805, 0xe00, 0xc42, 0x006, 0x006, 0x104, 0x006 } - } ; - unsigned int oldmode = ~umask(0) ; - uint8_t modes[3] = { oldmode & 7, (oldmode >> 3) & 7, (oldmode >> 6) & 7 } ; - uint8_t who = 0 ; - uint8_t perm = 0 ; - uint8_t state = 0 ; - char op = 0 ; - while (state < 5) - { - char c = *s++ ; - uint16_t what = table[state][cclass(c)] ; - state = what & 7 ; - if (what & 0x020) who |= who_value(c) ; - if (what & 0x080) perm = modes[byte_chr("ogu", 3, c)] ; - if (what & 0x100) perm |= perm_value(c) ; - if (what & 0x800) - { - unsigned int i = 3 ; - while (i--) if (who & (1 << i)) - switch (op) - { - case '-' : modes[i] &= ~perm ; break ; - case '+' : modes[i] |= perm ; break ; - case '=' : modes[i] = perm ; break ; - default : diesyntax("op") ; - } - } - if (what & 0x040) op = c ; - if (what & 0x200) who = 0 ; - if (what & 0x400) perm = 0 ; - } - if (state > 5) strerr_dief1x(1, "invalid mode string") ; - return ((unsigned int)modes[2] << 6) | ((unsigned int)modes[1] << 3) | modes[0] ; -} - -int main (int argc, char const **argv) -{ - int sym = 0 ; - unsigned int mode ; - PROG = "posix-umask" ; - setlocale(LC_ALL, "") ; /* totally supported, I swear */ - - { - subgetopt l = SUBGETOPT_ZERO ; - for (;;) - { - int opt = subgetopt_r(argc, argv, "S", &l) ; - if (opt == -1) break ; - switch (opt) - { - case 'S' : sym = 1 ; break ; - default : dieusage() ; - } - } - argc -= l.ind ; argv += l.ind ; - } - if (!argc) return output(sym) ; - if (!uint0_oscan(argv[0], &mode)) mode = ~parsemode(argv[0]) ; - umask(mode & 00777) ; - xexec0(argv+1) ; -} diff --git a/src/posix/posix-umask.txt b/src/posix/posix-umask.txt deleted file mode 100644 index 5bf49a2..0000000 --- a/src/posix/posix-umask.txt +++ /dev/null @@ -1,37 +0,0 @@ - - parsemode() function for posix-umask - - goal: parse the "u+r,g-wx,o=u" symbolic mode string and convert it -to a numeric value suitable for umask(). - In the purest skarnet.org tradition, we implement the parser via a DFA. - -class | 0 1 2 3 4 5 6 -st\ev | \0 , +-= ugo a rwxXst other ------------------------------------------------------------------------- -START | wo w w -0 | END START OP WHO WHO X X - -WHO | o w w -1 | END X OP WHO WHO X X - -OP | r o c p -2 | END START OP PERMCPY X PERM X - -PERMCPY | ! !rR !Ro -3 | END START OP X X X X - -PERM | ! !rR !Ro p -4 | END START OP X X PERM X ------------------------------------------------------------------------- - -END=5, X=6. -> states: 3 bits -7 actions -> 10 bits total, need uint16_t - - w: 0x020: who |= c - o: 0x040: store op - c: 0x080: copy perm from c - p: 0x100: perm |= c - r: 0x200: reset who - R: 0x400: reset perm - !: 0x800: apply (who, op, perm) change - -- cgit v1.3.1