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