1 /* $NetBSD: test.c,v 1.37 2008/09/10 19:00:51 christos Exp $ */ 2 3 /* 4 * test(1); version 7-like -- author Erik Baalbergen 5 * modified by Eric Gisin to be used as built-in. 6 * modified by Arnold Robbins to add SVR3 compatibility 7 * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). 8 * modified by J.T. Conklin for NetBSD. 9 * 10 * This program is in the Public Domain. 11 */ 12 13 #include <sys/cdefs.h> 14 #ifndef lint 15 __RCSID("$NetBSD: test.c,v 1.37 2008/09/10 19:00:51 christos Exp $"); 16 #endif 17 18 #include <sys/stat.h> 19 #include <sys/types.h> 20 21 #include <ctype.h> 22 #include <err.h> 23 #include <errno.h> 24 #include <limits.h> 25 #include <locale.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 #include <stdarg.h> 31 32 /* test(1) accepts the following grammar: 33 oexpr ::= aexpr | aexpr "-o" oexpr ; 34 aexpr ::= nexpr | nexpr "-a" aexpr ; 35 nexpr ::= primary | "!" primary 36 primary ::= unary-operator operand 37 | operand binary-operator operand 38 | operand 39 | "(" oexpr ")" 40 ; 41 unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"| 42 "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S"; 43 44 binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| 45 "-nt"|"-ot"|"-ef"; 46 operand ::= <any legal UNIX file name> 47 */ 48 49 enum token { 50 EOI, 51 FILRD, 52 FILWR, 53 FILEX, 54 FILEXIST, 55 FILREG, 56 FILDIR, 57 FILCDEV, 58 FILBDEV, 59 FILFIFO, 60 FILSOCK, 61 FILSYM, 62 FILGZ, 63 FILTT, 64 FILSUID, 65 FILSGID, 66 FILSTCK, 67 FILNT, 68 FILOT, 69 FILEQ, 70 FILUID, 71 FILGID, 72 STREZ, 73 STRNZ, 74 STREQ, 75 STRNE, 76 STRLT, 77 STRGT, 78 INTEQ, 79 INTNE, 80 INTGE, 81 INTGT, 82 INTLE, 83 INTLT, 84 UNOT, 85 BAND, 86 BOR, 87 LPAREN, 88 RPAREN, 89 OPERAND 90 }; 91 92 enum token_types { 93 UNOP, 94 BINOP, 95 BUNOP, 96 BBINOP, 97 PAREN 98 }; 99 100 struct t_op { 101 const char *op_text; 102 short op_num, op_type; 103 }; 104 105 static const struct t_op cop[] = { 106 {"!", UNOT, BUNOP}, 107 {"(", LPAREN, PAREN}, 108 {")", RPAREN, PAREN}, 109 {"<", STRLT, BINOP}, 110 {"=", STREQ, BINOP}, 111 {">", STRGT, BINOP}, 112 }; 113 114 static const struct t_op cop2[] = { 115 {"!=", STRNE, BINOP}, 116 }; 117 118 static const struct t_op mop3[] = { 119 {"ef", FILEQ, BINOP}, 120 {"eq", INTEQ, BINOP}, 121 {"ge", INTGE, BINOP}, 122 {"gt", INTGT, BINOP}, 123 {"le", INTLE, BINOP}, 124 {"lt", INTLT, BINOP}, 125 {"ne", INTNE, BINOP}, 126 {"nt", FILNT, BINOP}, 127 {"ot", FILOT, BINOP}, 128 }; 129 130 static const struct t_op mop2[] = { 131 {"G", FILGID, UNOP}, 132 {"L", FILSYM, UNOP}, 133 {"O", FILUID, UNOP}, 134 {"S", FILSOCK,UNOP}, 135 {"a", BAND, BBINOP}, 136 {"b", FILBDEV,UNOP}, 137 {"c", FILCDEV,UNOP}, 138 {"d", FILDIR, UNOP}, 139 {"e", FILEXIST,UNOP}, 140 {"f", FILREG, UNOP}, 141 {"g", FILSGID,UNOP}, 142 {"h", FILSYM, UNOP}, /* for backwards compat */ 143 {"k", FILSTCK,UNOP}, 144 {"n", STRNZ, UNOP}, 145 {"o", BOR, BBINOP}, 146 {"p", FILFIFO,UNOP}, 147 {"r", FILRD, UNOP}, 148 {"s", FILGZ, UNOP}, 149 {"t", FILTT, UNOP}, 150 {"u", FILSUID,UNOP}, 151 {"w", FILWR, UNOP}, 152 {"x", FILEX, UNOP}, 153 {"z", STREZ, UNOP}, 154 }; 155 156 static char **t_wp; 157 static struct t_op const *t_wp_op; 158 159 static void syntax(const char *, const char *); 160 static int oexpr(enum token); 161 static int aexpr(enum token); 162 static int nexpr(enum token); 163 static int primary(enum token); 164 static int binop(void); 165 static int test_access(struct stat *, mode_t); 166 static int filstat(char *, enum token); 167 static enum token t_lex(char *); 168 static int isoperand(void); 169 static long long getn(const char *); 170 static int newerf(const char *, const char *); 171 static int olderf(const char *, const char *); 172 static int equalf(const char *, const char *); 173 174 #if defined(SHELL) 175 extern void error(const char *, ...) __dead; 176 extern void *ckmalloc(size_t); 177 #else 178 static void error(const char *, ...) __dead; 179 180 static void 181 error(const char *msg, ...) 182 { 183 va_list ap; 184 185 va_start(ap, msg); 186 verrx(2, msg, ap); 187 /*NOTREACHED*/ 188 va_end(ap); 189 } 190 191 static void *ckmalloc(size_t); 192 static void * 193 ckmalloc(size_t nbytes) 194 { 195 void *p = malloc(nbytes); 196 197 if (!p) 198 error("Not enough memory!"); 199 return p; 200 } 201 #endif 202 203 #ifdef SHELL 204 int testcmd(int, char **); 205 206 int 207 testcmd(int argc, char **argv) 208 #else 209 int main(int, char *[]); 210 211 int 212 main(int argc, char *argv[]) 213 #endif 214 { 215 int res; 216 const char *argv0; 217 218 #ifdef SHELL 219 argv0 = argv[0]; 220 #else 221 setprogname(argv[0]); 222 (void)setlocale(LC_ALL, ""); 223 argv0 = getprogname(); 224 #endif 225 if (strcmp(argv0, "[") == 0) { 226 if (strcmp(argv[--argc], "]")) 227 error("missing ]"); 228 argv[argc] = NULL; 229 } 230 231 if (argc < 2) 232 return 1; 233 234 t_wp = &argv[1]; 235 res = !oexpr(t_lex(*t_wp)); 236 237 if (*t_wp != NULL && *++t_wp != NULL) 238 syntax(*t_wp, "unexpected operator"); 239 240 return res; 241 } 242 243 static void 244 syntax(const char *op, const char *msg) 245 { 246 247 if (op && *op) 248 error("%s: %s", op, msg); 249 else 250 error("%s", msg); 251 } 252 253 static int 254 oexpr(enum token n) 255 { 256 int res; 257 258 res = aexpr(n); 259 if (*t_wp == NULL) 260 return res; 261 if (t_lex(*++t_wp) == BOR) 262 return oexpr(t_lex(*++t_wp)) || res; 263 t_wp--; 264 return res; 265 } 266 267 static int 268 aexpr(enum token n) 269 { 270 int res; 271 272 res = nexpr(n); 273 if (*t_wp == NULL) 274 return res; 275 if (t_lex(*++t_wp) == BAND) 276 return aexpr(t_lex(*++t_wp)) && res; 277 t_wp--; 278 return res; 279 } 280 281 static int 282 nexpr(enum token n) 283 { 284 285 if (n == UNOT) 286 return !nexpr(t_lex(*++t_wp)); 287 return primary(n); 288 } 289 290 static int 291 primary(enum token n) 292 { 293 enum token nn; 294 int res; 295 296 if (n == EOI) 297 return 0; /* missing expression */ 298 if (n == LPAREN) { 299 if ((nn = t_lex(*++t_wp)) == RPAREN) 300 return 0; /* missing expression */ 301 res = oexpr(nn); 302 if (t_lex(*++t_wp) != RPAREN) 303 syntax(NULL, "closing paren expected"); 304 return res; 305 } 306 if (t_wp_op && t_wp_op->op_type == UNOP) { 307 /* unary expression */ 308 if (*++t_wp == NULL) 309 syntax(t_wp_op->op_text, "argument expected"); 310 switch (n) { 311 case STREZ: 312 return strlen(*t_wp) == 0; 313 case STRNZ: 314 return strlen(*t_wp) != 0; 315 case FILTT: 316 return isatty((int)getn(*t_wp)); 317 default: 318 return filstat(*t_wp, n); 319 } 320 } 321 322 if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) { 323 return binop(); 324 } 325 326 return strlen(*t_wp) > 0; 327 } 328 329 static int 330 binop(void) 331 { 332 const char *opnd1, *opnd2; 333 struct t_op const *op; 334 335 opnd1 = *t_wp; 336 (void) t_lex(*++t_wp); 337 op = t_wp_op; 338 339 if ((opnd2 = *++t_wp) == NULL) 340 syntax(op->op_text, "argument expected"); 341 342 switch (op->op_num) { 343 case STREQ: 344 return strcmp(opnd1, opnd2) == 0; 345 case STRNE: 346 return strcmp(opnd1, opnd2) != 0; 347 case STRLT: 348 return strcmp(opnd1, opnd2) < 0; 349 case STRGT: 350 return strcmp(opnd1, opnd2) > 0; 351 case INTEQ: 352 return getn(opnd1) == getn(opnd2); 353 case INTNE: 354 return getn(opnd1) != getn(opnd2); 355 case INTGE: 356 return getn(opnd1) >= getn(opnd2); 357 case INTGT: 358 return getn(opnd1) > getn(opnd2); 359 case INTLE: 360 return getn(opnd1) <= getn(opnd2); 361 case INTLT: 362 return getn(opnd1) < getn(opnd2); 363 case FILNT: 364 return newerf(opnd1, opnd2); 365 case FILOT: 366 return olderf(opnd1, opnd2); 367 case FILEQ: 368 return equalf(opnd1, opnd2); 369 default: 370 abort(); 371 /* NOTREACHED */ 372 } 373 } 374 375 /* 376 * The manual, and IEEE POSIX 1003.2, suggests this should check the mode bits, 377 * not use access(): 378 * 379 * True shall indicate only that the write flag is on. The file is not 380 * writable on a read-only file system even if this test indicates true. 381 * 382 * Unfortunately IEEE POSIX 1003.1-2001, as quoted in SuSv3, says only: 383 * 384 * True shall indicate that permission to read from file will be granted, 385 * as defined in "File Read, Write, and Creation". 386 * 387 * and that section says: 388 * 389 * When a file is to be read or written, the file shall be opened with an 390 * access mode corresponding to the operation to be performed. If file 391 * access permissions deny access, the requested operation shall fail. 392 * 393 * and of course access permissions are described as one might expect: 394 * 395 * * If a process has the appropriate privilege: 396 * 397 * * If read, write, or directory search permission is requested, 398 * access shall be granted. 399 * 400 * * If execute permission is requested, access shall be granted if 401 * execute permission is granted to at least one user by the file 402 * permission bits or by an alternate access control mechanism; 403 * otherwise, access shall be denied. 404 * 405 * * Otherwise: 406 * 407 * * The file permission bits of a file contain read, write, and 408 * execute/search permissions for the file owner class, file group 409 * class, and file other class. 410 * 411 * * Access shall be granted if an alternate access control mechanism 412 * is not enabled and the requested access permission bit is set for 413 * the class (file owner class, file group class, or file other class) 414 * to which the process belongs, or if an alternate access control 415 * mechanism is enabled and it allows the requested access; otherwise, 416 * access shall be denied. 417 * 418 * and when I first read this I thought: surely we can't go about using 419 * open(O_WRONLY) to try this test! However the POSIX 1003.1-2001 Rationale 420 * section for test does in fact say: 421 * 422 * On historical BSD systems, test -w directory always returned false 423 * because test tried to open the directory for writing, which always 424 * fails. 425 * 426 * and indeed this is in fact true for Seventh Edition UNIX, UNIX 32V, and UNIX 427 * System III, and thus presumably also for BSD up to and including 4.3. 428 * 429 * Secondly I remembered why using open() and/or access() are bogus. They 430 * don't work right for detecting read and write permissions bits when called 431 * by root. 432 * 433 * Interestingly the 'test' in 4.4BSD was closer to correct (as per 434 * 1003.2-1992) and it was implemented efficiently with stat() instead of 435 * open(). 436 * 437 * This was apparently broken in NetBSD around about 1994/06/30 when the old 438 * 4.4BSD implementation was replaced with a (arguably much better coded) 439 * implementation derived from pdksh. 440 * 441 * Note that modern pdksh is yet different again, but still not correct, at 442 * least not w.r.t. 1003.2-1992. 443 * 444 * As I think more about it and read more of the related IEEE docs I don't like 445 * that wording about 'test -r' and 'test -w' in 1003.1-2001 at all. I very 446 * much prefer the original wording in 1003.2-1992. It is much more useful, 447 * and so that's what I've implemented. 448 * 449 * (Note that a strictly conforming implementation of 1003.1-2001 is in fact 450 * totally useless for the case in question since its 'test -w' and 'test -r' 451 * can never fail for root for any existing files, i.e. files for which 'test 452 * -e' succeeds.) 453 * 454 * The rationale for 1003.1-2001 suggests that the wording was "clarified" in 455 * 1003.1-2001 to align with the 1003.2b draft. 1003.2b Draft 12 (July 1999), 456 * which is the latest copy I have, does carry the same suggested wording as is 457 * in 1003.1-2001, with its rationale saying: 458 * 459 * This change is a clarification and is the result of interpretation 460 * request PASC 1003.2-92 #23 submitted for IEEE Std 1003.2-1992. 461 * 462 * That interpretation can be found here: 463 * 464 * http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-23.html 465 * 466 * Not terribly helpful, unfortunately. I wonder who that fence sitter was. 467 * 468 * Worse, IMVNSHO, I think the authors of 1003.2b-D12 have mis-interpreted the 469 * PASC interpretation and appear to be gone against at least one widely used 470 * implementation (namely 4.4BSD). The problem is that for file access by root 471 * this means that if test '-r' and '-w' are to behave as if open() were called 472 * then there's no way for a shell script running as root to check if a file 473 * has certain access bits set other than by the grotty means of interpreting 474 * the output of 'ls -l'. This was widely considered to be a bug in V7's 475 * "test" and is, I believe, one of the reasons why direct use of access() was 476 * avoided in some more recent implementations! 477 * 478 * I have always interpreted '-r' to match '-w' and '-x' as per the original 479 * wording in 1003.2-1992, not the other way around. I think 1003.2b goes much 480 * too far the wrong way without any valid rationale and that it's best if we 481 * stick with 1003.2-1992 and test the flags, and not mimic the behaviour of 482 * open() since we already know very well how it will work -- existance of the 483 * file is all that matters to open() for root. 484 * 485 * Unfortunately the SVID is no help at all (which is, I guess, partly why 486 * we're in this mess in the first place :-). 487 * 488 * The SysV implementation (at least in the 'test' builtin in /bin/sh) does use 489 * access(name, 2) even though it also goes to much greater lengths for '-x' 490 * matching the 1003.2-1992 definition (which is no doubt where that definition 491 * came from). 492 * 493 * The ksh93 implementation uses access() for '-r' and '-w' if 494 * (euid==uid&&egid==gid), but uses st_mode for '-x' iff running as root. 495 * i.e. it does strictly conform to 1003.1-2001 (and presumably 1003.2b). 496 */ 497 static int 498 test_access(struct stat *sp, mode_t stmode) 499 { 500 gid_t *groups; 501 register int n; 502 uid_t euid; 503 int maxgroups; 504 505 /* 506 * I suppose we could use access() if not running as root and if we are 507 * running with ((euid == uid) && (egid == gid)), but we've already 508 * done the stat() so we might as well just test the permissions 509 * directly instead of asking the kernel to do it.... 510 */ 511 euid = geteuid(); 512 if (euid == 0) /* any bit is good enough */ 513 stmode = (stmode << 6) | (stmode << 3) | stmode; 514 else if (sp->st_uid == euid) 515 stmode <<= 6; 516 else if (sp->st_gid == getegid()) 517 stmode <<= 3; 518 else { 519 /* XXX stolen almost verbatim from ksh93.... */ 520 /* on some systems you can be in several groups */ 521 if ((maxgroups = getgroups(0, NULL)) <= 0) 522 maxgroups = NGROUPS_MAX; /* pre-POSIX system? */ 523 groups = ckmalloc((maxgroups + 1) * sizeof(gid_t)); 524 n = getgroups(maxgroups, groups); 525 while (--n >= 0) { 526 if (groups[n] == sp->st_gid) { 527 stmode <<= 3; 528 break; 529 } 530 } 531 free(groups); 532 } 533 534 return sp->st_mode & stmode; 535 } 536 537 static int 538 filstat(char *nm, enum token mode) 539 { 540 struct stat s; 541 542 if (mode == FILSYM ? lstat(nm, &s) : stat(nm, &s)) 543 return 0; 544 545 switch (mode) { 546 case FILRD: 547 return test_access(&s, S_IROTH); 548 case FILWR: 549 return test_access(&s, S_IWOTH); 550 case FILEX: 551 return test_access(&s, S_IXOTH); 552 case FILEXIST: 553 return 1; /* the successful lstat()/stat() is good enough */ 554 case FILREG: 555 return S_ISREG(s.st_mode); 556 case FILDIR: 557 return S_ISDIR(s.st_mode); 558 case FILCDEV: 559 return S_ISCHR(s.st_mode); 560 case FILBDEV: 561 return S_ISBLK(s.st_mode); 562 case FILFIFO: 563 return S_ISFIFO(s.st_mode); 564 case FILSOCK: 565 return S_ISSOCK(s.st_mode); 566 case FILSYM: 567 return S_ISLNK(s.st_mode); 568 case FILSUID: 569 return (s.st_mode & S_ISUID) != 0; 570 case FILSGID: 571 return (s.st_mode & S_ISGID) != 0; 572 case FILSTCK: 573 return (s.st_mode & S_ISVTX) != 0; 574 case FILGZ: 575 return s.st_size > (off_t)0; 576 case FILUID: 577 return s.st_uid == geteuid(); 578 case FILGID: 579 return s.st_gid == getegid(); 580 default: 581 return 1; 582 } 583 } 584 585 #define VTOC(x) (const unsigned char *)((const struct t_op *)x)->op_text 586 587 static int 588 compare1(const void *va, const void *vb) 589 { 590 const unsigned char *a = va; 591 const unsigned char *b = VTOC(vb); 592 593 return a[0] - b[0]; 594 } 595 596 static int 597 compare2(const void *va, const void *vb) 598 { 599 const unsigned char *a = va; 600 const unsigned char *b = VTOC(vb); 601 int z = a[0] - b[0]; 602 603 return z ? z : (a[1] - b[1]); 604 } 605 606 static struct t_op const * 607 findop(const char *s) 608 { 609 if (s[0] == '-') { 610 if (s[1] == '\0') 611 return NULL; 612 if (s[2] == '\0') 613 return bsearch(s + 1, mop2, __arraycount(mop2), 614 sizeof(*mop2), compare1); 615 else if (s[3] != '\0') 616 return NULL; 617 else 618 return bsearch(s + 1, mop3, __arraycount(mop3), 619 sizeof(*mop3), compare2); 620 } else { 621 if (s[1] == '\0') 622 return bsearch(s, cop, __arraycount(cop), sizeof(*cop), 623 compare1); 624 else if (strcmp(s, cop2[0].op_text) == 0) 625 return cop2; 626 else 627 return NULL; 628 } 629 } 630 631 static enum token 632 t_lex(char *s) 633 { 634 struct t_op const *op; 635 636 if (s == NULL) { 637 t_wp_op = NULL; 638 return EOI; 639 } 640 641 if ((op = findop(s)) != NULL) { 642 if (!((op->op_type == UNOP && isoperand()) || 643 (op->op_num == LPAREN && *(t_wp+1) == 0))) { 644 t_wp_op = op; 645 return op->op_num; 646 } 647 } 648 t_wp_op = NULL; 649 return OPERAND; 650 } 651 652 static int 653 isoperand(void) 654 { 655 struct t_op const *op; 656 char *s, *t; 657 658 if ((s = *(t_wp+1)) == 0) 659 return 1; 660 if ((t = *(t_wp+2)) == 0) 661 return 0; 662 if ((op = findop(s)) != NULL) 663 return op->op_type == BINOP && (t[0] != ')' || t[1] != '\0'); 664 return 0; 665 } 666 667 /* atoi with error detection */ 668 static long long 669 getn(const char *s) 670 { 671 char *p; 672 long long r; 673 674 errno = 0; 675 r = strtoll(s, &p, 10); 676 677 if (errno != 0) 678 if (errno == ERANGE && (r == LLONG_MAX || r == LLONG_MIN)) 679 error("%s: out of range", s); 680 681 while (isspace((unsigned char)*p)) 682 p++; 683 684 if (*p || p == s) 685 error("%s: bad number", s); 686 687 return r; 688 } 689 690 static int 691 newerf(const char *f1, const char *f2) 692 { 693 struct stat b1, b2; 694 695 return (stat(f1, &b1) == 0 && 696 stat(f2, &b2) == 0 && 697 b1.st_mtime > b2.st_mtime); 698 } 699 700 static int 701 olderf(const char *f1, const char *f2) 702 { 703 struct stat b1, b2; 704 705 return (stat(f1, &b1) == 0 && 706 stat(f2, &b2) == 0 && 707 b1.st_mtime < b2.st_mtime); 708 } 709 710 static int 711 equalf(const char *f1, const char *f2) 712 { 713 struct stat b1, b2; 714 715 return (stat(f1, &b1) == 0 && 716 stat(f2, &b2) == 0 && 717 b1.st_dev == b2.st_dev && 718 b1.st_ino == b2.st_ino); 719 } 720