diff options
Diffstat (limited to 'src/skaembutils/s6-test.c')
-rw-r--r-- | src/skaembutils/s6-test.c | 538 |
1 files changed, 0 insertions, 538 deletions
diff --git a/src/skaembutils/s6-test.c b/src/skaembutils/s6-test.c deleted file mode 100644 index d537619..0000000 --- a/src/skaembutils/s6-test.c +++ /dev/null @@ -1,538 +0,0 @@ -/* ISC license. */ - -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> -#include <stdlib.h> -#include <regex.h> - -#include <skalibs/posixplz.h> -#include <skalibs/types.h> -#include <skalibs/strerr.h> -#include <skalibs/djbunix.h> - -#define USAGE "s6-test expression... or [ expression... ]" - -enum opnum -{ - T_NOT, - T_AND, - T_OR, - T_LEFTP, - T_RIGHTP, - T_BLOCK, - T_CHAR, - T_DIR, - T_EXIST, - T_REGULAR, - T_SGID, - T_SYMLINK, - T_STICKY, - T_NONZERO, - T_FIFO, - T_READABLE, - T_NONZEROFILE, - T_TERM, - T_SUID, - T_WRITABLE, - T_EXECUTABLE, - T_ZERO, - T_EUID, - T_EGID, - T_SOCKET, - T_MODIFIED, - T_NEWER, - T_OLDER, - T_DEVINO, - T_STREQUAL, - T_STRNEQUAL, - T_STRLESSER, - T_STRLESSERE, - T_STRGREATER, - T_STRGREATERE, - T_NUMEQUAL, - T_NUMNEQUAL, - T_NUMGREATER, - T_NUMGREATERE, - T_NUMLESSER, - T_NUMLESSERE, - T_ENV, - T_MATCH -} ; - -struct token -{ - char const *string ; - enum opnum op ; - unsigned int type ; -} ; - -struct node -{ - enum opnum op ; - unsigned int type ; - unsigned int arg1 ; - unsigned int arg2 ; - char const *data ; -} ; - -static unsigned int lex (struct node *tree, char const *const *argv) -{ - static struct token const tokens[46] = - { - { "-n", T_NONZERO, 2 }, - { "-z", T_ZERO, 2 }, - { "=", T_STREQUAL, 3 }, - { "!=", T_STRNEQUAL, 3 }, - { "-eq", T_NUMEQUAL, 3 }, - { "-ne", T_NUMNEQUAL, 3 }, - { "-gt", T_NUMGREATER, 3 }, - { "-ge", T_NUMGREATERE, 3 }, - { "-lt", T_NUMLESSER, 3 }, - { "-le", T_NUMLESSERE, 3 }, - { "-f", T_REGULAR, 2 }, - { "-h", T_SYMLINK, 2 }, - { "-L", T_SYMLINK, 2 }, - { "-e", T_EXIST, 2 }, - { "-k", T_STICKY, 2 }, - { "-a", T_AND, 7 }, - { "-o", T_OR, 8 }, - { "!", T_NOT, 6 }, - { "(", T_LEFTP, 4 }, - { ")", T_RIGHTP, 5 }, - { "-b", T_BLOCK, 2 }, - { "-c", T_CHAR, 2 }, - { "-d", T_DIR, 2 }, - { "-g", T_SGID, 2 }, - { "-p", T_FIFO, 2 }, - { "-r", T_READABLE, 2 }, - { "-s", T_NONZEROFILE, 2 }, - { "-t", T_TERM, 2 }, - { "-u", T_SUID, 2 }, - { "-w", T_WRITABLE, 2 }, - { "-x", T_EXECUTABLE, 2 }, - { "-O", T_EUID, 2 }, - { "-U", T_EUID, 2 }, - { "-G", T_EGID, 2 }, - { "-S", T_SOCKET, 2 }, - { "-N", T_MODIFIED, 2 }, - { "-nt", T_NEWER, 3 }, - { "-ot", T_OLDER, 3 }, - { "-ef", T_DEVINO, 3 }, - { "<", T_STRLESSER, 3 }, - { "<=", T_STRLESSERE, 3 }, - { ">", T_STRGREATER, 3 }, - { ">=", T_STRGREATERE, 3 }, - { "-v", T_ENV, 2 }, - { "=~", T_MATCH, 3 }, - { 0, 0, 0 } - } ; - unsigned int pos = 0 ; - - for (; argv[pos] ; pos++) - { - unsigned int i = 0 ; - tree[pos].data = argv[pos] ; - for (i = 0 ; tokens[i].string ; i++) - if (!strcmp(argv[pos], tokens[i].string)) - { - tree[pos].op = tokens[i].op ; - tree[pos].type = tokens[i].type ; - break ; - } - if (!tokens[i].string) - { - tree[pos].op = T_NONZERO ; - tree[pos].type = 0 ; - tree[pos].arg1 = pos ; - if (*(argv[pos]) == '\\') tree[pos].data++ ; /* better than SUSv3 */ - } - } - return pos ; -} - -static unsigned int parse (struct node *tree, unsigned int n) -{ - static char const table[9][13] = - { - "xssssxsssxxxx", - "xxxxxaxxxxxxx", - "xsxxsxsssxxxx", - "sxxxxxxxxxxxx", - "xsxxsxsssxxxx", - "nxxxxNxxxAOEs", - "xsxxsxsssxxxx", - "nxxxxNxxxAsxx", - "nxxxxNxxxAOsx" - } ; - - unsigned int stack[n+2] ; - unsigned int sp = 0, pos = 0 ; - int cont = 1 ; - - stack[0] = n+1 ; - tree[n].type = 5 ; /* add ) for the final reduce */ - tree[n+1].type = 1 ; /* add EOF */ - - while (cont) - { - switch (table[tree[pos].type][tree[stack[sp]].type]) - { - case 'x' : /* error */ - { - char fmt[UINT_FMT] ; - fmt[uint_fmt(fmt, pos)] = 0 ; - strerr_dief2x(100, "parse error at argument ", fmt) ; - break ; - } - case 'a' : /* accept */ - { - cont = 0 ; - break ; - } - case 's' : /* shift */ - { - stack[++sp] = pos++ ; - break ; - } - case 'n' : /* reduce -> expr without nots, from atom */ - { - switch (tree[stack[sp-1]].type) - { - case 2 : - { - tree[stack[sp-1]].arg1 = stack[sp] ; - sp-- ; - break ; - } - case 3 : - { - tree[stack[sp-1]].arg1 = stack[sp-2] ; - tree[stack[sp-1]].arg2 = stack[sp] ; - stack[sp-2] = stack[sp-1] ; - sp -= 2 ; - break ; - } - /* default : assert: its a zero */ - } - tree[stack[sp]].type = 9 ; - while (tree[stack[sp-1]].type == 6) - { - tree[stack[sp-1]].type = 9 ; - tree[stack[sp-1]].arg1 = stack[sp] ; - sp-- ; - } - break ; - } - case 'N' : /* reduce -> expr without nots, from expr */ - { - if (tree[stack[sp-2]].type != 4) - { - char fmt[UINT_FMT] ; - fmt[uint_fmt(fmt, pos)] = 0 ; - strerr_dief2x(100, "parse error: bad right parenthesis at argument ", fmt) ; - } - stack[sp-2] = stack[sp-1] ; - sp -= 2 ; - tree[stack[sp]].type = 9 ; - while (tree[stack[sp-1]].type == 6) - { - tree[stack[sp-1]].type = 9 ; - tree[stack[sp-1]].arg1 = stack[sp] ; - sp-- ; - } - break ; - } - case 'A' : /* reduce -> exprs without ands */ - { - if (tree[stack[sp-1]].type == 7) - { - tree[stack[sp-1]].arg1 = stack[sp-2] ; - tree[stack[sp-1]].arg2 = stack[sp] ; - stack[sp-2] = stack[sp-1] ; - sp -= 2 ; - } - tree[stack[sp]].type = 10 ; - break ; - } - case 'O' : /* reduce -> expr without ors */ - { - if (tree[stack[sp-1]].type == 8) - { - tree[stack[sp-1]].arg1 = stack[sp-2] ; - tree[stack[sp-1]].arg2 = stack[sp] ; - stack[sp-2] = stack[sp-1] ; - sp -= 2 ; - } - tree[stack[sp]].type = 11 ; - break ; - } - case 'E' : /* reduce -> expr */ - { - tree[stack[sp]].type = 12 ; - break ; - } - default : /* can't happen */ - strerr_dief1x(101, "internal error, please submit a bug-report.") ; - } - } - if (sp != 2) strerr_dief1x(100, "parse error: too many left parentheses") ; - return stack[1] ; -} - -static int run (struct node const *tree, unsigned int root) -{ - switch (tree[root].op) - { - case T_NOT : - return !run(tree, tree[root].arg1) ; - case T_AND : - return run(tree, tree[root].arg1) && run(tree, tree[root].arg2) ; - case T_OR : - return run(tree, tree[root].arg1) || run(tree, tree[root].arg2) ; - case T_EXIST : - { - struct stat st ; - return !stat(tree[tree[root].arg1].data, &st) ; - } - case T_BLOCK : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return S_ISBLK(st.st_mode) ; - } - case T_CHAR : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return S_ISCHR(st.st_mode) ; - } - case T_DIR : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return S_ISDIR(st.st_mode) ; - } - case T_REGULAR : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return S_ISREG(st.st_mode) ; - } - case T_FIFO : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return S_ISFIFO(st.st_mode) ; - } - case T_SOCKET : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return S_ISSOCK(st.st_mode) ; - } - case T_SYMLINK : - { - struct stat st ; - if (lstat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return S_ISLNK(st.st_mode) ; - } - case T_SGID : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return (st.st_mode & S_ISGID) ; - } - case T_SUID : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return (st.st_mode & S_ISUID) ; - } - case T_STICKY : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return (st.st_mode & S_ISVTX) ; - } - case T_NONZEROFILE : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return (st.st_size > 0) ; - } - case T_MODIFIED : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return (st.st_mtime > st.st_atime) ; - } - case T_EUID : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return st.st_uid == geteuid() ; - } - case T_EGID : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - return st.st_gid == getegid() ; - } - case T_READABLE : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - if (st.st_uid == geteuid()) return st.st_mode & S_IRUSR ; - else if (st.st_gid == getegid()) return st.st_mode & S_IRGRP ; - else return st.st_mode & S_IROTH ; - } - case T_WRITABLE : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - if (st.st_uid == geteuid()) return st.st_mode & S_IWUSR ; - else if (st.st_gid == getegid()) return st.st_mode & S_IWGRP ; - else return st.st_mode & S_IWOTH ; - } - case T_EXECUTABLE : - { - struct stat st ; - if (stat(tree[tree[root].arg1].data, &st) == -1) return 0 ; - if (st.st_uid == geteuid()) return st.st_mode & S_IXUSR ; - else if (st.st_gid == getegid()) return st.st_mode & S_IXGRP ; - else return st.st_mode & S_IXOTH ; - } - case T_NEWER : - { - struct stat st1, st2 ; - if (stat(tree[tree[root].arg1].data, &st1) == -1) return 0 ; - if (stat(tree[tree[root].arg2].data, &st2) == -1) return 1 ; - return st1.st_mtime > st2.st_mtime ; - } - case T_OLDER : - { - struct stat st1, st2 ; - if (stat(tree[tree[root].arg1].data, &st1) == -1) return 1 ; - if (stat(tree[tree[root].arg2].data, &st2) == -1) return 0 ; - return st1.st_mtime < st2.st_mtime ; - } - case T_DEVINO : - { - struct stat st1, st2 ; - if (stat(tree[tree[root].arg1].data, &st1) == -1) return 0 ; - if (stat(tree[tree[root].arg2].data, &st2) == -1) return 1 ; - return (st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino) ; - } - case T_TERM : - { - unsigned int fd ; - if (!uint0_scan(tree[tree[root].arg1].data, &fd)) - strerr_dief2x(100, tree[root].data, " requires an integer argument") ; - return isatty(fd) ; - } - case T_NONZERO : - return tree[tree[root].arg1].data[0] ; - case T_ZERO : - return !tree[tree[root].arg1].data[0] ; - case T_STREQUAL : - return !strcmp(tree[tree[root].arg1].data, tree[tree[root].arg2].data) ; - case T_STRNEQUAL : - return !!strcmp(tree[tree[root].arg1].data, tree[tree[root].arg2].data) ; - case T_STRLESSER : - return strcmp(tree[tree[root].arg1].data, tree[tree[root].arg2].data) < 0 ; - case T_STRLESSERE : - return strcmp(tree[tree[root].arg1].data, tree[tree[root].arg2].data) <= 0 ; - case T_STRGREATER : - return strcmp(tree[tree[root].arg1].data, tree[tree[root].arg2].data) > 0 ; - case T_STRGREATERE : - return strcmp(tree[tree[root].arg1].data, tree[tree[root].arg2].data) >= 0 ; - case T_NUMEQUAL : - { - int n1, n2 ; - if (!int_scan(tree[tree[root].arg1].data, &n1) - || !int_scan(tree[tree[root].arg2].data, &n2)) - goto errorint ; - return n1 == n2 ; - } - case T_NUMNEQUAL : - { - int n1, n2 ; - if (!int_scan(tree[tree[root].arg1].data, &n1) - || !int_scan(tree[tree[root].arg2].data, &n2)) - goto errorint ; - return n1 != n2 ; - } - case T_NUMGREATER : - { - int n1, n2 ; - if (!int_scan(tree[tree[root].arg1].data, &n1) - || !int_scan(tree[tree[root].arg2].data, &n2)) - goto errorint ; - return n1 > n2 ; - } - case T_NUMGREATERE : - { - int n1, n2 ; - if (!int_scan(tree[tree[root].arg1].data, &n1) - || !int_scan(tree[tree[root].arg2].data, &n2)) - goto errorint ; - return n1 >= n2 ; - } - case T_NUMLESSER : - { - int n1, n2 ; - if (!int_scan(tree[tree[root].arg1].data, &n1) - || !int_scan(tree[tree[root].arg2].data, &n2)) - goto errorint ; - return n1 < n2 ; - } - case T_NUMLESSERE : - { - int n1, n2 ; - if (!int_scan(tree[tree[root].arg1].data, &n1) - || !int_scan(tree[tree[root].arg2].data, &n2)) - goto errorint ; - return n1 <= n2 ; - } - case T_ENV : - return !!getenv(tree[tree[root].arg1].data) ; - case T_MATCH : - { - regex_t re ; - int r = skalibs_regcomp(&re, tree[tree[root].arg2].data, REG_EXTENDED | REG_NOSUB) ; - if (r) - { - char buf[256] ; - regerror(r, &re, buf, 256) ; - strerr_diefu4x(r == REG_ESPACE ? 111 : 100, "compile ", tree[tree[root].arg2].data, " into a regular expression: ", buf) ; - } - r = regexec(&re, tree[tree[root].arg1].data, 0, 0, 0) ; - regfree(&re) ; - return !r ; - } - default: - strerr_dief1x(101, "operation not implemented") ; - } - -errorint: - strerr_dief2x(100, tree[root].data, " requires integer arguments") ; -} - -int main (int argc, char const *const *argv) -{ - PROG = "s6-test" ; - strerr_warnw1x("this program is now deprecated. Please use execline's eltest instead.") ; - if (argc <= 1) return 1 ; - { - struct node tree[argc + 2] ; - unsigned int n = lex(tree, argv+1) ; - if ((argv[0][0] == '[') && !argv[0][1]) - { - if (n && (!tree[n-1].type) && (tree[n-1].data[0] == ']') && !tree[n-1].data[1]) - n-- ; - else strerr_dief1x(100, "parse error: missing closing bracket") ; - } - return !run(tree, parse(tree, n)) ; - } -} |