Annotation of embedaddon/strongswan/src/libstrongswan/utils/utils.c, revision 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>