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