xref: /csrg-svn/local/toolchest/ksh/sh/test.c (revision 35170)
1*35170Smarc /*
2*35170Smarc 
3*35170Smarc  *      Copyright (c) 1984, 1985, 1986 AT&T
4*35170Smarc  *      All Rights Reserved
5*35170Smarc 
6*35170Smarc  *      THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35170Smarc  *      CODE OF AT&T.
8*35170Smarc  *      The copyright notice above does not
9*35170Smarc  *      evidence any actual or intended
10*35170Smarc  *      publication of such source code.
11*35170Smarc 
12*35170Smarc  */
13*35170Smarc /* @(#)test.c	1.1 */
14*35170Smarc /*
15*35170Smarc  * test expression
16*35170Smarc  * [ expression ]
17*35170Smarc  * Rewritten by David Korn
18*35170Smarc  */
19*35170Smarc 
20*35170Smarc #include	<sys/types.h>
21*35170Smarc #include	<sys/stat.h>
22*35170Smarc #include	"shtype.h"
23*35170Smarc #include	"defs.h"
24*35170Smarc #include	"test.h"
25*35170Smarc #include	"sym.h"
26*35170Smarc 
27*35170Smarc #define	tio(a,f)	(access(a,f)==0)
28*35170Smarc /* single char string compare */
29*35170Smarc #define c_eq(a,c)	(*a==c && *(a+1)==0)
30*35170Smarc /* two character string compare */
31*35170Smarc #define c2_eq(a,c1,c2)	(*a==c1 && *(a+1)==c2 && *(a+2)==0)
32*35170Smarc 
33*35170Smarc int ftype();
34*35170Smarc int testfn();
35*35170Smarc 
36*35170Smarc extern long aeval();
37*35170Smarc extern char *strchr();
38*35170Smarc extern void failed();
39*35170Smarc 
40*35170Smarc static char *nxtarg();
41*35170Smarc static time_t ftime_compare();
42*35170Smarc static int exp();
43*35170Smarc static int e3();
44*35170Smarc static int fsizep();
45*35170Smarc 
46*35170Smarc extern MSG	synmsg;
47*35170Smarc extern MSG	test_opts;
48*35170Smarc 
49*35170Smarc static int ap, ac;
50*35170Smarc static char **av;
51*35170Smarc 
testfn(argn,com)52*35170Smarc int testfn(argn, com)
53*35170Smarc char *com[];
54*35170Smarc register int argn;
55*35170Smarc {
56*35170Smarc 	register char *p = com[0];
57*35170Smarc 	av = com;
58*35170Smarc 	ap = 1;
59*35170Smarc 	if(c_eq(p,'['))
60*35170Smarc 	{
61*35170Smarc 		p = com[--argn];
62*35170Smarc 		if(!c_eq(p, ']'))
63*35170Smarc 			failed(btest,  endmatch);
64*35170Smarc 	}
65*35170Smarc 	if(argn <= 1)
66*35170Smarc 		return(1);
67*35170Smarc 	ac = argn;
68*35170Smarc 	return(!exp(0));
69*35170Smarc }
70*35170Smarc 
71*35170Smarc /*
72*35170Smarc  * evaluate a test expression.
73*35170Smarc  * flag is 0 on outer level
74*35170Smarc  * flag is 1 when in parenthesis
75*35170Smarc  * flag is 2 when evaluating -a
76*35170Smarc  */
77*35170Smarc 
exp(flag)78*35170Smarc static exp(flag)
79*35170Smarc {
80*35170Smarc 	register int r;
81*35170Smarc 	register char *p;
82*35170Smarc 	r = e3();
83*35170Smarc 	while(ap < ac)
84*35170Smarc 	{
85*35170Smarc 		p = nxtarg(0);
86*35170Smarc 		/* check for -o and -a */
87*35170Smarc 		if(flag && c_eq(p,')'))
88*35170Smarc 		{
89*35170Smarc 			ap--;
90*35170Smarc 			break;
91*35170Smarc 		}
92*35170Smarc 		if(*p=='-' && *(p+2)==0)
93*35170Smarc 		{
94*35170Smarc 			if(*++p == 'o')
95*35170Smarc 			{
96*35170Smarc 				if(flag==2)
97*35170Smarc 				{
98*35170Smarc 					ap--;
99*35170Smarc 					break;
100*35170Smarc 				}
101*35170Smarc 				r |= exp(3);
102*35170Smarc 				continue;
103*35170Smarc 			}
104*35170Smarc 			else if(*p == 'a')
105*35170Smarc 			{
106*35170Smarc 				r &= exp(2);
107*35170Smarc 				continue;
108*35170Smarc 			}
109*35170Smarc 		}
110*35170Smarc 		failed(btest,  synmsg);
111*35170Smarc 	}
112*35170Smarc 	return(r);
113*35170Smarc }
114*35170Smarc 
nxtarg(mt)115*35170Smarc static char *nxtarg(mt)
116*35170Smarc {
117*35170Smarc 	if(ap >= ac)
118*35170Smarc 	{
119*35170Smarc 		if(mt)
120*35170Smarc 		{
121*35170Smarc 			ap++;
122*35170Smarc 			return(0);
123*35170Smarc 		}
124*35170Smarc 		failed(btest, argexp);
125*35170Smarc 	}
126*35170Smarc 	return(av[ap++]);
127*35170Smarc }
128*35170Smarc 
129*35170Smarc 
e3()130*35170Smarc static e3()
131*35170Smarc {
132*35170Smarc 	register char *a;
133*35170Smarc 	register char *p2;
134*35170Smarc 	register int p1;
135*35170Smarc 	long int int1, int2;
136*35170Smarc 	char *op;
137*35170Smarc 	a=nxtarg(0);
138*35170Smarc 	if(c_eq(a, '!'))
139*35170Smarc 		return(!e3());
140*35170Smarc 	if(c_eq(a, '('))
141*35170Smarc 	{
142*35170Smarc 		p1 = exp(1);
143*35170Smarc 		p2 = nxtarg(0);
144*35170Smarc 		if(!c_eq(p2, ')'))
145*35170Smarc 			failed(btest,parexp);
146*35170Smarc 		return(p1);
147*35170Smarc 	}
148*35170Smarc 	p2 = nxtarg(1);
149*35170Smarc 	if(p2!=0 && (c_eq(p2,'=') || c2_eq(p2,'!','=')))
150*35170Smarc 		goto skip;
151*35170Smarc 	if(c2_eq(a,'-','t'))
152*35170Smarc 	{
153*35170Smarc 		if(p2 && isdigit(*p2))
154*35170Smarc 			 return(*(p2+1)?0:isatty(*p2-'0'));
155*35170Smarc 		else
156*35170Smarc 		{
157*35170Smarc 		/* test -t with no arguments */
158*35170Smarc 			ap--;
159*35170Smarc 			return(isatty(1));
160*35170Smarc 		}
161*35170Smarc 	}
162*35170Smarc 	if((*a=='-' && *(a+2)==0) && strchr(test_opts,*(a+1)))
163*35170Smarc 	{
164*35170Smarc 		if(p2==0 || c_eq(p2,')') )
165*35170Smarc 			failed(btest, argexp);
166*35170Smarc 		switch(*(a+1))
167*35170Smarc 		{
168*35170Smarc 			case 'r':
169*35170Smarc 				return(tio(p2, 4));
170*35170Smarc 			case 'w':
171*35170Smarc 				return(tio(p2, 2));
172*35170Smarc 			case 'x':
173*35170Smarc 				return(tio(p2, 1));
174*35170Smarc 			case 'd':
175*35170Smarc 				return(ftype(p2,S_IFMT,S_IFDIR));
176*35170Smarc 			case 'c':
177*35170Smarc 				return(ftype(p2,S_IFMT,S_IFCHR));
178*35170Smarc 			case 'b':
179*35170Smarc 				return(ftype(p2,S_IFMT,S_IFBLK));
180*35170Smarc 			case 'f':
181*35170Smarc 				return(ftype(p2,S_IFMT,S_IFREG));
182*35170Smarc 			case 'u':
183*35170Smarc 				return(ftype(p2,S_ISUID,S_ISUID));
184*35170Smarc 			case 'g':
185*35170Smarc 				return(ftype(p2,S_ISGID,S_ISGID));
186*35170Smarc 			case 'k':
187*35170Smarc 				return(ftype(p2,S_ISVTX,S_ISVTX));
188*35170Smarc 			case 'L':
189*35170Smarc #ifdef S_IFLNK
190*35170Smarc 				{
191*35170Smarc 					struct stat statb;
192*35170Smarc 					if(lstat(p2,&statb)<0)
193*35170Smarc 						return(0);
194*35170Smarc 					return((statb.st_mode&S_IFMT)==S_IFLNK);
195*35170Smarc 				}
196*35170Smarc #else
197*35170Smarc 				return(0);
198*35170Smarc #endif	/* S_IFLNK */
199*35170Smarc 			case 'p':
200*35170Smarc #ifdef S_IFIFO
201*35170Smarc 				return(ftype(p2,S_IFIFO,S_IFIFO));
202*35170Smarc #else
203*35170Smarc 				return(0);
204*35170Smarc #endif	/* S_IFIFO */
205*35170Smarc 			case 's':
206*35170Smarc 				return(fsizep(p2));
207*35170Smarc 			case 'n':
208*35170Smarc 				return(*p2 != 0);
209*35170Smarc 			case 'z':
210*35170Smarc 				return(*p2 == 0);
211*35170Smarc 		}
212*35170Smarc 	}
213*35170Smarc 	if(p2==0 || c_eq(p2,')'))
214*35170Smarc 	{
215*35170Smarc 		ap--;
216*35170Smarc 		return(*a!=0);
217*35170Smarc 	}
218*35170Smarc skip:
219*35170Smarc 	p1 = syslook(p2,testops);
220*35170Smarc 	op = p2;
221*35170Smarc 	if((p1&TEST_BINOP)==0)
222*35170Smarc 		p2 = nxtarg(0);
223*35170Smarc 	if(p1==0)
224*35170Smarc 		failed(op,badop);
225*35170Smarc 	if(p1&TEST_ARITH)
226*35170Smarc 	{
227*35170Smarc 		int1 = aeval(a);
228*35170Smarc 		int2 = aeval(p2);
229*35170Smarc 	}
230*35170Smarc 	switch(p1)
231*35170Smarc 	{
232*35170Smarc 		/* p1 must be one of the following values */
233*35170Smarc 		case TEST_AND:
234*35170Smarc 		case TEST_OR:
235*35170Smarc 			ap--;
236*35170Smarc 			return(*a!=0);
237*35170Smarc 		case TEST_SEQ:
238*35170Smarc 			return(eq(p2, a));
239*35170Smarc 		case TEST_SNE:
240*35170Smarc 			return(!eq(p2, a));
241*35170Smarc 		case TEST_EF:
242*35170Smarc 			return(eq_inode(p2,a));
243*35170Smarc 		case TEST_NT:
244*35170Smarc 			return(ftime_compare(a,p2)>0);
245*35170Smarc 		case TEST_OT:
246*35170Smarc 			return(ftime_compare(a,p2)<0);
247*35170Smarc 		case TEST_EQ:
248*35170Smarc 			return(int1==int2);
249*35170Smarc 		case TEST_NE:
250*35170Smarc 			return(int1!=int2);
251*35170Smarc 		case TEST_GT:
252*35170Smarc 			return(int1>int2);
253*35170Smarc 		case TEST_LT:
254*35170Smarc 			return(int1<int2);
255*35170Smarc 		case TEST_GE:
256*35170Smarc 			return(int1>=int2);
257*35170Smarc 		case TEST_LE:
258*35170Smarc 			return(int1<=int2);
259*35170Smarc 	}
260*35170Smarc 	/* NOTREACHED */
261*35170Smarc }
262*35170Smarc 
ftype(f,mask,field)263*35170Smarc ftype(f,mask,field)
264*35170Smarc char *f;
265*35170Smarc int field;
266*35170Smarc {
267*35170Smarc 	struct stat statb;
268*35170Smarc 	if(stat(f,&statb)<0)
269*35170Smarc 		return(0);
270*35170Smarc 	return((statb.st_mode&mask)==field);
271*35170Smarc }
272*35170Smarc 
fsizep(f)273*35170Smarc static fsizep(f)
274*35170Smarc char *f;
275*35170Smarc {
276*35170Smarc 	struct stat statb;
277*35170Smarc 	if(stat(f, &statb) <0)
278*35170Smarc 		return(0);
279*35170Smarc 	return(statb.st_size>0);
280*35170Smarc }
281*35170Smarc 
282*35170Smarc /*
283*35170Smarc  * returns the modification time of f1 - modification time of f2
284*35170Smarc  */
285*35170Smarc 
ftime_compare(file1,file2)286*35170Smarc static time_t ftime_compare(file1,file2)
287*35170Smarc char *file1,*file2;
288*35170Smarc {
289*35170Smarc 	struct stat statb1,statb2;
290*35170Smarc 	if(stat(file1,&statb1)<0)
291*35170Smarc 		statb1.st_mtime = 0;
292*35170Smarc 	if(stat(file2,&statb2)<0)
293*35170Smarc 		statb2.st_mtime = 0;
294*35170Smarc 	return(statb1.st_mtime-statb2.st_mtime);
295*35170Smarc }
296*35170Smarc 
297*35170Smarc /*
298*35170Smarc  * return true if inode of two files are the same
299*35170Smarc  */
300*35170Smarc 
eq_inode(file1,file2)301*35170Smarc eq_inode(file1,file2)
302*35170Smarc char *file1,*file2;
303*35170Smarc {
304*35170Smarc 	struct stat stat1,stat2;
305*35170Smarc 	if(stat(file1,&stat1)>=0  && stat(file2,&stat2)>=0)
306*35170Smarc 		if(stat1.st_dev == stat2.st_dev && stat1.st_ino == stat2.st_ino)
307*35170Smarc 			return(1);
308*35170Smarc 	return(0);
309*35170Smarc }
310*35170Smarc 
311