62b9aac28f7b5101cad229b2ac6a82054a7c5c12
[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.12 2005/03/21 02:17:36 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 <sys/times.h>
62 #include <ctype.h>
63 #include <dlfcn.h>
64 #include "defs.h"
65
66 void PError(char *Str);
67 void WinSockPError(char *Str);
68
69 void sleep(unsigned int Sec)
70 {
71   Sleep(Sec * 1000);
72 }
73
74 static unsigned int RandState;
75
76 void srandom(unsigned int Seed)
77 {
78   RandState = Seed;
79 }
80
81 unsigned int random(void)
82 {
83   RandState = RandState * 1103515245 + 12345;
84
85   return (RandState ^ (RandState >> 16)) & RAND_MAX;
86 }
87
88 int getpid(void)
89 {
90   return (int)GetCurrentThread();
91 }
92
93 int nanosleep(struct timespec *Req, struct timespec *Rem)
94 {
95   Sleep(Req->tv_sec * 1000 + Req->tv_nsec / 1000000);
96
97   Rem->tv_sec = 0;
98   Rem->tv_nsec = 0;
99
100   return 0;
101 }
102
103 void gettimeofday(struct timeval *TVal, void *TZone)
104 {
105   SYSTEMTIME SysTime;
106   FILETIME FileTime;
107   unsigned __int64 Ticks;
108
109   GetSystemTime(&SysTime);
110   SystemTimeToFileTime(&SysTime, &FileTime);
111
112   Ticks = ((__int64)FileTime.dwHighDateTime << 32) |
113     (__int64)FileTime.dwLowDateTime;
114
115   Ticks -= 116444736000000000LL;
116
117   TVal->tv_sec = (unsigned int)(Ticks / 10000000);
118   TVal->tv_usec = (unsigned int)(Ticks % 10000000) / 10;
119 }
120
121 long times(struct tms *Dummy)
122 {
123   return (long)GetTickCount();
124 }
125
126 int inet_aton(char *AddrStr, struct in_addr *Addr)
127 {
128   Addr->s_addr = inet_addr(AddrStr);
129
130   return 1;
131 }
132
133 char *StrError(unsigned int ErrNo)
134 {
135   static char Msg[1000];
136
137 #if !defined WINCE
138   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo,
139                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Msg,
140                 sizeof (Msg), NULL);
141 #else
142   short WideMsg[1000];
143
144   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo,
145                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), WideMsg,
146                 sizeof (WideMsg) / 2, NULL);
147
148   if (WideCharToMultiByte(CP_ACP, 0, WideMsg, -1, Msg, sizeof (Msg),
149                           NULL, NULL) == 0)
150     strcpy(Msg, "[cannot convert string]");
151 #endif
152
153   return Msg;
154 }
155
156 void PError(char *Str)
157 {
158   fprintf(stderr, "ERROR - %s: %s", Str, StrError(GetLastError()));
159 }
160
161 void WinSockPError(char *Str)
162 {
163   fprintf(stderr, "ERROR - %s: %s", Str, StrError(WSAGetLastError()));
164 }
165
166 // XXX - not thread-safe, which is okay for our purposes
167  
168 void *dlopen(char *Name, int Flags)
169 {
170 #if !defined WINCE
171   return (void *)LoadLibrary(Name);
172 #else
173   short WideName[1000];
174
175   MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof (WideName));
176   return (void *)LoadLibrary(WideName);
177 #endif
178 }
179
180 int dlclose(void *Handle)
181 {
182   FreeLibrary((HMODULE)Handle);
183   return 0;
184 }
185
186 void *dlsym(void *Handle, char *Name)
187 {
188 #if !defined WINCE
189   return GetProcAddress((HMODULE)Handle, Name);
190 #else
191   short WideName[1000];
192
193   MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof (WideName));
194   return GetProcAddress((HMODULE)Handle, WideName);
195 #endif
196 }
197
198 char *dlerror(void)
199 {
200   return StrError(GetLastError());
201 }
202
203 #define NS_INADDRSZ 4
204 #define NS_IN6ADDRSZ 16
205 #define NS_INT16SZ 2
206
207 static int inet_pton4(const char *src, unsigned char *dst)
208 {
209   int saw_digit, octets, ch;
210   u_char tmp[NS_INADDRSZ], *tp;
211
212   saw_digit = 0;
213   octets = 0;
214   *(tp = tmp) = 0;
215
216   while ((ch = *src++) != '\0')
217   {
218     if (ch >= '0' && ch <= '9') {
219       unsigned int new = *tp * 10 + (ch - '0');
220
221       if (new > 255)
222         return (0);
223
224       *tp = new;
225
226       if (!saw_digit)
227       {
228         if (++octets > 4)
229           return (0);
230
231         saw_digit = 1;
232       }
233     }
234
235     else if (ch == '.' && saw_digit)
236     {
237       if (octets == 4)
238         return (0);
239
240       *++tp = 0;
241
242       saw_digit = 0;
243     }
244
245     else
246       return (0);
247   }
248
249   if (octets < 4)
250     return (0);
251
252   memcpy(dst, tmp, NS_INADDRSZ);
253   return (1);
254 }
255
256 static int inet_pton6(const char *src, unsigned char *dst)
257 {
258   static const char xdigits[] = "0123456789abcdef";
259   u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
260   const char *curtok;
261   int ch, saw_xdigit;
262   u_int val;
263
264   tp = memset(tmp, '\0', NS_IN6ADDRSZ);
265   endp = tp + NS_IN6ADDRSZ;
266   colonp = NULL;
267
268   if (*src == ':')
269     if (*++src != ':')
270       return (0);
271
272   curtok = src;
273   saw_xdigit = 0;
274   val = 0;
275
276   while ((ch = tolower (*src++)) != '\0')
277   {
278     const char *pch;
279
280     pch = strchr(xdigits, ch);
281
282     if (pch != NULL)
283     {
284       val <<= 4;
285       val |= (pch - xdigits);
286
287       if (val > 0xffff)
288         return (0);
289
290       saw_xdigit = 1;
291       continue;
292     }
293
294     if (ch == ':')
295     {
296       curtok = src;
297
298       if (!saw_xdigit)
299       {
300         if (colonp)
301           return (0);
302
303         colonp = tp;
304         continue;
305       }
306
307       else if (*src == '\0')
308       {
309         return (0);
310       }
311
312       if (tp + NS_INT16SZ > endp)
313         return (0);
314
315       *tp++ = (u_char) (val >> 8) & 0xff;
316       *tp++ = (u_char) val & 0xff;
317       saw_xdigit = 0;
318       val = 0;
319       continue;
320     }
321
322     if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
323         inet_pton4(curtok, tp) > 0)
324     {
325       tp += NS_INADDRSZ;
326       saw_xdigit = 0;
327       break;
328     }
329
330     return (0);
331   }
332
333   if (saw_xdigit)
334   {
335     if (tp + NS_INT16SZ > endp)
336       return (0);
337
338     *tp++ = (u_char) (val >> 8) & 0xff;
339     *tp++ = (u_char) val & 0xff;
340   }
341
342   if (colonp != NULL)
343   {
344     const int n = tp - colonp;
345     int i;
346
347     if (tp == endp)
348       return (0);
349
350     for (i = 1; i <= n; i++)
351     {
352       endp[- i] = colonp[n - i];
353       colonp[n - i] = 0;
354     }
355
356     tp = endp;
357   }
358
359   if (tp != endp)
360     return (0);
361
362   memcpy(dst, tmp, NS_IN6ADDRSZ);
363   return (1);
364 }
365
366 int inet_pton(int af, char *src, void *dst)
367 {
368   switch (af)
369   {
370   case AF_INET:
371     return (inet_pton4(src, dst));
372
373   case AF_INET6:
374     return (inet_pton6(src, dst));
375
376   default:
377     return -1;
378   }
379 }
380
381 static char *inet_ntop4(const unsigned char *src, char *dst, int size)
382 {
383   static const char fmt[] = "%u.%u.%u.%u";
384   char tmp[sizeof "255.255.255.255"];
385
386   if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size)
387     return (NULL);
388
389   return strcpy(dst, tmp);
390 }
391
392 static char *inet_ntop6(const unsigned char *src, char *dst, int size)
393 {
394   char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
395   struct { int base, len; } best, cur;
396   u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
397   int i;
398
399   memset(words, '\0', sizeof words);
400
401   for (i = 0; i < NS_IN6ADDRSZ; i += 2)
402     words[i / 2] = (src[i] << 8) | src[i + 1];
403
404   best.base = -1;
405   cur.base = -1;
406
407   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
408   {
409     if (words[i] == 0)
410     {
411       if (cur.base == -1)
412         cur.base = i, cur.len = 1;
413
414       else
415         cur.len++;
416     }
417
418     else
419     {
420       if (cur.base != -1)
421       {
422         if (best.base == -1 || cur.len > best.len)
423           best = cur;
424
425         cur.base = -1;
426       }
427     }
428   }
429
430   if (cur.base != -1)
431   {
432     if (best.base == -1 || cur.len > best.len)
433       best = cur;
434   }
435
436   if (best.base != -1 && best.len < 2)
437     best.base = -1;
438
439   tp = tmp;
440
441   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++)
442   {
443     if (best.base != -1 && i >= best.base && i < (best.base + best.len))
444     {
445       if (i == best.base)
446         *tp++ = ':';
447
448       continue;
449     }
450
451     if (i != 0)
452       *tp++ = ':';
453
454     
455     if (i == 6 && best.base == 0 &&
456         (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
457     {
458       if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
459         return (NULL);
460
461       tp += strlen(tp);
462
463       break;
464     }
465
466     tp += sprintf(tp, "%x", words[i]);
467   }
468
469   if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ))
470     *tp++ = ':';
471
472   *tp++ = '\0';
473
474   if ((tp - tmp) > size)
475     return (NULL);
476
477   return strcpy(dst, tmp);
478 }
479
480 char *inet_ntop(int af, void *src, char *dst, int size)
481 {
482   switch (af)
483   {
484   case AF_INET:
485     return (inet_ntop4(src, dst, size));
486
487   case AF_INET6:
488     return (inet_ntop6(src, dst, size));
489
490   default:
491     return (NULL);
492   }
493 }
494
495 int isatty(int fd)
496 {
497 #if !defined WINCE
498   HANDLE Hand;
499   CONSOLE_SCREEN_BUFFER_INFO Info;
500   unsigned long Events;
501
502   if (fd == 0)
503   {
504     Hand = GetStdHandle(STD_INPUT_HANDLE);
505     return GetNumberOfConsoleInputEvents(Hand, &Events);
506   }
507
508   else if (fd == 1)
509   {
510     Hand = GetStdHandle(STD_OUTPUT_HANDLE);
511     return GetConsoleScreenBufferInfo(Hand, &Info);
512   }
513
514   else if (fd == 2)
515   {
516     Hand = GetStdHandle(STD_ERROR_HANDLE);
517     return GetConsoleScreenBufferInfo(Hand, &Info);
518   }
519
520   return -1;
521 #else
522   return 0;
523 #endif
524 }