plan9port

[fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port # fast
git clone https://src.adamsgaard.dk/plan9port.git # slow
Log | Files | Refs | README | LICENSE Back to index

test.c (5813B)


      1 /*
      2  * POSIX standard
      3  *	test expression
      4  *	[ expression ]
      5  *
      6  * Plan 9 additions:
      7  *	-A file exists and is append-only
      8  *	-L file exists and is exclusive-use
      9  *	-T file exists and is temporary
     10  */
     11 
     12 #include <u.h>
     13 #include <libc.h>
     14 
     15 #define isatty plan9_isatty
     16 
     17 #define EQ(a,b)	((tmp=a)==0?0:(strcmp(tmp,b)==0))
     18 
     19 int	ap;
     20 int	ac;
     21 char	**av;
     22 char	*tmp;
     23 
     24 void	synbad(char *, char *);
     25 int	fsizep(char *);
     26 int	isdir(char *);
     27 int	isreg(char *);
     28 int	isatty(int);
     29 int	isint(char *, int *);
     30 int	isolder(char *, char *);
     31 int	isolderthan(char *, char *);
     32 int	isnewerthan(char *, char *);
     33 int	hasmode(char *, ulong);
     34 int	tio(char *, int);
     35 int	e(void), e1(void), e2(void), e3(void);
     36 char	*nxtarg(int);
     37 
     38 void
     39 main(int argc, char *argv[])
     40 {
     41 	int r;
     42 	char *c;
     43 
     44 	ac = argc; av = argv; ap = 1;
     45 	if(EQ(argv[0],"[")) {
     46 		if(!EQ(argv[--ac],"]"))
     47 			synbad("] missing","");
     48 	}
     49 	argv[ac] = 0;
     50 	if (ac<=1)
     51 		exits("usage");
     52 	r = e();
     53 	/*
     54 	 * nice idea but short-circuit -o and -a operators may have
     55 	 * not consumed their right-hand sides.
     56 	 */
     57 	if(0 && (c = nxtarg(1)) != nil)
     58 		synbad("unexpected operator/operand: ", c);
     59 	exits(r?0:"false");
     60 }
     61 
     62 char *
     63 nxtarg(int mt)
     64 {
     65 	if(ap>=ac){
     66 		if(mt){
     67 			ap++;
     68 			return(0);
     69 		}
     70 		synbad("argument expected","");
     71 	}
     72 	return(av[ap++]);
     73 }
     74 
     75 int
     76 nxtintarg(int *pans)
     77 {
     78 	if(ap<ac && isint(av[ap], pans)){
     79 		ap++;
     80 		return 1;
     81 	}
     82 	return 0;
     83 }
     84 
     85 int
     86 e(void)
     87 {
     88 	int p1;
     89 
     90 	p1 = e1();
     91 	if (EQ(nxtarg(1), "-o"))
     92 		return(p1 || e());
     93 	ap--;
     94 	return(p1);
     95 }
     96 
     97 int
     98 e1(void)
     99 {
    100 	int p1;
    101 
    102 	p1 = e2();
    103 	if (EQ(nxtarg(1), "-a"))
    104 		return (p1 && e1());
    105 	ap--;
    106 	return(p1);
    107 }
    108 
    109 int
    110 e2(void)
    111 {
    112 	if (EQ(nxtarg(0), "!"))
    113 		return(!e2());
    114 	ap--;
    115 	return(e3());
    116 }
    117 
    118 int
    119 e3(void)
    120 {
    121 	int p1, int1, int2;
    122 	char *a, *p2;
    123 
    124 	a = nxtarg(0);
    125 	if(EQ(a, "(")) {
    126 		p1 = e();
    127 		if(!EQ(nxtarg(0), ")"))
    128 			synbad(") expected","");
    129 		return(p1);
    130 	}
    131 
    132 	if(EQ(a, "-A"))
    133 		return(hasmode(nxtarg(0), DMAPPEND));
    134 
    135 	if(EQ(a, "-L"))
    136 		return(hasmode(nxtarg(0), DMEXCL));
    137 
    138 	if(EQ(a, "-T"))
    139 		return(hasmode(nxtarg(0), DMTMP));
    140 
    141 	if(EQ(a, "-f"))
    142 		return(isreg(nxtarg(0)));
    143 
    144 	if(EQ(a, "-d"))
    145 		return(isdir(nxtarg(0)));
    146 
    147 	if(EQ(a, "-r"))
    148 		return(tio(nxtarg(0), 4));
    149 
    150 	if(EQ(a, "-w"))
    151 		return(tio(nxtarg(0), 2));
    152 
    153 	if(EQ(a, "-x"))
    154 		return(tio(nxtarg(0), 1));
    155 
    156 	if(EQ(a, "-e"))
    157 		return(tio(nxtarg(0), 0));
    158 
    159 	if(EQ(a, "-c"))
    160 		return(0);
    161 
    162 	if(EQ(a, "-b"))
    163 		return(0);
    164 
    165 	if(EQ(a, "-u"))
    166 		return(0);
    167 
    168 	if(EQ(a, "-g"))
    169 		return(0);
    170 
    171 	if(EQ(a, "-s"))
    172 		return(fsizep(nxtarg(0)));
    173 
    174 	if(EQ(a, "-t"))
    175 		if(ap>=ac)
    176 			return(isatty(1));
    177 		else if(nxtintarg(&int1))
    178 			return(isatty(int1));
    179 		else
    180 			synbad("not a valid file descriptor number ", "");
    181 
    182 	if(EQ(a, "-n"))
    183 		return(!EQ(nxtarg(0), ""));
    184 	if(EQ(a, "-z"))
    185 		return(EQ(nxtarg(0), ""));
    186 
    187 	p2 = nxtarg(1);
    188 	if (p2==0)
    189 		return(!EQ(a,""));
    190 	if(EQ(p2, "="))
    191 		return(EQ(nxtarg(0), a));
    192 
    193 	if(EQ(p2, "!="))
    194 		return(!EQ(nxtarg(0), a));
    195 
    196 	if(EQ(p2, "-older"))
    197 		return(isolder(nxtarg(0), a));
    198 
    199 	if(EQ(p2, "-ot"))
    200 		return(isolderthan(nxtarg(0), a));
    201 
    202 	if(EQ(p2, "-nt"))
    203 		return(isnewerthan(nxtarg(0), a));
    204 
    205 	if(!isint(a, &int1))
    206 		synbad("unexpected operator/operand: ", p2);
    207 
    208 	if(nxtintarg(&int2)){
    209 		if(EQ(p2, "-eq"))
    210 			return(int1==int2);
    211 		if(EQ(p2, "-ne"))
    212 			return(int1!=int2);
    213 		if(EQ(p2, "-gt"))
    214 			return(int1>int2);
    215 		if(EQ(p2, "-lt"))
    216 			return(int1<int2);
    217 		if(EQ(p2, "-ge"))
    218 			return(int1>=int2);
    219 		if(EQ(p2, "-le"))
    220 			return(int1<=int2);
    221 	}
    222 
    223 	synbad("unknown operator ",p2);
    224 	return 0;		/* to shut ken up */
    225 }
    226 
    227 int
    228 tio(char *a, int f)
    229 {
    230 	return access (a, f) >= 0;
    231 }
    232 
    233 /*
    234  * note that the name strings pointed to by Dir members are
    235  * allocated with the Dir itself (by the same call to malloc),
    236  * but are not included in sizeof(Dir), so copying a Dir won't
    237  * copy the strings it points to.
    238  */
    239 
    240 int
    241 hasmode(char *f, ulong m)
    242 {
    243 	int r;
    244 	Dir *dir;
    245 
    246 	dir = dirstat(f);
    247 	if (dir == nil)
    248 		return 0;
    249 	r = (dir->mode & m) != 0;
    250 	free(dir);
    251 	return r;
    252 }
    253 
    254 int
    255 isdir(char *f)
    256 {
    257 	return hasmode(f, DMDIR);
    258 }
    259 
    260 int
    261 isreg(char *f)
    262 {
    263 	int r;
    264 	Dir *dir;
    265 
    266 	dir = dirstat(f);
    267 	if (dir == nil)
    268 		return 0;
    269 	r = (dir->mode & DMDIR) == 0;
    270 	free(dir);
    271 	return r;
    272 }
    273 
    274 int
    275 isatty(int fd)
    276 {
    277 	int r;
    278 	Dir *d1, *d2;
    279 
    280 	d1 = dirfstat(fd);
    281 	d2 = dirstat("/dev/cons");
    282 	if (d1 == nil || d2 == nil)
    283 		r = 0;
    284 	else
    285 		r = d1->type == d2->type && d1->dev == d2->dev &&
    286 			d1->qid.path == d2->qid.path;
    287 	free(d1);
    288 	free(d2);
    289 	return r;
    290 }
    291 
    292 int
    293 fsizep(char *f)
    294 {
    295 	int r;
    296 	Dir *dir;
    297 
    298 	dir = dirstat(f);
    299 	if (dir == nil)
    300 		return 0;
    301 	r = dir->length > 0;
    302 	free(dir);
    303 	return r;
    304 }
    305 
    306 void
    307 synbad(char *s1, char *s2)
    308 {
    309 	int len;
    310 
    311 	write(2, "test: ", 6);
    312 	if ((len = strlen(s1)) != 0)
    313 		write(2, s1, len);
    314 	if ((len = strlen(s2)) != 0)
    315 		write(2, s2, len);
    316 	write(2, "\n", 1);
    317 	exits("bad syntax");
    318 }
    319 
    320 int
    321 isint(char *s, int *pans)
    322 {
    323 	char *ep;
    324 
    325 	*pans = strtol(s, &ep, 0);
    326 	return (*ep == 0);
    327 }
    328 
    329 int
    330 isolder(char *pin, char *f)
    331 {
    332 	int r;
    333 	ulong n, m;
    334 	char *p = pin;
    335 	Dir *dir;
    336 
    337 	dir = dirstat(f);
    338 	if (dir == nil)
    339 		return 0;
    340 
    341 	/* parse time */
    342 	n = 0;
    343 	while(*p){
    344 		m = strtoul(p, &p, 0);
    345 		switch(*p){
    346 		case 0:
    347 			n = m;
    348 			break;
    349 		case 'y':
    350 			m *= 12;
    351 			/* fall through */
    352 		case 'M':
    353 			m *= 30;
    354 			/* fall through */
    355 		case 'd':
    356 			m *= 24;
    357 			/* fall through */
    358 		case 'h':
    359 			m *= 60;
    360 			/* fall through */
    361 		case 'm':
    362 			m *= 60;
    363 			/* fall through */
    364 		case 's':
    365 			n += m;
    366 			p++;
    367 			break;
    368 		default:
    369 			synbad("bad time syntax, ", pin);
    370 		}
    371 	}
    372 
    373 	r = dir->mtime + n < time(0);
    374 	free(dir);
    375 	return r;
    376 }
    377 
    378 int
    379 isolderthan(char *a, char *b)
    380 {
    381 	int r;
    382 	Dir *ad, *bd;
    383 
    384 	ad = dirstat(a);
    385 	bd = dirstat(b);
    386 	if (ad == nil || bd == nil)
    387 		r = 0;
    388 	else
    389 		r = ad->mtime > bd->mtime;
    390 	free(ad);
    391 	free(bd);
    392 	return r;
    393 }
    394 
    395 int
    396 isnewerthan(char *a, char *b)
    397 {
    398 	int r;
    399 	Dir *ad, *bd;
    400 
    401 	ad = dirstat(a);
    402 	bd = dirstat(b);
    403 	if (ad == nil || bd == nil)
    404 		r = 0;
    405 	else
    406 		r = ad->mtime < bd->mtime;
    407 	free(ad);
    408 	free(bd);
    409 	return r;
    410 }