/src/strongswan/src/libstrongswan/utils/utils.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2008-2015 Tobias Brunner |
3 | | * Copyright (C) 2005-2008 Martin Willi |
4 | | * |
5 | | * Copyright (C) secunet Security Networks AG |
6 | | * |
7 | | * This program is free software; you can redistribute it and/or modify it |
8 | | * under the terms of the GNU General Public License as published by the |
9 | | * Free Software Foundation; either version 2 of the License, or (at your |
10 | | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. |
11 | | * |
12 | | * This program is distributed in the hope that it will be useful, but |
13 | | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
14 | | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
15 | | * for more details. |
16 | | */ |
17 | | |
18 | | #include "utils.h" |
19 | | |
20 | | #include <sys/types.h> |
21 | | #include <unistd.h> |
22 | | #include <limits.h> |
23 | | #include <ctype.h> |
24 | | #include <errno.h> |
25 | | #ifndef WIN32 |
26 | | # include <signal.h> |
27 | | #endif |
28 | | |
29 | | #ifndef HAVE_CLOSEFROM |
30 | | #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) |
31 | | # include <sys/stat.h> |
32 | | # include <fcntl.h> |
33 | | # include <sys/syscall.h> |
34 | | /* This is from the kernel sources. We limit the length of directory names to |
35 | | * 256 as we only use it to enumerate FDs. */ |
36 | | struct linux_dirent64 { |
37 | | uint64_t d_ino; |
38 | | int64_t d_off; |
39 | | unsigned short d_reclen; |
40 | | unsigned char d_type; |
41 | | char d_name[256]; |
42 | | }; |
43 | | #else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */ |
44 | | # include <dirent.h> |
45 | | #endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */ |
46 | | #endif |
47 | | |
48 | | #include <library.h> |
49 | | #include <collections/enumerator.h> |
50 | | |
51 | | #define FD_DIR "/proc/self/fd" |
52 | | |
53 | | #ifdef WIN32 |
54 | | |
55 | | #include <threading/mutex.h> |
56 | | #include <threading/condvar.h> |
57 | | |
58 | | /** |
59 | | * Flag to indicate signaled wait_sigint() |
60 | | */ |
61 | | static bool sigint_signaled = FALSE; |
62 | | |
63 | | /** |
64 | | * Condvar to wait in wait_sigint() |
65 | | */ |
66 | | static condvar_t *sigint_cond; |
67 | | |
68 | | /** |
69 | | * Mutex to check signaling() |
70 | | */ |
71 | | static mutex_t *sigint_mutex; |
72 | | |
73 | | /** |
74 | | * Control handler to catch ^C |
75 | | */ |
76 | | static BOOL WINAPI handler(DWORD dwCtrlType) |
77 | | { |
78 | | switch (dwCtrlType) |
79 | | { |
80 | | case CTRL_C_EVENT: |
81 | | case CTRL_BREAK_EVENT: |
82 | | case CTRL_CLOSE_EVENT: |
83 | | sigint_mutex->lock(sigint_mutex); |
84 | | sigint_signaled = TRUE; |
85 | | sigint_cond->signal(sigint_cond); |
86 | | sigint_mutex->unlock(sigint_mutex); |
87 | | return TRUE; |
88 | | default: |
89 | | return FALSE; |
90 | | } |
91 | | } |
92 | | |
93 | | /** |
94 | | * Windows variant |
95 | | */ |
96 | | void wait_sigint() |
97 | | { |
98 | | SetConsoleCtrlHandler(handler, TRUE); |
99 | | |
100 | | sigint_mutex = mutex_create(MUTEX_TYPE_DEFAULT); |
101 | | sigint_cond = condvar_create(CONDVAR_TYPE_DEFAULT); |
102 | | |
103 | | sigint_mutex->lock(sigint_mutex); |
104 | | while (!sigint_signaled) |
105 | | { |
106 | | sigint_cond->wait(sigint_cond, sigint_mutex); |
107 | | } |
108 | | sigint_mutex->unlock(sigint_mutex); |
109 | | |
110 | | sigint_mutex->destroy(sigint_mutex); |
111 | | sigint_cond->destroy(sigint_cond); |
112 | | } |
113 | | |
114 | | /** |
115 | | * Windows variant |
116 | | */ |
117 | | void send_sigint() |
118 | | { |
119 | | handler(CTRL_C_EVENT); |
120 | | } |
121 | | |
122 | | #else /* !WIN32 */ |
123 | | |
124 | | /** |
125 | | * Unix variant |
126 | | */ |
127 | | void wait_sigint() |
128 | 0 | { |
129 | 0 | sigset_t set; |
130 | |
|
131 | 0 | sigemptyset(&set); |
132 | 0 | sigaddset(&set, SIGINT); |
133 | 0 | sigaddset(&set, SIGTERM); |
134 | |
|
135 | 0 | sigprocmask(SIG_BLOCK, &set, NULL); |
136 | 0 | while (sigwaitinfo(&set, NULL) == -1 && errno == EINTR) |
137 | 0 | { |
138 | | /* wait for signal */ |
139 | 0 | } |
140 | 0 | } |
141 | | |
142 | | /** |
143 | | * Unix variant |
144 | | */ |
145 | | void send_sigint() |
146 | 0 | { |
147 | 0 | kill(0, SIGINT); |
148 | 0 | } |
149 | | |
150 | | #ifndef HAVE_SIGWAITINFO |
151 | | int sigwaitinfo(const sigset_t *set, void *info) |
152 | | { |
153 | | int sig, err; |
154 | | |
155 | | if (info) |
156 | | { /* we don't replicate siginfo_t, fail if anybody tries to use it */ |
157 | | errno = EINVAL; |
158 | | return -1; |
159 | | } |
160 | | err = sigwait(set, &sig); |
161 | | if (err != 0) |
162 | | { |
163 | | errno = err; |
164 | | sig = -1; |
165 | | } |
166 | | return sig; |
167 | | } |
168 | | #endif /* HAVE_SIGWAITINFO */ |
169 | | #endif /* WIN32 */ |
170 | | |
171 | | #ifndef HAVE_CLOSEFROM |
172 | | /** |
173 | | * Described in header. |
174 | | */ |
175 | | void closefrom(int low_fd) |
176 | 0 | { |
177 | 0 | int max_fd, dir_fd, fd; |
178 | | |
179 | | /* try to close only open file descriptors on Linux... */ |
180 | 0 | #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) |
181 | | /* By directly using a syscall we avoid any calls that might be unsafe after |
182 | | * fork() (e.g. malloc()). */ |
183 | 0 | char buffer[sizeof(struct linux_dirent64)]; |
184 | 0 | struct linux_dirent64 *entry; |
185 | 0 | int offset, len; |
186 | |
|
187 | 0 | dir_fd = open("/proc/self/fd", O_RDONLY); |
188 | 0 | if (dir_fd != -1) |
189 | 0 | { |
190 | 0 | while ((len = syscall(__NR_getdents64, dir_fd, buffer, |
191 | 0 | sizeof(buffer))) > 0) |
192 | 0 | { |
193 | 0 | for (offset = 0; offset < len; offset += entry->d_reclen) |
194 | 0 | { |
195 | 0 | entry = (struct linux_dirent64*)(buffer + offset); |
196 | 0 | if (!isdigit(entry->d_name[0])) |
197 | 0 | { |
198 | 0 | continue; |
199 | 0 | } |
200 | 0 | fd = atoi(entry->d_name); |
201 | 0 | if (fd != dir_fd && fd >= low_fd) |
202 | 0 | { |
203 | 0 | close(fd); |
204 | 0 | } |
205 | 0 | } |
206 | 0 | } |
207 | 0 | close(dir_fd); |
208 | 0 | return; |
209 | 0 | } |
210 | | #else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */ |
211 | | /* This is potentially unsafe when called after fork() in multi-threaded |
212 | | * applications. In particular opendir() will require an allocation. |
213 | | * Depends on how the malloc() implementation handles such situations. */ |
214 | | DIR *dir; |
215 | | struct dirent *entry; |
216 | | |
217 | | #ifndef HAVE_DIRFD |
218 | | /* if we don't have dirfd() lets close the lowest FD and hope it gets reused |
219 | | * by opendir() */ |
220 | | close(low_fd); |
221 | | dir_fd = low_fd++; |
222 | | #endif |
223 | | |
224 | | dir = opendir(FD_DIR); |
225 | | if (dir) |
226 | | { |
227 | | #ifdef HAVE_DIRFD |
228 | | dir_fd = dirfd(dir); |
229 | | #endif |
230 | | while ((entry = readdir(dir))) |
231 | | { |
232 | | if (!isdigit(entry->d_name[0])) |
233 | | { |
234 | | continue; |
235 | | } |
236 | | fd = atoi(entry->d_name); |
237 | | if (fd != dir_fd && fd >= low_fd) |
238 | | { |
239 | | close(fd); |
240 | | } |
241 | | } |
242 | | closedir(dir); |
243 | | return; |
244 | | } |
245 | | #endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */ |
246 | | |
247 | | /* ...fall back to closing all fds otherwise */ |
248 | | #ifdef WIN32 |
249 | | max_fd = _getmaxstdio(); |
250 | | #else |
251 | 0 | max_fd = (int)sysconf(_SC_OPEN_MAX); |
252 | 0 | #endif |
253 | 0 | if (max_fd < 0) |
254 | 0 | { |
255 | 0 | max_fd = 256; |
256 | 0 | } |
257 | 0 | for (fd = low_fd; fd < max_fd; fd++) |
258 | 0 | { |
259 | 0 | close(fd); |
260 | 0 | } |
261 | 0 | } |
262 | | #endif /* HAVE_CLOSEFROM */ |
263 | | |
264 | | /** |
265 | | * return null |
266 | | */ |
267 | | void *return_null() |
268 | 1 | { |
269 | 1 | return NULL; |
270 | 1 | } |
271 | | |
272 | | /** |
273 | | * returns TRUE |
274 | | */ |
275 | | bool return_true() |
276 | 0 | { |
277 | 0 | return TRUE; |
278 | 0 | } |
279 | | |
280 | | /** |
281 | | * returns FALSE |
282 | | */ |
283 | | bool return_false() |
284 | 0 | { |
285 | 0 | return FALSE; |
286 | 0 | } |
287 | | |
288 | | /** |
289 | | * nop operation |
290 | | */ |
291 | | void nop() |
292 | 0 | { |
293 | 0 | } |
294 | | |
295 | | /** |
296 | | * See header |
297 | | */ |
298 | | void utils_init() |
299 | 3.51k | { |
300 | | #ifdef WIN32 |
301 | | windows_init(); |
302 | | #endif |
303 | 3.51k | atomics_init(); |
304 | 3.51k | strerror_init(); |
305 | 3.51k | } |
306 | | |
307 | | /** |
308 | | * See header |
309 | | */ |
310 | | void utils_deinit() |
311 | 3.51k | { |
312 | | #ifdef WIN32 |
313 | | windows_deinit(); |
314 | | #endif |
315 | 3.51k | atomics_deinit(); |
316 | 3.51k | strerror_deinit(); |
317 | 3.51k | } |