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

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  */
        !             6: 
        !             7: #ifndef lint
        !             8: static char sccsid[] = "@(#)library.c  5.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.