2 * Misc. functions for systems that don't have them
4 * Copyright 1996 Alexandre Julliard
10 #include <be/kernel/fs_info.h>
11 #include <be/kernel/OS.h>
20 #include <sys/types.h>
23 #include <sys/ioctl.h>
27 #ifdef HAVE_SYS_MMAN_H
44 /***********************************************************************
48 unsigned int usleep (unsigned int useconds)
53 #elif defined(__BEOS__)
54 return snooze(useconds);
55 #elif defined(HAVE_SELECT)
58 delay.tv_sec = useconds / 1000000;
59 delay.tv_usec = useconds % 1000000;
61 select( 0, 0, 0, 0, &delay );
63 #else /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
66 #endif /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
68 #endif /* HAVE_USLEEP */
70 /***********************************************************************
74 void *memmove( void *dest, const void *src, unsigned int len )
76 register char *dst = dest;
78 /* Use memcpy if not overlapping */
79 if ((dst + len <= (char *)src) || ((char *)src + len <= dst))
81 memcpy( dst, src, len );
83 /* Otherwise do it the hard way (FIXME: could do better than this) */
86 while (len--) *dst++ = *((char *)src)++;
91 src = (char *)src + len - 1;
92 while (len--) *dst-- = *((char *)src)--;
96 #endif /* HAVE_MEMMOVE */
98 /***********************************************************************
101 #ifndef HAVE_STRERROR
102 const char *strerror( int err )
104 /* Let's hope we have sys_errlist then */
105 return sys_errlist[err];
107 #endif /* HAVE_STRERROR */
110 /***********************************************************************
113 #ifndef HAVE_GETPAGESIZE
114 size_t getpagesize(void)
117 return sysconf(_SC_PAGESIZE);
119 # error Cannot get the page size on this platform
122 #endif /* HAVE_GETPAGESIZE */
125 /***********************************************************************
128 #if !defined(HAVE_CLONE) && defined(__linux__)
129 int clone( int (*fn)(void *), void *stack, int flags, void *arg )
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"
139 "popl %%ebx\n\t" /* Contains fn in the child */
140 "testl %%eax,%%eax\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*/
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;
155 #endif /* __i386__ */
157 #endif /* !HAVE_CLONE && __linux__ */
159 /***********************************************************************
162 #ifndef HAVE_STRCASECMP
163 int strcasecmp( const char *str1, const char *str2 )
165 const unsigned char *ustr1 = (const unsigned char *)str1;
166 const unsigned char *ustr2 = (const unsigned char *)str2;
168 while (*ustr1 && toupper(*ustr1) == toupper(*ustr2)) {
172 return toupper(*ustr1) - toupper(*ustr2);
174 #endif /* HAVE_STRCASECMP */
176 /***********************************************************************
179 #ifndef HAVE_STRNCASECMP
180 int strncasecmp( const char *str1, const char *str2, size_t n )
182 const unsigned char *ustr1 = (const unsigned char *)str1;
183 const unsigned char *ustr2 = (const unsigned char *)str2;
187 while ((--n > 0) && *ustr1) {
188 if ((res = toupper(*ustr1) - toupper(*ustr2))) return res;
192 return toupper(*ustr1) - toupper(*ustr2);
194 #endif /* HAVE_STRNCASECMP */
196 /***********************************************************************
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.
204 * We should have a autoconf check for this.
206 int wine_openpty(int *master, int *slave, char *name,
207 struct termios *term, struct winsize *winsize)
210 return openpty(master, slave, name, term, winsize);
212 const char *ptr1, *ptr2;
215 strcpy (pts_name, "/dev/ptyXY");
217 for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
219 for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
222 if ((*master = open(pts_name, O_RDWR)) < 0) {
229 if ((*slave = open(pts_name, O_RDWR)) < 0) {
236 tcsetattr(*slave, TCSANOW, term);
238 ioctl(*slave, TIOCSWINSZ, winsize);
240 strcpy(name, pts_name);
249 /***********************************************************************
252 #ifndef HAVE_GETNETBYADDR
253 struct netent *getnetbyaddr(unsigned long net, int type)
258 #endif /* defined(HAVE_GETNETBYNAME) */
260 /***********************************************************************
263 #ifndef HAVE_GETNETBYNAME
264 struct netent *getnetbyname(const char *name)
269 #endif /* defined(HAVE_GETNETBYNAME) */
271 /***********************************************************************
274 #ifndef HAVE_GETPROTOBYNAME
275 struct protoent *getprotobyname(const char *name)
280 #endif /* !defined(HAVE_GETPROTOBYNAME) */
282 /***********************************************************************
285 #ifndef HAVE_GETPROTOBYNUMBER
286 struct protoent *getprotobynumber(int proto)
291 #endif /* !defined(HAVE_GETPROTOBYNUMBER) */
293 /***********************************************************************
296 #ifndef HAVE_GETSERVBYPORT
297 struct servent *getservbyport(int port, const char *proto)
302 #endif /* !defined(HAVE_GETSERVBYPORT) */
304 /***********************************************************************
307 #ifndef HAVE_GETSOCKOPT
308 int getsockopt(int socket, int level, int option_name,
309 void *option_value, size_t *option_len)
314 #endif /* !defined(HAVE_GETSOCKOPT) */
316 /***********************************************************************
319 #ifndef HAVE_INET_NETWORK
320 unsigned long inet_network(const char *cp)
325 #endif /* defined(HAVE_INET_NETWORK) */
327 /***********************************************************************
330 #ifndef HAVE_SETTIMEOFDAY
331 int settimeofday(struct timeval *tp, void *reserved)
339 #endif /* HAVE_SETTIMEOFDAY */
341 /***********************************************************************
345 int statfs(const char *name, struct statfs *info)
356 if ((mydev = dev_for_path(name)) < 0) {
361 if (fs_stat_dev(mydev,&fsinfo) < 0) {
366 info->f_bsize = fsinfo.block_size;
367 info->f_blocks = fsinfo.total_blocks;
368 info->f_bfree = fsinfo.free_blocks;
370 #else /* defined(__BEOS__) */
373 #endif /* defined(__BEOS__) */
375 #endif /* !defined(HAVE_STATFS) */
378 /***********************************************************************
382 int lstat(const char *file_name, struct stat *buf)
384 return stat( file_name, buf );
386 #endif /* HAVE_LSTAT */
388 /***********************************************************************
391 #ifndef HAVE_GETRLIMIT
392 int getrlimit (int resource, struct rlimit *rlim)
394 return -1; /* FAIL */
396 #endif /* HAVE_GETRLIMIT */
400 /***********************************************************************
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.
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.
417 static int solaris_try_mmap (void *addr, size_t len, int prot, int flags,
418 int fildes, off_t off)
420 char * volatile result = NULL;
421 int pagesize = getpagesize();
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. */
430 if ( (uintptr_t)addr & (pagesize-1) )
432 if ( flags & MAP_FIXED )
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. */
442 if ( (pid = vfork()) == -1 )
444 perror("solaris_try_mmap: vfork");
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 )
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 )
465 if ( result != (void *) -1 ) /* This should never happen ... */
466 munmap( result, len );
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. */
475 return result == addr;
479 /***********************************************************************
482 * Portable wrapper for anonymous mmaps
484 void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
486 static int fdzero = -1;
493 if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
495 perror( "/dev/zero: open" );
499 #endif /* MAP_ANON */
502 flags &= ~MAP_SHARED;
505 /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
507 flags |= MAP_PRIVATE;
511 if ( solaris_try_mmap( start, size, prot, flags, fdzero, 0 ) )
515 return mmap( start, size, prot, flags, fdzero, 0 );
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.
529 /***********************************************************************
532 void *wine_dlopen( const char *filename, int flag, char *error, int errorsize )
537 dlerror(); dlerror();
538 ret = dlopen( filename, flag );
542 strncpy( error, s ? s : "", errorsize );
543 error[errorsize - 1] = '\0';
550 strncpy( error, "dlopen interface not detected by configure", errorsize );
551 error[errorsize - 1] = '\0';
557 /***********************************************************************
560 void *wine_dlsym( void *handle, const char *symbol, char *error, int errorsize )
565 dlerror(); dlerror();
566 ret = dlsym( handle, symbol );
570 strncpy( error, s ? s : "", errorsize );
571 error[errorsize - 1] = '\0';
578 strncpy( error, "dlopen interface not detected by configure", errorsize );
579 error[errorsize - 1] = '\0';
585 /***********************************************************************
588 int wine_dlclose( void *handle, char *error, int errorsize )
593 dlerror(); dlerror();
594 ret = dlclose( handle );
598 strncpy( error, s ? s : "", errorsize );
599 error[errorsize - 1] = '\0';
606 strncpy( error, "dlopen interface not detected by configure", errorsize );
607 error[errorsize - 1] = '\0';
613 /***********************************************************************
614 * wine_rewrite_s4tos2
616 * Convert 4 byte Unicode strings to 2 byte Unicode strings in-place.
617 * This is only practical if literal strings are writable.
619 unsigned short* wine_rewrite_s4tos2(const wchar_t* str4 )
621 unsigned short *str2,*s2;
626 if ((*str4 & 0xffff0000) != 0) {
627 /* This string has already been converted. Return it as is */
628 return (unsigned short*)str4;
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.
635 str2=s2=(unsigned short*)str4;
637 *s2=(unsigned short)*str4;
639 } while (*str4++ != L'\0');
646 * NetBSD 1.5 doesn't have ecvt, fcvt, gcvt. We just check for ecvt, though.
647 * Fix/verify these implementations !
650 /***********************************************************************
653 char *ecvt (double number, int ndigits, int *decpt, int *sign)
655 static char buf[40]; /* ought to be enough */
657 sprintf(buf, "%.*e", ndigits /* FIXME wrong */, number);
658 *sign = (number < 0);
659 dec = strchr(buf, '.');
660 *decpt = (dec) ? (int)dec - (int)buf : -1;
664 /***********************************************************************
667 char *fcvt (double number, int ndigits, int *decpt, int *sign)
669 static char buf[40]; /* ought to be enough */
671 sprintf(buf, "%.*e", ndigits, number);
672 *sign = (number < 0);
673 dec = strchr(buf, '.');
674 *decpt = (dec) ? (int)dec - (int)buf : -1;
678 /***********************************************************************
681 * FIXME: uses both E and F.
683 char *gcvt (double number, size_t ndigit, char *buff)
685 sprintf(buff, "%.*E", (int)ndigit, number);
688 #endif /* HAVE_ECVT */