Annotation of embedaddon/libevent/evutil.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (c) 2007 Niels Provos <provos@citi.umich.edu>
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. The name of the author may not be used to endorse or promote products
        !            14:  *    derived from this software without specific prior written permission.
        !            15:  *
        !            16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            19:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            26:  */
        !            27: #ifdef HAVE_CONFIG_H
        !            28: #include "config.h"
        !            29: #endif
        !            30: 
        !            31: #ifdef WIN32
        !            32: #include <winsock2.h>
        !            33: #define WIN32_LEAN_AND_MEAN
        !            34: #include <windows.h>
        !            35: #undef WIN32_LEAN_AND_MEAN
        !            36: #endif
        !            37: 
        !            38: #include <sys/types.h>
        !            39: #ifdef HAVE_SYS_SOCKET_H
        !            40: #include <sys/socket.h>
        !            41: #endif
        !            42: #ifdef HAVE_UNISTD_H
        !            43: #include <unistd.h>
        !            44: #endif
        !            45: #ifdef HAVE_FCNTL_H
        !            46: #include <fcntl.h>
        !            47: #endif
        !            48: #ifdef HAVE_STDLIB_H
        !            49: #include <stdlib.h>
        !            50: #endif
        !            51: #include <errno.h>
        !            52: #if defined WIN32 && !defined(HAVE_GETTIMEOFDAY_H)
        !            53: #include <sys/timeb.h>
        !            54: #endif
        !            55: #include <stdio.h>
        !            56: #include <signal.h>
        !            57: 
        !            58: #include <sys/queue.h>
        !            59: #include "event.h"
        !            60: #include "event-internal.h"
        !            61: #include "evutil.h"
        !            62: #include "log.h"
        !            63: 
        !            64: int
        !            65: evutil_socketpair(int family, int type, int protocol, int fd[2])
        !            66: {
        !            67: #ifndef WIN32
        !            68:        return socketpair(family, type, protocol, fd);
        !            69: #else
        !            70:        /* This code is originally from Tor.  Used with permission. */
        !            71: 
        !            72:        /* This socketpair does not work when localhost is down. So
        !            73:         * it's really not the same thing at all. But it's close enough
        !            74:         * for now, and really, when localhost is down sometimes, we
        !            75:         * have other problems too.
        !            76:         */
        !            77:        int listener = -1;
        !            78:        int connector = -1;
        !            79:        int acceptor = -1;
        !            80:        struct sockaddr_in listen_addr;
        !            81:        struct sockaddr_in connect_addr;
        !            82:        int size;
        !            83:        int saved_errno = -1;
        !            84: 
        !            85:        if (protocol
        !            86: #ifdef AF_UNIX
        !            87:                || family != AF_UNIX
        !            88: #endif
        !            89:                ) {
        !            90:                EVUTIL_SET_SOCKET_ERROR(WSAEAFNOSUPPORT);
        !            91:                return -1;
        !            92:        }
        !            93:        if (!fd) {
        !            94:                EVUTIL_SET_SOCKET_ERROR(WSAEINVAL);
        !            95:                return -1;
        !            96:        }
        !            97: 
        !            98:        listener = socket(AF_INET, type, 0);
        !            99:        if (listener < 0)
        !           100:                return -1;
        !           101:        memset(&listen_addr, 0, sizeof(listen_addr));
        !           102:        listen_addr.sin_family = AF_INET;
        !           103:        listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
        !           104:        listen_addr.sin_port = 0;       /* kernel chooses port.  */
        !           105:        if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
        !           106:                == -1)
        !           107:                goto tidy_up_and_fail;
        !           108:        if (listen(listener, 1) == -1)
        !           109:                goto tidy_up_and_fail;
        !           110: 
        !           111:        connector = socket(AF_INET, type, 0);
        !           112:        if (connector < 0)
        !           113:                goto tidy_up_and_fail;
        !           114:        /* We want to find out the port number to connect to.  */
        !           115:        size = sizeof(connect_addr);
        !           116:        if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1)
        !           117:                goto tidy_up_and_fail;
        !           118:        if (size != sizeof (connect_addr))
        !           119:                goto abort_tidy_up_and_fail;
        !           120:        if (connect(connector, (struct sockaddr *) &connect_addr,
        !           121:                                sizeof(connect_addr)) == -1)
        !           122:                goto tidy_up_and_fail;
        !           123: 
        !           124:        size = sizeof(listen_addr);
        !           125:        acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
        !           126:        if (acceptor < 0)
        !           127:                goto tidy_up_and_fail;
        !           128:        if (size != sizeof(listen_addr))
        !           129:                goto abort_tidy_up_and_fail;
        !           130:        EVUTIL_CLOSESOCKET(listener);
        !           131:        /* Now check we are talking to ourself by matching port and host on the
        !           132:           two sockets.  */
        !           133:        if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1)
        !           134:                goto tidy_up_and_fail;
        !           135:        if (size != sizeof (connect_addr)
        !           136:                || listen_addr.sin_family != connect_addr.sin_family
        !           137:                || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
        !           138:                || listen_addr.sin_port != connect_addr.sin_port)
        !           139:                goto abort_tidy_up_and_fail;
        !           140:        fd[0] = connector;
        !           141:        fd[1] = acceptor;
        !           142: 
        !           143:        return 0;
        !           144: 
        !           145:  abort_tidy_up_and_fail:
        !           146:        saved_errno = WSAECONNABORTED;
        !           147:  tidy_up_and_fail:
        !           148:        if (saved_errno < 0)
        !           149:                saved_errno = WSAGetLastError();
        !           150:        if (listener != -1)
        !           151:                EVUTIL_CLOSESOCKET(listener);
        !           152:        if (connector != -1)
        !           153:                EVUTIL_CLOSESOCKET(connector);
        !           154:        if (acceptor != -1)
        !           155:                EVUTIL_CLOSESOCKET(acceptor);
        !           156: 
        !           157:        EVUTIL_SET_SOCKET_ERROR(saved_errno);
        !           158:        return -1;
        !           159: #endif
        !           160: }
        !           161: 
        !           162: int
        !           163: evutil_make_socket_nonblocking(int fd)
        !           164: {
        !           165: #ifdef WIN32
        !           166:        {
        !           167:                unsigned long nonblocking = 1;
        !           168:                ioctlsocket(fd, FIONBIO, (unsigned long*) &nonblocking);
        !           169:        }
        !           170: #else
        !           171:        {
        !           172:                long flags;
        !           173:                if ((flags = fcntl(fd, F_GETFL, NULL)) < 0) {
        !           174:                        event_warn("fcntl(%d, F_GETFL)", fd);
        !           175:                        return -1;
        !           176:                }
        !           177:                if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
        !           178:                        event_warn("fcntl(%d, F_SETFL)", fd);
        !           179:                        return -1;
        !           180:                }
        !           181:        }
        !           182: #endif
        !           183:        return 0;
        !           184: }
        !           185: 
        !           186: ev_int64_t
        !           187: evutil_strtoll(const char *s, char **endptr, int base)
        !           188: {
        !           189: #ifdef HAVE_STRTOLL
        !           190:        return (ev_int64_t)strtoll(s, endptr, base);
        !           191: #elif SIZEOF_LONG == 8
        !           192:        return (ev_int64_t)strtol(s, endptr, base);
        !           193: #elif defined(WIN32) && defined(_MSC_VER) && _MSC_VER < 1300
        !           194:        /* XXXX on old versions of MS APIs, we only support base
        !           195:         * 10. */
        !           196:        ev_int64_t r;
        !           197:        if (base != 10)
        !           198:                return 0;
        !           199:        r = (ev_int64_t) _atoi64(s);
        !           200:        while (isspace(*s))
        !           201:                ++s;
        !           202:        while (isdigit(*s))
        !           203:                ++s;
        !           204:        if (endptr)
        !           205:                *endptr = (char*) s;
        !           206:        return r;
        !           207: #elif defined(WIN32)
        !           208:        return (ev_int64_t) _strtoi64(s, endptr, base);
        !           209: #else
        !           210: #error "I don't know how to parse 64-bit integers."
        !           211: #endif
        !           212: }
        !           213: 
        !           214: #ifndef _EVENT_HAVE_GETTIMEOFDAY
        !           215: int
        !           216: evutil_gettimeofday(struct timeval *tv, struct timezone *tz)
        !           217: {
        !           218:        struct _timeb tb;
        !           219: 
        !           220:        if(tv == NULL)
        !           221:                return -1;
        !           222: 
        !           223:        _ftime(&tb);
        !           224:        tv->tv_sec = (long) tb.time;
        !           225:        tv->tv_usec = ((int) tb.millitm) * 1000;
        !           226:        return 0;
        !           227: }
        !           228: #endif
        !           229: 
        !           230: int
        !           231: evutil_snprintf(char *buf, size_t buflen, const char *format, ...)
        !           232: {
        !           233:        int r;
        !           234:        va_list ap;
        !           235:        va_start(ap, format);
        !           236:        r = evutil_vsnprintf(buf, buflen, format, ap);
        !           237:        va_end(ap);
        !           238:        return r;
        !           239: }
        !           240: 
        !           241: int
        !           242: evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap)
        !           243: {
        !           244: #ifdef _MSC_VER
        !           245:        int r = _vsnprintf(buf, buflen, format, ap);
        !           246:        buf[buflen-1] = '\0';
        !           247:        if (r >= 0)
        !           248:                return r;
        !           249:        else
        !           250:                return _vscprintf(format, ap);
        !           251: #else
        !           252:        int r = vsnprintf(buf, buflen, format, ap);
        !           253:        buf[buflen-1] = '\0';
        !           254:        return r;
        !           255: #endif
        !           256: }
        !           257: 
        !           258: static int
        !           259: evutil_issetugid(void)
        !           260: {
        !           261: #ifdef _EVENT_HAVE_ISSETUGID
        !           262:        return issetugid();
        !           263: #else
        !           264: 
        !           265: #ifdef _EVENT_HAVE_GETEUID
        !           266:        if (getuid() != geteuid())
        !           267:                return 1;
        !           268: #endif
        !           269: #ifdef _EVENT_HAVE_GETEGID
        !           270:        if (getgid() != getegid())
        !           271:                return 1;
        !           272: #endif
        !           273:        return 0;
        !           274: #endif
        !           275: }
        !           276: 
        !           277: const char *
        !           278: evutil_getenv(const char *varname)
        !           279: {
        !           280:        if (evutil_issetugid())
        !           281:                return NULL;
        !           282: 
        !           283:        return getenv(varname);
        !           284: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>