| /* Copyright (C) 1991-2014 Free Software Foundation, Inc. |
| This file is part of the GNU C Library. |
| |
| The GNU C Library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 of the License, or (at your option) any later version. |
| |
| The GNU C Library 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 |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with the GNU C Library; if not, see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include <signal.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <libintl.h> |
| #include <bits/libc-lock.h> |
| |
| static __libc_key_t key; |
| |
| /* If nonzero the key allocation failed and we should better use a |
| static buffer than fail. */ |
| #define BUFFERSIZ 100 |
| static char local_buf[BUFFERSIZ]; |
| static char *static_buf; |
| |
| /* Destructor for the thread-specific data. */ |
| static void init (void); |
| static void free_key_mem (void *mem); |
| static char *getbuffer (void); |
| |
| |
| /* Return a string describing the meaning of the signal number SIGNUM. */ |
| char * |
| strsignal (int signum) |
| { |
| __libc_once_define (static, once); |
| const char *desc; |
| |
| /* If we have not yet initialized the buffer do it now. */ |
| __libc_once (once, init); |
| |
| if ( |
| #ifdef SIGRTMIN |
| (signum >= SIGRTMIN && signum <= SIGRTMAX) || |
| #endif |
| signum < 0 || signum >= NSIG |
| || (desc = _sys_siglist[signum]) == NULL) |
| { |
| char *buffer = getbuffer (); |
| int len; |
| #ifdef SIGRTMIN |
| if (signum >= SIGRTMIN && signum <= SIGRTMAX) |
| len = __snprintf (buffer, BUFFERSIZ - 1, _("Real-time signal %d"), |
| signum - SIGRTMIN); |
| else |
| #endif |
| len = __snprintf (buffer, BUFFERSIZ - 1, _("Unknown signal %d"), |
| signum); |
| if (len >= BUFFERSIZ) |
| buffer = NULL; |
| else |
| buffer[len] = '\0'; |
| |
| return buffer; |
| } |
| |
| return (char *) _(desc); |
| } |
| |
| |
| /* Initialize buffer. */ |
| static void |
| init (void) |
| { |
| if (__libc_key_create (&key, free_key_mem)) |
| /* Creating the key failed. This means something really went |
| wrong. In any case use a static buffer which is better than |
| nothing. */ |
| static_buf = local_buf; |
| } |
| |
| |
| /* Free the thread specific data, this is done if a thread terminates. */ |
| static void |
| free_key_mem (void *mem) |
| { |
| free (mem); |
| __libc_setspecific (key, NULL); |
| } |
| |
| |
| /* Return the buffer to be used. */ |
| static char * |
| getbuffer (void) |
| { |
| char *result; |
| |
| if (static_buf != NULL) |
| result = static_buf; |
| else |
| { |
| /* We don't use the static buffer and so we have a key. Use it |
| to get the thread-specific buffer. */ |
| result = __libc_getspecific (key); |
| if (result == NULL) |
| { |
| /* No buffer allocated so far. */ |
| result = malloc (BUFFERSIZ); |
| if (result == NULL) |
| /* No more memory available. We use the static buffer. */ |
| result = local_buf; |
| else |
| __libc_setspecific (key, result); |
| } |
| } |
| |
| return result; |
| } |