Home | History | Annotate | Download | only in test
      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
     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 *
     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
     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
     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
    111 e2(void)
    112 {
    113 	if (EQ(nxtarg(0), "!"))
    114 		return (!e3());
    115 	ap--;
    116 	return (e3());
    117 }
    118 
    119 static int
    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
    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
    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
    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
    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
    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