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