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