Annotation of 43BSDTahoe/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.2 (Berkeley) 4/7/87";
                      9: #endif not lint
                     10: 
                     11: /*
                     12:  * General purpose routines.
                     13:  */
                     14: 
                     15: #include <stdio.h>
                     16: #include <errno.h>
                     17: #include "defs.h"
                     18: 
                     19: #define public
                     20: #define private static
                     21: #define and &&
                     22: #define nil(type)      ((type) 0)
                     23: 
                     24: typedef char *String;
                     25: typedef FILE *File;
                     26: typedef String Filename;
                     27: typedef char Boolean;
                     28: 
                     29: #undef FILE
                     30: 
                     31: String cmdname;                        /* name of command for error messages */
                     32: Filename errfilename;          /* current file associated with error */
                     33: short errlineno;               /* line number associated with error */
                     34: 
                     35: typedef int INTFUNC();
                     36: 
                     37: typedef struct {
                     38:     INTFUNC *func;
                     39: } ERRINFO;
                     40: 
                     41: #define ERR_IGNORE ((INTFUNC *) 0)
                     42: #define ERR_CATCH  ((INTFUNC *) 1)
                     43: 
                     44: public INTFUNC *onsyserr();
                     45: 
                     46: /*
                     47:  * Call a program.
                     48:  *
                     49:  * Three entries:
                     50:  *
                     51:  *     call, callv - call a program and wait for it, returning status
                     52:  *     backv - call a program and don't wait, returning process id
                     53:  *
                     54:  * The command's standard input and output are passed as FILE's.
                     55:  */
                     56: 
                     57: 
                     58: #define MAXNARGS 100    /* unchecked upper limit on max num of arguments */
                     59: #define BADEXEC 127    /* exec fails */
                     60: 
                     61: #define ischild(pid)    ((pid) == 0)
                     62: 
                     63: /* VARARGS3 */
                     64: public int call(name, in, out, args)
                     65: String name;
                     66: File in;
                     67: File out;
                     68: String args;
                     69: {
                     70:     String *ap, *argp;
                     71:     String argv[MAXNARGS];
                     72: 
                     73:     argp = &argv[0];
                     74:     *argp++ = name;
                     75:     ap = &args;
                     76:     while (*ap != nil(String)) {
                     77:        *argp++ = *ap++;
                     78:     }
                     79:     *argp = nil(String);
                     80:     return callv(name, in, out, argv);
                     81: }
                     82: 
                     83: public int callv(name, in, out, argv)
                     84: String name;
                     85: File in;
                     86: File out;
                     87: String *argv;
                     88: {
                     89:     int pid, status;
                     90: 
                     91:     pid = backv(name, in, out, argv);
                     92:     pwait(pid, &status);
                     93:     return status;
                     94: }
                     95: 
                     96: public int backv(name, in, out, argv)
                     97: String name;
                     98: File in;
                     99: File out;
                    100: String *argv;
                    101: {
                    102:     int pid;
                    103: 
                    104:     fflush(stdout);
                    105:     if (ischild(pid = fork())) {
                    106:        fswap(0, fileno(in));
                    107:        fswap(1, fileno(out));
                    108:        (void) onsyserr(EACCES, ERR_IGNORE);
                    109:        execvp(name, argv);
                    110:        _exit(BADEXEC);
                    111:     }
                    112:     return pid;
                    113: }
                    114: 
                    115: /*
                    116:  * Swap file numbers so as to redirect standard input and output.
                    117:  */
                    118: 
                    119: private fswap(oldfd, newfd)
                    120: int oldfd;
                    121: int newfd;
                    122: {
                    123:     if (oldfd != newfd) {
                    124:        close(oldfd);
                    125:        dup(newfd);
                    126:        close(newfd);
                    127:     }
                    128: }
                    129: 
                    130: /*
                    131:  * Invoke a shell on a command line.
                    132:  */
                    133: 
                    134: #define DEF_SHELL      "csh"
                    135: 
                    136: public shell(s)
                    137: String s;
                    138: {
                    139:     extern String getenv();
                    140:     String sh;
                    141: 
                    142:     if ((sh = getenv("SHELL")) == nil(String)) {
                    143:        sh = DEF_SHELL;
                    144:     }
                    145:     call(sh, stdin, stdout, "-c", s, 0);
                    146: }
                    147: 
                    148: /*
                    149:  * Wait for a process the right way.  We wait for a particular
                    150:  * process and if any others come along in between, we remember them
                    151:  * in case they are eventually waited for.
                    152:  *
                    153:  * This routine is not very efficient when the number of processes
                    154:  * to be remembered is large.
                    155:  */
                    156: 
                    157: typedef struct pidlist {
                    158:     int pid;
                    159:     int status;
                    160:     struct pidlist *next;
                    161: } Pidlist;
                    162: 
                    163: private Pidlist *pidlist, *pfind();
                    164: 
                    165: public pwait(pid, statusp)
                    166: int pid, *statusp;
                    167: {
                    168:        Pidlist *p;
                    169:        int pnum, status;
                    170: 
                    171:        p = pfind(pid);
                    172:        if (p != nil(Pidlist *)) {
                    173:            *statusp = p->status;
                    174:            dispose(p);
                    175:            return;
                    176:        }
                    177:        while ((pnum = wait(&status)) != pid && pnum >= 0) {
                    178:            p = alloc(1, Pidlist);
                    179:            p->pid = pnum;
                    180:            p->status = status;
                    181:            p->next = pidlist;
                    182:            pidlist = p;
                    183:        }
                    184:        if (pnum < 0) {
                    185:            p = pfind(pid);
                    186:            if (p == nil(Pidlist *)) {
                    187:                panic("pwait: pid %d not found", pid);
                    188:            }
                    189:            *statusp = p->status;
                    190:            dispose(p);
                    191:        } else {
                    192:            *statusp = status;
                    193:        }
                    194: #ifdef tahoe
                    195:        chkret(p, status);
                    196: #endif
                    197: }
                    198: 
                    199: /*
                    200:  * Look for the given process id on the pidlist.
                    201:  *
                    202:  * Unlink it from list if found.
                    203:  */
                    204: 
                    205: private Pidlist *pfind(pid)
                    206: int pid;
                    207: {
                    208:     register Pidlist *p, *prev;
                    209: 
                    210:     prev = nil(Pidlist *);
                    211:     for (p = pidlist; p != nil(Pidlist *); p = p->next) {
                    212:        if (p->pid == pid) {
                    213:            break;
                    214:        }
                    215:        prev = p;
                    216:     }
                    217:     if (p != nil(Pidlist *)) {
                    218:        if (prev == nil(Pidlist *)) {
                    219:            pidlist = p->next;
                    220:        } else {
                    221:            prev->next = p->next;
                    222:        }
                    223:     }
                    224:     return p;
                    225: }
                    226: 
                    227: /*
                    228:  * System call error handler.
                    229:  *
                    230:  * The syserr routine is called when a system call is about to
                    231:  * set the c-bit to report an error.  Certain errors are caught
                    232:  * and cause the process to print a message and immediately exit.
                    233:  */
                    234: 
                    235: extern int sys_nerr;
                    236: extern char *sys_errlist[];
                    237:  
                    238: /*
                    239:  * Before calling syserr, the integer errno is set to contain the
                    240:  * number of the error.
                    241:  */
                    242: 
                    243: extern int errno;
                    244: 
                    245: /*
                    246:  * default error handling
                    247:  */
                    248: 
                    249: private ERRINFO errinfo[] ={
                    250: /* no error */ ERR_IGNORE,
                    251: /* EPERM */    ERR_IGNORE,
                    252: /* ENOENT */   ERR_IGNORE,
                    253: /* ESRCH */    ERR_IGNORE,
                    254: /* EINTR */    ERR_CATCH,
                    255: /* EIO */      ERR_CATCH,
                    256: /* ENXIO */    ERR_CATCH,
                    257: /* E2BIG */    ERR_CATCH,
                    258: /* ENOEXEC */  ERR_CATCH,
                    259: /* EBADF */    ERR_IGNORE,
                    260: /* ECHILD */   ERR_CATCH,
                    261: /* EAGAIN */   ERR_CATCH,
                    262: /* ENOMEM */   ERR_CATCH,
                    263: /* EACCES */   ERR_CATCH,
                    264: /* EFAULT */   ERR_CATCH,
                    265: /* ENOTBLK */  ERR_CATCH,
                    266: /* EBUSY */    ERR_CATCH,
                    267: /* EEXIST */   ERR_CATCH,
                    268: /* EXDEV */    ERR_CATCH,
                    269: /* ENODEV */   ERR_CATCH,
                    270: /* ENOTDIR */  ERR_CATCH,
                    271: /* EISDIR */   ERR_CATCH,
                    272: /* EINVAL */   ERR_CATCH,
                    273: /* ENFILE */   ERR_CATCH,
                    274: /* EMFILE */   ERR_CATCH,
                    275: /* ENOTTY */   ERR_IGNORE,
                    276: /* ETXTBSY */  ERR_CATCH,
                    277: /* EFBIG */    ERR_CATCH,
                    278: /* ENOSPC */   ERR_CATCH,
                    279: /* ESPIPE */   ERR_CATCH,
                    280: /* EROFS */    ERR_CATCH,
                    281: /* EMLINK */   ERR_CATCH,
                    282: /* EPIPE */    ERR_CATCH,
                    283: /* EDOM */     ERR_CATCH,
                    284: /* ERANGE */   ERR_CATCH,
                    285: /* EQUOT */    ERR_CATCH,
                    286: };
                    287: 
                    288: public syserr()
                    289: {
                    290:     ERRINFO *e;
                    291: 
                    292:     e = &errinfo[errno];
                    293:     if (e->func == ERR_CATCH) {
                    294:        if (errno < sys_nerr) {
                    295:            panic(sys_errlist[errno]);
                    296:        } else {
                    297:            panic("errno %d", errno);
                    298:        }
                    299:     } else if (e->func != ERR_IGNORE) {
                    300:        (*e->func)();
                    301:     }
                    302: }
                    303: 
                    304: /*
                    305:  * Change the action on receipt of an error.
                    306:  */
                    307: 
                    308: public INTFUNC *onsyserr(n, f)
                    309: int n;
                    310: INTFUNC *f;
                    311: {
                    312:     INTFUNC *g = errinfo[n].func;
                    313: 
                    314:     errinfo[n].func = f;
                    315:     return(g);
                    316: }
                    317: 
                    318: /*
                    319:  * Main driver of error message reporting.
                    320:  */
                    321: 
                    322: /* VARARGS2 */
                    323: private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    324: String errname;
                    325: Boolean shouldquit;
                    326: String s;
                    327: {
                    328:     fflush(stdout);
                    329:     if (shouldquit and cmdname != nil(String)) {
                    330:        fprintf(stderr, "%s: ", cmdname);
                    331:     }
                    332:     if (errfilename != nil(Filename)) {
                    333:        fprintf(stderr, "%s: ", errfilename);
                    334:     }
                    335:     if (errlineno > 0) {
                    336:        fprintf(stderr, "%d: ", errlineno);
                    337:     }
                    338:     if (errname != nil(String)) {
                    339:        fprintf(stderr, "%s: ", errname);
                    340:     }
                    341:     fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    342:     putc('\n', stderr);
                    343:     if (shouldquit) {
                    344:        quit(1);
                    345:     }
                    346: }
                    347: 
                    348: /*
                    349:  * Errors are a little worse, they mean something is wrong,
                    350:  * but not so bad that processing can't continue.
                    351:  *
                    352:  * The routine "erecover" is called to recover from the error,
                    353:  * a default routine is provided that does nothing.
                    354:  */
                    355: 
                    356: /* VARARGS1 */
                    357: public error(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    358: String s;
                    359: {
                    360:     extern erecover();
                    361: 
                    362:     errmsg(nil(String), FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    363:     erecover();
                    364: }
                    365: 
                    366: /*
                    367:  * Non-recoverable user error.
                    368:  */
                    369: 
                    370: /* VARARGS1 */
                    371: public fatal(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    372: String s;
                    373: {
                    374:     errmsg("fatal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    375: }
                    376: 
                    377: /*
                    378:  * Panics indicate an internal program error.
                    379:  */
                    380: 
                    381: /* VARARGS1 */
                    382: public panic(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    383: String s;
                    384: {
                    385:     errmsg("panic", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    386: }
                    387: 
                    388: /*
                    389:  * Compare n-byte areas pointed to by s1 and s2
                    390:  * if n is 0 then compare up until one has a null byte.
                    391:  */
                    392: 
                    393: public int cmp(s1, s2, n)
                    394: register char *s1, *s2;
                    395: register unsigned int n;
                    396: {
                    397:     if (s1 == nil(char *) || s2 == nil(char *)) {
                    398:        panic("cmp: nil pointer");
                    399:     }
                    400:     if (n == 0) {
                    401:        while (*s1 == *s2++) {
                    402:            if (*s1++ == '\0') {
                    403:                return(0);
                    404:            }
                    405:        }
                    406:        return(*s1 - *(s2-1));
                    407:     } else {
                    408:        for (; n != 0; n--) {
                    409:            if (*s1++ != *s2++) {
                    410:                return(*(s1-1) - *(s2-1));
                    411:            }
                    412:        }
                    413:        return(0);
                    414:     }
                    415: }
                    416: 
                    417: /*
                    418:  * Move n bytes from src to dest.
                    419:  * If n is 0 move until a null is found.
                    420:  */
                    421: 
                    422: public mov(src, dest, n)
                    423: register char *src, *dest;
                    424: register int n;
                    425: {
                    426:     if (src == nil(char *)) {
                    427:        panic("mov: nil source");
                    428:     }
                    429:     if (dest == nil(char *)) {
                    430:        panic("mov: nil destination");
                    431:     }
                    432:     if (n > 0) {
                    433:        for (; n != 0; n--) {
                    434:            *dest++ = *src++;
                    435:        }
                    436:     } else {
                    437:        while ((*dest++ = *src++) != '\0');
                    438:     }
                    439: }

unix.superglobalmegacorp.com

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