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

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

unix.superglobalmegacorp.com

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