|
|
1.1 root 1: /*
2: * A shell.
3: * Glob interpretation.
4: */
5: #include "sh.h"
6:
7: #include <sys/types.h>
8: #include <sys/dir.h>
9: #include <sys/stat.h>
10:
11: #define isdir(s) (((s)->st_mode&S_IFMT)==S_IFDIR)
12:
13: struct nmlst {
14: struct nmlst *g_next;
15: char g_name[];
16: };
17:
18: char *dirn = NULL;
19: int pref = 0;
20:
21: struct nmlst *newnm();
22: char *gany();
23: char *dread();
24: int nmcmp();
25:
26: /*
27: * Initial glob driver, set up initial directory name, pattern, and
28: * suffix; call glob2; sort the results.
29: */
30: glob1(args)
31: char *args;
32: {
33: register char *patt;
34: register char *suff;
35: register int nsep;
36: int myargc;
37:
38: if (gany(args)==NULL) {
39: /* Nothing to match */
40: strip(args);
41: newarg(args, 0);
42: } else {
43: if (dirn != NULL)
44: sfree(dirn);
45: dirn = salloc(DIRSIZ);
46: if (args[0]=='/') {
47: pref = 0;
48: strcpy(dirn, "/");
49: patt = args + 1;
50: } else {
51: pref = 2;
52: strcpy(dirn, "./");
53: patt = args;
54: }
55:
56: if ((suff=index(patt, '/')) != NULL)
57: for (nsep=0; *suff=='/'; nsep+=1)
58: *suff++ = '\0';
59: else
60: nsep = 0;
61: myargc = nargc;
62: glob2(patt, nsep, suff);
63: if (myargc != nargc)
64: qsort(&nargv[myargc], nargc-myargc,
65: sizeof(nargv[0]), nmcmp);
66: else {
67: /* No match */
68: while (nsep-- > 0)
69: *--suff = '/';
70: strip(args);
71: newarg(args, 0);
72: }
73: }
74: }
75:
76: nmcmp(cpp1, cpp2)
77: char **cpp1, **cpp2;
78: {
79: return (strcmp(*cpp1, *cpp2));
80: }
81:
82: glob2(patt, nsep, suff)
83: char *patt, *suff;
84: int nsep;
85: {
86: register struct nmlst *nmlst = NULL;
87: struct nmlst *np;
88: register char *name;
89: char *nsuff, *ndirn;
90: int nnsep, dirp;
91:
92: if (gany(patt)==NULL) {
93: nmlst = newnm(nmlst, patt);
94: strip(nmlst->g_name);
95: } else if (dopen(dirn) >= 0) {
96: while ((name = dread()) != NULL) {
97: if (match(patt, name)
98: && (name[0]!='.' || patt[0]=='.')) {
99: nmlst = newnm(nmlst, name);
100: }
101: }
102: }
103: if (nmlst!=NULL) {
104: ndirn = salloc(strlen(dirn)+DIRSIZ+nsep+1);
105: strcpy(ndirn, dirn);
106: sfree(dirn);
107: dirn = ndirn;
108: dirp = strlen(dirn);
109: if ((nsuff=suff)!=NULL && (nsuff=index(nsuff, '/'))!=NULL)
110: for (nnsep=0; *nsuff=='/'; nnsep+=1)
111: *nsuff++ = '\0';
112: else
113: nnsep = 0;
114: while (nmlst!=NULL) {
115: name = dirn + dirp;
116: strcpy(name, nmlst->g_name);
117: nmlst = (np = nmlst)->g_next;
118: sfree(np);
119: mksep(name, nsep);
120: if (suff!=NULL)
121: glob2(suff, nnsep, nsuff);
122: else
123: newarg(dirn + pref, 1);
124: }
125: while (nnsep-- > 0)
126: *--nsuff = '/';
127: dirn[dirp] = '\0';
128: }
129: }
130:
131: /*
132: * See if a pattern matches a string.
133: * '\' escapes the next character.
134: */
135: match(pp, sp)
136: register char *pp;
137: register char *sp;
138: {
139: int c2;
140: register int c1;
141:
142: while ((c1=*pp++)) {
143: switch (c1) {
144: case '?':
145: if (*sp++)
146: continue;
147: return (0);
148: case '*':
149: do {
150: if (match(pp, sp))
151: return (1);
152: } while (*sp++);
153: return (0);
154: case '[':
155: if ((c2=*sp++) == '\0')
156: return (0);
157: for (;;) {
158: if ((c1=*pp++) == '\0' || c1 == ']')
159: return (0);
160: if (c1 == '\\' && (c1=*pp++) == '\0')
161: return (0);
162: if (c1 == c2)
163: break;
164: if (*pp == '-') {
165: pp += 1;
166: if (c2 < c1)
167: continue;
168: if ((c1=*pp++) == '\0')
169: return (0);
170: if (c1 == '\\' && (c1=*pp++) == '\0')
171: return (0);
172: if (c2 <= c1)
173: break;
174: }
175: }
176: while ((c1 = *pp++) != ']') {
177: if (c1 == '\0')
178: return (0);
179: if (c1 == '\\' && *pp++ == '\0')
180: return (0);
181: }
182: continue;
183: case '\\':
184: if ((c1=*pp++) == '\0')
185: return (0);
186: /* fall through */
187: default:
188: if (c1 == *sp++)
189: continue;
190: return (0);
191: }
192: }
193: return (*sp=='\0');
194: }
195:
196: struct nmlst *
197: newnm(olst, name)
198: struct nmlst *olst;
199: char *name;
200: {
201: register struct nmlst *np;
202: register int n;
203:
204: n = strlen(name)+1+sizeof(*np);
205: np = (struct nmlst *) salloc(n);
206: np->g_next = olst;
207: strcpy(np->g_name, name);
208: return (np);
209: }
210:
211: mksep(cp, ns)
212: register char *cp;
213: register int ns;
214: {
215: while (*cp != '\0')
216: cp += 1;
217: while (ns-- > 0)
218: *cp++ = '/';
219: *cp = '\0';
220: }
221:
222: newarg(p, f)
223: char *p;
224: {
225: struct stat s;
226:
227: if (f && stat(p, &s) < 0)
228: return;
229: nargc += 1;
230: nargv = addargl(nargv, duplstr(p, 0));
231: }
232:
233: /*
234: * Returns the location of the next unescaped glob character.
235: */
236: char *
237: gany(s)
238: register char *s;
239: {
240: register int c;
241:
242: while (*s)
243: if ((c=*s++) == '\\')
244: if (*s++ == '\0')
245: return (NULL);
246: else
247: continue;
248: else if (c == '*' || c == '?' || c == '[')
249: return (--s);
250: return (NULL);
251: }
252:
253: /*
254: * get rid of the glob escapes.
255: */
256: strip(s)
257: register char *s;
258: {
259: register char *p;
260:
261: p = s;
262: while (*s)
263: if ((*p = *s++) == '\\')
264: if (*p++ = *s++)
265: continue;
266: else
267: break;
268: else
269: p++;
270: *p = *s;
271: }
272:
273: int dfd;
274: int dcnt;
275: struct direct *dptr;
276: struct direct *dbuf = strt;
277: char dtmp[DIRSIZ+2] = { 0 };
278:
279: dopen(p)
280: char *p;
281: {
282: struct stat s;
283:
284: dcnt = 0;
285: if (stat(p, &s) < 0
286: || ! isdir(&s)
287: || (dfd = open(p, 0)) < 0)
288: dfd = -1;
289: return (dfd);
290: }
291:
292: char *
293: dread()
294: {
295: register struct direct *dp;
296:
297: while (dfd >= 0) {
298: while (dcnt-- > 0) {
299: dp = dptr++;
300: if (dp->d_ino != 0)
301: return (strncpy(dtmp, dp->d_name, DIRSIZ));
302: }
303: dptr = dbuf;
304: dcnt = read(dfd, (char *)dptr, 64*sizeof(dbuf[0]));
305: dcnt /= sizeof(dbuf[0]);
306: if (dcnt <= 0) {
307: close(dfd);
308: dfd = -1;
309: }
310: }
311: return (NULL);
312: }
313:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.