xref: /plan9-contrib/sys/src/cmd/test.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 /*
2  * POSIX standard
3  *	test expression
4  *	[ expression ]
5  */
6 
7 #include <u.h>
8 #include <libc.h>
9 #define EQ(a,b)	((tmp=a)==0?0:(strcmp(tmp,b)==0))
10 
11 int	ap;
12 int	ac;
13 char	**av;
14 char	*tmp;
15 
16 void	synbad(char *, char *);
17 int	length(char *);
18 int	fsizep(char *);
19 int	isdir(char *);
20 int	isreg(char *);
21 int	isatty(int);
22 int	isint(char *, int *);
23 int	tio(char *, int);
24 int	e(void), e1(void), e2(void), e3(void);
25 
26 void
27 main(int argc, char *argv[])
28 {
29 
30 	ac = argc; av = argv; ap = 1;
31 	if(EQ(argv[0],"[")) {
32 		if(!EQ(argv[--ac],"]"))
33 			synbad("] missing","");
34 	}
35 	argv[ac] = 0;
36 	if (ac<=1) exits("usage");
37 	exits(e()?0:"false");
38 }
39 
40 char *
41 nxtarg(int mt)
42 {
43 	if(ap>=ac){
44 		if(mt){
45 			ap++;
46 			return(0);
47 		}
48 		synbad("argument expected","");
49 	}
50 	return(av[ap++]);
51 }
52 
53 int
54 nxtintarg(int *pans)
55 {
56 	if(ap<ac && isint(av[ap], pans)){
57 		ap++;
58 		return 1;
59 	}
60 	return 0;
61 }
62 
63 int
64 e(void) {
65 	int p1;
66 
67 	p1 = e1();
68 	if (EQ(nxtarg(1), "-o")) return(p1 | e());
69 	ap--;
70 	return(p1);
71 }
72 
73 int
74 e1(void) {
75 	int p1;
76 
77 	p1 = e2();
78 	if (EQ(nxtarg(1), "-a")) return (p1 & e1());
79 	ap--;
80 	return(p1);
81 }
82 
83 int
84 e2(void) {
85 	if (EQ(nxtarg(0), "!"))
86 		return(!e3());
87 	ap--;
88 	return(e3());
89 }
90 
91 int
92 e3(void) {
93 	int p1;
94 	char *a;
95 	char *p2;
96 	int int1, int2;
97 
98 	a = nxtarg(0);
99 	if(EQ(a, "(")) {
100 		p1 = e();
101 		if(!EQ(nxtarg(0), ")")) synbad(") expected","");
102 		return(p1);
103 	}
104 
105 	if(EQ(a, "-f"))
106 		return(isreg(nxtarg(0)));
107 
108 	if(EQ(a, "-d"))
109 		return(isdir(nxtarg(0)));
110 
111 	if(EQ(a, "-r"))
112 		return(tio(nxtarg(0), 4));
113 
114 	if(EQ(a, "-w"))
115 		return(tio(nxtarg(0), 2));
116 
117 	if(EQ(a, "-x"))
118 		return(tio(nxtarg(0), 1));
119 
120 	if(EQ(a, "-e"))
121 		return(tio(nxtarg(0), 0));
122 
123 	if(EQ(a, "-c"))
124 		return(0);
125 
126 	if(EQ(a, "-b"))
127 		return(0);
128 
129 	if(EQ(a, "-u"))
130 		return(0);
131 
132 	if(EQ(a, "-g"))
133 		return(0);
134 
135 	if(EQ(a, "-s"))
136 		return(fsizep(nxtarg(0)));
137 
138 	if(EQ(a, "-t"))
139 		if(ap>=ac || !nxtintarg(&int1))
140 			return(isatty(1));
141 		else
142 			return(isatty(int1));
143 
144 	if(EQ(a, "-n"))
145 		return(!EQ(nxtarg(0), ""));
146 	if(EQ(a, "-z"))
147 		return(EQ(nxtarg(0), ""));
148 
149 	p2 = nxtarg(1);
150 	if (p2==0)
151 		return(!EQ(a,""));
152 	if(EQ(p2, "="))
153 		return(EQ(nxtarg(0), a));
154 
155 	if(EQ(p2, "!="))
156 		return(!EQ(nxtarg(0), a));
157 
158 	if(!isint(a, &int1))
159 		return(!EQ(a,""));
160 
161 	if(nxtintarg(&int2)){
162 		if(EQ(p2, "-eq"))
163 			return(int1==int2);
164 		if(EQ(p2, "-ne"))
165 			return(int1!=int2);
166 		if(EQ(p2, "-gt"))
167 			return(int1>int2);
168 		if(EQ(p2, "-lt"))
169 			return(int1<int2);
170 		if(EQ(p2, "-ge"))
171 			return(int1>=int2);
172 		if(EQ(p2, "-le"))
173 			return(int1<=int2);
174 	}
175 
176 	synbad("unknown operator ",p2);
177 	return 0;		/* to shut ken up */
178 }
179 
180 int
181 tio(char *a, int f)
182 {
183 	return access (a, f) >= 0;
184 }
185 
186 int
187 isdir(char *f)
188 {
189 	Dir dir;
190 
191 	if(dirstat(f,&dir)<0)
192 		return(0);
193 	return(dir.mode&CHDIR);
194 }
195 
196 int
197 isreg(char *f)
198 {
199 	Dir dir;
200 
201 	if(dirstat(f,&dir)<0)
202 		return(0);
203 	return(!(dir.mode&CHDIR));
204 }
205 
206 int
207 isatty(int fd)
208 {
209 	Dir d1, d2;
210 
211 	if(dirfstat(fd, &d1) < 0)
212 		return 0;
213 	if(dirstat("/dev/cons", &d2) < 0)
214 		return 0;
215 	return d1.type==d2.type && d1.dev==d2.dev && d1.qid.path==d2.qid.path;
216 }
217 
218 int
219 fsizep(char *f)
220 {
221 	Dir dir;
222 	if(dirstat(f,&dir)<0)
223 		return(0);
224 	return(dir.length>0);
225 }
226 
227 void
228 synbad(char *s1, char *s2)
229 {
230 	int len;
231 
232 	write(2, "test: ", 6);
233 	if ((len = strlen(s1)) != 0)
234 		write(2, s1, len);
235 	if ((len = strlen(s2)) != 0)
236 		write(2, s2, len);
237 	write(2, "\n", 1);
238 	exits("bad syntax");
239 }
240 
241 int
242 length(char *s)
243 {
244 	char *es=s;
245 	while(*es++);
246 	return(es-s-1);
247 }
248 
249 int
250 isint(char *s, int *pans)
251 {
252 	char *ep;
253 
254 	*pans = strtol(s, &ep, 0);
255 	return (*ep == 0);
256 }
257