1*9a747e4fSDavid du Colombier /* $Source: /u/mark/src/pax/RCS/namelist.c,v $
2*9a747e4fSDavid du Colombier *
3*9a747e4fSDavid du Colombier * $Revision: 1.6 $
4*9a747e4fSDavid du Colombier *
5*9a747e4fSDavid du Colombier * namelist.c - track filenames given as arguments to tar/cpio/pax
6*9a747e4fSDavid du Colombier *
7*9a747e4fSDavid du Colombier * DESCRIPTION
8*9a747e4fSDavid du Colombier *
9*9a747e4fSDavid du Colombier * Arguments may be regular expressions, therefore all agurments will
10*9a747e4fSDavid du Colombier * be treated as if they were regular expressions, even if they are
11*9a747e4fSDavid du Colombier * not.
12*9a747e4fSDavid du Colombier *
13*9a747e4fSDavid du Colombier * AUTHOR
14*9a747e4fSDavid du Colombier *
15*9a747e4fSDavid du Colombier * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
16*9a747e4fSDavid du Colombier *
17*9a747e4fSDavid du Colombier * Sponsored by The USENIX Association for public distribution.
18*9a747e4fSDavid du Colombier *
19*9a747e4fSDavid du Colombier * Copyright (c) 1989 Mark H. Colburn.
20*9a747e4fSDavid du Colombier * All rights reserved.
21*9a747e4fSDavid du Colombier *
22*9a747e4fSDavid du Colombier * Redistribution and use in source and binary forms are permitted
23*9a747e4fSDavid du Colombier * provided that the above copyright notice is duplicated in all such
24*9a747e4fSDavid du Colombier * forms and that any documentation, advertising materials, and other
25*9a747e4fSDavid du Colombier * materials related to such distribution and use acknowledge that the
26*9a747e4fSDavid du Colombier * software was developed by Mark H. Colburn and sponsored by The
27*9a747e4fSDavid du Colombier * USENIX Association.
28*9a747e4fSDavid du Colombier *
29*9a747e4fSDavid du Colombier * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
30*9a747e4fSDavid du Colombier * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
31*9a747e4fSDavid du Colombier * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32*9a747e4fSDavid du Colombier *
33*9a747e4fSDavid du Colombier * $Log: namelist.c,v $
34*9a747e4fSDavid du Colombier * Revision 1.6 89/02/13 09:14:48 mark
35*9a747e4fSDavid du Colombier * Fixed problem with directory errors
36*9a747e4fSDavid du Colombier *
37*9a747e4fSDavid du Colombier * Revision 1.5 89/02/12 12:14:00 mark
38*9a747e4fSDavid du Colombier * Fixed misspellings
39*9a747e4fSDavid du Colombier *
40*9a747e4fSDavid du Colombier * Revision 1.4 89/02/12 11:25:19 mark
41*9a747e4fSDavid du Colombier * Modifications to compile and link cleanly under USG
42*9a747e4fSDavid du Colombier *
43*9a747e4fSDavid du Colombier * Revision 1.3 89/02/12 10:40:23 mark
44*9a747e4fSDavid du Colombier * Fixed casting problems
45*9a747e4fSDavid du Colombier *
46*9a747e4fSDavid du Colombier * Revision 1.2 89/02/12 10:04:57 mark
47*9a747e4fSDavid du Colombier * 1.2 release fixes
48*9a747e4fSDavid du Colombier *
49*9a747e4fSDavid du Colombier * Revision 1.1 88/12/23 18:02:17 mark
50*9a747e4fSDavid du Colombier * Initial revision
51*9a747e4fSDavid du Colombier *
52*9a747e4fSDavid du Colombier */
53*9a747e4fSDavid du Colombier
54*9a747e4fSDavid du Colombier #ifndef lint
55*9a747e4fSDavid du Colombier static char *ident = "$Id: namelist.c,v 1.6 89/02/13 09:14:48 mark Exp $";
56*9a747e4fSDavid du Colombier static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
57*9a747e4fSDavid du Colombier #endif /* ! lint */
58*9a747e4fSDavid du Colombier
59*9a747e4fSDavid du Colombier
60*9a747e4fSDavid du Colombier /* Headers */
61*9a747e4fSDavid du Colombier
62*9a747e4fSDavid du Colombier #include "pax.h"
63*9a747e4fSDavid du Colombier
64*9a747e4fSDavid du Colombier
65*9a747e4fSDavid du Colombier /* Type Definitions */
66*9a747e4fSDavid du Colombier
67*9a747e4fSDavid du Colombier /*
68*9a747e4fSDavid du Colombier * Structure for keeping track of filenames and lists thereof.
69*9a747e4fSDavid du Colombier */
70*9a747e4fSDavid du Colombier struct nm_list {
71*9a747e4fSDavid du Colombier struct nm_list *next;
72*9a747e4fSDavid du Colombier short length; /* cached strlen(name) */
73*9a747e4fSDavid du Colombier char found; /* A matching file has been found */
74*9a747e4fSDavid du Colombier char firstch; /* First char is literally matched */
75*9a747e4fSDavid du Colombier char re; /* regexp pattern for item */
76*9a747e4fSDavid du Colombier char name[1]; /* name of file or rexexp */
77*9a747e4fSDavid du Colombier };
78*9a747e4fSDavid du Colombier
79*9a747e4fSDavid du Colombier struct dirinfo {
80*9a747e4fSDavid du Colombier char dirname[PATH_MAX + 1]; /* name of directory */
81*9a747e4fSDavid du Colombier OFFSET where; /* current location in directory */
82*9a747e4fSDavid du Colombier struct dirinfo *next;
83*9a747e4fSDavid du Colombier };
84*9a747e4fSDavid du Colombier
85*9a747e4fSDavid du Colombier
86*9a747e4fSDavid du Colombier /* Static Variables */
87*9a747e4fSDavid du Colombier
88*9a747e4fSDavid du Colombier static struct dirinfo *stack_head = (struct dirinfo *)NULL;
89*9a747e4fSDavid du Colombier
90*9a747e4fSDavid du Colombier
91*9a747e4fSDavid du Colombier /* Function Prototypes */
92*9a747e4fSDavid du Colombier
93*9a747e4fSDavid du Colombier #ifndef __STDC__
94*9a747e4fSDavid du Colombier
95*9a747e4fSDavid du Colombier static void pushdir();
96*9a747e4fSDavid du Colombier static struct dirinfo *popdir();
97*9a747e4fSDavid du Colombier
98*9a747e4fSDavid du Colombier #else
99*9a747e4fSDavid du Colombier
100*9a747e4fSDavid du Colombier static void pushdir(struct dirinfo *info);
101*9a747e4fSDavid du Colombier static struct dirinfo *popdir(void);
102*9a747e4fSDavid du Colombier
103*9a747e4fSDavid du Colombier #endif
104*9a747e4fSDavid du Colombier
105*9a747e4fSDavid du Colombier
106*9a747e4fSDavid du Colombier /* Internal Identifiers */
107*9a747e4fSDavid du Colombier
108*9a747e4fSDavid du Colombier static struct nm_list *namelast; /* Points to last name in list */
109*9a747e4fSDavid du Colombier static struct nm_list *namelist; /* Points to first name in list */
110*9a747e4fSDavid du Colombier
111*9a747e4fSDavid du Colombier
112*9a747e4fSDavid du Colombier /* addname - add a name to the namelist.
113*9a747e4fSDavid du Colombier *
114*9a747e4fSDavid du Colombier * DESCRIPTION
115*9a747e4fSDavid du Colombier *
116*9a747e4fSDavid du Colombier * Addname adds the name given to the name list. Memory for the
117*9a747e4fSDavid du Colombier * namelist structure is dynamically allocated. If the space for
118*9a747e4fSDavid du Colombier * the structure cannot be allocated, then the program will exit
119*9a747e4fSDavid du Colombier * the an out of memory error message and a non-zero return code
120*9a747e4fSDavid du Colombier * will be returned to the caller.
121*9a747e4fSDavid du Colombier *
122*9a747e4fSDavid du Colombier * PARAMETERS
123*9a747e4fSDavid du Colombier *
124*9a747e4fSDavid du Colombier * char *name - A pointer to the name to add to the list
125*9a747e4fSDavid du Colombier */
126*9a747e4fSDavid du Colombier
127*9a747e4fSDavid du Colombier #ifdef __STDC__
128*9a747e4fSDavid du Colombier
add_name(char * name)129*9a747e4fSDavid du Colombier void add_name(char *name)
130*9a747e4fSDavid du Colombier
131*9a747e4fSDavid du Colombier #else
132*9a747e4fSDavid du Colombier
133*9a747e4fSDavid du Colombier void add_name(name)
134*9a747e4fSDavid du Colombier char *name; /* pointer to name */
135*9a747e4fSDavid du Colombier
136*9a747e4fSDavid du Colombier #endif
137*9a747e4fSDavid du Colombier {
138*9a747e4fSDavid du Colombier int i; /* Length of string */
139*9a747e4fSDavid du Colombier struct nm_list *p; /* Current struct pointer */
140*9a747e4fSDavid du Colombier
141*9a747e4fSDavid du Colombier i = strlen(name);
142*9a747e4fSDavid du Colombier p = (struct nm_list *) malloc((unsigned) (i + sizeof(struct nm_list)));
143*9a747e4fSDavid du Colombier if (!p) {
144*9a747e4fSDavid du Colombier fatal("cannot allocate memory for namelist entry\n");
145*9a747e4fSDavid du Colombier }
146*9a747e4fSDavid du Colombier p->next = (struct nm_list *)NULL;
147*9a747e4fSDavid du Colombier p->length = i;
148*9a747e4fSDavid du Colombier strncpy(p->name, name, i);
149*9a747e4fSDavid du Colombier p->name[i] = '\0'; /* Null term */
150*9a747e4fSDavid du Colombier p->found = 0;
151*9a747e4fSDavid du Colombier p->firstch = isalpha(name[0]);
152*9a747e4fSDavid du Colombier if (strchr(name, '*') || strchr(name, '[') || strchr(name, '?')) {
153*9a747e4fSDavid du Colombier p->re = 1;
154*9a747e4fSDavid du Colombier }
155*9a747e4fSDavid du Colombier if (namelast) {
156*9a747e4fSDavid du Colombier namelast->next = p;
157*9a747e4fSDavid du Colombier }
158*9a747e4fSDavid du Colombier namelast = p;
159*9a747e4fSDavid du Colombier if (!namelist) {
160*9a747e4fSDavid du Colombier namelist = p;
161*9a747e4fSDavid du Colombier }
162*9a747e4fSDavid du Colombier }
163*9a747e4fSDavid du Colombier
164*9a747e4fSDavid du Colombier
165*9a747e4fSDavid du Colombier /* name_match - match a name from an archive with a name from the namelist
166*9a747e4fSDavid du Colombier *
167*9a747e4fSDavid du Colombier * DESCRIPTION
168*9a747e4fSDavid du Colombier *
169*9a747e4fSDavid du Colombier * Name_match attempts to find a name pointed at by p in the namelist.
170*9a747e4fSDavid du Colombier * If no namelist is available, then all filenames passed in are
171*9a747e4fSDavid du Colombier * assumed to match the filename criteria. Name_match knows how to
172*9a747e4fSDavid du Colombier * match names with regular expressions, etc.
173*9a747e4fSDavid du Colombier *
174*9a747e4fSDavid du Colombier * PARAMETERS
175*9a747e4fSDavid du Colombier *
176*9a747e4fSDavid du Colombier * char *p - the name to match
177*9a747e4fSDavid du Colombier *
178*9a747e4fSDavid du Colombier * RETURNS
179*9a747e4fSDavid du Colombier *
180*9a747e4fSDavid du Colombier * Returns 1 if the name is in the namelist, or no name list is
181*9a747e4fSDavid du Colombier * available, otherwise returns 0
182*9a747e4fSDavid du Colombier *
183*9a747e4fSDavid du Colombier */
184*9a747e4fSDavid du Colombier
185*9a747e4fSDavid du Colombier #ifdef __STDC__
186*9a747e4fSDavid du Colombier
name_match(char * p)187*9a747e4fSDavid du Colombier int name_match(char *p)
188*9a747e4fSDavid du Colombier
189*9a747e4fSDavid du Colombier #else
190*9a747e4fSDavid du Colombier
191*9a747e4fSDavid du Colombier int name_match(p)
192*9a747e4fSDavid du Colombier char *p;
193*9a747e4fSDavid du Colombier
194*9a747e4fSDavid du Colombier #endif
195*9a747e4fSDavid du Colombier {
196*9a747e4fSDavid du Colombier struct nm_list *nlp;
197*9a747e4fSDavid du Colombier int len;
198*9a747e4fSDavid du Colombier
199*9a747e4fSDavid du Colombier if ((nlp = namelist) == 0) {/* Empty namelist is easy */
200*9a747e4fSDavid du Colombier return (1);
201*9a747e4fSDavid du Colombier }
202*9a747e4fSDavid du Colombier len = strlen(p);
203*9a747e4fSDavid du Colombier for (; nlp != 0; nlp = nlp->next) {
204*9a747e4fSDavid du Colombier /* If first chars don't match, quick skip */
205*9a747e4fSDavid du Colombier if (nlp->firstch && nlp->name[0] != p[0]) {
206*9a747e4fSDavid du Colombier continue;
207*9a747e4fSDavid du Colombier }
208*9a747e4fSDavid du Colombier /* Regular expressions */
209*9a747e4fSDavid du Colombier if (nlp->re) {
210*9a747e4fSDavid du Colombier if (wildmat(nlp->name, p)) {
211*9a747e4fSDavid du Colombier nlp->found = 1; /* Remember it matched */
212*9a747e4fSDavid du Colombier return (1); /* We got a match */
213*9a747e4fSDavid du Colombier }
214*9a747e4fSDavid du Colombier continue;
215*9a747e4fSDavid du Colombier }
216*9a747e4fSDavid du Colombier /* Plain Old Strings */
217*9a747e4fSDavid du Colombier if (nlp->length <= len /* Archive len >= specified */
218*9a747e4fSDavid du Colombier && (p[nlp->length] == '\0' || p[nlp->length] == '/')
219*9a747e4fSDavid du Colombier && strncmp(p, nlp->name, nlp->length) == 0) {
220*9a747e4fSDavid du Colombier /* Name compare */
221*9a747e4fSDavid du Colombier nlp->found = 1; /* Remember it matched */
222*9a747e4fSDavid du Colombier return (1); /* We got a match */
223*9a747e4fSDavid du Colombier }
224*9a747e4fSDavid du Colombier }
225*9a747e4fSDavid du Colombier return (0);
226*9a747e4fSDavid du Colombier }
227*9a747e4fSDavid du Colombier
228*9a747e4fSDavid du Colombier
229*9a747e4fSDavid du Colombier /* names_notfound - print names of files in namelist that were not found
230*9a747e4fSDavid du Colombier *
231*9a747e4fSDavid du Colombier * DESCRIPTION
232*9a747e4fSDavid du Colombier *
233*9a747e4fSDavid du Colombier * Names_notfound scans through the namelist for any files which were
234*9a747e4fSDavid du Colombier * named, but for which a matching file was not processed by the
235*9a747e4fSDavid du Colombier * archive. Each of the files is listed on the standard error.
236*9a747e4fSDavid du Colombier *
237*9a747e4fSDavid du Colombier */
238*9a747e4fSDavid du Colombier
239*9a747e4fSDavid du Colombier #ifdef __STDC__
240*9a747e4fSDavid du Colombier
names_notfound(void)241*9a747e4fSDavid du Colombier void names_notfound(void)
242*9a747e4fSDavid du Colombier
243*9a747e4fSDavid du Colombier #else
244*9a747e4fSDavid du Colombier
245*9a747e4fSDavid du Colombier void names_notfound()
246*9a747e4fSDavid du Colombier
247*9a747e4fSDavid du Colombier #endif
248*9a747e4fSDavid du Colombier {
249*9a747e4fSDavid du Colombier struct nm_list *nlp;
250*9a747e4fSDavid du Colombier
251*9a747e4fSDavid du Colombier for (nlp = namelist; nlp != 0; nlp = nlp->next) {
252*9a747e4fSDavid du Colombier if (!nlp->found) {
253*9a747e4fSDavid du Colombier fprintf(stderr, "%s: %s not found in archive\n",
254*9a747e4fSDavid du Colombier myname, nlp->name);
255*9a747e4fSDavid du Colombier }
256*9a747e4fSDavid du Colombier free(nlp);
257*9a747e4fSDavid du Colombier }
258*9a747e4fSDavid du Colombier namelist = (struct nm_list *)NULL;
259*9a747e4fSDavid du Colombier namelast = (struct nm_list *)NULL;
260*9a747e4fSDavid du Colombier }
261*9a747e4fSDavid du Colombier
262*9a747e4fSDavid du Colombier
263*9a747e4fSDavid du Colombier /* name_init - set up to gather file names
264*9a747e4fSDavid du Colombier *
265*9a747e4fSDavid du Colombier * DESCRIPTION
266*9a747e4fSDavid du Colombier *
267*9a747e4fSDavid du Colombier * Name_init sets up the namelist pointers so that we may access the
268*9a747e4fSDavid du Colombier * command line arguments. At least the first item of the command
269*9a747e4fSDavid du Colombier * line (argv[0]) is assumed to be stripped off, prior to the
270*9a747e4fSDavid du Colombier * name_init call.
271*9a747e4fSDavid du Colombier *
272*9a747e4fSDavid du Colombier * PARAMETERS
273*9a747e4fSDavid du Colombier *
274*9a747e4fSDavid du Colombier * int argc - number of items in argc
275*9a747e4fSDavid du Colombier * char **argv - pointer to the command line arguments
276*9a747e4fSDavid du Colombier */
277*9a747e4fSDavid du Colombier
278*9a747e4fSDavid du Colombier #ifdef __STDC__
279*9a747e4fSDavid du Colombier
name_init(int argc,char ** argv)280*9a747e4fSDavid du Colombier void name_init(int argc, char **argv)
281*9a747e4fSDavid du Colombier
282*9a747e4fSDavid du Colombier #else
283*9a747e4fSDavid du Colombier
284*9a747e4fSDavid du Colombier void name_init(argc, argv)
285*9a747e4fSDavid du Colombier int argc;
286*9a747e4fSDavid du Colombier char **argv;
287*9a747e4fSDavid du Colombier
288*9a747e4fSDavid du Colombier #endif
289*9a747e4fSDavid du Colombier {
290*9a747e4fSDavid du Colombier /* Get file names from argv, after options. */
291*9a747e4fSDavid du Colombier n_argc = argc;
292*9a747e4fSDavid du Colombier n_argv = argv;
293*9a747e4fSDavid du Colombier }
294*9a747e4fSDavid du Colombier
295*9a747e4fSDavid du Colombier
296*9a747e4fSDavid du Colombier /* name_next - get the next name from argv or the name file.
297*9a747e4fSDavid du Colombier *
298*9a747e4fSDavid du Colombier * DESCRIPTION
299*9a747e4fSDavid du Colombier *
300*9a747e4fSDavid du Colombier * Name next finds the next name which is to be processed in the
301*9a747e4fSDavid du Colombier * archive. If the named file is a directory, then the directory
302*9a747e4fSDavid du Colombier * is recursively traversed for additional file names. Directory
303*9a747e4fSDavid du Colombier * names and locations within the directory are kept track of by
304*9a747e4fSDavid du Colombier * using a directory stack. See the pushdir/popdir function for
305*9a747e4fSDavid du Colombier * more details.
306*9a747e4fSDavid du Colombier *
307*9a747e4fSDavid du Colombier * The names come from argv, after options or from the standard input.
308*9a747e4fSDavid du Colombier *
309*9a747e4fSDavid du Colombier * PARAMETERS
310*9a747e4fSDavid du Colombier *
311*9a747e4fSDavid du Colombier * name - a pointer to a buffer of at least MAX_PATH + 1 bytes long;
312*9a747e4fSDavid du Colombier * statbuf - a pointer to a stat structure
313*9a747e4fSDavid du Colombier *
314*9a747e4fSDavid du Colombier * RETURNS
315*9a747e4fSDavid du Colombier *
316*9a747e4fSDavid du Colombier * Returns -1 if there are no names left, (e.g. EOF), otherwise returns
317*9a747e4fSDavid du Colombier * 0
318*9a747e4fSDavid du Colombier */
319*9a747e4fSDavid du Colombier
320*9a747e4fSDavid du Colombier #ifdef __STDC__
321*9a747e4fSDavid du Colombier
name_next(char * name,Stat * statbuf)322*9a747e4fSDavid du Colombier int name_next(char *name, Stat *statbuf)
323*9a747e4fSDavid du Colombier
324*9a747e4fSDavid du Colombier #else
325*9a747e4fSDavid du Colombier
326*9a747e4fSDavid du Colombier int name_next(name, statbuf)
327*9a747e4fSDavid du Colombier char *name;
328*9a747e4fSDavid du Colombier Stat *statbuf;
329*9a747e4fSDavid du Colombier
330*9a747e4fSDavid du Colombier #endif
331*9a747e4fSDavid du Colombier {
332*9a747e4fSDavid du Colombier int err = -1;
333*9a747e4fSDavid du Colombier static int in_subdir = 0;
334*9a747e4fSDavid du Colombier static DIR *dirp;
335*9a747e4fSDavid du Colombier struct dirent *d;
336*9a747e4fSDavid du Colombier static struct dirinfo *curr_dir;
337*9a747e4fSDavid du Colombier int len;
338*9a747e4fSDavid du Colombier
339*9a747e4fSDavid du Colombier do {
340*9a747e4fSDavid du Colombier if (names_from_stdin) {
341*9a747e4fSDavid du Colombier if (lineget(stdin, name) < 0) {
342*9a747e4fSDavid du Colombier return (-1);
343*9a747e4fSDavid du Colombier }
344*9a747e4fSDavid du Colombier if (nameopt(name) < 0) {
345*9a747e4fSDavid du Colombier continue;
346*9a747e4fSDavid du Colombier }
347*9a747e4fSDavid du Colombier } else {
348*9a747e4fSDavid du Colombier if (in_subdir) {
349*9a747e4fSDavid du Colombier if ((d = readdir(dirp)) != (struct dirent *)NULL) {
350*9a747e4fSDavid du Colombier /* Skip . and .. */
351*9a747e4fSDavid du Colombier if (strcmp(d->d_name, ".") == 0 ||
352*9a747e4fSDavid du Colombier strcmp(d->d_name, "..") == 0) {
353*9a747e4fSDavid du Colombier continue;
354*9a747e4fSDavid du Colombier }
355*9a747e4fSDavid du Colombier if (strlen(d->d_name) +
356*9a747e4fSDavid du Colombier strlen(curr_dir->dirname) >= PATH_MAX) {
357*9a747e4fSDavid du Colombier warn("name too long", d->d_name);
358*9a747e4fSDavid du Colombier continue;
359*9a747e4fSDavid du Colombier }
360*9a747e4fSDavid du Colombier strcpy(name, curr_dir->dirname);
361*9a747e4fSDavid du Colombier strcat(name, d->d_name);
362*9a747e4fSDavid du Colombier } else {
363*9a747e4fSDavid du Colombier closedir(dirp);
364*9a747e4fSDavid du Colombier in_subdir--;
365*9a747e4fSDavid du Colombier curr_dir = popdir();
366*9a747e4fSDavid du Colombier if (in_subdir) {
367*9a747e4fSDavid du Colombier errno = 0;
368*9a747e4fSDavid du Colombier if ((dirp=opendir(curr_dir->dirname)) == (DIR *)NULL) {
369*9a747e4fSDavid du Colombier warn(curr_dir->dirname, "error opening directory (1)");
370*9a747e4fSDavid du Colombier in_subdir--;
371*9a747e4fSDavid du Colombier }
372*9a747e4fSDavid du Colombier seekdir(dirp, curr_dir->where);
373*9a747e4fSDavid du Colombier }
374*9a747e4fSDavid du Colombier continue;
375*9a747e4fSDavid du Colombier }
376*9a747e4fSDavid du Colombier } else if (optind >= n_argc) {
377*9a747e4fSDavid du Colombier return (-1);
378*9a747e4fSDavid du Colombier } else {
379*9a747e4fSDavid du Colombier strcpy(name, n_argv[optind++]);
380*9a747e4fSDavid du Colombier }
381*9a747e4fSDavid du Colombier }
382*9a747e4fSDavid du Colombier if ((err = LSTAT(name, statbuf)) < 0) {
383*9a747e4fSDavid du Colombier warn(name, strerror());
384*9a747e4fSDavid du Colombier continue;
385*9a747e4fSDavid du Colombier }
386*9a747e4fSDavid du Colombier if (!names_from_stdin && (statbuf->sb_mode & S_IFMT) == S_IFDIR) {
387*9a747e4fSDavid du Colombier if (in_subdir) {
388*9a747e4fSDavid du Colombier curr_dir->where = telldir(dirp);
389*9a747e4fSDavid du Colombier pushdir(curr_dir);
390*9a747e4fSDavid du Colombier closedir(dirp);
391*9a747e4fSDavid du Colombier }
392*9a747e4fSDavid du Colombier in_subdir++;
393*9a747e4fSDavid du Colombier
394*9a747e4fSDavid du Colombier /* Build new prototype name */
395*9a747e4fSDavid du Colombier if ((curr_dir = (struct dirinfo *) mem_get(sizeof(struct dirinfo)))
396*9a747e4fSDavid du Colombier == (struct dirinfo *)NULL) {
397*9a747e4fSDavid du Colombier exit(2);
398*9a747e4fSDavid du Colombier }
399*9a747e4fSDavid du Colombier strcpy(curr_dir->dirname, name);
400*9a747e4fSDavid du Colombier len = strlen(curr_dir->dirname);
401*9a747e4fSDavid du Colombier while (len >= 1 && curr_dir->dirname[len - 1] == '/') {
402*9a747e4fSDavid du Colombier len--; /* Delete trailing slashes */
403*9a747e4fSDavid du Colombier }
404*9a747e4fSDavid du Colombier curr_dir->dirname[len++] = '/'; /* Now add exactly one back */
405*9a747e4fSDavid du Colombier curr_dir->dirname[len] = '\0';/* Make sure null-terminated */
406*9a747e4fSDavid du Colombier curr_dir->where = 0;
407*9a747e4fSDavid du Colombier
408*9a747e4fSDavid du Colombier errno = 0;
409*9a747e4fSDavid du Colombier do {
410*9a747e4fSDavid du Colombier if ((dirp = opendir(curr_dir->dirname)) == (DIR *)NULL) {
411*9a747e4fSDavid du Colombier warn(curr_dir->dirname, "error opening directory (2)");
412*9a747e4fSDavid du Colombier if (in_subdir > 1) {
413*9a747e4fSDavid du Colombier curr_dir = popdir();
414*9a747e4fSDavid du Colombier }
415*9a747e4fSDavid du Colombier in_subdir--;
416*9a747e4fSDavid du Colombier err = -1;
417*9a747e4fSDavid du Colombier continue;
418*9a747e4fSDavid du Colombier } else {
419*9a747e4fSDavid du Colombier seekdir(dirp, curr_dir->where);
420*9a747e4fSDavid du Colombier }
421*9a747e4fSDavid du Colombier } while (in_subdir && (! dirp));
422*9a747e4fSDavid du Colombier }
423*9a747e4fSDavid du Colombier } while (err < 0);
424*9a747e4fSDavid du Colombier return (0);
425*9a747e4fSDavid du Colombier }
426*9a747e4fSDavid du Colombier
427*9a747e4fSDavid du Colombier
428*9a747e4fSDavid du Colombier /* name_gather - gather names in a list for scanning.
429*9a747e4fSDavid du Colombier *
430*9a747e4fSDavid du Colombier * DESCRIPTION
431*9a747e4fSDavid du Colombier *
432*9a747e4fSDavid du Colombier * Name_gather takes names from the command line and adds them to
433*9a747e4fSDavid du Colombier * the name list.
434*9a747e4fSDavid du Colombier *
435*9a747e4fSDavid du Colombier * FIXME
436*9a747e4fSDavid du Colombier *
437*9a747e4fSDavid du Colombier * We could hash the names if we really care about speed here.
438*9a747e4fSDavid du Colombier */
439*9a747e4fSDavid du Colombier
440*9a747e4fSDavid du Colombier #ifdef __STDC__
441*9a747e4fSDavid du Colombier
name_gather(void)442*9a747e4fSDavid du Colombier void name_gather(void)
443*9a747e4fSDavid du Colombier
444*9a747e4fSDavid du Colombier #else
445*9a747e4fSDavid du Colombier
446*9a747e4fSDavid du Colombier void name_gather()
447*9a747e4fSDavid du Colombier
448*9a747e4fSDavid du Colombier #endif
449*9a747e4fSDavid du Colombier {
450*9a747e4fSDavid du Colombier while (optind < n_argc) {
451*9a747e4fSDavid du Colombier add_name(n_argv[optind++]);
452*9a747e4fSDavid du Colombier }
453*9a747e4fSDavid du Colombier }
454*9a747e4fSDavid du Colombier
455*9a747e4fSDavid du Colombier
456*9a747e4fSDavid du Colombier /* pushdir - pushes a directory name on the directory stack
457*9a747e4fSDavid du Colombier *
458*9a747e4fSDavid du Colombier * DESCRIPTION
459*9a747e4fSDavid du Colombier *
460*9a747e4fSDavid du Colombier * The pushdir function puses the directory structure which is pointed
461*9a747e4fSDavid du Colombier * to by "info" onto a stack for later processing. The information
462*9a747e4fSDavid du Colombier * may be retrieved later with a call to popdir().
463*9a747e4fSDavid du Colombier *
464*9a747e4fSDavid du Colombier * PARAMETERS
465*9a747e4fSDavid du Colombier *
466*9a747e4fSDavid du Colombier * dirinfo *info - pointer to directory structure to save
467*9a747e4fSDavid du Colombier */
468*9a747e4fSDavid du Colombier
469*9a747e4fSDavid du Colombier #ifdef __STDC__
470*9a747e4fSDavid du Colombier
pushdir(struct dirinfo * info)471*9a747e4fSDavid du Colombier static void pushdir(struct dirinfo *info)
472*9a747e4fSDavid du Colombier
473*9a747e4fSDavid du Colombier #else
474*9a747e4fSDavid du Colombier
475*9a747e4fSDavid du Colombier static void pushdir(info)
476*9a747e4fSDavid du Colombier struct dirinfo *info;
477*9a747e4fSDavid du Colombier
478*9a747e4fSDavid du Colombier #endif
479*9a747e4fSDavid du Colombier {
480*9a747e4fSDavid du Colombier if (stack_head == (struct dirinfo *)NULL) {
481*9a747e4fSDavid du Colombier stack_head = info;
482*9a747e4fSDavid du Colombier stack_head->next = (struct dirinfo *)NULL;
483*9a747e4fSDavid du Colombier } else {
484*9a747e4fSDavid du Colombier info->next = stack_head;
485*9a747e4fSDavid du Colombier stack_head = info;
486*9a747e4fSDavid du Colombier }
487*9a747e4fSDavid du Colombier }
488*9a747e4fSDavid du Colombier
489*9a747e4fSDavid du Colombier
490*9a747e4fSDavid du Colombier /* popdir - pop a directory structure off the directory stack.
491*9a747e4fSDavid du Colombier *
492*9a747e4fSDavid du Colombier * DESCRIPTION
493*9a747e4fSDavid du Colombier *
494*9a747e4fSDavid du Colombier * The popdir function pops the most recently pushed directory
495*9a747e4fSDavid du Colombier * structure off of the directory stack and returns it to the calling
496*9a747e4fSDavid du Colombier * function.
497*9a747e4fSDavid du Colombier *
498*9a747e4fSDavid du Colombier * RETURNS
499*9a747e4fSDavid du Colombier *
500*9a747e4fSDavid du Colombier * Returns a pointer to the most recently pushed directory structure
501*9a747e4fSDavid du Colombier * or NULL if the stack is empty.
502*9a747e4fSDavid du Colombier */
503*9a747e4fSDavid du Colombier
504*9a747e4fSDavid du Colombier #ifdef __STDC__
505*9a747e4fSDavid du Colombier
popdir(void)506*9a747e4fSDavid du Colombier static struct dirinfo *popdir(void)
507*9a747e4fSDavid du Colombier
508*9a747e4fSDavid du Colombier #else
509*9a747e4fSDavid du Colombier
510*9a747e4fSDavid du Colombier static struct dirinfo *popdir()
511*9a747e4fSDavid du Colombier
512*9a747e4fSDavid du Colombier #endif
513*9a747e4fSDavid du Colombier {
514*9a747e4fSDavid du Colombier struct dirinfo *tmp;
515*9a747e4fSDavid du Colombier
516*9a747e4fSDavid du Colombier if (stack_head == (struct dirinfo *)NULL) {
517*9a747e4fSDavid du Colombier return((struct dirinfo *)NULL);
518*9a747e4fSDavid du Colombier } else {
519*9a747e4fSDavid du Colombier tmp = stack_head;
520*9a747e4fSDavid du Colombier stack_head = stack_head->next;
521*9a747e4fSDavid du Colombier }
522*9a747e4fSDavid du Colombier return(tmp);
523*9a747e4fSDavid du Colombier }
524