dd85eec4a0a61b4faf9a0dade813a8574c70c9b7
[olsrd.git] / src / win32 / compat.c
1 /* 
2  * OLSR ad-hoc routing table management protocol
3  * Copyright (C) 2004 Thomas Lopatic (thomas@lopatic.de)
4  *
5  * This file is part of the olsr.org OLSR daemon.
6  *
7  * olsr.org is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * olsr.org is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with olsr.org; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * $Id: compat.c,v 1.9 2004/11/17 17:03:39 tlopatic Exp $
22  *
23  */
24
25 /*
26  * Copyright (c) 1996,1999 by Internet Software Consortium.
27  *
28  * Permission to use, copy, modify, and distribute this software for any
29  * purpose with or without fee is hereby granted, provided that the above
30  * copyright notice and this permission notice appear in all copies.
31  *
32  * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
33  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
34  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
35  * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
38  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
39  * SOFTWARE.
40  */
41
42 #include <unistd.h>
43 #include <sys/time.h>
44 #include <ctype.h>
45 #include <dlfcn.h>
46 #include "defs.h"
47
48 void PError(char *Str);
49 void WinSockPError(char *Str);
50
51 void sleep(unsigned int Sec)
52 {
53   Sleep(Sec * 1000);
54 }
55
56 static unsigned int RandState;
57
58 void srandom(unsigned int Seed)
59 {
60   RandState = Seed;
61 }
62
63 unsigned int random(void)
64 {
65   RandState = RandState * 1103515245 + 12345;
66
67   return (RandState ^ (RandState >> 16)) % (RAND_MAX + 1);
68 }
69
70 int getpid(void)
71 {
72   return (int)GetCurrentThread();
73 }
74
75 int nanosleep(struct timespec *Req, struct timespec *Rem)
76 {
77   Sleep(Req->tv_sec * 1000 + Req->tv_nsec / 1000000);
78
79   Rem->tv_sec = 0;
80   Rem->tv_nsec = 0;
81
82   return 0;
83 }
84
85 void gettimeofday(struct timeval *TVal, void *TZone)
86 {
87   SYSTEMTIME SysTime;
88   FILETIME FileTime;
89   unsigned __int64 Ticks;
90
91   GetSystemTime(&SysTime);
92   SystemTimeToFileTime(&SysTime, &FileTime);
93
94   Ticks = ((__int64)FileTime.dwHighDateTime << 32) |
95     (__int64)FileTime.dwLowDateTime;
96
97   Ticks -= 116444736000000000LL;
98
99   TVal->tv_sec = (unsigned int)(Ticks / 10000000);
100   TVal->tv_usec = (unsigned int)(Ticks % 10000000) / 10;
101 }
102
103 int inet_aton(char *AddrStr, struct in_addr *Addr)
104 {
105   Addr->s_addr = inet_addr(AddrStr);
106
107   return 1;
108 }
109
110 char *StrError(unsigned int ErrNo)
111 {
112   static char Msg[1000];
113   
114   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo,
115                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Msg,
116                 sizeof (Msg), NULL);
117         
118   return Msg;
119 }
120
121 void PError(char *Str)
122 {
123   char Msg[1000];
124   int Len;
125
126   sprintf(Msg, "ERROR - %s: ", Str);
127
128   Len = strlen(Msg);
129
130   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
131                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Msg + Len,
132                 sizeof (Msg) - Len, NULL);
133
134   fprintf(stderr, "%s\n", Msg);
135 }
136
137 void WinSockPError(char *Str)
138 {
139   char Msg[1000];
140   int Len;
141
142   sprintf(Msg, "ERROR - %s: ", Str);
143
144   Len = strlen(Msg);
145
146   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, WSAGetLastError(),
147                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Msg + Len,
148                 sizeof (Msg) - Len, NULL);
149
150   fprintf(stderr, "%s\n", Msg);
151 }
152
153 // XXX - not thread-safe, which is okay for our purposes
154  
155 void *dlopen(char *Name, int Flags)
156 {
157   return (void *)LoadLibrary(Name);
158 }
159
160 int dlclose(void *Handle)
161 {
162   FreeLibrary((HMODULE)Handle);
163   return 0;
164 }
165
166 void *dlsym(void *Handle, char *Name)
167 {
168   return GetProcAddress((HMODULE)Handle, Name);
169 }
170
171 char *dlerror(void)
172 {
173   return StrError(GetLastError());
174 }
175
176 #define NS_INADDRSZ 4
177 #define NS_IN6ADDRSZ 16
178 #define NS_INT16SZ 2
179
180 static int inet_pton4(const char *src, unsigned char *dst)
181 {
182   int saw_digit, octets, ch;
183   u_char tmp[NS_INADDRSZ], *tp;
184
185   saw_digit = 0;
186   octets = 0;
187   *(tp = tmp) = 0;
188
189   while ((ch = *src++) != '\0')
190   {
191     if (ch >= '0' && ch <= '9') {
192       unsigned int new = *tp * 10 + (ch - '0');
193
194       if (new > 255)
195         return (0);
196
197       *tp = new;
198
199       if (!saw_digit)
200       {
201         if (++octets > 4)
202           return (0);
203
204         saw_digit = 1;
205       }
206     }
207
208     else if (ch == '.' && saw_digit)
209     {
210       if (octets == 4)
211         return (0);
212
213       *++tp = 0;
214
215       saw_digit = 0;
216     }
217
218     else
219       return (0);
220   }
221
222   if (octets < 4)
223     return (0);
224
225   memcpy(dst, tmp, NS_INADDRSZ);
226   return (1);
227 }
228
229 static int inet_pton6(const char *src, unsigned char *dst)
230 {
231   static const char xdigits[] = "0123456789abcdef";
232   u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
233   const char *curtok;
234   int ch, saw_xdigit;
235   u_int val;
236
237   tp = memset(tmp, '\0', NS_IN6ADDRSZ);
238   endp = tp + NS_IN6ADDRSZ;
239   colonp = NULL;
240
241   if (*src == ':')
242     if (*++src != ':')
243       return (0);
244
245   curtok = src;
246   saw_xdigit = 0;
247   val = 0;
248
249   while ((ch = tolower (*src++)) != '\0')
250   {
251     const char *pch;
252
253     pch = strchr(xdigits, ch);
254
255     if (pch != NULL)
256     {
257       val <<= 4;
258       val |= (pch - xdigits);
259
260       if (val > 0xffff)
261         return (0);
262
263       saw_xdigit = 1;
264       continue;
265     }
266
267     if (ch == ':')
268     {
269       curtok = src;
270
271       if (!saw_xdigit)
272       {
273         if (colonp)
274           return (0);
275
276         colonp = tp;
277         continue;
278       }
279
280       else if (*src == '\0')
281       {
282         return (0);
283       }
284
285       if (tp + NS_INT16SZ > endp)
286         return (0);
287
288       *tp++ = (u_char) (val >> 8) & 0xff;
289       *tp++ = (u_char) val & 0xff;
290       saw_xdigit = 0;
291       val = 0;
292       continue;
293     }
294
295     if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
296         inet_pton4(curtok, tp) > 0)
297     {
298       tp += NS_INADDRSZ;
299       saw_xdigit = 0;
300       break;
301     }
302
303     return (0);
304   }
305
306   if (saw_xdigit)
307   {
308     if (tp + NS_INT16SZ > endp)
309       return (0);
310
311     *tp++ = (u_char) (val >> 8) & 0xff;
312     *tp++ = (u_char) val & 0xff;
313   }
314
315   if (colonp != NULL)
316   {
317     const int n = tp - colonp;
318     int i;
319
320     if (tp == endp)
321       return (0);
322
323     for (i = 1; i <= n; i++)
324     {
325       endp[- i] = colonp[n - i];
326       colonp[n - i] = 0;
327     }
328
329     tp = endp;
330   }
331
332   if (tp != endp)
333     return (0);
334
335   memcpy(dst, tmp, NS_IN6ADDRSZ);
336   return (1);
337 }
338
339 int inet_pton(int af, char *src, void *dst)
340 {
341   switch (af)
342   {
343   case AF_INET:
344     return (inet_pton4(src, dst));
345
346   case AF_INET6:
347     return (inet_pton6(src, dst));
348
349   default:
350     return -1;
351   }
352 }
353
354 static char *inet_ntop4(const unsigned char *src, char *dst, int size)
355 {
356   static const char fmt[] = "%u.%u.%u.%u";
357   char tmp[sizeof "255.255.255.255"];
358
359   if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size)
360     return (NULL);
361
362   return strcpy(dst, tmp);
363 }
364
365 static char *inet_ntop6(const unsigned char *src, char *dst, int size)
366 {
367   char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
368   struct { int base, len; } best, cur;
369   u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
370   int i;
371
372   memset(words, '\0', sizeof words);
373
374   for (i = 0; i < NS_IN6ADDRSZ; i += 2)
375     words[i / 2] = (src[i] << 8) | src[i + 1];
376
377   best.base = -1;
378   cur.base = -1;
379
380   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
381   {
382     if (words[i] == 0)
383     {
384       if (cur.base == -1)
385         cur.base = i, cur.len = 1;
386
387       else
388         cur.len++;
389     }
390
391     else
392     {
393       if (cur.base != -1)
394       {
395         if (best.base == -1 || cur.len > best.len)
396           best = cur;
397
398         cur.base = -1;
399       }
400     }
401   }
402
403   if (cur.base != -1)
404   {
405     if (best.base == -1 || cur.len > best.len)
406       best = cur;
407   }
408
409   if (best.base != -1 && best.len < 2)
410     best.base = -1;
411
412   tp = tmp;
413
414   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
415   {
416     if (best.base != -1 && i >= best.base && i < (best.base + best.len))
417     {
418       if (i == best.base)
419         *tp++ = ':';
420
421       continue;
422     }
423
424     if (i != 0)
425       *tp++ = ':';
426
427     
428     if (i == 6 && best.base == 0 &&
429         (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
430     {
431       if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
432         return (NULL);
433
434       tp += strlen(tp);
435
436       break;
437     }
438
439     tp += sprintf(tp, "%x", words[i]);
440   }
441
442   if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ))
443     *tp++ = ':';
444
445   *tp++ = '\0';
446
447   if ((tp - tmp) > size)
448     return (NULL);
449
450   return strcpy(dst, tmp);
451 }
452
453 char *inet_ntop(int af, void *src, char *dst, int size)
454 {
455   switch (af)
456   {
457   case AF_INET:
458     return (inet_ntop4(src, dst, size));
459
460   case AF_INET6:
461     return (inet_ntop6(src, dst, size));
462
463   default:
464     return (NULL);
465   }
466 }
467
468 int isatty(int fd)
469 {
470   HANDLE Hand;
471   CONSOLE_SCREEN_BUFFER_INFO Info;
472   unsigned long Events;
473
474   if (fd == 0)
475   {
476     Hand = GetStdHandle(STD_INPUT_HANDLE);
477     return GetNumberOfConsoleInputEvents(Hand, &Events);
478   }
479
480   else if (fd == 1)
481   {
482     Hand = GetStdHandle(STD_OUTPUT_HANDLE);
483     return GetConsoleScreenBufferInfo(Hand, &Info);
484   }
485
486   else if (fd == 2)
487   {
488     Hand = GetStdHandle(STD_ERROR_HANDLE);
489     return GetConsoleScreenBufferInfo(Hand, &Info);
490   }
491
492   return -1;
493 }