File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libevent / evutil.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:02:54 2012 UTC (12 years, 3 months ago) by misho
Branches: libevent, MAIN
CVS tags: v1_4_14bp0, v1_4_14b, HEAD
libevent

    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>