1 /* 2 * POSIX standard 3 * test expression 4 * [ expression ] 5 * 6 * Plan 9 additions: 7 * -A file exists and is append-only 8 * -L file exists and is exclusive-use 9 */ 10 11 #include <u.h> 12 #include <libc.h> 13 #define EQ(a,b) ((tmp=a)==0?0:(strcmp(tmp,b)==0)) 14 15 int ap; 16 int ac; 17 char **av; 18 char *tmp; 19 20 void synbad(char *, char *); 21 int fsizep(char *); 22 int isdir(char *); 23 int isreg(char *); 24 int isatty(int); 25 int isint(char *, int *); 26 int hasmode(char *, ulong); 27 int tio(char *, int); 28 int e(void), e1(void), e2(void), e3(void); 29 30 void 31 main(int argc, char *argv[]) 32 { 33 34 ac = argc; av = argv; ap = 1; 35 if(EQ(argv[0],"[")) { 36 if(!EQ(argv[--ac],"]")) 37 synbad("] missing",""); 38 } 39 argv[ac] = 0; 40 if (ac<=1) exits("usage"); 41 exits(e()?0:"false"); 42 } 43 44 char * 45 nxtarg(int mt) 46 { 47 if(ap>=ac){ 48 if(mt){ 49 ap++; 50 return(0); 51 } 52 synbad("argument expected",""); 53 } 54 return(av[ap++]); 55 } 56 57 int 58 nxtintarg(int *pans) 59 { 60 if(ap<ac && isint(av[ap], pans)){ 61 ap++; 62 return 1; 63 } 64 return 0; 65 } 66 67 int 68 e(void) { 69 int p1; 70 71 p1 = e1(); 72 if (EQ(nxtarg(1), "-o")) return(p1 || e()); 73 ap--; 74 return(p1); 75 } 76 77 int 78 e1(void) { 79 int p1; 80 81 p1 = e2(); 82 if (EQ(nxtarg(1), "-a")) return (p1 && e1()); 83 ap--; 84 return(p1); 85 } 86 87 int 88 e2(void) { 89 if (EQ(nxtarg(0), "!")) 90 return(!e2()); 91 ap--; 92 return(e3()); 93 } 94 95 int 96 e3(void) { 97 int p1; 98 char *a; 99 char *p2; 100 int int1, int2; 101 102 a = nxtarg(0); 103 if(EQ(a, "(")) { 104 p1 = e(); 105 if(!EQ(nxtarg(0), ")")) synbad(") expected",""); 106 return(p1); 107 } 108 109 if(EQ(a, "-A")) 110 return(hasmode(nxtarg(0), DMAPPEND)); 111 112 if(EQ(a, "-L")) 113 return(hasmode(nxtarg(0), DMEXCL)); 114 115 if(EQ(a, "-f")) 116 return(isreg(nxtarg(0))); 117 118 if(EQ(a, "-d")) 119 return(isdir(nxtarg(0))); 120 121 if(EQ(a, "-r")) 122 return(tio(nxtarg(0), 4)); 123 124 if(EQ(a, "-w")) 125 return(tio(nxtarg(0), 2)); 126 127 if(EQ(a, "-x")) 128 return(tio(nxtarg(0), 1)); 129 130 if(EQ(a, "-e")) 131 return(tio(nxtarg(0), 0)); 132 133 if(EQ(a, "-c")) 134 return(0); 135 136 if(EQ(a, "-b")) 137 return(0); 138 139 if(EQ(a, "-u")) 140 return(0); 141 142 if(EQ(a, "-g")) 143 return(0); 144 145 if(EQ(a, "-s")) 146 return(fsizep(nxtarg(0))); 147 148 if(EQ(a, "-t")) 149 if(ap>=ac || !nxtintarg(&int1)) 150 return(isatty(1)); 151 else 152 return(isatty(int1)); 153 154 if(EQ(a, "-n")) 155 return(!EQ(nxtarg(0), "")); 156 if(EQ(a, "-z")) 157 return(EQ(nxtarg(0), "")); 158 159 p2 = nxtarg(1); 160 if (p2==0) 161 return(!EQ(a,"")); 162 if(EQ(p2, "=")) 163 return(EQ(nxtarg(0), a)); 164 165 if(EQ(p2, "!=")) 166 return(!EQ(nxtarg(0), a)); 167 168 if(!isint(a, &int1)) 169 return(!EQ(a,"")); 170 171 if(nxtintarg(&int2)){ 172 if(EQ(p2, "-eq")) 173 return(int1==int2); 174 if(EQ(p2, "-ne")) 175 return(int1!=int2); 176 if(EQ(p2, "-gt")) 177 return(int1>int2); 178 if(EQ(p2, "-lt")) 179 return(int1<int2); 180 if(EQ(p2, "-ge")) 181 return(int1>=int2); 182 if(EQ(p2, "-le")) 183 return(int1<=int2); 184 } 185 186 synbad("unknown operator ",p2); 187 return 0; /* to shut ken up */ 188 } 189 190 int 191 tio(char *a, int f) 192 { 193 return access (a, f) >= 0; 194 } 195 196 /* copy to local memory; clear names for safety */ 197 int 198 localstat(char *f, Dir *dir) 199 { 200 Dir *d; 201 202 d = dirstat(f); 203 if(d == 0) 204 return(-1); 205 *dir = *d; 206 dir->name = 0; 207 dir->uid = 0; 208 dir->gid = 0; 209 dir->muid = 0; 210 return 0; 211 } 212 213 /* copy to local memory; clear names for safety */ 214 int 215 localfstat(int f, Dir *dir) 216 { 217 Dir *d; 218 219 d = dirfstat(f); 220 if(d == 0) 221 return(-1); 222 *dir = *d; 223 dir->name = 0; 224 dir->uid = 0; 225 dir->gid = 0; 226 dir->muid = 0; 227 return 0; 228 } 229 230 int 231 hasmode(char *f, ulong m) 232 { 233 Dir dir; 234 235 if(localstat(f,&dir)<0) 236 return(0); 237 return(dir.mode&m); 238 } 239 240 int 241 isdir(char *f) 242 { 243 Dir dir; 244 245 if(localstat(f,&dir)<0) 246 return(0); 247 return(dir.mode&DMDIR); 248 } 249 250 int 251 isreg(char *f) 252 { 253 Dir dir; 254 255 if(localstat(f,&dir)<0) 256 return(0); 257 return(!(dir.mode&DMDIR)); 258 } 259 260 int 261 isatty(int fd) 262 { 263 Dir d1, d2; 264 265 if(localfstat(fd, &d1) < 0) 266 return 0; 267 if(localstat("/dev/cons", &d2) < 0) 268 return 0; 269 return d1.type==d2.type && d1.dev==d2.dev && d1.qid.path==d2.qid.path; 270 } 271 272 int 273 fsizep(char *f) 274 { 275 Dir dir; 276 277 if(localstat(f,&dir)<0) 278 return(0); 279 return(dir.length>0); 280 } 281 282 void 283 synbad(char *s1, char *s2) 284 { 285 int len; 286 287 write(2, "test: ", 6); 288 if ((len = strlen(s1)) != 0) 289 write(2, s1, len); 290 if ((len = strlen(s2)) != 0) 291 write(2, s2, len); 292 write(2, "\n", 1); 293 exits("bad syntax"); 294 } 295 296 int 297 isint(char *s, int *pans) 298 { 299 char *ep; 300 301 *pans = strtol(s, &ep, 0); 302 return (*ep == 0); 303 } 304