procps 010114
This commit is contained in:
234
proc/sig.c
Normal file
234
proc/sig.c
Normal file
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright 1998 by Albert Cahalan; all rights resered.
|
||||
* This file may be used subject to the terms and conditions of the
|
||||
* GNU Library General Public License Version 2, or any later version
|
||||
* at your option, as published by the Free Software Foundation.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Library General Public License for more details.
|
||||
*/
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Linux signals:
|
||||
*
|
||||
* SIGSYS is required by Unix98.
|
||||
* SIGEMT is part of SysV, BSD, and ancient UNIX tradition.
|
||||
*
|
||||
* They are provided by these Linux ports: alpha, mips, sparc, and sparc64.
|
||||
* You get SIGSTKFLT and SIGUNUSED instead on i386, m68k, ppc, and arm.
|
||||
* (this is a Linux & libc bug -- both must be fixed)
|
||||
*
|
||||
* Total garbage: SIGIO SIGINFO SIGIOT SIGLOST SIGCLD
|
||||
* (popular ones are handled as aliases)
|
||||
* Nearly garbage: SIGSTKFLT SIGUNUSED (nothing else to fill slots)
|
||||
*/
|
||||
|
||||
/* Linux 2.3.29 replaces SIGUNUSED with the standard SIGSYS signal */
|
||||
#ifndef SIGSYS
|
||||
# warning Standards require that <signal.h> define SIGSYS
|
||||
# define SIGSYS SIGUNUSED
|
||||
#endif
|
||||
|
||||
/* If we see both, it is likely SIGSTKFLT (junk) was replaced. */
|
||||
#ifdef SIGEMT
|
||||
# undef SIGSTKFLT
|
||||
#endif
|
||||
|
||||
#ifndef SIGRTMIN
|
||||
# warning Standards require that <signal.h> define SIGRTMIN; assuming 32
|
||||
# define SIGRTMIN 32
|
||||
#endif
|
||||
|
||||
/* It seems the SPARC libc does not know the kernel supports SIGPWR. */
|
||||
#ifndef SIGPWR
|
||||
# warning Your header files lack SIGPWR. (assuming it is number 29)
|
||||
# define SIGPWR 29
|
||||
#endif
|
||||
|
||||
typedef struct mapstruct {
|
||||
char *name;
|
||||
int num;
|
||||
} mapstruct;
|
||||
|
||||
|
||||
static mapstruct sigtable[] = {
|
||||
{"ABRT", SIGABRT}, /* IOT */
|
||||
{"ALRM", SIGALRM},
|
||||
{"BUS", SIGBUS},
|
||||
{"CHLD", SIGCHLD}, /* CLD */
|
||||
{"CONT", SIGCONT},
|
||||
#ifdef SIGEMT
|
||||
{"EMT", SIGEMT},
|
||||
#endif
|
||||
{"FPE", SIGFPE},
|
||||
{"HUP", SIGHUP},
|
||||
{"ILL", SIGILL},
|
||||
{"INT", SIGINT},
|
||||
{"KILL", SIGKILL},
|
||||
{"PIPE", SIGPIPE},
|
||||
{"POLL", SIGPOLL}, /* IO */
|
||||
{"PROF", SIGPROF},
|
||||
{"PWR", SIGPWR},
|
||||
{"QUIT", SIGQUIT},
|
||||
{"SEGV", SIGSEGV},
|
||||
#ifdef SIGSTKFLT
|
||||
{"STKFLT", SIGSTKFLT},
|
||||
#endif
|
||||
{"STOP", SIGSTOP},
|
||||
{"SYS", SIGSYS}, /* UNUSED */
|
||||
{"TERM", SIGTERM},
|
||||
{"TRAP", SIGTRAP},
|
||||
{"TSTP", SIGTSTP},
|
||||
{"TTIN", SIGTTIN},
|
||||
{"TTOU", SIGTTOU},
|
||||
{"URG", SIGURG},
|
||||
{"USR1", SIGUSR1},
|
||||
{"USR2", SIGUSR2},
|
||||
{"VTALRM", SIGVTALRM},
|
||||
{"WINCH", SIGWINCH},
|
||||
{"XCPU", SIGXCPU},
|
||||
{"XFSZ", SIGXFSZ}
|
||||
};
|
||||
|
||||
static const int number_of_signals = sizeof(sigtable)/sizeof(mapstruct);
|
||||
|
||||
static int compare_signal_names(const void *a, const void *b){
|
||||
return strcasecmp( ((mapstruct*)a)->name, ((mapstruct*)b)->name );
|
||||
}
|
||||
|
||||
/* return -1 on failure */
|
||||
int signal_name_to_number(char *name){
|
||||
const mapstruct *ptr;
|
||||
mapstruct ms;
|
||||
long val;
|
||||
char *endp;
|
||||
int offset;
|
||||
|
||||
/* clean up name */
|
||||
if(!strncasecmp(name,"SIG",3)) name += 3;
|
||||
|
||||
if(!strcasecmp(name,"CLD")) return SIGCHLD;
|
||||
if(!strcasecmp(name,"IO")) return SIGPOLL;
|
||||
if(!strcasecmp(name,"IOT")) return SIGABRT;
|
||||
|
||||
/* search the table */
|
||||
ms.name = name;
|
||||
ptr = bsearch(&ms, sigtable, number_of_signals,
|
||||
sizeof(mapstruct), compare_signal_names
|
||||
);
|
||||
if(ptr) return ptr->num;
|
||||
|
||||
if(!strcasecmp(name,"RTMIN")) return SIGRTMIN;
|
||||
if(!strcasecmp(name,"EXIT")) return 0;
|
||||
if(!strcasecmp(name,"NULL")) return 0;
|
||||
|
||||
offset = 0;
|
||||
if(!strncasecmp(name,"RTMIN+",6)){
|
||||
name += 6;
|
||||
offset = SIGRTMIN;
|
||||
}
|
||||
|
||||
/* not found, so try as a number */
|
||||
val = strtol(name,&endp,10);
|
||||
if(*endp) return -1; /* not valid */
|
||||
if(val+SIGRTMIN>127) return -1; /* not valid */
|
||||
return val+offset;
|
||||
}
|
||||
|
||||
static const char *signal_number_to_name(int signo){
|
||||
static char buf[32];
|
||||
int n = number_of_signals;
|
||||
signo &= 0x7f; /* need to process exit values too */
|
||||
while(n--){
|
||||
if(sigtable[n].num==signo) return sigtable[n].name;
|
||||
}
|
||||
if(signo == SIGRTMIN) return "RTMIN";
|
||||
if(signo) sprintf(buf, "RTMIN+%d", signo-SIGRTMIN);
|
||||
else strcpy(buf,"0"); /* AIX has NULL; Solaris has EXIT */
|
||||
return buf;
|
||||
}
|
||||
|
||||
int print_given_signals(int argc, char *argv[], int max_line){
|
||||
char buf[1280]; /* 128 signals, "RTMIN+xx" is largest */
|
||||
int ret = 0; /* to be used as exit code by caller */
|
||||
int place = 0; /* position on this line */
|
||||
int amt;
|
||||
if(argc > 128) return 1;
|
||||
while(argc--){
|
||||
char tmpbuf[16];
|
||||
char *txt; /* convenient alias */
|
||||
txt = *argv;
|
||||
if(*txt >= '0' && *txt <= '9'){
|
||||
long val;
|
||||
char *endp;
|
||||
val = strtol(txt,&endp,10);
|
||||
if(*endp){
|
||||
fprintf(stderr, "Signal \"%s\" not known.\n", txt);
|
||||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
amt = sprintf(tmpbuf, "%s", signal_number_to_name(val));
|
||||
}else{
|
||||
int sno;
|
||||
sno = signal_name_to_number(txt);
|
||||
if(sno == -1){
|
||||
fprintf(stderr, "Signal \"%s\" not known.\n", txt);
|
||||
ret = 1;
|
||||
goto end;
|
||||
}
|
||||
amt = sprintf(tmpbuf, "%d", sno);
|
||||
}
|
||||
|
||||
if(!place){
|
||||
strcpy(buf,tmpbuf);
|
||||
place = amt;
|
||||
goto end;
|
||||
}
|
||||
if(amt+place+1 > max_line){
|
||||
printf("%s\n", buf);
|
||||
strcpy(buf,tmpbuf);
|
||||
place = amt;
|
||||
goto end;
|
||||
}
|
||||
sprintf(buf+place, " %s", tmpbuf);
|
||||
place += amt+1;
|
||||
end:
|
||||
argv++;
|
||||
}
|
||||
if(place) printf("%s\n", buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pretty_print_signals(void){
|
||||
int i = 0;
|
||||
while(++i <= number_of_signals){
|
||||
int n;
|
||||
n = printf("%2d %s", i, signal_number_to_name(i));
|
||||
if(i%7) printf(" \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + n);
|
||||
else printf("\n");
|
||||
}
|
||||
if((i-1)%7) printf("\n");
|
||||
}
|
||||
|
||||
void unix_print_signals(void){
|
||||
int pos = 0;
|
||||
int i = 0;
|
||||
while(++i <= number_of_signals){
|
||||
if(i-1) printf("%c", (pos>73)?(pos=0,'\n'):(pos++,' ') );
|
||||
pos += printf("%s", signal_number_to_name(i));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* sanity check */
|
||||
static int init_signal_list(void) __attribute__((constructor));
|
||||
static int init_signal_list(void){
|
||||
if(number_of_signals != 31){
|
||||
fprintf(stderr, "WARNING: %d signals -- adjust and recompile.\n", number_of_signals);
|
||||
}
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user