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