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>