Annotation of embedaddon/strongswan/src/libstrongswan/utils/utils.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008-2015 Tobias Brunner
3: * Copyright (C) 2005-2008 Martin Willi
4: * HSR 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: uint64_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: while (sigwaitinfo(&set, NULL) == -1 && errno == EINTR)
128: {
129: /* wait for signal */
130: }
131: }
132:
133: #ifndef HAVE_SIGWAITINFO
134: int sigwaitinfo(const sigset_t *set, void *info)
135: {
136: int sig, err;
137:
138: if (info)
139: { /* we don't replicate siginfo_t, fail if anybody tries to use it */
140: errno = EINVAL;
141: return -1;
142: }
143: err = sigwait(set, &sig);
144: if (err != 0)
145: {
146: errno = err;
147: sig = -1;
148: }
149: return sig;
150: }
151: #endif /* HAVE_SIGWAITINFO */
152: #endif /* WIN32 */
153:
154: #ifndef HAVE_CLOSEFROM
155: /**
156: * Described in header.
157: */
158: void closefrom(int low_fd)
159: {
160: int max_fd, dir_fd, fd;
161:
162: /* try to close only open file descriptors on Linux... */
163: #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
164: /* By directly using a syscall we avoid any calls that might be unsafe after
165: * fork() (e.g. malloc()). */
166: char buffer[sizeof(struct linux_dirent64)];
167: struct linux_dirent64 *entry;
168: int offset, len;
169:
170: dir_fd = open("/proc/self/fd", O_RDONLY);
171: if (dir_fd != -1)
172: {
173: while ((len = syscall(__NR_getdents64, dir_fd, buffer,
174: sizeof(buffer))) > 0)
175: {
176: for (offset = 0; offset < len; offset += entry->d_reclen)
177: {
178: entry = (struct linux_dirent64*)(buffer + offset);
179: if (!isdigit(entry->d_name[0]))
180: {
181: continue;
182: }
183: fd = atoi(entry->d_name);
184: if (fd != dir_fd && fd >= low_fd)
185: {
186: close(fd);
187: }
188: }
189: }
190: close(dir_fd);
191: return;
192: }
193: #else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */
194: /* This is potentially unsafe when called after fork() in multi-threaded
195: * applications. In particular opendir() will require an allocation.
196: * Depends on how the malloc() implementation handles such situations. */
197: DIR *dir;
198: struct dirent *entry;
199:
200: #ifndef HAVE_DIRFD
201: /* if we don't have dirfd() lets close the lowest FD and hope it gets reused
202: * by opendir() */
203: close(low_fd);
204: dir_fd = low_fd++;
205: #endif
206:
207: dir = opendir(FD_DIR);
208: if (dir)
209: {
210: #ifdef HAVE_DIRFD
211: dir_fd = dirfd(dir);
212: #endif
213: while ((entry = readdir(dir)))
214: {
215: if (!isdigit(entry->d_name[0]))
216: {
217: continue;
218: }
219: fd = atoi(entry->d_name);
220: if (fd != dir_fd && fd >= low_fd)
221: {
222: close(fd);
223: }
224: }
225: closedir(dir);
226: return;
227: }
228: #endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */
229:
230: /* ...fall back to closing all fds otherwise */
231: #ifdef WIN32
232: max_fd = _getmaxstdio();
233: #else
234: max_fd = (int)sysconf(_SC_OPEN_MAX);
235: #endif
236: if (max_fd < 0)
237: {
238: max_fd = 256;
239: }
240: for (fd = low_fd; fd < max_fd; fd++)
241: {
242: close(fd);
243: }
244: }
245: #endif /* HAVE_CLOSEFROM */
246:
247: /**
248: * return null
249: */
250: void *return_null()
251: {
252: return NULL;
253: }
254:
255: /**
256: * returns TRUE
257: */
258: bool return_true()
259: {
260: return TRUE;
261: }
262:
263: /**
264: * returns FALSE
265: */
266: bool return_false()
267: {
268: return FALSE;
269: }
270:
271: /**
272: * nop operation
273: */
274: void nop()
275: {
276: }
277:
278: /**
279: * See header
280: */
281: void utils_init()
282: {
283: #ifdef WIN32
284: windows_init();
285: #endif
286: atomics_init();
287: strerror_init();
288: }
289:
290: /**
291: * See header
292: */
293: void utils_deinit()
294: {
295: #ifdef WIN32
296: windows_deinit();
297: #endif
298: atomics_deinit();
299: strerror_deinit();
300: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>