2017-09-05 57 views
1

linux上的错误编号与系统有关。由于这个原因,作者 The Linux Programming Interface写了一个脚本来建立一个与错误号相对应的名字的数组。在系统上运行时,脚本将根据该系统上的错误编号构建阵列。该脚本显示在下面的代码块中。如何在Linux上构建一个信号名称数组?

CODE --------------------------------------------- -------------

#!/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; 
} 
' 

结果----------------------------- -------------------------------

static char *ename[] = { 
0 */ "", 
1 */ "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO", "ENXIO", "E2BIG", 
8 */ "ENOEXEC", "EBADF", "ECHILD", "EAGAIN/EWOULDBLOCK", "ENOMEM", 
13 */ "EACCES", "EFAULT", "ENOTBLK", "EBUSY", "EEXIST", "EXDEV", 
. 
. 
. 
. 
. 
. 
129 */ "EKEYREJECTED", "EOWNERDEAD", "ENOTRECOVERABLE", "ERFKILL" 
}; 
#define MAX_ENAME 132 

Linux上的信号数量也是系统相关的,I希望使用类似的脚本来生成一组信号名称。我怎样才能做到这一点?

+0

删除引号和替换'int'类型。 –

+0

你怎么称呼剧本?我的意思是你将哪些输入文件传递给awk命令? – hek2mgl

+0

信号常量在文件“signal.h”中定义。 – joenatech7

回答

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). 
$ 
+0

为什么你需要SIGABRT和6? –

+0

@ n.m。该程序不需要信号编号的数字和符号值,但是人们更容易看到'SIGABRT'是信号6,如果数据是这样的话 - 特别是因为事情没有按信号编号排序。这是故意的,控制冗余。 –