Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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 <u.h>
13
#include <libc.h>
14
 
15
#define EQ(a,b)	((tmp=a)==0?0:(strcmp(tmp,b)==0))
16
 
17
int	ap;
18
int	ac;
19
char	**av;
20
char	*tmp;
21
 
22
void	synbad(char *, char *);
23
int	fsizep(char *);
24
int	isdir(char *);
25
int	isreg(char *);
26
int	isatty(int);
27
int	isint(char *, int *);
28
int	isolder(char *, char *);
29
int	isolderthan(char *, char *);
30
int	isnewerthan(char *, char *);
31
int	hasmode(char *, ulong);
32
int	tio(char *, int);
33
int	e(void), e1(void), e2(void), e3(void);
34
char	*nxtarg(int);
35
 
36
void
37
main(int argc, char *argv[])
38
{
39
	int r;
40
	char *c;
41
 
42
	ac = argc; av = argv; ap = 1;
43
	if(EQ(argv[0],"[")) {
44
		if(!EQ(argv[--ac],"]"))
45
			synbad("] missing","");
46
	}
47
	argv[ac] = 0;
48
	if (ac<=1)
49
		exits("usage");
50
	r = e();
51
	/*
52
	 * nice idea but short-circuit -o and -a operators may have
53
	 * not consumed their right-hand sides.
54
	 */
55
	if(0 && (c = nxtarg(1)) != nil)
56
		synbad("unexpected operator/operand: ", c);
57
	exits(r?0:"false");
58
}
59
 
60
char *
61
nxtarg(int mt)
62
{
63
	if(ap>=ac){
64
		if(mt){
65
			ap++;
66
			return(0);
67
		}
68
		synbad("argument expected","");
69
	}
70
	return(av[ap++]);
71
}
72
 
73
int
74
nxtintarg(int *pans)
75
{
76
	if(ap<ac && isint(av[ap], pans)){
77
		ap++;
78
		return 1;
79
	}
80
	return 0;
81
}
82
 
83
int
84
e(void)
85
{
86
	int p1;
87
 
88
	p1 = e1();
89
	if (EQ(nxtarg(1), "-o"))
90
		return(p1 || e());
91
	ap--;
92
	return(p1);
93
}
94
 
95
int
96
e1(void)
97
{
98
	int p1;
99
 
100
	p1 = e2();
101
	if (EQ(nxtarg(1), "-a"))
102
		return (p1 && e1());
103
	ap--;
104
	return(p1);
105
}
106
 
107
int
108
e2(void)
109
{
110
	if (EQ(nxtarg(0), "!"))
111
		return(!e2());
112
	ap--;
113
	return(e3());
114
}
115
 
116
int
117
e3(void)
118
{
119
	int p1, int1, int2;
120
	char *a, *p2;
121
 
122
	a = nxtarg(0);
123
	if(EQ(a, "(")) {
124
		p1 = e();
125
		if(!EQ(nxtarg(0), ")"))
126
			synbad(") expected","");
127
		return(p1);
128
	}
129
 
130
	if(EQ(a, "-A"))
131
		return(hasmode(nxtarg(0), DMAPPEND));
132
 
133
	if(EQ(a, "-L"))
134
		return(hasmode(nxtarg(0), DMEXCL));
135
 
136
	if(EQ(a, "-T"))
137
		return(hasmode(nxtarg(0), DMTMP));
138
 
139
	if(EQ(a, "-f"))
140
		return(isreg(nxtarg(0)));
141
 
142
	if(EQ(a, "-d"))
143
		return(isdir(nxtarg(0)));
144
 
145
	if(EQ(a, "-r"))
146
		return(tio(nxtarg(0), 4));
147
 
148
	if(EQ(a, "-w"))
149
		return(tio(nxtarg(0), 2));
150
 
151
	if(EQ(a, "-x"))
152
		return(tio(nxtarg(0), 1));
153
 
154
	if(EQ(a, "-e"))
155
		return(tio(nxtarg(0), 0));
156
 
157
	if(EQ(a, "-c"))
158
		return(0);
159
 
160
	if(EQ(a, "-b"))
161
		return(0);
162
 
163
	if(EQ(a, "-u"))
164
		return(0);
165
 
166
	if(EQ(a, "-g"))
167
		return(0);
168
 
169
	if(EQ(a, "-s"))
170
		return(fsizep(nxtarg(0)));
171
 
172
	if(EQ(a, "-t"))
173
		if(ap>=ac)
174
			return(isatty(1));
175
		else if(nxtintarg(&int1))
176
			return(isatty(int1));
177
		else
178
			synbad("not a valid file descriptor number ", "");
179
 
180
	if(EQ(a, "-n"))
181
		return(!EQ(nxtarg(0), ""));
182
	if(EQ(a, "-z"))
183
		return(EQ(nxtarg(0), ""));
184
 
185
	p2 = nxtarg(1);
186
	if (p2==0)
187
		return(!EQ(a,""));
188
	if(EQ(p2, "="))
189
		return(EQ(nxtarg(0), a));
190
 
191
	if(EQ(p2, "!="))
192
		return(!EQ(nxtarg(0), a));
193
 
194
	if(EQ(p2, "-older"))
195
		return(isolder(nxtarg(0), a));
196
 
197
	if(EQ(p2, "-ot"))
198
		return(isolderthan(nxtarg(0), a));
199
 
200
	if(EQ(p2, "-nt"))
201
		return(isnewerthan(nxtarg(0), a));
202
 
203
	if(!isint(a, &int1))
204
		synbad("unexpected operator/operand: ", p2);
205
 
206
	if(nxtintarg(&int2)){
207
		if(EQ(p2, "-eq"))
208
			return(int1==int2);
209
		if(EQ(p2, "-ne"))
210
			return(int1!=int2);
211
		if(EQ(p2, "-gt"))
212
			return(int1>int2);
213
		if(EQ(p2, "-lt"))
214
			return(int1<int2);
215
		if(EQ(p2, "-ge"))
216
			return(int1>=int2);
217
		if(EQ(p2, "-le"))
218
			return(int1<=int2);
219
	}
220
 
221
	synbad("unknown operator ",p2);
222
	return 0;		/* to shut ken up */
223
}
224
 
225
int
226
tio(char *a, int f)
227
{
228
	return access (a, f) >= 0;
229
}
230
 
231
/*
232
 * note that the name strings pointed to by Dir members are
233
 * allocated with the Dir itself (by the same call to malloc),
234
 * but are not included in sizeof(Dir), so copying a Dir won't
235
 * copy the strings it points to.
236
 */
237
 
238
int
239
hasmode(char *f, ulong m)
240
{
241
	int r;
242
	Dir *dir;
243
 
244
	dir = dirstat(f);
245
	if (dir == nil)
246
		return 0;
247
	r = (dir->mode & m) != 0;
248
	free(dir);
249
	return r;
250
}
251
 
252
int
253
isdir(char *f)
254
{
255
	return hasmode(f, DMDIR);
256
}
257
 
258
int
259
isreg(char *f)
260
{
261
	int r;
262
	Dir *dir;
263
 
264
	dir = dirstat(f);
265
	if (dir == nil)
266
		return 0;
267
	r = (dir->mode & DMDIR) == 0;
268
	free(dir);
269
	return r;
270
}
271
 
272
int
273
isatty(int fd)
274
{
275
	int r;
276
	Dir *d1, *d2;
277
 
278
	d1 = dirfstat(fd);
279
	d2 = dirstat("/dev/cons");
280
	if (d1 == nil || d2 == nil)
281
		r = 0;
282
	else
283
		r = d1->type == d2->type && d1->dev == d2->dev &&
284
			d1->qid.path == d2->qid.path;
285
	free(d1);
286
	free(d2);
287
	return r;
288
}
289
 
290
int
291
fsizep(char *f)
292
{
293
	int r;
294
	Dir *dir;
295
 
296
	dir = dirstat(f);
297
	if (dir == nil)
298
		return 0;
299
	r = dir->length > 0;
300
	free(dir);
301
	return r;
302
}
303
 
304
void
305
synbad(char *s1, char *s2)
306
{
307
	int len;
308
 
309
	write(2, "test: ", 6);
310
	if ((len = strlen(s1)) != 0)
311
		write(2, s1, len);
312
	if ((len = strlen(s2)) != 0)
313
		write(2, s2, len);
314
	write(2, "\n", 1);
315
	exits("bad syntax");
316
}
317
 
318
int
319
isint(char *s, int *pans)
320
{
321
	char *ep;
322
 
323
	*pans = strtol(s, &ep, 0);
324
	return (*ep == 0);
325
}
326
 
327
int
328
isolder(char *pin, char *f)
329
{
330
	int r, rel;
331
	ulong n, m;
332
	char *p = pin;
333
	Dir *dir;
334
 
335
	dir = dirstat(f);
336
	if (dir == nil)
337
		return 0;
338
 
339
	/* parse time */
340
	n = 0;
341
	rel = 0;
342
	while(*p){
343
		m = strtoul(p, &p, 0);
344
		switch(*p){
345
		case 0:
346
			n = m;
347
			break;
348
		case 'y':
349
			m *= 12;
350
			/* fall through */
351
		case 'M':
352
			m *= 30;
353
			/* fall through */
354
		case 'd':
355
			m *= 24;
356
			/* fall through */
357
		case 'h':
358
			m *= 60;
359
			/* fall through */
360
		case 'm':
361
			m *= 60;
362
			/* fall through */
363
		case 's':
364
			n += m;
365
			p++;
366
			rel = 1;
367
			break;
368
		default:
369
			synbad("bad time syntax, ", pin);
370
		}
371
	}
372
	if (!rel)
373
		m = n;
374
	else{
375
		m = time(0);
376
		if (n > m)		/* before epoch? */
377
			m = 0;
378
		else
379
			m -= n;
380
	}
381
	r = dir->mtime < m;
382
	free(dir);
383
	return r;
384
}
385
 
386
int
387
isolderthan(char *a, char *b)
388
{
389
	int r;
390
	Dir *ad, *bd;
391
 
392
	ad = dirstat(a);
393
	bd = dirstat(b);
394
	if (ad == nil || bd == nil)
395
		r = 0;
396
	else
397
		r = ad->mtime > bd->mtime;
398
	free(ad);
399
	free(bd);
400
	return r;
401
}
402
 
403
int
404
isnewerthan(char *a, char *b)
405
{
406
	int r;
407
	Dir *ad, *bd;
408
 
409
	ad = dirstat(a);
410
	bd = dirstat(b);
411
	if (ad == nil || bd == nil)
412
		r = 0;
413
	else
414
		r = ad->mtime < bd->mtime;
415
	free(ad);
416
	free(bd);
417
	return r;
418
}