| 1 | /*- |
| 2 | * Copyright (c) 1990 The Regents of the University of California. |
| 3 | * All rights reserved. |
| 4 | * |
| 5 | * This code is derived from software contributed to Berkeley by |
| 6 | * Cimarron D. Taylor of the University of California, Berkeley. |
| 7 | * |
| 8 | * %sccs.include.redist.c% |
| 9 | */ |
| 10 | |
| 11 | #ifndef lint |
| 12 | static char sccsid[] = "@(#)option.c 5.3 (Berkeley) %G%"; |
| 13 | #endif /* not lint */ |
| 14 | |
| 15 | #include <sys/types.h> |
| 16 | #include <sys/stat.h> |
| 17 | #include <fts.h> |
| 18 | #include <stdio.h> |
| 19 | #include "find.h" |
| 20 | |
| 21 | typedef struct _option { |
| 22 | char *name; /* option name */ |
| 23 | int token; /* token value */ |
| 24 | PLAN *(*create)(); /* create function */ |
| 25 | #define O_NONE 0x01 /* no call required */ |
| 26 | #define O_ZERO 0x02 /* pass: nothing */ |
| 27 | #define O_ARGV 0x04 /* pass: argv, increment argv */ |
| 28 | #define O_ARGVP 0x08 /* pass: *argv, T_OK || T_EXEC */ |
| 29 | #define O_MASK 0x0f /* mask of op bits */ |
| 30 | #define O_OLD 0x10 /* deprecated syntax */ |
| 31 | #define O_NEW 0x20 /* new syntax */ |
| 32 | int flags; |
| 33 | } OPTION; |
| 34 | |
| 35 | PLAN *c_atime(), *c_ctime(), *c_depth(), *c_exec(), *c_follow(), |
| 36 | *c_fstype(), *c_group(), *c_inum(), *c_links(), *c_ls(), |
| 37 | *c_mtime(), *c_name(), *c_newer(), *c_nogroup(), *c_nouser(), |
| 38 | *c_perm(), *c_print(), *c_prune(), *c_size(), *c_type(), |
| 39 | *c_user(), *c_xdev(), *c_openparen(), *c_closeparen(), *c_not(), |
| 40 | *c_or(); |
| 41 | |
| 42 | OPTION options[] = { |
| 43 | "!", T_NOT, c_not, O_ZERO, |
| 44 | "(", T_OPENPAREN, c_openparen, O_ZERO, |
| 45 | ")", T_CLOSEPAREN, c_closeparen, O_ZERO, |
| 46 | "a", T_AND, NULL, O_NONE|O_OLD, |
| 47 | "and", T_AND, NULL, O_NONE|O_NEW, |
| 48 | "atime", T_ATIME, c_atime, O_ARGV, |
| 49 | "ctime", T_CTIME, c_ctime, O_ARGV, |
| 50 | "depth", T_DEPTH, c_depth, O_ZERO|O_OLD, |
| 51 | "exec", T_EXEC, c_exec, O_ARGVP, |
| 52 | "follow", T_FOLLOW, c_follow, O_ZERO|O_OLD, |
| 53 | "fstype", T_FSTYPE, c_fstype, O_ARGV, |
| 54 | "group", T_GROUP, c_group, O_ARGV, |
| 55 | "inum", T_INUM, c_inum, O_ARGV, |
| 56 | "links", T_LINKS, c_links, O_ARGV, |
| 57 | "ls", T_LS, c_ls, O_ZERO, |
| 58 | "mtime", T_MTIME, c_mtime, O_ARGV, |
| 59 | "name", T_NAME, c_name, O_ARGV, |
| 60 | "newer", T_NEWER, c_newer, O_ARGV, |
| 61 | "nogroup", T_NOGROUP, c_nogroup, O_ZERO, |
| 62 | "nouser", T_NOUSER, c_nouser, O_ZERO, |
| 63 | "o", T_OR, c_or, O_ZERO|O_OLD, |
| 64 | "ok", T_OK, c_exec, O_ARGVP, |
| 65 | "or", T_OR, c_or, O_ZERO|O_NEW, |
| 66 | "perm", T_PERM, c_perm, O_ARGV, |
| 67 | "print", T_PRINT, c_print, O_ZERO, |
| 68 | "prune", T_PRUNE, c_prune, O_ZERO, |
| 69 | "size", T_SIZE, c_size, O_ARGV, |
| 70 | "type", T_TYPE, c_type, O_ARGV, |
| 71 | "user", T_USER, c_user, O_ARGV, |
| 72 | "xdev", T_XDEV, c_xdev, O_ZERO|O_OLD, |
| 73 | { NULL }, |
| 74 | }; |
| 75 | |
| 76 | /* |
| 77 | * find_create -- |
| 78 | * create a node corresponding to a command line argument. |
| 79 | * |
| 80 | * TODO: |
| 81 | * add create/process function pointers to node, so we can skip |
| 82 | * this switch stuff. |
| 83 | */ |
| 84 | PLAN * |
| 85 | find_create(argvp) |
| 86 | char ***argvp; |
| 87 | { |
| 88 | extern int deprecated; |
| 89 | register OPTION *p; |
| 90 | OPTION tmp; |
| 91 | PLAN *new; |
| 92 | char **argv; |
| 93 | int typecompare(); |
| 94 | |
| 95 | argv = *argvp; |
| 96 | tmp.name = *argv++; |
| 97 | |
| 98 | /* strip off any leading dash */ |
| 99 | if (*tmp.name == '-') |
| 100 | ++tmp.name; |
| 101 | |
| 102 | p = (OPTION *)bsearch(&tmp, options, sizeof(options)/sizeof(OPTION), |
| 103 | sizeof(OPTION), typecompare); |
| 104 | if (!p || deprecated && p->flags&O_NEW || |
| 105 | !deprecated && p->flags&O_OLD) { |
| 106 | (void)fprintf(stderr, "find: unknown option %s.\n", *--argv); |
| 107 | exit(1); |
| 108 | } |
| 109 | if (p->flags & (O_ARGV|O_ARGVP) && !*argv) { |
| 110 | (void)fprintf(stderr, |
| 111 | "find: %s requires additional arguments.\n", *--argv); |
| 112 | exit(1); |
| 113 | } |
| 114 | |
| 115 | switch(p->flags&O_MASK) { |
| 116 | case O_NONE: |
| 117 | new = NULL; |
| 118 | break; |
| 119 | case O_ZERO: |
| 120 | new = (p->create)(); |
| 121 | break; |
| 122 | case O_ARGV: |
| 123 | new = (p->create)(*argv++); |
| 124 | break; |
| 125 | case O_ARGVP: |
| 126 | new = (p->create)(&argv, p->token == T_OK); |
| 127 | break; |
| 128 | } |
| 129 | *argvp = argv; |
| 130 | return(new); |
| 131 | } |
| 132 | |
| 133 | typecompare(a, b) |
| 134 | OPTION *a, *b; |
| 135 | { |
| 136 | return(strcmp(a->name, b->name)); |
| 137 | } |