|
|
1.1 root 1: /* @(#)expand.c 1.4 */
2: /*
3: * UNIX shell
4: *
5: * Bell Telephone Laboratories
6: *
7: */
8:
9: #include "defs.h"
10: #include <sys/types.h>
11: #include <sys/stat.h>
12: #include <ndir.h>
13:
14: #ifdef BSD4_2
15: #define DIRSIZE MAXNAMELEN
16: #else
17: #define DIRSIZE 14
18: #endif
19: #ifndef MAXNAMELEN
20: #define MAXNAMELEN 255
21: #endif
22:
23:
24: static char entry[DIRSIZE+1];
25:
26: /*
27: * globals (file name generation)
28: *
29: * "*" in params matches r.e ".*"
30: * "?" in params matches r.e. "."
31: * "[...]" in params matches character class
32: * "[...a-z...]" in params matches a through z.
33: *
34: */
35: extern int addg();
36:
37:
38: expand(as, rcnt)
39: char *as;
40: {
41: int count;
42: DIR *dirf;
43: BOOL dir = 0;
44: char *rescan = 0;
45: register char *s, *cs;
46: struct argnod *schain = gchain;
47: BOOL slash;
48:
49: if (trapnote & SIGSET)
50: return(0);
51: s = cs = as;
52:
53: /*
54: * check for meta chars
55: */
56: {
57: register BOOL open;
58:
59: slash = 0;
60: open = 0;
61: do
62: {
63: switch (*cs++)
64: {
65: case 0:
66: if (rcnt && slash)
67: break;
68: else
69: return(0);
70:
71: case '/':
72: slash++;
73: open = 0;
74: continue;
75:
76: case '[':
77: open++;
78: continue;
79:
80: case ']':
81: if (open == 0)
82: continue;
83:
84: case '?':
85: case '*':
86: if (rcnt > slash)
87: continue;
88: else
89: cs--;
90: break;
91:
92:
93: default:
94: continue;
95: }
96: break;
97: } while (TRUE);
98: }
99:
100: for (;;)
101: {
102: if (cs == s)
103: {
104: s = nullstr;
105: break;
106: }
107: else if (*--cs == '/')
108: {
109: *cs = 0;
110: if (s == cs)
111: s = "/";
112: break;
113: }
114: }
115:
116: if ((dirf = opendir(*s ? s : ".")) != 0)
117: dir = TRUE;
118:
119: count = 0;
120: if (*cs == 0)
121: *cs++ = 0200;
122:
123: if(dir)
124: {
125: register char *rs;
126: struct direct *e;
127:
128: rs = cs;
129: do
130: {
131: if (*rs == '/')
132: {
133: rescan = rs;
134: *rs = 0;
135: gchain = 0;
136: }
137: } while (*rs++);
138:
139: while ((e = readdir(dirf)) && (trapnote & SIGSET) == 0)
140: {
141: *(movstrn(e->d_name, entry, DIRSIZE)) = 0;
142:
143: if (entry[0] == '.' && *cs != '.')
144: {
145: if (entry[1] == 0)
146: continue;
147: if (entry[1] == '.' && entry[2] == 0)
148: continue;
149: }
150:
151: if (gmatch(entry, cs))
152: {
153: addg(s, entry, rescan);
154: count++;
155: }
156: }
157: closedir(dirf);
158:
159: if (rescan)
160: {
161: register struct argnod *rchain;
162:
163: rchain = gchain;
164: gchain = schain;
165: if (count)
166: {
167: count = 0;
168: while (rchain)
169: {
170: count += expand(rchain->argval, slash + 1);
171: rchain = rchain->argnxt;
172: }
173: }
174: *rescan = '/';
175: }
176: }
177:
178: {
179: register char c;
180:
181: s = as;
182: while (c = *s)
183: *s++ = (c & STRIP ? c : '/');
184: }
185: return(count);
186: }
187:
188:
189:
190: gmatch(s, p)
191: register char *s, *p;
192: {
193: register int scc;
194: char c;
195:
196: if (scc = *s++)
197: {
198: if ((scc &= STRIP) == 0)
199: scc=0200;
200: }
201: switch (c = *p++)
202: {
203: case '[':
204: {
205: BOOL ok;
206: int lc;
207: int notflag = 0;
208:
209: ok = 0;
210: lc = 077777;
211: if (*p == '^')
212: {
213: notflag = 1;
214: p++;
215: }
216: while (c = *p++)
217: {
218: if (c == ']')
219: return(ok ? gmatch(s, p) : 0);
220: else if (c == MINUS)
221: {
222: if (notflag)
223: {
224: if (scc < lc || scc > *(p++))
225: ok++;
226: else
227: return(0);
228: }
229: else
230: {
231: if (lc <= scc && scc <= (*p++))
232: ok++;
233: }
234: }
235: else
236: {
237: lc = c & STRIP;
238: if (notflag)
239: {
240: if (scc && scc != lc)
241: ok++;
242: else
243: return(0);
244: }
245: else
246: {
247: if (scc == lc)
248: ok++;
249: }
250: }
251: }
252: return(0);
253: }
254:
255: default:
256: if ((c & STRIP) != scc)
257: return(0);
258:
259: case '?':
260: return(scc ? gmatch(s, p) : 0);
261:
262: case '*':
263: while (*p == '*')
264: p++;
265:
266: if (*p == 0)
267: return(1);
268: --s;
269: while (*s)
270: {
271: if (gmatch(s++, p))
272: return(1);
273: }
274: return(0);
275:
276: case 0:
277: return(scc == 0);
278: }
279: }
280:
281: static int
282: addg(as1, as2, as3)
283: char *as1, *as2, *as3;
284: {
285: register char *s1, *s2;
286: register int c;
287:
288: s2 = locstak() + BYTESPERWORD;
289: s1 = as1;
290: while (c = *s1++)
291: {
292: if ((c &= STRIP) == 0)
293: {
294: *s2++ = '/';
295: break;
296: }
297: *s2++ = c;
298: }
299: s1 = as2;
300: while (*s2 = *s1++)
301: s2++;
302: if (s1 = as3)
303: {
304: *s2++ = '/';
305: while (*s2++ = *++s1);
306: }
307: makearg(endstak(s2));
308: }
309:
310: makearg(args)
311: register struct argnod *args;
312: {
313: args->argnxt = gchain;
314: gchain = args;
315: }
316:
317:
318: DIR *
319: opendir(name)
320: register char *name;
321: {
322: DIR dirbuf, *dirp;
323: struct stat statb;
324: char buf[MAXNAMELEN+1];
325: register char *s;
326:
327: *(movstrn(name, buf, MAXNAMELEN)) = 0;
328: for (s=buf; *s; s++)
329: *s &= STRIP;
330: if ((dirbuf.dd_fd = open(buf, 0)) < 0)
331: return(NULL);
332: if (fstat(dirbuf.dd_fd, &statb)!=0 || (statb.st_mode & S_IFMT)!=S_IFDIR){
333: close(dirbuf.dd_fd);
334: return(NULL);
335: }
336: dirbuf.dd_loc = 0;
337: dirp = (DIR *)alloc(sizeof(DIR));
338: *dirp = dirbuf;
339: return(dirp);
340: }
341:
342: void
343: closedir(dirp)
344: DIR *dirp;
345: {
346: close(dirp->dd_fd);
347: free((char *)dirp);
348: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.