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