⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 signal.c

📁 linux进程跟踪的工具和源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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 + -