📄 signal.c
字号:
/* * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation * Linux for s390 port by D.J. Barrow * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id: signal.c,v 1.28 2001/03/28 20:29:17 wichert Exp $ */#include "defs.h"#include <signal.h>#include <sys/user.h>#include <fcntl.h>#ifdef SVR4#include <sys/ucontext.h>#endif /* SVR4 */#ifdef HAVE_SYS_REG_H# include <sys/reg.h>#ifndef PTRACE_PEEKUSR# define PTRACE_PEEKUSR PTRACE_PEEKUSER#endif#ifndef PTRACE_POKEUSR# define PTRACE_POKEUSR PTRACE_POKEUSER#endif#elif defined(HAVE_LINUX_PTRACE_H)#undef PTRACE_SYSCALL#include <linux/ptrace.h>#endif#ifdef LINUX#ifdef IA64# include <asm/ptrace_offsets.h>#endif /* !IA64 */#if HAVE_ASM_REG_H#ifdef SPARC# define fpq kernel_fpq# define fq kernel_fq# define fpu kernel_fpu#endif#include <asm/reg.h>#ifdef SPARC# undef fpq# undef fq# undef fpu #endif#endif /* HAVE_ASM_REG_H */#ifdef HAVE_ASM_SIGCONTEXT_H#ifdef SPARCtypedef struct { struct regs si_regs; int si_mask;} m_siginfo_t;#else#include <asm/sigcontext.h>#endif /* SPARC */#else /* !HAVE_ASM_SIGCONTEXT_H */#ifdef I386struct sigcontext_struct { unsigned short gs, __gsh; unsigned short fs, __fsh; unsigned short es, __esh; unsigned short ds, __dsh; unsigned long edi; unsigned long esi; unsigned long ebp; unsigned long esp; unsigned long ebx; unsigned long edx; unsigned long ecx; unsigned long eax; unsigned long trapno; unsigned long err; unsigned long eip; unsigned short cs, __csh; unsigned long eflags; unsigned long esp_at_signal; unsigned short ss, __ssh; unsigned long i387; unsigned long oldmask; unsigned long cr2;};#else /* !I386 */#ifdef M68Kstruct sigcontext{ unsigned long sc_mask; unsigned long sc_usp; unsigned long sc_d0; unsigned long sc_d1; unsigned long sc_a0; unsigned long sc_a1; unsigned short sc_sr; unsigned long sc_pc; unsigned short sc_formatvec;};#endif /* M68K */#endif /* !I386 */#endif /* !HAVE_ASM_SIGCONTEXT_H */#ifndef NSIG#define NSIG 32#endif#ifdef ARM#undef NSIG#define NSIG 32#endif#endif /* LINUX */char *signalent0[] = {#include "signalent.h"};int nsignals0 = sizeof signalent0 / sizeof signalent0[0];#if SUPPORTED_PERSONALITIES >= 2char *signalent1[] = {#include "signalent1.h"};int nsignals1 = sizeof signalent1 / sizeof signalent1[0];#endif /* SUPPORTED_PERSONALITIES >= 2 */#if SUPPORTED_PERSONALITIES >= 3char *signalent2[] = {#include "signalent2.h"};int nsignals2 = sizeof signalent2 / sizeof signalent2[0];#endif /* SUPPORTED_PERSONALITIES >= 3 */char **signalent;int nsignals;#if defined(SUNOS4) || defined(FREEBSD)static struct xlat sigvec_flags[] = { { SV_ONSTACK, "SV_ONSTACK" }, { SV_INTERRUPT, "SV_INTERRUPT" }, { SV_RESETHAND, "SV_RESETHAND" }, { SA_NOCLDSTOP, "SA_NOCLDSTOP" }, { 0, NULL },};#endif /* SUNOS4 || FREEBSD */#ifdef HAVE_SIGACTIONstatic struct xlat sigact_flags[] = {#ifdef SA_RESTORER { SA_RESTORER, "SA_RESTORER" },#endif#ifdef SA_STACK { SA_STACK, "SA_STACK" },#endif#ifdef SA_RESTART { SA_RESTART, "SA_RESTART" },#endif#ifdef SA_INTERRUPT { SA_INTERRUPT, "SA_INTERRUPT" },#endif#ifdef SA_NOMASK { SA_NOMASK, "SA_NOMASK" },#endif#ifdef SA_ONESHOT { SA_ONESHOT, "SA_ONESHOT" },#endif#ifdef SA_SIGINFO { SA_SIGINFO, "SA_SIGINFO" },#endif#ifdef SA_RESETHAND { SA_RESETHAND, "SA_RESETHAND" },#endif#ifdef SA_ONSTACK { SA_ONSTACK, "SA_ONSTACK" },#endif#ifdef SA_NODEFER { SA_NODEFER, "SA_NODEFER" },#endif#ifdef SA_NOCLDSTOP { SA_NOCLDSTOP, "SA_NOCLDSTOP" },#endif#ifdef SA_NOCLDWAIT { SA_NOCLDWAIT, "SA_NOCLDWAIT" },#endif#ifdef _SA_BSDCALL { _SA_BSDCALL, "_SA_BSDCALL" },#endif { 0, NULL },};static struct xlat sigprocmaskcmds[] = { { SIG_BLOCK, "SIG_BLOCK" }, { SIG_UNBLOCK, "SIG_UNBLOCK" }, { SIG_SETMASK, "SIG_SETMASK" },#ifdef SIG_SETMASK32 { SIG_SETMASK32,"SIG_SETMASK32" },#endif { 0, NULL },};#endif /* HAVE_SIGACTION *//* Anonymous realtime signals. *//* Under glibc 2.1, SIGRTMIN et al are functions, but __SIGRTMIN is a constant. This is what we want. Otherwise, just use SIGRTMIN. */#ifdef SIGRTMIN#ifndef __SIGRTMIN#define __SIGRTMIN SIGRTMIN#define __SIGRTMAX SIGRTMAX /* likewise */#endif#endifchar *signame(sig)int sig;{ static char buf[30]; if (sig < nsignals) { return signalent[sig];#ifdef SIGRTMIN } else if (sig >= __SIGRTMIN && sig <= __SIGRTMAX) { sprintf(buf, "SIGRT_%ld", (long)(sig - __SIGRTMIN)); return buf;#endif /* SIGRTMIN */ } else { sprintf(buf, "%d", sig); return buf; }}#ifndef UNIXWAREstatic voidlong_to_sigset(l, s)long l;sigset_t *s;{ sigemptyset(s); *(long *)s = l;}#endifstatic intcopy_sigset_len(tcp, addr, s, len)struct tcb *tcp;long addr;sigset_t *s;int len;{ if (len > sizeof(*s)) len = sizeof(*s); sigemptyset(s); if (umoven(tcp, addr, len, (char *)s) < 0) return -1; return 0;}#ifdef LINUX/* Original sigset is unsigned long */#define copy_sigset(tcp, addr, s) copy_sigset_len(tcp, addr, s, sizeof(long))#else#define copy_sigset(tcp, addr, s) copy_sigset_len(tcp, addr, s, sizeof(sigset_t))#endifstatic char *sprintsigmask(s, mask, rt)char *s;sigset_t *mask;int rt; /* set might include realtime sigs */{ int i, nsigs; int maxsigs; char *format; static char outstr[256]; strcpy(outstr, s); s = outstr + strlen(outstr); nsigs = 0; maxsigs = nsignals;#ifdef __SIGRTMAX if (rt) maxsigs = __SIGRTMAX; /* instead */#endif for (i = 1; i < maxsigs; i++) { if (sigismember(mask, i) == 1) nsigs++; } if (nsigs >= nsignals * 2 / 3) { *s++ = '~'; for (i = 1; i < maxsigs; i++) { switch (sigismember(mask, i)) { case 1: sigdelset(mask, i); break; case 0: sigaddset(mask, i); break; } } } format = "%s"; *s++ = '['; for (i = 1; i < maxsigs; i++) { if (sigismember(mask, i) == 1) { /* real-time signals on solaris don't have * signalent entries */ if (i < nsignals) { sprintf(s, format, signalent[i] + 3); } else { char tsig[32]; sprintf(tsig, "%u", i); sprintf(s, format, tsig); } s += strlen(s); format = " %s"; } } *s++ = ']'; *s = '\0'; return outstr;}static voidprintsigmask(mask, rt)sigset_t *mask;int rt;{ tprintf("%s", sprintsigmask("", mask, rt));}voidprintsignal(nr)int nr;{ tprintf(signame(nr));}/* * Check process TCP for the disposition of signal SIG. * Return 1 if the process would somehow manage to survive signal SIG, * else return 0. This routine will never be called with SIGKILL. */intsigishandled(tcp, sig)struct tcb *tcp;int sig;{#ifdef LINUX int sfd; char sname[32]; char buf[1024]; char *s; int i; unsigned int signalled, blocked, ignored, caught; /* This is incredibly costly but it's worth it. */ sprintf(sname, "/proc/%d/stat", tcp->pid); if ((sfd = open(sname, O_RDONLY)) == -1) { perror(sname); return 1; } i = read(sfd, buf, 1024); buf[i] = '\0'; close(sfd); /* * Skip the extraneous fields. This loses if the * command name has any spaces in it. So be it. */ for (i = 0, s = buf; i < 30; i++) { while (*++s != ' ') { if (!*s) break; } } if (sscanf(s, "%u%u%u%u", &signalled, &blocked, &ignored, &caught) != 4) { fprintf(stderr, "/proc/pid/stat format error\n"); return 1; }#ifdef DEBUG fprintf(stderr, "sigs: %08x %08x %08x %08x\n", signalled, blocked, ignored, caught);#endif if ((ignored & sigmask(sig)) || (caught & sigmask(sig))) return 1;#endif /* LINUX */#ifdef SUNOS4 void (*u_signal)(); if (upeek(tcp->pid, uoff(u_signal[0]) + sig*sizeof(u_signal), (long *) &u_signal) < 0) { return 0; } if (u_signal != SIG_DFL) return 1;#endif /* SUNOS4 */#ifdef SVR4 /* * Since procfs doesn't interfere with wait I think it is safe * to punt on this question. If not, the information is there. */ return 1;#else /* !SVR4 */ switch (sig) { case SIGCONT: case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU: case SIGCHLD: case SIGIO:#if defined(SIGURG) && SIGURG != SIGIO case SIGURG:#endif case SIGWINCH: /* Gloria Gaynor says ... */ return 1; default: break; } return 0;#endif /* !SVR4 */}#if defined(SUNOS4) || defined(FREEBSD)intsys_sigvec(tcp)struct tcb *tcp;{ struct sigvec sv; long addr; if (entering(tcp)) { printsignal(tcp->u_arg[0]); tprintf(", "); addr = tcp->u_arg[1]; } else { addr = tcp->u_arg[2]; } if (addr == 0) tprintf("NULL"); else if (!verbose(tcp)) tprintf("%#lx", addr); else if (umove(tcp, addr, &sv) < 0) tprintf("{...}"); else { switch ((int) sv.sv_handler) { case (int) SIG_ERR: tprintf("{SIG_ERR}"); break; case (int) SIG_DFL: tprintf("{SIG_DFL}"); break; case (int) SIG_IGN: if (tcp->u_arg[0] == SIGTRAP) { tcp->flags |= TCB_SIGTRAPPED; kill(tcp->pid, SIGSTOP); } tprintf("{SIG_IGN}"); break; case (int) SIG_HOLD: if (tcp->u_arg[0] == SIGTRAP) { tcp->flags |= TCB_SIGTRAPPED; kill(tcp->pid, SIGSTOP); } tprintf("SIG_HOLD"); break; default: if (tcp->u_arg[0] == SIGTRAP) { tcp->flags |= TCB_SIGTRAPPED; kill(tcp->pid, SIGSTOP); } tprintf("{%#lx, ", (unsigned long) sv.sv_handler); printsigmask(&sv.sv_mask, 0); tprintf(", "); if (!printflags(sigvec_flags, sv.sv_flags)) tprintf("0"); tprintf("}"); } } if (entering(tcp)) tprintf(", "); return 0;}intsys_sigpause(tcp)struct tcb *tcp;{ if (entering(tcp)) { /* WTA: UD had a bug here: he forgot the braces */ sigset_t sigm; long_to_sigset(tcp->u_arg[0], &sigm); printsigmask(&sigm, 0); } return 0;}intsys_sigstack(tcp)struct tcb *tcp;{ struct sigstack ss; long addr; if (entering(tcp)) addr = tcp->u_arg[0]; else addr = tcp->u_arg[1]; if (addr == 0) tprintf("NULL"); else if (umove(tcp, addr, &ss) < 0) tprintf("%#lx", addr); else { tprintf("{ss_sp %#lx ", (unsigned long) ss.ss_sp); tprintf("ss_onstack %s}", ss.ss_onstack ? "YES" : "NO"); } if (entering(tcp)) tprintf(", "); return 0;}intsys_sigcleanup(tcp)struct tcb *tcp;{ return 0;}#endif /* SUNOS4 || FREEBSD */#ifndef SVR4intsys_sigsetmask(tcp)struct tcb *tcp;{ if (entering(tcp)) { sigset_t sigm; long_to_sigset(tcp->u_arg[0], &sigm);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -