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.1 (Berkeley) 6/7/85";
   9: #endif not lint
  10: 
  11: /*
  12:  * General purpose routines.
  13:  */
  14: 
  15: #include <stdio.h>
  16: #include <errno.h>
  17: 
  18: #define public
  19: #define private static
  20: #define and &&
  21: #define or ||
  22: #define not !
  23: #define ord(enumcon)    ((int) enumcon)
  24: #define nil(type)   ((type) 0)
  25: 
  26: typedef enum { FALSE, TRUE } Boolean;
  27: typedef char *String;
  28: typedef FILE *File;
  29: typedef String Filename;
  30: 
  31: #undef FILE
  32: 
  33: /*
  34:  * Definitions of standard C library routines that aren't in the
  35:  * standard I/O library, but which are generally useful.
  36:  */
  37: 
  38: extern long atol();     /* ascii to long */
  39: extern double atof();       /* ascii to floating point */
  40: extern char *mktemp();      /* make a temporary file name */
  41: 
  42: String cmdname;         /* name of command for error messages */
  43: Filename errfilename;       /* current file associated with error */
  44: short errlineno;        /* line number associated with error */
  45: 
  46: /*
  47:  * Definitions for doing memory allocation.
  48:  */
  49: 
  50: extern char *malloc();
  51: 
  52: #define alloc(n, type)  ((type *) malloc((unsigned) (n) * sizeof(type)))
  53: #define dispose(p)  { free((char *) p); p = 0; }
  54: 
  55: /*
  56:  * Macros for doing freads + fwrites.
  57:  */
  58: 
  59: #define get(fp, var)    fread((char *) &(var), sizeof(var), 1, fp)
  60: #define put(fp, var)    fwrite((char *) &(var), sizeof(var), 1, fp)
  61: 
  62: /*
  63:  * String definitions.
  64:  */
  65: 
  66: extern String strcpy(), index(), rindex();
  67: extern int strlen();
  68: 
  69: #define strdup(s)       strcpy(malloc((unsigned) strlen(s) + 1), s)
  70: #define streq(s1, s2)   (strcmp(s1, s2) == 0)
  71: 
  72: typedef int INTFUNC();
  73: 
  74: typedef struct {
  75:     INTFUNC *func;
  76: } ERRINFO;
  77: 
  78: #define ERR_IGNORE ((INTFUNC *) 0)
  79: #define ERR_CATCH  ((INTFUNC *) 1)
  80: 
  81: /*
  82:  * Call a program.
  83:  *
  84:  * Four entries:
  85:  *
  86:  *	call, callv - call a program and wait for it, returning status
  87:  *	back, backv - call a program and don't wait, returning process id
  88:  *
  89:  * The command's standard input and output are passed as FILE's.
  90:  */
  91: 
  92: 
  93: #define MAXNARGS 100    /* unchecked upper limit on max num of arguments */
  94: #define BADEXEC 127 /* exec fails */
  95: 
  96: #define ischild(pid)    ((pid) == 0)
  97: 
  98: /* VARARGS3 */
  99: public int call(name, in, out, args)
 100: String name;
 101: File in;
 102: File out;
 103: String args;
 104: {
 105:     String *ap, *argp;
 106:     String argv[MAXNARGS];
 107: 
 108:     argp = &argv[0];
 109:     *argp++ = name;
 110:     ap = &args;
 111:     while (*ap != nil(String)) {
 112:     *argp++ = *ap++;
 113:     }
 114:     *argp = nil(String);
 115:     return callv(name, in, out, argv);
 116: }
 117: 
 118: /* VARARGS3 */
 119: public int back(name, in, out, args)
 120: String name;
 121: File in;
 122: File out;
 123: String args;
 124: {
 125:     String *ap, *argp;
 126:     String argv[MAXNARGS];
 127: 
 128:     argp = &argv[0];
 129:     *argp++ = name;
 130:     ap = &args;
 131:     while (*ap != nil(String)) {
 132:     *argp++ = *ap++;
 133:     }
 134:     *argp = nil(String);
 135:     return backv(name, in, out, argv);
 136: }
 137: 
 138: public int callv(name, in, out, argv)
 139: String name;
 140: File in;
 141: File out;
 142: String *argv;
 143: {
 144:     int pid, status;
 145: 
 146:     pid = backv(name, in, out, argv);
 147:     pwait(pid, &status);
 148:     return status;
 149: }
 150: 
 151: public int backv(name, in, out, argv)
 152: String name;
 153: File in;
 154: File out;
 155: String *argv;
 156: {
 157:     int pid;
 158: 
 159:     fflush(stdout);
 160:     if (ischild(pid = fork())) {
 161:     fswap(0, fileno(in));
 162:     fswap(1, fileno(out));
 163:     onsyserr(EACCES, ERR_IGNORE);
 164:     execvp(name, argv);
 165:     _exit(BADEXEC);
 166:     }
 167:     return pid;
 168: }
 169: 
 170: /*
 171:  * Swap file numbers so as to redirect standard input and output.
 172:  */
 173: 
 174: private fswap(oldfd, newfd)
 175: int oldfd;
 176: int newfd;
 177: {
 178:     if (oldfd != newfd) {
 179:     close(oldfd);
 180:     dup(newfd);
 181:     close(newfd);
 182:     }
 183: }
 184: 
 185: /*
 186:  * Invoke a shell on a command line.
 187:  */
 188: 
 189: #define DEF_SHELL   "csh"
 190: 
 191: public shell(s)
 192: String s;
 193: {
 194:     extern String getenv();
 195:     String sh;
 196: 
 197:     if ((sh = getenv("SHELL")) == nil(String)) {
 198:     sh = DEF_SHELL;
 199:     }
 200:     call(sh, stdin, stdout, "-c", s, 0);
 201: }
 202: 
 203: /*
 204:  * Wait for a process the right way.  We wait for a particular
 205:  * process and if any others come along in between, we remember them
 206:  * in case they are eventually waited for.
 207:  *
 208:  * This routine is not very efficient when the number of processes
 209:  * to be remembered is large.
 210:  */
 211: 
 212: typedef struct pidlist {
 213:     int pid;
 214:     int status;
 215:     struct pidlist *next;
 216: } Pidlist;
 217: 
 218: private Pidlist *pidlist, *pfind();
 219: 
 220: public pwait(pid, statusp)
 221: int pid, *statusp;
 222: {
 223:     Pidlist *p;
 224:     int pnum, status;
 225: 
 226:     p = pfind(pid);
 227:     if (p != nil(Pidlist *)) {
 228:         *statusp = p->status;
 229:         dispose(p);
 230:         return;
 231:     }
 232:     while ((pnum = wait(&status)) != pid && pnum >= 0) {
 233:         p = alloc(1, Pidlist);
 234:         p->pid = pnum;
 235:         p->status = status;
 236:         p->next = pidlist;
 237:         pidlist = p;
 238:     }
 239:     if (pnum < 0) {
 240:         p = pfind(pid);
 241:         if (p == nil(Pidlist *)) {
 242:         panic("pwait: pid %d not found", pid);
 243:         }
 244:         *statusp = p->status;
 245:         dispose(p);
 246:     } else {
 247:         *statusp = status;
 248:     }
 249: }
 250: 
 251: /*
 252:  * Look for the given process id on the pidlist.
 253:  *
 254:  * Unlink it from list if found.
 255:  */
 256: 
 257: private Pidlist *pfind(pid)
 258: int pid;
 259: {
 260:     register Pidlist *p, *prev;
 261: 
 262:     prev = nil(Pidlist *);
 263:     for (p = pidlist; p != nil(Pidlist *); p = p->next) {
 264:     if (p->pid == pid) {
 265:         break;
 266:     }
 267:     prev = p;
 268:     }
 269:     if (p != nil(Pidlist *)) {
 270:     if (prev == nil(Pidlist *)) {
 271:         pidlist = p->next;
 272:     } else {
 273:         prev->next = p->next;
 274:     }
 275:     }
 276:     return p;
 277: }
 278: 
 279: /*
 280:  * System call error handler.
 281:  *
 282:  * The syserr routine is called when a system call is about to
 283:  * set the c-bit to report an error.  Certain errors are caught
 284:  * and cause the process to print a message and immediately exit.
 285:  */
 286: 
 287: extern int sys_nerr;
 288: extern char *sys_errlist[];
 289: 
 290: /*
 291:  * Before calling syserr, the integer errno is set to contain the
 292:  * number of the error.  The routine "_mycerror" is a dummy which
 293:  * is used to force the loader to get my version of cerror rather
 294:  * than the usual one.
 295:  */
 296: 
 297: extern int errno;
 298: extern _mycerror();
 299: 
 300: /*
 301:  * default error handling
 302:  */
 303: 
 304: private ERRINFO errinfo[] ={
 305: /* no error */  ERR_IGNORE,
 306: /* EPERM */ ERR_IGNORE,
 307: /* ENOENT */    ERR_IGNORE,
 308: /* ESRCH */ ERR_IGNORE,
 309: /* EINTR */ ERR_CATCH,
 310: /* EIO */   ERR_CATCH,
 311: /* ENXIO */ ERR_CATCH,
 312: /* E2BIG */ ERR_CATCH,
 313: /* ENOEXEC */   ERR_CATCH,
 314: /* EBADF */ ERR_IGNORE,
 315: /* ECHILD */    ERR_CATCH,
 316: /* EAGAIN */    ERR_CATCH,
 317: /* ENOMEM */    ERR_CATCH,
 318: /* EACCES */    ERR_CATCH,
 319: /* EFAULT */    ERR_CATCH,
 320: /* ENOTBLK */   ERR_CATCH,
 321: /* EBUSY */ ERR_CATCH,
 322: /* EEXIST */    ERR_CATCH,
 323: /* EXDEV */ ERR_CATCH,
 324: /* ENODEV */    ERR_CATCH,
 325: /* ENOTDIR */   ERR_CATCH,
 326: /* EISDIR */    ERR_CATCH,
 327: /* EINVAL */    ERR_CATCH,
 328: /* ENFILE */    ERR_CATCH,
 329: /* EMFILE */    ERR_CATCH,
 330: /* ENOTTY */    ERR_IGNORE,
 331: /* ETXTBSY */   ERR_CATCH,
 332: /* EFBIG */ ERR_CATCH,
 333: /* ENOSPC */    ERR_CATCH,
 334: /* ESPIPE */    ERR_CATCH,
 335: /* EROFS */ ERR_CATCH,
 336: /* EMLINK */    ERR_CATCH,
 337: /* EPIPE */ ERR_CATCH,
 338: /* EDOM */  ERR_CATCH,
 339: /* ERANGE */    ERR_CATCH,
 340: /* EQUOT */ ERR_CATCH,
 341: };
 342: 
 343: public syserr()
 344: {
 345:     ERRINFO *e;
 346: 
 347:     e = &errinfo[errno];
 348:     if (e->func == ERR_CATCH) {
 349:     if (errno < sys_nerr) {
 350:         panic(sys_errlist[errno]);
 351:     } else {
 352:         panic("errno %d", errno);
 353:     }
 354:     } else if (e->func != ERR_IGNORE) {
 355:     (*e->func)();
 356:     }
 357: }
 358: 
 359: /*
 360:  * Catcherrs only purpose is to get this module loaded and make
 361:  * sure my cerror is loaded (only applicable when this is in a library).
 362:  */
 363: 
 364: public catcherrs()
 365: {
 366:     _mycerror();
 367: }
 368: 
 369: /*
 370:  * Change the action on receipt of an error.
 371:  */
 372: 
 373: public onsyserr(n, f)
 374: int n;
 375: INTFUNC *f;
 376: {
 377:     errinfo[n].func = f;
 378: }
 379: 
 380: /*
 381:  * Standard error handling routines.
 382:  */
 383: 
 384: private short nerrs;
 385: private short nwarnings;
 386: 
 387: /*
 388:  * Main driver of error message reporting.
 389:  */
 390: 
 391: /* VARARGS2 */
 392: private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m)
 393: String errname;
 394: Boolean shouldquit;
 395: String s;
 396: {
 397:     fflush(stdout);
 398:     if (shouldquit and cmdname != nil(String)) {
 399:     fprintf(stderr, "%s: ", cmdname);
 400:     }
 401:     if (errfilename != nil(Filename)) {
 402:     fprintf(stderr, "%s: ", errfilename);
 403:     }
 404:     if (errlineno > 0) {
 405:     fprintf(stderr, "%d: ", errlineno);
 406:     }
 407:     if (errname != nil(String)) {
 408:     fprintf(stderr, "%s: ", errname);
 409:     }
 410:     fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
 411:     putc('\n', stderr);
 412:     if (shouldquit) {
 413:     quit(1);
 414:     }
 415: }
 416: 
 417: /*
 418:  * The messages are listed in increasing order of seriousness.
 419:  *
 420:  * First are warnings.
 421:  */
 422: 
 423: /* VARARGS1 */
 424: public warning(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
 425: String s;
 426: {
 427:     nwarnings++;
 428:     errmsg("warning", FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
 429: }
 430: 
 431: /*
 432:  * Errors are a little worse, they mean something is wrong,
 433:  * but not so bad that processing can't continue.
 434:  *
 435:  * The routine "erecover" is called to recover from the error,
 436:  * a default routine is provided that does nothing.
 437:  */
 438: 
 439: /* VARARGS1 */
 440: public error(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
 441: String s;
 442: {
 443:     extern erecover();
 444: 
 445:     nerrs++;
 446:     errmsg(nil(String), FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
 447:     erecover();
 448: }
 449: 
 450: /*
 451:  * Non-recoverable user error.
 452:  */
 453: 
 454: /* VARARGS1 */
 455: public fatal(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
 456: String s;
 457: {
 458:     errmsg("fatal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
 459: }
 460: 
 461: /*
 462:  * Panics indicate an internal program error.
 463:  */
 464: 
 465: /* VARARGS1 */
 466: public panic(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
 467: String s;
 468: {
 469:     errmsg("panic", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
 470: }
 471: 
 472: short numerrors()
 473: {
 474:     short r;
 475: 
 476:     r = nerrs;
 477:     nerrs = 0;
 478:     return r;
 479: }
 480: 
 481: short numwarnings()
 482: {
 483:     short r;
 484: 
 485:     r = nwarnings;
 486:     nwarnings = 0;
 487:     return r;
 488: }
 489: 
 490: /*
 491:  * Recover from an error.
 492:  *
 493:  * This is the default routine which we aren't using since we have our own.
 494:  *
 495: public erecover()
 496: {
 497: }
 498:  *
 499:  */
 500: 
 501: /*
 502:  * Default way to quit from a program is just to exit.
 503:  *
 504: public quit(r)
 505: int r;
 506: {
 507:     exit(r);
 508: }
 509:  *
 510:  */
 511: 
 512: /*
 513:  * Compare n-byte areas pointed to by s1 and s2
 514:  * if n is 0 then compare up until one has a null byte.
 515:  */
 516: 
 517: public int cmp(s1, s2, n)
 518: register char *s1, *s2;
 519: register unsigned int n;
 520: {
 521:     if (s1 == nil(char *) || s2 == nil(char *)) {
 522:     panic("cmp: nil pointer");
 523:     }
 524:     if (n == 0) {
 525:     while (*s1 == *s2++) {
 526:         if (*s1++ == '\0') {
 527:         return(0);
 528:         }
 529:     }
 530:     return(*s1 - *(s2-1));
 531:     } else {
 532:     for (; n != 0; n--) {
 533:         if (*s1++ != *s2++) {
 534:         return(*(s1-1) - *(s2-1));
 535:         }
 536:     }
 537:     return(0);
 538:     }
 539: }
 540: 
 541: /*
 542:  * Move n bytes from src to dest.
 543:  * If n is 0 move until a null is found.
 544:  */
 545: 
 546: public mov(src, dest, n)
 547: register char *src, *dest;
 548: register unsigned int n;
 549: {
 550:     if (src == nil(char *))
 551:     panic("mov: nil source");
 552:     if (dest == nil(char *))
 553:     panic("mov: nil destination");
 554:     if (n > 0) {
 555:     for (; n != 0; n--) {
 556:         *dest++ = *src++;
 557:     }
 558:     } else {
 559:     while ((*dest++ = *src++) != '\0');
 560:     }
 561: }

Defined functions

back defined in line 119; never used
backv defined in line 151; used 2 times
call defined in line 99; used 1 times
callv defined in line 138; used 1 times
catcherrs defined in line 364; never used
cmp defined in line 517; never used
errmsg defined in line 392; used 4 times
error defined in line 440; used 1 times
fatal defined in line 455; never used
fswap defined in line 174; used 2 times
mov defined in line 546; never used
numerrors defined in line 472; used 1 times
numwarnings defined in line 481; never used
onsyserr defined in line 373; used 1 times
panic defined in line 466; used 7 times
pfind defined in line 257; used 3 times
pwait defined in line 220; used 1 times
shell defined in line 191; never used
syserr defined in line 343; used 1 times
warning defined in line 424; never used

Defined variables

cmdname defined in line 42; used 2 times
errfilename defined in line 43; used 2 times
errlineno defined in line 44; used 2 times
nerrs defined in line 384; used 3 times
nwarnings defined in line 385; used 3 times
pidlist defined in line 218; used 4 times
public defined in line 517; never used
sccsid defined in line 8; never used

Defined struct's

pidlist defined in line 212; used 2 times
  • in line 215(2)

Defined typedef's

Filename defined in line 29; used 2 times
Pidlist defined in line 216; used 11 times
String defined in line 27; used 32 times

Defined macros

BADEXEC defined in line 94; used 1 times
DEF_SHELL defined in line 189; used 1 times
ERR_CATCH defined in line 79; used 31 times
ERR_IGNORE defined in line 78; used 8 times
MAXNARGS defined in line 93; used 2 times
alloc defined in line 52; used 1 times
and defined in line 20; used 1 times
dispose defined in line 53; used 2 times
get defined in line 59; never used
ischild defined in line 96; used 1 times
nil defined in line 24; used 19 times
not defined in line 22; never used
or defined in line 21; never used
ord defined in line 23; never used
private defined in line 19; used 7 times
public defined in line 18; used 14 times
put defined in line 60; never used
strdup defined in line 69; never used
streq defined in line 70; never used
Last modified: 1985-06-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4738
Valid CSS Valid XHTML 1.0 Strict