Annotation of 43BSDReno/pgrm/dbx/library.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted
                      6:  * provided that: (1) source distributions retain this entire copyright
                      7:  * notice and comment, and (2) distributions including binaries display
                      8:  * the following acknowledgement:  ``This product includes software
                      9:  * developed by the University of California, Berkeley and its contributors''
                     10:  * in the documentation or other materials provided with the distribution
                     11:  * and in all advertising materials mentioning features or use of this
                     12:  * software. Neither the name of the University nor the names of its
                     13:  * contributors may be used to endorse or promote products derived
                     14:  * from this software without specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
                     16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: static char sccsid[] = "@(#)library.c  5.4 (Berkeley) 6/1/90";
                     22: #endif /* not lint */
                     23: 
                     24: /*
                     25:  * General purpose routines.
                     26:  */
                     27: 
                     28: #include <stdio.h>
                     29: #include <errno.h>
                     30: #include <signal.h>
                     31: 
                     32: #define public
                     33: #define private static
                     34: #define and &&
                     35: #define or ||
                     36: #define not !
                     37: #define ord(enumcon)   ((int) enumcon)
                     38: #define nil(type)      ((type) 0)
                     39: 
                     40: typedef int integer;
                     41: typedef enum { FALSE, TRUE } boolean;
                     42: typedef char *String;
                     43: typedef FILE *File;
                     44: typedef String Filename;
                     45: 
                     46: #undef FILE
                     47: 
                     48: String cmdname;                        /* name of command for error messages */
                     49: Filename errfilename;          /* current file associated with error */
                     50: short errlineno;               /* line number associated with error */
                     51: 
                     52: /*
                     53:  * Definitions for doing memory allocation.
                     54:  */
                     55: 
                     56: extern char *malloc();
                     57: 
                     58: #define alloc(n, type) ((type *) malloc((unsigned) (n) * sizeof(type)))
                     59: #define dispose(p)     { free((char *) p); p = 0; }
                     60: 
                     61: /*
                     62:  * Macros for doing freads + fwrites.
                     63:  */
                     64: 
                     65: #define get(fp, var)   fread((char *) &(var), sizeof(var), 1, fp)
                     66: #define put(fp, var)   fwrite((char *) &(var), sizeof(var), 1, fp)
                     67: 
                     68: /*
                     69:  * String definitions.
                     70:  */
                     71: 
                     72: extern String strcpy(), index(), rindex();
                     73: extern int strlen();
                     74: 
                     75: #define strdup(s)              strcpy(malloc((unsigned) strlen(s) + 1), s)
                     76: #define streq(s1, s2)  (strcmp(s1, s2) == 0)
                     77: 
                     78: typedef int IntFunc();
                     79: 
                     80: IntFunc *onsyserr();
                     81: 
                     82: typedef struct {
                     83:     IntFunc *func;
                     84: } ErrInfo;
                     85: 
                     86: #define ERR_IGNORE ((IntFunc *) 0)
                     87: #define ERR_CATCH  ((IntFunc *) 1)
                     88: 
                     89: /*
                     90:  * Call a program.
                     91:  *
                     92:  * Four entries:
                     93:  *
                     94:  *     call, callv - call a program and wait for it, returning status
                     95:  *     back, backv - call a program and don't wait, returning process id
                     96:  *
                     97:  * The command's standard input and output are passed as FILE's.
                     98:  */
                     99: 
                    100: 
                    101: #define MAXNARGS 1000    /* unchecked upper limit on max num of arguments */
                    102: #define BADEXEC 127    /* exec fails */
                    103: 
                    104: #define ischild(pid)    ((pid) == 0)
                    105: 
                    106: /* VARARGS3 */
                    107: public int call(name, in, out, args)
                    108: String name;
                    109: File in;
                    110: File out;
                    111: String args;
                    112: {
                    113:     String *ap, *argp;
                    114:     String argv[MAXNARGS];
                    115: 
                    116:     argp = &argv[0];
                    117:     *argp++ = name;
                    118:     ap = &args;
                    119:     while (*ap != nil(String)) {
                    120:        *argp++ = *ap++;
                    121:     }
                    122:     *argp = nil(String);
                    123:     return callv(name, in, out, argv);
                    124: }
                    125: 
                    126: /* VARARGS3 */
                    127: public int back(name, in, out, args)
                    128: String name;
                    129: File in;
                    130: File out;
                    131: String args;
                    132: {
                    133:     String *ap, *argp;
                    134:     String argv[MAXNARGS];
                    135: 
                    136:     argp = &argv[0];
                    137:     *argp++ = name;
                    138:     ap = &args;
                    139:     while (*ap != nil(String)) {
                    140:        *argp++ = *ap++;
                    141:     }
                    142:     *argp = nil(String);
                    143:     return backv(name, in, out, argv);
                    144: }
                    145: 
                    146: public int callv(name, in, out, argv)
                    147: String name;
                    148: File in;
                    149: File out;
                    150: String *argv;
                    151: {
                    152:     int pid, status;
                    153: 
                    154:     pid = backv(name, in, out, argv);
                    155:     pwait(pid, &status);
                    156:     return status;
                    157: }
                    158: 
                    159: public int backv(name, in, out, argv)
                    160: String name;
                    161: File in;
                    162: File out;
                    163: String *argv;
                    164: {
                    165:     int pid;
                    166: 
                    167:     fflush(stdout);
                    168:     if (ischild(pid = fork())) {
                    169:        fswap(0, fileno(in));
                    170:        fswap(1, fileno(out));
                    171:        onsyserr(EACCES, ERR_IGNORE);
                    172:        execvp(name, argv);
                    173:        _exit(BADEXEC);
                    174:     }
                    175:     return pid;
                    176: }
                    177: 
                    178: /*
                    179:  * Swap file numbers so as to redirect standard input and output.
                    180:  */
                    181: 
                    182: private fswap(oldfd, newfd)
                    183: int oldfd;
                    184: int newfd;
                    185: {
                    186:     if (oldfd != newfd) {
                    187:        close(oldfd);
                    188:        dup(newfd);
                    189:        close(newfd);
                    190:     }
                    191: }
                    192: 
                    193: /*
                    194:  * Invoke a shell on a command line.
                    195:  */
                    196: 
                    197: #define DEF_SHELL      "csh"
                    198: 
                    199: public shell(s)
                    200: String s;
                    201: {
                    202:     extern String getenv();
                    203:     String sh;
                    204: 
                    205:     if ((sh = getenv("SHELL")) == nil(String)) {
                    206:        sh = DEF_SHELL;
                    207:     }
                    208:     if (s != nil(String) and *s != '\0') {
                    209:        call(sh, stdin, stdout, "-c", s, 0);
                    210:     } else {
                    211:        call(sh, stdin, stdout, 0);
                    212:     }
                    213: }
                    214: 
                    215: /*
                    216:  * Wait for a process the right way.  We wait for a particular
                    217:  * process and if any others come along in between, we remember them
                    218:  * in case they are eventually waited for.
                    219:  *
                    220:  * This routine is not very efficient when the number of processes
                    221:  * to be remembered is large.
                    222:  *
                    223:  * To deal with a kernel idiosyncrasy, we keep a list on the side
                    224:  * of "traced" processes, and do not notice them when waiting for
                    225:  * another process.
                    226:  */
                    227: 
                    228: typedef struct pidlist {
                    229:     int pid;
                    230:     int status;
                    231:     struct pidlist *next;
                    232: } Pidlist;
                    233: 
                    234: private Pidlist *pidlist, *ptrclist, *pfind();
                    235: 
                    236: public ptraced(pid)
                    237: int pid;
                    238: {
                    239:     Pidlist *p;
                    240: 
                    241:     p = alloc(1, Pidlist);
                    242:     p->pid = pid;
                    243:     p->next = ptrclist;
                    244:     ptrclist = p;
                    245: }
                    246: 
                    247: public unptraced(pid)
                    248: int pid;
                    249: {
                    250:     register Pidlist *p, *prev;
                    251: 
                    252:     prev = nil(Pidlist *);
                    253:     p = ptrclist;
                    254:     while (p != nil(Pidlist *) and p->pid != pid) {
                    255:        prev = p;
                    256:        p = p->next;
                    257:     }
                    258:     if (p != nil(Pidlist *)) {
                    259:        if (prev == nil(Pidlist *)) {
                    260:            ptrclist = p->next;
                    261:        } else {
                    262:            prev->next = p->next;
                    263:        }
                    264:        dispose(p);
                    265:     }
                    266: }
                    267: 
                    268: private boolean isptraced(pid)
                    269: int pid;
                    270: {
                    271:     register Pidlist *p;
                    272: 
                    273:     p = ptrclist;
                    274:     while (p != nil(Pidlist *) and p->pid != pid) {
                    275:        p = p->next;
                    276:     }
                    277:     return (boolean) (p != nil(Pidlist *));
                    278: }
                    279: 
                    280: public pwait(pid, statusp)
                    281: int pid, *statusp;
                    282: {
                    283:     Pidlist *p;
                    284:     int pnum, status;
                    285: 
                    286:     p = pfind(pid);
                    287:     if (p != nil(Pidlist *)) {
                    288:        *statusp = p->status;
                    289:        dispose(p);
                    290:     } else {
                    291:        pnum = wait(&status);
                    292:        while (pnum != pid and pnum >= 0) {
                    293:            if (not isptraced(pnum)) {
                    294:                p = alloc(1, Pidlist);
                    295:                p->pid = pnum;
                    296:                p->status = status;
                    297:                p->next = pidlist;
                    298:                pidlist = p;
                    299:            }
                    300:            pnum = wait(&status);
                    301:        }
                    302:        if (pnum < 0) {
                    303:            p = pfind(pid);
                    304:            if (p == nil(Pidlist *)) {
                    305:                panic("pwait: pid %d not found", pid);
                    306:            }
                    307:            *statusp = p->status;
                    308:            dispose(p);
                    309:        } else {
                    310:            *statusp = status;
                    311:        }
                    312:     }
                    313: }
                    314: 
                    315: /*
                    316:  * Look for the given process id on the pidlist.
                    317:  *
                    318:  * Unlink it from list if found.
                    319:  */
                    320: 
                    321: private Pidlist *pfind(pid)
                    322: int pid;
                    323: {
                    324:     register Pidlist *p, *prev;
                    325: 
                    326:     prev = nil(Pidlist *);
                    327:     for (p = pidlist; p != nil(Pidlist *); p = p->next) {
                    328:        if (p->pid == pid) {
                    329:            break;
                    330:        }
                    331:        prev = p;
                    332:     }
                    333:     if (p != nil(Pidlist *)) {
                    334:        if (prev == nil(Pidlist *)) {
                    335:            pidlist = p->next;
                    336:        } else {
                    337:            prev->next = p->next;
                    338:        }
                    339:     }
                    340:     return p;
                    341: }
                    342: 
                    343: /*
                    344:  * System call error handler.
                    345:  *
                    346:  * The syserr routine is called when a system call is about to
                    347:  * set the c-bit to report an error.  Certain errors are caught
                    348:  * and cause the process to print a message and immediately exit.
                    349:  */
                    350: 
                    351: extern int sys_nerr;
                    352: extern char *sys_errlist[];
                    353:  
                    354: /*
                    355:  * Before calling syserr, the integer errno is set to contain the
                    356:  * number of the error.  The routine "_mycerror" is a dummy which
                    357:  * is used to force the loader to get my version of cerror rather
                    358:  * than the usual one.
                    359:  */
                    360: 
                    361: extern int errno;
                    362: extern _mycerror();
                    363: 
                    364: /*
                    365:  * Initialize error information, setting defaults for handling errors.
                    366:  */
                    367: 
                    368: private ErrInfo *errinfo;
                    369: 
                    370: private initErrInfo ()
                    371: {
                    372:     integer i;
                    373: 
                    374:     errinfo = alloc(sys_nerr, ErrInfo);
                    375:     for (i = 0; i < sys_nerr; i++) {
                    376:        errinfo[i].func = ERR_CATCH;
                    377:     }
                    378:     errinfo[0].func = ERR_IGNORE;
                    379:     errinfo[EPERM].func = ERR_IGNORE;
                    380:     errinfo[ENOENT].func = ERR_IGNORE;
                    381:     errinfo[ESRCH].func = ERR_IGNORE;
                    382:     errinfo[EBADF].func = ERR_IGNORE;
                    383:     errinfo[ENOTTY].func = ERR_IGNORE;
                    384:     errinfo[EOPNOTSUPP].func = ERR_IGNORE;
                    385: }
                    386: 
                    387: public syserr()
                    388: {
                    389:     register ErrInfo *e;
                    390: 
                    391:     if (errno < 0 or errno > sys_nerr) {
                    392:        fatal("errno %d", errno);
                    393:     } else {
                    394:        if (errinfo == nil(ErrInfo *)) {
                    395:            initErrInfo();
                    396:        }
                    397:        e = &(errinfo[errno]);
                    398:        if (e->func == ERR_CATCH) {
                    399:            fatal(sys_errlist[errno]);
                    400:        } else if (e->func != ERR_IGNORE) {
                    401:            (*e->func)();
                    402:        }
                    403:     }
                    404: }
                    405: 
                    406: /*
                    407:  * Catcherrs' purpose is to initialize the errinfo table, get this module
                    408:  * loaded, and make sure my cerror is loaded (only applicable when this is
                    409:  * in a library).
                    410:  */
                    411: 
                    412: public catcherrs()
                    413: {
                    414:     _mycerror();
                    415:     initErrInfo();
                    416: }
                    417: 
                    418: /*
                    419:  * Turn off the error catching mechanism completely by having all errors
                    420:  * ignored.  This is most useful between a fork and an exec.
                    421:  */
                    422: 
                    423: public nocatcherrs()
                    424: {
                    425:     integer i;
                    426: 
                    427:     for (i = 0; i < sys_nerr; i++) {
                    428:        errinfo[i].func = ERR_IGNORE;
                    429:     }
                    430: }
                    431: 
                    432: /*
                    433:  * Change the action on receipt of an error, returning the previous action.
                    434:  */
                    435: 
                    436: public IntFunc *onsyserr(n, f)
                    437: int n;
                    438: IntFunc *f;
                    439: {
                    440:     IntFunc *oldf;
                    441: 
                    442:     if (errinfo == nil(ErrInfo *)) {
                    443:        initErrInfo();
                    444:     }
                    445:     oldf = errinfo[n].func;
                    446:     errinfo[n].func = f;
                    447:     return oldf;
                    448: }
                    449: 
                    450: /*
                    451:  * Print the message associated with the given signal.
                    452:  * Like a "perror" for signals.
                    453:  */
                    454: 
                    455: #ifdef SIGWINCH
                    456: public int sys_nsig = NSIG;
                    457: #else not 4.3 BSD
                    458: /*
                    459:  * This table is correct for 4.2-like systems but will
                    460:  * be inadequate for System V (which is the sort of
                    461:  * Unix that needs it!).
                    462:  */
                    463: public String sys_siglist[] = {
                    464:     "no signal",
                    465:     "hangup",
                    466:     "interrupt",
                    467:     "quit",
                    468:     "illegal instruction",
                    469:     "trace trap",
                    470:     "IOT instruction",
                    471:     "EMT instruction",
                    472:     "floating point exception",
                    473:     "kill",
                    474:     "bus error",
                    475:     "segmentation violation",
                    476:     "bad argument to system call",
                    477:     "broken pipe",
                    478:     "alarm clock",
                    479:     "soft kill",
                    480:     "urgent I/O condition",
                    481:     "stop signal not from tty",
                    482:     "stop signal from tty",
                    483:     "continue",
                    484:     "child termination",
                    485:     "stop (tty input)",
                    486:     "stop (tty output)",
                    487:     "possible input/output",
                    488:     "exceeded CPU time limit",
                    489:     "exceeded file size limit"
                    490: };
                    491: public int sys_nsig = sizeof sys_siglist / sizeof sys_siglist[0];
                    492: #endif
                    493: 
                    494: public psignal(s, n)
                    495: String s;
                    496: integer n;
                    497: {
                    498:     String msg;
                    499:     integer len;
                    500:     extern String sys_siglist[];
                    501: 
                    502:     if (n >= 0 and n < sys_nsig) {
                    503:        msg = sys_siglist[n];
                    504:     } else {
                    505:        msg = "Unknown signal";
                    506:     }
                    507:     len = strlen(s);
                    508:     if (len > 0) {
                    509:        write(2, s, len);
                    510:        write(2, ": ", 2);
                    511:     }
                    512:     write(2, msg, strlen(msg));
                    513:     write(2, "\n", 1);
                    514: }
                    515: 
                    516: /*
                    517:  * Standard error handling routines.
                    518:  */
                    519: 
                    520: private short nerrs;
                    521: private short nwarnings;
                    522: 
                    523: /*
                    524:  * Main driver of error message reporting.
                    525:  */
                    526: 
                    527: /* VARARGS2 */
                    528: private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    529: String errname;
                    530: boolean shouldquit;
                    531: String s;
                    532: {
                    533:     fflush(stdout);
                    534:     if (shouldquit and cmdname != nil(String)) {
                    535:        fprintf(stderr, "%s: ", cmdname);
                    536:     }
                    537:     if (errfilename != nil(Filename)) {
                    538:        fprintf(stderr, "%s: ", errfilename);
                    539:     }
                    540:     if (errlineno > 0) {
                    541:        fprintf(stderr, "%d: ", errlineno);
                    542:     }
                    543:     if (errname != nil(String)) {
                    544:        fprintf(stderr, "%s: ", errname);
                    545:     }
                    546:     fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    547:     putc('\n', stderr);
                    548:     fflush(stderr);
                    549:     if (shouldquit) {
                    550:        quit(1);
                    551:     }
                    552: }
                    553: 
                    554: /*
                    555:  * For when printf isn't sufficient for printing the error message ...
                    556:  */
                    557: 
                    558: public beginerrmsg()
                    559: {
                    560:     fflush(stdout);
                    561:     if (errfilename != nil(String)) {
                    562:        fprintf(stderr, "%s: ", errfilename);
                    563:     }
                    564:     if (errlineno > 0) {
                    565:        fprintf(stderr, "%d: ", errlineno);
                    566:     }
                    567: }
                    568: 
                    569: public enderrmsg()
                    570: {
                    571:     putc('\n', stderr);
                    572:     fflush(stderr);
                    573:     erecover();
                    574: }
                    575: 
                    576: /*
                    577:  * The messages are listed in increasing order of seriousness.
                    578:  *
                    579:  * First are warnings.
                    580:  */
                    581: 
                    582: /* VARARGS1 */
                    583: public warning(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    584: String s;
                    585: {
                    586:     nwarnings++;
                    587:     errmsg("warning", FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    588: }
                    589: 
                    590: /*
                    591:  * Errors are a little worse, they mean something is wrong,
                    592:  * but not so bad that processing can't continue.
                    593:  *
                    594:  * The routine "erecover" is called to recover from the error,
                    595:  * a default routine is provided that does nothing.
                    596:  */
                    597: 
                    598: /* VARARGS1 */
                    599: public error(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    600: String s;
                    601: {
                    602:     extern erecover();
                    603: 
                    604:     nerrs++;
                    605:     errmsg(nil(String), FALSE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    606:     erecover();
                    607: }
                    608: 
                    609: /*
                    610:  * Non-recoverable user error.
                    611:  */
                    612: 
                    613: /* VARARGS1 */
                    614: public fatal(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    615: String s;
                    616: {
                    617:     errmsg("fatal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    618: }
                    619: 
                    620: /*
                    621:  * Panics indicate an internal program error.
                    622:  */
                    623: 
                    624: /* VARARGS1 */
                    625: public panic(s, a, b, c, d, e, f, g, h, i, j, k, l, m)
                    626: String s;
                    627: {
                    628:     errmsg("internal error", TRUE, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
                    629: }
                    630: 
                    631: short numerrors()
                    632: {
                    633:     short r;
                    634: 
                    635:     r = nerrs;
                    636:     nerrs = 0;
                    637:     return r;
                    638: }
                    639: 
                    640: short numwarnings()
                    641: {
                    642:     short r;
                    643: 
                    644:     r = nwarnings;
                    645:     nwarnings = 0;
                    646:     return r;
                    647: }
                    648: 
                    649: /*
                    650:  * Recover from an error.
                    651:  *
                    652:  * This is the default routine which we aren't using since we have our own.
                    653:  *
                    654: public erecover()
                    655: {
                    656: }
                    657:  *
                    658:  */
                    659: 
                    660: /*
                    661:  * Default way to quit from a program is just to exit.
                    662:  *
                    663: public quit(r)
                    664: int r;
                    665: {
                    666:     exit(r);
                    667: }
                    668:  *
                    669:  */
                    670: 
                    671: /*
                    672:  * Compare n-byte areas pointed to by s1 and s2
                    673:  * if n is 0 then compare up until one has a null byte.
                    674:  */
                    675: 
                    676: public int cmp(s1, s2, n)
                    677: register char *s1, *s2;
                    678: register unsigned int n;
                    679: {
                    680:     if (s1 == nil(char *) || s2 == nil(char *)) {
                    681:        panic("cmp: nil pointer");
                    682:     }
                    683:     if (n == 0) {
                    684:        while (*s1 == *s2++) {
                    685:            if (*s1++ == '\0') {
                    686:                return(0);
                    687:            }
                    688:        }
                    689:        return(*s1 - *(s2-1));
                    690:     } else {
                    691:        for (; n != 0; n--) {
                    692:            if (*s1++ != *s2++) {
                    693:                return(*(s1-1) - *(s2-1));
                    694:            }
                    695:        }
                    696:        return(0);
                    697:     }
                    698: }
                    699: 
                    700: /*
                    701:  * Move n bytes from src to dest.
                    702:  * If n is 0 move until a null is found.
                    703:  */
                    704: 
                    705: public mov(src, dest, n)
                    706: register char *src, *dest;
                    707: register unsigned int n;
                    708: {
                    709:     if (src == nil(char *))
                    710:        panic("mov: nil source");
                    711:     if (dest == nil(char *))
                    712:        panic("mov: nil destination");
                    713:     if (n != 0) {
                    714:        for (; n != 0; n--) {
                    715:            *dest++ = *src++;
                    716:        }
                    717:     } else {
                    718:        while ((*dest++ = *src++) != '\0');
                    719:     }
                    720: }
                    721: 
                    722: #ifdef IRIS /* or in general for 4.2 - System V C library interface */
                    723: 
                    724: public bcopy (fromaddr, toaddr, n)
                    725: char *fromaddr, *toaddr;
                    726: int n;
                    727: {
                    728:     blt(toaddr, fromaddr, n);
                    729: }
                    730: 
                    731: public bzero (addr, n)
                    732: char *addr;
                    733: int n;
                    734: {
                    735:     register char *p, *q;
                    736: 
                    737:     p = addr;
                    738:     q = p + n;
                    739:     while (p < q) {
                    740:        *p++ = '\0';
                    741:     }
                    742: }
                    743: 
                    744: #include <string.h>
                    745: 
                    746: public char *index (s, c)
                    747: char *s, c;
                    748: {
                    749:     return strchr(s, c);
                    750: }
                    751: 
                    752: public char *rindex (s, c)
                    753: char *s, c;
                    754: {
                    755:     return strrchr(s, c);
                    756: }
                    757: 
                    758: #endif

unix.superglobalmegacorp.com

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