Commit | Line | Data |
---|---|---|
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 | ||
13 | char usagestr[] "usage: glob2 libs command arg ..."; | |
14 | ||
15 | char shell[] "/bin/sh"; | |
16 | char 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 | ||
26 | char *lib; | |
27 | ||
28 | char ab[STRSIZ]; | |
29 | char *ava[200]; | |
30 | char **av &ava[1]; | |
31 | char *string ab; | |
32 | int ncoll; | |
33 | ||
34 | char path[100]; | |
35 | char *pathp path; | |
36 | int globbed; | |
37 | char *entp; | |
38 | ||
39 | int errno; | |
40 | int stbuff[18]; | |
41 | ||
42 | main(argc, argv) | |
43 | char *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 | ||
107 | execute(afile, aarg) | |
108 | char *afile; | |
109 | char **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 | ||
135 | collect(as) | |
136 | { | |
137 | char **oav; | |
138 | ||
139 | oav = av; | |
140 | globbed = 0; | |
141 | expand(as); | |
142 | sort(oav); | |
143 | } | |
144 | ||
145 | sort(oav) | |
146 | char **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 | ||
164 | expand(as) | |
165 | char *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); | |
219 | endit: | |
220 | pathp = spathp; | |
221 | *pathp = 0; | |
222 | } | |
223 | ||
224 | toolong() | |
225 | { | |
226 | panic("Arg list too long"); | |
227 | } | |
228 | ||
229 | patherr() | |
230 | { | |
231 | prs("Path too long: "); | |
232 | panic(path); | |
233 | } | |
234 | ||
235 | match(s, p) | |
236 | char *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 | ||
249 | amatch(as, ap) | |
250 | char *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; | |
259 | nextc: | |
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') { | |
309 | slash: | |
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 | ||
330 | compar(as1, as2) | |
331 | char *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 | ||
348 | cat(as1, as2) | |
349 | char *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 | ||
368 | prs(str) | |
369 | char *str; | |
370 | { | |
371 | register char *cp; | |
372 | ||
373 | cp = str; | |
374 | while(*cp) | |
375 | cp++; | |
376 | write(2, str, cp-str); | |
377 | } | |
378 | ||
379 | panic(str) | |
380 | { | |
381 | prs(str); | |
382 | write(2, &"\n", 1); | |
383 | exit(1); | |
384 | } |