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