70 #define FTW_SLN 7
71 #endif
72 #define LINEBUF_SIZE LINE_MAX /* input or output lines */
73 #define REMOTE_FS "/etc/dfs/fstypes"
74 #define N_FSTYPES 20
75 #define SHELL_MAXARGS 253 /* see doexec() for description */
76
77 /*
78 * This is the list of operations
79 * F_USER and F_GROUP are named to avoid conflict with USER and GROUP defined
80 * in sys/acl.h
81 */
82
83 enum Command
84 {
85 PRINT,
86 ACL, AMIN, AND, ATIME, CMIN, CPIO, CSIZE, CTIME, DEPTH, EXEC, F_GROUP,
87 F_GROUPACL, F_USER, F_USERACL, FOLLOW, FSTYPE, INAME, INUM, IPATH,
88 IREGEX, LINKS, LOCAL, LPAREN, LS, MAXDEPTH, MINDEPTH, MMIN, MOUNT,
89 MTIME, NAME, NCPIO, NEWER, NOGRP, NOT, NOUSER, OK, OR, PATH, PERM,
90 PRINT0, PRUNE, REGEX, RPAREN, SIZE, TYPE, VARARGS, XATTR
91 };
92
93 enum Type
94 {
95 Unary, Id, Num, Str, Exec, Cpio, Op
96 };
97
98 struct Args
99 {
100 char name[10];
101 enum Command action;
102 enum Type type;
103 };
104
105 /*
106 * Except for pathnames, these are the only legal arguments
107 */
108 static struct Args commands[] =
109 {
110 "!", NOT, Op,
111 "(", LPAREN, Unary,
112 ")", RPAREN, Unary,
113 "-a", AND, Op,
114 "-acl", ACL, Unary,
115 "-amin", AMIN, Num,
116 "-and", AND, Op,
117 "-atime", ATIME, Num,
118 "-cmin", CMIN, Num,
119 "-cpio", CPIO, Cpio,
120 "-ctime", CTIME, Num,
121 "-depth", DEPTH, Unary,
122 "-exec", EXEC, Exec,
123 "-follow", FOLLOW, Unary,
124 "-fstype", FSTYPE, Str,
125 "-group", F_GROUP, Num,
126 "-groupacl", F_GROUPACL, Num,
127 "-iname", INAME, Str,
128 "-inum", INUM, Num,
129 "-ipath", IPATH, Str,
130 "-iregex", IREGEX, Str,
131 "-links", LINKS, Num,
132 "-local", LOCAL, Unary,
133 "-ls", LS, Unary,
134 "-maxdepth", MAXDEPTH, Num,
135 "-mindepth", MINDEPTH, Num,
136 "-mmin", MMIN, Num,
137 "-mount", MOUNT, Unary,
138 "-mtime", MTIME, Num,
139 "-name", NAME, Str,
140 "-ncpio", NCPIO, Cpio,
141 "-newer", NEWER, Str,
187
188
189 /*
190 * Prototype variable size arglist buffer
191 */
192
193 struct Arglist
194 {
195 struct Arglist *next;
196 char *end;
197 char *nextstr;
198 char **firstvar;
199 char **nextvar;
200 char *arglist[1];
201 };
202
203
204 static int compile();
205 static int execute();
206 static int doexec(char *, char **, int *);
207 static struct Args *lookup();
208 static int ok();
209 static void usage(void) __NORETURN;
210 static struct Arglist *varargs();
211 static int list();
212 static char *getgroup();
213 static FILE *cmdopen();
214 static int cmdclose();
215 static char *getshell();
216 static void init_remote_fs();
217 static char *getname();
218 static int readmode();
219 static mode_t getmode();
220 static char *gettail();
221
222
223 static int walkflags = FTW_CHDIR|FTW_PHYS|FTW_ANYERR|FTW_NOLOOP;
224 static struct Node *topnode;
225 static struct Node *freenode; /* next free node we may use later */
226 static char *cpio[] = { "cpio", "-o", 0 };
512 goto err;
513 if (oldnp->type == Op) {
514 (void) fprintf(stderr,
515 gettext("%s: cannot immediately"
516 " follow an operand with ')'\n"),
517 cmdname);
518 exit(1);
519 }
520 oldnp->next = 0;
521 return (av-argv);
522
523 case FOLLOW:
524 walkflags &= ~FTW_PHYS;
525 break;
526 case MOUNT:
527 walkflags |= FTW_MOUNT;
528 break;
529 case DEPTH:
530 walkflags |= FTW_DEPTH;
531 break;
532
533 case LOCAL:
534 np->first.l = 0L;
535 np->first.ll = 0LL;
536 np->second.i = '+';
537 /*
538 * Make it compatible to df -l for
539 * future enhancement. So, anything
540 * that is not remote, then it is
541 * local.
542 */
543 init_remote_fs();
544 break;
545
546 case SIZE:
547 if (b[strlen(b)-1] == 'c')
548 np->action = CSIZE;
549 /*FALLTHROUGH*/
550 case INUM:
551 np->first.ll = atoll(b);
950 val = (ll > np->first.ll);
951 else if (np->second.i == '-')
952 val = (ll < np->first.ll);
953 else
954 val = (ll == np->first.ll);
955 break;
956 num:
957 if (np->second.i == '+')
958 val = (l > np->first.l);
959 else if (np->second.i == '-')
960 val = (l < np->first.l);
961 else
962 val = (l == np->first.l);
963 break;
964 case OK:
965 val = ok(name, np->first.ap);
966 break;
967 case EXEC:
968 val = doexec(name, np->first.ap, NULL);
969 break;
970
971 case VARARGS: {
972 struct Arglist *ap = np->first.vp;
973 char *cp;
974 cp = ap->nextstr - (strlen(name)+1);
975 if (cp >= (char *)(ap->nextvar+3)) {
976 /* there is room just copy the name */
977 val = 1;
978 (void) strcpy(cp, name);
979 *ap->nextvar++ = cp;
980 ap->nextstr = cp;
981 } else {
982 /* no more room, exec command */
983 *ap->nextvar++ = name;
984 *ap->nextvar = 0;
985 val = 1;
986 (void) doexec((char *)0, ap->arglist,
987 &exec_exitcode);
988 ap->nextstr = ap->end;
989 ap->nextvar = ap->firstvar;
1301 if (status)
1302 exit_status = 1;
1303 }
1304 /* all the invocations have completed */
1305 exit(exit_status);
1306 }
1307
1308 if (name && dummyseen) {
1309 for (av = argv; cp = *av++; ) {
1310 if (cp == name)
1311 av[-1] = dummyarg;
1312 }
1313 }
1314
1315 if (r && exitcode != NULL)
1316 *exitcode = 3; /* use to indicate error in cmd invocation */
1317
1318 return (!r);
1319 }
1320
1321
1322 /*
1323 * Table lookup routine
1324 */
1325 static struct Args *
1326 lookup(word)
1327 char *word;
1328 {
1329 struct Args *argp = commands;
1330 int second;
1331 if (word == 0 || *word == 0)
1332 return (0);
1333 second = word[1];
1334 while (*argp->name) {
1335 if (second == argp->name[1] && strcmp(word, argp->name) == 0)
1336 return (argp);
1337 argp++;
1338 }
1339 return (0);
1340 }
1341
|
70 #define FTW_SLN 7
71 #endif
72 #define LINEBUF_SIZE LINE_MAX /* input or output lines */
73 #define REMOTE_FS "/etc/dfs/fstypes"
74 #define N_FSTYPES 20
75 #define SHELL_MAXARGS 253 /* see doexec() for description */
76
77 /*
78 * This is the list of operations
79 * F_USER and F_GROUP are named to avoid conflict with USER and GROUP defined
80 * in sys/acl.h
81 */
82
83 enum Command
84 {
85 PRINT,
86 ACL, AMIN, AND, ATIME, CMIN, CPIO, CSIZE, CTIME, DEPTH, EXEC, F_GROUP,
87 F_GROUPACL, F_USER, F_USERACL, FOLLOW, FSTYPE, INAME, INUM, IPATH,
88 IREGEX, LINKS, LOCAL, LPAREN, LS, MAXDEPTH, MINDEPTH, MMIN, MOUNT,
89 MTIME, NAME, NCPIO, NEWER, NOGRP, NOT, NOUSER, OK, OR, PATH, PERM,
90 PRINT0, PRUNE, REGEX, RPAREN, SIZE, TYPE, VARARGS, XATTR, DELETE
91 };
92
93 enum Type
94 {
95 Unary, Id, Num, Str, Exec, Cpio, Op
96 };
97
98 struct Args
99 {
100 char name[10];
101 enum Command action;
102 enum Type type;
103 };
104
105 /*
106 * Except for pathnames, these are the only legal arguments
107 */
108 static struct Args commands[] =
109 {
110 "!", NOT, Op,
111 "(", LPAREN, Unary,
112 ")", RPAREN, Unary,
113 "-a", AND, Op,
114 "-acl", ACL, Unary,
115 "-amin", AMIN, Num,
116 "-and", AND, Op,
117 "-atime", ATIME, Num,
118 "-cmin", CMIN, Num,
119 "-cpio", CPIO, Cpio,
120 "-ctime", CTIME, Num,
121 "-depth", DEPTH, Unary,
122 "-delete", DELETE, Unary,
123 "-exec", EXEC, Exec,
124 "-follow", FOLLOW, Unary,
125 "-fstype", FSTYPE, Str,
126 "-group", F_GROUP, Num,
127 "-groupacl", F_GROUPACL, Num,
128 "-iname", INAME, Str,
129 "-inum", INUM, Num,
130 "-ipath", IPATH, Str,
131 "-iregex", IREGEX, Str,
132 "-links", LINKS, Num,
133 "-local", LOCAL, Unary,
134 "-ls", LS, Unary,
135 "-maxdepth", MAXDEPTH, Num,
136 "-mindepth", MINDEPTH, Num,
137 "-mmin", MMIN, Num,
138 "-mount", MOUNT, Unary,
139 "-mtime", MTIME, Num,
140 "-name", NAME, Str,
141 "-ncpio", NCPIO, Cpio,
142 "-newer", NEWER, Str,
188
189
190 /*
191 * Prototype variable size arglist buffer
192 */
193
194 struct Arglist
195 {
196 struct Arglist *next;
197 char *end;
198 char *nextstr;
199 char **firstvar;
200 char **nextvar;
201 char *arglist[1];
202 };
203
204
205 static int compile();
206 static int execute();
207 static int doexec(char *, char **, int *);
208 static int dodelete(char *, struct stat *, struct FTW *);
209 static struct Args *lookup();
210 static int ok();
211 static void usage(void) __NORETURN;
212 static struct Arglist *varargs();
213 static int list();
214 static char *getgroup();
215 static FILE *cmdopen();
216 static int cmdclose();
217 static char *getshell();
218 static void init_remote_fs();
219 static char *getname();
220 static int readmode();
221 static mode_t getmode();
222 static char *gettail();
223
224
225 static int walkflags = FTW_CHDIR|FTW_PHYS|FTW_ANYERR|FTW_NOLOOP;
226 static struct Node *topnode;
227 static struct Node *freenode; /* next free node we may use later */
228 static char *cpio[] = { "cpio", "-o", 0 };
514 goto err;
515 if (oldnp->type == Op) {
516 (void) fprintf(stderr,
517 gettext("%s: cannot immediately"
518 " follow an operand with ')'\n"),
519 cmdname);
520 exit(1);
521 }
522 oldnp->next = 0;
523 return (av-argv);
524
525 case FOLLOW:
526 walkflags &= ~FTW_PHYS;
527 break;
528 case MOUNT:
529 walkflags |= FTW_MOUNT;
530 break;
531 case DEPTH:
532 walkflags |= FTW_DEPTH;
533 break;
534 case DELETE:
535 walkflags |= (FTW_DEPTH | FTW_PHYS);
536 walkflags &= ~FTW_CHDIR;
537 (*actionp)++;
538 break;
539
540 case LOCAL:
541 np->first.l = 0L;
542 np->first.ll = 0LL;
543 np->second.i = '+';
544 /*
545 * Make it compatible to df -l for
546 * future enhancement. So, anything
547 * that is not remote, then it is
548 * local.
549 */
550 init_remote_fs();
551 break;
552
553 case SIZE:
554 if (b[strlen(b)-1] == 'c')
555 np->action = CSIZE;
556 /*FALLTHROUGH*/
557 case INUM:
558 np->first.ll = atoll(b);
957 val = (ll > np->first.ll);
958 else if (np->second.i == '-')
959 val = (ll < np->first.ll);
960 else
961 val = (ll == np->first.ll);
962 break;
963 num:
964 if (np->second.i == '+')
965 val = (l > np->first.l);
966 else if (np->second.i == '-')
967 val = (l < np->first.l);
968 else
969 val = (l == np->first.l);
970 break;
971 case OK:
972 val = ok(name, np->first.ap);
973 break;
974 case EXEC:
975 val = doexec(name, np->first.ap, NULL);
976 break;
977 case DELETE:
978 val = dodelete(name, statb, state);
979 break;
980
981 case VARARGS: {
982 struct Arglist *ap = np->first.vp;
983 char *cp;
984 cp = ap->nextstr - (strlen(name)+1);
985 if (cp >= (char *)(ap->nextvar+3)) {
986 /* there is room just copy the name */
987 val = 1;
988 (void) strcpy(cp, name);
989 *ap->nextvar++ = cp;
990 ap->nextstr = cp;
991 } else {
992 /* no more room, exec command */
993 *ap->nextvar++ = name;
994 *ap->nextvar = 0;
995 val = 1;
996 (void) doexec((char *)0, ap->arglist,
997 &exec_exitcode);
998 ap->nextstr = ap->end;
999 ap->nextvar = ap->firstvar;
1311 if (status)
1312 exit_status = 1;
1313 }
1314 /* all the invocations have completed */
1315 exit(exit_status);
1316 }
1317
1318 if (name && dummyseen) {
1319 for (av = argv; cp = *av++; ) {
1320 if (cp == name)
1321 av[-1] = dummyarg;
1322 }
1323 }
1324
1325 if (r && exitcode != NULL)
1326 *exitcode = 3; /* use to indicate error in cmd invocation */
1327
1328 return (!r);
1329 }
1330
1331 static int
1332 dodelete(char *name, struct stat *statb, struct FTW *state)
1333 {
1334 char *fn;
1335 int rc = 0;
1336
1337 /* restrict symlinks */
1338 if ((walkflags & FTW_PHYS) == 0) {
1339 (void) fprintf(stderr,
1340 gettext("-delete is not allowed when symlinks are "
1341 "followed.\n"));
1342 return (1);
1343 }
1344
1345 fn = name + state->base;
1346 if (strcmp(fn, ".") == 0) {
1347 /* nothing to do */
1348 return (1);
1349 }
1350
1351 if (strchr(fn, '/') != NULL) {
1352 (void) fprintf(stderr,
1353 gettext("-delete with relative path is unsafe."));
1354 return (1);
1355 }
1356
1357 if (S_ISDIR(statb->st_mode)) {
1358 /* delete directory */
1359 rc = rmdir(name);
1360 } else {
1361 /* delete file */
1362 rc = unlink(name);
1363 }
1364
1365 if (rc < 0) {
1366 /* operation failed */
1367 (void) fprintf(stderr, gettext("delete failed %s: %s\n"),
1368 name, strerror(errno));
1369 return (1);
1370 }
1371
1372 return (1);
1373 }
1374
1375 /*
1376 * Table lookup routine
1377 */
1378 static struct Args *
1379 lookup(word)
1380 char *word;
1381 {
1382 struct Args *argp = commands;
1383 int second;
1384 if (word == 0 || *word == 0)
1385 return (0);
1386 second = word[1];
1387 while (*argp->name) {
1388 if (second == argp->name[1] && strcmp(word, argp->name) == 0)
1389 return (argp);
1390 argp++;
1391 }
1392 return (0);
1393 }
1394
|