Implement most of the MRU related functions.
[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 #ifdef __svr4__
401 /***********************************************************************
402  *             solaris_try_mmap
403  *
404  * The purpose of this routine is to emulate the behaviour of
405  * the Linux mmap() routine if a non-NULL address is passed,
406  * but the MAP_FIXED flag is not set.  Linux in this case tries
407  * to place the mapping at the specified address, *unless* the
408  * range is already in use.  Solaris, however, completely ignores
409  * the address argument in this case.
410  *
411  * As Wine code occasionally relies on the Linux behaviour, e.g. to
412  * be able to map non-relocateable PE executables to their proper
413  * start addresses, or to map the DOS memory to 0, this routine
414  * emulates the Linux behaviour by checking whether the desired
415  * address range is still available, and placing the mapping there
416  * using MAP_FIXED if so.
417  */
418 static int solaris_try_mmap (void *addr, size_t len, int prot, int flags,
419                             int fildes, off_t off)
420 {
421     char * volatile result = NULL;
422     int pagesize = getpagesize();
423     pid_t pid;
424
425     /* We only try to map to a fixed address if
426        addr is non-NULL and properly aligned,
427        and MAP_FIXED isn't already specified. */
428
429     if ( !addr )
430         return FALSE;
431     if ( (uintptr_t)addr & (pagesize-1) )
432         return FALSE;
433     if ( flags & MAP_FIXED )
434         return FALSE;
435
436     /* We use vfork() to freeze all threads of the
437        current process.  This allows us to check without
438        race condition whether the desired memory range is
439        already in use.  Note that because vfork() shares
440        the address spaces between parent and child, we
441        can actually perform the mapping in the child. */
442
443     if ( (pid = vfork()) == -1 )
444     {
445         perror("solaris_try_mmap: vfork");
446         exit(1);
447     }
448     if ( pid == 0 )
449     {
450         int i;
451         char vec;
452
453         /* We call mincore() for every page in the desired range.
454            If any of these calls succeeds, the page is already
455            mapped and we must fail. */
456         for ( i = 0; i < len; i += pagesize )
457             if ( mincore( (caddr_t)addr + i, pagesize, &vec ) != -1 )
458                _exit(1);
459
460         /* Perform the mapping with MAP_FIXED set.  This is safe
461            now, as none of the pages is currently in use. */
462         result = mmap( addr, len, prot, flags | MAP_FIXED, fildes, off );
463         if ( result == addr )
464             _exit(0);
465
466         if ( result != (void *) -1 ) /* This should never happen ... */
467             munmap( result, len );
468
469        _exit(1);
470     }
471
472     /* vfork() lets the parent continue only after the child
473        has exited.  Furthermore, Wine sets SIGCHLD to SIG_IGN,
474        so we don't need to wait for the child. */
475
476     return result == addr;
477 }
478 #endif
479
480 /***********************************************************************
481  *              wine_anon_mmap
482  *
483  * Portable wrapper for anonymous mmaps
484  */
485 void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
486 {
487     static int fdzero = -1;
488
489 #ifdef MAP_ANON
490     flags |= MAP_ANON;
491 #else
492     if (fdzero == -1)
493     {
494         if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
495         {
496             perror( "/dev/zero: open" );
497             exit(1);
498         }
499     }
500 #endif  /* MAP_ANON */
501
502 #ifdef MAP_SHARED
503     flags &= ~MAP_SHARED;
504 #endif
505
506     /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
507 #ifdef MAP_PRIVATE
508     flags |= MAP_PRIVATE;
509 #endif
510
511 #ifdef __svr4__
512     if ( solaris_try_mmap( start, size, prot, flags, fdzero, 0 ) )
513         return start;
514 #endif
515
516     return mmap( start, size, prot, flags, fdzero, 0 );
517 }
518
519
520 /*
521  * These functions provide wrappers around dlopen() and associated
522  * functions.  They work around a bug in glibc 2.1.x where calling
523  * a dl*() function after a previous dl*() function has failed
524  * without a dlerror() call between the two will cause a crash.
525  * They all take a pointer to a buffer that
526  * will receive the error description (from dlerror()).  This
527  * parameter may be NULL if the error description is not required.
528  */
529
530 /***********************************************************************
531  *              wine_dlopen
532  */
533 void *wine_dlopen( const char *filename, int flag, char *error, int errorsize )
534 {
535 #ifdef HAVE_DLOPEN
536     void *ret;
537     char *s;
538     dlerror(); dlerror();
539     ret = dlopen( filename, flag );
540     s = dlerror();
541     if (error)
542     {
543         strncpy( error, s ? s : "", errorsize );
544         error[errorsize - 1] = '\0';
545     }
546     dlerror();
547     return ret;
548 #else
549     if (error)
550     {
551         strncpy( error, "dlopen interface not detected by configure", errorsize );
552         error[errorsize - 1] = '\0';
553     }
554     return NULL;
555 #endif
556 }
557
558 /***********************************************************************
559  *              wine_dlsym
560  */
561 void *wine_dlsym( void *handle, const char *symbol, char *error, int errorsize )
562 {
563 #ifdef HAVE_DLOPEN
564     void *ret;
565     char *s;
566     dlerror(); dlerror();
567     ret = dlsym( handle, symbol );
568     s = dlerror();
569     if (error)
570     {
571         strncpy( error, s ? s : "", errorsize );
572         error[errorsize - 1] = '\0';
573     }
574     dlerror();
575     return ret;
576 #else
577     if (error)
578     {
579         strncpy( error, "dlopen interface not detected by configure", errorsize );
580         error[errorsize - 1] = '\0';
581     }
582     return NULL;
583 #endif
584 }
585
586 /***********************************************************************
587  *              wine_dlclose
588  */
589 int wine_dlclose( void *handle, char *error, int errorsize )
590 {
591 #ifdef HAVE_DLOPEN
592     int ret;
593     char *s;
594     dlerror(); dlerror();
595     ret = dlclose( handle );
596     s = dlerror();
597     if (error)
598     {
599         strncpy( error, s ? s : "", errorsize );
600         error[errorsize - 1] = '\0';
601     }
602     dlerror();
603     return ret;
604 #else
605     if (error)
606     {
607         strncpy( error, "dlopen interface not detected by configure", errorsize );
608         error[errorsize - 1] = '\0';
609     }
610     return 1;
611 #endif
612 }
613
614 /***********************************************************************
615  *              wine_rewrite_s4tos2
616  *
617  * Convert 4 byte Unicode strings to 2 byte Unicode strings in-place.
618  * This is only practical if literal strings are writable.
619  */
620 unsigned short* wine_rewrite_s4tos2(const wchar_t* str4 )
621 {
622     unsigned short *str2,*s2;
623
624     if (str4==NULL)
625       return NULL;
626
627     if ((*str4 & 0xffff0000) != 0) {
628         /* This string has already been converted. Return it as is */
629         return (unsigned short*)str4;
630     }
631
632     /* Note that we can also end up here if the string has a single 
633      * character. In such a case we will convert the string over and 
634      * over again. But this is harmless.
635      */
636     str2=s2=(unsigned short*)str4;
637     do {
638         *s2=(unsigned short)*str4;
639         s2++;
640     } while (*str4++ != L'\0');
641
642     return str2;
643 }
644
645 #ifndef HAVE_ECVT
646 /*
647  * NetBSD 1.5 doesn't have ecvt, fcvt, gcvt. We just check for ecvt, though.
648  * Fix/verify these implementations !
649  */
650
651 /***********************************************************************
652  *              ecvt
653  */
654 char *ecvt (double number, int  ndigits,  int  *decpt,  int *sign)
655 {
656     static buf[40]; /* ought to be enough */
657     char *dec;
658     sprintf(buf, "%.*e", ndigits /* FIXME wrong */, number); 
659     *sign = (number < 0);
660     dec = strchr(buf, '.');
661     *decpt = (dec) ? (int)dec - (int)buf : -1;
662     return buf;
663 }
664
665 /***********************************************************************
666  *              fcvt
667  */
668 char *fcvt (double number, int  ndigits,  int  *decpt,  int *sign)
669 {
670     static buf[40]; /* ought to be enough */
671     char *dec;
672     sprintf(buf, "%.*e", ndigits, number);
673     *sign = (number < 0);
674     dec = strchr(buf, '.');
675     *decpt = (dec) ? (int)dec - (int)buf : -1;
676     return buf;
677 }
678
679 /***********************************************************************
680  *              gcvt
681  *
682  * FIXME: uses both E and F.
683  */
684 char *gcvt (double number, size_t  ndigit,  char *buff)
685 {
686     sprintf(buff, "%.*E", ndigit, number);
687     return buff;
688 }
689 #endif /* HAVE_ECVT */