1 /* 2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 7 /* All Rights Reserved */ 8 9 /* 10 * Copyright (c) 1980 Regents of the University of California. 11 * All rights reserved. The Berkeley software License Agreement 12 * specifies the terms and conditions for redistribution. 13 */ 14 15 /* 16 * test expression 17 * [ expression ] 18 */ 19 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <unistd.h> 23 #include <sys/types.h> 24 #include <sys/stat.h> 25 #include <string.h> 26 27 #define EQ(a, b) ((strcmp(a, b) == 0)) 28 29 static char *nxtarg(int mt); 30 static int exp(void); 31 static int e1(void); 32 static int e2(void); 33 static int e3(void); 34 static int tio(char *a, int f); 35 static int ftype(char *f, int field); 36 static int filtyp(char *f, int field); 37 static int fsizep(char *f); 38 static void synbad(char *s1, char *s2); 39 40 static int ap; 41 static int ac; 42 static char **av; 43 44 int 45 main(int argc, char *argv[]) 46 { 47 int status; 48 49 ac = argc; av = argv; ap = 1; 50 if (EQ(argv[0], "[")) { 51 if (!EQ(argv[--ac], "]")) 52 synbad("] missing", ""); 53 } 54 argv[ac] = 0; 55 if (ac <= 1) 56 exit(1); 57 status = (exp() ? 0 : 1); 58 if (nxtarg(1) != 0) 59 synbad("too many arguments", ""); 60 return (status); 61 } 62 63 static char * 64 nxtarg(int mt) 65 { 66 if (ap >= ac) { 67 if (mt) { 68 ap++; 69 return (0); 70 } 71 synbad("argument expected", ""); 72 } 73 return (av[ap++]); 74 } 75 76 static int 77 exp(void) 78 { 79 int p1; 80 char *p2; 81 82 p1 = e1(); 83 p2 = nxtarg(1); 84 if (p2 != 0) { 85 if (EQ(p2, "-o")) 86 return (p1 | exp()); 87 if (EQ(p2, "]")) 88 synbad("syntax error", ""); 89 } 90 ap--; 91 return (p1); 92 } 93 94 static int 95 e1(void) 96 { 97 int p1; 98 char *p2; 99 100 p1 = e2(); 101 p2 = nxtarg(1); 102 if ((p2 != 0) && EQ(p2, "-a")) 103 return (p1 & e1()); 104 ap--; 105 return (p1); 106 } 107 108 static int 109 e2(void) 110 { 111 if (EQ(nxtarg(0), "!")) 112 return (!e3()); 113 ap--; 114 return (e3()); 115 } 116 117 static int 118 e3(void) 119 { 120 int p1; 121 char *a; 122 char *p2; 123 int int1, int2; 124 125 a = nxtarg(0); 126 if (EQ(a, "(")) { 127 p1 = exp(); 128 if (!EQ(nxtarg(0), ")")) synbad(") expected", ""); 129 return (p1); 130 } 131 p2 = nxtarg(1); 132 ap--; 133 if ((p2 == 0) || (!EQ(p2, "=") && !EQ(p2, "!="))) { 134 if (EQ(a, "-r")) 135 return (tio(nxtarg(0), 4)); 136 137 if (EQ(a, "-w")) 138 return (tio(nxtarg(0), 2)); 139 140 if (EQ(a, "-x")) 141 return (tio(nxtarg(0), 1)); 142 143 if (EQ(a, "-d")) 144 return (filtyp(nxtarg(0), S_IFDIR)); 145 146 if (EQ(a, "-c")) 147 return (filtyp(nxtarg(0), S_IFCHR)); 148 149 if (EQ(a, "-b")) 150 return (filtyp(nxtarg(0), S_IFBLK)); 151 152 if (EQ(a, "-f")) { 153 struct stat statb; 154 155 return (stat(nxtarg(0), &statb) >= 0 && 156 (statb.st_mode & S_IFMT) != S_IFDIR); 157 } 158 159 if (EQ(a, "-h")) 160 return (filtyp(nxtarg(0), S_IFLNK)); 161 162 if (EQ(a, "-u")) 163 return (ftype(nxtarg(0), S_ISUID)); 164 165 if (EQ(a, "-g")) 166 return (ftype(nxtarg(0), S_ISGID)); 167 168 if (EQ(a, "-k")) 169 return (ftype(nxtarg(0), S_ISVTX)); 170 171 if (EQ(a, "-p")) 172 #ifdef S_IFIFO 173 return (filtyp(nxtarg(0), S_IFIFO)); 174 #else 175 return (nxtarg(0), 0); 176 #endif 177 178 if (EQ(a, "-s")) 179 return (fsizep(nxtarg(0))); 180 181 if (EQ(a, "-t")) 182 if (ap >= ac) 183 return (isatty(1)); 184 else if (EQ((a = nxtarg(0)), "-a") || EQ(a, "-o")) { 185 ap--; 186 return (isatty(1)); 187 } else 188 return (isatty(atoi(a))); 189 190 if (EQ(a, "-n")) 191 return (!EQ(nxtarg(0), "")); 192 if (EQ(a, "-z")) 193 return (EQ(nxtarg(0), "")); 194 } 195 196 p2 = nxtarg(1); 197 if (p2 == 0) 198 return (!EQ(a, "")); 199 if (EQ(p2, "-a") || EQ(p2, "-o")) { 200 ap--; 201 return (!EQ(a, "")); 202 } 203 if (EQ(p2, "=")) 204 return (EQ(nxtarg(0), a)); 205 206 if (EQ(p2, "!=")) 207 return (!EQ(nxtarg(0), a)); 208 209 int1 = atoi(a); 210 int2 = atoi(nxtarg(0)); 211 if (EQ(p2, "-eq")) 212 return (int1 == int2); 213 if (EQ(p2, "-ne")) 214 return (int1 != int2); 215 if (EQ(p2, "-gt")) 216 return (int1 > int2); 217 if (EQ(p2, "-lt")) 218 return (int1 < int2); 219 if (EQ(p2, "-ge")) 220 return (int1 >= int2); 221 if (EQ(p2, "-le")) 222 return (int1 <= int2); 223 224 synbad("unknown operator ", p2); 225 /* NOTREACHED */ 226 return (0); 227 } 228 229 static int 230 tio(char *a, int f) 231 { 232 if (access(a, f) == 0) 233 return (1); 234 else 235 return (0); 236 } 237 238 static int 239 ftype(char *f, int field) 240 { 241 struct stat statb; 242 243 if (stat(f, &statb) < 0) 244 return (0); 245 if ((statb.st_mode & field) == field) 246 return (1); 247 return (0); 248 } 249 250 static int 251 filtyp(char *f, int field) 252 { 253 struct stat statb; 254 255 if (field == S_IFLNK) { 256 if (lstat(f, &statb) < 0) 257 return (0); 258 } else { 259 if (stat(f, &statb) < 0) 260 return (0); 261 } 262 if ((statb.st_mode & S_IFMT) == field) 263 return (1); 264 else 265 return (0); 266 } 267 268 static int 269 fsizep(char *f) 270 { 271 struct stat statb; 272 273 if (stat(f, &statb) < 0) 274 return (0); 275 return (statb.st_size > 0); 276 } 277 278 static void 279 synbad(char *s1, char *s2) 280 { 281 (void) write(2, "test: ", 6); 282 (void) write(2, s1, strlen(s1)); 283 (void) write(2, s2, strlen(s2)); 284 (void) write(2, "\n", 1); 285 exit(255); 286 } 287