00001
00002
00003
00004
00005 #include <sys/types.h>
00006 #include <sys/stat.h>
00007 #include <sys/wait.h>
00008 #include <fcntl.h>
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <unistd.h>
00012 #include <time.h>
00013 #include <pwd.h>
00014 #include <grp.h>
00015 #include <dirent.h>
00016 #include <limits.h>
00017 #include <stdio.h>
00018
00019
00020
00021 #ifdef S_IFLNK
00022 #define LSTAT lstat
00023 #else
00024 #define LSTAT stat
00025 #endif
00026
00027 #define SHELL "/bin/sh"
00028 #define MAXARG 256
00029 #define BSIZE 512
00030 #define SECS_PER_DAY (24L*60L*60L)
00031
00032 #define OP_NAME 1
00033 #define OP_PERM 2
00034 #define OP_TYPE 3
00035 #define OP_LINKS 4
00036 #define OP_USER 5
00037 #define OP_GROUP 6
00038 #define OP_SIZE 7
00039 #define OP_SIZEC 8
00040 #define OP_INUM 9
00041 #define OP_ATIME 10
00042 #define OP_CTIME 11
00043 #define OP_MTIME 12
00044 #define OP_EXEC 13
00045 #define OP_OK 14
00046 #define OP_PRINT 15
00047 #define OP_PRINT0 16
00048 #define OP_NEWER 17
00049 #define OP_CNEWER 18
00050 #define OP_AND 19
00051 #define OP_OR 20
00052 #define OP_XDEV 21
00053 #define OP_DEPTH 22
00054 #define OP_PRUNE 23
00055 #define OP_NOUSER 24
00056 #define OP_NOGROUP 25
00057 #define LPAR 26
00058 #define RPAR 27
00059 #define NOT 28
00060
00061
00062 #define EOI -1
00063 #define NONE 0
00064
00065
00066 #define ISWHO(c) ((c == 'u') || (c == 'g') || (c == 'o') || (c == 'a'))
00067 #define ISOPER(c) ((c == '-') || (c == '=') || (c == '+'))
00068 #define ISMODE(c) ((c == 'r') || (c == 'w') || (c == 'x') || \
00069 (c == 's') || (c == 't'))
00070 #define MUSER 1
00071 #define MGROUP 2
00072 #define MOTHERS 4
00073
00074
00075 struct exec {
00076 int e_cnt;
00077 char *e_vec[MAXARG];
00078 };
00079
00080 struct node {
00081 int n_type;
00082 union {
00083 char *n_str;
00084 struct {
00085 long n_val;
00086 int n_sign;
00087 } n_int;
00088 struct exec *n_exec;
00089 struct {
00090 struct node *n_left, *n_right;
00091 } n_opnd;
00092 } n_info;
00093 };
00094
00095 struct oper {
00096 char *op_str;
00097 int op_val;
00098 } ops[] = {
00099
00100 {
00101 "name", OP_NAME
00102 },
00103 {
00104 "perm", OP_PERM
00105 },
00106 {
00107 "type", OP_TYPE
00108 },
00109 {
00110 "links", OP_LINKS
00111 },
00112 {
00113 "user", OP_USER
00114 },
00115 {
00116 "group", OP_GROUP
00117 },
00118 {
00119 "size", OP_SIZE
00120 },
00121 {
00122 "inum", OP_INUM
00123 },
00124 {
00125 "atime", OP_ATIME
00126 },
00127 {
00128 "ctime", OP_CTIME
00129 },
00130 {
00131 "mtime", OP_MTIME
00132 },
00133 {
00134 "exec", OP_EXEC
00135 },
00136 {
00137 "ok", OP_OK
00138 },
00139 {
00140 "print", OP_PRINT
00141 },
00142 {
00143 "print0", OP_PRINT0
00144 },
00145 {
00146 "newer", OP_NEWER
00147 },
00148 {
00149 "cnewer", OP_CNEWER
00150 },
00151 {
00152 "a", OP_AND
00153 },
00154 {
00155 "o", OP_OR
00156 },
00157 {
00158 "xdev", OP_XDEV
00159 },
00160 {
00161 "depth", OP_DEPTH
00162 },
00163 {
00164 "prune", OP_PRUNE
00165 },
00166 {
00167 "nouser", OP_NOUSER
00168 },
00169 {
00170 "nogroup", OP_NOGROUP
00171 },
00172 {
00173 0, 0
00174 }
00175 };
00176
00177
00178 char **ipp;
00179 char *prog;
00180 char *epath;
00181 long current_time;
00182 int tty;
00183 int xdev_flag = 0;
00184 int devnr;
00185 int depth_flag = 0;
00186 int prune_here;
00187 int um;
00188 int needprint = 1;
00189
00190
00191
00192 _PROTOTYPE(int main, (int argc, char **argv));
00193 _PROTOTYPE(char *Malloc, (int n));
00194 _PROTOTYPE(char *Salloc, (char *s));
00195 _PROTOTYPE(void find, (char *path, struct node * pred, char *last));
00196 _PROTOTYPE(int check, (char *path, struct stat * st, struct node * n, char *last));
00197 _PROTOTYPE(int ichk, (long val, struct node * n));
00198 _PROTOTYPE(int lex, (char *str));
00199 _PROTOTYPE(struct node * newnode, (int t));
00200 _PROTOTYPE(int isnumber, (char *str, int base, int sign));
00201 _PROTOTYPE(void number, (char *str, int base, long *pl, int *ps));
00202 _PROTOTYPE(void fmode, (char *str, long *pl, int *ps));
00203 _PROTOTYPE(struct node * expr, (int t));
00204 _PROTOTYPE(struct node * primary, (int t));
00205 _PROTOTYPE(struct node * secondary, (int t));
00206 _PROTOTYPE(void checkarg, (char *arg));
00207 _PROTOTYPE(struct node * simple, (int t));
00208 _PROTOTYPE(void nonfatal, (char *s1, char *s2));
00209 _PROTOTYPE(void fatal, (char *s1, char *s2));
00210 _PROTOTYPE(int smatch, (char *s, char *t));
00211 _PROTOTYPE(char *find_bin, (char *s));
00212 _PROTOTYPE(int execute, (int op, struct exec * e, char *path));
00213 _PROTOTYPE(void domode, (int op, int *mode, int bits));
00214
00215
00216
00217 char *Malloc(n)
00218 int n;
00219 {
00220 char *m;
00221
00222 if ((m = (char *) malloc(n)) == (char *) NULL) fatal("out of memory", "");
00223 return m;
00224 }
00225
00226
00227 char *Salloc(s)
00228 char *s;
00229 {
00230 return strcpy(Malloc(strlen(s) + 1), s);
00231 }
00232
00233
00234
00235 int main(argc, argv)
00236 int argc;
00237 char *argv[];
00238 {
00239 char **pathlist, *path, *last;
00240 int pathcnt = 0, i;
00241 struct node *pred;
00242
00243 prog = *argv++;
00244 if ((epath = getenv("PATH")) == (char *) NULL)
00245 fatal("Can't get path from environment", "");
00246 (void) umask(um = umask(0));
00247 time(¤t_time);
00248
00249 pathlist= argv;
00250 while (--argc > 0 && lex(*argv) == NONE) {
00251 pathcnt++;
00252 argv++;
00253 }
00254 if (pathcnt == 0)
00255 fatal("Usage: path-list [predicate-list]", "");
00256
00257 ipp = argv;
00258 if (argc != 0) {
00259 pred = expr(lex(*ipp));
00260 if (lex(*++ipp) != EOI)
00261 fatal("syntax error: garbage at end of predicate", "");
00262 } else
00263 pred = (struct node *) NULL;
00264
00265 for (i = 0; i < pathcnt; i++) {
00266 if (xdev_flag) xdev_flag = 2;
00267 path = pathlist[i];
00268 if ((last = strrchr(path, '/')) == NULL) last = path; else last++;
00269 find(path, pred, last);
00270 }
00271 return 0;
00272 }
00273
00274 void find(path, pred, last)
00275 char *path, *last;
00276 struct node *pred;
00277 {
00278 char spath[PATH_MAX];
00279 register char *send = spath, *p;
00280 struct stat st;
00281 DIR *dp;
00282 struct dirent *de;
00283
00284 if (path[1] == '\0' && *path == '/') {
00285 *send++ = '/';
00286 *send = '\0';
00287 } else
00288 while (*send++ = *path++) {
00289 }
00290
00291 if (LSTAT(spath, &st) == -1)
00292 nonfatal("can't get status of ", spath);
00293 else {
00294 switch (xdev_flag) {
00295 case 0:
00296 break;
00297 case 1:
00298 if (st.st_dev != devnr) return;
00299 break;
00300 case 2:
00301 xdev_flag = 1;
00302 devnr = st.st_dev;
00303 break;
00304 }
00305
00306 prune_here = 0;
00307 if (!depth_flag && check(spath, &st, pred, last) && needprint)
00308 printf("%s\n", spath);
00309 if (!prune_here && (st.st_mode & S_IFMT) == S_IFDIR) {
00310 if ((dp = opendir(spath)) == NULL) {
00311 nonfatal("can't read directory ", spath);
00312 perror( "Error" );
00313 return;
00314 }
00315 send[-1] = '/';
00316 while ((de = readdir(dp)) != NULL) {
00317 p = de->d_name;
00318 if ((de->d_name[0] != '.') || ((de->d_name[1])
00319 && ((de->d_name[1] != '.')
00320 || (de->d_name[2])))) {
00321 strcpy(send, de->d_name);
00322 find(spath, pred, send);
00323 }
00324 }
00325 closedir(dp);
00326 }
00327 if (depth_flag) {
00328 send[-1] = '\0';
00329 if (check(spath, &st, pred, last) && needprint)
00330 printf("%s\n", spath);
00331 }
00332 }
00333 }
00334
00335 int check(path, st, n, last)
00336 char *path, *last;
00337 register struct stat *st;
00338 register struct node *n;
00339 {
00340 if (n == (struct node *) NULL) return 1;
00341 switch (n->n_type) {
00342 case OP_AND:
00343 return check(path, st, n->n_info.n_opnd.n_left, last) &&
00344 check(path, st, n->n_info.n_opnd.n_right, last);
00345 case OP_OR:
00346 return check(path, st, n->n_info.n_opnd.n_left, last) ||
00347 check(path, st, n->n_info.n_opnd.n_right, last);
00348 case NOT:
00349 return !check(path, st, n->n_info.n_opnd.n_left, last);
00350 case OP_NAME:
00351 return smatch(last, n->n_info.n_str);
00352 case OP_PERM:
00353 if (n->n_info.n_int.n_sign < 0)
00354 return(st->st_mode & (int) n->n_info.n_int.n_val) ==
00355 (int) n->n_info.n_int.n_val;
00356 return(st->st_mode & 07777) == (int) n->n_info.n_int.n_val;
00357 case OP_NEWER:
00358 return st->st_mtime > n->n_info.n_int.n_val;
00359 case OP_CNEWER:
00360 return st->st_ctime > n->n_info.n_int.n_val;
00361 case OP_TYPE:
00362 return(st->st_mode & S_IFMT) == (mode_t) n->n_info.n_int.n_val;
00363 case OP_LINKS:
00364 return ichk((long) (st->st_nlink), n);
00365 case OP_USER:
00366 return st->st_uid == n->n_info.n_int.n_val;
00367 case OP_GROUP:
00368 return st->st_gid == n->n_info.n_int.n_val;
00369 case OP_SIZE:
00370 return ichk((st->st_size == 0) ? 0L :
00371 (long) ((st->st_size - 1) / BSIZE + 1), n);
00372 case OP_SIZEC:
00373 return ichk((long) st->st_size, n);
00374 case OP_INUM:
00375 return ichk((long) (st->st_ino), n);
00376 case OP_ATIME:
00377 return ichk(st->st_atime, n);
00378 case OP_CTIME:
00379 return ichk(st->st_ctime, n);
00380 case OP_MTIME:
00381 return ichk(st->st_mtime, n);
00382 case OP_EXEC:
00383 case OP_OK:
00384 return execute(n->n_type, n->n_info.n_exec, path);
00385 case OP_PRINT:
00386 printf("%s\n", path);
00387 return 1;
00388 case OP_PRINT0:
00389 printf("%s", path); putchar(0);
00390 return 1;
00391 case OP_XDEV:
00392 case OP_DEPTH:
00393 return 1;
00394 case OP_PRUNE:
00395 prune_here = 1;
00396 return 1;
00397 case OP_NOUSER:
00398 return(getpwuid(st->st_uid) == (struct passwd *) NULL);
00399 case OP_NOGROUP:
00400 return(getgrgid(st->st_gid) == (struct group *) NULL);
00401 }
00402 fatal("ILLEGAL NODE", "");
00403 return 0;
00404 }
00405
00406 int ichk(val, n)
00407 long val;
00408 struct node *n;
00409 {
00410 switch (n->n_info.n_int.n_sign) {
00411 case 0:
00412 return val == n->n_info.n_int.n_val;
00413 case 1:
00414 return val > n->n_info.n_int.n_val;
00415 case -1: return val < n->n_info.n_int.n_val;
00416 }
00417 fatal("internal: bad n_sign", "");
00418 return 0;
00419 }
00420
00421 int lex(str)
00422 char *str;
00423 {
00424 if (str == (char *) NULL) return EOI;
00425 if (*str == '-') {
00426 register struct oper *op;
00427
00428 str++;
00429 for (op = ops; op->op_str; op++)
00430 if (strcmp(str, op->op_str) == 0) break;
00431 return op->op_val;
00432 }
00433 if (str[1] == 0) {
00434 switch (*str) {
00435 case '(':
00436 return LPAR;
00437 case ')':
00438 return RPAR;
00439 case '!': return NOT;
00440 }
00441 }
00442 return NONE;
00443 }
00444
00445 struct node *
00446 newnode(t)
00447 int t;
00448 {
00449 struct node *n = (struct node *) Malloc(sizeof(struct node));
00450
00451 n->n_type = t;
00452 return n;
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 int isnumber(str, base, sign)
00467 register char *str;
00468 int base;
00469 int sign;
00470 {
00471 if (sign && ((*str == '-') || ((base == 8) && (*str == '+')))) str++;
00472 while ((*str >= '0') && (*str < ('0' + base))) str++;
00473 return(*str == '\0' ? 1 : 0);
00474 }
00475
00476
00477 void number(str, base, pl, ps)
00478 char *str;
00479 int base;
00480 long *pl;
00481 int *ps;
00482 {
00483 int up = '0' + base - 1;
00484 long val = 0;
00485
00486 *ps = ((*str == '-' || *str == '+') ? ((*str++ == '-') ? -1 : 1) : 0);
00487 while (*str >= '0' && *str <= up) val = base * val + *str++ - '0';
00488 if (*str) fatal("syntax error: illegal numeric value", "");
00489 *pl = val;
00490 }
00491
00492
00493 void domode(op, mode, bits)
00494 int op;
00495 int *mode;
00496 int bits;
00497 {
00498 switch (op) {
00499 case '-':
00500 *mode &= ~bits;
00501 break;
00502 case '=':
00503 *mode |= bits;
00504 break;
00505 case '+':
00506 *mode |= (bits & ~um);
00507 }
00508 }
00509
00510 void fmode(str, pl, ps)
00511 char *str;
00512 long *pl;
00513 int *ps;
00514 {
00515 int m = 0, w, op;
00516 char *p = str;
00517
00518 if (*p == '-') {
00519 *ps = -1;
00520 p++;
00521 } else
00522 *ps = 0;
00523
00524 while (*p) {
00525 w = 0;
00526 if (ISOPER(*p))
00527 w = MUSER | MGROUP | MOTHERS;
00528 else if (!ISWHO(*p))
00529 fatal("u, g, o, or a expected: ", p);
00530 else {
00531 while (ISWHO(*p)) {
00532 switch (*p) {
00533 case 'u':
00534 w |= MUSER;
00535 break;
00536 case 'g':
00537 w |= MGROUP;
00538 break;
00539 case 'o':
00540 w |= MOTHERS;
00541 break;
00542 case 'a':
00543 w = MUSER | MGROUP | MOTHERS;
00544 }
00545 p++;
00546 }
00547 if (!ISOPER(*p)) fatal("-, + or = expected: ", p);
00548 }
00549 op = *p++;
00550 while (ISMODE(*p)) {
00551 switch (*p) {
00552 case 'r':
00553 if (w & MUSER) domode(op, &m, S_IRUSR);
00554 if (w & MGROUP) domode(op, &m, S_IRGRP);
00555 if (w & MOTHERS) domode(op, &m, S_IROTH);
00556 break;
00557 case 'w':
00558 if (w & MUSER) domode(op, &m, S_IWUSR);
00559 if (w & MGROUP) domode(op, &m, S_IWGRP);
00560 if (w & MOTHERS) domode(op, &m, S_IWOTH);
00561 break;
00562 case 'x':
00563 if (w & MUSER) domode(op, &m, S_IXUSR);
00564 if (w & MGROUP) domode(op, &m, S_IXGRP);
00565 if (w & MOTHERS) domode(op, &m, S_IXOTH);
00566 break;
00567 case 's':
00568 if (w & MUSER) domode(op, &m, S_ISUID);
00569 if (w & MGROUP) domode(op, &m, S_ISGID);
00570 break;
00571 case 't':
00572 domode(op, &m, S_ISVTX);
00573 }
00574 p++;
00575 }
00576 if (*p) {
00577 if (*p == ',')
00578 p++;
00579 else
00580 fatal("garbage at end of mode string: ", p);
00581 }
00582 }
00583 *pl = m;
00584 }
00585
00586 struct node *
00587 expr(t)
00588 int t;
00589 {
00590 struct node *nd, *p, *nd2;
00591
00592 nd = primary(t);
00593 if ((t = lex(*++ipp)) == OP_OR) {
00594 nd2 = expr(lex(*++ipp));
00595 p = newnode(OP_OR);
00596 p->n_info.n_opnd.n_left = nd;
00597 p->n_info.n_opnd.n_right = nd2;
00598 return p;
00599 }
00600 ipp--;
00601 return nd;
00602 }
00603
00604 struct node *
00605 primary(t)
00606 int t;
00607 {
00608 struct node *nd, *p, *nd2;
00609
00610 nd = secondary(t);
00611 if ((t = lex(*++ipp)) != OP_AND) {
00612 ipp--;
00613 if (t == EOI || t == RPAR || t == OP_OR) return nd;
00614 }
00615 nd2 = primary(lex(*++ipp));
00616 p = newnode(OP_AND);
00617 p->n_info.n_opnd.n_left = nd;
00618 p->n_info.n_opnd.n_right = nd2;
00619 return p;
00620 }
00621
00622 struct node *
00623 secondary(t)
00624 int t;
00625 {
00626 struct node *n, *p;
00627
00628 if (t == LPAR) {
00629 n = expr(lex(*++ipp));
00630 if (lex(*++ipp) != RPAR) fatal("syntax error, ) expected", "");
00631 return n;
00632 }
00633 if (t == NOT) {
00634 n = secondary(lex(*++ipp));
00635 p = newnode(NOT);
00636 p->n_info.n_opnd.n_left = n;
00637 return p;
00638 }
00639 return simple(t);
00640 }
00641
00642 void checkarg(arg)
00643 char *arg;
00644 {
00645 if (arg == 0) fatal("syntax error, argument expected", "");
00646 }
00647
00648 struct node *
00649 simple(t)
00650 int t;
00651 {
00652 struct node *p = newnode(t);
00653 struct exec *e;
00654 struct stat est;
00655 struct passwd *pw;
00656 struct group *gr;
00657 long l;
00658 int i;
00659
00660 switch (t) {
00661 case OP_TYPE:
00662 checkarg(*++ipp);
00663 switch (**ipp) {
00664 case 'b':
00665 p->n_info.n_int.n_val = S_IFBLK;
00666 break;
00667 case 'c':
00668 p->n_info.n_int.n_val = S_IFCHR;
00669 break;
00670 case 'd':
00671 p->n_info.n_int.n_val = S_IFDIR;
00672 break;
00673 case 'f':
00674 p->n_info.n_int.n_val = S_IFREG;
00675 break;
00676 case 'p':
00677 p->n_info.n_int.n_val = S_IFIFO;
00678 break;
00679 case 's':
00680 p->n_info.n_int.n_val = ~0;
00681 break;
00682 case 'l':
00683 #ifdef S_IFLNK
00684 p->n_info.n_int.n_val = S_IFLNK;
00685 #else
00686 p->n_info.n_int.n_val = ~0;
00687 #endif
00688 break;
00689 default:
00690 fatal("-type needs b, c, d, f, p, s or l", "");
00691 }
00692 break;
00693 case OP_USER:
00694 checkarg(*++ipp);
00695 if (((pw = getpwnam(*ipp)) == NULL)
00696 && isnumber(*ipp, 10, 0))
00697 number(*ipp, 10, &(p->n_info.n_int.n_val),
00698 &(p->n_info.n_int.n_sign));
00699 else {
00700 if (pw == NULL)
00701 fatal("unknown user: ", *ipp);
00702 p->n_info.n_int.n_val = pw->pw_uid;
00703 p->n_info.n_int.n_sign = 0;
00704 }
00705 break;
00706 case OP_GROUP:
00707 checkarg(*++ipp);
00708 if (((gr = getgrnam(*ipp)) == NULL)
00709 && isnumber(*ipp, 10, 0))
00710 number(*ipp, 10, &(p->n_info.n_int.n_val),
00711 &(p->n_info.n_int.n_sign));
00712 else {
00713 if (gr == NULL)
00714 fatal("unknown group: ", *ipp);
00715 p->n_info.n_int.n_val = gr->gr_gid;
00716 p->n_info.n_int.n_sign = 0;
00717 }
00718 break;
00719 case OP_SIZE:
00720 checkarg(*++ipp);
00721 i = strlen(*ipp) - 1;
00722 if ((*ipp)[i] == 'c') {
00723 p->n_type = OP_SIZEC;
00724 (*ipp)[i] = '\0';
00725 }
00726 number(*ipp, 10, &(p->n_info.n_int.n_val),
00727 &(p->n_info.n_int.n_sign));
00728 break;
00729 case OP_LINKS:
00730 case OP_INUM:
00731 checkarg(*++ipp);
00732 number(*ipp, 10, &(p->n_info.n_int.n_val),
00733 &(p->n_info.n_int.n_sign));
00734 break;
00735 case OP_PERM:
00736 checkarg(*++ipp);
00737 if (isnumber(*ipp, 8, 1)) number(*ipp, 8, &(p->n_info.n_int.n_val),
00738 &(p->n_info.n_int.n_sign));
00739 else
00740 fmode(*ipp, &(p->n_info.n_int.n_val),
00741 &(p->n_info.n_int.n_sign));
00742 break;
00743 case OP_ATIME:
00744 case OP_CTIME:
00745 case OP_MTIME:
00746 checkarg(*++ipp);
00747 number(*ipp, 10, &l, &(p->n_info.n_int.n_sign));
00748 p->n_info.n_int.n_val = current_time - l * SECS_PER_DAY;
00749
00750 p->n_info.n_int.n_sign *= -1;
00751 break;
00752 case OP_EXEC:
00753 case OP_OK:
00754 checkarg(*++ipp);
00755 e = (struct exec *) Malloc(sizeof(struct exec));
00756 e->e_cnt = 2;
00757 e->e_vec[0] = SHELL;
00758 p->n_info.n_exec = e;
00759 while (*ipp) {
00760 if (**ipp == ';' && (*ipp)[1] == '\0') {
00761 e->e_vec[e->e_cnt] = 0;
00762 break;
00763 }
00764 e->e_vec[(e->e_cnt)++] =
00765 (**ipp == '{' && (*ipp)[1] == '}'
00766 && (*ipp)[2] == '\0') ? (char *) (-1) : *ipp;
00767 ipp++;
00768 }
00769 if (*ipp == 0) fatal("-exec/-ok: ; missing", "");
00770 if ((e->e_vec[1] = find_bin(e->e_vec[2])) == 0)
00771 fatal("can't find program ", e->e_vec[2]);
00772 if (t == OP_OK)
00773 if ((tty = open("/dev/tty", O_RDWR)) < 0)
00774 fatal("can't open /dev/tty", "");
00775 break;
00776 case OP_CNEWER:
00777 case OP_NEWER:
00778 checkarg(*++ipp);
00779 if (LSTAT(*ipp, &est) == -1)
00780 fatal("-newer: can't get status of ", *ipp);
00781 p->n_info.n_int.n_val = est.st_mtime;
00782 break;
00783 case OP_NAME:
00784 checkarg(*++ipp);
00785 p->n_info.n_str = *ipp;
00786 break;
00787 case OP_XDEV: xdev_flag = 1; break;
00788 case OP_DEPTH: depth_flag = 1; break;
00789 case OP_PRUNE:
00790 case OP_PRINT:
00791 case OP_PRINT0:
00792 case OP_NOUSER: case OP_NOGROUP: break;
00793 default:
00794 fatal("syntax error, operator expected", "");
00795 }
00796 if ((t == OP_PRINT) || (t == OP_PRINT0) || (t == OP_EXEC) || (t == OP_OK))
00797 needprint = 0;
00798
00799 return p;
00800 }
00801
00802
00803
00804 void nonfatal(s1, s2)
00805 char *s1, *s2;
00806 {
00807 fprintf(stderr, "%s: %s%s\n", prog, s1, s2);
00808 }
00809
00810 void fatal(s1, s2)
00811 char *s1, *s2;
00812 {
00813 nonfatal(s1, s2);
00814 exit(1);
00815 }
00816
00817
00818
00819 int smatch(s, t)
00820 char *s, *t;
00821 {
00822 register n;
00823
00824 if (*t == '\0') return *s == '\0';
00825 if (*t == '*') {
00826 ++t;
00827 do
00828 if (smatch(s, t)) return 1;
00829 while (*s++ != '\0');
00830 return 0;
00831 }
00832 if (*s == '\0') return 0;
00833 if (*t == '\\') return (*s == *++t) ? smatch(++s, ++t) : 0;
00834 if (*t == '?') return smatch(++s, ++t);
00835 if (*t == '[') {
00836 while (*++t != ']') {
00837 if (*t == '\\') ++t;
00838 if (*(t + 1) != '-')
00839 if (*t == *s) {
00840 while (*++t != ']')
00841 if (*t == '\\') ++t;
00842 return smatch(++s, ++t);
00843 } else
00844 continue;
00845 if (*(t + 2) == ']') return(*s == *t || *s == '-');
00846 n = (*(t + 2) == '\\') ? 3 : 2;
00847 if (*s >= *t && *s <= *(t + n)) {
00848 while (*++t != ']')
00849 if (*t == '\\') ++t;
00850 return smatch(++s, ++t);
00851 }
00852 t += n;
00853 }
00854 return 0;
00855 }
00856 return(*s == *t) ? smatch(++s, ++t) : 0;
00857 }
00858
00859
00860
00861
00862 char *
00863 find_bin(s)
00864 char *s;
00865 {
00866 char *f, *l, buf[PATH_MAX];
00867
00868 if (*s == '/')
00869 return(access(s, 1) == 0) ? s : 0;
00870 l = f = epath;
00871 for (;;) {
00872 if (*l == ':' || *l == 0) {
00873 if (l == f) {
00874 if (access(s, 1) == 0) return Salloc(s);
00875 f++;
00876 } else {
00877 register char *p = buf, *q = s;
00878
00879 while (f != l) *p++ = *f++;
00880 f++;
00881 *p++ = '/';
00882 while (*p++ = *q++) {
00883 }
00884 if (access(buf, 1) == 0) return Salloc(buf);
00885 }
00886 if (*l == 0) break;
00887 }
00888 l++;
00889 }
00890 return 0;
00891 }
00892
00893 int execute(op, e, path)
00894 int op;
00895 struct exec *e;
00896 char *path;
00897 {
00898 int s, pid;
00899 char *argv[MAXARG];
00900 register char **p, **q;
00901
00902 for (p = e->e_vec, q = argv; *p;)
00903 if ((*q++ = *p++) == (char *) -1) q[-1] = path;
00904 *q = '\0';
00905 if (op == OP_OK) {
00906 char answer[10];
00907
00908 for (p = &argv[2]; *p; p++) {
00909 write(tty, *p, strlen(*p));
00910 write(tty, " ", 1);
00911 }
00912 write(tty, "? ", 2);
00913 if (read(tty, answer, 10) < 2 || *answer != 'y') return 0;
00914 }
00915 if ((pid = fork()) == -1) fatal("can't fork", "");
00916 if (pid == 0) {
00917 register i = 3;
00918
00919 while (close(i++) == 0) {
00920 }
00921 execv(argv[1], &argv[2]);
00922 execv(argv[0], &argv[1]);
00923 fatal("exec failure: ", argv[1]);
00924 exit(127);
00925 }
00926 return wait(&s) == pid && s == 0;
00927 }