1717a08b6SSheldon Hearn /* $NetBSD: test.c,v 1.21 1999/04/05 09:48:38 kleink Exp $ */ 2717a08b6SSheldon Hearn 3717a08b6SSheldon Hearn /* 4717a08b6SSheldon Hearn * test(1); version 7-like -- author Erik Baalbergen 5717a08b6SSheldon Hearn * modified by Eric Gisin to be used as built-in. 6717a08b6SSheldon Hearn * modified by Arnold Robbins to add SVR3 compatibility 7717a08b6SSheldon Hearn * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). 8717a08b6SSheldon Hearn * modified by J.T. Conklin for NetBSD. 94b88c807SRodney W. Grimes * 10717a08b6SSheldon Hearn * This program is in the Public Domain. 114b88c807SRodney W. Grimes */ 124b88c807SRodney W. Grimes 134b88c807SRodney W. Grimes #ifndef lint 149ba8bd65SPhilippe Charnier static const char rcsid[] = 15717a08b6SSheldon Hearn "$Id: test.c,v 1.22 1999/08/14 05:38:04 chris Exp $"; 164b88c807SRodney W. Grimes #endif /* not lint */ 174b88c807SRodney W. Grimes 18717a08b6SSheldon Hearn #include <sys/types.h> 19007d3350SEivind Eklund #include <sys/stat.h> 204b88c807SRodney W. Grimes 214b88c807SRodney W. Grimes #include <ctype.h> 224b88c807SRodney W. Grimes #include <err.h> 234b88c807SRodney W. Grimes #include <errno.h> 244b88c807SRodney W. Grimes #include <stdio.h> 254b88c807SRodney W. Grimes #include <stdlib.h> 264b88c807SRodney W. Grimes #include <string.h> 274b88c807SRodney W. Grimes #include <unistd.h> 284b88c807SRodney W. Grimes 29717a08b6SSheldon Hearn /* test(1) accepts the following grammar: 30717a08b6SSheldon Hearn oexpr ::= aexpr | aexpr "-o" oexpr ; 31717a08b6SSheldon Hearn aexpr ::= nexpr | nexpr "-a" aexpr ; 32717a08b6SSheldon Hearn nexpr ::= primary | "!" primary 33717a08b6SSheldon Hearn primary ::= unary-operator operand 34717a08b6SSheldon Hearn | operand binary-operator operand 35717a08b6SSheldon Hearn | operand 36717a08b6SSheldon Hearn | "(" oexpr ")" 37717a08b6SSheldon Hearn ; 38717a08b6SSheldon Hearn unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"| 39717a08b6SSheldon Hearn "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S"; 404b88c807SRodney W. Grimes 41717a08b6SSheldon Hearn binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| 42717a08b6SSheldon Hearn "-nt"|"-ot"|"-ef"; 43717a08b6SSheldon Hearn operand ::= <any legal UNIX file name> 444b88c807SRodney W. Grimes */ 45717a08b6SSheldon Hearn 46717a08b6SSheldon Hearn enum token { 47717a08b6SSheldon Hearn EOI, 48717a08b6SSheldon Hearn FILRD, 49717a08b6SSheldon Hearn FILWR, 50717a08b6SSheldon Hearn FILEX, 51717a08b6SSheldon Hearn FILEXIST, 52717a08b6SSheldon Hearn FILREG, 53717a08b6SSheldon Hearn FILDIR, 54717a08b6SSheldon Hearn FILCDEV, 55717a08b6SSheldon Hearn FILBDEV, 56717a08b6SSheldon Hearn FILFIFO, 57717a08b6SSheldon Hearn FILSOCK, 58717a08b6SSheldon Hearn FILSYM, 59717a08b6SSheldon Hearn FILGZ, 60717a08b6SSheldon Hearn FILTT, 61717a08b6SSheldon Hearn FILSUID, 62717a08b6SSheldon Hearn FILSGID, 63717a08b6SSheldon Hearn FILSTCK, 64717a08b6SSheldon Hearn FILNT, 65717a08b6SSheldon Hearn FILOT, 66717a08b6SSheldon Hearn FILEQ, 67717a08b6SSheldon Hearn FILUID, 68717a08b6SSheldon Hearn FILGID, 69717a08b6SSheldon Hearn STREZ, 70717a08b6SSheldon Hearn STRNZ, 71717a08b6SSheldon Hearn STREQ, 72717a08b6SSheldon Hearn STRNE, 73717a08b6SSheldon Hearn STRLT, 74717a08b6SSheldon Hearn STRGT, 75717a08b6SSheldon Hearn INTEQ, 76717a08b6SSheldon Hearn INTNE, 77717a08b6SSheldon Hearn INTGE, 78717a08b6SSheldon Hearn INTGT, 79717a08b6SSheldon Hearn INTLE, 80717a08b6SSheldon Hearn INTLT, 81717a08b6SSheldon Hearn UNOT, 82717a08b6SSheldon Hearn BAND, 83717a08b6SSheldon Hearn BOR, 84717a08b6SSheldon Hearn LPAREN, 85717a08b6SSheldon Hearn RPAREN, 86717a08b6SSheldon Hearn OPERAND 874b88c807SRodney W. Grimes }; 884b88c807SRodney W. Grimes 89717a08b6SSheldon Hearn enum token_types { 90717a08b6SSheldon Hearn UNOP, 91717a08b6SSheldon Hearn BINOP, 92717a08b6SSheldon Hearn BUNOP, 93717a08b6SSheldon Hearn BBINOP, 94717a08b6SSheldon Hearn PAREN 954b88c807SRodney W. Grimes }; 964b88c807SRodney W. Grimes 97717a08b6SSheldon Hearn struct t_op { 98717a08b6SSheldon Hearn const char *op_text; 99717a08b6SSheldon Hearn short op_num, op_type; 100717a08b6SSheldon Hearn } const ops [] = { 101717a08b6SSheldon Hearn {"-r", FILRD, UNOP}, 102717a08b6SSheldon Hearn {"-w", FILWR, UNOP}, 103717a08b6SSheldon Hearn {"-x", FILEX, UNOP}, 104717a08b6SSheldon Hearn {"-e", FILEXIST,UNOP}, 105717a08b6SSheldon Hearn {"-f", FILREG, UNOP}, 106717a08b6SSheldon Hearn {"-d", FILDIR, UNOP}, 107717a08b6SSheldon Hearn {"-c", FILCDEV,UNOP}, 108717a08b6SSheldon Hearn {"-b", FILBDEV,UNOP}, 109717a08b6SSheldon Hearn {"-p", FILFIFO,UNOP}, 110717a08b6SSheldon Hearn {"-u", FILSUID,UNOP}, 111717a08b6SSheldon Hearn {"-g", FILSGID,UNOP}, 112717a08b6SSheldon Hearn {"-k", FILSTCK,UNOP}, 113717a08b6SSheldon Hearn {"-s", FILGZ, UNOP}, 114717a08b6SSheldon Hearn {"-t", FILTT, UNOP}, 115717a08b6SSheldon Hearn {"-z", STREZ, UNOP}, 116717a08b6SSheldon Hearn {"-n", STRNZ, UNOP}, 117717a08b6SSheldon Hearn {"-h", FILSYM, UNOP}, /* for backwards compat */ 118717a08b6SSheldon Hearn {"-O", FILUID, UNOP}, 119717a08b6SSheldon Hearn {"-G", FILGID, UNOP}, 120717a08b6SSheldon Hearn {"-L", FILSYM, UNOP}, 121717a08b6SSheldon Hearn {"-S", FILSOCK,UNOP}, 122717a08b6SSheldon Hearn {"=", STREQ, BINOP}, 123717a08b6SSheldon Hearn {"!=", STRNE, BINOP}, 124717a08b6SSheldon Hearn {"<", STRLT, BINOP}, 125717a08b6SSheldon Hearn {">", STRGT, BINOP}, 126717a08b6SSheldon Hearn {"-eq", INTEQ, BINOP}, 127717a08b6SSheldon Hearn {"-ne", INTNE, BINOP}, 128717a08b6SSheldon Hearn {"-ge", INTGE, BINOP}, 129717a08b6SSheldon Hearn {"-gt", INTGT, BINOP}, 130717a08b6SSheldon Hearn {"-le", INTLE, BINOP}, 131717a08b6SSheldon Hearn {"-lt", INTLT, BINOP}, 132717a08b6SSheldon Hearn {"-nt", FILNT, BINOP}, 133717a08b6SSheldon Hearn {"-ot", FILOT, BINOP}, 134717a08b6SSheldon Hearn {"-ef", FILEQ, BINOP}, 135717a08b6SSheldon Hearn {"!", UNOT, BUNOP}, 136717a08b6SSheldon Hearn {"-a", BAND, BBINOP}, 137717a08b6SSheldon Hearn {"-o", BOR, BBINOP}, 138717a08b6SSheldon Hearn {"(", LPAREN, PAREN}, 139717a08b6SSheldon Hearn {")", RPAREN, PAREN}, 140717a08b6SSheldon Hearn {0, 0, 0} 1414b88c807SRodney W. Grimes }; 1424b88c807SRodney W. Grimes 143717a08b6SSheldon Hearn struct t_op const *t_wp_op; 144717a08b6SSheldon Hearn char **t_wp; 145717a08b6SSheldon Hearn 146717a08b6SSheldon Hearn static void syntax __P((const char *, const char *)); 147717a08b6SSheldon Hearn static enum token t_lex __P((char *)); 148717a08b6SSheldon Hearn static int oexpr __P((enum token)); 149717a08b6SSheldon Hearn static int aexpr __P((enum token)); 150717a08b6SSheldon Hearn static int nexpr __P((enum token)); 151717a08b6SSheldon Hearn static int primary __P((enum token)); 152717a08b6SSheldon Hearn static int binop __P((void)); 153717a08b6SSheldon Hearn static int filstat __P((char *, enum token)); 154717a08b6SSheldon Hearn static int isoperand __P((void)); 155717a08b6SSheldon Hearn static int getn __P((const char *)); 156717a08b6SSheldon Hearn static int newerf __P((const char *, const char *)); 157717a08b6SSheldon Hearn static int olderf __P((const char *, const char *)); 158717a08b6SSheldon Hearn static int equalf __P((const char *, const char *)); 1594b88c807SRodney W. Grimes 1604b88c807SRodney W. Grimes int 1614b88c807SRodney W. Grimes main(argc, argv) 1624b88c807SRodney W. Grimes int argc; 163717a08b6SSheldon Hearn char **argv; 1644b88c807SRodney W. Grimes { 165717a08b6SSheldon Hearn int res; 1664b88c807SRodney W. Grimes 167717a08b6SSheldon Hearn if (strcmp(argv[0], "[") == 0) { 1684b88c807SRodney W. Grimes if (strcmp(argv[--argc], "]")) 1694b88c807SRodney W. Grimes errx(2, "missing ]"); 1704b88c807SRodney W. Grimes argv[argc] = NULL; 1714b88c807SRodney W. Grimes } 1724b88c807SRodney W. Grimes 173717a08b6SSheldon Hearn t_wp = &argv[1]; 174717a08b6SSheldon Hearn res = !oexpr(t_lex(*t_wp)); 175717a08b6SSheldon Hearn 176717a08b6SSheldon Hearn if (*t_wp != NULL && *++t_wp != NULL) 177717a08b6SSheldon Hearn syntax(*t_wp, "unexpected operator"); 178717a08b6SSheldon Hearn 179717a08b6SSheldon Hearn return res; 1804b88c807SRodney W. Grimes } 181717a08b6SSheldon Hearn 182717a08b6SSheldon Hearn static void 183717a08b6SSheldon Hearn syntax(op, msg) 184717a08b6SSheldon Hearn const char *op; 185717a08b6SSheldon Hearn const char *msg; 186717a08b6SSheldon Hearn { 187717a08b6SSheldon Hearn 188717a08b6SSheldon Hearn if (op && *op) 189717a08b6SSheldon Hearn errx(2, "%s: %s", op, msg); 190717a08b6SSheldon Hearn else 191717a08b6SSheldon Hearn errx(2, "%s", msg); 1924b88c807SRodney W. Grimes } 193717a08b6SSheldon Hearn 194717a08b6SSheldon Hearn static int 195717a08b6SSheldon Hearn oexpr(n) 196717a08b6SSheldon Hearn enum token n; 197717a08b6SSheldon Hearn { 198717a08b6SSheldon Hearn int res; 199717a08b6SSheldon Hearn 200717a08b6SSheldon Hearn res = aexpr(n); 201717a08b6SSheldon Hearn if (t_lex(*++t_wp) == BOR) 202717a08b6SSheldon Hearn return oexpr(t_lex(*++t_wp)) || res; 203717a08b6SSheldon Hearn t_wp--; 204717a08b6SSheldon Hearn return res; 2054b88c807SRodney W. Grimes } 206717a08b6SSheldon Hearn 207717a08b6SSheldon Hearn static int 208717a08b6SSheldon Hearn aexpr(n) 209717a08b6SSheldon Hearn enum token n; 210717a08b6SSheldon Hearn { 211717a08b6SSheldon Hearn int res; 212717a08b6SSheldon Hearn 213717a08b6SSheldon Hearn res = nexpr(n); 214717a08b6SSheldon Hearn if (t_lex(*++t_wp) == BAND) 215717a08b6SSheldon Hearn return aexpr(t_lex(*++t_wp)) && res; 216717a08b6SSheldon Hearn t_wp--; 217717a08b6SSheldon Hearn return res; 218717a08b6SSheldon Hearn } 219717a08b6SSheldon Hearn 220717a08b6SSheldon Hearn static int 221717a08b6SSheldon Hearn nexpr(n) 222717a08b6SSheldon Hearn enum token n; /* token */ 223717a08b6SSheldon Hearn { 224717a08b6SSheldon Hearn if (n == UNOT) 225717a08b6SSheldon Hearn return !nexpr(t_lex(*++t_wp)); 226717a08b6SSheldon Hearn return primary(n); 227717a08b6SSheldon Hearn } 228717a08b6SSheldon Hearn 229717a08b6SSheldon Hearn static int 230717a08b6SSheldon Hearn primary(n) 231717a08b6SSheldon Hearn enum token n; 232717a08b6SSheldon Hearn { 233717a08b6SSheldon Hearn enum token nn; 234717a08b6SSheldon Hearn int res; 235717a08b6SSheldon Hearn 236717a08b6SSheldon Hearn if (n == EOI) 237717a08b6SSheldon Hearn return 0; /* missing expression */ 238717a08b6SSheldon Hearn if (n == LPAREN) { 239717a08b6SSheldon Hearn if ((nn = t_lex(*++t_wp)) == RPAREN) 240717a08b6SSheldon Hearn return 0; /* missing expression */ 241717a08b6SSheldon Hearn res = oexpr(nn); 242717a08b6SSheldon Hearn if (t_lex(*++t_wp) != RPAREN) 243717a08b6SSheldon Hearn syntax(NULL, "closing paren expected"); 244717a08b6SSheldon Hearn return res; 245717a08b6SSheldon Hearn } 246717a08b6SSheldon Hearn if (t_wp_op && t_wp_op->op_type == UNOP) { 247717a08b6SSheldon Hearn /* unary expression */ 248717a08b6SSheldon Hearn if (*++t_wp == NULL) 249717a08b6SSheldon Hearn syntax(t_wp_op->op_text, "argument expected"); 250717a08b6SSheldon Hearn switch (n) { 251717a08b6SSheldon Hearn case STREZ: 252717a08b6SSheldon Hearn return strlen(*t_wp) == 0; 253717a08b6SSheldon Hearn case STRNZ: 254717a08b6SSheldon Hearn return strlen(*t_wp) != 0; 255717a08b6SSheldon Hearn case FILTT: 256717a08b6SSheldon Hearn return isatty(getn(*t_wp)); 2574b88c807SRodney W. Grimes default: 258717a08b6SSheldon Hearn return filstat(*t_wp, n); 259717a08b6SSheldon Hearn } 2604b88c807SRodney W. Grimes } 2614b88c807SRodney W. Grimes 262717a08b6SSheldon Hearn if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) { 263717a08b6SSheldon Hearn return binop(); 2644b88c807SRodney W. Grimes } 265717a08b6SSheldon Hearn 266717a08b6SSheldon Hearn return strlen(*t_wp) > 0; 2674b88c807SRodney W. Grimes } 2684b88c807SRodney W. Grimes 2694b88c807SRodney W. Grimes static int 270717a08b6SSheldon Hearn binop() 2714b88c807SRodney W. Grimes { 272717a08b6SSheldon Hearn const char *opnd1, *opnd2; 273717a08b6SSheldon Hearn struct t_op const *op; 2744b88c807SRodney W. Grimes 275717a08b6SSheldon Hearn opnd1 = *t_wp; 276717a08b6SSheldon Hearn (void) t_lex(*++t_wp); 277717a08b6SSheldon Hearn op = t_wp_op; 2784b88c807SRodney W. Grimes 279717a08b6SSheldon Hearn if ((opnd2 = *++t_wp) == NULL) 280717a08b6SSheldon Hearn syntax(op->op_text, "argument expected"); 2814b88c807SRodney W. Grimes 282717a08b6SSheldon Hearn switch (op->op_num) { 2834b88c807SRodney W. Grimes case STREQ: 284717a08b6SSheldon Hearn return strcmp(opnd1, opnd2) == 0; 2854b88c807SRodney W. Grimes case STRNE: 286717a08b6SSheldon Hearn return strcmp(opnd1, opnd2) != 0; 287717a08b6SSheldon Hearn case STRLT: 288717a08b6SSheldon Hearn return strcmp(opnd1, opnd2) < 0; 289717a08b6SSheldon Hearn case STRGT: 290717a08b6SSheldon Hearn return strcmp(opnd1, opnd2) > 0; 291717a08b6SSheldon Hearn case INTEQ: 292717a08b6SSheldon Hearn return getn(opnd1) == getn(opnd2); 293717a08b6SSheldon Hearn case INTNE: 294717a08b6SSheldon Hearn return getn(opnd1) != getn(opnd2); 295717a08b6SSheldon Hearn case INTGE: 296717a08b6SSheldon Hearn return getn(opnd1) >= getn(opnd2); 297717a08b6SSheldon Hearn case INTGT: 298717a08b6SSheldon Hearn return getn(opnd1) > getn(opnd2); 299717a08b6SSheldon Hearn case INTLE: 300717a08b6SSheldon Hearn return getn(opnd1) <= getn(opnd2); 301717a08b6SSheldon Hearn case INTLT: 302717a08b6SSheldon Hearn return getn(opnd1) < getn(opnd2); 303717a08b6SSheldon Hearn case FILNT: 304717a08b6SSheldon Hearn return newerf (opnd1, opnd2); 305717a08b6SSheldon Hearn case FILOT: 306717a08b6SSheldon Hearn return olderf (opnd1, opnd2); 307717a08b6SSheldon Hearn case FILEQ: 308717a08b6SSheldon Hearn return equalf (opnd1, opnd2); 309717a08b6SSheldon Hearn default: 310717a08b6SSheldon Hearn abort(); 311717a08b6SSheldon Hearn /* NOTREACHED */ 312717a08b6SSheldon Hearn } 313717a08b6SSheldon Hearn } 314717a08b6SSheldon Hearn 315717a08b6SSheldon Hearn static int 316717a08b6SSheldon Hearn filstat(nm, mode) 317717a08b6SSheldon Hearn char *nm; 318717a08b6SSheldon Hearn enum token mode; 319717a08b6SSheldon Hearn { 320717a08b6SSheldon Hearn struct stat s; 321717a08b6SSheldon Hearn 322717a08b6SSheldon Hearn if (mode == FILSYM ? lstat(nm, &s) : stat(nm, &s)) 323717a08b6SSheldon Hearn return 0; 324717a08b6SSheldon Hearn 325717a08b6SSheldon Hearn switch (mode) { 326717a08b6SSheldon Hearn case FILRD: 327717a08b6SSheldon Hearn return access(nm, R_OK) == 0; 328717a08b6SSheldon Hearn case FILWR: 329717a08b6SSheldon Hearn return access(nm, W_OK) == 0; 330717a08b6SSheldon Hearn case FILEX: 331717a08b6SSheldon Hearn return access(nm, X_OK) == 0; 332717a08b6SSheldon Hearn case FILEXIST: 333717a08b6SSheldon Hearn return access(nm, F_OK) == 0; 334717a08b6SSheldon Hearn case FILREG: 335717a08b6SSheldon Hearn return S_ISREG(s.st_mode); 336717a08b6SSheldon Hearn case FILDIR: 337717a08b6SSheldon Hearn return S_ISDIR(s.st_mode); 338717a08b6SSheldon Hearn case FILCDEV: 339717a08b6SSheldon Hearn return S_ISCHR(s.st_mode); 340717a08b6SSheldon Hearn case FILBDEV: 341717a08b6SSheldon Hearn return S_ISBLK(s.st_mode); 342717a08b6SSheldon Hearn case FILFIFO: 343717a08b6SSheldon Hearn return S_ISFIFO(s.st_mode); 344717a08b6SSheldon Hearn case FILSOCK: 345717a08b6SSheldon Hearn return S_ISSOCK(s.st_mode); 346717a08b6SSheldon Hearn case FILSYM: 347717a08b6SSheldon Hearn return S_ISLNK(s.st_mode); 348717a08b6SSheldon Hearn case FILSUID: 349717a08b6SSheldon Hearn return (s.st_mode & S_ISUID) != 0; 350717a08b6SSheldon Hearn case FILSGID: 351717a08b6SSheldon Hearn return (s.st_mode & S_ISGID) != 0; 352717a08b6SSheldon Hearn case FILSTCK: 353717a08b6SSheldon Hearn return (s.st_mode & S_ISVTX) != 0; 354717a08b6SSheldon Hearn case FILGZ: 355717a08b6SSheldon Hearn return s.st_size > (off_t)0; 356717a08b6SSheldon Hearn case FILUID: 357717a08b6SSheldon Hearn return s.st_uid == geteuid(); 358717a08b6SSheldon Hearn case FILGID: 359717a08b6SSheldon Hearn return s.st_gid == getegid(); 360717a08b6SSheldon Hearn default: 361717a08b6SSheldon Hearn return 1; 362717a08b6SSheldon Hearn } 363717a08b6SSheldon Hearn } 364717a08b6SSheldon Hearn 365717a08b6SSheldon Hearn static enum token 366717a08b6SSheldon Hearn t_lex(s) 367717a08b6SSheldon Hearn char *s; 368717a08b6SSheldon Hearn { 369717a08b6SSheldon Hearn struct t_op const *op = ops; 370717a08b6SSheldon Hearn 371717a08b6SSheldon Hearn if (s == 0) { 372717a08b6SSheldon Hearn t_wp_op = NULL; 373717a08b6SSheldon Hearn return EOI; 374717a08b6SSheldon Hearn } 375717a08b6SSheldon Hearn while (op->op_text) { 376717a08b6SSheldon Hearn if (strcmp(s, op->op_text) == 0) { 377717a08b6SSheldon Hearn if ((op->op_type == UNOP && isoperand()) || 378717a08b6SSheldon Hearn (op->op_num == LPAREN && *(t_wp+1) == 0)) 3794b88c807SRodney W. Grimes break; 380717a08b6SSheldon Hearn t_wp_op = op; 381717a08b6SSheldon Hearn return op->op_num; 3824b88c807SRodney W. Grimes } 383717a08b6SSheldon Hearn op++; 384717a08b6SSheldon Hearn } 385717a08b6SSheldon Hearn t_wp_op = NULL; 386717a08b6SSheldon Hearn return OPERAND; 3874b88c807SRodney W. Grimes } 3884b88c807SRodney W. Grimes 3894b88c807SRodney W. Grimes static int 390717a08b6SSheldon Hearn isoperand() 3914b88c807SRodney W. Grimes { 392717a08b6SSheldon Hearn struct t_op const *op = ops; 393717a08b6SSheldon Hearn char *s; 394717a08b6SSheldon Hearn char *t; 3954b88c807SRodney W. Grimes 396717a08b6SSheldon Hearn if ((s = *(t_wp+1)) == 0) 397717a08b6SSheldon Hearn return 1; 398717a08b6SSheldon Hearn if ((t = *(t_wp+2)) == 0) 399717a08b6SSheldon Hearn return 0; 400717a08b6SSheldon Hearn while (op->op_text) { 401717a08b6SSheldon Hearn if (strcmp(s, op->op_text) == 0) 402717a08b6SSheldon Hearn return op->op_type == BINOP && 403717a08b6SSheldon Hearn (t[0] != ')' || t[1] != '\0'); 404717a08b6SSheldon Hearn op++; 405717a08b6SSheldon Hearn } 406717a08b6SSheldon Hearn return 0; 4074b88c807SRodney W. Grimes } 4084b88c807SRodney W. Grimes 409717a08b6SSheldon Hearn /* atoi with error detection */ 4104b88c807SRodney W. Grimes static int 411717a08b6SSheldon Hearn getn(s) 412717a08b6SSheldon Hearn const char *s; 4134b88c807SRodney W. Grimes { 414717a08b6SSheldon Hearn char *p; 415717a08b6SSheldon Hearn long r; 4164b88c807SRodney W. Grimes 4174b88c807SRodney W. Grimes errno = 0; 418717a08b6SSheldon Hearn r = strtol(s, &p, 10); 419717a08b6SSheldon Hearn 420717a08b6SSheldon Hearn if (errno != 0) 421717a08b6SSheldon Hearn errx(2, "%s: out of range", s); 422717a08b6SSheldon Hearn 423717a08b6SSheldon Hearn while (isspace((unsigned char)*p)) 424717a08b6SSheldon Hearn p++; 425717a08b6SSheldon Hearn 426717a08b6SSheldon Hearn if (*p) 427717a08b6SSheldon Hearn errx(2, "%s: bad number", s); 428717a08b6SSheldon Hearn 429717a08b6SSheldon Hearn return (int) r; 4304b88c807SRodney W. Grimes } 4314b88c807SRodney W. Grimes 432717a08b6SSheldon Hearn static int 433717a08b6SSheldon Hearn newerf (f1, f2) 434717a08b6SSheldon Hearn const char *f1, *f2; 4354b88c807SRodney W. Grimes { 436717a08b6SSheldon Hearn struct stat b1, b2; 4374b88c807SRodney W. Grimes 438717a08b6SSheldon Hearn return (stat (f1, &b1) == 0 && 439717a08b6SSheldon Hearn stat (f2, &b2) == 0 && 440717a08b6SSheldon Hearn b1.st_mtime > b2.st_mtime); 4414b88c807SRodney W. Grimes } 4424b88c807SRodney W. Grimes 443717a08b6SSheldon Hearn static int 444717a08b6SSheldon Hearn olderf (f1, f2) 445717a08b6SSheldon Hearn const char *f1, *f2; 4464b88c807SRodney W. Grimes { 447717a08b6SSheldon Hearn struct stat b1, b2; 4484b88c807SRodney W. Grimes 449717a08b6SSheldon Hearn return (stat (f1, &b1) == 0 && 450717a08b6SSheldon Hearn stat (f2, &b2) == 0 && 451717a08b6SSheldon Hearn b1.st_mtime < b2.st_mtime); 452717a08b6SSheldon Hearn } 453717a08b6SSheldon Hearn 454717a08b6SSheldon Hearn static int 455717a08b6SSheldon Hearn equalf (f1, f2) 456717a08b6SSheldon Hearn const char *f1, *f2; 457717a08b6SSheldon Hearn { 458717a08b6SSheldon Hearn struct stat b1, b2; 459717a08b6SSheldon Hearn 460717a08b6SSheldon Hearn return (stat (f1, &b1) == 0 && 461717a08b6SSheldon Hearn stat (f2, &b2) == 0 && 462717a08b6SSheldon Hearn b1.st_dev == b2.st_dev && 463717a08b6SSheldon Hearn b1.st_ino == b2.st_ino); 4644b88c807SRodney W. Grimes } 465