Since we're comparing the return value to a smallish integer anyway, we might as well use that bb_strtou() returns UINT_MAX for malformed input. Referencing errno is kinda bloaty on glibc. While NSIG is not in POSIX, we do already rely on it being defined, compile-time const and smallish, since arrays in struct globals_misc are defined in terms of it. function old new delta get_signum 312 286 -26 Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
		
			
				
	
	
		
			270 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			270 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* vi: set sw=4 ts=4: */
 | 
						|
/*
 | 
						|
 * Signal name/number conversion routines.
 | 
						|
 *
 | 
						|
 * Copyright 2006 Rob Landley <rob@landley.net>
 | 
						|
 *
 | 
						|
 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
 | 
						|
 */
 | 
						|
//config:config FEATURE_RTMINMAX
 | 
						|
//config:	bool "Support RTMIN[+n] and RTMAX[-n] signal names"
 | 
						|
//config:	default y
 | 
						|
//config:	help
 | 
						|
//config:	Support RTMIN[+n] and RTMAX[-n] signal names
 | 
						|
//config:	in kill, killall etc. This costs ~250 bytes.
 | 
						|
//config:
 | 
						|
//config:config FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS
 | 
						|
//config:	bool "Use the definitions of SIGRTMIN/SIGRTMAX provided by libc"
 | 
						|
//config:	default y
 | 
						|
//config:	depends on FEATURE_RTMINMAX
 | 
						|
//config:	help
 | 
						|
//config:	Some C libraries reserve a few real-time signals for internal
 | 
						|
//config:	use, and adjust the values of SIGRTMIN/SIGRTMAX seen by
 | 
						|
//config:	applications accordingly. Saying yes here means that a signal
 | 
						|
//config:	name RTMIN+n will be interpreted according to the libc definition
 | 
						|
//config:	of SIGRTMIN, and not the raw definition provided by the kernel.
 | 
						|
//config:	This behavior matches "kill -l RTMIN+n" from bash.
 | 
						|
 | 
						|
#include "libbb.h"
 | 
						|
 | 
						|
/* Believe it or not, but some arches have more than 32 SIGs!
 | 
						|
 * HPPA: SIGSTKFLT == 36. */
 | 
						|
 | 
						|
static const char signals[][7] ALIGN1 = {
 | 
						|
	// SUSv3 says kill must support these, and specifies the numerical values,
 | 
						|
	// http://www.opengroup.org/onlinepubs/009695399/utilities/kill.html
 | 
						|
	// {0, "EXIT"}, {1, "HUP"}, {2, "INT"}, {3, "QUIT"},
 | 
						|
	// {6, "ABRT"}, {9, "KILL"}, {14, "ALRM"}, {15, "TERM"}
 | 
						|
	// And Posix adds the following:
 | 
						|
	// {SIGILL, "ILL"}, {SIGTRAP, "TRAP"}, {SIGFPE, "FPE"}, {SIGUSR1, "USR1"},
 | 
						|
	// {SIGSEGV, "SEGV"}, {SIGUSR2, "USR2"}, {SIGPIPE, "PIPE"}, {SIGCHLD, "CHLD"},
 | 
						|
	// {SIGCONT, "CONT"}, {SIGSTOP, "STOP"}, {SIGTSTP, "TSTP"}, {SIGTTIN, "TTIN"},
 | 
						|
	// {SIGTTOU, "TTOU"}
 | 
						|
 | 
						|
	[0] = "EXIT",
 | 
						|
#ifdef SIGHUP
 | 
						|
	[SIGHUP   ] = "HUP",
 | 
						|
#endif
 | 
						|
#ifdef SIGINT
 | 
						|
	[SIGINT   ] = "INT",
 | 
						|
#endif
 | 
						|
#ifdef SIGQUIT
 | 
						|
	[SIGQUIT  ] = "QUIT",
 | 
						|
#endif
 | 
						|
#ifdef SIGILL
 | 
						|
	[SIGILL   ] = "ILL",
 | 
						|
#endif
 | 
						|
#ifdef SIGTRAP
 | 
						|
	[SIGTRAP  ] = "TRAP",
 | 
						|
#endif
 | 
						|
#ifdef SIGABRT
 | 
						|
	[SIGABRT  ] = "ABRT",
 | 
						|
#endif
 | 
						|
#ifdef SIGBUS
 | 
						|
	[SIGBUS   ] = "BUS",
 | 
						|
#endif
 | 
						|
#ifdef SIGFPE
 | 
						|
	[SIGFPE   ] = "FPE",
 | 
						|
#endif
 | 
						|
#ifdef SIGKILL
 | 
						|
	[SIGKILL  ] = "KILL",
 | 
						|
#endif
 | 
						|
#ifdef SIGUSR1
 | 
						|
	[SIGUSR1  ] = "USR1",
 | 
						|
#endif
 | 
						|
#ifdef SIGSEGV
 | 
						|
	[SIGSEGV  ] = "SEGV",
 | 
						|
#endif
 | 
						|
#ifdef SIGUSR2
 | 
						|
	[SIGUSR2  ] = "USR2",
 | 
						|
#endif
 | 
						|
#ifdef SIGPIPE
 | 
						|
	[SIGPIPE  ] = "PIPE",
 | 
						|
#endif
 | 
						|
#ifdef SIGALRM
 | 
						|
	[SIGALRM  ] = "ALRM",
 | 
						|
#endif
 | 
						|
#ifdef SIGTERM
 | 
						|
	[SIGTERM  ] = "TERM",
 | 
						|
#endif
 | 
						|
#ifdef SIGSTKFLT
 | 
						|
	[SIGSTKFLT] = "STKFLT",
 | 
						|
#endif
 | 
						|
#ifdef SIGCHLD
 | 
						|
	[SIGCHLD  ] = "CHLD",
 | 
						|
#endif
 | 
						|
#ifdef SIGCONT
 | 
						|
	[SIGCONT  ] = "CONT",
 | 
						|
#endif
 | 
						|
#ifdef SIGSTOP
 | 
						|
	[SIGSTOP  ] = "STOP",
 | 
						|
#endif
 | 
						|
#ifdef SIGTSTP
 | 
						|
	[SIGTSTP  ] = "TSTP",
 | 
						|
#endif
 | 
						|
#ifdef SIGTTIN
 | 
						|
	[SIGTTIN  ] = "TTIN",
 | 
						|
#endif
 | 
						|
#ifdef SIGTTOU
 | 
						|
	[SIGTTOU  ] = "TTOU",
 | 
						|
#endif
 | 
						|
#ifdef SIGURG
 | 
						|
	[SIGURG   ] = "URG",
 | 
						|
#endif
 | 
						|
#ifdef SIGXCPU
 | 
						|
	[SIGXCPU  ] = "XCPU",
 | 
						|
#endif
 | 
						|
#ifdef SIGXFSZ
 | 
						|
	[SIGXFSZ  ] = "XFSZ",
 | 
						|
#endif
 | 
						|
#ifdef SIGVTALRM
 | 
						|
	[SIGVTALRM] = "VTALRM",
 | 
						|
#endif
 | 
						|
#ifdef SIGPROF
 | 
						|
	[SIGPROF  ] = "PROF",
 | 
						|
#endif
 | 
						|
#ifdef SIGWINCH
 | 
						|
	[SIGWINCH ] = "WINCH",
 | 
						|
#endif
 | 
						|
#ifdef SIGPOLL
 | 
						|
	[SIGPOLL  ] = "POLL",
 | 
						|
#endif
 | 
						|
#ifdef SIGPWR
 | 
						|
	[SIGPWR   ] = "PWR",
 | 
						|
#endif
 | 
						|
#ifdef SIGSYS
 | 
						|
	[SIGSYS   ] = "SYS",
 | 
						|
#endif
 | 
						|
#if ENABLE_FEATURE_RTMINMAX && !ENABLE_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS
 | 
						|
# ifdef __SIGRTMIN
 | 
						|
	[__SIGRTMIN] = "RTMIN",
 | 
						|
# endif
 | 
						|
// This makes array about x2 bigger.
 | 
						|
// More compact approach is to special-case SIGRTMAX in print_signames()
 | 
						|
//# ifdef __SIGRTMAX
 | 
						|
//	[__SIGRTMAX] = "RTMAX",
 | 
						|
//# endif
 | 
						|
#endif
 | 
						|
};
 | 
						|
 | 
						|
// Convert signal name to number.
 | 
						|
 | 
						|
int FAST_FUNC get_signum(const char *name)
 | 
						|
{
 | 
						|
	unsigned i;
 | 
						|
 | 
						|
	/* bb_strtou returns UINT_MAX on error. NSIG is smaller
 | 
						|
	 * than UINT_MAX on any sane Unix. Hence no need
 | 
						|
	 * to check errno after bb_strtou().
 | 
						|
	 */
 | 
						|
	i = bb_strtou(name, NULL, 10);
 | 
						|
	if (i < NSIG) /* for shells, we allow 0 too */
 | 
						|
		return i;
 | 
						|
	if (strncasecmp(name, "SIG", 3) == 0)
 | 
						|
		name += 3;
 | 
						|
	for (i = 0; i < ARRAY_SIZE(signals); i++)
 | 
						|
		if (strcasecmp(name, signals[i]) == 0)
 | 
						|
			return i;
 | 
						|
 | 
						|
#if ENABLE_DESKTOP
 | 
						|
# if defined(SIGIOT) || defined(SIGIO)
 | 
						|
	/* SIGIO[T] are aliased to other names,
 | 
						|
	 * thus cannot be stored in the signals[] array.
 | 
						|
	 * Need special code to recognize them */
 | 
						|
	if ((name[0] | 0x20) == 'i' && (name[1] | 0x20) == 'o') {
 | 
						|
#  ifdef SIGIO
 | 
						|
		if (!name[2])
 | 
						|
			return SIGIO;
 | 
						|
#  endif
 | 
						|
#  ifdef SIGIOT
 | 
						|
		if ((name[2] | 0x20) == 't' && !name[3])
 | 
						|
			return SIGIOT;
 | 
						|
#  endif
 | 
						|
	}
 | 
						|
# endif
 | 
						|
#endif
 | 
						|
 | 
						|
#if ENABLE_FEATURE_RTMINMAX && defined(SIGRTMIN) && defined(SIGRTMAX)
 | 
						|
	{
 | 
						|
# if ENABLE_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS
 | 
						|
		/* Use the libc provided values. */
 | 
						|
		unsigned sigrtmin = SIGRTMIN;
 | 
						|
		unsigned sigrtmax = SIGRTMAX;
 | 
						|
# else
 | 
						|
	/* Use the "raw" SIGRTMIN/MAX. Underscored names, if exist, provide
 | 
						|
	 * them. If they don't exist, fall back to non-underscored ones: */
 | 
						|
#  if !defined(__SIGRTMIN)
 | 
						|
#   define __SIGRTMIN SIGRTMIN
 | 
						|
#  endif
 | 
						|
#  if !defined(__SIGRTMAX)
 | 
						|
#   define __SIGRTMAX SIGRTMAX
 | 
						|
#  endif
 | 
						|
 | 
						|
#  define sigrtmin __SIGRTMIN
 | 
						|
#  define sigrtmax __SIGRTMAX
 | 
						|
# endif
 | 
						|
		if (strncasecmp(name, "RTMIN", 5) == 0) {
 | 
						|
			if (!name[5])
 | 
						|
				return sigrtmin;
 | 
						|
			if (name[5] == '+') {
 | 
						|
				i = bb_strtou(name + 6, NULL, 10);
 | 
						|
				if (i <= sigrtmax - sigrtmin)
 | 
						|
					return sigrtmin + i;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else if (strncasecmp(name, "RTMAX", 5) == 0) {
 | 
						|
			if (!name[5])
 | 
						|
				return sigrtmax;
 | 
						|
			if (name[5] == '-') {
 | 
						|
				i = bb_strtou(name + 6, NULL, 10);
 | 
						|
				if (i <= sigrtmax - sigrtmin)
 | 
						|
					return sigrtmax - i;
 | 
						|
			}
 | 
						|
		}
 | 
						|
# undef sigrtmin
 | 
						|
# undef sigrtmax
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
	return -1;
 | 
						|
}
 | 
						|
 | 
						|
// Convert signal number to name
 | 
						|
 | 
						|
const char* FAST_FUNC get_signame(int number)
 | 
						|
{
 | 
						|
	if ((unsigned)number < ARRAY_SIZE(signals)) {
 | 
						|
		if (signals[number][0]) /* if it's not an empty str */
 | 
						|
			return signals[number];
 | 
						|
	}
 | 
						|
 | 
						|
	return itoa(number);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Print the whole signal list
 | 
						|
 | 
						|
void FAST_FUNC print_signames(void)
 | 
						|
{
 | 
						|
	unsigned signo;
 | 
						|
 | 
						|
	for (signo = 1; signo < ARRAY_SIZE(signals); signo++) {
 | 
						|
		const char *name = signals[signo];
 | 
						|
		if (name[0])
 | 
						|
			printf("%2u) %s\n", signo, name);
 | 
						|
	}
 | 
						|
#if ENABLE_FEATURE_RTMINMAX
 | 
						|
# if ENABLE_FEATURE_RTMINMAX_USE_LIBC_DEFINITIONS
 | 
						|
#  if defined(SIGRTMIN) && defined(SIGRTMAX)
 | 
						|
	printf("%2u) %s\n", SIGRTMIN, "RTMIN");
 | 
						|
	printf("%2u) %s\n", SIGRTMAX, "RTMAX");
 | 
						|
#  endif
 | 
						|
# else
 | 
						|
// __SIGRTMIN is included in signals[] array.
 | 
						|
#  ifdef __SIGRTMAX
 | 
						|
	printf("%2u) %s\n", __SIGRTMAX, "RTMAX");
 | 
						|
#  endif
 | 
						|
# endif
 | 
						|
#endif
 | 
						|
}
 |