|
|
1.1 ! root 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: * Redistribution and use in source and binary forms are permitted provided ! 9: * that: (1) source distributions retain this entire copyright notice and ! 10: * comment, and (2) distributions including binaries display the following ! 11: * acknowledgement: ``This product includes software developed by the ! 12: * University of California, Berkeley and its contributors'' in the ! 13: * documentation or other materials provided with the distribution and in ! 14: * all advertising materials mentioning features or use of this software. ! 15: * Neither the name of the University nor the names of its contributors may ! 16: * be used to endorse or promote products derived from this software without ! 17: * specific prior written permission. ! 18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 19: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 20: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 21: */ ! 22: ! 23: #ifndef lint ! 24: char copyright[] = ! 25: "@(#) Copyright (c) 1990 The Regents of the University of California.\n\ ! 26: All rights reserved.\n"; ! 27: #endif /* not lint */ ! 28: ! 29: #ifndef lint ! 30: static char sccsid[] = "@(#)find.c 4.32 (Berkeley) 7/1/90"; ! 31: #endif /* not lint */ ! 32: ! 33: #include <sys/types.h> ! 34: #include <sys/stat.h> ! 35: #include <fts.h> ! 36: #include <stdio.h> ! 37: #include <string.h> ! 38: #include <errno.h> ! 39: #include "find.h" ! 40: ! 41: FTS *tree; /* pointer to top of FTS hierarchy */ ! 42: time_t now; /* time find was run */ ! 43: int ftsoptions; /* options passed to ftsopen() */ ! 44: int deprecated; /* old or new syntax */ ! 45: int depth; /* set by -depth option */ ! 46: int output_specified; /* one of -print, -ok or -exec was specified */ ! 47: ! 48: main(argc, argv) ! 49: int argc; ! 50: char **argv; ! 51: { ! 52: PLAN *plan; ! 53: char **p, **paths; ! 54: PLAN *find_formplan(); ! 55: time_t time(); ! 56: ! 57: (void)time(&now); /* initialize the time-of-day */ ! 58: ! 59: if (argc < 2) ! 60: usage(); ! 61: ! 62: paths = argv; ! 63: ftsoptions = FTS_NOSTAT|FTS_PHYSICAL; ! 64: ! 65: /* ! 66: * if arguments start with an option, treat it like new syntax; ! 67: * otherwise, if has a "-option" anywhere (which isn't an argument ! 68: * to another command) treat it as old syntax. ! 69: */ ! 70: if (argv[1][0] != '-') ! 71: for (p = argv + 1; *p; ++p) { ! 72: if (!strcmp(*p, "exec") || !strcmp(*p, "ok")) { ! 73: while (p[1] && strcmp(*++p, ";")); ! 74: continue; ! 75: } ! 76: if (**p == '-') { ! 77: deprecated = 1; ! 78: oldsyntax(&argv); ! 79: break; ! 80: } ! 81: } ! 82: if (!deprecated) ! 83: newsyntax(argc, &argv); ! 84: ! 85: plan = find_formplan(argv); /* execution plan */ ! 86: find_execute(plan, paths); ! 87: } ! 88: ! 89: /* ! 90: * find_formplan -- ! 91: * process the command line and create a "plan" corresponding to the ! 92: * command arguments. ! 93: */ ! 94: PLAN * ! 95: find_formplan(argv) ! 96: char **argv; ! 97: { ! 98: PLAN *plan, *tail, *new; ! 99: PLAN *c_print(), *find_create(), *find_squish_not(), *find_squish_or(); ! 100: PLAN *find_squish_paren(); ! 101: ! 102: /* ! 103: * for each argument in the command line, determine what kind of node ! 104: * it is, create the appropriate node type and add the new plan node ! 105: * to the end of the existing plan. The resulting plan is a linked ! 106: * list of plan nodes. For example, the string: ! 107: * ! 108: * % find . -name foo -newer bar -print ! 109: * ! 110: * results in the plan: ! 111: * ! 112: * [-name foo]--> [-newer bar]--> [-print] ! 113: * ! 114: * in this diagram, `[-name foo]' represents the plan node generated ! 115: * by c_name() with an argument of foo and `-->' represents the ! 116: * plan->next pointer. ! 117: */ ! 118: for (plan = NULL; *argv;) { ! 119: if (!(new = find_create(&argv))) ! 120: continue; ! 121: if (plan == NULL) ! 122: tail = plan = new; ! 123: else { ! 124: tail->next = new; ! 125: tail = new; ! 126: } ! 127: } ! 128: ! 129: /* ! 130: * if the user didn't specify one of -print, -ok or -exec, then -print ! 131: * is assumed so we add a -print node on the end. It is possible that ! 132: * the user might want the -print someplace else on the command line, ! 133: * but there's no way to know that. ! 134: */ ! 135: if (!output_specified) { ! 136: new = c_print(); ! 137: if (plan == NULL) ! 138: tail = plan = new; ! 139: else { ! 140: tail->next = new; ! 141: tail = new; ! 142: } ! 143: } ! 144: ! 145: /* ! 146: * the command line has been completely processed into a search plan ! 147: * except for the (, ), !, and -o operators. Rearrange the plan so ! 148: * that the portions of the plan which are affected by the operators ! 149: * are moved into operator nodes themselves. For example: ! 150: * ! 151: * [!]--> [-name foo]--> [-print] ! 152: * ! 153: * becomes ! 154: * ! 155: * [! [-name foo] ]--> [-print] ! 156: * ! 157: * and ! 158: * ! 159: * [(]--> [-depth]--> [-name foo]--> [)]--> [-print] ! 160: * ! 161: * becomes ! 162: * ! 163: * [expr [-depth]-->[-name foo] ]--> [-print] ! 164: * ! 165: * operators are handled in order of precedence. ! 166: */ ! 167: ! 168: plan = find_squish_paren(plan); /* ()'s */ ! 169: plan = find_squish_not(plan); /* !'s */ ! 170: plan = find_squish_or(plan); /* -o's */ ! 171: return(plan); ! 172: } ! 173: ! 174: /* ! 175: * find_execute -- ! 176: * take a search plan and an array of search paths and executes the plan ! 177: * over all FTSENT's returned for the given search paths. ! 178: */ ! 179: find_execute(plan, paths) ! 180: PLAN *plan; /* search plan */ ! 181: char **paths; /* array of pathnames to traverse */ ! 182: { ! 183: FTSENT *entry; /* current fts entry */ ! 184: PLAN *p; ! 185: ! 186: if (!(tree = ftsopen(paths, ftsoptions, NULL))) { ! 187: (void)fprintf(stderr, "find: ftsopen: %s.\n", strerror(errno)); ! 188: exit(1); ! 189: } ! 190: while (entry = ftsread(tree)) { ! 191: switch(entry->fts_info) { ! 192: case FTS_DNR: ! 193: (void)fprintf(stderr, ! 194: "find: %s: unable to read.\n", entry->fts_path); ! 195: continue; ! 196: case FTS_DNX: ! 197: (void)fprintf(stderr, ! 198: "find: %s: unable to search.\n", entry->fts_path); ! 199: continue; ! 200: case FTS_ERR: ! 201: (void)fprintf(stderr, ! 202: "find: %s: %s.\n", entry->fts_path, ! 203: strerror(errno)); ! 204: continue; ! 205: case FTS_D: ! 206: if (depth) ! 207: continue; ! 208: break; ! 209: case FTS_DC: ! 210: (void)fprintf(stderr, ! 211: "find: directory cycle: %s.\n", entry->fts_path); ! 212: continue; ! 213: case FTS_DP: ! 214: if (!depth) ! 215: continue; ! 216: case FTS_NS: ! 217: if (!(ftsoptions & FTS_NOSTAT)) { ! 218: (void)fprintf(stderr, ! 219: "find: can't stat: %s.\n", entry->fts_path); ! 220: continue; ! 221: } ! 222: break; ! 223: } ! 224: ! 225: /* ! 226: * call all the functions in the execution plan until one is ! 227: * false or all have been executed. This is where we do all ! 228: * the work specified by the user on the command line. ! 229: */ ! 230: for (p = plan; p && (p->eval)(p, entry); p = p->next); ! 231: } ! 232: (void)ftsclose(tree); ! 233: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.