Alexandre Julliard | 18f92e7 | 1996-07-17 20:02:21 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Misc. functions for systems that don't have them |
| 3 | * |
| 4 | * Copyright 1996 Alexandre Julliard |
| 5 | */ |
| 6 | |
| 7 | #include "config.h" |
Patrik Stridvall | 1ed4ecf | 1999-06-26 14:58:24 +0000 | [diff] [blame] | 8 | |
Alexandre Julliard | 3b96efc | 1999-09-04 14:36:02 +0000 | [diff] [blame^] | 9 | #include <ctype.h> |
Marcus Meissner | 3b09284 | 1999-02-20 16:46:39 +0000 | [diff] [blame] | 10 | #include <stdio.h> |
David Luyer | ee517e8 | 1999-02-28 12:27:56 +0000 | [diff] [blame] | 11 | #include <string.h> |
Patrik Stridvall | 1ed4ecf | 1999-06-26 14:58:24 +0000 | [diff] [blame] | 12 | #include <unistd.h> |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 13 | #include <sys/types.h> |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 14 | #include <sys/time.h> |
Alexandre Julliard | 8da12c4 | 1999-01-17 16:55:11 +0000 | [diff] [blame] | 15 | #include <sys/stat.h> |
| 16 | #include <sys/ioctl.h> |
| 17 | #include <errno.h> |
| 18 | #include <fcntl.h> |
| 19 | #include <termios.h> |
Marcus Meissner | 592ba10 | 1999-01-20 14:18:55 +0000 | [diff] [blame] | 20 | #ifdef HAVE_LIBIO_H |
| 21 | # include <libio.h> |
| 22 | #endif |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 23 | |
| 24 | #ifndef HAVE_USLEEP |
Alexandre Julliard | 349a953 | 1997-02-02 19:01:52 +0000 | [diff] [blame] | 25 | #ifdef __EMX__ |
| 26 | unsigned int usleep (unsigned int useconds) { DosSleep(useconds); } |
| 27 | #else |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 28 | unsigned int usleep (unsigned int useconds) |
| 29 | { |
| 30 | struct timeval delay; |
| 31 | |
| 32 | delay.tv_sec = 0; |
| 33 | delay.tv_usec = useconds; |
| 34 | |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 35 | select( 0, 0, 0, 0, &delay ); |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 36 | return 0; |
| 37 | } |
Alexandre Julliard | 349a953 | 1997-02-02 19:01:52 +0000 | [diff] [blame] | 38 | #endif |
Alexandre Julliard | 4f8c37b | 1996-01-14 18:12:01 +0000 | [diff] [blame] | 39 | #endif /* HAVE_USLEEP */ |
| 40 | |
Alexandre Julliard | 18f92e7 | 1996-07-17 20:02:21 +0000 | [diff] [blame] | 41 | #ifndef HAVE_MEMMOVE |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 42 | void *memmove( void *dest, const void *src, unsigned int len ) |
Alexandre Julliard | 18f92e7 | 1996-07-17 20:02:21 +0000 | [diff] [blame] | 43 | { |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 44 | register char *dst = dest; |
| 45 | |
Alexandre Julliard | 18f92e7 | 1996-07-17 20:02:21 +0000 | [diff] [blame] | 46 | /* Use memcpy if not overlapping */ |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 47 | if ((dst + len <= (char *)src) || ((char *)src + len <= dst)) |
Alexandre Julliard | 18f92e7 | 1996-07-17 20:02:21 +0000 | [diff] [blame] | 48 | { |
| 49 | memcpy( dst, src, len ); |
| 50 | } |
| 51 | /* Otherwise do it the hard way (FIXME: could do better than this) */ |
| 52 | else if (dst < src) |
| 53 | { |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 54 | while (len--) *dst++ = *((char *)src)++; |
Alexandre Julliard | 18f92e7 | 1996-07-17 20:02:21 +0000 | [diff] [blame] | 55 | } |
| 56 | else |
| 57 | { |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 58 | dst += len - 1; |
Alexandre Julliard | 18f92e7 | 1996-07-17 20:02:21 +0000 | [diff] [blame] | 59 | src = (char *)src + len - 1; |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 60 | while (len--) *dst-- = *((char *)src)--; |
Alexandre Julliard | 18f92e7 | 1996-07-17 20:02:21 +0000 | [diff] [blame] | 61 | } |
Alexandre Julliard | ac9c9b0 | 1996-07-28 18:50:11 +0000 | [diff] [blame] | 62 | return dest; |
Alexandre Julliard | 18f92e7 | 1996-07-17 20:02:21 +0000 | [diff] [blame] | 63 | } |
| 64 | #endif /* HAVE_MEMMOVE */ |
Alexandre Julliard | 44ed71f | 1997-12-21 19:17:50 +0000 | [diff] [blame] | 65 | |
| 66 | #ifndef HAVE_STRERROR |
| 67 | const char *strerror( int err ) |
| 68 | { |
| 69 | /* Let's hope we have sys_errlist then */ |
| 70 | return sys_errlist[err]; |
| 71 | } |
| 72 | #endif /* HAVE_STRERROR */ |
Alexandre Julliard | 0623a6f | 1998-01-18 18:01:49 +0000 | [diff] [blame] | 73 | |
| 74 | #if !defined(HAVE_CLONE) && defined(__linux__) |
| 75 | #include <assert.h> |
| 76 | #include <errno.h> |
| 77 | #include <syscall.h> |
| 78 | int clone( int (*fn)(void *), void *stack, int flags, void *arg ) |
| 79 | { |
| 80 | #ifdef __i386__ |
| 81 | int ret; |
| 82 | void **stack_ptr = (void **)stack; |
| 83 | *--stack_ptr = arg; /* Push argument on stack */ |
| 84 | *--stack_ptr = fn; /* Push function pointer (popped into ebx) */ |
| 85 | __asm__ __volatile__( "pushl %%ebx\n\t" |
| 86 | "movl %2,%%ebx\n\t" |
| 87 | "int $0x80\n\t" |
| 88 | "popl %%ebx\n\t" /* Contains fn in the child */ |
| 89 | "testl %%eax,%%eax\n\t" |
| 90 | "jnz 0f\n\t" |
| 91 | "call *%%ebx\n\t" /* Should never return */ |
| 92 | "xorl %%eax,%%eax\n\t" /* Just in case it does*/ |
| 93 | "0:" |
| 94 | : "=a" (ret) |
Marcus Meissner | 4ede296 | 1999-02-21 18:18:42 +0000 | [diff] [blame] | 95 | : "0" (SYS_clone), "r" (flags), "c" (stack_ptr) ); |
Alexandre Julliard | 0623a6f | 1998-01-18 18:01:49 +0000 | [diff] [blame] | 96 | assert( ret ); /* If ret is 0, we returned from the child function */ |
| 97 | if (ret > 0) return ret; |
| 98 | errno = -ret; |
| 99 | return -1; |
| 100 | #else |
| 101 | errno = EINVAL; |
| 102 | return -1; |
| 103 | #endif /* __i386__ */ |
| 104 | } |
| 105 | #endif /* !HAVE_CLONE && __linux__ */ |
Alexandre Julliard | 8da12c4 | 1999-01-17 16:55:11 +0000 | [diff] [blame] | 106 | |
| 107 | |
Alexandre Julliard | 3b96efc | 1999-09-04 14:36:02 +0000 | [diff] [blame^] | 108 | #ifndef HAVE_STRCASECMP |
| 109 | int strcasecmp( const char *str1, const char *str2 ) |
| 110 | { |
| 111 | while (*str1 && toupper(*str1) == toupper(*str2)) { str1++; str2++; } |
| 112 | return toupper(*str1) - toupper(*str2); |
| 113 | } |
| 114 | #endif /* HAVE_STRCASECMP */ |
| 115 | |
| 116 | #ifndef HAVE_STRNCASECMP |
| 117 | int strncasecmp( const char *str1, const char *str2, size_t n ) |
| 118 | { |
| 119 | int res; |
| 120 | if (!n) return 0; |
| 121 | while ((--n > 0) && *str1) |
| 122 | if ((res = toupper(*str1++) - toupper(*str2++))) return res; |
| 123 | return toupper(*str1) - toupper(*str2); |
| 124 | } |
| 125 | #endif /* HAVE_STRNCASECMP */ |
| 126 | |
Alexandre Julliard | 8da12c4 | 1999-01-17 16:55:11 +0000 | [diff] [blame] | 127 | /** |
| 128 | * It looks like the openpty that comes with glibc in RedHat 5.0 |
| 129 | * is buggy (second call returns what looks like a dup of 0 and 1 |
| 130 | * instead of a new pty), this is a generic replacement. |
| 131 | */ |
| 132 | /** We will have an autoconf check for this soon... */ |
| 133 | |
| 134 | int wine_openpty(int *master, int *slave, char *name, |
| 135 | struct termios *term, struct winsize *winsize) |
| 136 | { |
| 137 | char *ptr1, *ptr2; |
| 138 | char pts_name[512]; |
| 139 | |
| 140 | strcpy (pts_name, "/dev/ptyXY"); |
| 141 | |
| 142 | for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) { |
| 143 | pts_name[8] = *ptr1; |
| 144 | for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) { |
| 145 | pts_name[9] = *ptr2; |
| 146 | |
| 147 | if ((*master = open(pts_name, O_RDWR)) < 0) { |
| 148 | if (errno == ENOENT) |
| 149 | return -1; |
| 150 | else |
| 151 | continue; |
| 152 | } |
| 153 | pts_name[5] = 't'; |
| 154 | if ((*slave = open(pts_name, O_RDWR)) < 0) { |
| 155 | pts_name[5] = 'p'; |
| 156 | continue; |
| 157 | } |
| 158 | |
| 159 | if (term != NULL) |
| 160 | tcsetattr(*slave, TCSANOW, term); |
| 161 | if (winsize != NULL) |
| 162 | ioctl(*slave, TIOCSWINSZ, winsize); |
| 163 | if (name != NULL) |
| 164 | strcpy(name, pts_name); |
| 165 | return *slave; |
| 166 | } |
| 167 | } |
| 168 | return -1; |
| 169 | } |
| 170 | |