1 /* beos.c
2  * (c) 2002 Mikulas Patocka
3  * This file is a part of the Links program, released under GPL
4  */
5 
6 #if defined(__BEOS__) || defined(__HAIKU__)
7 
8 #include "com-defs.h"
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <sys/time.h>
18 #include <netinet/in.h>
19 #include <be/kernel/OS.h>
20 
21 #define SHS	128
22 
23 #ifndef MAXINT
24 #define MAXINT 0x7fffffff
25 #endif
26 
27 #ifdef __HAIKU__
28 int closesocket(int);
29 #endif
30 
be_read(int s,void * ptr,int len)31 int be_read(int s, void *ptr, int len)
32 {
33 	if (s >= SHS) return recv(s - SHS, ptr, len, 0);
34 	return read(s, ptr, len);
35 }
36 
be_write(int s,void * ptr,int len)37 int be_write(int s, void *ptr, int len)
38 {
39 	if (s >= SHS) return send(s - SHS, ptr, len, 0);
40 	return write(s, ptr, len);
41 }
42 
be_close(int s)43 int be_close(int s)
44 {
45 	if (s >= SHS) return closesocket(s - SHS);
46 	return close(s);
47 }
48 
be_socket(int af,int sock,int prot)49 int be_socket(int af, int sock, int prot)
50 {
51 	int h = socket(af, sock, prot);
52 	if (h < 0) return h;
53 	return h + SHS;
54 }
55 
be_connect(int s,struct sockaddr * sa,int sal)56 int be_connect(int s, struct sockaddr *sa, int sal)
57 {
58 	return connect(s - SHS, sa, sal);
59 }
60 
be_getpeername(int s,struct sockaddr * sa,int * sal)61 int be_getpeername(int s, struct sockaddr *sa, int *sal)
62 {
63 	return getpeername(s - SHS, sa, sal);
64 }
65 
be_getsockname(int s,struct sockaddr * sa,int * sal)66 int be_getsockname(int s, struct sockaddr *sa, int *sal)
67 {
68 	return getsockname(s - SHS, sa, sal);
69 }
70 
be_listen(int s,int c)71 int be_listen(int s, int c)
72 {
73 	return listen(s - SHS, c);
74 }
75 
be_accept(int s,struct sockaddr * sa,int * sal)76 int be_accept(int s, struct sockaddr *sa, int *sal)
77 {
78 	int a = accept(s - SHS, sa, sal);
79 	if (a < 0) return -1;
80 	return a + SHS;
81 }
82 
be_bind(int s,struct sockaddr * sa,int sal)83 int be_bind(int s, struct sockaddr *sa, int sal)
84 {
85 	/*struct sockaddr_in *sin = (struct sockaddr_in *)sa;
86 	if (!ntohs(sin->sin_port)) {
87 		int i;
88 		for (i = 16384; i < 49152; i++) {
89 			sin->sin_port = htons(i);
90 			if (!be_bind(s, sa, sal)) return 0;
91 		}
92 		return -1;
93 	}*/
94 	if (bind(s - SHS, sa, sal)) return -1;
95 	getsockname(s - SHS, sa, &sal);
96 	return 0;
97 }
98 
99 #define PIPE_RETRIES	10
100 
be_pipe(int * fd)101 int be_pipe(int *fd)
102 {
103 	int s1, s2, s3, l;
104 	struct sockaddr_in sa1, sa2;
105 	int retry_count = 0;
106 	again:
107 	if ((s1 = be_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
108 		/*perror("socket1");*/
109 		goto fatal_retry;
110 	}
111 	if ((s2 = be_socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
112 		/*perror("socket2");*/
113 		be_close(s1);
114 		goto fatal_retry;
115 	}
116 	memset(&sa1, 0, sizeof(sa1));
117 	sa1.sin_family = AF_INET;
118 	sa1.sin_port = htons(0);
119 	sa1.sin_addr.s_addr = INADDR_ANY;
120 	if (be_bind(s1, (struct sockaddr *)&sa1, sizeof(sa1))) {
121 		/*perror("bind");*/
122 		clo:
123 		be_close(s1);
124 		be_close(s2);
125 		goto fatal_retry;
126 	}
127 	if (be_listen(s1, 1)) {
128 		/*perror("listen");*/
129 		goto clo;
130 	}
131 	if (be_connect(s2, (struct sockaddr *)&sa1, sizeof(sa1))) {
132 		/*perror("connect");*/
133 		goto clo;
134 	}
135 	l = sizeof(sa2);
136 	if ((s3 = be_accept(s1, (struct sockaddr *)&sa2, &l)) < 0) {
137 		/*perror("accept");*/
138 		goto clo;
139 	}
140 	be_getsockname(s3, (struct sockaddr *)&sa1, &l);
141 	if (sa1.sin_addr.s_addr != sa2.sin_addr.s_addr) {
142 		be_close(s3);
143 		goto clo;
144 	}
145 	be_close(s1);
146 	fd[0] = s2;
147 	fd[1] = s3;
148 	return 0;
149 
150 	fatal_retry:
151 	if (++retry_count > PIPE_RETRIES) return -1;
152 	sleep(1);
153 	goto again;
154 }
155 
be_select(int n,struct fd_set * rd,struct fd_set * wr,struct fd_set * exc,struct timeval * tm)156 int be_select(int n, struct fd_set *rd, struct fd_set *wr, struct fd_set *exc, struct timeval *tm)
157 {
158 	int i, s;
159 	struct fd_set d, rrd;
160 retry:
161 	FD_ZERO(&d);
162 	if (!rd) rd = &d;
163 	if (!wr) wr = &d;
164 	if (!exc) exc = &d;
165 	if (n >= FD_SETSIZE) n = FD_SETSIZE;
166 	FD_ZERO(exc);
167 	for (i = 0; i < n; i++) if ((i < SHS && FD_ISSET(i, rd)) || FD_ISSET(i, wr)) {
168 		for (i = SHS; i < n; i++) FD_CLR(i, rd);
169 		return MAXINT;
170 	}
171 	FD_ZERO(&rrd);
172 	for (i = SHS; i < n; i++) if (FD_ISSET(i, rd)) FD_SET(i - SHS, &rrd);
173 	if ((s = select(FD_SETSIZE, &rrd, &d, &d, tm)) < 0) {
174 		if (errno == EINTR) goto retry;
175 		FD_ZERO(rd);
176 		return 0;
177 	}
178 	FD_ZERO(rd);
179 	for (i = SHS; i < n; i++) if (FD_ISSET(i - SHS, &rrd)) FD_SET(i, rd);
180 	return s;
181 }
182 
183 #ifndef SO_ERROR
184 #define SO_ERROR	10001
185 #endif
186 
be_getsockopt(int s,int level,int optname,void * optval,int * optlen)187 int be_getsockopt(int s, int level, int optname, void *optval, int *optlen)
188 {
189 	if (optname == SO_ERROR && *optlen >= sizeof(int)) {
190 		*(int *)optval = 0;
191 		*optlen = sizeof(int);
192 		return 0;
193 	}
194 	return -1;
195 }
196 
197 int start_thr(void (*)(void *), void *, unsigned char *);
198 
199 int ihpipe[2];
200 
201 int inth;
202 
input_handle_th(void * p)203 void input_handle_th(void *p)
204 {
205 	char c;
206 	int b = 0;
207 	setsockopt(ihpipe[1], SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
208 	while (1) if (read(0, &c, 1) == 1) be_write(ihpipe[1], &c, 1);
209 }
210 
get_input_handle()211 int get_input_handle()
212 {
213 	static int h = -1;
214 	if (h >= 0) return h;
215 	if (be_pipe(ihpipe) < 0) return -1;
216 	if ((inth = start_thr(input_handle_th, NULL, "input_thread")) < 0) {
217 		closesocket(ihpipe[0]);
218 		closesocket(ihpipe[1]);
219 		fprintf(stderr, "Can't spawn input thread");
220 		exit(4);
221 	}
222 	return h = ihpipe[0];
223 }
224 
block_stdin()225 void block_stdin()
226 {
227 	suspend_thread(inth);
228 }
229 
unblock_stdin()230 void unblock_stdin()
231 {
232 	resume_thread(inth);
233 }
234 
235 /*int ohpipe[2];
236 
237 #define O_BUF	16384
238 
239 void output_handle_th(void *p)
240 {
241 	char *c = malloc(O_BUF);
242 	int r, b = 0;
243 	if (!c) return;
244 	setsockopt(ohpipe[1], SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
245 	while ((r = be_read(ohpipe[0], c, O_BUF)) > 0) write(1, c, r);
246 	free(c);
247 }
248 
249 int get_output_handle()
250 {
251 	static int h = -1;
252 	if (h >= 0) return h;
253 	if (be_pipe(ohpipe) < 0) return -1;
254 	if (start_thr(output_handle_th, NULL, "output_thread") < 0) {
255 		closesocket(ohpipe[0]);
256 		closesocket(ohpipe[1]);
257 		fprintf(stderr, "Can't spawn output thread");
258 		exit(4);
259 	}
260 	return h = ohpipe[1];
261 }*/
262 
263 #else
264 
265 typedef int beos_c_no_empty_unit;
266 
267 #endif
268