1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
24
25
26 /*
27 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
29 */
30 /*
31 * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
32 *
33 * Sccsid @(#)test.c 1.10 (gritter) 12/25/06
34 */
35 /* from OpenSolaris "test.c 1.15 05/06/08 SMI" */
36
37 /*
38 * test expression
39 * [ expression ]
40 */
41
42 #include "defs.h"
43 #include <sys/types.h>
44 #include <sys/stat.h>
45
46 static int ap, ac;
47 static unsigned char **av;
48
49 /* test.c */
50 static unsigned char *nxtarg(int);
51 static int sexp(void);
52 static int e1(void);
53 static int e2(void);
54 static int e3(void);
55 static int ftype(const unsigned char *, int);
56 static int filtyp(const unsigned char *, int);
57 static int fsizep(const unsigned char *);
58 static void bfailed(const unsigned char *, const unsigned char *,
59 const unsigned char *);
60
61 int
test(int argn,unsigned char * com[])62 test(int argn, unsigned char *com[])
63 {
64 ac = argn;
65 av = com;
66 ap = 1;
67 if (eq(com[0],"["))
68 {
69 if (!eq(com[--ac], "]"))
70 failed("test", "] missing");
71 }
72 com[ac] = 0;
73 if (ac <= 1)
74 return(1);
75 #ifdef SUS
76 if (ac == 2)
77 return(eq(nxtarg(0), ""));
78 if (ac == 3 || ac == 4)
79 return(!e3());
80 #endif /* SUS */
81 return(sexp() ? 0 : 1);
82 }
83
84 static unsigned char *
nxtarg(int mt)85 nxtarg(int mt)
86 {
87 if (ap >= ac)
88 {
89 if (mt)
90 {
91 ap++;
92 return(0);
93 }
94 failed("test", "argument expected");
95 }
96 return(av[ap++]);
97 }
98
99 static int
sexp(void)100 sexp(void)
101 {
102 int p1;
103 unsigned char *p2;
104
105 p1 = e1();
106 p2 = nxtarg(1);
107 if (p2 != 0)
108 {
109 if (eq(p2, "-o"))
110 return(p1 | sexp());
111
112 /* if (!eq(p2, ")"))
113 failed("test", synmsg); */
114 }
115 ap--;
116 return(p1);
117 }
118
119 static int
e1(void)120 e1(void)
121 {
122 int p1;
123 unsigned char *p2;
124
125 p1 = e2();
126 p2 = nxtarg(1);
127
128 if ((p2 != 0) && eq(p2, "-a"))
129 return(p1 & e1());
130 ap--;
131 return(p1);
132 }
133
134 static int
e2(void)135 e2(void)
136 {
137 if (eq(nxtarg(0), "!"))
138 return(!e3());
139 ap--;
140 return(e3());
141 }
142
143 static int
e3(void)144 e3(void)
145 {
146 int p1;
147 register unsigned char *a;
148 unsigned char *p2;
149 long long ll_1, ll_2;
150
151 a = nxtarg(0);
152 if (eq(a, "("))
153 {
154 p1 = sexp();
155 if (!eq(nxtarg(0), ")"))
156 failed("test",") expected");
157 return(p1);
158 }
159 p2 = nxtarg(1);
160 ap--;
161 if ((p2 == 0) || (!eq(p2, "=") && !eq(p2, "!=")))
162 {
163 if (eq(a, "-r"))
164 return(chk_access(nxtarg(0), S_IREAD, 0) == 0);
165 if (eq(a, "-w"))
166 return(chk_access(nxtarg(0), S_IWRITE, 0) == 0);
167 if (eq(a, "-x"))
168 return(chk_access(nxtarg(0), S_IEXEC, 0) == 0);
169 #ifdef SUS
170 if (eq(a, "-e"))
171 return(access(nxtarg(0), F_OK) == 0);
172 if (eq(a, "-S"))
173 return(filtyp(nxtarg(0), S_IFSOCK));
174 if (eq(a, "!"))
175 return(!e3());
176 #endif /* SUS */
177 if (eq(a, "-d"))
178 return(filtyp(nxtarg(0), S_IFDIR));
179 if (eq(a, "-c"))
180 return(filtyp(nxtarg(0), S_IFCHR));
181 if (eq(a, "-b"))
182 return(filtyp(nxtarg(0), S_IFBLK));
183 if (eq(a, "-f"))
184 if (ucb_builtins) {
185 struct stat statb;
186
187 return(stat((char *)nxtarg(0), &statb) >= 0 &&
188 (statb.st_mode & S_IFMT) != S_IFDIR);
189 }
190 else
191 return(filtyp(nxtarg(0), S_IFREG));
192 if (eq(a, "-u"))
193 return(ftype(nxtarg(0), S_ISUID));
194 if (eq(a, "-g"))
195 return(ftype(nxtarg(0), S_ISGID));
196 if (eq(a, "-k"))
197 return(ftype(nxtarg(0), S_ISVTX));
198 if (eq(a, "-p"))
199 return(filtyp(nxtarg(0), S_IFIFO));
200 if (eq(a, "-h") || eq(a, "-L"))
201 return(filtyp(nxtarg(0), S_IFLNK));
202 if (eq(a, "-s"))
203 return(fsizep(nxtarg(0)));
204 if (eq(a, "-t"))
205 {
206 if (ap >= ac) /* no args */
207 return(isatty(1));
208 else if (eq((a = nxtarg(0)), "-a") || eq(a, "-o"))
209 {
210 ap--;
211 return(isatty(1));
212 }
213 else
214 return(isatty(atoi((char *)a)));
215 }
216 if (eq(a, "-n"))
217 return(!eq(nxtarg(0), ""));
218 if (eq(a, "-z"))
219 return(eq(nxtarg(0), ""));
220 }
221
222 p2 = nxtarg(1);
223 if (p2 == 0)
224 return(!eq(a, ""));
225 if (eq(p2, "-a") || eq(p2, "-o"))
226 {
227 ap--;
228 return(!eq(a, ""));
229 }
230 if (eq(p2, "="))
231 return(eq(nxtarg(0), a));
232 if (eq(p2, "!="))
233 return(!eq(nxtarg(0), a));
234 ll_1 = stoifll(a);
235 ll_2 = stoifll(nxtarg(0));
236 if (eq(p2, "-eq"))
237 return (ll_1 == ll_2);
238 if (eq(p2, "-ne"))
239 return (ll_1 != ll_2);
240 if (eq(p2, "-gt"))
241 return (ll_1 > ll_2);
242 if (eq(p2, "-lt"))
243 return (ll_1 < ll_2);
244 if (eq(p2, "-ge"))
245 return (ll_1 >= ll_2);
246 if (eq(p2, "-le"))
247 return (ll_1 <= ll_2);
248
249 bfailed(btest, badop, p2);
250 /* NOTREACHED */
251 return 0;
252 }
253
254
255 static int
ftype(const unsigned char * f,int field)256 ftype(const unsigned char *f, int field)
257 {
258 struct stat statb;
259
260 if (stat((char *)f, &statb) < 0)
261 return(0);
262 if ((statb.st_mode & field) == field)
263 return(1);
264 return(0);
265 }
266
267 static int
filtyp(const unsigned char * f,int field)268 filtyp(const unsigned char *f, int field)
269 {
270 struct stat statb;
271 int (*statf)(const char *, struct stat *) =
272 (field == S_IFLNK) ? lstat : stat;
273
274 if ((*statf)(f, &statb) < 0)
275 return(0);
276 if ((statb.st_mode & S_IFMT) == field)
277 return(1);
278 else
279 return(0);
280 }
281
282
283
284 static int
fsizep(const unsigned char * f)285 fsizep(const unsigned char *f)
286 {
287 struct stat statb;
288
289 if (stat((char *)f, &statb) < 0)
290 return(0);
291 return(statb.st_size > 0);
292 }
293
294 /*
295 * fake diagnostics to continue to look like original
296 * test(1) diagnostics
297 */
298 static void
bfailed(const unsigned char * s1,const unsigned char * s2,const unsigned char * s3)299 bfailed(const unsigned char *s1, const unsigned char *s2,
300 const unsigned char *s3)
301 {
302 prp();
303 prs(s1);
304 if (s2)
305 {
306 prs(colon);
307 prs(s2);
308 prs(s3);
309 }
310 newline();
311 exitsh(ERROR);
312 }
313