/* * Copyright (C) 2005-2009 Team XBMC * http://www.xbmc.org * * 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, 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 XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include <unistd.h> #include <stdlib.h> #include <string.h> #include <netdb.h> #include <pthread.h> #include <errno.h> #include "OSXGNUReplacements.h" size_t strnlen(const char *s, size_t n) { size_t i; for (i=0; i<n && s[i] != '\0'; i++) /* noop */ ; return i; } char* strndup(char const *s, size_t n) { size_t len = strnlen(s, n); char *new_str = (char*)malloc(len + 1); if (new_str == NULL) return NULL; new_str[len] = '\0'; return (char*)memcpy(new_str, s, len); } /* From http://svn.digium.com/view/asterisk/trunk/main/utils.c GNU General Public License Version 2 Brief Reentrant replacement for gethostbyname for BSD-based systems. Note This routine is derived from code originally written and placed in the public domain by Enzo Michelangeli <em@em.no-ip.com> */ static pthread_mutex_t gethostbyname_r_mutex = PTHREAD_MUTEX_INITIALIZER; // int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { int hsave; struct hostent *ph; pthread_mutex_lock(&gethostbyname_r_mutex); /* begin critical area */ hsave = h_errno; ph = gethostbyname(name); *h_errnop = h_errno; /* copy h_errno to *h_herrnop */ if (ph == NULL) { *result = NULL; } else { char **p, **q; char *pbuf; int nbytes = 0; int naddr = 0, naliases = 0; /* determine if we have enough space in buf */ /* count how many addresses */ for (p = ph->h_addr_list; *p != 0; p++) { nbytes += ph->h_length; /* addresses */ nbytes += sizeof(*p); /* pointers */ naddr++; } nbytes += sizeof(*p); /* one more for the terminating NULL */ /* count how many aliases, and total length of strings */ for (p = ph->h_aliases; *p != 0; p++) { nbytes += (strlen(*p)+1); /* aliases */ nbytes += sizeof(*p); /* pointers */ naliases++; } nbytes += sizeof(*p); /* one more for the terminating NULL */ /* here nbytes is the number of bytes required in buffer */ /* as a terminator must be there, the minimum value is ph->h_length */ if (nbytes > buflen) { *result = NULL; pthread_mutex_unlock(&gethostbyname_r_mutex); /* end critical area */ return ERANGE; /* not enough space in buf!! */ } /* There is enough space. Now we need to do a deep copy! */ /* Allocation in buffer: from [0] to [(naddr-1) * sizeof(*p)]: pointers to addresses at [naddr * sizeof(*p)]: NULL from [(naddr+1) * sizeof(*p)] to [(naddr+naliases) * sizeof(*p)] : pointers to aliases at [(naddr+naliases+1) * sizeof(*p)]: NULL then naddr addresses (fixed length), and naliases aliases (asciiz). */ *ret = *ph; /* copy whole structure (not its address!) */ /* copy addresses */ q = (char **)buf; /* pointer to pointers area (type: char **) */ ret->h_addr_list = q; /* update pointer to address list */ pbuf = buf + ((naddr + naliases + 2) * sizeof(*p)); /* skip that area */ for (p = ph->h_addr_list; *p != 0; p++) { memcpy(pbuf, *p, ph->h_length); /* copy address bytes */ *q++ = pbuf; /* the pointer is the one inside buf... */ pbuf += ph->h_length; /* advance pbuf */ } *q++ = NULL; /* address list terminator */ /* copy aliases */ ret->h_aliases = q; /* update pointer to aliases list */ for (p = ph->h_aliases; *p != 0; p++) { strcpy(pbuf, *p); /* copy alias strings */ *q++ = pbuf; /* the pointer is the one inside buf... */ pbuf += strlen(*p); /* advance pbuf */ *pbuf++ = 0; /* string terminator */ } *q++ = NULL; /* terminator */ strcpy(pbuf, ph->h_name); /* copy alias strings */ ret->h_name = pbuf; pbuf += strlen(ph->h_name); /* advance pbuf */ *pbuf++ = 0; /* string terminator */ *result = ret; /* and let *result point to structure */ } h_errno = hsave; /* restore h_errno */ pthread_mutex_unlock(&gethostbyname_r_mutex); /* end critical area */ return (*result == NULL); /* return 0 on success, non-zero on error */ } /* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU C Library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <errno.h> /* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR (and null-terminate it). *LINEPTR is a pointer returned from malloc (or NULL), pointing to *N characters of space. It is realloc'd as necessary. Returns the number of characters read (not including the null terminator), or -1 on error or EOF. */ ssize_t getdelim (lineptr, n, terminator, stream) char **lineptr; size_t *n; int terminator; FILE *stream; { char *line, *p; size_t size, copy; if (stream == NULL || lineptr == NULL || n == NULL) { errno = EINVAL; return -1; } if (ferror (stream)) return -1; /* Make sure we have a line buffer to start with. */ if (*lineptr == NULL || *n < 2) /* !seen and no buf yet need 2 chars. */ { #ifndef MAX_CANON #define MAX_CANON 256 #endif line = realloc (*lineptr, MAX_CANON); if (line == NULL) return -1; *lineptr = line; *n = MAX_CANON; } line = *lineptr; size = *n; copy = size; p = line; while (1) { size_t len; while (--copy > 0) { register int c = getc (stream); if (c == EOF) goto lose; else if ((*p++ = c) == terminator) goto win; } /* Need to enlarge the line buffer. */ len = p - line; size *= 2; line = realloc (line, size); if (line == NULL) goto lose; *lineptr = line; *n = size; p = line + len; copy = size - len; } lose: if (p == *lineptr) return -1; /* Return a partial line since we got an error in the middle. */ win: *p = '\0'; return p - *lineptr; } ssize_t getline (char **lineptr, size_t *n, FILE *stream) { return getdelim (lineptr, n, '\n', stream); }