1 | /* Copyright (C) 1991-2020 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) any later version. |
8 | |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with the GNU C Library; if not, see |
16 | <https://www.gnu.org/licenses/>. */ |
17 | |
18 | #include <signal.h> |
19 | #include <stdio.h> |
20 | #include <stdlib.h> |
21 | #include <string.h> |
22 | #include <libintl.h> |
23 | #include <libc-lock.h> |
24 | |
25 | static __libc_key_t key; |
26 | |
27 | /* If nonzero the key allocation failed and we should better use a |
28 | static buffer than fail. */ |
29 | #define BUFFERSIZ 100 |
30 | static char local_buf[BUFFERSIZ]; |
31 | static char *static_buf; |
32 | |
33 | /* Destructor for the thread-specific data. */ |
34 | static void init (void); |
35 | static void free_key_mem (void *mem); |
36 | static char *getbuffer (void); |
37 | |
38 | |
39 | /* Return a string describing the meaning of the signal number SIGNUM. */ |
40 | char * |
41 | strsignal (int signum) |
42 | { |
43 | __libc_once_define (static, once); |
44 | const char *desc; |
45 | |
46 | /* If we have not yet initialized the buffer do it now. */ |
47 | __libc_once (once, init); |
48 | |
49 | if ( |
50 | #ifdef SIGRTMIN |
51 | (signum >= SIGRTMIN && signum <= SIGRTMAX) || |
52 | #endif |
53 | signum < 0 || signum >= NSIG |
54 | || (desc = _sys_siglist[signum]) == NULL) |
55 | { |
56 | char *buffer = getbuffer (); |
57 | int len; |
58 | #ifdef SIGRTMIN |
59 | if (signum >= SIGRTMIN && signum <= SIGRTMAX) |
60 | len = __snprintf (buffer, BUFFERSIZ - 1, _("Real-time signal %d" ), |
61 | signum - SIGRTMIN); |
62 | else |
63 | #endif |
64 | len = __snprintf (buffer, BUFFERSIZ - 1, _("Unknown signal %d" ), |
65 | signum); |
66 | if (len >= BUFFERSIZ) |
67 | buffer = NULL; |
68 | else |
69 | buffer[len] = '\0'; |
70 | |
71 | return buffer; |
72 | } |
73 | |
74 | return (char *) _(desc); |
75 | } |
76 | |
77 | |
78 | /* Initialize buffer. */ |
79 | static void |
80 | init (void) |
81 | { |
82 | if (__libc_key_create (&key, free_key_mem)) |
83 | /* Creating the key failed. This means something really went |
84 | wrong. In any case use a static buffer which is better than |
85 | nothing. */ |
86 | static_buf = local_buf; |
87 | } |
88 | |
89 | |
90 | /* Free the thread specific data, this is done if a thread terminates. */ |
91 | static void |
92 | free_key_mem (void *mem) |
93 | { |
94 | free (mem); |
95 | __libc_setspecific (key, NULL); |
96 | } |
97 | |
98 | |
99 | /* Return the buffer to be used. */ |
100 | static char * |
101 | getbuffer (void) |
102 | { |
103 | char *result; |
104 | |
105 | if (static_buf != NULL) |
106 | result = static_buf; |
107 | else |
108 | { |
109 | /* We don't use the static buffer and so we have a key. Use it |
110 | to get the thread-specific buffer. */ |
111 | result = __libc_getspecific (key); |
112 | if (result == NULL) |
113 | { |
114 | /* No buffer allocated so far. */ |
115 | result = malloc (BUFFERSIZ); |
116 | if (result == NULL) |
117 | /* No more memory available. We use the static buffer. */ |
118 | result = local_buf; |
119 | else |
120 | __libc_setspecific (key, result); |
121 | } |
122 | } |
123 | |
124 | return result; |
125 | } |
126 | |