|
|
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.