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
47 /***********************************************************************
51 unsigned int usleep (unsigned int useconds
)
56 #elif defined(__BEOS__)
57 return snooze(useconds
);
58 #elif defined(HAVE_SELECT)
61 delay
.tv_sec
= useconds
/ 1000000;
62 delay
.tv_usec
= useconds
% 1000000;
64 select( 0, 0, 0, 0, &delay
);
66 #else /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
69 #endif /* defined(__EMX__) || defined(__BEOS__) || defined(HAVE_SELECT) */
71 #endif /* HAVE_USLEEP */
73 /***********************************************************************
77 void *memmove( void *dest
, const void *src
, unsigned int len
)
79 register char *dst
= dest
;
81 /* Use memcpy if not overlapping */
82 if ((dst
+ len
<= (char *)src
) || ((char *)src
+ len
<= dst
))
84 memcpy( dst
, src
, len
);
86 /* Otherwise do it the hard way (FIXME: could do better than this) */
89 while (len
--) *dst
++ = *((char *)src
)++;
94 src
= (char *)src
+ len
- 1;
95 while (len
--) *dst
-- = *((char *)src
)--;
99 #endif /* HAVE_MEMMOVE */
101 /***********************************************************************
104 #ifndef HAVE_STRERROR
105 const char *strerror( int err
)
107 /* Let's hope we have sys_errlist then */
108 return sys_errlist
[err
];
110 #endif /* HAVE_STRERROR */
113 /***********************************************************************
116 #ifndef HAVE_GETPAGESIZE
117 size_t getpagesize(void)
120 return sysconf(_SC_PAGESIZE
);
122 # error Cannot get the page size on this platform
125 #endif /* HAVE_GETPAGESIZE */
128 /***********************************************************************
131 #if !defined(HAVE_CLONE) && defined(__linux__)
132 int clone( int (*fn
)(void *), void *stack
, int flags
, void *arg
)
136 void **stack_ptr
= (void **)stack
;
137 *--stack_ptr
= arg
; /* Push argument on stack */
138 *--stack_ptr
= fn
; /* Push function pointer (popped into ebx) */
139 __asm__
__volatile__( "pushl %%ebx\n\t"
142 "popl %%ebx\n\t" /* Contains fn in the child */
143 "testl %%eax,%%eax\n\t"
145 "xorl %ebp,%ebp\n\t" /* Terminate the stack frames */
146 "call *%%ebx\n\t" /* Should never return */
147 "xorl %%eax,%%eax\n\t" /* Just in case it does*/
150 : "0" (SYS_clone
), "r" (flags
), "c" (stack_ptr
) );
151 assert( ret
); /* If ret is 0, we returned from the child function */
152 if (ret
> 0) return ret
;
158 #endif /* __i386__ */
160 #endif /* !HAVE_CLONE && __linux__ */
162 /***********************************************************************
165 #ifndef HAVE_STRCASECMP
166 int strcasecmp( const char *str1
, const char *str2
)
168 const unsigned char *ustr1
= (const unsigned char *)str1
;
169 const unsigned char *ustr2
= (const unsigned char *)str2
;
171 while (*ustr1
&& toupper(*ustr1
) == toupper(*ustr2
)) {
175 return toupper(*ustr1
) - toupper(*ustr2
);
177 #endif /* HAVE_STRCASECMP */
179 /***********************************************************************
182 #ifndef HAVE_STRNCASECMP
183 int strncasecmp( const char *str1
, const char *str2
, size_t n
)
185 const unsigned char *ustr1
= (const unsigned char *)str1
;
186 const unsigned char *ustr2
= (const unsigned char *)str2
;
190 while ((--n
> 0) && *ustr1
) {
191 if ((res
= toupper(*ustr1
) - toupper(*ustr2
))) return res
;
195 return toupper(*ustr1
) - toupper(*ustr2
);
197 #endif /* HAVE_STRNCASECMP */
199 /***********************************************************************
202 * It looks like the openpty that comes with glibc in RedHat 5.0
203 * is buggy (second call returns what looks like a dup of 0 and 1
204 * instead of a new pty), this is a generic replacement.
207 * We should have a autoconf check for this.
209 int wine_openpty(int *master
, int *slave
, char *name
,
210 struct termios
*term
, struct winsize
*winsize
)
213 return openpty(master
, slave
, name
, term
, winsize
);
215 const char *ptr1
, *ptr2
;
218 strcpy (pts_name
, "/dev/ptyXY");
220 for (ptr1
= "pqrstuvwxyzPQRST"; *ptr1
!= 0; ptr1
++) {
222 for (ptr2
= "0123456789abcdef"; *ptr2
!= 0; ptr2
++) {
225 if ((*master
= open(pts_name
, O_RDWR
)) < 0) {
232 if ((*slave
= open(pts_name
, O_RDWR
)) < 0) {
239 tcsetattr(*slave
, TCSANOW
, term
);
241 ioctl(*slave
, TIOCSWINSZ
, winsize
);
243 strcpy(name
, pts_name
);
252 /***********************************************************************
255 #ifndef HAVE_GETNETBYADDR
256 struct netent
*getnetbyaddr(unsigned long net
, int type
)
261 #endif /* defined(HAVE_GETNETBYNAME) */
263 /***********************************************************************
266 #ifndef HAVE_GETNETBYNAME
267 struct netent
*getnetbyname(const char *name
)
272 #endif /* defined(HAVE_GETNETBYNAME) */
274 /***********************************************************************
277 #ifndef HAVE_GETPROTOBYNAME
278 struct protoent
*getprotobyname(const char *name
)
283 #endif /* !defined(HAVE_GETPROTOBYNAME) */
285 /***********************************************************************
288 #ifndef HAVE_GETPROTOBYNUMBER
289 struct protoent
*getprotobynumber(int proto
)
294 #endif /* !defined(HAVE_GETPROTOBYNUMBER) */
296 /***********************************************************************
299 #ifndef HAVE_GETSERVBYPORT
300 struct servent
*getservbyport(int port
, const char *proto
)
305 #endif /* !defined(HAVE_GETSERVBYPORT) */
307 /***********************************************************************
310 #ifndef HAVE_GETSOCKOPT
311 int getsockopt(int socket
, int level
, int option_name
,
312 void *option_value
, size_t *option_len
)
317 #endif /* !defined(HAVE_GETSOCKOPT) */
319 /***********************************************************************
322 #ifndef HAVE_INET_NETWORK
323 unsigned long inet_network(const char *cp
)
328 #endif /* defined(HAVE_INET_NETWORK) */
330 /***********************************************************************
333 #ifndef HAVE_SETTIMEOFDAY
334 int settimeofday(struct timeval
*tp
, void *reserved
)
342 #endif /* HAVE_SETTIMEOFDAY */
344 /***********************************************************************
348 int statfs(const char *name
, struct statfs
*info
)
359 if ((mydev
= dev_for_path(name
)) < 0) {
364 if (fs_stat_dev(mydev
,&fsinfo
) < 0) {
369 info
->f_bsize
= fsinfo
.block_size
;
370 info
->f_blocks
= fsinfo
.total_blocks
;
371 info
->f_bfree
= fsinfo
.free_blocks
;
373 #else /* defined(__BEOS__) */
376 #endif /* defined(__BEOS__) */
378 #endif /* !defined(HAVE_STATFS) */
381 /***********************************************************************
385 int lstat(const char *file_name
, struct stat
*buf
)
387 return stat( file_name
, buf
);
389 #endif /* HAVE_LSTAT */
391 /***********************************************************************
394 #ifndef HAVE_GETRLIMIT
395 int getrlimit (int resource
, struct rlimit
*rlim
)
397 return -1; /* FAIL */
399 #endif /* HAVE_GETRLIMIT */
402 #if defined(__svr4__) || defined(__NetBSD__)
403 /***********************************************************************
406 * The purpose of this routine is to emulate the behaviour of
407 * the Linux mmap() routine if a non-NULL address is passed,
408 * but the MAP_FIXED flag is not set. Linux in this case tries
409 * to place the mapping at the specified address, *unless* the
410 * range is already in use. Solaris, however, completely ignores
411 * the address argument in this case.
413 * As Wine code occasionally relies on the Linux behaviour, e.g. to
414 * be able to map non-relocateable PE executables to their proper
415 * start addresses, or to map the DOS memory to 0, this routine
416 * emulates the Linux behaviour by checking whether the desired
417 * address range is still available, and placing the mapping there
418 * using MAP_FIXED if so.
420 static int try_mmap_fixed (void *addr
, size_t len
, int prot
, int flags
,
421 int fildes
, off_t off
)
423 char * volatile result
= NULL
;
424 int pagesize
= getpagesize();
427 /* We only try to map to a fixed address if
428 addr is non-NULL and properly aligned,
429 and MAP_FIXED isn't already specified. */
433 if ( (uintptr_t)addr
& (pagesize
-1) )
435 if ( flags
& MAP_FIXED
)
438 /* We use vfork() to freeze all threads of the
439 current process. This allows us to check without
440 race condition whether the desired memory range is
441 already in use. Note that because vfork() shares
442 the address spaces between parent and child, we
443 can actually perform the mapping in the child. */
445 if ( (pid
= vfork()) == -1 )
447 perror("try_mmap_fixed: vfork");
455 /* We call mincore() for every page in the desired range.
456 If any of these calls succeeds, the page is already
457 mapped and we must fail. */
458 for ( i
= 0; i
< len
; i
+= pagesize
)
459 if ( mincore( (caddr_t
)addr
+ i
, pagesize
, &vec
) != -1 )
462 /* Perform the mapping with MAP_FIXED set. This is safe
463 now, as none of the pages is currently in use. */
464 result
= mmap( addr
, len
, prot
, flags
| MAP_FIXED
, fildes
, off
);
465 if ( result
== addr
)
468 if ( result
!= (void *) -1 ) /* This should never happen ... */
469 munmap( result
, len
);
474 /* vfork() lets the parent continue only after the child
475 has exited. Furthermore, Wine sets SIGCHLD to SIG_IGN,
476 so we don't need to wait for the child. */
478 return result
== addr
;
482 /***********************************************************************
485 * Portable wrapper for anonymous mmaps
487 void *wine_anon_mmap( void *start
, size_t size
, int prot
, int flags
)
489 static int fdzero
= -1;
496 if ((fdzero
= open( "/dev/zero", O_RDONLY
)) == -1)
498 perror( "/dev/zero: open" );
502 #endif /* MAP_ANON */
505 flags
&= ~MAP_SHARED
;
508 /* Linux EINVAL's on us if we don't pass MAP_PRIVATE to an anon mmap */
510 flags
|= MAP_PRIVATE
;
513 #if defined(__svr4__) || defined(__NetBSD__)
514 if ( try_mmap_fixed( start
, size
, prot
, flags
, fdzero
, 0 ) )
518 return mmap( start
, size
, prot
, flags
, fdzero
, 0 );
523 * These functions provide wrappers around dlopen() and associated
524 * functions. They work around a bug in glibc 2.1.x where calling
525 * a dl*() function after a previous dl*() function has failed
526 * without a dlerror() call between the two will cause a crash.
527 * They all take a pointer to a buffer that
528 * will receive the error description (from dlerror()). This
529 * parameter may be NULL if the error description is not required.
532 /***********************************************************************
535 void *wine_dlopen( const char *filename
, int flag
, char *error
, int errorsize
)
540 dlerror(); dlerror();
541 ret
= dlopen( filename
, flag
);
545 strncpy( error
, s
? s
: "", errorsize
);
546 error
[errorsize
- 1] = '\0';
553 strncpy( error
, "dlopen interface not detected by configure", errorsize
);
554 error
[errorsize
- 1] = '\0';
560 /***********************************************************************
563 void *wine_dlsym( void *handle
, const char *symbol
, char *error
, int errorsize
)
568 dlerror(); dlerror();
569 ret
= dlsym( handle
, symbol
);
573 strncpy( error
, s
? s
: "", errorsize
);
574 error
[errorsize
- 1] = '\0';
581 strncpy( error
, "dlopen interface not detected by configure", errorsize
);
582 error
[errorsize
- 1] = '\0';
588 /***********************************************************************
591 int wine_dlclose( void *handle
, char *error
, int errorsize
)
596 dlerror(); dlerror();
597 ret
= dlclose( handle
);
601 strncpy( error
, s
? s
: "", errorsize
);
602 error
[errorsize
- 1] = '\0';
609 strncpy( error
, "dlopen interface not detected by configure", errorsize
);
610 error
[errorsize
- 1] = '\0';
616 /***********************************************************************
617 * wine_rewrite_s4tos2
619 * Convert 4 byte Unicode strings to 2 byte Unicode strings in-place.
620 * This is only practical if literal strings are writable.
622 unsigned short* wine_rewrite_s4tos2(const wchar_t* str4
)
624 unsigned short *str2
,*s2
;
629 if ((*str4
& 0xffff0000) != 0) {
630 /* This string has already been converted. Return it as is */
631 return (unsigned short*)str4
;
634 /* Note that we can also end up here if the string has a single
635 * character. In such a case we will convert the string over and
636 * over again. But this is harmless.
638 str2
=s2
=(unsigned short*)str4
;
640 *s2
=(unsigned short)*str4
;
642 } while (*str4
++ != L
'\0');
649 * NetBSD 1.5 doesn't have ecvt, fcvt, gcvt. We just check for ecvt, though.
650 * Fix/verify these implementations !
653 /***********************************************************************
656 char *ecvt (double number
, int ndigits
, int *decpt
, int *sign
)
658 static char buf
[40]; /* ought to be enough */
660 sprintf(buf
, "%.*e", ndigits
/* FIXME wrong */, number
);
661 *sign
= (number
< 0);
662 dec
= strchr(buf
, '.');
663 *decpt
= (dec
) ? (int)dec
- (int)buf
: -1;
667 /***********************************************************************
670 char *fcvt (double number
, int ndigits
, int *decpt
, int *sign
)
672 static char buf
[40]; /* ought to be enough */
674 sprintf(buf
, "%.*e", ndigits
, number
);
675 *sign
= (number
< 0);
676 dec
= strchr(buf
, '.');
677 *decpt
= (dec
) ? (int)dec
- (int)buf
: -1;
681 /***********************************************************************
684 * FIXME: uses both E and F.
686 char *gcvt (double number
, size_t ndigit
, char *buff
)
688 sprintf(buff
, "%.*E", (int)ndigit
, number
);
691 #endif /* HAVE_ECVT */