Make srvx compile on cygwin again.
[srvx.git] / src / compat.c
1 #undef gettimeofday
2 #undef memcpy
3 #undef memset
4 #undef strerror
5
6 #include "common.h"
7
8 #ifdef HAVE_SYS_TIMEB_H
9 # include <sys/timeb.h>
10 #endif
11 #ifdef HAVE_MEMORY_H
12 # include <memory.h>
13 #endif
14 #ifdef HAVE_ARPA_INET_H
15 # include <arpa/inet.h>
16 #endif
17
18 #if !defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME)
19 extern gettimeofday(struct timeval * tv, struct timezone * tz);
20 {
21     if (!tv)
22     {
23         errno = EFAULT;
24         return -1;
25     }
26
27     struct timeb tb;
28
29     ftime(&tb); /* FIXME: some versions are void return others int */
30
31     tv->tv_sec  = tb.time;
32     tv->tv_usec = ((long)tb.millitm)*1000;
33     if (tz)
34     {
35         tz->tz_minuteswest = 0;
36         tz->tz_dsttime     = 0;
37     }
38
39     return 0;
40 }
41 #endif
42
43 #ifndef HAVE_MEMCPY
44 extern void * memcpy(void * dest, void const * src, unsigned long n)
45 {
46 /* very slow, your fault for not having memcpy()*/
47     unsigned char * td=dest;
48     unsigned char * ts=src;
49     unsigned long   i;
50
51     if (!td || !ts)
52         return NULL;
53
54     for (i=0; i<n; i++)
55         td[i] = ts[i];
56     return dest;
57 }
58 #endif
59
60 #ifndef HAVE_MEMSET
61 /* very slow, deal with it */
62 extern void * memset(void * dest, int c, unsigned long n)
63 {
64     unsigned char * temp=dest;
65     unsigned long   i;
66
67     if (!temp)
68         return NULL;
69
70     for (i=0; i<n; i++)
71         temp[i] = (unsigned char)c;
72     return dest;
73 }
74 #endif
75
76 #ifndef HAVE_STRDUP
77 extern char * strdup(char const * str)
78 {
79     char * out;
80
81     if (!str)
82         return NULL;
83     if (!(out = malloc(strlen(str)+1)))
84         return NULL;
85     strcpy(out,str);
86     return out;
87 }
88 #endif
89
90 #ifndef HAVE_STRERROR
91 extern char const * strerror(int errornum)
92 {
93     if (errornum==0)
94         return "No error";
95 #ifdef EPERM
96     if (errornum==EPERM)
97         return "Operation not permitted";
98 #endif
99 #ifdef ENOENT
100     if (errornum==ENOENT)
101         return "No such file or directory";
102 #endif
103 #ifdef ESRCH
104     if (errornum==ESRCH)
105         return "No such process";
106 #endif
107 #ifdef EINTR
108     if (errornum==EINTR)
109         return "Interrupted system call";
110 #endif
111 #ifdef EIO
112     if (errornum==EIO)
113         return "I/O error";
114 #endif
115 #ifdef ENXIO
116     if (errornum==EIO)
117         return "No such device or address";
118 #endif
119 #ifdef EBADF
120     if (errornum==EBADF)
121         return "Bad file number";
122 #endif
123 #ifdef EAGAIN
124     if (errornum==EAGAIN)
125         return "Try again";
126 #endif
127 #ifdef ENOMEM
128     if (errornum==ENOMEM)
129         return "Out of memory";
130 #endif
131 #ifdef EACCES
132     if (errornum==EACCES)
133         return "Permission denied";
134 #endif
135 #ifdef EFAULT
136     if (errornum==EFAULT)
137         return "Bad address";
138 #endif
139 #ifdef EBUSY
140     if (errornum==EBUSY)
141         return "Device or resource busy";
142 #endif
143 #ifdef EEXIST
144     if (errornum==EEXIST)
145         return "File exists";
146 #endif
147 #ifdef EXDEV
148     if (errornum==EXDEV)
149         return "Cross-device link";
150 #endif
151 #ifdef EDEADLK
152     if (errornum==EXDEV)
153         return "Resource deadlock would occur";
154 #endif
155 #ifdef EDEADLOCK
156     if (errornum==EDEADLOCK)
157         return "Resource deadlock would occur";
158 #endif
159 #ifdef ENODEV
160     if (errornum==ENODEV)
161         return "No such device";
162 #endif
163 #ifdef ENOTDIR
164     if (errornum==ENOTDIR)
165         return "Not a directory";
166 #endif
167 #ifdef EISDIR
168     if (errornum==EISDIR)
169         return "Is a directory";
170 #endif
171 #ifdef EINVAL
172     if (errornum==EINVAL)
173         return "Invalid argument";
174 #endif
175 #ifdef ENFILE
176     if (errornum==ENFILE)
177         return "Too many open files in system";
178 #endif
179 #ifdef EMFILE
180     if (errornum==EMFILE)
181         return "Too many open files";
182 #endif
183 #ifdef ENOTTY
184     if (errornum==ENOTTY)
185         return "Not a typewriter";
186 #endif
187 #ifdef ETXTBSY
188     if (errornum==ETXTBSY)
189         return "Text file busy";
190 #endif
191 #ifdef EFBIG
192     if (errornum==EFBIG)
193         return "File too large";
194 #endif
195 #ifdef ENOSPC
196     if (errornum==ENOSPC)
197         return "No space left on device";
198 #endif
199 #ifdef ESPIPE
200     if (errornum==ESPIPE)
201         return "Illegal seek";
202 #endif
203 #ifdef EROFS
204     if (errornum==EROFS)
205         return "Read-only file system";
206 #endif
207 #ifdef EMLINK
208     if (errornum==EMLINK)
209         return "Too many links";
210 #endif
211 #ifdef EPIPE
212     if (errornum==EPIPE)
213         return "Broken pipe";
214 #endif
215 #ifdef EDOM
216     if (errornum==EDOM)
217         return "Math argument out of domain of func";
218 #endif
219 #ifdef ERANGE
220     if (errornum==ERANGE)
221         return "Math result not representable";
222 #endif
223 #ifdef ENAMETOOLONG
224     if (errornum==ENAMETOOLONG)
225         return "File name too long";
226 #endif
227 #ifdef ENOLCK
228     if (errornum==ENOLCK)
229         return "No record locks avaliable";
230 #endif
231 #ifdef ENOSYS
232     if (errornum==ENOSYS)
233         return "Function not implemented";
234 #endif
235 #ifdef ENOTEMPTY
236     if (errornum==ENOTEMPTY)
237         return "Directory not empty";
238 #endif
239 #ifdef ELOOP
240     if (errornum==ELOOP)
241         return "Too many symbolic links encountered";
242 #endif
243 #ifdef EHOSTDOWN
244     if (errornum==EHOSTDOWN)
245         return "Host is down";
246 #endif
247 #ifdef EHOSTUNREACH
248     if (errornum==EHOSTUNREACH)
249         return "No route to host";
250 #endif
251 #ifdef EALREADY
252     if (errornum==EALREADY)
253         return "Operation already in progress";
254 #endif
255 #ifdef EINPROGRESS
256     if (errornum==EINPROGRESS)
257         return "Operation now in progress";
258 #endif
259 #ifdef ESTALE
260     if (errornum==ESTALE)
261         return "Stale NFS filehandle";
262 #endif
263 #ifdef EDQUOT
264     if (errornum==EDQUOT)
265         return "Quota exceeded";
266 #endif
267 #ifdef EWOULDBLOCK
268     if (errornum==EWOULDBLOCK)
269         return "Operation would block";
270 #endif
271 #ifdef ECOMM
272     if (errornum==ECOMM)
273         return "Communication error on send";
274 #endif
275 #ifdef EPROTO
276     if (errornum==EPROTO)
277         return "Protocol error";
278 #endif
279 #ifdef EPROTONOSUPPORT
280     if (errornum==EPROTONOSUPPORT)
281         return "Protocol not supported";
282 #endif
283 #ifdef ESOCKTNOSUPPORT
284     if (errornum==ESOCKTNOSUPPORT)
285         return "Socket type not supported";
286 #endif
287 #ifdef ESOCKTNOSUPPORT
288     if (errornum==EOPNOTSUPP)
289         return "Operation not supported";
290 #endif
291 #ifdef EPFNOSUPPORT
292     if (errornum==EPFNOSUPPORT)
293         return "Protocol family not supported";
294 #endif
295 #ifdef EAFNOSUPPORT
296     if (errornum==EAFNOSUPPORT)
297         return "Address family not supported by protocol family";
298 #endif
299 #ifdef EADDRINUSE
300     if (errornum==EADDRINUSE)
301         return "Address already in use";
302 #endif
303 #ifdef EADDRNOTAVAIL
304     if (errornum==EADDRNOTAVAIL)
305         return "Cannot assign requested address";
306 #endif
307 #ifdef ENETDOWN
308     if (errornum==ENETDOWN)
309         return "Network is down";
310 #endif
311 #ifdef ENETUNREACH
312     if (errornum==ENETUNREACH)
313         return "Network is unreachable";
314 #endif
315 #ifdef ENETRESET
316     if (errornum==ENETRESET)
317         return "Network dropped connection on reset";
318 #endif
319 #ifdef ECONNABORTED
320     if (errornum==ECONNABORTED)
321         return "Software caused connection abort";
322 #endif
323 #ifdef ECONNRESET
324     if (errornum==ECONNRESET)
325         return " Connection reset by peer";
326 #endif
327 #ifdef ENOBUFS
328     if (errornum==ENOBUFS)
329         return "No buffer space available";
330 #endif
331 #ifdef EISCONN
332     if (errornum==EISCONN)
333         return "Socket is already connected";
334 #endif
335 #ifdef ENOTCONN
336     if (errornum==ENOTCONN)
337         return "Socket is not connected";
338 #endif
339 #ifdef ESHUTDOWN
340     if (errornum==ESHUTDOWN)
341         return " Cannot send after socket shutdown";
342 #endif
343 #ifdef ETIMEDOUT
344     if (errornum==ETIMEDOUT)
345         return "Connection timed out";
346 #endif
347 #ifdef ECONNREFUSED
348     if (errornum==ECONNREFUSED)
349         return "Connection refused";
350 #endif
351     return "Unknown error";
352 }
353 #endif
354
355 #ifndef HAVE_GETADDRINFO
356
357 int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res)
358 {
359     /* Only support IPv4 if OS doesn't provide this function. */
360     struct sockaddr_in sin;
361
362     if (hints && hints->ai_family != AF_INET)
363         return 1;
364     memset(&sin, 0, sizeof(sin));
365     sin.sin_family = AF_INET;
366
367     if (node) {
368         if (hints && hints->ai_flags & AI_NUMERICHOST) {
369 #if HAVE_INET_ATON
370             if (!inet_aton(node, &sin.sin_addr))
371                 return 2;
372 #else
373             sin.sin_addr.s_addr = inet_addr(node);
374             if (sin.sin_addr.s_addr == INADDR_NONE)
375                 return 2;
376 #endif
377         } else {
378             struct hostent *he;
379             he = gethostbyname(node);
380             if (!he)
381                 return 3;
382             memcpy(&sin.sin_addr, he->h_addr, he->h_length);
383         }
384     } else if (hints && hints->ai_flags & AI_PASSIVE) {
385         /* leave it unspecifed */
386     } else {
387         inet_aton("127.0.0.1", &sin.sin_addr);
388     }
389
390     if (!service)
391         sin.sin_port = ntohs(0);
392     else if (!(sin.sin_port = ntohs(atoi(service))))
393         return 4;
394
395     *res = calloc(1, sizeof(**res) + sizeof(sin));
396     (*res)->ai_family = sin.sin_family;
397     (*res)->ai_socktype = hints && hints->ai_socktype ? hints->ai_socktype : SOCK_STREAM;
398     (*res)->ai_protocol = hints && hints->ai_socktype ? hints->ai_socktype : 0;
399     (*res)->ai_addrlen = sizeof(sin);
400     (*res)->ai_addr = (struct sockaddr*)(*res + 1);
401     memcpy((*res)->ai_addr, &sin, (*res)->ai_addrlen);
402     (*res)->ai_canonname = 0;
403     (*res)->ai_next = 0;
404     return 0;
405 }
406
407 /* TODO: implement fallback getnameinfo() */
408
409 void freeaddrinfo(struct addrinfo *res)
410 {
411     struct addrinfo *next;
412     for (; res; res = next) {
413         next = res->ai_next;
414         free(res);
415     }
416 }
417
418 #endif