|
|
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: #ifndef BSD4_2
13: #include <ndir.h>
14: #else
15: #include <sys/dir.h>
16: #endif
17:
18: #ifdef BSD4_2
19: #define DIRSIZE MAXNAMELEN
20: #else
21: #define DIRSIZE 14
22: #endif
23: #ifndef MAXNAMELEN
24: #define MAXNAMELEN 255
25: #endif
26:
27:
28: static char entry[DIRSIZE+1];
29:
30: /*
31: * globals (file name generation)
32: *
33: * "*" in params matches r.e ".*"
34: * "?" in params matches r.e. "."
35: * "[...]" in params matches character class
36: * "[...a-z...]" in params matches a through z.
37: *
38: */
39:
40: static addg();
41:
42: expand(as, rcnt)
43: char *as;
44: {
45: int count;
46: DIR *dirf;
47: BOOL dir = 0;
48: char *rescan = 0;
49: register char *s, *cs;
50: struct argnod *schain = gchain;
51: BOOL slash;
52:
53: if (trapnote & SIGSET)
54: return(0);
55: s = cs = as;
56: /*
57: * check for meta chars
58: */
59: {
60: register BOOL open;
61:
62: slash = 0;
63: open = 0;
64: do
65: {
66: switch (*cs++)
67: {
68: case 0:
69: if (rcnt && slash)
70: break;
71: else
72: return(0);
73:
74: case '/':
75: slash++;
76: open = 0;
77: continue;
78:
79: case '[':
80: open++;
81: continue;
82:
83: case ']':
84: if (open == 0)
85: continue;
86:
87: case '?':
88: case '*':
89: if (rcnt > slash)
90: continue;
91: else
92: cs--;
93: break;
94:
95:
96: default:
97: continue;
98: }
99: break;
100: } while (TRUE);
101: }
102:
103: for (;;)
104: {
105: if (cs == s)
106: {
107: s = nullstr;
108: break;
109: }
110: else if (*--cs == '/')
111: {
112: *cs = 0;
113: if (s == cs)
114: s = "/";
115: break;
116: }
117: }
118:
119: if ((dirf = opendir(*s ? s : ".")) != 0)
120: dir = TRUE;
121:
122: count = 0;
123: if (*cs == 0)
124: *cs++ = 0200;
125:
126: if(dir)
127: {
128: register char *rs;
129: struct direct *e;
130:
131: rs = cs;
132: do
133: {
134: if (*rs == '/')
135: {
136: rescan = rs;
137: *rs = 0;
138: gchain = 0;
139: }
140: } while (*rs++);
141:
142: while ((e = readdir(dirf)) && (trapnote & SIGSET) == 0)
143: {
144: *(movstrn(e->d_name, entry, DIRSIZE)) = 0;
145:
146: if (entry[0] == '.' && *cs != '.')
147: {
148: if (entry[1] == 0)
149: continue;
150: if (entry[1] == '.' && entry[2] == 0)
151: continue;
152: }
153:
154: if (gmatch(entry, cs))
155: {
156: addg(s, entry, rescan);
157: count++;
158: }
159: }
160: closedir(dirf);
161:
162: if (rescan)
163: {
164: register struct argnod *rchain;
165:
166: rchain = gchain;
167: gchain = schain;
168: if (count)
169: {
170: count = 0;
171: while (rchain)
172: {
173: count += expand(rchain->argval, slash + 1);
174: rchain = rchain->argnxt;
175: }
176: }
177: *rescan = '/';
178: }
179: }
180:
181: {
182: register char c;
183:
184: s = as;
185: while (c = *s)
186: *s++ = (c & STRIP ? c : '/');
187: }
188: return(count);
189: }
190:
191:
192:
193: gmatch(s, p)
194: register char *s, *p;
195: {
196: register int scc;
197: char c;
198:
199: if (scc = *s++)
200: {
201: if ((scc &= STRIP) == 0)
202: scc=0200;
203: }
204: switch (c = *p++)
205: {
206: case '[':
207: {
208: BOOL ok;
209: int lc;
210: int notflag = 0;
211:
212: ok = 0;
213: lc = 077777;
214: if (*p == '^')
215: {
216: notflag = 1;
217: p++;
218: }
219: while (c = *p++)
220: {
221: if (c == ']')
222: return(ok ? gmatch(s, p) : 0);
223: else if (c == MINUS)
224: {
225: if (notflag)
226: {
227: if (scc < lc || scc > *(p++))
228: ok++;
229: else
230: return(0);
231: }
232: else
233: {
234: if (lc <= scc && scc <= (*p++))
235: ok++;
236: }
237: }
238: else
239: {
240: lc = c & STRIP;
241: if (notflag)
242: {
243: if (scc && scc != lc)
244: ok++;
245: else
246: return(0);
247: }
248: else
249: {
250: if (scc == lc)
251: ok++;
252: }
253: }
254: }
255: return(0);
256: }
257:
258: default:
259: if ((c & STRIP) != scc)
260: return(0);
261:
262: case '?':
263: return(scc ? gmatch(s, p) : 0);
264:
265: case '*':
266: while (*p == '*')
267: p++;
268:
269: if (*p == 0)
270: return(1);
271: --s;
272: while (*s)
273: {
274: if (gmatch(s++, p))
275: return(1);
276: }
277: return(0);
278:
279: case 0:
280: return(scc == 0);
281: }
282: }
283:
284: static
285: addg(as1, as2, as3)
286: char *as1, *as2, *as3;
287: {
288: register char *s1;
289: register int c;
290:
291: staktop = locstak() + BYTESPERWORD;
292: s1 = as1;
293: while (c = *s1++)
294: {
295: if ((c &= STRIP) == 0)
296: {
297: pushstak('/');
298: break;
299: }
300: pushstak(c);
301: }
302: s1 = as2;
303: while (c = *s1++)
304: pushstak(c);
305: if (s1 = as3)
306: {
307: pushstak('/');
308: do
309: pushstak(*++s1);
310: while(*s1);
311: }
312: makearg(fixstak());
313: }
314:
315: makearg(args)
316: register struct argnod *args;
317: {
318: args->argnxt = gchain;
319: gchain = args;
320: }
321:
322:
323: DIR *
324: opendir(name)
325: register char *name;
326: {
1.1.1.2 ! root 327: int i;
1.1 root 328: DIR dirbuf, *dirp;
1.1.1.2 ! root 329: register char *p;
! 330: struct stat st;
! 331:
1.1 root 332: char buf[MAXNAMELEN+1];
333: register char *s;
334:
335: *(movstrn(name, buf, MAXNAMELEN)) = 0;
336: for (s=buf; *s; s++)
337: *s &= STRIP;
338: if ((dirbuf.dd_fd = open(buf, 0)) < 0)
339: return(NULL);
1.1.1.2 ! root 340: if (fstat(dirbuf.dd_fd, &st)!=0 || (st.st_mode & S_IFMT)!=S_IFDIR){
1.1 root 341: close(dirbuf.dd_fd);
342: return(NULL);
343: }
344: dirp = (DIR *)shalloc(sizeof(DIR));
345: *dirp = dirbuf;
1.1.1.2 ! root 346: dirp->dd_loc = 0;
! 347: i = read(dirp->dd_fd, dirp->dd_buf, DIRBLKSIZ);
! 348: if(i <= 0) {
! 349: close(dirp->dd_fd);
! 350: free(dirp);
! 351: return(0);
! 352: }
! 353: lseek(dirp->dd_fd, 0L, 0);
! 354: /* the cray and the 68000 are big-endians, vax is not
! 355: v9: ??.0000000000000??..000000000000|||||||||
! 356: cray: ????????.00000000000000000000000????????..0000000000000000000000|||||||
! 357: 68k: ????0X01.000????0X02..00|||||||| X=12
! 358: vaxn: ????X010.000????X020..00|||||||
! 359: /* shortest cray sys v dir is 64 bytes, shortest v8 is 32, and shortest
! 360: * sun 4.2(68k) is 24 (except it's supposed to be a whole block long)
! 361: */
! 362: if(i < 24) /* mysteriously short directory */
! 363: goto old;
! 364: p = dirp->dd_buf;
! 365: if(p[8] != '.') {
! 366: old:
! 367: if (fstat(dirp->dd_fd, &st) < 0) {
! 368: close(dirp->dd_fd);
! 369: free(dirp);
! 370: return(0);
! 371: }
! 372: if (st.st_ino == *(ino_t *)dirp->dd_buf)
! 373: dirp->dd_type = TOLD;
! 374: else
! 375: dirp->dd_type = TOLDSWAP;
! 376: return(dirp);
! 377: }
! 378: if(p[20] == '.' && p[21] == '.') { /* bsd-like or bogus */
! 379: if(*(short *)&p[4] == 0x000c) {
! 380: dirp->dd_type = TBSD;
! 381: return(dirp);
! 382: }
! 383: if(*(short *)&p[4] == 0x0c00) {
! 384: dirp->dd_type = TBSDSWAP;
! 385: return(dirp);
! 386: }
! 387: dirp->dd_type = TUNK;
! 388: return(dirp);
! 389: }
! 390: if(i >= 32 && p[9] == 0 && p[40] == '.' && p[41] == '.' && p[42] == 0) {
! 391: dirp->dd_type = TCRAY;
! 392: return(dirp);
! 393: }
! 394: dirp->dd_type = TUNK;
1.1 root 395: return(dirp);
396: }
397:
398: void
399: closedir(dirp)
400: DIR *dirp;
401: {
402: close(dirp->dd_fd);
403: shfree((char *)dirp);
404: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.