BSD 1 development
[unix-history] / s8 / glob2.c
CommitLineData
000e6f24
BJ
1#
2
3/*
4 * glob1 libs command arg ...
5 *
6 * Modified by: Bill Joy (UCB) Oct 1976
7 *
8 * takes library name string from the shell
9 * allows patterns to match directory names, i.e. "/mnt/c*?/.q"
10 * knows about pascal object and forks px's
11 */
12
13char usagestr[] "usage: glob2 libs command arg ...";
14
15char shell[] "/bin/sh";
16char px[] "/bin/px";
17
18#define PCXN 0404
19#define E2BIG 7
20#define ENOEXEC 8
21#define ENOENT 2
22
23#define STRSIZ 522
24#define PTHSIZ 100
25
26char *lib;
27
28char ab[STRSIZ];
29char *ava[200];
30char **av &ava[1];
31char *string ab;
32int ncoll;
33
34char path[100];
35char *pathp path;
36int globbed;
37char *entp;
38
39int errno;
40int stbuff[18];
41
42main(argc, argv)
43char *argv[];
44{
45 register char *cp1, *cp2, *cpl;
46
47 if (argc < 4)
48 panic(usagestr);
49 argv++;
50 argc--;
51 lib = *argv++;
52 argc--;
53 *av++ = *argv++;
54 argc--;
55 while (argc)
56 {
57 collect(*argv++);
58 argc--;
59 }
60 if (ncoll==0)
61 panic("No match");
62 cp1 = ava[1];
63 while(*cp1 && *cp1 != '/')
64 cp1++;
65 if (*cp1 || getuid())
66 execute(ava[1], &ava[1]);
67 if (!*cp1)
68 {
69 if (cpl = lib)
70 for(;;)
71 {
72 while ((*cpl & 0177) == ' ')
73 cpl++;
74 if (!*cpl)
75 break;
76 cp1 = path;
77 while (*cpl =& 0177)
78 if (*cpl == ' ')
79 break;
80 else if (cp1 >= &path[PTHSIZ-2])
81 patherr();
82 else
83 *cp1++ = *cpl++;
84 *cp1++ = '/';
85 cp2 = ava[1];
86 while(*cp1++ = *cp2++)
87 if (cp1 >= &path[PTHSIZ])
88 patherr();
89 execute(path, &ava[1]);
90 }
91 cp1 = path;
92 cp2 = "/usr/bin/";
93 while(*cp1++ = *cp2++)
94 ;
95 cp1--;
96 cp2 = ava[1];
97 while(*cp1++ = *cp2++)
98 if (cp1 >= &path[PTHSIZ])
99 patherr();
100 execute(path+4, &ava[1]);
101 execute(path, &ava[1]);
102 }
103 prs(ava[1]);
104 panic(": not found");
105}
106
107execute(afile, aarg)
108char *afile;
109char **aarg;
110{
111 register char *file, **arg;
112 register i;
113 int w;
114
115 arg = aarg;
116 file = afile;
117 execv(file, arg);
118 if (errno==ENOEXEC) {
119 arg[0] = file;
120 *--arg = shell;
121 i = open(file, 0);
122 if (i >= 0) {
123 if (read(i, &w, 2) == 2 && w == PCXN)
124 *arg = px;
125 close(i);
126 }
127 execv(*arg, arg);
128 prs("no ");
129 prs(*arg);
130 panic("!!");
131 } else if (errno==E2BIG)
132 toolong();
133}
134
135collect(as)
136{
137 char **oav;
138
139 oav = av;
140 globbed = 0;
141 expand(as);
142 sort(oav);
143}
144
145sort(oav)
146char **oav;
147{
148 register char **p1, **p2, **c;
149
150 p1 = oav;
151 while (p1 < av-1) {
152 p2 = p1;
153 while(++p2 < av) {
154 if (compar(*p1, *p2) > 0) {
155 c = *p1;
156 *p1 = *p2;
157 *p2 = c;
158 }
159 }
160 p1++;
161 }
162}
163
164expand(as)
165char *as;
166{
167 register char *cs;
168 char *spathp;
169 register int dirf;
170 static struct {
171 int ino;
172 char name[16];
173 } entry;
174
175 spathp = pathp;
176 cs = as;
177 while (*cs != '*' && *cs != '?' && *cs != '[') {
178 if (pathp >= &path[PTHSIZ])
179 patherr();
180 else if ((*pathp++ = *cs++) == 0) {
181 if (!globbed)
182 *av++ = cat(as, "");
183 else if (stat(path, &stbuff) >= 0) {
184 *av++ = cat(path, "");
185 ncoll++;
186 }
187 goto endit;
188 }
189 }
190 pathp = spathp;
191 cs--;
192 while (cs >= as && *cs != '/')
193 cs--;
194 while (as <= cs)
195 if (pathp >= &path[PTHSIZ])
196 patherr();
197 else
198 *pathp++ = *as++;
199 *pathp = 0;
200 dirf = open(path, 0);
201 if (dirf<0)
202 if (globbed)
203 goto endit;
204 else {
205 prs(path);
206 panic(": cannot open");
207 }
208 globbed++;
209 cs++;
210 while (read(dirf, &entry, 16) == 16) {
211 if (entry.ino==0)
212 continue;
213 if (match(entry.name, cs)) {
214 *av++ = cat(path, entry.name);
215 ncoll++;
216 }
217 }
218 close(dirf);
219endit:
220 pathp = spathp;
221 *pathp = 0;
222}
223
224toolong()
225{
226 panic("Arg list too long");
227}
228
229patherr()
230{
231 prs("Path too long: ");
232 panic(path);
233}
234
235match(s, p)
236char *s, *p;
237{
238 register c, sentp;
239
240 if (*s == '.' && *p != '.')
241 return(0);
242 sentp = entp;
243 entp = s;
244 c = amatch(s, p);
245 entp = sentp;
246 return(c);
247}
248
249amatch(as, ap)
250char *as, *ap;
251{
252 register char *s, *p;
253 register scc;
254 int c, cc, ok, lc;
255 char *spathp;
256
257 s = as;
258 p = ap;
259nextc:
260 if(scc = *s++ & 0177)
261 if ((scc =& 0177) == 0)
262 scc = 0200;
263 switch (c = *p++) {
264 case '[':
265 ok = 0;
266 lc = 077777;
267 while (cc = *p++) {
268 if (cc == ']') {
269 if (ok)
270 goto nextc;
271 else
272 return(0);
273 } else if (cc == '-') {
274 if (lc <= scc && scc <= *p++)
275 ok++;
276 } else
277 if (scc == (lc = cc))
278 ok++;
279 }
280 panic("missing ]");
281 case '*':
282 if(*p == '\0')
283 return(1);
284 else if (*p == '/') {
285 p++;
286 goto slash;
287 }
288 s--;
289 while(*s)
290 if (amatch(s, p))
291 return(1);
292 else
293 s++;
294 return(0);
295 case '\0':
296 return(scc == '\0');
297 default:
298 if (c == scc)
299 goto nextc;
300 else
301 return(0);
302 case '?':
303 if (scc != '\0')
304 goto nextc;
305 else
306 return(0);
307 case '/':
308 if (scc == '\0') {
309slash:
310 s = entp;
311 spathp = pathp;
312 while (*pathp = *s++)
313 pathp++;
314 *pathp++ = '/';
315 *pathp = 0;
316 if (stat(path, &stbuff) == 0)
317 if ((stbuff[2] & 060000) == 040000)
318 if (*p == 0) {
319 *av++ = cat(path, "");
320 ncoll++;
321 } else
322 expand(p);
323 pathp = spathp;
324 *pathp = 0;
325 }
326 return(0);
327 }
328}
329
330compar(as1, as2)
331char *as1, *as2;
332{
333 register char *s1, *s2;
334
335 s1 = as1;
336 s2 = as2;
337 while (*s1++ == *s2)
338 if (*s2++ == 0)
339 return(0);
340 if (*--s1 == '/')
341 return(-1);
342 else if (*s2 == '/')
343 return(1);
344 else
345 return (*s1 - *s2);
346}
347
348cat(as1, as2)
349char *as1, *as2;
350{
351 register char *s1, *s2;
352
353 s2 = string;
354 s1 = as1;
355 while (*s2++ = (*s1++ & 0177))
356 if (s2 >= &ab[STRSIZ])
357 toolong();
358 s1 = as2;
359 s2--;
360 while (*s2++ = *s1++)
361 if (s2 > &ab[STRSIZ])
362 toolong();
363 s1 = string;
364 string = s2;
365 return(s1);
366}
367
368prs(str)
369char *str;
370{
371 register char *cp;
372
373 cp = str;
374 while(*cp)
375 cp++;
376 write(2, str, cp-str);
377}
378
379panic(str)
380{
381 prs(str);
382 write(2, &"\n", 1);
383 exit(1);
384}