BSD 4_3_Tahoe release
[unix-history] / usr / src / ucb / dbx / library.c
index b4c75b3..c123e6e 100644 (file)
@@ -1,6 +1,14 @@
-/* Copyright (c) 1982 Regents of the University of California */
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)library.c  5.2 (Berkeley) 1/12/88";
+#endif not lint
 
 
-static char sccsid[] = "%Z%%M% %I% %G%";
+static char rcsid[] = "$Header: library.c,v 1.2 87/03/25 20:50:14 donn Exp $";
 
 /*
  * General purpose routines.
 
 /*
  * General purpose routines.
@@ -18,22 +26,14 @@ static char sccsid[] = "%Z%%M% %I% %G%";
 #define ord(enumcon)   ((int) enumcon)
 #define nil(type)      ((type) 0)
 
 #define ord(enumcon)   ((int) enumcon)
 #define nil(type)      ((type) 0)
 
-typedef enum { FALSE, TRUE } Boolean;
+typedef int integer;
+typedef enum { FALSE, TRUE } boolean;
 typedef char *String;
 typedef FILE *File;
 typedef String Filename;
 
 #undef FILE
 
 typedef char *String;
 typedef FILE *File;
 typedef String Filename;
 
 #undef FILE
 
-/*
- * Definitions of standard C library routines that aren't in the
- * standard I/O library, but which are generally useful.
- */
-
-extern long atol();            /* ascii to long */
-extern double atof();          /* ascii to floating point */
-extern char *mktemp();         /* make a temporary file name */
-
 String cmdname;                        /* name of command for error messages */
 Filename errfilename;          /* current file associated with error */
 short errlineno;               /* line number associated with error */
 String cmdname;                        /* name of command for error messages */
 Filename errfilename;          /* current file associated with error */
 short errlineno;               /* line number associated with error */
@@ -64,14 +64,16 @@ extern int strlen();
 #define strdup(s)              strcpy(malloc((unsigned) strlen(s) + 1), s)
 #define streq(s1, s2)  (strcmp(s1, s2) == 0)
 
 #define strdup(s)              strcpy(malloc((unsigned) strlen(s) + 1), s)
 #define streq(s1, s2)  (strcmp(s1, s2) == 0)
 
-typedef int INTFUNC();
+typedef int IntFunc();
+
+IntFunc *onsyserr();
 
 typedef struct {
 
 typedef struct {
-    INTFUNC *func;
-} ERRINFO;
+    IntFunc *func;
+} ErrInfo;
 
 
-#define ERR_IGNORE ((INTFUNC *) 0)
-#define ERR_CATCH  ((INTFUNC *) 1)
+#define ERR_IGNORE ((IntFunc *) 0)
+#define ERR_CATCH  ((IntFunc *) 1)
 
 /*
  * Call a program.
 
 /*
  * Call a program.
@@ -85,7 +87,7 @@ typedef struct {
  */
 
 
  */
 
 
-#define MAXNARGS 100    /* unchecked upper limit on max num of arguments */
+#define MAXNARGS 1000    /* unchecked upper limit on max num of arguments */
 #define BADEXEC 127    /* exec fails */
 
 #define ischild(pid)    ((pid) == 0)
 #define BADEXEC 127    /* exec fails */
 
 #define ischild(pid)    ((pid) == 0)
@@ -206,6 +208,10 @@ String s;
  *
  * This routine is not very efficient when the number of processes
  * to be remembered is large.
  *
  * This routine is not very efficient when the number of processes
  * to be remembered is large.
+ *
+ * To deal with a kernel idiosyncrasy, we keep a list on the side
+ * of "traced" processes, and do not notice them when waiting for
+ * another process.
  */
 
 typedef struct pidlist {
  */
 
 typedef struct pidlist {
@@ -214,26 +220,73 @@ typedef struct pidlist {
     struct pidlist *next;
 } Pidlist;
 
     struct pidlist *next;
 } Pidlist;
 
-private Pidlist *pidlist, *pfind();
+private Pidlist *pidlist, *ptrclist, *pfind();
+
+public ptraced(pid)
+int pid;
+{
+    Pidlist *p;
+
+    p = alloc(1, Pidlist);
+    p->pid = pid;
+    p->next = ptrclist;
+    ptrclist = p;
+}
+
+public unptraced(pid)
+int pid;
+{
+    register Pidlist *p, *prev;
+
+    prev = nil(Pidlist *);
+    p = ptrclist;
+    while (p != nil(Pidlist *) and p->pid != pid) {
+       prev = p;
+       p = p->next;
+    }
+    if (p != nil(Pidlist *)) {
+       if (prev == nil(Pidlist *)) {
+           ptrclist = p->next;
+       } else {
+           prev->next = p->next;
+       }
+       dispose(p);
+    }
+}
+
+private boolean isptraced(pid)
+int pid;
+{
+    register Pidlist *p;
+
+    p = ptrclist;
+    while (p != nil(Pidlist *) and p->pid != pid) {
+       p = p->next;
+    }
+    return (boolean) (p != nil(Pidlist *));
+}
 
 public pwait(pid, statusp)
 int pid, *statusp;
 {
 
 public pwait(pid, statusp)
 int pid, *statusp;
 {
-       Pidlist *p;
-       int pnum, status;
+    Pidlist *p;
+    int pnum, status;
 
 
-       p = pfind(pid);
-       if (p != nil(Pidlist *)) {
-           *statusp = p->status;
-           dispose(p);
-           return;
-       }
-       while ((pnum = wait(&status)) != pid && pnum >= 0) {
-           p = alloc(1, Pidlist);
-           p->pid = pnum;
-           p->status = status;
-           p->next = pidlist;
-           pidlist = p;
+    p = pfind(pid);
+    if (p != nil(Pidlist *)) {
+       *statusp = p->status;
+       dispose(p);
+    } else {
+       pnum = wait(&status);
+       while (pnum != pid and pnum >= 0) {
+           if (not isptraced(pnum)) {
+               p = alloc(1, Pidlist);
+               p->pid = pnum;
+               p->status = status;
+               p->next = pidlist;
+               pidlist = p;
+           }
+           pnum = wait(&status);
        }
        if (pnum < 0) {
            p = pfind(pid);
        }
        if (pnum < 0) {
            p = pfind(pid);
@@ -243,8 +296,9 @@ int pid, *statusp;
            *statusp = p->status;
            dispose(p);
        } else {
            *statusp = p->status;
            dispose(p);
        } else {
-               *statusp = status;
+           *statusp = status;
        }
        }
+    }
 }
 
 /*
 }
 
 /*
@@ -297,83 +351,89 @@ extern int errno;
 extern _mycerror();
 
 /*
 extern _mycerror();
 
 /*
- * Default error handling.
+ * Initialize error information, setting defaults for handling errors.
  */
 
  */
 
-private ERRINFO errinfo[] ={
-/* no error */ ERR_IGNORE,
-/* EPERM */    ERR_IGNORE,
-/* ENOENT */   ERR_IGNORE,
-/* ESRCH */    ERR_IGNORE,
-/* EINTR */    ERR_CATCH,
-/* EIO */      ERR_CATCH,
-/* ENXIO */    ERR_CATCH,
-/* E2BIG */    ERR_CATCH,
-/* ENOEXEC */  ERR_CATCH,
-/* EBADF */    ERR_IGNORE,
-/* ECHILD */   ERR_CATCH,
-/* EAGAIN */   ERR_CATCH,
-/* ENOMEM */   ERR_CATCH,
-/* EACCES */   ERR_CATCH,
-/* EFAULT */   ERR_CATCH,
-/* ENOTBLK */  ERR_CATCH,
-/* EBUSY */    ERR_CATCH,
-/* EEXIST */   ERR_CATCH,
-/* EXDEV */    ERR_CATCH,
-/* ENODEV */   ERR_CATCH,
-/* ENOTDIR */  ERR_CATCH,
-/* EISDIR */   ERR_CATCH,
-/* EINVAL */   ERR_CATCH,
-/* ENFILE */   ERR_CATCH,
-/* EMFILE */   ERR_CATCH,
-/* ENOTTY */   ERR_IGNORE,
-/* ETXTBSY */  ERR_CATCH,
-/* EFBIG */    ERR_CATCH,
-/* ENOSPC */   ERR_CATCH,
-/* ESPIPE */   ERR_CATCH,
-/* EROFS */    ERR_CATCH,
-/* EMLINK */   ERR_CATCH,
-/* EPIPE */    ERR_CATCH,
-/* EDOM */     ERR_CATCH,
-/* ERANGE */   ERR_CATCH,
-/* EQUOT */    ERR_CATCH,
-};
+private ErrInfo *errinfo;
+
+private initErrInfo ()
+{
+    integer i;
+
+    errinfo = alloc(sys_nerr, ErrInfo);
+    for (i = 0; i < sys_nerr; i++) {
+       errinfo[i].func = ERR_CATCH;
+    }
+    errinfo[0].func = ERR_IGNORE;
+    errinfo[EPERM].func = ERR_IGNORE;
+    errinfo[ENOENT].func = ERR_IGNORE;
+    errinfo[ESRCH].func = ERR_IGNORE;
+    errinfo[EBADF].func = ERR_IGNORE;
+    errinfo[ENOTTY].func = ERR_IGNORE;
+    errinfo[EOPNOTSUPP].func = ERR_IGNORE;
+}
 
 public syserr()
 {
 
 public syserr()
 {
-    ERRINFO *e;
+    register ErrInfo *e;
 
 
-    e = &errinfo[errno];
-    if (e->func == ERR_CATCH) {
-       if (errno < sys_nerr) {
+    if (errno < 0 or errno > sys_nerr) {
+       fatal("errno %d", errno);
+    } else {
+       if (errinfo == nil(ErrInfo *)) {
+           initErrInfo();
+       }
+       e = &(errinfo[errno]);
+       if (e->func == ERR_CATCH) {
            fatal(sys_errlist[errno]);
            fatal(sys_errlist[errno]);
-       } else {
-           fatal("errno %d", errno);
+       } else if (e->func != ERR_IGNORE) {
+           (*e->func)();
        }
        }
-    } else if (e->func != ERR_IGNORE) {
-       (*e->func)();
     }
 }
 
 /*
     }
 }
 
 /*
- * Catcherrs only purpose is to get this module loaded and make
- * sure my cerror is loaded (only applicable when this is in a library).
+ * Catcherrs' purpose is to initialize the errinfo table, get this module
+ * loaded, and make sure my cerror is loaded (only applicable when this is
+ * in a library).
  */
 
 public catcherrs()
 {
     _mycerror();
  */
 
 public catcherrs()
 {
     _mycerror();
+    initErrInfo();
 }
 
 /*
 }
 
 /*
- * Change the action on receipt of an error.
+ * Turn off the error catching mechanism completely by having all errors
+ * ignored.  This is most useful between a fork and an exec.
  */
 
  */
 
-public onsyserr(n, f)
+public nocatcherrs()
+{
+    integer i;
+
+    for (i = 0; i < sys_nerr; i++) {
+       errinfo[i].func = ERR_IGNORE;
+    }
+}
+
+/*
+ * Change the action on receipt of an error, returning the previous action.
+ */
+
+public IntFunc *onsyserr(n, f)
 int n;
 int n;
-INTFUNC *f;
+IntFunc *f;
 {
 {
+    IntFunc *oldf;
+
+    if (errinfo == nil(ErrInfo *)) {
+       initErrInfo();
+    }
+    oldf = errinfo[n].func;
     errinfo[n].func = f;
     errinfo[n].func = f;
+    return oldf;
 }
 
 /*
 }
 
 /*
@@ -381,7 +441,14 @@ INTFUNC *f;
  * Like a "perror" for signals.
  */
 
  * Like a "perror" for signals.
  */
 
+#ifdef SIGWINCH
 public int sys_nsig = NSIG;
 public int sys_nsig = NSIG;
+#else not 4.3 BSD
+/*
+ * This table is correct for 4.2-like systems but will
+ * be inadequate for System V (which is the sort of
+ * Unix that needs it!).
+ */
 public String sys_siglist[] = {
     "no signal",
     "hangup",
 public String sys_siglist[] = {
     "no signal",
     "hangup",
@@ -408,26 +475,30 @@ public String sys_siglist[] = {
     "stop (tty output)",
     "possible input/output",
     "exceeded CPU time limit",
     "stop (tty output)",
     "possible input/output",
     "exceeded CPU time limit",
-    "exceeded file size limit",
-    nil(String)
+    "exceeded file size limit"
 };
 };
+public int sys_nsig = sizeof sys_siglist / sizeof sys_siglist[0];
+#endif
 
 
-public psig(s)
+public psignal(s, n)
 String s;
 String s;
+integer n;
 {
 {
-    String c;
-    int n;
+    String msg;
+    integer len;
+    extern String sys_siglist[];
 
 
-    c = "Unknown signal";
-    if (errno < sys_nsig) {
-       c = sys_errlist[errno];
+    if (n >= 0 and n < sys_nsig) {
+       msg = sys_siglist[n];
+    } else {
+       msg = "Unknown signal";
     }
     }
-    n = strlen(s);
-    if (n > 0) {
-       write(2, s, n);
+    len = strlen(s);
+    if (len > 0) {
+       write(2, s, len);
        write(2, ": ", 2);
     }
        write(2, ": ", 2);
     }
-    write(2, c, strlen(c));
+    write(2, msg, strlen(msg));
     write(2, "\n", 1);
 }
 
     write(2, "\n", 1);
 }
 
@@ -445,7 +516,7 @@ private short nwarnings;
 /* VARARGS2 */
 private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m)
 String errname;
 /* VARARGS2 */
 private errmsg(errname, shouldquit, s, a, b, c, d, e, f, g, h, i, j, k, l, m)
 String errname;
-Boolean shouldquit;
+boolean shouldquit;
 String s;
 {
     fflush(stdout);
 String s;
 {
     fflush(stdout);
@@ -463,6 +534,7 @@ String s;
     }
     fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
     putc('\n', stderr);
     }
     fprintf(stderr, s, a, b, c, d, e, f, g, h, i, j, k, l, m);
     putc('\n', stderr);
+    fflush(stderr);
     if (shouldquit) {
        quit(1);
     }
     if (shouldquit) {
        quit(1);
     }
@@ -486,6 +558,7 @@ public beginerrmsg()
 public enderrmsg()
 {
     putc('\n', stderr);
 public enderrmsg()
 {
     putc('\n', stderr);
+    fflush(stderr);
     erecover();
 }
 
     erecover();
 }
 
@@ -634,3 +707,41 @@ register unsigned int n;
        while ((*dest++ = *src++) != '\0');
     }
 }
        while ((*dest++ = *src++) != '\0');
     }
 }
+
+#ifdef IRIS /* or in general for 4.2 - System V C library interface */
+
+public bcopy (fromaddr, toaddr, n)
+char *fromaddr, *toaddr;
+int n;
+{
+    blt(toaddr, fromaddr, n);
+}
+
+public bzero (addr, n)
+char *addr;
+int n;
+{
+    register char *p, *q;
+
+    p = addr;
+    q = p + n;
+    while (p < q) {
+       *p++ = '\0';
+    }
+}
+
+#include <string.h>
+
+public char *index (s, c)
+char *s, c;
+{
+    return strchr(s, c);
+}
+
+public char *rindex (s, c)
+char *s, c;
+{
+    return strrchr(s, c);
+}
+
+#endif