libexplain  1.4.D001
libexplain/buffer/signal.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2009, 2010, 2013 Peter Miller
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU Lesser General Public License as
00007  * published by the Free Software Foundation; either version 3 of the
00008  * License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include <libexplain/ac/signal.h>
00020 #include <libexplain/ac/string.h>
00021 
00022 #include <libexplain/buffer/signal.h>
00023 #include <libexplain/parse_bits.h>
00024 #include <libexplain/sizeof.h>
00025 
00026 
00027 static explain_parse_bits_table_t table[] =
00028 {
00029 #ifdef SIGHUP
00030     { "SIGHUP", SIGHUP },
00031 #endif
00032 #ifdef SIGINT
00033     { "SIGINT", SIGINT },
00034 #endif
00035 #ifdef SIGQUIT
00036     { "SIGQUIT", SIGQUIT },
00037 #endif
00038 #ifdef SIGILL
00039     { "SIGILL", SIGILL },
00040 #endif
00041 #ifdef SIGABRT
00042     { "SIGABRT", SIGABRT },
00043 #endif
00044 #ifdef SIGFPE
00045     { "SIGFPE", SIGFPE },
00046 #endif
00047 #ifdef SIGKILL
00048     { "SIGKILL", SIGKILL },
00049 #endif
00050 #ifdef SIGSEGV
00051     { "SIGSEGV", SIGSEGV },
00052 #endif
00053 #ifdef SIGPIPE
00054     { "SIGPIPE", SIGPIPE },
00055 #endif
00056 #ifdef SIGALRM
00057     { "SIGALRM", SIGALRM },
00058 #endif
00059 #ifdef SIGTERM
00060     { "SIGTERM", SIGTERM },
00061 #endif
00062 #ifdef SIGUSR1
00063     { "SIGUSR1", SIGUSR1 },
00064 #endif
00065 #ifdef SIGUSR2
00066     { "SIGUSR2", SIGUSR2 },
00067 #endif
00068 #ifdef SIGCHLD
00069     { "SIGCHLD", SIGCHLD },
00070 #endif
00071 #ifdef SIGCONT
00072     { "SIGCONT", SIGCONT },
00073 #endif
00074 #ifdef SIGSTOP
00075     { "SIGSTOP", SIGSTOP },
00076 #endif
00077 #ifdef SIGTSTP
00078     { "SIGTSTP", SIGTSTP },
00079 #endif
00080 #ifdef SIGTTIN
00081     { "SIGTTIN", SIGTTIN },
00082 #endif
00083 #ifdef SIGTTOU
00084     { "SIGTTOU", SIGTTOU },
00085 #endif
00086 
00087 #ifdef SIGBUS
00088     { "SIGBUS", SIGBUS },
00089 #endif
00090 #ifdef SIGPOLL
00091     { "SIGPOLL", SIGPOLL },
00092 #endif
00093 #ifdef SIGPROF
00094     { "SIGPROF", SIGPROF },
00095 #endif
00096 #ifdef SIGSYS
00097     { "SIGSYS", SIGSYS },
00098 #endif
00099 #ifdef SIGTRAP
00100     { "SIGTRAP", SIGTRAP },
00101 #endif
00102 #ifdef SIGURG
00103     { "SIGURG", SIGURG },
00104 #endif
00105 #ifdef SIGVTALRM
00106     { "SIGVTALRM", SIGVTALRM },
00107 #endif
00108 #ifdef SIGXCPU
00109     { "SIGXCPU", SIGXCPU },
00110 #endif
00111 #ifdef SIGXFSZ
00112     { "SIGXFSZ", SIGXFSZ },
00113 #endif
00114 
00115 #ifdef SIGIOT
00116     { "SIGIOT", SIGIOT }, /* synonym for SIGABRT, must be in table after */
00117 #endif
00118 #ifdef SIGEMT
00119     { "SIGEMT", SIGEMT },
00120 #endif
00121 #ifdef SIGSTKFLT
00122     { "SIGSTKFLT", SIGSTKFLT },
00123 #endif
00124 #ifdef SIGIO
00125     { "SIGIO", SIGIO },
00126 #endif
00127 #ifdef SIGCLD
00128     { "SIGCLD", SIGCLD }, /* synonym for SIGCHLD, must be in table after */
00129 #endif
00130 #ifdef SIGPWR
00131     { "SIGPWR", SIGPWR },
00132 #endif
00133 #ifdef SIGLOST
00134     { "SIGLOST", SIGLOST }, /* synonym for SIGIO, must be after in table */
00135 #endif
00136 #ifdef SIGWINCH
00137     { "SIGWINCH", SIGWINCH },
00138 #endif
00139 #ifdef SIGUNUSED
00140     { "SIGUNUSED", SIGUNUSED }, /* may be synonym for SIGSYS, so table after */
00141 #endif
00142 
00143 #ifdef _NSIG
00144     { "_NSIG", _NSIG },
00145 #endif
00146 
00147 #if !defined(_SIGRTMIN) && !defined(__SIGRTMIN)
00148     /* sometimes this is a non-constant macro: sysconf(_SC_SIGRTMIN) */
00149     { "SIGRTMIN", SIGRTMIN },
00150 #endif
00151 #ifdef __SIGRTMIN
00152     { "SIGRTMIN", __SIGRTMIN },
00153     { "__SIGRTMIN", __SIGRTMIN },
00154 #endif
00155 #ifdef _SIGRTMIN
00156     { "SIGRTMIN", _SIGRTMIN },
00157     { "_SIGRTMIN", _SIGRTMIN },
00158 #endif
00159 
00160 #if !defined(_SIGRTMAX) && !defined(__SIGRTMAX)
00161     /* sometimes this is a non-constant macro: sysconf(_SC_SIGRTMAX) */
00162     { "SIGRTMAX", SIGRTMAX },
00163 #endif
00164 #ifdef _SIGRTMAX
00165     { "SIGRTMAX", _SIGRTMAX },
00166     { "_SIGRTMAX", _SIGRTMAX },
00167 #endif
00168 #ifdef __SIGRTMAX
00169     { "SIGRTMAX", __SIGRTMAX },
00170     { "__SIGRTMAX", __SIGRTMAX },
00171 #endif
00172 };
00173 
00174 
00175 static void
00176 fix_real_time_values(void)
00177 {
00178 #if defined(__SIGRTMIN) || defined(_SIGRTMIN)
00179     explain_parse_bits_table_t *tp;
00180     static int      done;
00181 
00182     if (done)
00183         return;
00184     done = 1;
00185 
00186     /*
00187      * This is needed if SIGRTMIN et al are actually macros calling
00188      * sysconf(_SC_SIGRTMIN), etc.
00189      */
00190     for (tp = table; tp < ENDOF(table); ++tp)
00191     {
00192         if (0 == strcmp(tp->name, "SIGRTMIN"))
00193             tp->value = SIGRTMIN;
00194         if (0 == strcmp(tp->name, "SIGRTMAX"))
00195             tp->value = SIGRTMAX;
00196     }
00197 #endif
00198 }
00199 
00200 
00201 void
00202 explain_buffer_signal(explain_string_buffer_t *sb, int signum)
00203 {
00204     const explain_parse_bits_table_t *tp;
00205 
00206     fix_real_time_values();
00207     tp = explain_parse_bits_find_by_value(signum, table, SIZEOF(table));
00208     if (tp)
00209     {
00210         explain_string_buffer_puts(sb, tp->name);
00211         return;
00212     }
00213 
00214 #if defined(SIGRTMIN) && defined(SIGRTMAX)
00215     {
00216         int             rtmin;
00217         int             rtmax;
00218 
00219         /*
00220          * Don't worry about the SIGRTMIN+0 case being ugly, because the
00221          * table already dealt with that case.
00222          */
00223         rtmin = SIGRTMIN;
00224         rtmax = SIGRTMAX;
00225         if (rtmin <= signum && signum <= rtmax)
00226         {
00227             explain_string_buffer_printf
00228             (
00229                 sb,
00230                 "SIGRTMIN + %d",
00231                 signum - rtmin
00232             );
00233             return;
00234         }
00235     }
00236 #endif
00237 
00238     explain_string_buffer_printf(sb, "%d", signum);
00239 }
00240 
00241 
00242 int
00243 explain_signal_parse_or_die(const char *text, const char *caption)
00244 {
00245     fix_real_time_values();
00246     return explain_parse_bits_or_die(text, table, SIZEOF(table), caption);
00247 }
00248 
00249 
00250 /* vim: set ts=8 sw=4 et : */