Home | History | Annotate | Download | only in pending
      1 /* test.c - evaluate expression
      2  *
      3  * Copyright 2013 Rob Landley <rob (at) landley.net>
      4  *
      5  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html
      6 
      7 USE_TEST(NEWTOY(test, NULL, TOYFLAG_USR|TOYFLAG_BIN))
      8 
      9 config TEST
     10   bool "test"
     11   default n
     12   help
     13     usage: test [-bcdefghLPrSsuwx PATH] [-nz STRING] [-t FD] [X ?? Y]
     14 
     15     Return true or false by performing tests. (With no arguments return false.)
     16 
     17     --- Tests with a single argument (after the option):
     18     PATH is/has:
     19       -b  block device   -f  regular file   -p  fifo           -u  setuid bit
     20       -c  char device    -g  setgid         -r  read bit       -w  write bit
     21       -d  directory      -h  symlink        -S  socket         -x  execute bit
     22       -e  exists         -L  symlink        -s  nonzero size
     23     STRING is:
     24       -n  nonzero size   -z  zero size      (STRING by itself implies -n)
     25     FD (integer file descriptor) is:
     26       -t  a TTY
     27 
     28     --- Tests with one argument on each side of an operator:
     29     Two strings:
     30       =  are identical	 !=  differ
     31     Two integers:
     32       -eq  equal         -gt  first > second    -lt  first < second
     33       -ne  not equal     -ge  first >= second   -le  first <= second
     34 
     35     --- Modify or combine tests:
     36       ! EXPR     not (swap true/false)   EXPR -a EXPR    and (are both true)
     37       ( EXPR )   evaluate this first     EXPR -o EXPR    or (is either true)
     38 */
     39 
     40 #include "toys.h"
     41 
     42 void test_main(void)
     43 {
     44   int id, not;
     45   char *s, *err_fmt = "Bad flag '%s'";
     46 
     47   toys.exitval = 2;
     48   if (!strcmp("[", toys.which->name))
     49     if (!strcmp("]", toys.optargs[--toys.optc])) error_exit("Missing ']'");
     50   if (!strcmp("!", toys.optargs[0])) {
     51     not = 1;
     52     toys.optargs++;
     53     toys.optc--;
     54   }
     55   if (!toys.optc) toys.exitval = 0;
     56   else if (toys.optargs[0][0] == '-') {
     57     id = stridx("bcdefghLpSsurwxznt", toys.optargs[0][1]);
     58     if (id == -1 || toys.optargs[0][2]) error_exit(err_fmt, toys.optargs[0]);
     59     if (id < 12) {
     60       struct stat st;
     61       int nolink;
     62 
     63       toys.exitval = 1;
     64       if (lstat(toys.optargs[1], &st) == -1) return;
     65       nolink = !S_ISLNK(st.st_mode);
     66       if (!nolink && (stat(toys.optargs[1], &st) == -1)) return;
     67 
     68       if (id == 0) toys.exitval = !S_ISBLK(st.st_mode); // b
     69       else if (id == 1) toys.exitval = !S_ISCHR(st.st_mode); // c
     70       else if (id == 2) toys.exitval = !S_ISDIR(st.st_mode); // d
     71       else if (id == 3) toys.exitval = 0; // e
     72       else if (id == 4) toys.exitval = !S_ISREG(st.st_mode); // f
     73       else if (id == 5) toys.exitval = !(st.st_mode & S_ISGID); // g
     74       else if ((id == 6) || (id == 7)) toys.exitval = nolink; // hL
     75       else if (id == 8) toys.exitval = !S_ISFIFO(st.st_mode); // p
     76       else if (id == 9) toys.exitval = !S_ISSOCK(st.st_mode); // S
     77       else if (id == 10) toys.exitval = st.st_size == 0; // s
     78       else toys.exitval = !(st.st_mode & S_ISUID); // u
     79     }
     80     else if (id < 15) // rwx
     81       toys.exitval = access(toys.optargs[1], 1 << (id - 12)) == -1;
     82     else if (id < 17) // zn
     83       toys.exitval = toys.optargs[1] && !*toys.optargs[1] ^ (id - 15);
     84     else { // t
     85       struct termios termios;
     86       toys.exitval = tcgetattr(atoi(toys.optargs[1]), &termios) == -1;
     87     }
     88   }
     89   else if (toys.optc == 1) toys.exitval = *toys.optargs[0] == 0;
     90   else if (toys.optc == 3) {
     91     if (*toys.optargs[1] == '-') {
     92       long a = atol(toys.optargs[0]), b = atol(toys.optargs[2]);
     93 
     94       s = toys.optargs[1] + 1;
     95       if (!strcmp("eq", s)) toys.exitval = a != b;
     96       else if (!strcmp("ne", s)) toys.exitval = a == b;
     97       else if (!strcmp("gt", s)) toys.exitval = a < b;
     98       else if (!strcmp("ge", s)) toys.exitval = a <= b;
     99       else if (!strcmp("lt", s)) toys.exitval = a > b;
    100       else if (!strcmp("le", s)) toys.exitval = a >= b;
    101       else error_exit(err_fmt, toys.optargs[1]);
    102     }
    103     else {
    104       int result = strcmp(toys.optargs[0], toys.optargs[2]);
    105 
    106       s = toys.optargs[1];
    107       if (!strcmp("=", s)) toys.exitval = !!result;
    108       else if (!strcmp("!=", s)) toys.exitval = !result;
    109       else error_exit(err_fmt, toys.optargs[1]);
    110     }
    111   }
    112   toys.exitval ^= not;
    113   return;
    114 }
    115