Annotation of 42BSD/ucb/dbx/library.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.