Annotation of 43BSD/ucb/pascal/pdx/library.c, revision 1.1

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

unix.superglobalmegacorp.com

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