1 /*
2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
7 /* All Rights Reserved */
8
9 /*
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley software License Agreement
12 * specifies the terms and conditions for redistribution.
13 */
14
15 /*
16 * test expression
17 * [ expression ]
18 */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <string.h>
26
27 #define EQ(a, b) ((strcmp(a, b) == 0))
28
29 static char *nxtarg(int mt);
30 static int exp(void);
31 static int e1(void);
32 static int e2(void);
33 static int e3(void);
34 static int tio(char *a, int f);
35 static int ftype(char *f, int field);
36 static int filtyp(char *f, int field);
37 static int fsizep(char *f);
38 static void synbad(char *s1, char *s2);
39
40 static int ap;
41 static int ac;
42 static char **av;
43
44 int
main(int argc,char * argv[])45 main(int argc, char *argv[])
46 {
47 int status;
48
49 ac = argc; av = argv; ap = 1;
50 if (EQ(argv[0], "[")) {
51 if (!EQ(argv[--ac], "]"))
52 synbad("] missing", "");
53 }
54 argv[ac] = 0;
55 if (ac <= 1)
56 exit(1);
57 status = (exp() ? 0 : 1);
58 if (nxtarg(1) != 0)
59 synbad("too many arguments", "");
60 return (status);
61 }
62
63 static char *
nxtarg(int mt)64 nxtarg(int mt)
65 {
66 if (ap >= ac) {
67 if (mt) {
68 ap++;
69 return (0);
70 }
71 synbad("argument expected", "");
72 }
73 return (av[ap++]);
74 }
75
76 static int
exp(void)77 exp(void)
78 {
79 int p1;
80 char *p2;
81
82 p1 = e1();
83 p2 = nxtarg(1);
84 if (p2 != 0) {
85 if (EQ(p2, "-o"))
86 return (p1 | exp());
87 if (EQ(p2, "]"))
88 synbad("syntax error", "");
89 }
90 ap--;
91 return (p1);
92 }
93
94 static int
e1(void)95 e1(void)
96 {
97 int p1;
98 char *p2;
99
100 p1 = e2();
101 p2 = nxtarg(1);
102 if ((p2 != 0) && EQ(p2, "-a"))
103 return (p1 & e1());
104 ap--;
105 return (p1);
106 }
107
108 static int
e2(void)109 e2(void)
110 {
111 if (EQ(nxtarg(0), "!"))
112 return (!e3());
113 ap--;
114 return (e3());
115 }
116
117 static int
e3(void)118 e3(void)
119 {
120 int p1;
121 char *a;
122 char *p2;
123 int int1, int2;
124
125 a = nxtarg(0);
126 if (EQ(a, "(")) {
127 p1 = exp();
128 if (!EQ(nxtarg(0), ")")) synbad(") expected", "");
129 return (p1);
130 }
131 p2 = nxtarg(1);
132 ap--;
133 if ((p2 == 0) || (!EQ(p2, "=") && !EQ(p2, "!="))) {
134 if (EQ(a, "-r"))
135 return (tio(nxtarg(0), 4));
136
137 if (EQ(a, "-w"))
138 return (tio(nxtarg(0), 2));
139
140 if (EQ(a, "-x"))
141 return (tio(nxtarg(0), 1));
142
143 if (EQ(a, "-d"))
144 return (filtyp(nxtarg(0), S_IFDIR));
145
146 if (EQ(a, "-c"))
147 return (filtyp(nxtarg(0), S_IFCHR));
148
149 if (EQ(a, "-b"))
150 return (filtyp(nxtarg(0), S_IFBLK));
151
152 if (EQ(a, "-f")) {
153 struct stat statb;
154
155 return (stat(nxtarg(0), &statb) >= 0 &&
156 (statb.st_mode & S_IFMT) != S_IFDIR);
157 }
158
159 if (EQ(a, "-h"))
160 return (filtyp(nxtarg(0), S_IFLNK));
161
162 if (EQ(a, "-u"))
163 return (ftype(nxtarg(0), S_ISUID));
164
165 if (EQ(a, "-g"))
166 return (ftype(nxtarg(0), S_ISGID));
167
168 if (EQ(a, "-k"))
169 return (ftype(nxtarg(0), S_ISVTX));
170
171 if (EQ(a, "-p"))
172 #ifdef S_IFIFO
173 return (filtyp(nxtarg(0), S_IFIFO));
174 #else
175 return (nxtarg(0), 0);
176 #endif
177
178 if (EQ(a, "-s"))
179 return (fsizep(nxtarg(0)));
180
181 if (EQ(a, "-t"))
182 if (ap >= ac)
183 return (isatty(1));
184 else if (EQ((a = nxtarg(0)), "-a") || EQ(a, "-o")) {
185 ap--;
186 return (isatty(1));
187 } else
188 return (isatty(atoi(a)));
189
190 if (EQ(a, "-n"))
191 return (!EQ(nxtarg(0), ""));
192 if (EQ(a, "-z"))
193 return (EQ(nxtarg(0), ""));
194 }
195
196 p2 = nxtarg(1);
197 if (p2 == 0)
198 return (!EQ(a, ""));
199 if (EQ(p2, "-a") || EQ(p2, "-o")) {
200 ap--;
201 return (!EQ(a, ""));
202 }
203 if (EQ(p2, "="))
204 return (EQ(nxtarg(0), a));
205
206 if (EQ(p2, "!="))
207 return (!EQ(nxtarg(0), a));
208
209 int1 = atoi(a);
210 int2 = atoi(nxtarg(0));
211 if (EQ(p2, "-eq"))
212 return (int1 == int2);
213 if (EQ(p2, "-ne"))
214 return (int1 != int2);
215 if (EQ(p2, "-gt"))
216 return (int1 > int2);
217 if (EQ(p2, "-lt"))
218 return (int1 < int2);
219 if (EQ(p2, "-ge"))
220 return (int1 >= int2);
221 if (EQ(p2, "-le"))
222 return (int1 <= int2);
223
224 synbad("unknown operator ", p2);
225 /* NOTREACHED */
226 return (0);
227 }
228
229 static int
tio(char * a,int f)230 tio(char *a, int f)
231 {
232 if (access(a, f) == 0)
233 return (1);
234 else
235 return (0);
236 }
237
238 static int
ftype(char * f,int field)239 ftype(char *f, int field)
240 {
241 struct stat statb;
242
243 if (stat(f, &statb) < 0)
244 return (0);
245 if ((statb.st_mode & field) == field)
246 return (1);
247 return (0);
248 }
249
250 static int
filtyp(char * f,int field)251 filtyp(char *f, int field)
252 {
253 struct stat statb;
254
255 if (field == S_IFLNK) {
256 if (lstat(f, &statb) < 0)
257 return (0);
258 } else {
259 if (stat(f, &statb) < 0)
260 return (0);
261 }
262 if ((statb.st_mode & S_IFMT) == field)
263 return (1);
264 else
265 return (0);
266 }
267
268 static int
fsizep(char * f)269 fsizep(char *f)
270 {
271 struct stat statb;
272
273 if (stat(f, &statb) < 0)
274 return (0);
275 return (statb.st_size > 0);
276 }
277
278 static void
synbad(char * s1,char * s2)279 synbad(char *s1, char *s2)
280 {
281 (void) write(2, "test: ", 6);
282 (void) write(2, s1, strlen(s1));
283 (void) write(2, s2, strlen(s2));
284 (void) write(2, "\n", 1);
285 exit(255);
286 }
287