Add copyright
[unix-history] / usr / src / old / dbx / library.c
index 2b863d4..947aa23 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.
+ */
 
 
-/* static char sccsid[] = "@(#)library.c 1.1 9/2/82"; */
+#ifndef lint
+static char sccsid[] = "@(#)library.c  5.1 (Berkeley) %G%";
+#endif not lint
+
+static char rcsid[] = "$Header: library.c,v 1.5 84/12/26 10:39:52 linton Exp $";
 
 /*
  * General purpose routines.
 
 /*
  * General purpose routines.
 #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 */
@@ -85,7 +85,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 +206,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 +218,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 +294,9 @@ int pid, *statusp;
            *statusp = p->status;
            dispose(p);
        } else {
            *statusp = p->status;
            dispose(p);
        } else {
-               *statusp = status;
+           *statusp = status;
        }
        }
+    }
 }
 
 /*
 }
 
 /*
@@ -297,72 +349,71 @@ 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()
 {
     ERRINFO *e;
 
 
 public syserr()
 {
     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();
+}
+
+/*
+ * Turn off the error catching mechanism completely by having all errors
+ * ignored.  This is most useful between a fork and an exec.
+ */
+
+public nocatcherrs()
+{
+    integer i;
+
+    for (i = 0; i < sys_nerr; i++) {
+       errinfo[i].func = ERR_IGNORE;
+    }
 }
 
 /*
 }
 
 /*
@@ -373,6 +424,9 @@ public onsyserr(n, f)
 int n;
 INTFUNC *f;
 {
 int n;
 INTFUNC *f;
 {
+    if (errinfo == nil(ERRINFO *)) {
+       initErrInfo();
+    }
     errinfo[n].func = f;
 }
 
     errinfo[n].func = f;
 }
 
@@ -382,52 +436,26 @@ INTFUNC *f;
  */
 
 public int sys_nsig = NSIG;
  */
 
 public int sys_nsig = NSIG;
-public String sys_siglist[] = {
-    "no signal",
-    "hangup",
-    "interrupt",
-    "quit",
-    "illegal instruction",
-    "trace trap",
-    "IOT instruction",
-    "EMT instruction",
-    "floating point exception",
-    "kill",
-    "bus error",
-    "segmentation violation",
-    "bad argument to system call",
-    "broken pipe",
-    "alarm clock",
-    "soft kill",
-    "urgent I/O condition",
-    "stop signal not from tty",
-    "stop signal from tty",
-    "continue",
-    "child termination",
-    "stop (tty input)",
-    "stop (tty output)",
-    "possible input/output",
-    "exceeded CPU time limit",
-    "exceeded file size limit",
-    nil(String)
-};
-
-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 +473,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);