diff options
Diffstat (limited to 'beos.c')
-rw-r--r-- | beos.c | 267 |
1 files changed, 267 insertions, 0 deletions
@@ -0,0 +1,267 @@ +/* beos.c + * (c) 2002 Mikulas Patocka + * This file is a part of the Links program, released under GPL + */ + +#if defined(__BEOS__) || defined(__HAIKU__) + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <be/kernel/OS.h> + +#define SHS 128 + +#ifndef MAXINT +#define MAXINT 0x7fffffff +#endif + +#ifdef __HAIKU__ +int closesocket(int); +#endif + +#include "beos.h" + +int be_read(int s, void *ptr, int len) +{ + if (s >= SHS) return recv(s - SHS, ptr, len, 0); + return read(s, ptr, len); +} + +int be_write(int s, void *ptr, int len) +{ + if (s >= SHS) return send(s - SHS, ptr, len, 0); + return write(s, ptr, len); +} + +int be_close(int s) +{ + if (s >= SHS) return closesocket(s - SHS); + return close(s); +} + +int be_socket(int af, int sock, int prot) +{ + int h = socket(af, sock, prot); + if (h < 0) return h; + return h + SHS; +} + +int be_connect(int s, struct sockaddr *sa, int sal) +{ + return connect(s - SHS, sa, sal); +} + +int be_getpeername(int s, struct sockaddr *sa, int *sal) +{ + return getpeername(s - SHS, sa, sal); +} + +int be_getsockname(int s, struct sockaddr *sa, int *sal) +{ + return getsockname(s - SHS, sa, sal); +} + +int be_listen(int s, int c) +{ + return listen(s - SHS, c); +} + +int be_accept(int s, struct sockaddr *sa, int *sal) +{ + int a = accept(s - SHS, sa, sal); + if (a < 0) return -1; + return a + SHS; +} + +int be_bind(int s, struct sockaddr *sa, int sal) +{ + /*struct sockaddr_in *sin = (struct sockaddr_in *)sa; + if (!ntohs(sin->sin_port)) { + int i; + for (i = 16384; i < 49152; i++) { + sin->sin_port = htons(i); + if (!be_bind(s, sa, sal)) return 0; + } + return -1; + }*/ + if (bind(s - SHS, sa, sal)) return -1; + getsockname(s - SHS, sa, &sal); + return 0; +} + +#define PIPE_RETRIES 10 + +int be_pipe(int *fd) +{ + int s1, s2, s3, l; + struct sockaddr_in sa1, sa2; + int retry_count = 0; + again: + if ((s1 = be_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + /*perror("socket1");*/ + goto fatal_retry; + } + if ((s2 = be_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + /*perror("socket2");*/ + be_close(s1); + goto fatal_retry; + } + memset(&sa1, 0, sizeof(sa1)); + sa1.sin_family = AF_INET; + sa1.sin_port = htons(0); + sa1.sin_addr.s_addr = INADDR_ANY; + if (be_bind(s1, (struct sockaddr *)&sa1, sizeof(sa1))) { + /*perror("bind");*/ + clo: + be_close(s1); + be_close(s2); + goto fatal_retry; + } + if (be_listen(s1, 1)) { + /*perror("listen");*/ + goto clo; + } + if (be_connect(s2, (struct sockaddr *)&sa1, sizeof(sa1))) { + /*perror("connect");*/ + goto clo; + } + l = sizeof(sa2); + if ((s3 = be_accept(s1, (struct sockaddr *)&sa2, &l)) < 0) { + /*perror("accept");*/ + goto clo; + } + be_getsockname(s3, (struct sockaddr *)&sa1, &l); + if (sa1.sin_addr.s_addr != sa2.sin_addr.s_addr) { + be_close(s3); + goto clo; + } + be_close(s1); + fd[0] = s2; + fd[1] = s3; + return 0; + + fatal_retry: + if (++retry_count > PIPE_RETRIES) return -1; + sleep(1); + goto again; +} + +int be_select(int n, struct fd_set *rd, struct fd_set *wr, struct fd_set *exc, struct timeval *tm) +{ + int i, s; + struct fd_set d, rrd; +retry: + FD_ZERO(&d); + if (!rd) rd = &d; + if (!wr) wr = &d; + if (!exc) exc = &d; + if (n >= FD_SETSIZE) n = FD_SETSIZE; + FD_ZERO(exc); + for (i = 0; i < n; i++) if ((i < SHS && FD_ISSET(i, rd)) || FD_ISSET(i, wr)) { + for (i = SHS; i < n; i++) FD_CLR(i, rd); + return MAXINT; + } + FD_ZERO(&rrd); + for (i = SHS; i < n; i++) if (FD_ISSET(i, rd)) FD_SET(i - SHS, &rrd); + if ((s = select(FD_SETSIZE, &rrd, &d, &d, tm)) < 0) { + if (errno == EINTR) goto retry; + FD_ZERO(rd); + return 0; + } + FD_ZERO(rd); + for (i = SHS; i < n; i++) if (FD_ISSET(i - SHS, &rrd)) FD_SET(i, rd); + return s; +} + +#ifndef SO_ERROR +#define SO_ERROR 10001 +#endif + +int be_getsockopt(int s, int level, int optname, void *optval, int *optlen) +{ + if (optname == SO_ERROR && *optlen >= sizeof(int)) { + *(int *)optval = 0; + *optlen = sizeof(int); + return 0; + } + return -1; +} + +static int ihpipe[2]; + +static int inth; + +static void input_handle_th(void *p) +{ + char c; + int b = 0; + setsockopt(ihpipe[1], SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); + while (1) if (read(0, &c, 1) == 1) be_write(ihpipe[1], &c, 1); +} + +int get_input_handle(void) +{ + static int h = -1; + if (h >= 0) return h; + if (be_pipe(ihpipe) < 0) return -1; + if ((inth = start_thr(input_handle_th, NULL, "input_thread")) < 0) { + closesocket(ihpipe[0]); + closesocket(ihpipe[1]); + error("Can't spawn input thread"); + fatal_tty_exit(); + exit(4); + } + return h = ihpipe[0]; +} + +void block_stdin(void) +{ + suspend_thread(inth); +} + +void unblock_stdin(void) +{ + resume_thread(inth); +} + +/*int ohpipe[2]; + +#define O_BUF 16384 + +static void output_handle_th(void *p) +{ + char *c = malloc(O_BUF); + int r, b = 0; + if (!c) return; + setsockopt(ohpipe[1], SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); + while ((r = be_read(ohpipe[0], c, O_BUF)) > 0) write(1, c, r); + free(c); +} + +int get_output_handle(void) +{ + static int h = -1; + if (h >= 0) return h; + if (be_pipe(ohpipe) < 0) return -1; + if (start_thr(output_handle_th, NULL, "output_thread") < 0) { + closesocket(ohpipe[0]); + closesocket(ohpipe[1]); + error("Can't spawn output thread"); + fatal_tty_exit(); + exit(4); + } + return h = ohpipe[1]; +}*/ + +#else + +typedef int beos_c_no_empty_unit; + +#endif |