Annotation of embedaddon/libevent/evutil.c, revision 1.1.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>