]>
git.ipfire.org Git - people/ms/strongswan.git/blob - src/libstrongswan/utils/utils.c
94863d3d6b353e26b426aeeb1acb5d0b43ce7a7b
2 * Copyright (C) 2008-2015 Tobias Brunner
3 * Copyright (C) 2005-2008 Martin Willi
4 * HSR Hochschule fuer Technik Rapperswil
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>.
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
19 #include <sys/types.h>
28 #ifndef HAVE_CLOSEFROM
29 #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
30 # include <sys/stat.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
{
38 unsigned short d_reclen
;
42 #else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */
44 #endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */
48 #include <collections/enumerator.h>
50 #define FD_DIR "/proc/self/fd"
54 #include <threading/mutex.h>
55 #include <threading/condvar.h>
58 * Flag to indicate signaled wait_sigint()
60 static bool sigint_signaled
= FALSE
;
63 * Condvar to wait in wait_sigint()
65 static condvar_t
*sigint_cond
;
68 * Mutex to check signaling()
70 static mutex_t
*sigint_mutex
;
73 * Control handler to catch ^C
75 static BOOL WINAPI
handler(DWORD dwCtrlType
)
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
);
97 SetConsoleCtrlHandler(handler
, TRUE
);
99 sigint_mutex
= mutex_create(MUTEX_TYPE_DEFAULT
);
100 sigint_cond
= condvar_create(CONDVAR_TYPE_DEFAULT
);
102 sigint_mutex
->lock(sigint_mutex
);
103 while (!sigint_signaled
)
105 sigint_cond
->wait(sigint_cond
, sigint_mutex
);
107 sigint_mutex
->unlock(sigint_mutex
);
109 sigint_mutex
->destroy(sigint_mutex
);
110 sigint_cond
->destroy(sigint_cond
);
123 sigaddset(&set
, SIGINT
);
124 sigaddset(&set
, SIGTERM
);
126 sigprocmask(SIG_BLOCK
, &set
, NULL
);
127 while (sigwaitinfo(&set
, NULL
) == -1 && errno
== EINTR
)
129 /* wait for signal */
133 #ifndef HAVE_SIGWAITINFO
134 int sigwaitinfo(const sigset_t
*set
, void *info
)
139 { /* we don't replicate siginfo_t, fail if anybody tries to use it */
143 err
= sigwait(set
, &sig
);
151 #endif /* HAVE_SIGWAITINFO */
154 #ifndef HAVE_CLOSEFROM
156 * Described in header.
158 void closefrom(int low_fd
)
160 int max_fd
, dir_fd
, fd
;
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
;
170 dir_fd
= open("/proc/self/fd", O_RDONLY
);
173 while ((len
= syscall(__NR_getdents64
, dir_fd
, buffer
,
174 sizeof(buffer
))) > 0)
176 for (offset
= 0; offset
< len
; offset
+= entry
->d_reclen
)
178 entry
= (struct linux_dirent64
*)(buffer
+ offset
);
179 if (!isdigit(entry
->d_name
[0]))
183 fd
= atoi(entry
->d_name
);
184 if (fd
!= dir_fd
&& fd
>= low_fd
)
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. */
198 struct dirent
*entry
;
201 /* if we don't have dirfd() lets close the lowest FD and hope it gets reused
207 dir
= opendir(FD_DIR
);
213 while ((entry
= readdir(dir
)))
215 if (!isdigit(entry
->d_name
[0]))
219 fd
= atoi(entry
->d_name
);
220 if (fd
!= dir_fd
&& fd
>= low_fd
)
228 #endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */
230 /* ...fall back to closing all fds otherwise */
232 max_fd
= _getmaxstdio();
234 max_fd
= (int)sysconf(_SC_OPEN_MAX
);
240 for (fd
= low_fd
; fd
< max_fd
; fd
++)
245 #endif /* HAVE_CLOSEFROM */