/* MiddleMan filtering proxy server Copyright (C) 2002 Jason McLaughlin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include #include #include #include #include #include #include #include #include "proto.h" extern char **environ; #ifdef HAVE_GETHOSTBYNAME_R /* wrapper for reentrant gethostbyname function */ HOSTENT *p_gethostbyname(char *host) { int ret, err; char buf[1024]; HOSTENT *hostent; struct hostent h, *hp; ret = gethostbyname_r(host, &h, buf, sizeof(buf), &hp, &err); if (ret != 0) return NULL; hostent = xmalloc(sizeof(HOSTENT)); hostent->addr = xmalloc(sizeof(struct in_addr)); memcpy(hostent->addr, h.h_addr_list[0], sizeof(struct in_addr)); hostent->len = sizeof(struct in_addr); return hostent; } #else pthread_mutex_t gethostbyname_mutex = PTHREAD_MUTEX_INITIALIZER; /* stupid work-around for systems without gethostbyname_r */ HOSTENT *p_gethostbyname(char *host) { HOSTENT *hostent; struct hostent *h; pthread_mutex_lock(&gethostbyname_mutex); h = gethostbyname(host); if (h == NULL) { pthread_mutex_unlock(&gethostbyname_mutex); return NULL; } hostent = xmalloc(sizeof(HOSTENT)); hostent->addr = xmalloc(h->h_length); memcpy(hostent->addr, h->h_addr_list[0], h->h_length); hostent->len = h->h_length; pthread_mutex_unlock(&gethostbyname_mutex); return hostent; } #endif /* HAVE_GETHOSTBYNAME_R */ #ifdef HAVE_POLL /* wrapper for poll() for systems that actually implement this */ int p_poll(struct pollfd *pollfd, int fds, int timeout) { return poll(pollfd, fds, timeout); } #else /* basic poll() wrapper using select for system's lacking that feature */ int p_poll(struct pollfd *pfd, int fds, int timeout) { int i, ret, hfd = 0; fd_set readlist, writelist; struct timeval tv; FD_ZERO(&readlist); FD_ZERO(&writelist); if (timeout >= 0) { tv.tv_usec = timeout * 1000; tv.tv_sec = tv.tv_usec / 1000000; tv.tv_usec %= 1000000; } for (i = 0; i < fds; i++) { if (pfd[i].fd >= hfd) hfd = pfd[i].fd + 1; pfd[i].revents = 0; if (pfd[i].events & POLLIN) FD_SET(pfd[i].fd, &readlist); if (pfd[i].events & POLLOUT) FD_SET(pfd[i].fd, &writelist); } ret = select(hfd, &readlist, &writelist, NULL, (timeout >= 0) ? &tv : NULL); if (ret > 0) { for (i = 0; i < fds; i++) { if (FD_ISSET(pfd[i].fd, &readlist)) pfd[i].revents |= POLLIN; if (FD_ISSET(pfd[i].fd, &writelist)) pfd[i].revents |= POLLOUT; if (fcntl(pfd[i].fd, F_GETFL, O_NDELAY) == -1) pfd[i].revents |= POLLHUP; } } return ret; } #endif /* HAVE_POLL */ #ifdef HAVE_SETENV int p_setenv(char *var, char *value, int overwrite) { return setenv(var, value, overwrite); } #else /* solaris, et al lack setenv(), this will emulate it's behavior */ int p_setenv(char *var, char *value, int overwrite) { char *buf; if (!overwrite && getenv(var)) return -1; buf = xmalloc(strlen(var) + strlen(value) + 2); sprintf(buf, "%s=%s", var, value); return putenv(buf); } #endif /* HAVE_SETENV */ /* clearenv() is glibc-specific, setting environ to NULL will do for other platforms */ void p_clearenv() { #ifdef HAVE_CLEARENV clearenv(); #else environ = NULL; #endif }