2 bc7cb1a1 2003-11-23 devnull * POSIX standard
3 bc7cb1a1 2003-11-23 devnull * test expression
4 bc7cb1a1 2003-11-23 devnull * [ expression ]
6 bc7cb1a1 2003-11-23 devnull * Plan 9 additions:
7 bc7cb1a1 2003-11-23 devnull * -A file exists and is append-only
8 bc7cb1a1 2003-11-23 devnull * -L file exists and is exclusive-use
9 e1ad38bf 2007-05-19 devnull * -T file exists and is temporary
12 bc7cb1a1 2003-11-23 devnull #include <u.h>
13 bc7cb1a1 2003-11-23 devnull #include <libc.h>
15 f9888587 2007-05-21 devnull #define isatty plan9_isatty
17 bc7cb1a1 2003-11-23 devnull #define EQ(a,b) ((tmp=a)==0?0:(strcmp(tmp,b)==0))
21 bc7cb1a1 2003-11-23 devnull char **av;
22 bc7cb1a1 2003-11-23 devnull char *tmp;
24 bc7cb1a1 2003-11-23 devnull void synbad(char *, char *);
25 bc7cb1a1 2003-11-23 devnull int fsizep(char *);
26 bc7cb1a1 2003-11-23 devnull int isdir(char *);
27 bc7cb1a1 2003-11-23 devnull int isreg(char *);
28 e1ad38bf 2007-05-19 devnull int isatty(int);
29 bc7cb1a1 2003-11-23 devnull int isint(char *, int *);
30 e1ad38bf 2007-05-19 devnull int isolder(char *, char *);
31 e1ad38bf 2007-05-19 devnull int isolderthan(char *, char *);
32 e1ad38bf 2007-05-19 devnull int isnewerthan(char *, char *);
33 bc7cb1a1 2003-11-23 devnull int hasmode(char *, ulong);
34 bc7cb1a1 2003-11-23 devnull int tio(char *, int);
35 bc7cb1a1 2003-11-23 devnull int e(void), e1(void), e2(void), e3(void);
36 e1ad38bf 2007-05-19 devnull char *nxtarg(int);
39 bc7cb1a1 2003-11-23 devnull main(int argc, char *argv[])
44 bc7cb1a1 2003-11-23 devnull ac = argc; av = argv; ap = 1;
45 bc7cb1a1 2003-11-23 devnull if(EQ(argv[0],"[")) {
46 bc7cb1a1 2003-11-23 devnull if(!EQ(argv[--ac],"]"))
47 bc7cb1a1 2003-11-23 devnull synbad("] missing","");
49 bc7cb1a1 2003-11-23 devnull argv[ac] = 0;
50 e1ad38bf 2007-05-19 devnull if (ac<=1)
51 e1ad38bf 2007-05-19 devnull exits("usage");
54 e1ad38bf 2007-05-19 devnull * nice idea but short-circuit -o and -a operators may have
55 e1ad38bf 2007-05-19 devnull * not consumed their right-hand sides.
57 e1ad38bf 2007-05-19 devnull if(0 && (c = nxtarg(1)) != nil)
58 e1ad38bf 2007-05-19 devnull synbad("unexpected operator/operand: ", c);
59 e1ad38bf 2007-05-19 devnull exits(r?0:"false");
63 bc7cb1a1 2003-11-23 devnull nxtarg(int mt)
65 bc7cb1a1 2003-11-23 devnull if(ap>=ac){
68 bc7cb1a1 2003-11-23 devnull return(0);
70 bc7cb1a1 2003-11-23 devnull synbad("argument expected","");
72 bc7cb1a1 2003-11-23 devnull return(av[ap++]);
76 bc7cb1a1 2003-11-23 devnull nxtintarg(int *pans)
78 bc7cb1a1 2003-11-23 devnull if(ap<ac && isint(av[ap], pans)){
80 bc7cb1a1 2003-11-23 devnull return 1;
82 bc7cb1a1 2003-11-23 devnull return 0;
90 bc7cb1a1 2003-11-23 devnull p1 = e1();
91 e1ad38bf 2007-05-19 devnull if (EQ(nxtarg(1), "-o"))
92 e1ad38bf 2007-05-19 devnull return(p1 || e());
94 bc7cb1a1 2003-11-23 devnull return(p1);
102 bc7cb1a1 2003-11-23 devnull p1 = e2();
103 e1ad38bf 2007-05-19 devnull if (EQ(nxtarg(1), "-a"))
104 e1ad38bf 2007-05-19 devnull return (p1 && e1());
106 bc7cb1a1 2003-11-23 devnull return(p1);
110 e1ad38bf 2007-05-19 devnull e2(void)
112 bc7cb1a1 2003-11-23 devnull if (EQ(nxtarg(0), "!"))
113 bc7cb1a1 2003-11-23 devnull return(!e2());
115 bc7cb1a1 2003-11-23 devnull return(e3());
119 e1ad38bf 2007-05-19 devnull e3(void)
121 e1ad38bf 2007-05-19 devnull int p1, int1, int2;
122 e1ad38bf 2007-05-19 devnull char *a, *p2;
124 bc7cb1a1 2003-11-23 devnull a = nxtarg(0);
125 bc7cb1a1 2003-11-23 devnull if(EQ(a, "(")) {
126 bc7cb1a1 2003-11-23 devnull p1 = e();
127 e1ad38bf 2007-05-19 devnull if(!EQ(nxtarg(0), ")"))
128 e1ad38bf 2007-05-19 devnull synbad(") expected","");
129 bc7cb1a1 2003-11-23 devnull return(p1);
132 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-A"))
133 bc7cb1a1 2003-11-23 devnull return(hasmode(nxtarg(0), DMAPPEND));
135 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-L"))
136 bc7cb1a1 2003-11-23 devnull return(hasmode(nxtarg(0), DMEXCL));
138 e1ad38bf 2007-05-19 devnull if(EQ(a, "-T"))
139 e1ad38bf 2007-05-19 devnull return(hasmode(nxtarg(0), DMTMP));
141 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-f"))
142 bc7cb1a1 2003-11-23 devnull return(isreg(nxtarg(0)));
144 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-d"))
145 bc7cb1a1 2003-11-23 devnull return(isdir(nxtarg(0)));
147 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-r"))
148 bc7cb1a1 2003-11-23 devnull return(tio(nxtarg(0), 4));
150 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-w"))
151 bc7cb1a1 2003-11-23 devnull return(tio(nxtarg(0), 2));
153 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-x"))
154 bc7cb1a1 2003-11-23 devnull return(tio(nxtarg(0), 1));
156 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-e"))
157 bc7cb1a1 2003-11-23 devnull return(tio(nxtarg(0), 0));
159 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-c"))
160 bc7cb1a1 2003-11-23 devnull return(0);
162 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-b"))
163 bc7cb1a1 2003-11-23 devnull return(0);
165 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-u"))
166 bc7cb1a1 2003-11-23 devnull return(0);
168 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-g"))
169 bc7cb1a1 2003-11-23 devnull return(0);
171 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-s"))
172 bc7cb1a1 2003-11-23 devnull return(fsizep(nxtarg(0)));
174 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-t"))
175 e1ad38bf 2007-05-19 devnull if(ap>=ac)
176 bc7cb1a1 2003-11-23 devnull return(isatty(1));
177 e1ad38bf 2007-05-19 devnull else if(nxtintarg(&int1))
178 bc7cb1a1 2003-11-23 devnull return(isatty(int1));
180 e1ad38bf 2007-05-19 devnull synbad("not a valid file descriptor number ", "");
182 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-n"))
183 bc7cb1a1 2003-11-23 devnull return(!EQ(nxtarg(0), ""));
184 bc7cb1a1 2003-11-23 devnull if(EQ(a, "-z"))
185 bc7cb1a1 2003-11-23 devnull return(EQ(nxtarg(0), ""));
187 bc7cb1a1 2003-11-23 devnull p2 = nxtarg(1);
188 bc7cb1a1 2003-11-23 devnull if (p2==0)
189 bc7cb1a1 2003-11-23 devnull return(!EQ(a,""));
190 bc7cb1a1 2003-11-23 devnull if(EQ(p2, "="))
191 bc7cb1a1 2003-11-23 devnull return(EQ(nxtarg(0), a));
193 bc7cb1a1 2003-11-23 devnull if(EQ(p2, "!="))
194 bc7cb1a1 2003-11-23 devnull return(!EQ(nxtarg(0), a));
196 e1ad38bf 2007-05-19 devnull if(EQ(p2, "-older"))
197 e1ad38bf 2007-05-19 devnull return(isolder(nxtarg(0), a));
199 e1ad38bf 2007-05-19 devnull if(EQ(p2, "-ot"))
200 e1ad38bf 2007-05-19 devnull return(isolderthan(nxtarg(0), a));
202 e1ad38bf 2007-05-19 devnull if(EQ(p2, "-nt"))
203 e1ad38bf 2007-05-19 devnull return(isnewerthan(nxtarg(0), a));
205 bc7cb1a1 2003-11-23 devnull if(!isint(a, &int1))
206 e1ad38bf 2007-05-19 devnull synbad("unexpected operator/operand: ", p2);
208 bc7cb1a1 2003-11-23 devnull if(nxtintarg(&int2)){
209 bc7cb1a1 2003-11-23 devnull if(EQ(p2, "-eq"))
210 bc7cb1a1 2003-11-23 devnull return(int1==int2);
211 bc7cb1a1 2003-11-23 devnull if(EQ(p2, "-ne"))
212 bc7cb1a1 2003-11-23 devnull return(int1!=int2);
213 bc7cb1a1 2003-11-23 devnull if(EQ(p2, "-gt"))
214 bc7cb1a1 2003-11-23 devnull return(int1>int2);
215 bc7cb1a1 2003-11-23 devnull if(EQ(p2, "-lt"))
216 bc7cb1a1 2003-11-23 devnull return(int1<int2);
217 bc7cb1a1 2003-11-23 devnull if(EQ(p2, "-ge"))
218 bc7cb1a1 2003-11-23 devnull return(int1>=int2);
219 bc7cb1a1 2003-11-23 devnull if(EQ(p2, "-le"))
220 bc7cb1a1 2003-11-23 devnull return(int1<=int2);
223 bc7cb1a1 2003-11-23 devnull synbad("unknown operator ",p2);
224 bc7cb1a1 2003-11-23 devnull return 0; /* to shut ken up */
228 bc7cb1a1 2003-11-23 devnull tio(char *a, int f)
230 bc7cb1a1 2003-11-23 devnull return access (a, f) >= 0;
233 bc7cb1a1 2003-11-23 devnull /* copy to local memory; clear names for safety */
235 bc7cb1a1 2003-11-23 devnull localstat(char *f, Dir *dir)
239 bc7cb1a1 2003-11-23 devnull d = dirstat(f);
240 e1ad38bf 2007-05-19 devnull if(d == nil)
241 bc7cb1a1 2003-11-23 devnull return(-1);
242 bc7cb1a1 2003-11-23 devnull *dir = *d;
243 e1ad38bf 2007-05-19 devnull free(d);
244 bc7cb1a1 2003-11-23 devnull dir->name = 0;
245 bc7cb1a1 2003-11-23 devnull dir->uid = 0;
246 bc7cb1a1 2003-11-23 devnull dir->gid = 0;
247 bc7cb1a1 2003-11-23 devnull dir->muid = 0;
248 bc7cb1a1 2003-11-23 devnull return 0;
251 bc7cb1a1 2003-11-23 devnull /* copy to local memory; clear names for safety */
253 bc7cb1a1 2003-11-23 devnull localfstat(int f, Dir *dir)
257 bc7cb1a1 2003-11-23 devnull d = dirfstat(f);
258 e1ad38bf 2007-05-19 devnull if(d == nil)
259 bc7cb1a1 2003-11-23 devnull return(-1);
260 bc7cb1a1 2003-11-23 devnull *dir = *d;
261 e1ad38bf 2007-05-19 devnull free(d);
262 bc7cb1a1 2003-11-23 devnull dir->name = 0;
263 bc7cb1a1 2003-11-23 devnull dir->uid = 0;
264 bc7cb1a1 2003-11-23 devnull dir->gid = 0;
265 bc7cb1a1 2003-11-23 devnull dir->muid = 0;
266 bc7cb1a1 2003-11-23 devnull return 0;
270 bc7cb1a1 2003-11-23 devnull hasmode(char *f, ulong m)
272 bc7cb1a1 2003-11-23 devnull Dir dir;
274 bc7cb1a1 2003-11-23 devnull if(localstat(f,&dir)<0)
275 bc7cb1a1 2003-11-23 devnull return(0);
276 bc7cb1a1 2003-11-23 devnull return(dir.mode&m);
280 bc7cb1a1 2003-11-23 devnull isdir(char *f)
282 bc7cb1a1 2003-11-23 devnull Dir dir;
284 bc7cb1a1 2003-11-23 devnull if(localstat(f,&dir)<0)
285 bc7cb1a1 2003-11-23 devnull return(0);
286 bc7cb1a1 2003-11-23 devnull return(dir.mode&DMDIR);
290 bc7cb1a1 2003-11-23 devnull isreg(char *f)
292 bc7cb1a1 2003-11-23 devnull Dir dir;
294 bc7cb1a1 2003-11-23 devnull if(localstat(f,&dir)<0)
295 bc7cb1a1 2003-11-23 devnull return(0);
296 bc7cb1a1 2003-11-23 devnull return(!(dir.mode&DMDIR));
300 e1ad38bf 2007-05-19 devnull isatty(int fd)
302 e1ad38bf 2007-05-19 devnull Dir d1, d2;
304 e1ad38bf 2007-05-19 devnull if(localfstat(fd, &d1) < 0)
305 e1ad38bf 2007-05-19 devnull return 0;
306 e1ad38bf 2007-05-19 devnull if(localstat("/dev/cons", &d2) < 0)
307 e1ad38bf 2007-05-19 devnull return 0;
308 e1ad38bf 2007-05-19 devnull return d1.type==d2.type && d1.dev==d2.dev && d1.qid.path==d2.qid.path;
312 bc7cb1a1 2003-11-23 devnull fsizep(char *f)
314 bc7cb1a1 2003-11-23 devnull Dir dir;
316 bc7cb1a1 2003-11-23 devnull if(localstat(f,&dir)<0)
317 bc7cb1a1 2003-11-23 devnull return(0);
318 bc7cb1a1 2003-11-23 devnull return(dir.length>0);
322 bc7cb1a1 2003-11-23 devnull synbad(char *s1, char *s2)
324 bc7cb1a1 2003-11-23 devnull int len;
326 bc7cb1a1 2003-11-23 devnull write(2, "test: ", 6);
327 bc7cb1a1 2003-11-23 devnull if ((len = strlen(s1)) != 0)
328 bc7cb1a1 2003-11-23 devnull write(2, s1, len);
329 bc7cb1a1 2003-11-23 devnull if ((len = strlen(s2)) != 0)
330 bc7cb1a1 2003-11-23 devnull write(2, s2, len);
331 bc7cb1a1 2003-11-23 devnull write(2, "\n", 1);
332 bc7cb1a1 2003-11-23 devnull exits("bad syntax");
336 bc7cb1a1 2003-11-23 devnull isint(char *s, int *pans)
338 bc7cb1a1 2003-11-23 devnull char *ep;
340 bc7cb1a1 2003-11-23 devnull *pans = strtol(s, &ep, 0);
341 bc7cb1a1 2003-11-23 devnull return (*ep == 0);
345 e1ad38bf 2007-05-19 devnull isolder(char *pin, char *f)
347 e1ad38bf 2007-05-19 devnull char *p = pin;
348 e1ad38bf 2007-05-19 devnull ulong n, m;
349 e1ad38bf 2007-05-19 devnull Dir dir;
351 e1ad38bf 2007-05-19 devnull if(localstat(f,&dir)<0)
352 e1ad38bf 2007-05-19 devnull return(0);
354 e1ad38bf 2007-05-19 devnull /* parse time */
356 e1ad38bf 2007-05-19 devnull while(*p){
357 e1ad38bf 2007-05-19 devnull m = strtoul(p, &p, 0);
358 e1ad38bf 2007-05-19 devnull switch(*p){
362 e1ad38bf 2007-05-19 devnull case 'y':
363 e1ad38bf 2007-05-19 devnull m *= 12;
364 e1ad38bf 2007-05-19 devnull /* fall through */
365 e1ad38bf 2007-05-19 devnull case 'M':
366 e1ad38bf 2007-05-19 devnull m *= 30;
367 e1ad38bf 2007-05-19 devnull /* fall through */
368 e1ad38bf 2007-05-19 devnull case 'd':
369 e1ad38bf 2007-05-19 devnull m *= 24;
370 e1ad38bf 2007-05-19 devnull /* fall through */
371 e1ad38bf 2007-05-19 devnull case 'h':
372 e1ad38bf 2007-05-19 devnull m *= 60;
373 e1ad38bf 2007-05-19 devnull /* fall through */
374 e1ad38bf 2007-05-19 devnull case 'm':
375 e1ad38bf 2007-05-19 devnull m *= 60;
376 e1ad38bf 2007-05-19 devnull /* fall through */
377 e1ad38bf 2007-05-19 devnull case 's':
381 e1ad38bf 2007-05-19 devnull default:
382 e1ad38bf 2007-05-19 devnull synbad("bad time syntax, ", pin);
386 e1ad38bf 2007-05-19 devnull return(dir.mtime+n < time(0));
390 e1ad38bf 2007-05-19 devnull isolderthan(char *a, char *b)
392 e1ad38bf 2007-05-19 devnull Dir ad, bd;
394 e1ad38bf 2007-05-19 devnull if(localstat(a, &ad)<0)
395 e1ad38bf 2007-05-19 devnull return(0);
396 e1ad38bf 2007-05-19 devnull if(localstat(b, &bd)<0)
397 e1ad38bf 2007-05-19 devnull return(0);
398 e1ad38bf 2007-05-19 devnull return ad.mtime > bd.mtime;
402 e1ad38bf 2007-05-19 devnull isnewerthan(char *a, char *b)
404 e1ad38bf 2007-05-19 devnull Dir ad, bd;
406 e1ad38bf 2007-05-19 devnull if(localstat(a, &ad)<0)
407 e1ad38bf 2007-05-19 devnull return(0);
408 e1ad38bf 2007-05-19 devnull if(localstat(b, &bd)<0)
409 e1ad38bf 2007-05-19 devnull return(0);
410 e1ad38bf 2007-05-19 devnull return ad.mtime < bd.mtime;