test.c (4503B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <errno.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <sys/stat.h> 7 #include <unistd.h> 8 9 #include "util.h" 10 11 static void 12 stoi(char *s, int *a) 13 { 14 char *p; 15 errno = 0; 16 *a = strtol(s, &p, 0); 17 if (errno || !*s || *p) 18 enprintf(2, "bad integer %s\n", s); 19 } 20 21 static int unary_b(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISBLK (buf.st_mode); } 22 static int unary_c(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISCHR (buf.st_mode); } 23 static int unary_d(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISDIR (buf.st_mode); } 24 static int unary_f(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISREG (buf.st_mode); } 25 static int unary_g(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISGID & buf.st_mode ; } 26 static int unary_h(char *s) { struct stat buf; if (lstat(s, &buf)) return 0; return S_ISLNK (buf.st_mode); } 27 static int unary_p(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISFIFO (buf.st_mode); } 28 static int unary_S(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISSOCK (buf.st_mode); } 29 static int unary_s(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return buf.st_size ; } 30 static int unary_u(char *s) { struct stat buf; if ( stat(s, &buf)) return 0; return S_ISUID & buf.st_mode ; } 31 32 static int unary_n(char *s) { return strlen(s); } 33 static int unary_z(char *s) { return !strlen(s); } 34 35 static int unary_e(char *s) { return access(s, F_OK); } 36 static int unary_r(char *s) { return access(s, R_OK); } 37 static int unary_w(char *s) { return access(s, W_OK); } 38 static int unary_x(char *s) { return access(s, X_OK); } 39 40 static int unary_t(char *s) { int fd; stoi(s, &fd); return isatty(fd); } 41 42 static int binary_se(char *s1, char *s2) { return strcmp(s1, s2) == 0; } 43 static int binary_sn(char *s1, char *s2) { return strcmp(s1, s2) != 0; } 44 45 static int binary_eq(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a == b; } 46 static int binary_ne(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a != b; } 47 static int binary_gt(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a > b; } 48 static int binary_ge(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a >= b; } 49 static int binary_lt(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a < b; } 50 static int binary_le(char *s1, char *s2) { int a, b; stoi(s1, &a); stoi(s2, &b); return a <= b; } 51 52 typedef struct { 53 char *name; 54 int (*func)(); 55 } Test; 56 57 static Test unary[] = { 58 { "-b", unary_b }, 59 { "-c", unary_c }, 60 { "-d", unary_d }, 61 { "-e", unary_e }, 62 { "-f", unary_f }, 63 { "-g", unary_g }, 64 { "-h", unary_h }, 65 { "-L", unary_h }, 66 { "-n", unary_n }, 67 { "-p", unary_p }, 68 { "-r", unary_r }, 69 { "-S", unary_S }, 70 { "-s", unary_s }, 71 { "-t", unary_t }, 72 { "-u", unary_u }, 73 { "-w", unary_w }, 74 { "-x", unary_x }, 75 { "-z", unary_z }, 76 77 { NULL, NULL }, 78 }; 79 80 static Test binary[] = { 81 { "=" , binary_se }, 82 { "!=" , binary_sn }, 83 { "-eq", binary_eq }, 84 { "-ne", binary_ne }, 85 { "-gt", binary_gt }, 86 { "-ge", binary_ge }, 87 { "-lt", binary_lt }, 88 { "-le", binary_le }, 89 90 { NULL, NULL }, 91 }; 92 93 static Test * 94 find_test(Test *tests, char *name) 95 { 96 Test *t; 97 98 for (t = tests; t->name; ++t) 99 if (strcmp(t->name, name) == 0) 100 return t; 101 return NULL; 102 } 103 104 static int 105 noarg(char **argv) 106 { 107 return 0; 108 } 109 110 static int 111 onearg(char **argv) 112 { 113 return strlen(argv[0]); 114 } 115 116 static int 117 twoarg(char **argv) 118 { 119 Test *t = find_test(unary, *argv); 120 121 if (strcmp(argv[0], "!") == 0) 122 return !onearg(argv + 1); 123 124 if (t) 125 return t->func(argv[1]); 126 127 return enprintf(2, "bad unary test %s\n", argv[0]), 0; 128 } 129 130 static int 131 threearg(char **argv) 132 { 133 Test *t = find_test(binary, argv[1]); 134 135 if (t) 136 return t->func(argv[0], argv[2]); 137 138 if (strcmp(argv[0], "!") == 0) 139 return !twoarg(argv + 1); 140 141 return enprintf(2, "bad binary test %s\n", argv[1]), 0; 142 } 143 144 static int 145 fourarg(char **argv) 146 { 147 if (strcmp(argv[0], "!") == 0) 148 return !threearg(argv + 1); 149 150 return enprintf(2, "too many arguments\n"), 0; 151 } 152 153 int 154 main(int argc, char **argv) 155 { 156 int (*narg[])(char**) = { noarg, onearg, twoarg, threearg, fourarg }; 157 int len = strlen(argv[0]); 158 159 if (len && argv[0][len - 1] == '[') 160 if (strcmp(argv[--argc], "]") != 0) 161 enprintf(2, "no matching ]\n"); 162 163 --argc; ++argv; 164 165 if (argc > 4) 166 enprintf(2, "too many arguments\n"); 167 168 return !narg[argc](argv); 169 }