Put AC_DEFINE symbols definitions directly in the configure script so
[wine] / library / port.c
1 /*
2  * Misc. functions for systems that don't have them
3  *
4  * Copyright 1996 Alexandre Julliard
5  */
6
7 #include "config.h"
8 #include "wine/port.h"
9
10 #ifdef __BEOS__
11 #include <be/kernel/fs_info.h>
12 #include <be/kernel/OS.h>
13 #endif
14
15 #include <assert.h>
16 #include <ctype.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <sys/stat.h>
24 #include <sys/ioctl.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <termios.h>
28 #ifdef HAVE_SYS_MMAN_H
29 #include <sys/mman.h>
30 #endif
31 #ifdef HAVE_LIBIO_H
32 # include <libio.h>
33 #endif
34 #ifdef HAVE_SYSCALL_H
35 # include <syscall.h>
36 #endif
37 #ifdef HAVE_PTY_H
38 # include <pty.h>
39 #endif
40 #ifdef HAVE_LIBUTIL_H
41 # include <libutil.h>
42 #endif
43
44
45 /***********************************************************************
46  *              usleep
47  */
48 #ifndef HAVE_USLEEP
49 unsigned int usleep (unsigned int useconds)
50 {
51 #if defined(__EMX__)
52     DosSleep(useconds);
53     return 0;
54 #elif defined(__BEOS__)
55     return snooze(useconds);
56 #elif defined(HAVE_SELECT)
57     struct timeval delay;
58
59     delay.tv_sec = useconds / 1000000;
60     delay.tv_usec = useconds % 1000000;
61
62     select( 0, 0, 0, 0, &delay );
63     return 0;
64 #else /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
65     errno = ENOSYS;
66     return -1;
67 #endif /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
68 }
69 #endif /* HAVE_USLEEP */
70
71 /***********************************************************************
72  *              memmove
73  */
74 #ifndef HAVE_MEMMOVE
75 void *memmove( void *dest, const void *src, unsigned int len )
76 {
77     register char *dst = dest;
78
79     /* Use memcpy if not overlapping */
80     if ((dst + len <= (char *)src) || ((char *)src + len <= dst))
81     {
82         memcpy( dst, src, len );
83     }
84     /* Otherwise do it the hard way (FIXME: could do better than this) */
85     else if (dst < src)
86     {
87         while (len--) *dst++ = *((char *)src)++;
88     }
89     else
90     {
91         dst += len - 1;
92         src = (char *)src + len - 1;
93         while (len--) *dst-- = *((char *)src)--;
94     }
95     return dest;
96 }
97 #endif  /* HAVE_MEMMOVE */
98
99 /***********************************************************************
100  *              strerror
101  */
102 #ifndef HAVE_STRERROR
103 const char *strerror( int err )
104 {
105     /* Let's hope we have sys_errlist then */
106     return sys_errlist[err];
107 }
108 #endif  /* HAVE_STRERROR */
109
110
111 /***********************************************************************
112  *              getpagesize
113  */
114 #ifndef HAVE_GETPAGESIZE
115 size_t getpagesize(void)
116 {
117 # ifdef __svr4__
118     return sysconf(_SC_PAGESIZE);
119 # else
120 #  error Cannot get the page size on this platform
121 # endif
122 }
123 #endif  /* HAVE_GETPAGESIZE */
124
125
126 /***********************************************************************
127  *              clone
128  */
129 #if !defined(HAVE_CLONE) && defined(__linux__)
130 int clone( int (*fn)(void *), void *stack, int flags, void *arg )
131 {
132 #ifdef __i386__
133     int ret;
134     void **stack_ptr = (void **)stack;
135     *--stack_ptr = arg;  /* Push argument on stack */
136     *--stack_ptr = fn;   /* Push function pointer (popped into ebx) */
137     __asm__ __volatile__( "pushl %%ebx\n\t"
138                           "movl %2,%%ebx\n\t"
139                           "int $0x80\n\t"
140                           "popl %%ebx\n\t"   /* Contains fn in the child */
141                           "testl %%eax,%%eax\n\t"
142                           "jnz 0f\n\t"
143                           "xorl %ebp,%ebp\n\t"    /* Terminate the stack frames */
144                           "call *%%ebx\n\t"       /* Should never return */
145                           "xorl %%eax,%%eax\n\t"  /* Just in case it does*/
146                           "0:"
147                           : "=a" (ret)
148                           : "0" (SYS_clone), "r" (flags), "c" (stack_ptr) );
149     assert( ret );  /* If ret is 0, we returned from the child function */
150     if (ret > 0) return ret;
151     errno = -ret;
152     return -1;
153 #else
154     errno = EINVAL;
155     return -1;
156 #endif  /* __i386__ */
157 }
158 #endif  /* !HAVE_CLONE && __linux__ */
159
160 /***********************************************************************
161  *              strcasecmp
162  */
163 #ifndef HAVE_STRCASECMP
164 int strcasecmp( const char *str1, const char *str2 )
165 {
166     const unsigned char *ustr1 = (const unsigned char *)str1;
167     const unsigned char *ustr2 = (const unsigned char *)str2;
168
169     while (*ustr1 && toupper(*ustr1) == toupper(*ustr2)) {
170         ustr1++;
171         ustr2++;
172     }
173     return toupper(*ustr1) - toupper(*ustr2);
174 }
175 #endif /* HAVE_STRCASECMP */
176
177 /***********************************************************************
178  *              strncasecmp
179  */
180 #ifndef HAVE_STRNCASECMP
181 int strncasecmp( const char *str1, const char *str2, size_t n )
182 {
183     const unsigned char *ustr1 = (const unsigned char *)str1;
184     const unsigned char *ustr2 = (const unsigned char *)str2;
185     int res;
186
187     if (!n) return 0;
188     while ((--n > 0) && *ustr1) {
189         if ((res = toupper(*ustr1) - toupper(*ustr2))) return res;
190         ustr1++;
191         ustr2++;
192     }
193     return toupper(*ustr1) - toupper(*ustr2);
194 }
195 #endif /* HAVE_STRNCASECMP */
196
197 /***********************************************************************
198  *              wine_openpty
199  * NOTE
200  *   It looks like the openpty that comes with glibc in RedHat 5.0
201  *   is buggy (second call returns what looks like a dup of 0 and 1
202  *   instead of a new pty), this is a generic replacement.
203  *
204  * FIXME
205  *   We should have a autoconf check for this.
206  */
207 int wine_openpty(int *master, int *slave, char *name,
208                  struct termios *term, struct winsize *winsize)
209 {
210 #ifdef HAVE_OPENPTY
211     return openpty(master, slave, name, term, winsize);
212 #else
213     const char *ptr1, *ptr2;
214     char pts_name[512];
215
216     strcpy (pts_name, "/dev/ptyXY");
217
218     for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
219         pts_name[8] = *ptr1;
220         for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
221             pts_name[9] = *ptr2;
222
223             if ((*master = open(pts_name, O_RDWR)) < 0) {
224                 if (errno == ENOENT)
225                     return -1;
226                 else
227                     continue;
228             }
229             pts_name[5] = 't';
230             if ((*slave = open(pts_name, O_RDWR)) < 0) {
231                 pts_name[5] = 'p';
232                 close (*master);
233                 continue;
234             }
235
236             if (term != NULL)
237                 tcsetattr(*slave, TCSANOW, term);
238             if (winsize != NULL)
239                 ioctl(*slave, TIOCSWINSZ, winsize);
240             if (name != NULL)
241                 strcpy(name, pts_name);
242             return *slave;
243         }
244     }
245     errno = EMFILE;
246     return -1;
247 #endif
248 }
249
250 /***********************************************************************
251  *              getnetbyaddr
252  */
253 #ifndef HAVE_GETNETBYADDR
254 struct netent *getnetbyaddr(unsigned long net, int type)
255 {
256     errno = ENOSYS;
257     return NULL;
258 }
259 #endif /* defined(HAVE_GETNETBYNAME) */
260
261 /***********************************************************************
262  *              getnetbyname
263  */
264 #ifndef HAVE_GETNETBYNAME
265 struct netent *getnetbyname(const char *name)
266 {
267     errno = ENOSYS;
268     return NULL;
269 }
270 #endif /* defined(HAVE_GETNETBYNAME) */
271
272 /***********************************************************************
273  *              getprotobyname
274  */
275 #ifndef HAVE_GETPROTOBYNAME
276 struct protoent *getprotobyname(const char *name)
277 {
278     errno = ENOSYS;
279     return NULL;
280 }
281 #endif /* !defined(HAVE_GETPROTOBYNAME) */
282
283 /***********************************************************************
284  *              getprotobynumber
285  */
286 #ifndef HAVE_GETPROTOBYNUMBER
287 struct protoent *getprotobynumber(int proto)
288 {
289     errno = ENOSYS;
290     return NULL;
291 }
292 #endif /* !defined(HAVE_GETPROTOBYNUMBER) */
293
294 /***********************************************************************
295  *              getservbyport
296  */
297 #ifndef HAVE_GETSERVBYPORT
298 struct servent *getservbyport(int port, const char *proto)
299 {
300     errno = ENOSYS;
301     return NULL;
302 }
303 #endif /* !defined(HAVE_GETSERVBYPORT) */
304
305 /***********************************************************************
306  *              getsockopt
307  */
308 #ifndef HAVE_GETSOCKOPT
309 int getsockopt(int socket, int level, int option_name,
310                void *option_value, size_t *option_len)
311 {
312     errno = ENOSYS;
313     return -1;
314 }
315 #endif /* !defined(HAVE_GETSOCKOPT) */
316
317 /***********************************************************************
318  *              inet_network
319  */
320 #ifndef HAVE_INET_NETWORK
321 unsigned long inet_network(const char *cp)
322 {
323     errno = ENOSYS;
324     return 0;
325 }
326 #endif /* defined(HAVE_INET_NETWORK) */
327
328 /***********************************************************************
329  *              settimeofday
330  */
331 #ifndef HAVE_SETTIMEOFDAY
332 int settimeofday(struct timeval *tp, void *reserved)
333 {
334     tp->tv_sec = 0;
335     tp->tv_usec = 0;
336
337     errno = ENOSYS;
338     return -1;
339 }
340 #endif /* HAVE_SETTIMEOFDAY */
341
342 /***********************************************************************
343  *              statfs
344  */
345 #ifndef HAVE_STATFS
346 int statfs(const char *name, struct statfs *info)
347 {
348 #ifdef __BEOS__
349     dev_t mydev;
350     fs_info fsinfo;
351
352     if(!info) {
353         errno = ENOSYS;
354         return -1;
355     }
356
357     if ((mydev = dev_for_path(name)) < 0) {
358         errno = ENOSYS;
359         return -1;
360     }
361
362     if (fs_stat_dev(mydev,&fsinfo) < 0) {
363         errno = ENOSYS;
364         return -1;
365     }
366
367     info->f_bsize = fsinfo.block_size;
368     info->f_blocks = fsinfo.total_blocks;
369     info->f_bfree = fsinfo.free_blocks;
370     return 0;
371 #else /* defined(__BEOS__) */
372     errno = ENOSYS;
373     return -1;
374 #endif /* defined(__BEOS__) */
375 }
376 #endif /* !defined(HAVE_STATFS) */
377
378
379 /***********************************************************************
380  *              lstat
381  */
382 #ifndef HAVE_LSTAT
383 int lstat(const char *file_name, struct stat *buf)
384 {
385     return stat( file_name, buf );
386 }
387 #endif /* HAVE_LSTAT */
388
389 /***********************************************************************
390  *              getrlimit
391  */
392 #ifndef HAVE_GETRLIMIT
393 int getrlimit (int resource, struct rlimit *rlim)
394 {
395     return -1; /* FAIL */
396 }
397 #endif /* HAVE_GETRLIMIT */
398
399 /***********************************************************************
400  *              wine_anon_mmap
401  *
402  * Portable wrapper for anonymous mmaps
403  */
404 void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
405 {
406     static int fdzero = -1;
407
408 #ifdef MAP_ANON
409     flags |= MAP_ANON;
410 #else
411     if (fdzero == -1)
412     {
413         if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
414         {
415             perror( "/dev/zero: open" );
416             exit(1);
417         }
418     }
419 #endif  /* MAP_ANON */
420
421 #ifdef MAP_SHARED
422     flags &= ~MAP_SHARED;
423 #endif
424
425     /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
426 #ifdef MAP_PRIVATE
427     flags |= MAP_PRIVATE;
428 #endif
429
430     return mmap( start, size, prot, flags, fdzero, 0 );
431 }
432
433
434 /*
435  * These functions provide wrappers around dlopen() and associated
436  * functions.  They work around a bug in glibc 2.1.x where calling
437  * a dl*() function after a previous dl*() function has failed
438  * without a dlerror() call between the two will cause a crash.
439  * They all take a pointer to a buffer that
440  * will receive the error description (from dlerror()).  This
441  * parameter may be NULL if the error description is not required.
442  */
443
444 /***********************************************************************
445  *              wine_dlopen
446  */
447 void *wine_dlopen( const char *filename, int flag, char *error, int errorsize )
448 {
449 #ifdef HAVE_DLOPEN
450     void *ret;
451     char *s;
452     dlerror(); dlerror();
453     ret = dlopen( filename, flag );
454     s = dlerror();
455     if (error)
456     {
457         strncpy( error, s ? s : "", errorsize );
458         error[errorsize - 1] = '\0';
459     }
460     dlerror();
461     return ret;
462 #else
463     if (error)
464     {
465         strncpy( error, "dlopen interface not detected by configure", errorsize );
466         error[errorsize - 1] = '\0';
467     }
468     return NULL;
469 #endif
470 }
471
472 /***********************************************************************
473  *              wine_dlsym
474  */
475 void *wine_dlsym( void *handle, const char *symbol, char *error, int errorsize )
476 {
477 #ifdef HAVE_DLOPEN
478     void *ret;
479     char *s;
480     dlerror(); dlerror();
481     ret = dlsym( handle, symbol );
482     s = dlerror();
483     if (error)
484     {
485         strncpy( error, s ? s : "", errorsize );
486         error[errorsize - 1] = '\0';
487     }
488     dlerror();
489     return ret;
490 #else
491     if (error)
492     {
493         strncpy( error, "dlopen interface not detected by configure", errorsize );
494         error[errorsize - 1] = '\0';
495     }
496     return NULL;
497 #endif
498 }
499
500 /***********************************************************************
501  *              wine_dlclose
502  */
503 int wine_dlclose( void *handle, char *error, int errorsize )
504 {
505 #ifdef HAVE_DLOPEN
506     int ret;
507     char *s;
508     dlerror(); dlerror();
509     ret = dlclose( handle );
510     s = dlerror();
511     if (error)
512     {
513         strncpy( error, s ? s : "", errorsize );
514         error[errorsize - 1] = '\0';
515     }
516     dlerror();
517     return ret;
518 #else
519     if (error)
520     {
521         strncpy( error, "dlopen interface not detected by configure", errorsize );
522         error[errorsize - 1] = '\0';
523     }
524     return 1;
525 #endif
526 }
527
528 /***********************************************************************
529  *              wine_rewrite_s4tos2
530  *
531  * Convert 4 byte Unicode strings to 2 byte Unicode strings in-place.
532  * This is only practical if literal strings are writable.
533  */
534 unsigned short* wine_rewrite_s4tos2(const wchar_t* str4 )
535 {
536     unsigned short *str2,*s2;
537
538     if (str4==NULL)
539       return NULL;
540
541     if ((*str4 & 0xffff0000) != 0) {
542         /* This string has already been converted. Return it as is */
543         return (unsigned short*)str4;
544     }
545
546     /* Note that we can also end up here if the string has a single 
547      * character. In such a case we will convert the string over and 
548      * over again. But this is harmless.
549      */
550     str2=s2=(unsigned short*)str4;
551     do {
552         *s2=(unsigned short)*str4;
553         s2++;
554     } while (*str4++ != L'\0');
555
556     return str2;
557 }
558
559 #ifndef HAVE_ECVT
560 /*
561  * NetBSD 1.5 doesn't have ecvt, fcvt, gcvt. We just check for ecvt, though.
562  * Fix/verify these implementations !
563  */
564
565 /***********************************************************************
566  *              ecvt
567  */
568 char *ecvt (double number, int  ndigits,  int  *decpt,  int *sign)
569 {
570     static buf[40]; /* ought to be enough */
571     char *dec;
572     sprintf(buf, "%.*e", ndigits /* FIXME wrong */, number); 
573     *sign = (number < 0);
574     dec = strchr(buf, '.');
575     *decpt = (dec) ? (int)dec - (int)buf : -1;
576     return buf;
577 }
578
579 /***********************************************************************
580  *              fcvt
581  */
582 char *fcvt (double number, int  ndigits,  int  *decpt,  int *sign)
583 {
584     static buf[40]; /* ought to be enough */
585     char *dec;
586     sprintf(buf, "%.*e", ndigits, number);
587     *sign = (number < 0);
588     dec = strchr(buf, '.');
589     *decpt = (dec) ? (int)dec - (int)buf : -1;
590     return buf;
591 }
592
593 /***********************************************************************
594  *              gcvt
595  *
596  * FIXME: uses both E and F.
597  */
598 char *gcvt (double number, size_t  ndigit,  char *buff)
599 {
600     sprintf(buff, "%.*E", ndigit, number);
601     return buff;
602 }
603 #endif /* HAVE_ECVT */