2 * Misc. functions for systems that don't have them
4 * Copyright 1996 Alexandre Julliard
11 #include <be/kernel/fs_info.h>
12 #include <be/kernel/OS.h>
21 #include <sys/types.h>
24 #include <sys/ioctl.h>
28 #ifdef HAVE_SYS_MMAN_H
45 /***********************************************************************
49 unsigned int usleep (unsigned int useconds)
54 #elif defined(__BEOS__)
55 return snooze(useconds);
56 #elif defined(HAVE_SELECT)
59 delay.tv_sec = useconds / 1000000;
60 delay.tv_usec = useconds % 1000000;
62 select( 0, 0, 0, 0, &delay );
64 #else /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
67 #endif /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
69 #endif /* HAVE_USLEEP */
71 /***********************************************************************
75 void *memmove( void *dest, const void *src, unsigned int len )
77 register char *dst = dest;
79 /* Use memcpy if not overlapping */
80 if ((dst + len <= (char *)src) || ((char *)src + len <= dst))
82 memcpy( dst, src, len );
84 /* Otherwise do it the hard way (FIXME: could do better than this) */
87 while (len--) *dst++ = *((char *)src)++;
92 src = (char *)src + len - 1;
93 while (len--) *dst-- = *((char *)src)--;
97 #endif /* HAVE_MEMMOVE */
99 /***********************************************************************
102 #ifndef HAVE_STRERROR
103 const char *strerror( int err )
105 /* Let's hope we have sys_errlist then */
106 return sys_errlist[err];
108 #endif /* HAVE_STRERROR */
111 /***********************************************************************
114 #ifndef HAVE_GETPAGESIZE
115 size_t getpagesize(void)
118 return sysconf(_SC_PAGESIZE);
120 # error Cannot get the page size on this platform
123 #endif /* HAVE_GETPAGESIZE */
126 /***********************************************************************
129 #if !defined(HAVE_CLONE) && defined(__linux__)
130 int clone( int (*fn)(void *), void *stack, int flags, void *arg )
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"
140 "popl %%ebx\n\t" /* Contains fn in the child */
141 "testl %%eax,%%eax\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*/
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;
156 #endif /* __i386__ */
158 #endif /* !HAVE_CLONE && __linux__ */
160 /***********************************************************************
163 #ifndef HAVE_STRCASECMP
164 int strcasecmp( const char *str1, const char *str2 )
166 const unsigned char *ustr1 = (const unsigned char *)str1;
167 const unsigned char *ustr2 = (const unsigned char *)str2;
169 while (*ustr1 && toupper(*ustr1) == toupper(*ustr2)) {
173 return toupper(*ustr1) - toupper(*ustr2);
175 #endif /* HAVE_STRCASECMP */
177 /***********************************************************************
180 #ifndef HAVE_STRNCASECMP
181 int strncasecmp( const char *str1, const char *str2, size_t n )
183 const unsigned char *ustr1 = (const unsigned char *)str1;
184 const unsigned char *ustr2 = (const unsigned char *)str2;
188 while ((--n > 0) && *ustr1) {
189 if ((res = toupper(*ustr1) - toupper(*ustr2))) return res;
193 return toupper(*ustr1) - toupper(*ustr2);
195 #endif /* HAVE_STRNCASECMP */
197 /***********************************************************************
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.
205 * We should have a autoconf check for this.
207 int wine_openpty(int *master, int *slave, char *name,
208 struct termios *term, struct winsize *winsize)
211 return openpty(master, slave, name, term, winsize);
213 const char *ptr1, *ptr2;
216 strcpy (pts_name, "/dev/ptyXY");
218 for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
220 for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
223 if ((*master = open(pts_name, O_RDWR)) < 0) {
230 if ((*slave = open(pts_name, O_RDWR)) < 0) {
237 tcsetattr(*slave, TCSANOW, term);
239 ioctl(*slave, TIOCSWINSZ, winsize);
241 strcpy(name, pts_name);
250 /***********************************************************************
253 #ifndef HAVE_GETNETBYADDR
254 struct netent *getnetbyaddr(unsigned long net, int type)
259 #endif /* defined(HAVE_GETNETBYNAME) */
261 /***********************************************************************
264 #ifndef HAVE_GETNETBYNAME
265 struct netent *getnetbyname(const char *name)
270 #endif /* defined(HAVE_GETNETBYNAME) */
272 /***********************************************************************
275 #ifndef HAVE_GETPROTOBYNAME
276 struct protoent *getprotobyname(const char *name)
281 #endif /* !defined(HAVE_GETPROTOBYNAME) */
283 /***********************************************************************
286 #ifndef HAVE_GETPROTOBYNUMBER
287 struct protoent *getprotobynumber(int proto)
292 #endif /* !defined(HAVE_GETPROTOBYNUMBER) */
294 /***********************************************************************
297 #ifndef HAVE_GETSERVBYPORT
298 struct servent *getservbyport(int port, const char *proto)
303 #endif /* !defined(HAVE_GETSERVBYPORT) */
305 /***********************************************************************
308 #ifndef HAVE_GETSOCKOPT
309 int getsockopt(int socket, int level, int option_name,
310 void *option_value, size_t *option_len)
315 #endif /* !defined(HAVE_GETSOCKOPT) */
317 /***********************************************************************
320 #ifndef HAVE_INET_NETWORK
321 unsigned long inet_network(const char *cp)
326 #endif /* defined(HAVE_INET_NETWORK) */
328 /***********************************************************************
331 #ifndef HAVE_SETTIMEOFDAY
332 int settimeofday(struct timeval *tp, void *reserved)
340 #endif /* HAVE_SETTIMEOFDAY */
342 /***********************************************************************
346 int statfs(const char *name, struct statfs *info)
357 if ((mydev = dev_for_path(name)) < 0) {
362 if (fs_stat_dev(mydev,&fsinfo) < 0) {
367 info->f_bsize = fsinfo.block_size;
368 info->f_blocks = fsinfo.total_blocks;
369 info->f_bfree = fsinfo.free_blocks;
371 #else /* defined(__BEOS__) */
374 #endif /* defined(__BEOS__) */
376 #endif /* !defined(HAVE_STATFS) */
379 /***********************************************************************
383 int lstat(const char *file_name, struct stat *buf)
385 return stat( file_name, buf );
387 #endif /* HAVE_LSTAT */
389 /***********************************************************************
392 #ifndef HAVE_GETRLIMIT
393 int getrlimit (int resource, struct rlimit *rlim)
395 return -1; /* FAIL */
397 #endif /* HAVE_GETRLIMIT */
401 /***********************************************************************
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.
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.
418 static int solaris_try_mmap (void *addr, size_t len, int prot, int flags,
419 int fildes, off_t off)
421 char * volatile result = NULL;
422 int pagesize = getpagesize();
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. */
431 if ( (uintptr_t)addr & (pagesize-1) )
433 if ( flags & MAP_FIXED )
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. */
443 if ( (pid = vfork()) == -1 )
445 perror("solaris_try_mmap: vfork");
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 )
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 )
466 if ( result != (void *) -1 ) /* This should never happen ... */
467 munmap( result, len );
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. */
476 return result == addr;
480 /***********************************************************************
483 * Portable wrapper for anonymous mmaps
485 void *wine_anon_mmap( void *start, size_t size, int prot, int flags )
487 static int fdzero = -1;
494 if ((fdzero = open( "/dev/zero", O_RDONLY )) == -1)
496 perror( "/dev/zero: open" );
500 #endif /* MAP_ANON */
503 flags &= ~MAP_SHARED;
506 /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
508 flags |= MAP_PRIVATE;
512 if ( solaris_try_mmap( start, size, prot, flags, fdzero, 0 ) )
516 return mmap( start, size, prot, flags, fdzero, 0 );
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.
530 /***********************************************************************
533 void *wine_dlopen( const char *filename, int flag, char *error, int errorsize )
538 dlerror(); dlerror();
539 ret = dlopen( filename, flag );
543 strncpy( error, s ? s : "", errorsize );
544 error[errorsize - 1] = '\0';
551 strncpy( error, "dlopen interface not detected by configure", errorsize );
552 error[errorsize - 1] = '\0';
558 /***********************************************************************
561 void *wine_dlsym( void *handle, const char *symbol, char *error, int errorsize )
566 dlerror(); dlerror();
567 ret = dlsym( handle, symbol );
571 strncpy( error, s ? s : "", errorsize );
572 error[errorsize - 1] = '\0';
579 strncpy( error, "dlopen interface not detected by configure", errorsize );
580 error[errorsize - 1] = '\0';
586 /***********************************************************************
589 int wine_dlclose( void *handle, char *error, int errorsize )
594 dlerror(); dlerror();
595 ret = dlclose( handle );
599 strncpy( error, s ? s : "", errorsize );
600 error[errorsize - 1] = '\0';
607 strncpy( error, "dlopen interface not detected by configure", errorsize );
608 error[errorsize - 1] = '\0';
614 /***********************************************************************
615 * wine_rewrite_s4tos2
617 * Convert 4 byte Unicode strings to 2 byte Unicode strings in-place.
618 * This is only practical if literal strings are writable.
620 unsigned short* wine_rewrite_s4tos2(const wchar_t* str4 )
622 unsigned short *str2,*s2;
627 if ((*str4 & 0xffff0000) != 0) {
628 /* This string has already been converted. Return it as is */
629 return (unsigned short*)str4;
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.
636 str2=s2=(unsigned short*)str4;
638 *s2=(unsigned short)*str4;
640 } while (*str4++ != L'\0');
647 * NetBSD 1.5 doesn't have ecvt, fcvt, gcvt. We just check for ecvt, though.
648 * Fix/verify these implementations !
651 /***********************************************************************
654 char *ecvt (double number, int ndigits, int *decpt, int *sign)
656 static buf[40]; /* ought to be enough */
658 sprintf(buf, "%.*e", ndigits /* FIXME wrong */, number);
659 *sign = (number < 0);
660 dec = strchr(buf, '.');
661 *decpt = (dec) ? (int)dec - (int)buf : -1;
665 /***********************************************************************
668 char *fcvt (double number, int ndigits, int *decpt, int *sign)
670 static buf[40]; /* ought to be enough */
672 sprintf(buf, "%.*e", ndigits, number);
673 *sign = (number < 0);
674 dec = strchr(buf, '.');
675 *decpt = (dec) ? (int)dec - (int)buf : -1;
679 /***********************************************************************
682 * FIXME: uses both E and F.
684 char *gcvt (double number, size_t ndigit, char *buff)
686 sprintf(buff, "%.*E", ndigit, number);
689 #endif /* HAVE_ECVT */