1 /* $NetBSD: test.c,v 1.41 2016/09/05 01:00:07 sevan 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.41 2016/09/05 01:00:07 sevan 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 __dead 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 __printflike(1, 2); 176 extern void *ckmalloc(size_t); 177 #else 178 static void error(const char *, ...) __dead __printflike(1, 2); 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 210 main(int argc, char *argv[]) 211 #endif 212 { 213 int res; 214 const char *argv0; 215 216 #ifdef SHELL 217 argv0 = argv[0]; 218 #else 219 setprogname(argv[0]); 220 (void)setlocale(LC_ALL, ""); 221 argv0 = getprogname(); 222 #endif 223 if (strcmp(argv0, "[") == 0) { 224 if (strcmp(argv[--argc], "]")) 225 error("missing ]"); 226 argv[argc] = NULL; 227 } 228 229 if (argc < 2) 230 return 1; 231 232 t_wp = &argv[1]; 233 res = !oexpr(t_lex(*t_wp)); 234 235 if (*t_wp != NULL && *++t_wp != NULL) 236 syntax(*t_wp, "unexpected operator"); 237 238 return res; 239 } 240 241 static void 242 syntax(const char *op, const char *msg) 243 { 244 245 if (op && *op) 246 error("%s: %s", op, msg); 247 else 248 error("%s", msg); 249 } 250 251 static int 252 oexpr(enum token n) 253 { 254 int res; 255 256 res = aexpr(n); 257 if (*t_wp == NULL) 258 return res; 259 if (t_lex(*++t_wp) == BOR) 260 return oexpr(t_lex(*++t_wp)) || res; 261 t_wp--; 262 return res; 263 } 264 265 static int 266 aexpr(enum token n) 267 { 268 int res; 269 270 res = nexpr(n); 271 if (*t_wp == NULL) 272 return res; 273 if (t_lex(*++t_wp) == BAND) 274 return aexpr(t_lex(*++t_wp)) && res; 275 t_wp--; 276 return res; 277 } 278 279 static int 280 nexpr(enum token n) 281 { 282 283 if (n == UNOT) 284 return !nexpr(t_lex(*++t_wp)); 285 return primary(n); 286 } 287 288 static int 289 primary(enum token n) 290 { 291 enum token nn; 292 int res; 293 294 if (n == EOI) 295 return 0; /* missing expression */ 296 if (n == LPAREN) { 297 if ((nn = t_lex(*++t_wp)) == RPAREN) 298 return 0; /* missing expression */ 299 res = oexpr(nn); 300 if (t_lex(*++t_wp) != RPAREN) 301 syntax(NULL, "closing paren expected"); 302 return res; 303 } 304 if (t_wp_op && t_wp_op->op_type == UNOP) { 305 /* unary expression */ 306 if (*++t_wp == NULL) 307 syntax(t_wp_op->op_text, "argument expected"); 308 switch (n) { 309 case STREZ: 310 return strlen(*t_wp) == 0; 311 case STRNZ: 312 return strlen(*t_wp) != 0; 313 case FILTT: 314 return isatty((int)getn(*t_wp)); 315 default: 316 return filstat(*t_wp, n); 317 } 318 } 319 320 if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) { 321 return binop(); 322 } 323 324 return strlen(*t_wp) > 0; 325 } 326 327 static int 328 binop(void) 329 { 330 const char *opnd1, *opnd2; 331 struct t_op const *op; 332 333 opnd1 = *t_wp; 334 (void) t_lex(*++t_wp); 335 op = t_wp_op; 336 337 if ((opnd2 = *++t_wp) == NULL) 338 syntax(op->op_text, "argument expected"); 339 340 switch (op->op_num) { 341 case STREQ: 342 return strcmp(opnd1, opnd2) == 0; 343 case STRNE: 344 return strcmp(opnd1, opnd2) != 0; 345 case STRLT: 346 return strcmp(opnd1, opnd2) < 0; 347 case STRGT: 348 return strcmp(opnd1, opnd2) > 0; 349 case INTEQ: 350 return getn(opnd1) == getn(opnd2); 351 case INTNE: 352 return getn(opnd1) != getn(opnd2); 353 case INTGE: 354 return getn(opnd1) >= getn(opnd2); 355 case INTGT: 356 return getn(opnd1) > getn(opnd2); 357 case INTLE: 358 return getn(opnd1) <= getn(opnd2); 359 case INTLT: 360 return getn(opnd1) < getn(opnd2); 361 case FILNT: 362 return newerf(opnd1, opnd2); 363 case FILOT: 364 return olderf(opnd1, opnd2); 365 case FILEQ: 366 return equalf(opnd1, opnd2); 367 default: 368 abort(); 369 /* NOTREACHED */ 370 } 371 } 372 373 /* 374 * The manual, and IEEE POSIX 1003.2, suggests this should check the mode bits, 375 * not use access(): 376 * 377 * True shall indicate only that the write flag is on. The file is not 378 * writable on a read-only file system even if this test indicates true. 379 * 380 * Unfortunately IEEE POSIX 1003.1-2001, as quoted in SuSv3, says only: 381 * 382 * True shall indicate that permission to read from file will be granted, 383 * as defined in "File Read, Write, and Creation". 384 * 385 * and that section says: 386 * 387 * When a file is to be read or written, the file shall be opened with an 388 * access mode corresponding to the operation to be performed. If file 389 * access permissions deny access, the requested operation shall fail. 390 * 391 * and of course access permissions are described as one might expect: 392 * 393 * * If a process has the appropriate privilege: 394 * 395 * * If read, write, or directory search permission is requested, 396 * access shall be granted. 397 * 398 * * If execute permission is requested, access shall be granted if 399 * execute permission is granted to at least one user by the file 400 * permission bits or by an alternate access control mechanism; 401 * otherwise, access shall be denied. 402 * 403 * * Otherwise: 404 * 405 * * The file permission bits of a file contain read, write, and 406 * execute/search permissions for the file owner class, file group 407 * class, and file other class. 408 * 409 * * Access shall be granted if an alternate access control mechanism 410 * is not enabled and the requested access permission bit is set for 411 * the class (file owner class, file group class, or file other class) 412 * to which the process belongs, or if an alternate access control 413 * mechanism is enabled and it allows the requested access; otherwise, 414 * access shall be denied. 415 * 416 * and when I first read this I thought: surely we can't go about using 417 * open(O_WRONLY) to try this test! However the POSIX 1003.1-2001 Rationale 418 * section for test does in fact say: 419 * 420 * On historical BSD systems, test -w directory always returned false 421 * because test tried to open the directory for writing, which always 422 * fails. 423 * 424 * and indeed this is in fact true for Seventh Edition UNIX, UNIX 32V, and UNIX 425 * System III, and thus presumably also for BSD up to and including 4.3. 426 * 427 * Secondly I remembered why using open() and/or access() are bogus. They 428 * don't work right for detecting read and write permissions bits when called 429 * by root. 430 * 431 * Interestingly the 'test' in 4.4BSD was closer to correct (as per 432 * 1003.2-1992) and it was implemented efficiently with stat() instead of 433 * open(). 434 * 435 * This was apparently broken in NetBSD around about 1994/06/30 when the old 436 * 4.4BSD implementation was replaced with a (arguably much better coded) 437 * implementation derived from pdksh. 438 * 439 * Note that modern pdksh is yet different again, but still not correct, at 440 * least not w.r.t. 1003.2-1992. 441 * 442 * As I think more about it and read more of the related IEEE docs I don't like 443 * that wording about 'test -r' and 'test -w' in 1003.1-2001 at all. I very 444 * much prefer the original wording in 1003.2-1992. It is much more useful, 445 * and so that's what I've implemented. 446 * 447 * (Note that a strictly conforming implementation of 1003.1-2001 is in fact 448 * totally useless for the case in question since its 'test -w' and 'test -r' 449 * can never fail for root for any existing files, i.e. files for which 'test 450 * -e' succeeds.) 451 * 452 * The rationale for 1003.1-2001 suggests that the wording was "clarified" in 453 * 1003.1-2001 to align with the 1003.2b draft. 1003.2b Draft 12 (July 1999), 454 * which is the latest copy I have, does carry the same suggested wording as is 455 * in 1003.1-2001, with its rationale saying: 456 * 457 * This change is a clarification and is the result of interpretation 458 * request PASC 1003.2-92 #23 submitted for IEEE Std 1003.2-1992. 459 * 460 * That interpretation can be found here: 461 * 462 * http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-23.html 463 * 464 * Not terribly helpful, unfortunately. I wonder who that fence sitter was. 465 * 466 * Worse, IMVNSHO, I think the authors of 1003.2b-D12 have mis-interpreted the 467 * PASC interpretation and appear to be gone against at least one widely used 468 * implementation (namely 4.4BSD). The problem is that for file access by root 469 * this means that if test '-r' and '-w' are to behave as if open() were called 470 * then there's no way for a shell script running as root to check if a file 471 * has certain access bits set other than by the grotty means of interpreting 472 * the output of 'ls -l'. This was widely considered to be a bug in V7's 473 * "test" and is, I believe, one of the reasons why direct use of access() was 474 * avoided in some more recent implementations! 475 * 476 * I have always interpreted '-r' to match '-w' and '-x' as per the original 477 * wording in 1003.2-1992, not the other way around. I think 1003.2b goes much 478 * too far the wrong way without any valid rationale and that it's best if we 479 * stick with 1003.2-1992 and test the flags, and not mimic the behaviour of 480 * open() since we already know very well how it will work -- existance of the 481 * file is all that matters to open() for root. 482 * 483 * Unfortunately the SVID is no help at all (which is, I guess, partly why 484 * we're in this mess in the first place :-). 485 * 486 * The SysV implementation (at least in the 'test' builtin in /bin/sh) does use 487 * access(name, 2) even though it also goes to much greater lengths for '-x' 488 * matching the 1003.2-1992 definition (which is no doubt where that definition 489 * came from). 490 * 491 * The ksh93 implementation uses access() for '-r' and '-w' if 492 * (euid==uid&&egid==gid), but uses st_mode for '-x' iff running as root. 493 * i.e. it does strictly conform to 1003.1-2001 (and presumably 1003.2b). 494 */ 495 static int 496 test_access(struct stat *sp, mode_t stmode) 497 { 498 gid_t *groups; 499 register int n; 500 uid_t euid; 501 int maxgroups; 502 503 /* 504 * I suppose we could use access() if not running as root and if we are 505 * running with ((euid == uid) && (egid == gid)), but we've already 506 * done the stat() so we might as well just test the permissions 507 * directly instead of asking the kernel to do it.... 508 */ 509 euid = geteuid(); 510 if (euid == 0) /* any bit is good enough */ 511 stmode = (stmode << 6) | (stmode << 3) | stmode; 512 else if (sp->st_uid == euid) 513 stmode <<= 6; 514 else if (sp->st_gid == getegid()) 515 stmode <<= 3; 516 else { 517 /* XXX stolen almost verbatim from ksh93.... */ 518 /* on some systems you can be in several groups */ 519 if ((maxgroups = getgroups(0, NULL)) <= 0) 520 maxgroups = NGROUPS_MAX; /* pre-POSIX system? */ 521 groups = ckmalloc((maxgroups + 1) * sizeof(gid_t)); 522 n = getgroups(maxgroups, groups); 523 while (--n >= 0) { 524 if (groups[n] == sp->st_gid) { 525 stmode <<= 3; 526 break; 527 } 528 } 529 free(groups); 530 } 531 532 return sp->st_mode & stmode; 533 } 534 535 static int 536 filstat(char *nm, enum token mode) 537 { 538 struct stat s; 539 540 if (mode == FILSYM ? lstat(nm, &s) : stat(nm, &s)) 541 return 0; 542 543 switch (mode) { 544 case FILRD: 545 return test_access(&s, S_IROTH); 546 case FILWR: 547 return test_access(&s, S_IWOTH); 548 case FILEX: 549 return test_access(&s, S_IXOTH); 550 case FILEXIST: 551 return 1; /* the successful lstat()/stat() is good enough */ 552 case FILREG: 553 return S_ISREG(s.st_mode); 554 case FILDIR: 555 return S_ISDIR(s.st_mode); 556 case FILCDEV: 557 return S_ISCHR(s.st_mode); 558 case FILBDEV: 559 return S_ISBLK(s.st_mode); 560 case FILFIFO: 561 return S_ISFIFO(s.st_mode); 562 case FILSOCK: 563 return S_ISSOCK(s.st_mode); 564 case FILSYM: 565 return S_ISLNK(s.st_mode); 566 case FILSUID: 567 return (s.st_mode & S_ISUID) != 0; 568 case FILSGID: 569 return (s.st_mode & S_ISGID) != 0; 570 case FILSTCK: 571 return (s.st_mode & S_ISVTX) != 0; 572 case FILGZ: 573 return s.st_size > (off_t)0; 574 case FILUID: 575 return s.st_uid == geteuid(); 576 case FILGID: 577 return s.st_gid == getegid(); 578 default: 579 return 1; 580 } 581 } 582 583 #define VTOC(x) (const unsigned char *)((const struct t_op *)x)->op_text 584 585 static int 586 compare1(const void *va, const void *vb) 587 { 588 const unsigned char *a = va; 589 const unsigned char *b = VTOC(vb); 590 591 return a[0] - b[0]; 592 } 593 594 static int 595 compare2(const void *va, const void *vb) 596 { 597 const unsigned char *a = va; 598 const unsigned char *b = VTOC(vb); 599 int z = a[0] - b[0]; 600 601 return z ? z : (a[1] - b[1]); 602 } 603 604 static struct t_op const * 605 findop(const char *s) 606 { 607 if (s[0] == '-') { 608 if (s[1] == '\0') 609 return NULL; 610 if (s[2] == '\0') 611 return bsearch(s + 1, mop2, __arraycount(mop2), 612 sizeof(*mop2), compare1); 613 else if (s[3] != '\0') 614 return NULL; 615 else 616 return bsearch(s + 1, mop3, __arraycount(mop3), 617 sizeof(*mop3), compare2); 618 } else { 619 if (s[1] == '\0') 620 return bsearch(s, cop, __arraycount(cop), sizeof(*cop), 621 compare1); 622 else if (strcmp(s, cop2[0].op_text) == 0) 623 return cop2; 624 else 625 return NULL; 626 } 627 } 628 629 static enum token 630 t_lex(char *s) 631 { 632 struct t_op const *op; 633 634 if (s == NULL) { 635 t_wp_op = NULL; 636 return EOI; 637 } 638 639 if ((op = findop(s)) != NULL) { 640 if (!((op->op_type == UNOP && isoperand()) || 641 (op->op_num == LPAREN && *(t_wp+1) == 0))) { 642 t_wp_op = op; 643 return op->op_num; 644 } 645 } 646 t_wp_op = NULL; 647 return OPERAND; 648 } 649 650 static int 651 isoperand(void) 652 { 653 struct t_op const *op; 654 char *s, *t; 655 656 if ((s = *(t_wp+1)) == 0) 657 return 1; 658 if ((t = *(t_wp+2)) == 0) 659 return 0; 660 if ((op = findop(s)) != NULL) 661 return op->op_type == BINOP && (t[0] != ')' || t[1] != '\0'); 662 return 0; 663 } 664 665 /* atoi with error detection */ 666 static long long 667 getn(const char *s) 668 { 669 char *p; 670 long long r; 671 672 errno = 0; 673 r = strtoll(s, &p, 10); 674 675 if (errno != 0) 676 if (errno == ERANGE && (r == LLONG_MAX || r == LLONG_MIN)) 677 error("%s: out of range", s); 678 679 while (isspace((unsigned char)*p)) 680 p++; 681 682 if (*p || p == s) 683 error("%s: bad number", s); 684 685 return r; 686 } 687 688 static int 689 newerf(const char *f1, const char *f2) 690 { 691 struct stat b1, b2; 692 693 return (stat(f1, &b1) == 0 && 694 stat(f2, &b2) == 0 && 695 timespeccmp(&b1.st_mtim, &b2.st_mtim, >)); 696 } 697 698 static int 699 olderf(const char *f1, const char *f2) 700 { 701 struct stat b1, b2; 702 703 return (stat(f1, &b1) == 0 && 704 stat(f2, &b2) == 0 && 705 timespeccmp(&b1.st_mtim, &b2.st_mtim, <)); 706 } 707 708 static int 709 equalf(const char *f1, const char *f2) 710 { 711 struct stat b1, b2; 712 713 return (stat(f1, &b1) == 0 && 714 stat(f2, &b2) == 0 && 715 b1.st_dev == b2.st_dev && 716 b1.st_ino == b2.st_ino); 717 } 718