|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)library.c 5.2 (Berkeley) 4/7/87"; ! 9: #endif not lint ! 10: ! 11: /* ! 12: * General purpose routines. ! 13: */ ! 14: ! 15: #include <stdio.h> ! 16: #include <errno.h> ! 17: #include "defs.h" ! 18: ! 19: #define public ! 20: #define private static ! 21: #define and && ! 22: #define nil(type) ((type) 0) ! 23: ! 24: typedef char *String; ! 25: typedef FILE *File; ! 26: typedef String Filename; ! 27: typedef char Boolean; ! 28: ! 29: #undef FILE ! 30: ! 31: String cmdname; /* name of command for error messages */ ! 32: Filename errfilename; /* current file associated with error */ ! 33: short errlineno; /* line number associated with error */ ! 34: ! 35: typedef int INTFUNC(); ! 36: ! 37: typedef struct { ! 38: INTFUNC *func; ! 39: } ERRINFO; ! 40: ! 41: #define ERR_IGNORE ((INTFUNC *) 0) ! 42: #define ERR_CATCH ((INTFUNC *) 1) ! 43: ! 44: public INTFUNC *onsyserr(); ! 45: ! 46: /* ! 47: * Call a program. ! 48: * ! 49: * Three entries: ! 50: * ! 51: * call, callv - call a program and wait for it, returning status ! 52: * backv - call a program and don't wait, returning process id ! 53: * ! 54: * The command's standard input and output are passed as FILE's. ! 55: */ ! 56: ! 57: ! 58: #define MAXNARGS 100 /* unchecked upper limit on max num of arguments */ ! 59: #define BADEXEC 127 /* exec fails */ ! 60: ! 61: #define ischild(pid) ((pid) == 0) ! 62: ! 63: /* VARARGS3 */ ! 64: public int call(name, in, out, args) ! 65: String name; ! 66: File in; ! 67: File out; ! 68: String args; ! 69: { ! 70: String *ap, *argp; ! 71: String argv[MAXNARGS]; ! 72: ! 73: argp = &argv[0]; ! 74: *argp++ = name; ! 75: ap = &args; ! 76: while (*ap != nil(String)) { ! 77: *argp++ = *ap++; ! 78: } ! 79: *argp = nil(String); ! 80: return callv(name, in, out, argv); ! 81: } ! 82: ! 83: public int callv(name, in, out, argv) ! 84: String name; ! 85: File in; ! 86: File out; ! 87: String *argv; ! 88: { ! 89: int pid, status; ! 90: ! 91: pid = backv(name, in, out, argv); ! 92: pwait(pid, &status); ! 93: return status; ! 94: } ! 95: ! 96: public int backv(name, in, out, argv) ! 97: String name; ! 98: File in; ! 99: File out; ! 100: String *argv; ! 101: { ! 102: int pid; ! 103: ! 104: fflush(stdout); ! 105: if (ischild(pid = fork())) { ! 106: fswap(0, fileno(in)); ! 107: fswap(1, fileno(out)); ! 108: (void) onsyserr(EACCES, ERR_IGNORE); ! 109: execvp(name, argv); ! 110: _exit(BADEXEC); ! 111: } ! 112: return pid; ! 113: } ! 114: ! 115: /* ! 116: * Swap file numbers so as to redirect standard input and output. ! 117: */ ! 118: ! 119: private fswap(oldfd, newfd) ! 120: int oldfd; ! 121: int newfd; ! 122: { ! 123: if (oldfd != newfd) { ! 124: close(oldfd); ! 125: dup(newfd); ! 126: close(newfd); ! 127: } ! 128: } ! 129: ! 130: /* ! 131: * Invoke a shell on a command line. ! 132: */ ! 133: ! 134: #define DEF_SHELL "csh" ! 135: ! 136: public shell(s) ! 137: String s; ! 138: { ! 139: extern String getenv(); ! 140: String sh; ! 141: ! 142: if ((sh = getenv("SHELL")) == nil(String)) { ! 143: sh = DEF_SHELL; ! 144: } ! 145: call(sh, stdin, stdout, "-c", s, 0); ! 146: } ! 147: ! 148: /* ! 149: * Wait for a process the right way. We wait for a particular ! 150: * process and if any others come along in between, we remember them ! 151: * in case they are eventually waited for. ! 152: * ! 153: * This routine is not very efficient when the number of processes ! 154: * to be remembered is large. ! 155: */ ! 156: ! 157: typedef struct pidlist { ! 158: int pid; ! 159: int status; ! 160: struct pidlist *next; ! 161: } Pidlist; ! 162: ! 163: private Pidlist *pidlist, *pfind(); ! 164: ! 165: public pwait(pid, statusp) ! 166: int pid, *statusp; ! 167: { ! 168: Pidlist *p; ! 169: int pnum, status; ! 170: ! 171: p = pfind(pid); ! 172: if (p != nil(Pidlist *)) { ! 173: *statusp = p->status; ! 174: dispose(p); ! 175: return; ! 176: } ! 177: while ((pnum = wait(&status)) != pid && pnum >= 0) { ! 178: p = alloc(1, Pidlist); ! 179: p->pid = pnum; ! 180: p->status = status; ! 181: p->next = pidlist; ! 182: pidlist = p; ! 183: } ! 184: if (pnum < 0) { ! 185: p = pfind(pid); ! 186: if (p == nil(Pidlist *)) { ! 187: panic("pwait: pid %d not found", pid); ! 188: } ! 189: *statusp = p->status; ! 190: dispose(p); ! 191: } else { ! 192: *statusp = status; ! 193: } ! 194: #ifdef tahoe ! 195: chkret(p, status); ! 196: #endif ! 197: } ! 198: ! 199: /* ! 200: * Look for the given process id on the pidlist. ! 201: * ! 202: * Unlink it from list if found. ! 203: */ ! 204: ! 205: private Pidlist *pfind(pid) ! 206: int pid; ! 207: { ! 208: register Pidlist *p, *prev; ! 209: ! 210: prev = nil(Pidlist *); ! 211: for (p = pidlist; p != nil(Pidlist *); p = p->next) { ! 212: if (p->pid == pid) { ! 213: break; ! 214: } ! 215: prev = p; ! 216: } ! 217: if (p != nil(Pidlist *)) { ! 218: if (prev == nil(Pidlist *)) { ! 219: pidlist = p->next; ! 220: } else { ! 221: prev->next = p->next; ! 222: } ! 223: } ! 224: return p; ! 225: } ! 226: ! 227: /* ! 228: * System call error handler. ! 229: * ! 230: * The syserr routine is called when a system call is about to ! 231: * set the c-bit to report an error. Certain errors are caught ! 232: * and cause the process to print a message and immediately exit. ! 233: */ ! 234: ! 235: extern int sys_nerr; ! 236: extern char *sys_errlist[]; ! 237: ! 238: /* ! 239: * Before calling syserr, the integer errno is set to contain the ! 240: * number of the error. ! 241: */ ! 242: ! 243: extern int errno; ! 244: ! 245: /* ! 246: * default error handling ! 247: */ ! 248: ! 249: private ERRINFO errinfo[] ={ ! 250: /* no error */ ERR_IGNORE, ! 251: /* EPERM */ ERR_IGNORE, ! 252: /* ENOENT */ ERR_IGNORE, ! 253: /* ESRCH */ ERR_IGNORE, ! 254: /* EINTR */ ERR_CATCH, ! 255: /* EIO */ ERR_CATCH, ! 256: /* ENXIO */ ERR_CATCH, ! 257: /* E2BIG */ ERR_CATCH, ! 258: /* ENOEXEC */ ERR_CATCH, ! 259: /* EBADF */ ERR_IGNORE, ! 260: /* ECHILD */ ERR_CATCH, ! 261: /* EAGAIN */ ERR_CATCH, ! 262: /* ENOMEM */ ERR_CATCH, ! 263: /* EACCES */ ERR_CATCH, ! 264: /* EFAULT */ ERR_CATCH, ! 265: /* ENOTBLK */ ERR_CATCH, ! 266: /* EBUSY */ ERR_CATCH, ! 267: /* EEXIST */ ERR_CATCH, ! 268: /* EXDEV */ ERR_CATCH, ! 269: /* ENODEV */ ERR_CATCH, ! 270: /* ENOTDIR */ ERR_CATCH, ! 271: /* EISDIR */ ERR_CATCH, ! 272: /* EINVAL */ ERR_CATCH, ! 273: /* ENFILE */ ERR_CATCH, ! 274: /* EMFILE */ ERR_CATCH, ! 275: /* ENOTTY */ ERR_IGNORE, ! 276: /* ETXTBSY */ ERR_CATCH, ! 277: /* EFBIG */ ERR_CATCH, ! 278: /* ENOSPC */ ERR_CATCH, ! 279: /* ESPIPE */ ERR_CATCH, ! 280: /* EROFS */ ERR_CATCH, ! 281: /* EMLINK */ ERR_CATCH, ! 282: /* EPIPE */ ERR_CATCH, ! 283: /* EDOM */ ERR_CATCH, ! 284: /* ERANGE */ ERR_CATCH, ! 285: /* EQUOT */ ERR_CATCH, ! 286: }; ! 287: ! 288: public syserr() ! 289: { ! 290: ERRINFO *e; ! 291: ! 292: e = &errinfo[errno]; ! 293: if (e->func == ERR_CATCH) { ! 294: if (errno < sys_nerr) { ! 295: panic(sys_errlist[errno]); ! 296: } else { ! 297: panic("errno %d", errno); ! 298: } ! 299: } else if (e->func != ERR_IGNORE) { ! 300: (*e->func)(); ! 301: } ! 302: } ! 303: ! 304: /* ! 305: * Change the action on receipt of an error. ! 306: */ ! 307: ! 308: public INTFUNC *onsyserr(n, f) ! 309: int n; ! 310: INTFUNC *f; ! 311: { ! 312: INTFUNC *g = errinfo[n].func; ! 313: ! 314: errinfo[n].func = f; ! 315: return(g); ! 316: } ! 317: ! 318: /* ! 319: * Main driver of error message reporting. ! 320: */ ! 321: ! 322: /* VARARGS2 */ ! 323: private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m) ! 324: String errname; ! 325: Boolean shouldquit; ! 326: String s; ! 327: { ! 328: fflush(stdout); ! 329: if (shouldquit and cmdname != nil(String)) { ! 330: fprintf(stderr, "%s: ", cmdname); ! 331: } ! 332: if (errfilename != nil(Filename)) { ! 333: fprintf(stderr, "%s: ", errfilename); ! 334: } ! 335: if (errlineno > 0) { ! 336: fprintf(stderr, "%d: ", errlineno); ! 337: } ! 338: if (errname != nil(String)) { ! 339: fprintf(stderr, "%s: ", errname); ! 340: } ! 341: fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m); ! 342: putc('\n', stderr); ! 343: if (shouldquit) { ! 344: quit(1); ! 345: } ! 346: } ! 347: ! 348: /* ! 349: * Errors are a little worse, they mean something is wrong, ! 350: * but not so bad that processing can't continue. ! 351: * ! 352: * The routine "erecover" is called to recover from the error, ! 353: * a default routine is provided that does nothing. ! 354: */ ! 355: ! 356: /* VARARGS1 */ ! 357: public error(s, a, b, c, d, e, f, g, h, i, j, k, l, m) ! 358: String s; ! 359: { ! 360: extern erecover(); ! 361: ! 362: errmsg(nil(String), FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m); ! 363: erecover(); ! 364: } ! 365: ! 366: /* ! 367: * Non-recoverable user error. ! 368: */ ! 369: ! 370: /* VARARGS1 */ ! 371: public fatal(s, a, b, c, d, e, f, g, h, i, j, k, l, m) ! 372: String s; ! 373: { ! 374: errmsg("fatal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m); ! 375: } ! 376: ! 377: /* ! 378: * Panics indicate an internal program error. ! 379: */ ! 380: ! 381: /* VARARGS1 */ ! 382: public panic(s, a, b, c, d, e, f, g, h, i, j, k, l, m) ! 383: String s; ! 384: { ! 385: errmsg("panic", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m); ! 386: } ! 387: ! 388: /* ! 389: * Compare n-byte areas pointed to by s1 and s2 ! 390: * if n is 0 then compare up until one has a null byte. ! 391: */ ! 392: ! 393: public int cmp(s1, s2, n) ! 394: register char *s1, *s2; ! 395: register unsigned int n; ! 396: { ! 397: if (s1 == nil(char *) || s2 == nil(char *)) { ! 398: panic("cmp: nil pointer"); ! 399: } ! 400: if (n == 0) { ! 401: while (*s1 == *s2++) { ! 402: if (*s1++ == '\0') { ! 403: return(0); ! 404: } ! 405: } ! 406: return(*s1 - *(s2-1)); ! 407: } else { ! 408: for (; n != 0; n--) { ! 409: if (*s1++ != *s2++) { ! 410: return(*(s1-1) - *(s2-1)); ! 411: } ! 412: } ! 413: return(0); ! 414: } ! 415: } ! 416: ! 417: /* ! 418: * Move n bytes from src to dest. ! 419: * If n is 0 move until a null is found. ! 420: */ ! 421: ! 422: public mov(src, dest, n) ! 423: register char *src, *dest; ! 424: register int n; ! 425: { ! 426: if (src == nil(char *)) { ! 427: panic("mov: nil source"); ! 428: } ! 429: if (dest == nil(char *)) { ! 430: panic("mov: nil destination"); ! 431: } ! 432: if (n > 0) { ! 433: for (; n != 0; n--) { ! 434: *dest++ = *src++; ! 435: } ! 436: } else { ! 437: while ((*dest++ = *src++) != '\0'); ! 438: } ! 439: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.