/*
* The olsr.org Optimized Link-State Routing daemon (olsrd)
* Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of olsr.org, olsrd nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Visit http://www.olsr.org for more information.
*
* If you find this software useful feel free to make a donation
* to the project. For more information see the website or contact
* the copyright holders.
*
* $Id: compat.c,v 1.16 2007/07/15 21:09:38 bernd67 Exp $
*/
/*
* Copyright (c) 1996,1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#include <unistd.h>
#include <sys/time.h>
#include <sys/times.h>
#include <ctype.h>
#include <dlfcn.h>
#include <io.h>
#include "defs.h"
void PError(char *Str);
void WinSockPError(char *Str);
void sleep(unsigned int Sec)
{
Sleep(Sec * 1000);
}
static unsigned int RandState;
void srandom(unsigned int Seed)
{
RandState = Seed;
}
unsigned int random(void)
{
RandState = RandState * 1103515245 + 12345;
return (RandState ^ (RandState >> 16)) & RAND_MAX;
}
int getpid(void)
{
return (int)GetCurrentThread();
}
int nanosleep(struct timespec *Req, struct timespec *Rem)
{
Sleep(Req->tv_sec * 1000 + Req->tv_nsec / 1000000);
Rem->tv_sec = 0;
Rem->tv_nsec = 0;
return 0;
}
void gettimeofday(struct timeval *TVal, void *TZone __attribute__((unused)))
{
SYSTEMTIME SysTime;
FILETIME FileTime;
unsigned __int64 Ticks;
GetSystemTime(&SysTime);
SystemTimeToFileTime(&SysTime, &FileTime);
Ticks = ((__int64)FileTime.dwHighDateTime << 32) |
(__int64)FileTime.dwLowDateTime;
Ticks -= 116444736000000000LL;
TVal->tv_sec = (unsigned int)(Ticks / 10000000);
TVal->tv_usec = (unsigned int)(Ticks % 10000000) / 10;
}
long times(struct tms *Dummy __attribute__((unused)))
{
return (long)GetTickCount();
}
int inet_aton(const char *AddrStr, struct in_addr *Addr)
{
Addr->s_addr = inet_addr(AddrStr);
return 1;
}
char *StrError(unsigned int ErrNo)
{
static char Msg[1000];
#if !defined WINCE
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Msg,
sizeof (Msg), NULL);
#else
short WideMsg[1000];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), WideMsg,
sizeof (WideMsg) / 2, NULL);
if (WideCharToMultiByte(CP_ACP, 0, WideMsg, -1, Msg, sizeof (Msg),
NULL, NULL) == 0)
strcpy(Msg, "[cannot convert string]");
#endif
return Msg;
}
void PError(char *Str)
{
fprintf(stderr, "ERROR - %s: %s", Str, StrError(GetLastError()));
}
void WinSockPError(char *Str)
{
fprintf(stderr, "ERROR - %s: %s", Str, StrError(WSAGetLastError()));
}
// XXX - not thread-safe, which is okay for our purposes
void *dlopen(char *Name, int Flags __attribute__((unused)))
{
#if !defined WINCE
return (void *)LoadLibrary(Name);
#else
short WideName[1000];
MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof (WideName));
return (void *)LoadLibrary(WideName);
#endif
}
int dlclose(void *Handle)
{
FreeLibrary((HMODULE)Handle);
return 0;
}
void *dlsym(void *Handle, char *Name)
{
#if !defined WINCE
return GetProcAddress((HMODULE)Handle, Name);
#else
short WideName[1000];
MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof (WideName));
return GetProcAddress((HMODULE)Handle, WideName);
#endif
}
char *dlerror(void)
{
return StrError(GetLastError());
}
#define NS_INADDRSZ 4
#define NS_IN6ADDRSZ 16
#define NS_INT16SZ 2
static int inet_pton4(const char *src, unsigned char *dst)
{
int saw_digit, octets, ch;
u_char tmp[NS_INADDRSZ], *tp;
saw_digit = 0;
octets = 0;
*(tp = tmp) = 0;
while ((ch = *src++) != '\0')
{
if (ch >= '0' && ch <= '9') {
unsigned int new = *tp * 10 + (ch - '0');
if (new > 255)
return (0);
*tp = new;
if (!saw_digit)
{
if (++octets > 4)
return (0);
saw_digit = 1;
}
}
else if (ch == '.' && saw_digit)
{
if (octets == 4)
return (0);
*++tp = 0;
saw_digit = 0;
}
else
return (0);
}
if (octets < 4)
return (0);
memcpy(dst, tmp, NS_INADDRSZ);
return (1);
}
static int inet_pton6(const char *src, unsigned char *dst)
{
static const char xdigits[] = "0123456789abcdef";
u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
const char *curtok;
int ch, saw_xdigit;
u_int val;
tp = memset(tmp, '\0', NS_IN6ADDRSZ);
endp = tp + NS_IN6ADDRSZ;
colonp = NULL;
if (*src == ':')
if (*++src != ':')
return (0);
curtok = src;
saw_xdigit = 0;
val = 0;
while ((ch = tolower (*src++)) != '\0')
{
const char *pch;
pch = strchr(xdigits, ch);
if (pch != NULL)
{
val <<= 4;
val |= (pch - xdigits);
if (val > 0xffff)
return (0);
saw_xdigit = 1;
continue;
}
if (ch == ':')
{
curtok = src;
if (!saw_xdigit)
{
if (colonp)
return (0);
colonp = tp;
continue;
}
else if (*src == '\0')
{
return (0);
}
if (tp + NS_INT16SZ > endp)
return (0);
*tp++ = (u_char) (val >> 8) & 0xff;
*tp++ = (u_char) val & 0xff;
saw_xdigit = 0;
val = 0;
continue;
}
if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
inet_pton4(curtok, tp) > 0)
{
tp += NS_INADDRSZ;
saw_xdigit = 0;
break;
}
return (0);
}
if (saw_xdigit)
{
if (tp + NS_INT16SZ > endp)
return (0);
*tp++ = (u_char) (val >> 8) & 0xff;
*tp++ = (u_char) val & 0xff;
}
if (colonp != NULL)
{
const int n = tp - colonp;
int i;
if (tp == endp)
return (0);
for (i = 1; i <= n; i++)
{
endp[- i] = colonp[n - i];
colonp[n - i] = 0;
}
tp = endp;
}
if (tp != endp)
return (0);
memcpy(dst, tmp, NS_IN6ADDRSZ);
return (1);
}
int inet_pton(int af, const char *src, void *dst)
{
switch (af)
{
case AF_INET:
return (inet_pton4(src, dst));
case AF_INET6:
return (inet_pton6(src, dst));
default:
return -1;
}
}
static char *inet_ntop4(const unsigned char *src, char *dst, int size)
{
static const char fmt[] = "%u.%u.%u.%u";
char tmp[sizeof "255.255.255.255"];
if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size)
return (NULL);
return strcpy(dst, tmp);
}
static char *inet_ntop6(const unsigned char *src, char *dst, int size)
{
char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
struct { int base, len; } best, cur;
u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
int i;
memset(words, '\0', sizeof words);
for (i = 0; i < NS_IN6ADDRSZ; i += 2)
words[i / 2] = (src[i] << 8) | src[i + 1];
best.base = -1;
cur.base = -1;
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
{
if (words[i] == 0)
{
if (cur.base == -1)
cur.base = i, cur.len = 1;
else
cur.len++;
}
else
{
if (cur.base != -1)
{
if (best.base == -1 || cur.len > best.len)
best = cur;
cur.base = -1;
}
}
}
if (cur.base != -1)
{
if (best.base == -1 || cur.len > best.len)
best = cur;
}
if (best.base != -1 && best.len < 2)
best.base = -1;
tp = tmp;
for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
{
if (best.base != -1 && i >= best.base && i < (best.base + best.len))
{
if (i == best.base)
*tp++ = ':';
continue;
}
if (i != 0)
*tp++ = ':';
if (i == 6 && best.base == 0 &&
(best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
{
if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
return (NULL);
tp += strlen(tp);
break;
}
tp += sprintf(tp, "%x", words[i]);
}
if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ))
*tp++ = ':';
*tp++ = '\0';
if ((tp - tmp) > size)
return (NULL);
return strcpy(dst, tmp);
}
char *inet_ntop(int af, const void *src, char *dst, int size)
{
switch (af)
{
case AF_INET:
return (inet_ntop4(src, dst, size));
case AF_INET6:
return (inet_ntop6(src, dst, size));
default:
return (NULL);
}
}
int isatty(int fd)
{
#if !defined WINCE
HANDLE Hand;
CONSOLE_SCREEN_BUFFER_INFO Info;
unsigned long Events;
if (fd == 0)
{
Hand = GetStdHandle(STD_INPUT_HANDLE);
return GetNumberOfConsoleInputEvents(Hand, &Events);
}
else if (fd == 1)
{
Hand = GetStdHandle(STD_OUTPUT_HANDLE);
return GetConsoleScreenBufferInfo(Hand, &Info);
}
else if (fd == 2)
{
Hand = GetStdHandle(STD_ERROR_HANDLE);
return GetConsoleScreenBufferInfo(Hand, &Info);
}
return -1;
#else
return 0;
#endif
}
#define CHUNK_SIZE 512
/* and we emulate a real write(2) syscall using send() */
int write(int fd, const void *buf, unsigned int count)
{
size_t written = 0;
while (written < count) {
ssize_t rc = send(fd, buf+written, min(count-written, CHUNK_SIZE), 0);
if (rc <= 0) {
break;
}
written += rc;
}
return written;
}
syntax highlighted by Code2HTML, v. 0.9.1