linux上的错误号与系统有关。出于这个原因,作者
license
编写了一个脚本来构建与错误号对应的名称数组。在系统上运行时,脚本将根据该系统上的错误号构建阵列。该脚本显示在下面的代码块中。
CODE ---------------------------------------------- ------------
The Linux Programming Interface
RESULT ---------------------------------------------- --------------
#!/bin/sh
#
# Create a new version of the file ename.c.inc by parsing symbolic
# error names defined in errno.h
#
echo '#include <errno.h>' | cpp -dM |
sed -n -e '/#define *E/s/#define *//p' |sort -k2n |
awk '
BEGIN {
entries_per_line = 4
line_len = 68;
last = 0;
varname =" enames";
print "static char *ename[] = {";
line = " /* 0 */ \"\"";
}
{
if ($2 ~ /^E[A-Z0-9]*$/) { # These entries are sorted at top
synonym[$1] = $2;
} else {
while (last + 1 < $2) {
last++;
line = line ", ";
if (length(line ename) > line_len || last == 1) {
print line;
line = " /* " last " */ ";
line = sprintf(" /* %3d */ ", last);
}
line = line "\"" "\"" ;
}
last = $2;
ename = $1;
for (k in synonym)
if (synonym[k] == $1) ename = ename "/" k;
line = line ", ";
if (length(line ename) > line_len || last == 1) {
print line;
line = " /* " last " */ ";
line = sprintf(" /* %3d */ ", last);;
}
line = line "\"" ename "\"" ;
}
}
END {
print line;
print "};"
print "";
print "#define MAX_ENAME " last;
}
'
Linux上的信号编号也与系统有关,我想使用类似的脚本生成一组信号名称。我怎么能这样做?
答案 0 :(得分:0)
我使用的脚本就是这个Perl脚本:
#!/usr/bin/env perl
#
# @(#)$Id: gensignal.pl,v 1.2 2013/05/31 20:56:27 jleffler Exp $
#
# Generate table of signal number constants from given file(s)
use warnings;
use strict;
use File::Temp qw( tempfile );
my %symlist;
my $maxsymlen = 0;
my $maxmsglen = 0;
die qq{Usage: $0 signal.h 'compiler and flags'\n} unless scalar(@ARGV) == 2;
my $header = $ARGV[0];
my $command = "$ARGV[1] -H -c";
my ($tfh, $name) = tempfile("gensignal-XXXXXX", SUFFIX => '.c', DIR => '.', UNLINK => 1);
print $tfh "#include <$header>\n";
close $tfh;
my @headers;
open my $nfh, "-|", "$command $name 2>&1" or die "Failed to execute command $command $name";
while (<$nfh>)
{
chomp;
next unless m/^\./;
s/^\.+ //;
push @headers, $_;
}
close $nfh;
$name =~ s/\.c$/.o/;
unlink $name;
@ARGV = @headers;
while (<>)
{
next unless m%^\s*#\s*define\s+(SIG[A-Z0-9a-z]+)\s+(\d+)\s*/\*\s*([A-Za-z].*\S)\s*\*/%;
$symlist{$1} = { number => $2, message => $3 };
$maxsymlen = length($1) if length($1) > $maxsymlen;
$maxmsglen = length($3) if length($3) > $maxmsglen;
}
my $format = sprintf " { %%-%ds %%-%ds %%-5s %%-%ds },\n", $maxsymlen + 3, $maxsymlen + 1, $maxmsglen + 2;
foreach my $key (sort keys %symlist)
{
my $name = qq{"$key",};
my $symbol = qq{$key,};
my $number = qq{$symlist{$key}->{number},};
my $message = qq{"$symlist{$key}->{message}"};
print "#ifdef $key\n";
printf $format, $name, $symbol, $number, $message;
print "#endif\n";
}
它需要与GCC兼容的编译器 - 它使用-H
选项生成头文件列表。
在Ubuntu 16.04上,输出为:
#ifdef SIGABRT
{ "SIGABRT", SIGABRT, 6, "Abort (ANSI)." },
#endif
#ifdef SIGALRM
{ "SIGALRM", SIGALRM, 14, "Alarm clock (POSIX)." },
#endif
#ifdef SIGBUS
{ "SIGBUS", SIGBUS, 7, "BUS error (4.2 BSD)." },
#endif
#ifdef SIGCHLD
{ "SIGCHLD", SIGCHLD, 17, "Child status has changed (POSIX)." },
#endif
#ifdef SIGCONT
{ "SIGCONT", SIGCONT, 18, "Continue (POSIX)." },
#endif
#ifdef SIGFPE
{ "SIGFPE", SIGFPE, 8, "Floating-point exception (ANSI)." },
#endif
#ifdef SIGHUP
{ "SIGHUP", SIGHUP, 1, "Hangup (POSIX)." },
#endif
#ifdef SIGILL
{ "SIGILL", SIGILL, 4, "Illegal instruction (ANSI)." },
#endif
#ifdef SIGINT
{ "SIGINT", SIGINT, 2, "Interrupt (ANSI)." },
#endif
#ifdef SIGIO
{ "SIGIO", SIGIO, 29, "I/O now possible (4.2 BSD)." },
#endif
#ifdef SIGIOT
{ "SIGIOT", SIGIOT, 6, "IOT trap (4.2 BSD)." },
#endif
#ifdef SIGKILL
{ "SIGKILL", SIGKILL, 9, "Kill, unblockable (POSIX)." },
#endif
#ifdef SIGPIPE
{ "SIGPIPE", SIGPIPE, 13, "Broken pipe (POSIX)." },
#endif
#ifdef SIGPROF
{ "SIGPROF", SIGPROF, 27, "Profiling alarm clock (4.2 BSD)." },
#endif
#ifdef SIGPWR
{ "SIGPWR", SIGPWR, 30, "Power failure restart (System V)." },
#endif
#ifdef SIGQUIT
{ "SIGQUIT", SIGQUIT, 3, "Quit (POSIX)." },
#endif
#ifdef SIGSEGV
{ "SIGSEGV", SIGSEGV, 11, "Segmentation violation (ANSI)." },
#endif
#ifdef SIGSTKFLT
{ "SIGSTKFLT", SIGSTKFLT, 16, "Stack fault." },
#endif
#ifdef SIGSTOP
{ "SIGSTOP", SIGSTOP, 19, "Stop, unblockable (POSIX)." },
#endif
#ifdef SIGSYS
{ "SIGSYS", SIGSYS, 31, "Bad system call." },
#endif
#ifdef SIGTERM
{ "SIGTERM", SIGTERM, 15, "Termination (ANSI)." },
#endif
#ifdef SIGTRAP
{ "SIGTRAP", SIGTRAP, 5, "Trace trap (POSIX)." },
#endif
#ifdef SIGTSTP
{ "SIGTSTP", SIGTSTP, 20, "Keyboard stop (POSIX)." },
#endif
#ifdef SIGTTIN
{ "SIGTTIN", SIGTTIN, 21, "Background read from tty (POSIX)." },
#endif
#ifdef SIGTTOU
{ "SIGTTOU", SIGTTOU, 22, "Background write to tty (POSIX)." },
#endif
#ifdef SIGURG
{ "SIGURG", SIGURG, 23, "Urgent condition on socket (4.2 BSD)." },
#endif
#ifdef SIGUSR1
{ "SIGUSR1", SIGUSR1, 10, "User-defined signal 1 (POSIX)." },
#endif
#ifdef SIGUSR2
{ "SIGUSR2", SIGUSR2, 12, "User-defined signal 2 (POSIX)." },
#endif
#ifdef SIGVTALRM
{ "SIGVTALRM", SIGVTALRM, 26, "Virtual alarm clock (4.2 BSD)." },
#endif
#ifdef SIGWINCH
{ "SIGWINCH", SIGWINCH, 28, "Window size change (4.3 BSD, Sun)." },
#endif
#ifdef SIGXCPU
{ "SIGXCPU", SIGXCPU, 24, "CPU limit exceeded (4.2 BSD)." },
#endif
#ifdef SIGXFSZ
{ "SIGXFSZ", SIGXFSZ, 25, "File size limit exceeded (4.2 BSD)." },
#endif
您将获得标题中记录的信号名称(按排序顺序),符号,数字及其含义。
该信息应保存在gensignal.h
中,然后可以编译以下代码:
/*
@(#)File: $RCSfile: signal.c,v $
@(#)Version: $Revision: 1.12 $
@(#)Last changed: $Date: 2016/03/24 21:42:19 $
@(#)Purpose: Print messages corresponding to signal number or name
@(#)Author: J Leffler
@(#)Copyright: (C) JLSS 2012-13,2015-16
*/
/*TABSTOP=4*/
#define MAIN_PROGRAM
#ifndef _GNU_SOURCE
#define _GNU_SOURCE /* Linux */
#endif
#ifndef _DARWIN_C_SOURCE
#define _DARWIN_C_SOURCE /* Mac OS X */
#endif
/* Need O/S specific messages as well as POSIX messages */
/* Do not #include "posixver.h" */
#include <ctype.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "emalloc.h"
#include "jlss.h"
#include "range.h"
#include "stderr.h"
typedef struct sig_info
{
const char *sigsym; /* Signal symbol - "EINTR" */
int signum; /* Signal number - EINTR */
int sigdef; /* Signal define - 4 */
const char *sigmsg; /* Signal message - Interrupted system call */
} sig_info;
/*
** Generate gensignal.h using:
** perl gensignal.pl /usr/include/sys/signal.h > gensignal.h
** NB: list must be sorted alphabetically on symbol name
*/
static const sig_info sig_msgs[] =
{
#include "gensignal.h"
};
static const sig_info sig_zero = { "SIGNONE", 0, 0, "No signal" };
static const char optstr[] = "hlqV";
static const char usestr[] = "[-hlqV] [lo[:hi] ...]";
static const char hlpstr[] =
" -h Print help and exit\n"
" -l Print list of all signals\n"
" -q Validate signal but don't print messages\n"
" -V Print version and exit\n"
;
#define DIM(x) (sizeof(x)/sizeof(*(x)))
static const sig_info *sig_nums[DIM(sig_msgs)];
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
extern const char jlss_id_signal_c[];
const char jlss_id_signal_c[] = "@(#)$Id: signal.c,v 1.12 2016/03/24 21:42:19 jleffler Exp $";
#endif /* lint */
static int cmp_sig_number(const void *v1, const void *v2)
{
int e1 = (*((const sig_info * const *)v1))->signum;
int e2 = (*((const sig_info * const *)v2))->signum;
return(e1 - e2);
}
static void map_numbers(void)
{
for (size_t i = 0; i < DIM(sig_msgs); i++)
sig_nums[i] = &sig_msgs[i];
qsort(sig_nums, DIM(sig_nums), sizeof(*sig_nums), cmp_sig_number);
}
static const sig_info *sig_info_number(int num)
{
sig_info lookfor = { 0, num, 0, 0 };
sig_info *lookptr = &lookfor;
const sig_info **found = bsearch(&lookptr, sig_nums, DIM(sig_nums), sizeof(*sig_nums), cmp_sig_number);
return((found != 0) ? *found : 0);
}
static int cmp_sig_symbol(const void *v1, const void *v2)
{
const char *s1 = ((const sig_info *)v1)->sigsym;
const char *s2 = ((const sig_info *)v2)->sigsym;
return(strcmp(s1, s2));
}
static int pr_string_signal(const char *arg, int qflag)
{
int estat = EXIT_SUCCESS;
char *name = estrdup(arg);
sig_info lookfor = { name, 0, 0, 0 };
strupper(name);
if (strncmp(name, "SIG", sizeof("SIG")-1) != 0)
{
free(name);
name = MALLOC(strlen(arg) + sizeof("SIG"));
strcpy(name, "SIG");
strcpy(name + sizeof("SIG") - 1, arg);
strupper(name);
}
const sig_info *found = bsearch(&lookfor, sig_msgs, DIM(sig_msgs), sizeof(*sig_msgs), cmp_sig_symbol);
if (found == 0)
{
if (qflag == 0)
err_remark("unrecognized symbol %s\n", arg);
estat = EXIT_FAILURE;
}
else if (qflag == 0)
printf("%s (%d): %s\n", found->sigsym, found->signum, found->sigmsg);
free(name);
return(estat);
}
static int pr_signals_range(int lo, int hi, int qflag)
{
int estat = EXIT_SUCCESS;
for (int msg = lo; msg <= hi; msg++)
{
const sig_info *info = (msg == 0) ? &sig_zero : sig_info_number(msg);
if (info == 0)
{
if (qflag == 0)
err_remark("no name for signal = %d\n", msg);
estat = EXIT_FAILURE;
}
else if (qflag == 0)
printf("%d (%s): %s\n", msg, info->sigsym, info->sigmsg);
}
return estat;
}
static int pr_number_signal(const char *arg, int qflag)
{
int estat = EXIT_FAILURE;
long lo;
long hi;
const char *endp;
const char *ptr = arg;
int max_sig = sig_nums[DIM(sig_msgs)-1]->signum;
while ((endp = numeric_range(ptr, &lo, &hi)) != 0)
{
if (endp == ptr)
{
err_remark("Invalid range specified (%s) - should be lo[:hi]\n", ptr);
break;
}
else if (lo < 0 || lo > max_sig || hi < 0 || hi > max_sig || lo > hi)
{
if (lo != hi)
err_remark("Invalid signal number range %ld:%ld (valid range is 0:%d)\n",
lo, hi, max_sig);
else
err_remark("Invalid signal number %ld (valid range is 0:%d)\n",
hi, max_sig);
}
else
estat = pr_signals_range((int)lo, (int)hi, qflag);
ptr = endp;
}
return(estat);
}
static int pr_signal(char *arg, int qflag)
{
int estat;
if (isalpha(*arg))
estat = pr_string_signal(arg, qflag);
else
estat = pr_number_signal(arg, qflag);
return(estat);
}
static void list_signals(void)
{
for (size_t i = 0; i < DIM(sig_msgs); i++)
{
char number[10];
snprintf(number, sizeof(number), "%d", sig_nums[i]->signum);
pr_number_signal(number, 0);
}
}
int main(int argc, char **argv)
{
int i;
int opt;
int nstat;
int estat = EXIT_SUCCESS;
int qflag = 0;
int lflag = 0;
err_setarg0(argv[0]);
map_numbers();
while ((opt = getopt(argc, argv, optstr)) != EOF)
{
switch (opt)
{
case 'l':
if (qflag)
err_error("Cannot set both -l and -q options\n");
lflag = 1;
break;
case 'q':
if (lflag)
err_error("Cannot set both -l and -q options\n");
qflag = 1;
break;
case 'V':
err_version("SIGNAL", "$Revision: 1.12 $ ($Date: 2016/03/24 21:42:19 $)");
/*NOTREACHED*/
case 'h':
err_help(usestr, hlpstr);
/*NOTREACHED*/
default:
err_usage(usestr);
/*NOTREACHED*/
}
}
if (lflag)
{
if (optind != argc)
err_usage(usestr);
list_signals();
}
else
{
if (optind >= argc)
err_usage(usestr);
for (i = optind; i < argc; i++)
{
nstat = pr_signal(argv[i], qflag);
if (nstat == EXIT_FAILURE)
estat = nstat;
}
}
return(estat);
}
您需要从https://github.com/jleffler/soq/tree/master/src/libsoq获取一堆库函数:
posixver.h
debug.h
emalloc.c
emalloc.h
errhelp.c
estrdup.c
jlss.h
kludge.h
range.h
range2.c
stderr.h
stderr.c
strupper.c
运行时,它会产生(例如):
$ signal hup 3
SIGHUP (1): Hangup (POSIX).
3 (SIGQUIT): Quit (POSIX).
$