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