Annotation of 43BSD/ucb/pascal/pdx/library.c, revision 1.1.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.