X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/ca69b757b65bf295672dd50d3d64258e2ae3a97d..dc0e9d5051968b633dbad1c43b90e583b0784799:/usr/src/old/dbx/process.c diff --git a/usr/src/old/dbx/process.c b/usr/src/old/dbx/process.c index de2ec3ab9c..edb31aa7b9 100644 --- a/usr/src/old/dbx/process.c +++ b/usr/src/old/dbx/process.c @@ -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[] = "@(#)process.c 1.11 %G%"; +#ifndef lint +static char sccsid[] = "@(#)process.c 5.3 (Berkeley) %G%"; +#endif not lint + +static char rcsid[] = "$Header: process.c,v 1.4 88/01/10 00:49:31 donn Exp $"; /* * Process management. @@ -14,6 +22,7 @@ static char sccsid[] = "@(#)process.c 1.11 %G%"; #include "machine.h" #include "events.h" #include "tree.h" +#include "eval.h" #include "operators.h" #include "source.h" #include "object.h" @@ -22,8 +31,6 @@ static char sccsid[] = "@(#)process.c 1.11 %G%"; #include "coredump.h" #include #include -#include -#include #include #ifndef public @@ -32,6 +39,8 @@ typedef struct Process *Process; Process process; +#define DEFSIG -1 + #include "machine.h" #endif @@ -41,11 +50,12 @@ Process process; #define FINISHED 0 /* - * Cache-ing of instruction segment is done to reduce the number - * of system calls. + * A cache of the instruction segment is kept to reduce the number + * of system calls. Might be better just to read the entire + * code space into memory. */ -#define CSIZE 1003 /* size of instruction cache */ +#define CACHESIZE 1003 typedef struct { Word addr; @@ -63,10 +73,12 @@ struct Process { Word oreg[NREG]; /* registers when process last stopped */ short status; /* either STOPPED or FINISHED */ short signo; /* signal that stopped process */ + short sigcode; /* extra signal information */ int exitval; /* return value from exit() */ long sigset; /* bit array of traced signals */ - CacheWord word[CSIZE]; /* text segment cache */ + CacheWord word[CACHESIZE]; /* text segment cache */ Ttyinfo ttyinfo; /* process' terminal characteristics */ + Address sigstatus; /* process' handler for current signal */ }; /* @@ -78,7 +90,7 @@ typedef enum { TEXTSEG, DATASEG } PioSeg; private struct Process pbuf; -#define MAXNCMDARGS 100 /* maximum number of arguments to RUN */ +#define MAXNCMDARGS 1000 /* maximum number of arguments to RUN */ extern int errno; @@ -93,24 +105,36 @@ private String infile, outfile; public process_init() { - register Integer i; - Char buf[10]; + register integer i; + char buf[10]; process = &pbuf; process->status = (coredump) ? STOPPED : NOTSTARTED; setsigtrace(); - for (i = 0; i < NREG; i++) { - sprintf(buf, "$r%d", i); - defregname(identname(buf, false), i); - } - defregname(identname("$ap", true), ARGP); +# if vax || tahoe + for (i = 0; i < NREG; i++) { + sprintf(buf, "$r%d", i); + defregname(identname(buf, false), i); + } +# ifdef vax + defregname(identname("$ap", true), ARGP); +# endif +# else +# ifdef mc68000 + for (i = 0; i < 8; i++) { + sprintf(buf, "$d%d", i); + defregname(identname(buf, false), i); + sprintf(buf, "$a%d", i); + defregname(identname(buf, false), i + 8); + } +# endif +# endif defregname(identname("$fp", true), FRP); defregname(identname("$sp", true), STKP); defregname(identname("$pc", true), PROGCTR); if (coredump) { coredump_readin(process->mask, process->reg, process->signo); pc = process->reg[PROGCTR]; - getsrcpos(); } arginit(); } @@ -167,13 +191,13 @@ String infile, outfile; } else { argv[argc] = nil; } + pstart(process, argv, infile, outfile); if (remade(objname)) { reinit(argv, infile, outfile); } - pstart(process, argv, infile, outfile); if (process->status == STOPPED) { - pc = 0; - curfunc = program; + pc = CODESTART; + setcurfunc(program); if (objsize != 0) { cond = build(O_EQ, build(O_SYM, pcsym), build(O_LCON, lastaddr())); event_once(cond, buildcmdlist(build(O_ENDX))); @@ -216,9 +240,12 @@ private setsigtrace() psigtrace(p, SIGHUP, false); psigtrace(p, SIGKILL, false); psigtrace(p, SIGALRM, false); - psigtrace(p, SIGTSTP, false); - psigtrace(p, SIGCONT, false); +# ifdef SIGTSTP + psigtrace(p, SIGTSTP, false); + psigtrace(p, SIGCONT, false); +# endif psigtrace(p, SIGCHLD, false); + psigtrace(p, SIGWINCH, false); } /* @@ -285,7 +312,7 @@ public run() start(argv, infile, outfile); just_started = true; isstopped = false; - cont(); + cont(0); } /* @@ -300,12 +327,11 @@ typedef int Intfunc(); private Intfunc *dbintr; private intr(); -#define succeeds == true -#define fails == false - public cont(signo) -int signo; +integer signo; { + integer s; + dbintr = signal(SIGINT, intr); if (just_started) { just_started = false; @@ -316,14 +342,16 @@ int signo; isstopped = false; stepover(); } + s = signo; for (;;) { if (single_stepping) { printnews(); } else { setallbps(); - resume(signo); + resume(s); unsetallbps(); - if (bpact() fails) { + s = DEFSIG; + if (not isbperr() or not bpact()) { printstatus(); } } @@ -333,12 +361,12 @@ int signo; } /* - * This routine is called if we get an interrupt while "running" px + * This routine is called if we get an interrupt while "running" * but actually in the debugger. Could happen, for example, while * processing breakpoints. * * We basically just want to keep going; the assumption is - * that when the process resumes it will get the interrupt + * that when the process resumes it will get the interrupt, * which will then be handled. */ @@ -362,22 +390,17 @@ int signo; register Process p; p = process; - if (traceexec) { - printf("execution resumes at pc 0x%x\n", process->reg[PROGCTR]); - fflush(stdout); - } pcont(p, signo); pc = process->reg[PROGCTR]; - if (traceexec) { - printf("execution stops at pc 0x%x on sig %d\n", - process->reg[PROGCTR], p->signo); - fflush(stdout); - } if (p->status != STOPPED) { if (p->signo != 0) { error("program terminated by signal %d", p->signo); - } else { - error("program unexpectedly exited with %d", p->exitval); + } else if (not runfirst) { + if (p->exitval == 0) { + error("program exited"); + } else { + error("program exited with code %d", p->exitval); + } } } } @@ -407,14 +430,60 @@ public stepc() public next() { + Address oldfrp, newfrp; + if (not isstopped) { error("can't continue execution"); } isstopped = false; - dostep(true); + oldfrp = reg(FRP); + do { + dostep(true); + pc = reg(PROGCTR); + newfrp = reg(FRP); + } while (newfrp < oldfrp and newfrp != 0); isstopped = true; } +/* + * Continue execution until the current function returns, or, + * if the given argument is non-nil, until execution returns to + * somewhere within the given function. + */ + +public rtnfunc (f) +Symbol f; +{ + Address addr; + Symbol t; + + if (not isstopped) { + error("can't continue execution"); + } else if (f != nil and not isactive(f)) { + error("%s is not active", symname(f)); + } else { + addr = return_addr(); + if (addr == nil) { + error("no place to return to"); + } else { + isstopped = false; + contto(addr); + if (f != nil) { + for (;;) { + t = whatblock(pc); + addr = return_addr(); + if (t == f or addr == nil) break; + contto(addr); + } + } + if (not bpact()) { + isstopped = true; + printstatus(); + } + } + } +} + /* * Single-step over the current machine instruction. * @@ -424,10 +493,13 @@ public next() * source line. */ -private stepover() +public stepover() { Boolean b; + if (traceexec) { + printf("!! stepping over 0x%x\n", process->reg[PROGCTR]); + } if (single_stepping) { dostep(false); } else { @@ -436,22 +508,54 @@ private stepover() dostep(false); inst_tracing = b; } + if (traceexec) { + printf("!! stepped over to 0x%x\n", process->reg[PROGCTR]); + } } /* - * Resume execution up to the given address. It is assumed that - * no breakpoints exist between the current address and the one - * we're stepping to. This saves us from setting all the breakpoints. + * Resume execution up to the given address. We can either ignore + * breakpoints (stepto) or catch them (contto). */ public stepto(addr) Address addr; { - setbp(addr); - resume(0); - unsetbp(addr); - if (not isbperr()) { - printstatus(); + xto(addr, false); +} + +private contto (addr) +Address addr; +{ + xto(addr, true); +} + +private xto (addr, catchbps) +Address addr; +boolean catchbps; +{ + Address curpc; + + if (catchbps) { + stepover(); + } + curpc = process->reg[PROGCTR]; + if (addr != curpc) { + if (traceexec) { + printf("!! stepping from 0x%x to 0x%x\n", curpc, addr); + } + if (catchbps) { + setallbps(); + } + setbp(addr); + resume(DEFSIG); + unsetbp(addr); + if (catchbps) { + unsetallbps(); + } + if (not isbperr()) { + printstatus(); + } } } @@ -460,14 +564,19 @@ Address addr; * This routine does not return. */ -public printstatus() +public printstatus () { int status; if (process->status == FINISHED) { exit(0); } else { - curfunc = whatblock(pc); + if (runfirst) { + fprintf(stderr, "\nEntering debugger ...\n"); + printheading(); + init(); + } + setcurfunc(whatblock(pc)); getsrcpos(); if (process->signo == SIGINT) { isstopped = true; @@ -483,7 +592,6 @@ public printstatus() } erecover(); } else { - fixbps(); fixintr(); isstopped = true; printerror(); @@ -500,9 +608,11 @@ public printloc() printf("in "); printname(stdout, curfunc); putchar(' '); - if (curline > 0) { + if (curline > 0 and not useInstLoc) { printsrcpos(); } else { + useInstLoc = false; + curline = 0; printf("at 0x%x", pc); } } @@ -524,20 +634,53 @@ Process p; } /* - * Return the signal number which stopped the process. + * Predicate to test if the reason the process stopped was because + * of a breakpoint. If so, as a side effect clear the local copy of + * signal handler associated with process. We must do this so as to + * not confuse future stepping or continuing by possibly concluding + * the process should continue with a SIGTRAP handler. */ -public Integer errnum(p) +public boolean isbperr() +{ + Process p; + boolean b; + + p = process; + if (p->status == STOPPED and p->signo == SIGTRAP) { + b = true; + p->sigstatus = 0; + } else { + b = false; + } + return b; +} + +/* + * Return the signal number that stopped the process. + */ + +public integer errnum (p) Process p; { return p->signo; } +/* + * Return the signal code associated with the signal. + */ + +public integer errcode (p) +Process p; +{ + return p->sigcode; +} + /* * Return the termination code of the process. */ -public Integer exitcode(p) +public integer exitcode (p) Process p; { return p->exitval; @@ -548,15 +691,15 @@ Process p; * outside this module. * * They invoke "pio" which eventually leads to a call to "ptrace". - * The system generates an I/O error when a ptrace fails, we assume - * during a read/write to the process that such an error is due to - * a misguided address and ignore it. + * The system generates an I/O error when a ptrace fails. During reads + * these are ignored, during writes they are reported as an error, and + * for anything else they cause a fatal error. */ extern Intfunc *onsyserr(); private badaddr; -private rwerr(); +private read_err(), write_err(); /* * Read from the process' instruction area. @@ -569,7 +712,7 @@ int nbytes; { Intfunc *f; - f = onsyserr(EIO, rwerr); + f = onsyserr(EIO, read_err); badaddr = addr; if (coredump) { coredump_readtext(buff, addr, nbytes); @@ -594,7 +737,7 @@ int nbytes; if (coredump) { error("no process to write to"); } - f = onsyserr(EIO, rwerr); + f = onsyserr(EIO, write_err); badaddr = addr; pio(process, PWRITE, TEXTSEG, buff, addr, nbytes); onsyserr(EIO, f); @@ -611,14 +754,16 @@ int nbytes; { Intfunc *f; - f = onsyserr(EIO, rwerr); badaddr = addr; if (coredump) { + f = onsyserr(EFAULT, read_err); coredump_readdata(buff, addr, nbytes); + onsyserr(EFAULT, f); } else { + f = onsyserr(EIO, read_err); pio(process, PREAD, DATASEG, buff, addr, nbytes); + onsyserr(EIO, f); } - onsyserr(EIO, f); } /* @@ -635,39 +780,36 @@ int nbytes; if (coredump) { error("no process to write to"); } - f = onsyserr(EIO, rwerr); + f = onsyserr(EIO, write_err); badaddr = addr; pio(process, PWRITE, DATASEG, buff, addr, nbytes); onsyserr(EIO, f); } /* - * Error handler. + * Trap for errors in reading or writing to a process. + * The current approach is to "ignore" read errors and complain + * bitterly about write errors. */ -private rwerr() +private read_err() { /* - * Current response is to ignore the error and let the result - * (-1) ripple back up to the process. - * - error("bad read/write process address 0x%x", badaddr); + * Ignore. */ } -/* - * Ptrace interface. - */ +private write_err() +{ + error("can't write to process (address 0x%x)", badaddr); +} /* - * This magic macro enables us to look at the process' registers - * in its user structure. Very gross. + * Ptrace interface. */ -#define regloc(reg) (ctob(UPAGES) + ( sizeof(int) * (reg) )) - #define WMASK (~(sizeof(Word) - 1)) -#define cachehash(addr) ((unsigned) ((addr >> 2) % CSIZE)) +#define cachehash(addr) ((unsigned) ((addr >> 2) % CACHESIZE)) #define FIRSTSIG SIGINT #define LASTSIG SIGQUIT @@ -690,6 +832,14 @@ private rwerr() #define SSTEP 9 /* continue for approximately one instruction */ #define PKILL 8 /* terminate the process */ +#ifdef IRIS +# define readreg(p, r) ptrace(10, p->pid, r, 0) +# define writereg(p, r, v) ptrace(11, p->pid, r, v) +#else +# define readreg(p, r) ptrace(UREAD, p->pid, regloc(r), 0); +# define writereg(p, r, v) ptrace(UWRITE, p->pid, regloc(r), v); +#endif + /* * Start up a new process by forking and exec-ing the * given argument list, returning when the process is loaded @@ -708,52 +858,57 @@ String infile; String outfile; { int status; - Fileid in, out; - if (p->pid != 0) { /* child already running? */ - ptrace(PKILL, p->pid, 0, 0); /* ... kill it! */ - pwait(p->pid, &status); /* wait for it to exit */ - unptraced(p->pid); + if (p->pid != 0) { + pterm(p); + cacheflush(p); } + fflush(stdout); psigtrace(p, SIGTRAP, true); - p->pid = vfork(); +# ifdef IRIS + p->pid = fork(); +# else + p->pid = vfork(); +# endif if (p->pid == -1) { panic("can't fork"); } if (ischild(p->pid)) { + nocatcherrs(); traceme(); if (infile != nil) { - in = open(infile, 0); - if (in == -1) { - write(2, "can't read ", 11); - write(2, infile, strlen(infile)); - write(2, "\n", 1); - _exit(1); - } - fswap(0, in); + infrom(infile); } if (outfile != nil) { - out = creat(outfile, 0666); - if (out == -1) { - write(2, "can't write ", 12); - write(2, outfile, strlen(outfile)); - write(2, "\n", 1); - _exit(1); - } - fswap(1, out); + outto(outfile); } execv(argv[0], argv); - write(2, "can't exec ", 11); - write(2, argv[0], strlen(argv[0])); - write(2, "\n", 1); _exit(1); } pwait(p->pid, &status); getinfo(p, status); if (p->status != STOPPED) { - error("program could not begin execution"); + beginerrmsg(); + fprintf(stderr, "warning: cannot execute %s\n", argv[0]); + } else { + ptraced(p->pid); + } +} + +/* + * Terminate a ptrace'd process. + */ + +public pterm (p) +Process p; +{ + integer status; + + if (p != nil and p->pid != 0) { + ptrace(PKILL, p->pid, 0, 0); + pwait(p->pid, &status); + unptraced(p->pid); } - ptraced(p->pid); } /* @@ -770,13 +925,19 @@ private pcont(p, signo) Process p; int signo; { - int status; + int s, status; if (p->pid == 0) { - error("program not active"); + error("program is not active"); } + s = signo; do { - setinfo(p, signo); + setinfo(p, s); + if (traceexec) { + printf("!! pcont from 0x%x with signal %d (%d)\n", + p->reg[PROGCTR], s, p->signo); + fflush(stdout); + } sigs_off(); if (ptrace(CONT, p->pid, p->reg[PROGCTR], p->signo) < 0) { panic("error %d trying to continue process", errno); @@ -784,24 +945,68 @@ int signo; pwait(p->pid, &status); sigs_on(); getinfo(p, status); + if (p->status == STOPPED and traceexec and not istraced(p)) { + printf("!! ignored signal %d at 0x%x\n", + p->signo, p->reg[PROGCTR]); + fflush(stdout); + } + s = p->signo; } while (p->status == STOPPED and not istraced(p)); + if (traceexec) { + printf("!! pcont to 0x%x on signal %d\n", p->reg[PROGCTR], p->signo); + fflush(stdout); + } } /* * Single step as best ptrace can. */ -public pstep(p) +public pstep(p, signo) Process p; +integer signo; { - int status; + int s, status; - setinfo(p, 0); - sigs_off(); - ptrace(SSTEP, p->pid, p->reg[PROGCTR], p->signo); - pwait(p->pid, &status); - sigs_on(); - getinfo(p, status); + s = signo; + do { + setinfo(p, s); + if (traceexec) { + printf("!! pstep from 0x%x with signal %d (%d)\n", + p->reg[PROGCTR], s, p->signo); + fflush(stdout); + } + sigs_off(); + if (ptrace(SSTEP, p->pid, p->reg[PROGCTR], p->signo) < 0) { + panic("error %d trying to step process", errno); + } + pwait(p->pid, &status); + sigs_on(); + getinfo(p, status); +# if mc68000 || m68000 + if (p->status == STOPPED and p->signo == SIGTRAP) { + p->reg[PROGCTR] += 2; + } +# endif + if (p->status == STOPPED and traceexec and not istraced(p)) { + printf("!! pstep ignored signal %d at 0x%x\n", + p->signo, p->reg[PROGCTR]); + fflush(stdout); + } + s = p->signo; + } while (p->status == STOPPED and not istraced(p)); + if (traceexec) { + printf("!! pstep to 0x%x on signal %d\n", + p->reg[PROGCTR], p->signo); + fflush(stdout); + } + if (p->status != STOPPED) { + if (p->exitval == 0) { + error("program exited\n"); + } else { + error("program exited with code %d\n", p->exitval); + } + } } /* @@ -867,30 +1072,43 @@ private sigs_on() * Get process information from user area. */ -private int rloc[] ={ - R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC -}; - -private getinfo(p, status) +private getinfo (p, status) register Process p; register int status; { register int i; + Address addr; p->signo = (status&0177); p->exitval = ((status >> 8)&0377); if (p->signo != STOPPED) { p->status = FINISHED; + p->pid = 0; + p->reg[PROGCTR] = 0; } else { p->status = p->signo; p->signo = p->exitval; p->exitval = 0; - p->mask = ptrace(UREAD, p->pid, regloc(PS), 0); +# ifdef IRIS + p->mask = readreg(p, RPS); +# else + p->sigcode = ptrace(UREAD, p->pid, &((struct user *)0)->u_code, 0); + p->mask = readreg(p, PS); +# endif for (i = 0; i < NREG; i++) { - p->reg[i] = ptrace(UREAD, p->pid, regloc(rloc[i]), 0); + p->reg[i] = readreg(p, rloc[i]); p->oreg[i] = p->reg[i]; } +# ifdef mc68000 + if (p->status == STOPPED and p->signo == SIGTRAP and + p->reg[PROGCTR] > CODESTART + ) { + p->reg[PROGCTR] -= 2; + } +# endif savetty(stdout, &(p->ttyinfo)); + addr = (Address) &(((struct user *) 0)->u_signal[p->signo]); + p->sigstatus = (Address) ptrace(UREAD, p->pid, addr, 0); } } @@ -898,24 +1116,45 @@ register int status; * Set process's user area information from given process structure. */ -private setinfo(p, signo) +private setinfo (p, signo) register Process p; int signo; { register int i; register int r; - if (istraced(p)) { + if (signo == DEFSIG) { + if (istraced(p) and (p->sigstatus == 0 or p->sigstatus == 1)) { + p->signo = 0; + } + } else { p->signo = signo; } for (i = 0; i < NREG; i++) { if ((r = p->reg[i]) != p->oreg[i]) { - ptrace(UWRITE, p->pid, regloc(rloc[i]), r); + writereg(p, rloc[i], r); } } restoretty(stdout, &(p->ttyinfo)); } +/* + * Return the address associated with the current signal. + * (Plus two since the address points to the beginning of a procedure). + */ + +public Address usignal (p) +Process p; +{ + Address r; + + r = p->sigstatus; + if (r != 0 and r != 1) { + r += FUNCOFFSET; + } + return r; +} + /* * Structure for reading and writing by words, but dealing with bytes. */ @@ -974,6 +1213,28 @@ int nbytes; byteoff = (nbytes&(~WMASK)); nbytes -= byteoff; bufend = cp + nbytes; +#ifdef tahoe + if (((int)cp)&WMASK) { + /* + * Must copy a byte at a time, buffer not word addressable. + */ + while (cp < bufend) { + if (op == PREAD) { + w.pword = fetch(p, seg, newaddr); + for (i = 0; i < sizeof(Word); i++) + *cp++ = w.pbyte[i]; + } else { + for (i = 0; i < sizeof(Word); i++) + w.pbyte[i] = *cp++; + store(p, seg, newaddr, w.pword); + } + newaddr += sizeof(Word); + } + } else { + /* + * Buffer, word aligned, act normally... + */ +#endif while (cp < bufend) { if (op == PREAD) { *((Word *) cp) = fetch(p, seg, newaddr); @@ -983,6 +1244,9 @@ int nbytes; cp += sizeof(Word); newaddr += sizeof(Word); } +#ifdef tahoe + } +#endif if (byteoff > 0) { w.pword = fetch(p, seg, newaddr); for (i = 0; i < byteoff; i++) { @@ -1076,18 +1340,69 @@ Word data; } } +/* + * Flush the instruction cache associated with a process. + */ + +private cacheflush (p) +Process p; +{ + bzero(p->word, sizeof(p->word)); +} + public printptraceinfo() { printf("%d fetchs, %d reads, %d writes\n", nfetchs, nreads, nwrites); } /* - * Swap file numbers so as to redirect standard input and output. + * Redirect input. + * Assuming this is called from a child, we should be careful to avoid + * (possibly) shared standard I/O buffers. + */ + +private infrom (filename) +String filename; +{ + Fileid in; + + in = open(filename, 0); + if (in == -1) { + write(2, "can't read ", 11); + write(2, filename, strlen(filename)); + write(2, "\n", 1); + _exit(1); + } + fswap(0, in); +} + +/* + * Redirect standard output. + * Same assumptions as for "infrom" above. + */ + +private outto (filename) +String filename; +{ + Fileid out; + + out = creat(filename, 0666); + if (out == -1) { + write(2, "can't write ", 12); + write(2, filename, strlen(filename)); + write(2, "\n", 1); + _exit(1); + } + fswap(1, out); +} + +/* + * Swap file numbers, useful for redirecting standard input or output. */ private fswap(oldfd, newfd) -int oldfd; -int newfd; +Fileid oldfd; +Fileid newfd; { if (oldfd != newfd) { close(oldfd); @@ -1095,3 +1410,104 @@ int newfd; close(newfd); } } + +/* + * Signal name manipulation. + */ + +private String signames[NSIG] = { + 0, + "HUP", "INT", "QUIT", "ILL", "TRAP", + "IOT", "EMT", "FPE", "KILL", "BUS", + "SEGV", "SYS", "PIPE", "ALRM", "TERM", + 0, "STOP", "TSTP", "CONT", "CHLD", + "TTIN", "TTOU", "TINT", "XCPU", "XFSZ", + "VTALRM", "PROF", "WINCH", "USR1", "USR2" +}; + +/* + * Get the signal number associated with a given name. + * The name is first translated to upper case if necessary. + */ + +public integer siglookup (s) +String s; +{ + register char *p, *q; + char buf[100]; + integer i; + + p = s; + q = buf; + while (*p != '\0') { + if (*p >= 'a' and *p <= 'z') { + *q = (*p - 'a') + 'A'; + } else { + *q = *p; + } + ++p; + ++q; + } + *q = '\0'; + p = buf; + if (buf[0] == 'S' and buf[1] == 'I' and buf[2] == 'G') { + p += 3; + } + i = 1; + for (;;) { + if (i >= sizeof(signames) div sizeof(signames[0])) { + error("signal \"%s\" unknown", s); + i = 0; + break; + } + if (signames[i] != nil and streq(signames[i], p)) { + break; + } + ++i; + } + return i; +} + +/* + * Print all signals being ignored by the debugger. + * These signals are auotmatically + * passed on to the debugged process. + */ + +public printsigsignored (p) +Process p; +{ + printsigs(~p->sigset); +} + +/* + * Print all signals being intercepted by + * the debugger for the specified process. + */ + +public printsigscaught(p) +Process p; +{ + printsigs(p->sigset); +} + +private printsigs (set) +integer set; +{ + integer s; + char separator[2]; + + separator[0] = '\0'; + for (s = 1; s < sizeof(signames) div sizeof(signames[0]); s++) { + if (set & setrep(s)) { + if (signames[s] != nil) { + printf("%s%s", separator, signames[s]); + separator[0] = ' '; + separator[1] = '\0'; + } + } + } + if (separator[0] == ' ') { + putchar('\n'); + } +}