Fix win32 compile
[olsrd.git] / src / win32 / compat.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
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 #include <unistd.h>
60 #include <sys/time.h>
61 #include <ctype.h>
62 #include <dlfcn.h>
63 #include <io.h>
64 #include <arpa/inet.h>
65 #include <stdio.h>
66
67 #include "defs.h"
68 #include "common/string.h"
69 #include "os_time.h"
70
71 static unsigned int RandState;
72
73 void
74 srandom(unsigned int Seed)
75 {
76   RandState = Seed;
77 }
78
79 unsigned int
80 random(void)
81 {
82   RandState = RandState * 1103515245 + 12345;
83
84   return (RandState ^ (RandState >> 16)) & RAND_MAX;
85 }
86
87 int
88 getpid(void)
89 {
90   HANDLE h = GetCurrentThread();
91   return (int)h;
92 }
93
94 char *
95 win32_strerror(unsigned int ErrNo)
96 {
97   static char Msg[1000];
98
99 #if !defined WINCE
100   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), Msg, sizeof(Msg), NULL);
101 #else
102   short WideMsg[1000];
103
104   FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrNo,
105                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), WideMsg, sizeof(WideMsg) / 2, NULL);
106
107   if (WideCharToMultiByte(CP_ACP, 0, WideMsg, -1, Msg, sizeof(Msg), NULL, NULL) == 0)
108     strscpy(Msg, "[cannot convert string]", sizeof(Msg));
109 #endif
110
111   return Msg;
112 }
113
114 // XXX - not thread-safe, which is okay for our purposes
115 void *
116 dlopen(const char *Name, int Flags __attribute__ ((unused)))
117 {
118 #if !defined WINCE
119   return (void *)LoadLibrary(Name);
120 #else
121   short WideName[1000];
122
123   MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof(WideName));
124   return (void *)LoadLibrary(WideName);
125 #endif
126 }
127
128 int
129 dlclose(void *Handle)
130 {
131   FreeLibrary((HMODULE) Handle);
132   return 0;
133 }
134
135 void *
136 dlsym(void *Handle, const char *Name)
137 {
138 #if !defined WINCE
139   return GetProcAddress((HMODULE) Handle, Name);
140 #else
141   short WideName[1000];
142
143   MultiByteToWideChar(CP_ACP, 0, Name, -1, WideName, sizeof(WideName));
144   return GetProcAddress((HMODULE) Handle, WideName);
145 #endif
146 }
147
148 char *
149 dlerror(void)
150 {
151   return win32_strerror(GetLastError());
152 }
153
154 #define NS_INADDRSZ 4
155 #define NS_IN6ADDRSZ 16
156 #define NS_INT16SZ 2
157
158 static int
159 inet_pton4(const char *src, unsigned char *dst)
160 {
161   int saw_digit, octets, ch;
162   u_char tmp[NS_INADDRSZ], *tp;
163
164   saw_digit = 0;
165   octets = 0;
166   *(tp = tmp) = 0;
167
168   while ((ch = *src++) != '\0') {
169     if (ch >= '0' && ch <= '9') {
170       unsigned int new = *tp * 10 + (ch - '0');
171
172       if (new > 255)
173         return (0);
174
175       *tp = new;
176
177       if (!saw_digit) {
178         if (++octets > 4)
179           return (0);
180
181         saw_digit = 1;
182       }
183     }
184
185     else if (ch == '.' && saw_digit) {
186       if (octets == 4)
187         return (0);
188
189       *++tp = 0;
190
191       saw_digit = 0;
192     }
193
194     else
195       return (0);
196   }
197
198   if (octets < 4)
199     return (0);
200
201   memcpy(dst, tmp, NS_INADDRSZ);
202   return (1);
203 }
204
205 static int
206 inet_pton6(const char *src, unsigned char *dst)
207 {
208   static const char xdigits[] = "0123456789abcdef";
209   u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
210   const char *curtok;
211   int ch, saw_xdigit;
212   u_int val;
213
214   tp = memset(tmp, '\0', NS_IN6ADDRSZ);
215   endp = tp + NS_IN6ADDRSZ;
216   colonp = NULL;
217
218   if (*src == ':')
219     if (*++src != ':')
220       return (0);
221
222   curtok = src;
223   saw_xdigit = 0;
224   val = 0;
225
226   while ((ch = tolower(*src++)) != '\0') {
227     const char *pch;
228
229     pch = strchr(xdigits, ch);
230
231     if (pch != NULL) {
232       val <<= 4;
233       val |= (pch - xdigits);
234
235       if (val > 0xffff)
236         return (0);
237
238       saw_xdigit = 1;
239       continue;
240     }
241
242     if (ch == ':') {
243       curtok = src;
244
245       if (!saw_xdigit) {
246         if (colonp)
247           return (0);
248
249         colonp = tp;
250         continue;
251       }
252
253       else if (*src == '\0') {
254         return (0);
255       }
256
257       if (tp + NS_INT16SZ > endp)
258         return (0);
259
260       *tp++ = (u_char) (val >> 8) & 0xff;
261       *tp++ = (u_char) val & 0xff;
262       saw_xdigit = 0;
263       val = 0;
264       continue;
265     }
266
267     if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0) {
268       tp += NS_INADDRSZ;
269       saw_xdigit = 0;
270       break;
271     }
272
273     return (0);
274   }
275
276   if (saw_xdigit) {
277     if (tp + NS_INT16SZ > endp)
278       return (0);
279
280     *tp++ = (u_char) (val >> 8) & 0xff;
281     *tp++ = (u_char) val & 0xff;
282   }
283
284   if (colonp != NULL) {
285     const int n = tp - colonp;
286     int i;
287
288     if (tp == endp)
289       return (0);
290
291     for (i = 1; i <= n; i++) {
292       endp[-i] = colonp[n - i];
293       colonp[n - i] = 0;
294     }
295
296     tp = endp;
297   }
298
299   if (tp != endp)
300     return (0);
301
302   memcpy(dst, tmp, NS_IN6ADDRSZ);
303   return (1);
304 }
305
306 int
307 inet_pton(int af, const char *src, void *dst)
308 {
309   switch (af) {
310   case AF_INET:
311     return (inet_pton4(src, dst));
312
313   case AF_INET6:
314     return (inet_pton6(src, dst));
315
316   default:
317     return -1;
318   }
319 }
320
321 static char *
322 inet_ntop4(const unsigned char *src, char *dst, int size)
323 {
324   static const char fmt[] = "%u.%u.%u.%u";
325   char tmp[sizeof "255.255.255.255"];
326
327   if (sprintf(tmp, fmt, src[0], src[1], src[2], src[3]) > size)
328     return (NULL);
329
330   return strscpy(dst, tmp, size);
331 }
332
333 static char *
334 inet_ntop6(const unsigned char *src, char *dst, int size)
335 {
336   char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
337   struct {
338     int base, len;
339   } best, cur;
340   u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
341   int i;
342
343   memset(words, '\0', sizeof words);
344
345   for (i = 0; i < NS_IN6ADDRSZ; i += 2)
346     words[i / 2] = (src[i] << 8) | src[i + 1];
347
348   best.base = -1;
349   cur.base = -1;
350
351   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
352     if (words[i] == 0) {
353       if (cur.base == -1)
354         cur.base = i, cur.len = 1;
355
356       else
357         cur.len++;
358     }
359
360     else {
361       if (cur.base != -1) {
362         if (best.base == -1 || cur.len > best.len)
363           best = cur;
364
365         cur.base = -1;
366       }
367     }
368   }
369
370   if (cur.base != -1) {
371     if (best.base == -1 || cur.len > best.len)
372       best = cur;
373   }
374
375   if (best.base != -1 && best.len < 2)
376     best.base = -1;
377
378   tp = tmp;
379
380   for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
381     if (best.base != -1 && i >= best.base && i < (best.base + best.len)) {
382       if (i == best.base)
383         *tp++ = ':';
384
385       continue;
386     }
387
388     if (i != 0)
389       *tp++ = ':';
390
391
392     if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) {
393       if (!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
394         return (NULL);
395
396       tp += strlen(tp);
397
398       break;
399     }
400
401     tp += sprintf(tp, "%x", words[i]);
402   }
403
404   if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ))
405     *tp++ = ':';
406
407   *tp++ = '\0';
408
409   if ((tp - tmp) > size)
410     return (NULL);
411
412   return strscpy(dst, tmp, size);
413 }
414
415 char *
416 inet_ntop(int af, const void *src, char *dst, int size)
417 {
418   switch (af) {
419   case AF_INET:
420     return (inet_ntop4(src, dst, size));
421
422   case AF_INET6:
423     return (inet_ntop6(src, dst, size));
424
425   default:
426     return (NULL);
427   }
428 }
429
430 int
431 isatty(int fd)
432 {
433 #if !defined WINCE
434   HANDLE Hand;
435   CONSOLE_SCREEN_BUFFER_INFO Info;
436   unsigned long Events;
437
438   if (fd == 0) {
439     Hand = GetStdHandle(STD_INPUT_HANDLE);
440     return GetNumberOfConsoleInputEvents(Hand, &Events);
441   }
442
443   else if (fd == 1) {
444     Hand = GetStdHandle(STD_OUTPUT_HANDLE);
445     return GetConsoleScreenBufferInfo(Hand, &Info);
446   }
447
448   else if (fd == 2) {
449     Hand = GetStdHandle(STD_ERROR_HANDLE);
450     return GetConsoleScreenBufferInfo(Hand, &Info);
451   }
452
453   return -1;
454 #else
455   return 0;
456 #endif
457 }
458
459 #define CHUNK_SIZE 512
460
461 /* and we emulate a real write(2) syscall using send() */
462 int
463 write(int fd, const void *buf, unsigned int count)
464 {
465   size_t written = 0;
466   while (written < count) {
467     ssize_t rc = send(fd, (const void *)((const unsigned char *)buf + written),
468                       min(count - written, CHUNK_SIZE), 0);
469     if (rc <= 0) {
470       break;
471     }
472     written += rc;
473   }
474   return written;
475 }
476
477 /*
478  * Local Variables:
479  * c-basic-offset: 2
480  * indent-tabs-mode: nil
481  * End:
482  */