|
|
1.1 root 1: /*
2: * Miscellaneous functions
3: */
4:
5: #include <stddef.h>
6: #include <stdlib.h>
7: #include <limits.h>
8: #include <string.h>
9: #include <signal.h>
10: #include <errno.h>
11: #include <setjmp.h>
12: #include <sys/types.h>
13: #include <sys/stat.h>
14: #include <access.h>
15: #include "sh.h"
16: #include "expand.h"
17: #include "table.h"
18:
19: char ctypes [UCHAR_MAX]; /* type bits for unsigned char */
20:
21: /*
22: * Fast character classes
23: */
24: void
25: setctypes(s, t)
26: register Const char *s;
27: register int t;
28: {
29: register int i;
30:
31: if ((t&C_IFS)) {
32: for (i = 0; i < UCHAR_MAX; i++)
33: ctypes[i] &=~ C_IFS;
34: ctypes[0] |= C_IFS; /* include \0 in C_IFS */
35: }
36: ctypes[(unsigned char) *s++] |= t; /* allow leading \0 in string */
37: while (*s != 0)
38: ctypes[(unsigned char) *s++] |= t;
39: }
40:
41: void
42: initctypes()
43: {
44: register int c;
45:
46: for (c = 'a'; c <= 'z'; c++)
47: ctypes[c] |= C_ALPHA;
48: for (c = 'A'; c <= 'Z'; c++)
49: ctypes[c] |= C_ALPHA;
50: ctypes['_'] |= C_ALPHA;
51: setctypes("0123456789", C_DIGIT);
52: setctypes("\0 \t\n|&;<>()", C_LEX1);
53: setctypes("*@#!$-?", C_VAR1);
54: setctypes("=-+?#%", C_SUBOP);
55: }
56:
57: /* convert unsigned long to base N string */
58:
59: char *
60: ulton(n, base)
61: register unsigned long n;
62: int base;
63: {
64: register char *p;
65: static char buf [20];
66:
67: p = &buf[sizeof(buf)];
68: *--p = '\0';
69: do {
70: *--p = "0123456789ABCDEF"[n%base];
71: n /= base;
72: } while (n != 0);
73: return p;
74: }
75:
76: char *
77: strsave(s, ap)
78: register char *s;
79: Area *ap;
80: {
81: return strcpy((char*) alloc((size_t)strlen(s)+1, ap), s);
82: }
83:
84: static struct option {
85: char *name;
86: int flag;
87: } options[] = {
88: {"allexport", FEXPORT},
89: {"bgnice", FBGNICE},
90: #if EDIT
91: {"emacs", FEMACS},
92: #endif
93: {"errexit", FERREXIT},
94: {"hashall", FHASHALL},
95: {"ignoreeof", FIGNEOF},
96: {"interactive", FTALKING},
97: {"keyword", FKEYWORD},
98: {"markdirs", FMARKDIRS},
99: {"monitor", FMONITOR},
100: {"noexec", FNOEXEC},
101: {"noglob", FNOGLOB},
102: {"nounset", FNOUNSET},
103: {"privileged", FPRIVILEGED},
104: {"stdin", FSTDIN},
105: {"trackall", FHASHALL},
106: {"verbose", FVERBOSE},
107: {"xtrace", FXTRACE},
108: {NULL, 0}
109: };
110:
111: /*
112: * translate -o option into F* constant
113: */
114: int
115: option(n)
116: Const char *n;
117: {
118: register struct option *op;
119:
120: for (op = options; op->name != NULL; op++)
121: if (strcmp(op->name, n) == 0)
122: return op->flag;
123: return 0;
124: }
125:
126: char *
127: getoptions()
128: {
129: register int c;
130: char m [26+1];
131: register char *cp = m;
132:
133: for (c = 'a'; c <= 'z'; c++)
134: if (flag[FLAG(c)])
135: *cp++ = (char) c;
136: *cp = 0;
137: return strsave(m, ATEMP);
138: }
139:
140: void
141: printoptions()
142: {
143: register struct option *op;
144:
145: for (op = options; op->name != NULL; op++)
146: if (flag[op->flag])
147: shellf("%s ", op->name);
148: shellf("\n");
149: }
150:
151: /* atoi with error detection */
152:
153: getn(as)
154: char *as;
155: {
156: register char *s;
157: register int n;
158:
159: s = as;
160: if (*s == '-')
161: s++;
162: for (n = 0; digit(*s); s++)
163: n = (n*10) + (*s-'0');
164: if (*s)
165: errorf("%s: bad number\n", as);
166: return (*as == '-') ? -n : n;
167: }
168:
169: /*
170: * stripped down strerror for kill and exec
171: */
172: char *
173: strerror(i)
174: int i;
175: {
176: switch (i) {
177: case EINVAL:
178: return "Invalid argument";
179: case EACCES:
180: return "Permission denied";
181: case ESRCH:
182: return "No such process";
183: case EPERM:
184: return "Not owner";
185: case ENOENT:
186: return "No such file or directory";
187: case ENOTDIR:
188: return "Not a directory";
189: case ENOEXEC:
190: return "Exec format error";
191: case ENOMEM:
192: return "Not enough memory";
193: case E2BIG:
194: return "Argument list too long or program too large";
195: default:
196: return "Unknown system error";
197: }
198: }
199:
200: xpexpand(xp)
201: register XPtrV *xp;
202: {
203: int n = XPsize(*xp);
204: Void **vp;
205: register Void **dvp, **svp;
206:
207: vp = alloc(sizeofN(Void*, n*2), ATEMP);
208: for (svp = xp->beg, dvp = vp; svp < xp->cur; )
209: *dvp++ = *svp++;
210: afree((Void*) xp->beg, ATEMP);
211: xp->beg = vp;
212: xp->cur = vp + n;
213: xp->end = vp + n*2;
214: }
215:
216: /* -------- gmatch.c -------- */
217:
218: /*
219: * int gmatch(string, pattern)
220: * char *string, *pattern;
221: *
222: * Match a pattern as in sh(1).
223: * pattern character are prefixed with MAGIC by expand.
224: */
225:
226: #define NOT '!' /* might use ^ */
227:
228: static char *cclass ARGS((char *, int c));
229:
230: int
231: gmatch(s, p)
232: register unsigned char *s, *p;
233: {
234: register int sc, pc;
235:
236: if (s == NULL || p == NULL)
237: return 0;
238: while ((pc = *p++) != 0) {
239: sc = *s++;
240: if (pc == MAGIC) {
241: switch (*p++) {
242: case '[':
243: if ((p = cclass(p, sc)) == NULL)
244: return (0);
245: break;
246:
247: case '?':
248: if (sc == 0)
249: return (0);
250: break;
251:
252: case '*':
253: s--;
254: do {
255: if (*p == '\0' || gmatch(s, p)) {
256: return (1);
257: }
258: } while (*s++ != '\0');
259: return (0);
260:
261: }
262: } else
263: if (sc != pc)
264: return 0;
265: }
266: return (*s == 0);
267: }
268:
269: static char *
270: cclass(p, sub)
271: register char *p;
272: register int sub;
273: {
274: register int c, d, not, found = 0;
275:
276: if ((not = *p == NOT))
277: p++;
278: do {
279: if (*p == '\0')
280: return NULL;
281: c = *p;
282: if (p[1] == '-' && p[2] != ']') {
283: d = p[2];
284: p++;
285: } else
286: d = c;
287: if (c == sub || c <= sub && sub <= d)
288: found = 1;
289: } while (*++p != ']');
290:
291: return (found != not) ? p+1 : NULL;
292: }
293:
294: /* -------- qsort.c -------- */
295:
296: /*
297: * quick sort of array of generic pointers to objects.
298: */
299:
300: void
301: qsortp(base, n, f)
302: Void **base; /* base address */
303: size_t n; /* elements */
304: int (*f)(); /* compare function */
305: {
306: qsort1(base, base + n, f);
307: }
308:
309: #define swap2(a, b) {\
310: register Void *t; t = *(a); *(a) = *(b); *(b) = t;\
311: }
312: #define swap3(a, b, c) {\
313: register Void *t; t = *(a); *(a) = *(c); *(c) = *(b); *(b) = t;\
314: }
315:
316: qsort1(base, lim, f)
317: Void **base, **lim;
318: int (*f)();
319: {
320: register Void **i, **j;
321: register Void **lptr, **hptr;
322: size_t n;
323: int c;
324:
325: top:
326: n = (lim - base) / 2;
327: if (n == 0)
328: return;
329: hptr = lptr = base+n;
330: i = base;
331: j = lim - 1;
332:
333: for (;;) {
334: if (i < lptr) {
335: if ((c = (*f)(*i, *lptr)) == 0) {
336: lptr --;
337: swap2(i, lptr);
338: continue;
339: }
340: if (c < 0) {
341: i += 1;
342: continue;
343: }
344: }
345:
346: begin:
347: if (j > hptr) {
348: if ((c = (*f)(*hptr, *j)) == 0) {
349: hptr ++;
350: swap2(hptr, j);
351: goto begin;
352: }
353: if (c > 0) {
354: if (i == lptr) {
355: hptr ++;
356: swap3(i, hptr, j);
357: i = lptr += 1;
358: goto begin;
359: }
360: swap2(i, j);
361: j -= 1;
362: i += 1;
363: continue;
364: }
365: j -= 1;
366: goto begin;
367: }
368:
369: if (i == lptr) {
370: if (lptr-base >= lim-hptr) {
371: qsort1(hptr+1, lim, f);
372: lim = lptr;
373: } else {
374: qsort1(base, lptr, f);
375: base = hptr+1;
376: }
377: goto top;
378: }
379:
380: lptr -= 1;
381: swap3(j, lptr, i);
382: j = hptr -= 1;
383: }
384: }
385:
386: int
387: xstrcmp(p1, p2)
388: Void *p1, *p2;
389: {
390: return (strcmp((char *)p1, (char *)p2));
391: }
392:
393: #if COHERENT
394: /*
395: * check to see if new mail has arrived in the mailbox specified by $MAIL.
396: * if so, issue a friendly message.
397: */
398: void
399: mail()
400: {
401: char *mp; /* MAIL */
402: char *mcp; /* MAILCHECK */
403: static time_t interval = MAILINTERVAL; /* seconds between checks */
404: static time_t lasttime;
405: time_t currtime, time();
406: static long mailsize = -1;
407: struct stat sbuf;
408:
409: if (((mp = strval(global("MAIL"))) == NULL) || *mp == '\0')
410: return;
411: if ((mcp = strval(global("MAILCHECK"))) != NULL && *mcp != '\0')
412: if ((interval = (time_t)getn(mcp)) < 0)
413: interval = MAILINTERVAL;
414:
415: currtime = time((time_t *)0);
416: if ((currtime - lasttime) < interval)
417: return;
418: lasttime = currtime;
419:
420: if (stat(mp, &sbuf) < 0) {
421: mailsize = 0;
422: } else {
423: if (sbuf.st_size != 0 && sbuf.st_size > mailsize) {
424: if (mailsize == -1)
425: printf("You have mail.\n");
426: else
427: printf("You have new mail.\n");
428: }
429: mailsize = sbuf.st_size;
430: }
431: }
432:
433: /*
434: * modified version of access() which makes sure that anything
435: * executable is really a file. This fixes a bug (misfeature) where
436: * directories found along $PATH are treated as unexecutable executables.
437: */
438: eaccess(name, mode)
439: char *name;
440: int mode;
441: {
442: struct stat sbuf;
443: int ret;
444:
445: if ((mode & AEXEC) == 0)
446: return access(name, mode);
447: if ((ret = access(name, mode)) != 0)
448: return ret;
449: if (stat(name, &sbuf) < 0)
450: return 1;
451: return ((sbuf.st_mode & S_IFMT) != S_IFREG);
452: }
453: #endif /* COHERENT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.