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