diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2023-02-02 05:29:17 +0000 |
---|---|---|
committer | Laurent Bercot <ska@appnovation.com> | 2023-02-02 05:29:17 +0000 |
commit | 9d55d49dad0f4cb90e6ff2f9b1c3bc46a6fcf05f (patch) | |
tree | ea63cf6dd496942aa194e864f37cc56229d596fb /src/posix | |
parent | edf81b0d16322e5d49ec22f394b669d9094daac1 (diff) | |
download | execline-9d55d49dad0f4cb90e6ff2f9b1c3bc46a6fcf05f.tar.xz |
Multicall improvements
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src/posix')
-rw-r--r-- | src/posix/deps-exe/posix-cd | 1 | ||||
-rw-r--r-- | src/posix/deps-exe/posix-umask | 1 | ||||
-rw-r--r-- | src/posix/posix-cd.c | 160 | ||||
-rw-r--r-- | src/posix/posix-umask.c | 174 | ||||
-rw-r--r-- | src/posix/posix-umask.txt | 37 |
5 files changed, 0 insertions, 373 deletions
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 <sys/stat.h> -#include <string.h> -#include <unistd.h> -#include <stdlib.h> -#include <limits.h> -#include <locale.h> - -#include <skalibs/bytestr.h> -#include <skalibs/sgetopt.h> -#include <skalibs/allreadwrite.h> -#include <skalibs/strerr.h> -#include <skalibs/stralloc.h> -#include <skalibs/djbunix.h> -#include <skalibs/env.h> -#include <skalibs/exec.h> - -#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 <stdint.h> -#include <sys/stat.h> -#include <locale.h> - -#include <skalibs/gccattributes.h> -#include <skalibs/bytestr.h> -#include <skalibs/types.h> -#include <skalibs/sgetopt.h> -#include <skalibs/buffer.h> -#include <skalibs/strerr.h> -#include <skalibs/exec.h> - -#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 - |