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