fca614ef4a25448ae6f26cd290fe335bc5f20dff
[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 #ifndef WIN32
24 # include <signal.h>
25 #endif
26
27 #ifndef HAVE_CLOSEFROM
28 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
29 # include <sys/stat.h>
30 # include <fcntl.h>
31 # include <sys/syscall.h>
32 /* This is from the kernel sources. We limit the length of directory names to
33 * 256 as we only use it to enumerate FDs. */
34 struct linux_dirent64 {
35 u_int64_t d_ino;
36 int64_t d_off;
37 unsigned short d_reclen;
38 unsigned char d_type;
39 char d_name[256];
40 };
41 #else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */
42 # include <dirent.h>
43 #endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */
44 #endif
45
46 #include <library.h>
47 #include <collections/enumerator.h>
48
49 #define FD_DIR "/proc/self/fd"
50
51 #ifdef WIN32
52
53 #include <threading/mutex.h>
54 #include <threading/condvar.h>
55
56 /**
57 * Flag to indicate signaled wait_sigint()
58 */
59 static bool sigint_signaled = FALSE;
60
61 /**
62 * Condvar to wait in wait_sigint()
63 */
64 static condvar_t *sigint_cond;
65
66 /**
67 * Mutex to check signaling()
68 */
69 static mutex_t *sigint_mutex;
70
71 /**
72 * Control handler to catch ^C
73 */
74 static BOOL WINAPI handler(DWORD dwCtrlType)
75 {
76 switch (dwCtrlType)
77 {
78 case CTRL_C_EVENT:
79 case CTRL_BREAK_EVENT:
80 case CTRL_CLOSE_EVENT:
81 sigint_mutex->lock(sigint_mutex);
82 sigint_signaled = TRUE;
83 sigint_cond->signal(sigint_cond);
84 sigint_mutex->unlock(sigint_mutex);
85 return TRUE;
86 default:
87 return FALSE;
88 }
89 }
90
91 /**
92 * Windows variant
93 */
94 void wait_sigint()
95 {
96 SetConsoleCtrlHandler(handler, TRUE);
97
98 sigint_mutex = mutex_create(MUTEX_TYPE_DEFAULT);
99 sigint_cond = condvar_create(CONDVAR_TYPE_DEFAULT);
100
101 sigint_mutex->lock(sigint_mutex);
102 while (!sigint_signaled)
103 {
104 sigint_cond->wait(sigint_cond, sigint_mutex);
105 }
106 sigint_mutex->unlock(sigint_mutex);
107
108 sigint_mutex->destroy(sigint_mutex);
109 sigint_cond->destroy(sigint_cond);
110 }
111
112 #else /* !WIN32 */
113
114 /**
115 * Unix variant
116 */
117 void wait_sigint()
118 {
119 sigset_t set;
120
121 sigemptyset(&set);
122 sigaddset(&set, SIGINT);
123 sigaddset(&set, SIGTERM);
124
125 sigprocmask(SIG_BLOCK, &set, NULL);
126 sigwaitinfo(&set, NULL);
127 }
128
129 #endif
130
131 #ifndef HAVE_CLOSEFROM
132 /**
133 * Described in header.
134 */
135 void closefrom(int low_fd)
136 {
137 int max_fd, dir_fd, fd;
138
139 /* try to close only open file descriptors on Linux... */
140 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
141 /* By directly using a syscall we avoid any calls that might be unsafe after
142 * fork() (e.g. malloc()). */
143 char buffer[sizeof(struct linux_dirent64)];
144 struct linux_dirent64 *entry;
145 int offset, len;
146
147 dir_fd = open("/proc/self/fd", O_RDONLY);
148 if (dir_fd != -1)
149 {
150 while ((len = syscall(SYS_getdents64, dir_fd, buffer,
151 sizeof(buffer))) > 0)
152 {
153 for (offset = 0; offset < len; offset += entry->d_reclen)
154 {
155 entry = (struct linux_dirent64*)(buffer + offset);
156 if (!isdigit(entry->d_name[0]))
157 {
158 continue;
159 }
160 fd = atoi(entry->d_name);
161 if (fd != dir_fd && fd >= low_fd)
162 {
163 close(fd);
164 }
165 }
166 }
167 close(dir_fd);
168 return;
169 }
170 #else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */
171 /* This is potentially unsafe when called after fork() in multi-threaded
172 * applications. In particular opendir() will require an allocation.
173 * Depends on how the malloc() implementation handles such situations. */
174 DIR *dir;
175 struct dirent *entry;
176
177 #ifndef HAVE_DIRFD
178 /* if we don't have dirfd() lets close the lowest FD and hope it gets reused
179 * by opendir() */
180 close(low_fd);
181 dir_fd = low_fd++;
182 #endif
183
184 dir = opendir(FD_DIR);
185 if (dir)
186 {
187 #ifdef HAVE_DIRFD
188 dir_fd = dirfd(dir);
189 #endif
190 while ((entry = readdir(dir)))
191 {
192 if (!isdigit(entry->d_name[0]))
193 {
194 continue;
195 }
196 fd = atoi(entry->d_name);
197 if (fd != dir_fd && fd >= low_fd)
198 {
199 close(fd);
200 }
201 }
202 closedir(dir);
203 return;
204 }
205 #endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */
206
207 /* ...fall back to closing all fds otherwise */
208 #ifdef WIN32
209 max_fd = _getmaxstdio();
210 #else
211 max_fd = (int)sysconf(_SC_OPEN_MAX);
212 #endif
213 if (max_fd < 0)
214 {
215 max_fd = 256;
216 }
217 for (fd = low_fd; fd < max_fd; fd++)
218 {
219 close(fd);
220 }
221 }
222 #endif /* HAVE_CLOSEFROM */
223
224 /**
225 * return null
226 */
227 void *return_null()
228 {
229 return NULL;
230 }
231
232 /**
233 * returns TRUE
234 */
235 bool return_true()
236 {
237 return TRUE;
238 }
239
240 /**
241 * returns FALSE
242 */
243 bool return_false()
244 {
245 return FALSE;
246 }
247
248 /**
249 * nop operation
250 */
251 void nop()
252 {
253 }
254
255 /**
256 * See header
257 */
258 void utils_init()
259 {
260 #ifdef WIN32
261 windows_init();
262 #endif
263 atomics_init();
264 strerror_init();
265 }
266
267 /**
268 * See header
269 */
270 void utils_deinit()
271 {
272 #ifdef WIN32
273 windows_deinit();
274 #endif
275 atomics_deinit();
276 strerror_deinit();
277 }