find.c revision 1590
12061Sjkh/*- 240495Sbde * Copyright (c) 1991, 1993, 1994 32061Sjkh * The Regents of the University of California. All rights reserved. 438666Sjb * 532427Sjb * This code is derived from software contributed to Berkeley by 638666Sjb * Cimarron D. Taylor of the University of California, Berkeley. 738666Sjb * 838666Sjb * Redistribution and use in source and binary forms, with or without 938666Sjb * modification, are permitted provided that the following conditions 1038666Sjb * are met: 1138666Sjb * 1. Redistributions of source code must retain the above copyright 1238666Sjb * notice, this list of conditions and the following disclaimer. 1338666Sjb * 2. Redistributions in binary form must reproduce the above copyright 1438666Sjb * notice, this list of conditions and the following disclaimer in the 1538666Sjb * documentation and/or other materials provided with the distribution. 1638666Sjb * 3. All advertising materials mentioning features or use of this software 1738666Sjb * must display the following acknowledgement: 1838978Sjb * This product includes software developed by the University of 1938978Sjb * California, Berkeley and its contributors. 2032427Sjb * 4. Neither the name of the University nor the names of its contributors 2138666Sjb * may be used to endorse or promote products derived from this software 2238666Sjb * without specific prior written permission. 2338666Sjb * 2438666Sjb * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2538666Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2638666Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2717308Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2838666Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2938666Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3038666Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3119175Sbde * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3238666Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3338666Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3438042Sbde * SUCH DAMAGE. 3539726Sjb */ 3638666Sjb 3738666Sjb#ifndef lint 3838042Sbdestatic char sccsid[] = "@(#)find.c 8.3 (Berkeley) 4/1/94"; 3938666Sjb#endif /* not lint */ 4038666Sjb 4117308Speter#include <sys/types.h> 4238666Sjb#include <sys/stat.h> 4338666Sjb 4438666Sjb#include <err.h> 4538666Sjb#include <errno.h> 4617308Speter#include <fts.h> 4738666Sjb#include <stdio.h> 4838666Sjb#include <string.h> 4938666Sjb#include <stdlib.h> 5038666Sjb 5138666Sjb#include "find.h" 5238666Sjb 5317308Speter/* 5438666Sjb * find_formplan -- 5538666Sjb * process the command line and create a "plan" corresponding to the 5638666Sjb * command arguments. 5738666Sjb */ 5838666SjbPLAN * 5938666Sjbfind_formplan(argv) 6017308Speter char **argv; 6138666Sjb{ 6217308Speter PLAN *plan, *tail, *new; 6338666Sjb 6417308Speter /* 6527910Sasami * for each argument in the command line, determine what kind of node 6638666Sjb * it is, create the appropriate node type and add the new plan node 6738666Sjb * to the end of the existing plan. The resulting plan is a linked 6838666Sjb * list of plan nodes. For example, the string: 6927910Sasami * 7038666Sjb * % find . -name foo -newer bar -print 7138666Sjb * 7238666Sjb * results in the plan: 7327910Sasami * 7438666Sjb * [-name foo]--> [-newer bar]--> [-print] 7538666Sjb * 7638666Sjb * in this diagram, `[-name foo]' represents the plan node generated 7738666Sjb * by c_name() with an argument of foo and `-->' represents the 7838666Sjb * plan->next pointer. 7938666Sjb */ 8038666Sjb for (plan = tail = NULL; *argv;) { 8117308Speter if (!(new = find_create(&argv))) 8238666Sjb continue; 8338666Sjb if (plan == NULL) 8438666Sjb tail = plan = new; 8527910Sasami else { 8638666Sjb tail->next = new; 8738666Sjb tail = new; 8827910Sasami } 8938666Sjb } 9027910Sasami 9117308Speter /* 9238666Sjb * if the user didn't specify one of -print, -ok or -exec, then -print 9338666Sjb * is assumed so we add a -print node on the end. It is possible that 9417308Speter * the user might want the -print someplace else on the command line, 9540495Sbde * but there's no way to know that. 9640495Sbde */ 9740495Sbde if (!isoutput) { 9840495Sbde new = c_print(); 992061Sjkh if (plan == NULL) 10017308Speter tail = plan = new; 10138666Sjb else { 10217308Speter tail->next = new; 10338666Sjb tail = new; 10438666Sjb } 10538666Sjb } 1062302Spaul 10739206Sjkh /* 10839206Sjkh * the command line has been completely processed into a search plan 10939206Sjkh * except for the (, ), !, and -o operators. Rearrange the plan so 11017308Speter * that the portions of the plan which are affected by the operators 11138666Sjb * are moved into operator nodes themselves. For example: 11238666Sjb * 11317308Speter * [!]--> [-name foo]--> [-print] 11438666Sjb * 11538666Sjb * becomes 11638666Sjb * 11717308Speter * [! [-name foo] ]--> [-print] 11838666Sjb * 11938666Sjb * and 1202061Sjkh * 12117308Speter * [(]--> [-depth]--> [-name foo]--> [)]--> [-print] 12238666Sjb * 12338666Sjb * becomes 12417308Speter * 12538666Sjb * [expr [-depth]-->[-name foo] ]--> [-print] 1263626Swollman * 12717308Speter * operators are handled in order of precedence. 12838666Sjb */ 12938666Sjb 13017308Speter plan = paren_squish(plan); /* ()'s */ 13138978Sjb plan = not_squish(plan); /* !'s */ 13238978Sjb plan = or_squish(plan); /* -o's */ 1333626Swollman return (plan); 13417308Speter} 13538666Sjb 13617308SpeterFTS *tree; /* pointer to top of FTS hierarchy */ 13738666Sjb 13838666Sjb/* 13938666Sjb * find_execute -- 140 * take a search plan and an array of search paths and executes the plan 141 * over all FTSENT's returned for the given search paths. 142 */ 143int 144find_execute(plan, paths) 145 PLAN *plan; /* search plan */ 146 char **paths; /* array of pathnames to traverse */ 147{ 148 register FTSENT *entry; 149 PLAN *p; 150 int rval; 151 152 if ((tree = fts_open(paths, ftsoptions, (int (*)())NULL)) == NULL) 153 err(1, "ftsopen"); 154 155 for (rval = 0; (entry = fts_read(tree)) != NULL;) { 156 switch (entry->fts_info) { 157 case FTS_D: 158 if (isdepth) 159 continue; 160 break; 161 case FTS_DP: 162 if (!isdepth) 163 continue; 164 break; 165 case FTS_DNR: 166 case FTS_ERR: 167 case FTS_NS: 168 (void)fflush(stdout); 169 warnx("%s: %s", 170 entry->fts_path, strerror(entry->fts_errno)); 171 rval = 1; 172 continue; 173 } 174#define BADCH " \t\n\\'\"" 175 if (isxargs && strpbrk(entry->fts_path, BADCH)) { 176 (void)fflush(stdout); 177 warnx("%s: illegal path", entry->fts_path); 178 rval = 1; 179 continue; 180 } 181 182 /* 183 * Call all the functions in the execution plan until one is 184 * false or all have been executed. This is where we do all 185 * the work specified by the user on the command line. 186 */ 187 for (p = plan; p && (p->eval)(p, entry); p = p->next); 188 } 189 if (errno) 190 err(1, "fts_read"); 191 return (rval); 192} 193