1 #ifndef LINT
2 /* @(#) makelist.c 2.3 88/01/24 12:46:44 */
3 static char sccsid[]="@(#) makelist.c 2.3 88/01/24 12:46:44";
4 #endif /* LINT */
5 
6 /*
7 Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
8 (C) Copyright 1988 Rahul Dhesi -- All rights reserved
9 */
10 
11 #include "options.h"
12 #include "portable.h"
13 #include "errors.i"
14 #include "zoo.h"
15 #include "zooio.h"
16 #include "various.h"
17 
18 #include "zoofns.h"
19 #include "assert.h"
20 #include "debug.h"
21 
22 char *nameptr PARMS((char *));
23 void modpath PARMS((char *));
24 
25 /*******************/
26 /*
27 makelist() gets all pathnames corresponding to a set of filespecs and
28 adds them to a list.  Not more than "flistsize" pathnames are added.
29 Into `longest' it returns the length of the longest name added, or
30 zero if none added.
31 
32 Files ignore1, ignore2, and ignore3 are not added to the list.
33 A file that is a device/directory is also not added to the list.
34 
35 However, if ignore1 is NULL, both these tests are skipped and all files
36 will be added to the list.
37 */
38 
makelist(argc,argv,flist,flistsize,ignore1,ignore2,ignore3,longest)39 void makelist (argc, argv, flist, flistsize, ignore1, ignore2, ignore3, longest)
40 int argc;               /* number of filespec supplied */
41 char *argv[];           /* array of pointers to supplied filespecs */
42 register char *flist[]; /* array of pointers to filenames we will add */
43 int flistsize;          /* home many names we can use */
44 char *ignore1, *ignore2, *ignore3; /* files to exclude from list */
45 int *longest;        /* length of longest name in list */
46 {
47    char *this_path;        /* current pathname */
48    int fptr;               /* pointer to within flist */
49    register int i, j;      /* loop counters */
50 
51 #ifdef WILDCARD
52    char *pat_name;         /* filename part of pattern */
53 #endif
54 
55    int gap;                /* for Shell sort */
56 
57    flistsize--;            /* allow for one terminating NULL entry */
58    fptr = *longest = 0;
59 
60    assert(argc > 0);
61 
62 #define WCLEN	4	/* length needed for wildcard, and a little extra */
63 
64    while (argc > 0) {
65 #ifdef WILDCARD
66 		int argok = 0;											/* arg not matched yet */
67 #endif
68       char *this_arg;
69 		this_arg = emalloc (strlen (*argv) + WCLEN);
70 		strcpy (this_arg, *argv);
71 
72       /* Initialize fileset 0.  Select all files -- we will later
73 	 		filter out the ones wanted */
74 #ifdef FOLD
75       str_lwr (this_arg);
76 #endif
77 
78 #ifdef WILDCARD
79       pat_name = str_dup (nameptr (this_arg));		/* pattern without path */
80 #ifdef VER_CH /* trailing version field */
81 {
82    static char version_field[] = " *";
83    char *p;
84    p = strrchr (pat_name, VER_CH);
85    if (p == NULL) {
86       *version_field = VER_CH;
87       pat_name = newcat (pat_name, version_field); /* adds trailing ";*" */
88    }
89 }
90 #endif
91 		/*
92 		replace filename by wildcard;  however, if argument ends in slash,
93 		then simply append wildcard so we get all files in that directory
94 		*/
95 #ifdef FORCESLASH
96 			fixslash (this_arg);				/* convert backslashes to slashes */
97 #endif
98 
99 		if (*lastptr(this_arg) == *(char *) PATH_CH) {
100 			strcat (this_arg, WILDCARD);
101 			pat_name = "*";					/* and select all files */
102 		} else
103 #ifdef SPEC_WILD
104 			spec_wild (this_arg);
105 #else
106       	strcpy (nameptr (this_arg), WILDCARD);
107 #endif /* SPEC_WILD */
108 #endif /* WILDCARD */
109 
110       nextfile (0, this_arg, 0);
111       while (fptr < flistsize &&
112             (this_path = nextfile(1, (char *) NULL, 0)) != NULL) {
113          char *this_name = nameptr (this_path);
114 			modpath (this_path);					/* do any needed changes to path */
115 
116 #ifdef IGNORECASE
117 #define	COMPARE	str_icmp
118 #else
119 #define	COMPARE	strcmp
120 #endif
121 			if (ignore1 != NULL) {
122 				if (samefile (this_name,ignore1)  ||    /* exclude ignored files */
123 					 samefile (this_name,ignore2)  ||
124 					 samefile (this_name,ignore3))
125 					continue;
126 
127 #ifdef CHEKUDIR
128 				if (isuadir(this_path))
129 					continue;
130 #else /* CHEKUDIR */
131 # ifdef CHEKDIR
132 				if (isfdir(this_path))
133 					continue;
134 # endif /* CHEKDIR */
135 #endif /* CHEKUDIR */
136 			} /* end if ignore1 ! = NULL */
137 
138 /*
139 If WILDCARD is defined (e.g. AmigaDOS, MS-DOS, VAX/VMS), then nextfile()
140 returns all filenames and we must now select the ones we need by pattern
141 matching.  If WILDCARD is not defined (e.g. **IX), filenames have already been
142 selected by the shell and need not be tested again.
143 */
144 #ifdef WILDCARD
145 			if (match_half (this_name,pat_name) ||
146 				match_half (pat_name, "?-?") &&     /* character range */
147 					*this_name >= *pat_name && *this_name <= pat_name[2])
148 #endif
149 			{
150 #ifdef WILDCARD
151 				argok = 1;									/* remember arg matched */
152 #endif
153 				flist[fptr++] = str_dup (this_path);
154 				if (*longest < strlen(this_path))
155 					*longest = strlen(this_path);
156 			}
157 
158 		} /* end while */
159 #ifdef WILDCARD
160 		if (argok == 0) {									/* no match for argument */
161 			prterror ('e', "Could not open %s\n", *argv);
162 		}
163 #endif
164       argc--;
165       argv++;
166    }
167    /* fptr is now 1 + index of last item in array */
168 
169    if (this_path != NULL && fptr >= flistsize)
170       prterror ('w', too_many_files, flistsize);
171 #ifndef  DONT_SORT
172    /* Shell sort -- K&R p. 58 */
173    for (gap = fptr/2; gap > 0; gap /= 2)
174       for (i = gap; i < fptr; i++)
175          for (j = i - gap; j >= 0 &&
176             strcmp(flist[j],flist[j+gap]) > 0; j -= gap) {
177             char *t = flist[j]; flist[j] = flist[j+gap]; flist[j+gap] = t;
178          }
179 #endif /* DONT_SORT */
180 
181    fptr--;     /* fptr is now index of last item in array */
182 
183    /* Remove duplicates */
184    for (i = 0; i < fptr; i++) {
185       while (i<fptr && COMPARE(flist[i],flist[i+1]) == 0) {
186          for (j = i; j < fptr; j++)
187             flist[j] = flist[j+1];
188          fptr--;
189       }
190    }
191 
192    flist[++fptr] = NULL;      /* NULL entry terminates list */
193 }
194 
195 /*******
196 modpath() makes any changes needed before pathname is stored;
197 currently these could involve folding it to lower case and
198 converting backslashes to forward slashes
199 */
200 
201 /*ARGSUSED*/
modpath(path)202 void modpath (path)
203 char *path;
204 {
205 #ifdef FOLD
206 	str_lwr (path);
207 #endif
208 
209 #ifdef FORCESLASH
210 	fixslash (path);				/* convert backslashes to slashes */
211 #endif
212 }
213 
214 #ifdef CHEKDIR
215 /* Function isfdir returns 1 if pathname is a directory else 0 */
isfdir(this_path)216 int isfdir (this_path)
217 char *this_path;
218 {
219 	int dir;
220 	ZOOFILE f;
221 	f = zooopen (this_path, Z_READ);
222 	if (f == NOFILE)
223 		return 0;
224 	else {
225 		dir = isadir(f);  zooclose(f);
226 	}
227 	return (dir);
228 }
229 #endif
230