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