1 /* $NetBSD: test.c,v 1.43 2018/09/13 22:00:58 kre 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.43 2018/09/13 22:00:58 kre 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 #ifndef SMALL 96 , 97 BUNOP, 98 BBINOP, 99 PAREN 100 #endif 101 }; 102 103 struct t_op { 104 const char *op_text; 105 short op_num, op_type; 106 }; 107 108 static const struct t_op cop[] = { 109 #ifndef SMALL 110 {"!", UNOT, BUNOP}, 111 {"(", LPAREN, PAREN}, 112 {")", RPAREN, PAREN}, 113 #endif 114 {"<", STRLT, BINOP}, 115 {"=", STREQ, BINOP}, 116 {">", STRGT, BINOP}, 117 }; 118 119 static const struct t_op cop2[] = { 120 {"!=", STRNE, BINOP}, 121 }; 122 123 static const struct t_op mop3[] = { 124 {"ef", FILEQ, BINOP}, 125 {"eq", INTEQ, BINOP}, 126 {"ge", INTGE, BINOP}, 127 {"gt", INTGT, BINOP}, 128 {"le", INTLE, BINOP}, 129 {"lt", INTLT, BINOP}, 130 {"ne", INTNE, BINOP}, 131 {"nt", FILNT, BINOP}, 132 {"ot", FILOT, BINOP}, 133 }; 134 135 static const struct t_op mop2[] = { 136 {"G", FILGID, UNOP}, 137 {"L", FILSYM, UNOP}, 138 {"O", FILUID, UNOP}, 139 {"S", FILSOCK,UNOP}, 140 #ifndef SMALL 141 {"a", BAND, BBINOP}, 142 #endif 143 {"b", FILBDEV,UNOP}, 144 {"c", FILCDEV,UNOP}, 145 {"d", FILDIR, UNOP}, 146 {"e", FILEXIST,UNOP}, 147 {"f", FILREG, UNOP}, 148 {"g", FILSGID,UNOP}, 149 {"h", FILSYM, UNOP}, /* for backwards compat */ 150 {"k", FILSTCK,UNOP}, 151 {"n", STRNZ, UNOP}, 152 #ifndef SMALL 153 {"o", BOR, BBINOP}, 154 #endif 155 {"p", FILFIFO,UNOP}, 156 {"r", FILRD, UNOP}, 157 {"s", FILGZ, UNOP}, 158 {"t", FILTT, UNOP}, 159 {"u", FILSUID,UNOP}, 160 {"w", FILWR, UNOP}, 161 {"x", FILEX, UNOP}, 162 {"z", STREZ, UNOP}, 163 }; 164 165 #ifndef SMALL 166 static char **t_wp; 167 static struct t_op const *t_wp_op; 168 #endif 169 170 #ifndef SMALL 171 __dead static void syntax(const char *, const char *); 172 static int oexpr(enum token); 173 static int aexpr(enum token); 174 static int nexpr(enum token); 175 static int primary(enum token); 176 static int binop(void); 177 static enum token t_lex(char *); 178 static int isoperand(void); 179 #endif 180 static struct t_op const *findop(const char *); 181 static int perform_unop(enum token, const char *); 182 static int perform_binop(enum token, const char *, const char *); 183 static int test_access(struct stat *, mode_t); 184 static int filstat(const char *, enum token); 185 static long long getn(const char *); 186 static int newerf(const char *, const char *); 187 static int olderf(const char *, const char *); 188 static int equalf(const char *, const char *); 189 190 static int one_arg(const char *); 191 static int two_arg(const char *, const char *); 192 static int three_arg(const char *, const char *, const char *); 193 static int four_arg(const char *, const char *, const char *, const char *); 194 195 #if defined(SHELL) 196 extern void error(const char *, ...) __dead __printflike(1, 2); 197 extern void *ckmalloc(size_t); 198 #else 199 static void error(const char *, ...) __dead __printflike(1, 2); 200 201 static void 202 error(const char *msg, ...) 203 { 204 va_list ap; 205 206 va_start(ap, msg); 207 verrx(2, msg, ap); 208 /*NOTREACHED*/ 209 va_end(ap); 210 } 211 212 static void *ckmalloc(size_t); 213 static void * 214 ckmalloc(size_t nbytes) 215 { 216 void *p = malloc(nbytes); 217 218 if (!p) 219 error("Not enough memory!"); 220 return p; 221 } 222 #endif 223 224 #ifdef SHELL 225 int testcmd(int, char **); 226 227 int 228 testcmd(int argc, char **argv) 229 #else 230 int 231 main(int argc, char *argv[]) 232 #endif 233 { 234 int res; 235 const char *argv0; 236 237 #ifdef SHELL 238 argv0 = argv[0]; 239 #else 240 setprogname(argv[0]); 241 (void)setlocale(LC_ALL, ""); 242 argv0 = getprogname(); 243 #endif 244 if (strcmp(argv0, "[") == 0) { 245 if (strcmp(argv[--argc], "]")) 246 error("missing ]"); 247 argv[argc] = NULL; 248 } 249 250 /* 251 * POSIX defines operations of test for up to 4 args 252 * (depending upon what the args are in some cases) 253 * 254 * arg count does not include the command name, (but argc does) 255 * nor the closing ']' when the command was '[' (removed above) 256 * 257 * None of the following allow -a or -o as an operator (those 258 * only apply in the evaluation of unspeicified expressions) 259 * 260 * Note that the xxx_arg() functions return "shell" true/false 261 * (0 == true, 1 == false) or -1 for "unspecified case" 262 * 263 * Other functions return C true/false (1 == true, 0 == false) 264 * 265 * Hence we simply return the result from xxx_arg(), but 266 * invert the result of oexpr() below before returning it. 267 */ 268 switch (argc - 1) { 269 case -1: /* impossible, but never mind */ 270 case 0: /* test $a where a='' false */ 271 return 1; 272 273 case 1: /* test "$a" */ 274 return one_arg(argv[1]); /* always works */ 275 276 case 2: /* test op "$a" */ 277 res = two_arg(argv[1], argv[2]); 278 if (res >= 0) 279 return res; 280 break; 281 282 case 3: /* test "$a" op "$b" or test ! op "$a" */ 283 res = three_arg(argv[1], argv[2], argv[3]); 284 if (res >= 0) 285 return res; 286 break; 287 288 case 4: /* test ! "$a" op "$b" or test ( op "$a" ) */ 289 res = four_arg(argv[1], argv[2], argv[3], argv[4]); 290 if (res >= 0) 291 return res; 292 break; 293 294 default: 295 break; 296 } 297 298 /* 299 * All other cases produce unspecified results 300 * (including cases above with small arg counts where the 301 * args are not what was expected to be seen) 302 * 303 * We fall back to the old method, of attempting to parse 304 * the expr (highly ambiguous as there is no distinction between 305 * operators and operands that happen to look like operators) 306 */ 307 308 #ifdef SMALL 309 error("SMALL test, no fallback usage"); 310 #else 311 312 t_wp = &argv[1]; 313 res = !oexpr(t_lex(*t_wp)); 314 315 if (*t_wp != NULL && *++t_wp != NULL) 316 syntax(*t_wp, "unexpected operator"); 317 318 return res; 319 #endif 320 } 321 322 #ifndef SMALL 323 static void 324 syntax(const char *op, const char *msg) 325 { 326 327 if (op && *op) 328 error("%s: %s", op, msg); 329 else 330 error("%s", msg); 331 } 332 #endif 333 334 static int 335 one_arg(const char *arg) 336 { 337 /* 338 * True (exit 0, so false...) if arg is not a null string 339 * False (so exit 1, so true) if it is. 340 */ 341 return *arg == '\0'; 342 } 343 344 static int 345 two_arg(const char *a1, const char *a2) 346 { 347 static struct t_op const *op; 348 349 if (a1[0] == '!' && a1[1] == 0) 350 return !one_arg(a2); 351 352 op = findop(a1); 353 if (op != NULL && op->op_type == UNOP) 354 return !perform_unop(op->op_num, a2); 355 356 #ifndef TINY 357 /* 358 * an extension, but as we've entered the realm of the unspecified 359 * we're allowed... test ( $a ) where a='' 360 */ 361 if (a1[0] == '(' && a2[0] == ')' && (a1[1] | a2[1]) == 0) 362 return 1; 363 #endif 364 365 return -1; 366 } 367 368 static int 369 three_arg(const char *a1, const char *a2, const char *a3) 370 { 371 static struct t_op const *op; 372 int res; 373 374 op = findop(a2); 375 if (op != NULL && op->op_type == BINOP) 376 return !perform_binop(op->op_num, a1, a3); 377 378 if (a1[1] != '\0') 379 return -1; 380 381 if (a1[0] == '!') { 382 res = two_arg(a2, a3); 383 if (res >= 0) 384 res = !res; 385 return res; 386 } 387 388 #ifndef TINY 389 if (a1[0] == '(' && a3[0] == ')' && a3[1] == '\0') 390 return one_arg(a2); 391 #endif 392 393 return -1; 394 } 395 396 static int 397 four_arg(const char *a1, const char *a2, const char *a3, const char *a4) 398 { 399 int res; 400 401 if (a1[1] != '\0') 402 return -1; 403 404 if (a1[0] == '!') { 405 res = three_arg(a2, a3, a4); 406 if (res >= 0) 407 res = !res; 408 return res; 409 } 410 411 #ifndef TINY 412 if (a1[0] == '(' && a4[0] == ')' && a4[1] == '\0') 413 return two_arg(a2, a3); 414 #endif 415 416 return -1; 417 } 418 419 #ifndef SMALL 420 static int 421 oexpr(enum token n) 422 { 423 int res; 424 425 res = aexpr(n); 426 if (*t_wp == NULL) 427 return res; 428 if (t_lex(*++t_wp) == BOR) 429 return oexpr(t_lex(*++t_wp)) || res; 430 t_wp--; 431 return res; 432 } 433 434 static int 435 aexpr(enum token n) 436 { 437 int res; 438 439 res = nexpr(n); 440 if (*t_wp == NULL) 441 return res; 442 if (t_lex(*++t_wp) == BAND) 443 return aexpr(t_lex(*++t_wp)) && res; 444 t_wp--; 445 return res; 446 } 447 448 static int 449 nexpr(enum token n) 450 { 451 452 if (n == UNOT) 453 return !nexpr(t_lex(*++t_wp)); 454 return primary(n); 455 } 456 457 static int 458 primary(enum token n) 459 { 460 enum token nn; 461 int res; 462 463 if (n == EOI) 464 return 0; /* missing expression */ 465 if (n == LPAREN) { 466 if ((nn = t_lex(*++t_wp)) == RPAREN) 467 return 0; /* missing expression */ 468 res = oexpr(nn); 469 if (t_lex(*++t_wp) != RPAREN) 470 syntax(NULL, "closing paren expected"); 471 return res; 472 } 473 if (t_wp_op && t_wp_op->op_type == UNOP) { 474 /* unary expression */ 475 if (*++t_wp == NULL) 476 syntax(t_wp_op->op_text, "argument expected"); 477 return perform_unop(n, *t_wp); 478 } 479 480 if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) { 481 return binop(); 482 } 483 484 return strlen(*t_wp) > 0; 485 } 486 #endif /* !SMALL */ 487 488 static int 489 perform_unop(enum token n, const char *opnd) 490 { 491 switch (n) { 492 case STREZ: 493 return strlen(opnd) == 0; 494 case STRNZ: 495 return strlen(opnd) != 0; 496 case FILTT: 497 return isatty((int)getn(opnd)); 498 default: 499 return filstat(opnd, n); 500 } 501 } 502 503 #ifndef SMALL 504 static int 505 binop(void) 506 { 507 const char *opnd1, *opnd2; 508 struct t_op const *op; 509 510 opnd1 = *t_wp; 511 (void) t_lex(*++t_wp); 512 op = t_wp_op; 513 514 if ((opnd2 = *++t_wp) == NULL) 515 syntax(op->op_text, "argument expected"); 516 517 return perform_binop(op->op_num, opnd1, opnd2); 518 } 519 #endif 520 521 static int 522 perform_binop(enum token op_num, const char *opnd1, const char *opnd2) 523 { 524 switch (op_num) { 525 case STREQ: 526 return strcmp(opnd1, opnd2) == 0; 527 case STRNE: 528 return strcmp(opnd1, opnd2) != 0; 529 case STRLT: 530 return strcmp(opnd1, opnd2) < 0; 531 case STRGT: 532 return strcmp(opnd1, opnd2) > 0; 533 case INTEQ: 534 return getn(opnd1) == getn(opnd2); 535 case INTNE: 536 return getn(opnd1) != getn(opnd2); 537 case INTGE: 538 return getn(opnd1) >= getn(opnd2); 539 case INTGT: 540 return getn(opnd1) > getn(opnd2); 541 case INTLE: 542 return getn(opnd1) <= getn(opnd2); 543 case INTLT: 544 return getn(opnd1) < getn(opnd2); 545 case FILNT: 546 return newerf(opnd1, opnd2); 547 case FILOT: 548 return olderf(opnd1, opnd2); 549 case FILEQ: 550 return equalf(opnd1, opnd2); 551 default: 552 abort(); 553 /* NOTREACHED */ 554 } 555 } 556 557 /* 558 * The manual, and IEEE POSIX 1003.2, suggests this should check the mode bits, 559 * not use access(): 560 * 561 * True shall indicate only that the write flag is on. The file is not 562 * writable on a read-only file system even if this test indicates true. 563 * 564 * Unfortunately IEEE POSIX 1003.1-2001, as quoted in SuSv3, says only: 565 * 566 * True shall indicate that permission to read from file will be granted, 567 * as defined in "File Read, Write, and Creation". 568 * 569 * and that section says: 570 * 571 * When a file is to be read or written, the file shall be opened with an 572 * access mode corresponding to the operation to be performed. If file 573 * access permissions deny access, the requested operation shall fail. 574 * 575 * and of course access permissions are described as one might expect: 576 * 577 * * If a process has the appropriate privilege: 578 * 579 * * If read, write, or directory search permission is requested, 580 * access shall be granted. 581 * 582 * * If execute permission is requested, access shall be granted if 583 * execute permission is granted to at least one user by the file 584 * permission bits or by an alternate access control mechanism; 585 * otherwise, access shall be denied. 586 * 587 * * Otherwise: 588 * 589 * * The file permission bits of a file contain read, write, and 590 * execute/search permissions for the file owner class, file group 591 * class, and file other class. 592 * 593 * * Access shall be granted if an alternate access control mechanism 594 * is not enabled and the requested access permission bit is set for 595 * the class (file owner class, file group class, or file other class) 596 * to which the process belongs, or if an alternate access control 597 * mechanism is enabled and it allows the requested access; otherwise, 598 * access shall be denied. 599 * 600 * and when I first read this I thought: surely we can't go about using 601 * open(O_WRONLY) to try this test! However the POSIX 1003.1-2001 Rationale 602 * section for test does in fact say: 603 * 604 * On historical BSD systems, test -w directory always returned false 605 * because test tried to open the directory for writing, which always 606 * fails. 607 * 608 * and indeed this is in fact true for Seventh Edition UNIX, UNIX 32V, and UNIX 609 * System III, and thus presumably also for BSD up to and including 4.3. 610 * 611 * Secondly I remembered why using open() and/or access() are bogus. They 612 * don't work right for detecting read and write permissions bits when called 613 * by root. 614 * 615 * Interestingly the 'test' in 4.4BSD was closer to correct (as per 616 * 1003.2-1992) and it was implemented efficiently with stat() instead of 617 * open(). 618 * 619 * This was apparently broken in NetBSD around about 1994/06/30 when the old 620 * 4.4BSD implementation was replaced with a (arguably much better coded) 621 * implementation derived from pdksh. 622 * 623 * Note that modern pdksh is yet different again, but still not correct, at 624 * least not w.r.t. 1003.2-1992. 625 * 626 * As I think more about it and read more of the related IEEE docs I don't like 627 * that wording about 'test -r' and 'test -w' in 1003.1-2001 at all. I very 628 * much prefer the original wording in 1003.2-1992. It is much more useful, 629 * and so that's what I've implemented. 630 * 631 * (Note that a strictly conforming implementation of 1003.1-2001 is in fact 632 * totally useless for the case in question since its 'test -w' and 'test -r' 633 * can never fail for root for any existing files, i.e. files for which 'test 634 * -e' succeeds.) 635 * 636 * The rationale for 1003.1-2001 suggests that the wording was "clarified" in 637 * 1003.1-2001 to align with the 1003.2b draft. 1003.2b Draft 12 (July 1999), 638 * which is the latest copy I have, does carry the same suggested wording as is 639 * in 1003.1-2001, with its rationale saying: 640 * 641 * This change is a clarification and is the result of interpretation 642 * request PASC 1003.2-92 #23 submitted for IEEE Std 1003.2-1992. 643 * 644 * That interpretation can be found here: 645 * 646 * http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-23.html 647 * 648 * Not terribly helpful, unfortunately. I wonder who that fence sitter was. 649 * 650 * Worse, IMVNSHO, I think the authors of 1003.2b-D12 have mis-interpreted the 651 * PASC interpretation and appear to be gone against at least one widely used 652 * implementation (namely 4.4BSD). The problem is that for file access by root 653 * this means that if test '-r' and '-w' are to behave as if open() were called 654 * then there's no way for a shell script running as root to check if a file 655 * has certain access bits set other than by the grotty means of interpreting 656 * the output of 'ls -l'. This was widely considered to be a bug in V7's 657 * "test" and is, I believe, one of the reasons why direct use of access() was 658 * avoided in some more recent implementations! 659 * 660 * I have always interpreted '-r' to match '-w' and '-x' as per the original 661 * wording in 1003.2-1992, not the other way around. I think 1003.2b goes much 662 * too far the wrong way without any valid rationale and that it's best if we 663 * stick with 1003.2-1992 and test the flags, and not mimic the behaviour of 664 * open() since we already know very well how it will work -- existance of the 665 * file is all that matters to open() for root. 666 * 667 * Unfortunately the SVID is no help at all (which is, I guess, partly why 668 * we're in this mess in the first place :-). 669 * 670 * The SysV implementation (at least in the 'test' builtin in /bin/sh) does use 671 * access(name, 2) even though it also goes to much greater lengths for '-x' 672 * matching the 1003.2-1992 definition (which is no doubt where that definition 673 * came from). 674 * 675 * The ksh93 implementation uses access() for '-r' and '-w' if 676 * (euid==uid&&egid==gid), but uses st_mode for '-x' iff running as root. 677 * i.e. it does strictly conform to 1003.1-2001 (and presumably 1003.2b). 678 */ 679 static int 680 test_access(struct stat *sp, mode_t stmode) 681 { 682 gid_t *groups; 683 register int n; 684 uid_t euid; 685 int maxgroups; 686 687 /* 688 * I suppose we could use access() if not running as root and if we are 689 * running with ((euid == uid) && (egid == gid)), but we've already 690 * done the stat() so we might as well just test the permissions 691 * directly instead of asking the kernel to do it.... 692 */ 693 euid = geteuid(); 694 if (euid == 0) /* any bit is good enough */ 695 stmode = (stmode << 6) | (stmode << 3) | stmode; 696 else if (sp->st_uid == euid) 697 stmode <<= 6; 698 else if (sp->st_gid == getegid()) 699 stmode <<= 3; 700 else { 701 /* XXX stolen almost verbatim from ksh93.... */ 702 /* on some systems you can be in several groups */ 703 if ((maxgroups = getgroups(0, NULL)) <= 0) 704 maxgroups = NGROUPS_MAX; /* pre-POSIX system? */ 705 groups = ckmalloc((maxgroups + 1) * sizeof(gid_t)); 706 n = getgroups(maxgroups, groups); 707 while (--n >= 0) { 708 if (groups[n] == sp->st_gid) { 709 stmode <<= 3; 710 break; 711 } 712 } 713 free(groups); 714 } 715 716 return sp->st_mode & stmode; 717 } 718 719 static int 720 filstat(const char *nm, enum token mode) 721 { 722 struct stat s; 723 724 if (mode == FILSYM ? lstat(nm, &s) : stat(nm, &s)) 725 return 0; 726 727 switch (mode) { 728 case FILRD: 729 return test_access(&s, S_IROTH); 730 case FILWR: 731 return test_access(&s, S_IWOTH); 732 case FILEX: 733 return test_access(&s, S_IXOTH); 734 case FILEXIST: 735 return 1; /* the successful lstat()/stat() is good enough */ 736 case FILREG: 737 return S_ISREG(s.st_mode); 738 case FILDIR: 739 return S_ISDIR(s.st_mode); 740 case FILCDEV: 741 return S_ISCHR(s.st_mode); 742 case FILBDEV: 743 return S_ISBLK(s.st_mode); 744 case FILFIFO: 745 return S_ISFIFO(s.st_mode); 746 case FILSOCK: 747 return S_ISSOCK(s.st_mode); 748 case FILSYM: 749 return S_ISLNK(s.st_mode); 750 case FILSUID: 751 return (s.st_mode & S_ISUID) != 0; 752 case FILSGID: 753 return (s.st_mode & S_ISGID) != 0; 754 case FILSTCK: 755 return (s.st_mode & S_ISVTX) != 0; 756 case FILGZ: 757 return s.st_size > (off_t)0; 758 case FILUID: 759 return s.st_uid == geteuid(); 760 case FILGID: 761 return s.st_gid == getegid(); 762 default: 763 return 1; 764 } 765 } 766 767 #define VTOC(x) (const unsigned char *)((const struct t_op *)x)->op_text 768 769 static int 770 compare1(const void *va, const void *vb) 771 { 772 const unsigned char *a = va; 773 const unsigned char *b = VTOC(vb); 774 775 return a[0] - b[0]; 776 } 777 778 static int 779 compare2(const void *va, const void *vb) 780 { 781 const unsigned char *a = va; 782 const unsigned char *b = VTOC(vb); 783 int z = a[0] - b[0]; 784 785 return z ? z : (a[1] - b[1]); 786 } 787 788 static struct t_op const * 789 findop(const char *s) 790 { 791 if (s[0] == '-') { 792 if (s[1] == '\0') 793 return NULL; 794 if (s[2] == '\0') 795 return bsearch(s + 1, mop2, __arraycount(mop2), 796 sizeof(*mop2), compare1); 797 else if (s[3] != '\0') 798 return NULL; 799 else 800 return bsearch(s + 1, mop3, __arraycount(mop3), 801 sizeof(*mop3), compare2); 802 } else { 803 if (s[1] == '\0') 804 return bsearch(s, cop, __arraycount(cop), sizeof(*cop), 805 compare1); 806 else if (strcmp(s, cop2[0].op_text) == 0) 807 return cop2; 808 else 809 return NULL; 810 } 811 } 812 813 #ifndef SMALL 814 static enum token 815 t_lex(char *s) 816 { 817 struct t_op const *op; 818 819 if (s == NULL) { 820 t_wp_op = NULL; 821 return EOI; 822 } 823 824 if ((op = findop(s)) != NULL) { 825 if (!((op->op_type == UNOP && isoperand()) || 826 (op->op_num == LPAREN && *(t_wp+1) == 0))) { 827 t_wp_op = op; 828 return op->op_num; 829 } 830 } 831 t_wp_op = NULL; 832 return OPERAND; 833 } 834 835 static int 836 isoperand(void) 837 { 838 struct t_op const *op; 839 char *s, *t; 840 841 if ((s = *(t_wp+1)) == 0) 842 return 1; 843 if ((t = *(t_wp+2)) == 0) 844 return 0; 845 if ((op = findop(s)) != NULL) 846 return op->op_type == BINOP && (t[0] != ')' || t[1] != '\0'); 847 return 0; 848 } 849 #endif 850 851 /* atoi with error detection */ 852 static long long 853 getn(const char *s) 854 { 855 char *p; 856 long long r; 857 858 errno = 0; 859 r = strtoll(s, &p, 10); 860 861 if (errno != 0) 862 if (errno == ERANGE && (r == LLONG_MAX || r == LLONG_MIN)) 863 error("%s: out of range", s); 864 865 if (p != s) 866 while (isspace((unsigned char)*p)) 867 p++; 868 869 if (*p || p == s) 870 error("'%s': bad number", s); 871 872 return r; 873 } 874 875 static int 876 newerf(const char *f1, const char *f2) 877 { 878 struct stat b1, b2; 879 880 return (stat(f1, &b1) == 0 && 881 stat(f2, &b2) == 0 && 882 timespeccmp(&b1.st_mtim, &b2.st_mtim, >)); 883 } 884 885 static int 886 olderf(const char *f1, const char *f2) 887 { 888 struct stat b1, b2; 889 890 return (stat(f1, &b1) == 0 && 891 stat(f2, &b2) == 0 && 892 timespeccmp(&b1.st_mtim, &b2.st_mtim, <)); 893 } 894 895 static int 896 equalf(const char *f1, const char *f2) 897 { 898 struct stat b1, b2; 899 900 return (stat(f1, &b1) == 0 && 901 stat(f2, &b2) == 0 && 902 b1.st_dev == b2.st_dev && 903 b1.st_ino == b2.st_ino); 904 } 905