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