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