| ---
ttest.c (5813B)
---
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 * -T file exists and is temporary
10 */
11
12 #include
13 #include
14
15 #define isatty plan9_isatty
16
17 #define EQ(a,b) ((tmp=a)==0?0:(strcmp(tmp,b)==0))
18
19 int ap;
20 int ac;
21 char **av;
22 char *tmp;
23
24 void synbad(char *, char *);
25 int fsizep(char *);
26 int isdir(char *);
27 int isreg(char *);
28 int isatty(int);
29 int isint(char *, int *);
30 int isolder(char *, char *);
31 int isolderthan(char *, char *);
32 int isnewerthan(char *, char *);
33 int hasmode(char *, ulong);
34 int tio(char *, int);
35 int e(void), e1(void), e2(void), e3(void);
36 char *nxtarg(int);
37
38 void
39 main(int argc, char *argv[])
40 {
41 int r;
42 char *c;
43
44 ac = argc; av = argv; ap = 1;
45 if(EQ(argv[0],"[")) {
46 if(!EQ(argv[--ac],"]"))
47 synbad("] missing","");
48 }
49 argv[ac] = 0;
50 if (ac<=1)
51 exits("usage");
52 r = e();
53 /*
54 * nice idea but short-circuit -o and -a operators may have
55 * not consumed their right-hand sides.
56 */
57 if(0 && (c = nxtarg(1)) != nil)
58 synbad("unexpected operator/operand: ", c);
59 exits(r?0:"false");
60 }
61
62 char *
63 nxtarg(int mt)
64 {
65 if(ap>=ac){
66 if(mt){
67 ap++;
68 return(0);
69 }
70 synbad("argument expected","");
71 }
72 return(av[ap++]);
73 }
74
75 int
76 nxtintarg(int *pans)
77 {
78 if(ap=ac)
176 return(isatty(1));
177 else if(nxtintarg(&int1))
178 return(isatty(int1));
179 else
180 synbad("not a valid file descriptor number ", "");
181
182 if(EQ(a, "-n"))
183 return(!EQ(nxtarg(0), ""));
184 if(EQ(a, "-z"))
185 return(EQ(nxtarg(0), ""));
186
187 p2 = nxtarg(1);
188 if (p2==0)
189 return(!EQ(a,""));
190 if(EQ(p2, "="))
191 return(EQ(nxtarg(0), a));
192
193 if(EQ(p2, "!="))
194 return(!EQ(nxtarg(0), a));
195
196 if(EQ(p2, "-older"))
197 return(isolder(nxtarg(0), a));
198
199 if(EQ(p2, "-ot"))
200 return(isolderthan(nxtarg(0), a));
201
202 if(EQ(p2, "-nt"))
203 return(isnewerthan(nxtarg(0), a));
204
205 if(!isint(a, &int1))
206 synbad("unexpected operator/operand: ", p2);
207
208 if(nxtintarg(&int2)){
209 if(EQ(p2, "-eq"))
210 return(int1==int2);
211 if(EQ(p2, "-ne"))
212 return(int1!=int2);
213 if(EQ(p2, "-gt"))
214 return(int1>int2);
215 if(EQ(p2, "-lt"))
216 return(int1=int2);
219 if(EQ(p2, "-le"))
220 return(int1<=int2);
221 }
222
223 synbad("unknown operator ",p2);
224 return 0; /* to shut ken up */
225 }
226
227 int
228 tio(char *a, int f)
229 {
230 return access (a, f) >= 0;
231 }
232
233 /*
234 * note that the name strings pointed to by Dir members are
235 * allocated with the Dir itself (by the same call to malloc),
236 * but are not included in sizeof(Dir), so copying a Dir won't
237 * copy the strings it points to.
238 */
239
240 int
241 hasmode(char *f, ulong m)
242 {
243 int r;
244 Dir *dir;
245
246 dir = dirstat(f);
247 if (dir == nil)
248 return 0;
249 r = (dir->mode & m) != 0;
250 free(dir);
251 return r;
252 }
253
254 int
255 isdir(char *f)
256 {
257 return hasmode(f, DMDIR);
258 }
259
260 int
261 isreg(char *f)
262 {
263 int r;
264 Dir *dir;
265
266 dir = dirstat(f);
267 if (dir == nil)
268 return 0;
269 r = (dir->mode & DMDIR) == 0;
270 free(dir);
271 return r;
272 }
273
274 int
275 isatty(int fd)
276 {
277 int r;
278 Dir *d1, *d2;
279
280 d1 = dirfstat(fd);
281 d2 = dirstat("/dev/cons");
282 if (d1 == nil || d2 == nil)
283 r = 0;
284 else
285 r = d1->type == d2->type && d1->dev == d2->dev &&
286 d1->qid.path == d2->qid.path;
287 free(d1);
288 free(d2);
289 return r;
290 }
291
292 int
293 fsizep(char *f)
294 {
295 int r;
296 Dir *dir;
297
298 dir = dirstat(f);
299 if (dir == nil)
300 return 0;
301 r = dir->length > 0;
302 free(dir);
303 return r;
304 }
305
306 void
307 synbad(char *s1, char *s2)
308 {
309 int len;
310
311 write(2, "test: ", 6);
312 if ((len = strlen(s1)) != 0)
313 write(2, s1, len);
314 if ((len = strlen(s2)) != 0)
315 write(2, s2, len);
316 write(2, "\n", 1);
317 exits("bad syntax");
318 }
319
320 int
321 isint(char *s, int *pans)
322 {
323 char *ep;
324
325 *pans = strtol(s, &ep, 0);
326 return (*ep == 0);
327 }
328
329 int
330 isolder(char *pin, char *f)
331 {
332 int r;
333 ulong n, m;
334 char *p = pin;
335 Dir *dir;
336
337 dir = dirstat(f);
338 if (dir == nil)
339 return 0;
340
341 /* parse time */
342 n = 0;
343 while(*p){
344 m = strtoul(p, &p, 0);
345 switch(*p){
346 case 0:
347 n = m;
348 break;
349 case 'y':
350 m *= 12;
351 /* fall through */
352 case 'M':
353 m *= 30;
354 /* fall through */
355 case 'd':
356 m *= 24;
357 /* fall through */
358 case 'h':
359 m *= 60;
360 /* fall through */
361 case 'm':
362 m *= 60;
363 /* fall through */
364 case 's':
365 n += m;
366 p++;
367 break;
368 default:
369 synbad("bad time syntax, ", pin);
370 }
371 }
372
373 r = dir->mtime + n < time(0);
374 free(dir);
375 return r;
376 }
377
378 int
379 isolderthan(char *a, char *b)
380 {
381 int r;
382 Dir *ad, *bd;
383
384 ad = dirstat(a);
385 bd = dirstat(b);
386 if (ad == nil || bd == nil)
387 r = 0;
388 else
389 r = ad->mtime > bd->mtime;
390 free(ad);
391 free(bd);
392 return r;
393 }
394
395 int
396 isnewerthan(char *a, char *b)
397 {
398 int r;
399 Dir *ad, *bd;
400
401 ad = dirstat(a);
402 bd = dirstat(b);
403 if (ad == nil || bd == nil)
404 r = 0;
405 else
406 r = ad->mtime < bd->mtime;
407 free(ad);
408 free(bd);
409 return r;
410 } |