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