1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * bsdsocket.library emulation machine-independent part
5 *
6 * Copyright 1997, 1998 Mathias Ortmann
7 *
8 * Library initialization code (c) Tauno Taipaleenmaki
9 */
10 
11 #include "sysconfig.h"
12 #include "sysdeps.h"
13 
14 #include <assert.h>
15 #include <stddef.h>
16 
17 #include "options.h"
18 #include "uae/memory.h"
19 #include "custom.h"
20 #include "newcpu.h"
21 #include "autoconf.h"
22 #include "traps.h"
23 #include "bsdsocket.h"
24 #include "threaddep/thread.h"
25 #include "native2amiga.h"
26 
27 #ifdef FSUAE // NL
28 #if defined(WINDOWS) && !defined(_WIN32)
29 #define _WIN32
30 #endif
31 #endif
32 
33 #ifdef FSUAE //NL
34 /*
35 FIXME: there is something strange here:
36 For example, there is:
37                         if (ulTmp < number_sys_error) {
38                             tagcopy (currtag, currval, tagptr, &iotextptrs[ulTmp]);
39 Bit iotextptrs are never initialized. Instead, there this this initalization using the same number_sys_error variable:
40     for (i = 0; i < (int) (number_sys_error); i++)
41         errnotextptrs[i] = addstr (&tmp1, errortexts[i]);
42 */
43 #endif
44 #ifdef BSDSOCKET
45 
46 int log_bsd = 0;
47 struct socketbase *socketbases;
48 static uae_u32 SockLibBase;
49 
50 #define SOCKPOOLSIZE 128
51 #define UNIQUE_ID (-1)
52 
53 /* ObtainSocket()/ReleaseSocket() public socket pool */
54 struct sockd {
55 	long sockpoolids[SOCKPOOLSIZE];
56 	SOCKET_TYPE sockpoolsocks[SOCKPOOLSIZE];
57 	uae_u32 sockpoolflags[SOCKPOOLSIZE];
58 };
59 
60 static long curruniqid = 65536;
61 static struct sockd *sockdata;
62 
strncpyha(uae_u32 dst,const uae_char * src,int size)63 uae_u32 strncpyha (uae_u32 dst, const uae_char *src, int size)
64 {
65 	uae_u32 res = dst;
66 	if (!addr_valid (_T("strncpyha"), dst, size))
67 		return res;
68 	while (size--) {
69 		put_byte (dst++, *src);
70 		if (!*src++)
71 			return res;
72 	}
73 	return res;
74 }
75 
addstr(uae_u32 * dst,const TCHAR * src)76 uae_u32 addstr (uae_u32 * dst, const TCHAR *src)
77 {
78 	uae_u32 res = *dst;
79 	int len;
80 	char *s = ua (src);
81 	len = strlen (s) + 1;
82 	strcpyha_safe (*dst, s);
83 	(*dst) += len;
84 	xfree (s);
85 	return res;
86 }
addstr_ansi(uae_u32 * dst,const uae_char * src)87 uae_u32 addstr_ansi (uae_u32 * dst, const uae_char *src)
88 {
89 	uae_u32 res = *dst;
90 	int len;
91 	len = strlen (src) + 1;
92 	strcpyha_safe (*dst, src);
93 	(*dst) += len;
94 	return res;
95 }
96 
addmem(uae_u32 * dst,const uae_char * src,int len)97 uae_u32 addmem (uae_u32 * dst, const uae_char *src, int len)
98 {
99 	uae_u32 res = *dst;
100 
101 	if (!src)
102 		return 0;
103 
104 	memcpyha_safe (*dst, (uae_u8*)src, len);
105 	(*dst) += len;
106 
107 	return res;
108 }
109 
110 /* Get current task */
gettask(TrapContext * context)111 static uae_u32 gettask (TrapContext *context)
112 {
113 	uae_u32 currtask, a1 = m68k_areg (regs, 1);
114 	TCHAR *tskname;
115 
116 	m68k_areg (regs, 1) = 0;
117 	currtask = CallLib (context, get_long (4), -0x126); /* FindTask */
118 
119 	m68k_areg (regs, 1) = a1;
120 
121 	tskname = au((char*)get_real_address (get_long (currtask + 10)));
122 	BSDTRACE ((_T("[%s] "), tskname));
123 	xfree (tskname);
124 	return currtask;
125 }
126 
127 /* errno/herrno setting */
bsdsocklib_seterrno(SB,int sb_errno)128 void bsdsocklib_seterrno (SB, int sb_errno)
129 {
130 	sb->sb_errno = sb_errno;
131 	if (sb->sb_errno >= 1001 && sb->sb_errno <= 1005)
132 		bsdsocklib_setherrno(sb,sb->sb_errno-1000);
133 	if (sb->errnoptr) {
134 		switch (sb->errnosize) {
135 		case 1:
136 			put_byte (sb->errnoptr, sb_errno);
137 			break;
138 		case 2:
139 			put_word (sb->errnoptr, sb_errno);
140 			break;
141 		case 4:
142 			put_long (sb->errnoptr, sb_errno);
143 		}
144 	}
145 }
146 
bsdsocklib_setherrno(SB,int sb_herrno)147 void bsdsocklib_setherrno (SB, int sb_herrno)
148 {
149 	sb->sb_herrno = sb_herrno;
150 
151 	if (sb->herrnoptr) {
152 		switch (sb->herrnosize) {
153 		case 1:
154 			put_byte (sb->herrnoptr, sb_herrno);
155 			break;
156 		case 2:
157 			put_word (sb->herrnoptr, sb_herrno);
158 			break;
159 		case 4:
160 			put_long (sb->herrnoptr, sb_herrno);
161 		}
162 	}
163 }
164 
callfdcallback(TrapContext * context,SB,uae_u32 fd,uae_u32 action)165 uae_u32 callfdcallback (TrapContext *context, SB, uae_u32 fd, uae_u32 action)
166 {
167 	uae_u32 v;
168 	if (!sb->fdcallback)
169 		return 0;
170 	BSDTRACE((_T("FD_CALLBACK(%d,%d) "), fd, action));
171 	m68k_dreg (regs, 0) = fd;
172 	m68k_dreg (regs, 1) = action;
173 	v = CallFunc (context, sb->fdcallback);
174 	BSDTRACE((_T("-> %d\n"), v));
175 	return v;
176 }
177 
checksd(TrapContext * context,SB,int sd)178 bool checksd(TrapContext *context, SB, int sd)
179 {
180 	int iCounter;
181 	SOCKET s;
182 
183 	s = getsock(sb,sd);
184 	if (s != INVALID_SOCKET) {
185 		for (iCounter  = 1; iCounter <= sb->dtablesize; iCounter++) {
186 			if (iCounter != sd) {
187 				if (getsock(sb,iCounter) == s) {
188 					releasesock(context, sb, sd);
189 					return true;
190 				}
191 			}
192 		}
193 		for (iCounter  = 0; iCounter < SOCKPOOLSIZE; iCounter++) {
194 			if (s == sockdata->sockpoolsocks[iCounter])
195 				return true;
196 		}
197 	}
198 	BSDTRACE((_T("checksd FALSE s 0x%x sd %d\n"),s,sd));
199 	return false;
200 }
201 
setsd(TrapContext * context,SB,int sd,SOCKET_TYPE s)202 void setsd(TrapContext *context, SB, int sd, SOCKET_TYPE s)
203 {
204 	callfdcallback (context, sb, sd - 1, FDCB_ALLOC);
205 	sb->dtable[sd - 1] = s;
206 }
207 
208 /* Socket descriptor/opaque socket handle management */
getsd(TrapContext * context,SB,SOCKET_TYPE s)209 int getsd (TrapContext *context, SB, SOCKET_TYPE s)
210 {
211 	int i, fdcb;
212 	SOCKET_TYPE *dt = sb->dtable;
213 
214 	/* return socket descriptor if already exists */
215 	for (i = sb->dtablesize; i--;) {
216 		if (dt[i] == s)
217 			return i + 1;
218 	}
219 
220 	/* create new table entry */
221 	fdcb = 0;
222 	for (i = 0; i < sb->dtablesize; i++) {
223 		if (dt[i] == -1) {
224 			if (callfdcallback (context, sb, i, FDCB_CHECK)) {
225 				/* fd was allocated by link lib */
226 				dt[i] = -2;
227 				continue;
228 			}
229 			dt[i] = s;
230 			sb->ftable[i] = SF_BLOCKING;
231 			return i + 1;
232 		} else if (dt[i] == -2) {
233 			fdcb = 1;
234 		}
235 	}
236 	/* recheck callback allocated FDs */
237 	if (fdcb) {
238 		for (i = 0; i < sb->dtablesize; i++) {
239 			if (dt[i] == -2) {
240 				if (!callfdcallback (context, sb, i, FDCB_CHECK)) {
241 					dt[i] = s;
242 					sb->ftable[i] = SF_BLOCKING;
243 					return i + 1;
244 				}
245 			}
246 		}
247 	}
248 
249 	/* descriptor table full. */
250 	bsdsocklib_seterrno (sb, 24); /* EMFILE */
251 
252 	return -1;
253 }
254 
getsock(SB,int sd)255 SOCKET_TYPE getsock (SB, int sd)
256 {
257 	if ((unsigned int) (sd - 1) >= (unsigned int) sb->dtablesize) {
258 		BSDTRACE ((_T("Invalid Socket Descriptor (%d)\n"), sd));
259 		bsdsocklib_seterrno (sb, 38); /* ENOTSOCK */
260 		return -1;
261 	}
262 	if (sb->dtable[sd - 1] == INVALID_SOCKET) {
263 		struct socketbase *sb1, *nsb;
264 		uaecptr ot;
265 		if (!addr_valid (_T("getsock1"), sb->ownertask + 10, 4))
266 			return -1;
267 		ot = get_long (sb->ownertask + 10);
268 		if (!addr_valid (_T("getsock2"), ot, 1))
269 			return -1;
270 		// Fix for Newsrog (All Tasks of Newsrog using the same dtable)
271 		for (sb1 = socketbases; sb1; sb1 = nsb) {
272 			uaecptr ot1;
273 			if (!addr_valid (_T("getsock3"), sb1->ownertask + 10, 4))
274 				break;
275 			ot1 = get_long (sb1->ownertask + 10);
276 			if (!addr_valid (_T("getsock4"), ot1, 1))
277 				break;
278 			if (strcmp((char*)get_real_address (ot1), (char*)get_real_address (ot)) == 0) {
279 				// Task with same name already exists -> use same dtable
280 				if (sb1->dtable[sd - 1] != INVALID_SOCKET)
281 					return sb1->dtable[sd - 1];
282 			}
283 			nsb = sb1->next;
284 		}
285 	}
286 	return sb->dtable[sd - 1];
287 }
288 
releasesock(TrapContext * context,SB,int sd)289 void releasesock (TrapContext *context, SB, int sd)
290 {
291 	if ((unsigned int) (sd - 1) < (unsigned int) sb->dtablesize) {
292 		sb->dtable[sd - 1] = -1;
293 		callfdcallback (context, sb, sd - 1, FDCB_FREE);
294 	}
295 }
296 
297 /* Signal queue */
298 /* @@@ TODO: ensure proper interlocking */
299 #if 1
300 struct socketbase *sbsigqueue;
301 volatile int bsd_int_requested;
302 #endif
303 
addtosigqueue(SB,int events)304 void addtosigqueue (SB, int events)
305 {
306 	locksigqueue ();
307 
308 	if (events)
309 		sb->sigstosend |= sb->eventsigs;
310 	else
311 		sb->sigstosend |= ((uae_u32) 1) << sb->signal;
312 
313 	if (!sb->dosignal) {
314 		sb->nextsig = sbsigqueue;
315 		sbsigqueue = sb;
316 	}
317 	sb->dosignal = 1;
318 
319 	bsd_int_requested |= 1;
320 
321 	unlocksigqueue ();
322 }
323 
324 
bsdsock_fake_int_handler(void)325 void bsdsock_fake_int_handler(void)
326 {
327 	locksigqueue ();
328 
329 	bsd_int_requested = 0;
330 
331 	if (sbsigqueue != NULL) {
332 		SB;
333 
334 		for (sb = sbsigqueue; sb; sb = sb->nextsig) {
335 			if (sb->dosignal == 1) {
336 				uae_Signal (sb->ownertask, sb->sigstosend);
337 				sb->sigstosend = 0;
338 			}
339 			sb->dosignal = 0;
340 		}
341 
342 		sbsigqueue = NULL;
343 	}
344 
345 	unlocksigqueue ();
346 }
347 
waitsig(TrapContext * context,SB)348 void waitsig (TrapContext *context, SB)
349 {
350 	long sigs;
351 	m68k_dreg (regs, 0) = (((uae_u32) 1) << sb->signal) | sb->eintrsigs;
352 	if ((sigs = CallLib (context, sb->sysbase, -0x13e)) & sb->eintrsigs) { /* Wait */
353 		sockabort (sb);
354 		bsdsocklib_seterrno (sb, 4); /* EINTR */
355 
356 		// Set signal
357 		m68k_dreg (regs, 0) = sigs;
358 		m68k_dreg (regs, 1) = sb->eintrsigs;
359 		sigs = CallLib (context, sb->sysbase, -0x132); /* SetSignal() */
360 
361 		sb->eintr = 1;
362 	} else
363 		sb->eintr = 0;
364 }
365 
cancelsig(TrapContext * context,SB)366 void cancelsig (TrapContext *context, SB)
367 {
368 	locksigqueue ();
369 	if (sb->dosignal)
370 		sb->dosignal = 2;
371 	unlocksigqueue ();
372 
373 	m68k_dreg (regs, 0) = 0;
374 	m68k_dreg (regs, 1) = ((uae_u32) 1) << sb->signal;
375 	CallLib (context, sb->sysbase, -0x132); /* SetSignal() */
376 }
377 
378 /* Allocate and initialize per-task state structure */
alloc_socketbase(TrapContext * context)379 static struct socketbase *alloc_socketbase (TrapContext *context)
380 {
381 	SB;
382 	int i;
383 
384 	if ((sb = xcalloc (struct socketbase, 1)) != NULL) {
385 		sb->ownertask = gettask (context);
386 		sb->sysbase = get_long (4);
387 
388 		m68k_dreg (regs, 0) = -1;
389 		sb->signal = CallLib (context, sb->sysbase, -0x14A); /* AllocSignal */
390 
391 		if (sb->signal == -1) {
392 			write_log (_T("bsdsocket: ERROR: Couldn't allocate signal for task 0x%08x.\n"), sb->ownertask);
393 			free (sb);
394 			return NULL;
395 		}
396 		m68k_dreg (regs, 0) = SCRATCHBUFSIZE;
397 		m68k_dreg (regs, 1) = 0;
398 
399 		sb->dtablesize = DEFAULT_DTABLE_SIZE;
400 		/* @@@ check malloc() result */
401 		sb->dtable = (SOCKET*)malloc (sb->dtablesize * sizeof (*sb->dtable));
402 		sb->ftable = (int*)malloc (sb->dtablesize * sizeof (*sb->ftable));
403 
404 		for (i = sb->dtablesize; i--;)
405 			sb->dtable[i] = -1;
406 
407 		sb->eintrsigs = 0x1000; /* SIGBREAKF_CTRL_C */
408 
409 		sb->logfacility = 1 << 3; /* LOG_USER */
410 		sb->logmask = 0xff;
411 
412 		if (!host_sbinit (context, sb)) {
413 			/* @@@ free everything   */
414 		}
415 
416 		locksigqueue();
417 
418 		if (socketbases)
419 			sb->next = socketbases;
420 		socketbases = sb;
421 
422 		unlocksigqueue();
423 
424 		return sb;
425 	}
426 	return NULL;
427 }
428 
get_socketbase(TrapContext * context)429 STATIC_INLINE struct socketbase *get_socketbase (TrapContext *context)
430 {
431 	return (struct socketbase*)get_pointer (m68k_areg (regs, 6) + offsetof (struct UAEBSDBase, sb));
432 }
433 
free_socketbase(TrapContext * context)434 static void free_socketbase (TrapContext *context)
435 {
436 	struct socketbase *sb, *nsb;
437 
438 	if ((sb = get_socketbase (context)) != NULL) {
439 		m68k_dreg (regs, 0) = sb->signal;
440 		CallLib (context, sb->sysbase, -0x150); /* FreeSignal */
441 
442 		if (sb->hostent) {
443 			m68k_areg (regs, 1) = sb->hostent;
444 			m68k_dreg (regs, 0) = sb->hostentsize;
445 			CallLib (context, sb->sysbase, -0xD2); /* FreeMem */
446 
447 		}
448 		if (sb->protoent) {
449 			m68k_areg (regs, 1) = sb->protoent;
450 			m68k_dreg (regs, 0) = sb->protoentsize;
451 			CallLib (context, sb->sysbase, -0xD2); /* FreeMem */
452 
453 		}
454 		if (sb->servent) {
455 			m68k_areg (regs, 1) = sb->servent;
456 			m68k_dreg (regs, 0) = sb->serventsize;
457 			CallLib (context, sb->sysbase, -0xD2); /* FreeMem */
458 
459 		}
460 		host_sbcleanup (sb);
461 
462 		free (sb->dtable);
463 		free (sb->ftable);
464 
465 		locksigqueue ();
466 
467 		if (sb == socketbases)
468 			socketbases = sb->next;
469 		else {
470 			for (nsb = socketbases; nsb; nsb = nsb->next) {
471 				if (sb == nsb->next) {
472 					nsb->next = sb->next;
473 					break;
474 				}
475 			}
476 		}
477 
478 #if 1
479 		if (sb == sbsigqueue)
480 			sbsigqueue = sb->next;
481 		else {
482 			for (nsb = sbsigqueue; nsb; nsb = nsb->next) {
483 				if (sb == nsb->next) {
484 					nsb->next = sb->next;
485 					break;
486 				}
487 			}
488 		}
489 #endif
490 
491 		unlocksigqueue ();
492 
493 		free (sb);
494 	}
495 }
496 
bsdsocklib_Expunge(TrapContext * context)497 static uae_u32 REGPARAM2 bsdsocklib_Expunge (TrapContext *context)
498 {
499 	BSDTRACE ((_T("Expunge() -> [ignored]\n")));
500 	return 0;
501 }
502 
503 static uae_u32 functable, datatable, inittable;
504 
bsdsocklib_Open(TrapContext * context)505 static uae_u32 REGPARAM2 bsdsocklib_Open (TrapContext *context)
506 {
507 	uae_u32 result = 0;
508 	int opencount;
509 	SB;
510 
511 	BSDTRACE ((_T("OpenLibrary() -> ")));
512 
513 	if ((sb = alloc_socketbase (context)) != NULL) {
514 		put_word (SockLibBase + 32, opencount = get_word (SockLibBase + 32) + 1);
515 
516 		m68k_areg (regs, 0) = functable;
517 		m68k_areg (regs, 1) = datatable;
518 		m68k_areg (regs, 2) = 0;
519 		m68k_dreg (regs, 0) = sizeof (struct UAEBSDBase);
520 		m68k_dreg (regs, 1) = 0;
521 		result = CallLib (context, sb->sysbase, -0x54); /* MakeLibrary */
522 
523 		put_pointer (result + offsetof (struct UAEBSDBase, sb), sb);
524 
525 		BSDTRACE ((_T("%0x [%d]\n"), result, opencount));
526 	} else
527 		BSDTRACE ((_T("failed (out of memory)\n")));
528 
529 	return result;
530 }
531 
bsdsocklib_Close(TrapContext * context)532 static uae_u32 REGPARAM2 bsdsocklib_Close (TrapContext *context)
533 {
534 	int opencount;
535 
536 	uae_u32 base = m68k_areg (regs, 6);
537 	uae_u32 negsize = get_word (base + 16);
538 
539 	free_socketbase (context);
540 
541 	put_word (SockLibBase + 32, opencount = get_word (SockLibBase + 32) - 1);
542 
543 	m68k_areg (regs, 1) = base - negsize;
544 	m68k_dreg (regs, 0) = negsize + get_word (base + 18);
545 	CallLib (context, get_long (4), -0xD2); /* FreeMem */
546 
547 	BSDTRACE ((_T("CloseLibrary() -> [%d]\n"), opencount));
548 
549 	return 0;
550 }
551 
552 /* socket(domain, type, protocol)(d0/d1/d2) */
bsdsocklib_socket(TrapContext * context)553 static uae_u32 REGPARAM2 bsdsocklib_socket (TrapContext *context)
554 {
555 	struct socketbase *sb = get_socketbase (context);
556 	return host_socket (context, sb, m68k_dreg (regs, 0), m68k_dreg (regs, 1),
557 		m68k_dreg (regs, 2));
558 }
559 
560 /* bind(s, name, namelen)(d0/a0/d1) */
bsdsocklib_bind(TrapContext * context)561 static uae_u32 REGPARAM2 bsdsocklib_bind (TrapContext *context)
562 {
563 	struct socketbase *sb = get_socketbase (context);
564 	return host_bind (context, sb, m68k_dreg (regs, 0), m68k_areg (regs, 0),
565 		m68k_dreg (regs, 1));
566 }
567 
568 /* listen(s, backlog)(d0/d1) */
bsdsocklib_listen(TrapContext * context)569 static uae_u32 REGPARAM2 bsdsocklib_listen (TrapContext *context)
570 {
571 	struct socketbase *sb = get_socketbase (context);
572 	return host_listen (context, sb, m68k_dreg (regs, 0), m68k_dreg (regs, 1));
573 }
574 
575 /* accept(s, addr, addrlen)(d0/a0/a1) */
bsdsocklib_accept(TrapContext * context)576 static uae_u32 REGPARAM2 bsdsocklib_accept (TrapContext *context)
577 {
578 	struct socketbase *sb = get_socketbase (context);
579 	host_accept (context, sb, m68k_dreg (regs, 0), m68k_areg (regs, 0), m68k_areg (regs, 1));
580 	return sb->resultval;
581 }
582 
583 /* connect(s, name, namelen)(d0/a0/d1) */
bsdsocklib_connect(TrapContext * context)584 static uae_u32 REGPARAM2 bsdsocklib_connect (TrapContext *context)
585 {
586 	struct socketbase *sb = get_socketbase (context);
587 	host_connect (context, sb, m68k_dreg (regs, 0), m68k_areg (regs, 0), m68k_dreg (regs, 1));
588 	return sb->sb_errno ? -1 : 0;
589 }
590 
591 /* sendto(s, msg, len, flags, to, tolen)(d0/a0/d1/d2/a1/d3) */
bsdsocklib_sendto(TrapContext * context)592 static uae_u32 REGPARAM2 bsdsocklib_sendto (TrapContext *context)
593 {
594 	struct socketbase *sb = get_socketbase (context);
595 	host_sendto (context, sb, m68k_dreg (regs, 0), m68k_areg (regs, 0), m68k_dreg (regs, 1),
596 		m68k_dreg (regs, 2), m68k_areg (regs, 1), m68k_dreg (regs, 3));
597 	return sb->resultval;
598 }
599 
600 /* send(s, msg, len, flags)(d0/a0/d1/d2) */
bsdsocklib_send(TrapContext * context)601 static uae_u32 REGPARAM2 bsdsocklib_send (TrapContext *context)
602 {
603 	struct socketbase *sb = get_socketbase (context);
604 	host_sendto (context, sb, m68k_dreg (regs, 0), m68k_areg (regs, 0), m68k_dreg (regs, 1),
605 		m68k_dreg (regs, 2), 0, 0);
606 	return sb->resultval;
607 }
608 
609 /* recvfrom(s, buf, len, flags, from, fromlen)(d0/a0/d1/d2/a1/a2) */
bsdsocklib_recvfrom(TrapContext * context)610 static uae_u32 REGPARAM2 bsdsocklib_recvfrom (TrapContext *context)
611 {
612 	struct socketbase *sb = get_socketbase (context);
613 	host_recvfrom (context, sb, m68k_dreg (regs, 0), m68k_areg (regs, 0), m68k_dreg (regs, 1),
614 		m68k_dreg (regs, 2), m68k_areg (regs, 1), m68k_areg (regs, 2));
615 	return sb->resultval;
616 }
617 
618 /* recv(s, buf, len, flags)(d0/a0/d1/d2) */
bsdsocklib_recv(TrapContext * context)619 static uae_u32 REGPARAM2 bsdsocklib_recv (TrapContext *context)
620 {
621 	struct socketbase *sb = get_socketbase (context);
622 	host_recvfrom (context, sb, m68k_dreg (regs, 0), m68k_areg (regs, 0), m68k_dreg (regs, 1),
623 		m68k_dreg (regs, 2), 0, 0);
624 	return sb->resultval;
625 }
626 
627 /* shutdown(s, how)(d0/d1) */
bsdsocklib_shutdown(TrapContext * context)628 static uae_u32 REGPARAM2 bsdsocklib_shutdown (TrapContext *context)
629 {
630 	struct socketbase *sb = get_socketbase (context);
631 	return host_shutdown (sb, m68k_dreg (regs, 0), m68k_dreg (regs, 1));
632 }
633 
634 /* setsockopt(s, level, optname, optval, optlen)(d0/d1/d2/a0/d3) */
bsdsocklib_setsockopt(TrapContext * context)635 static uae_u32 REGPARAM2 bsdsocklib_setsockopt (TrapContext *context)
636 {
637 	struct socketbase *sb = get_socketbase (context);
638 	host_setsockopt (sb, m68k_dreg (regs, 0), m68k_dreg (regs, 1), m68k_dreg (regs, 2),
639 		m68k_areg (regs, 0), m68k_dreg (regs, 3));
640 	return sb->resultval;
641 }
642 
643 /* getsockopt(s, level, optname, optval, optlen)(d0/d1/d2/a0/a1) */
bsdsocklib_getsockopt(TrapContext * context)644 static uae_u32 REGPARAM2 bsdsocklib_getsockopt (TrapContext *context)
645 {
646 	struct socketbase *sb = get_socketbase (context);
647 	return host_getsockopt (sb, m68k_dreg (regs, 0), m68k_dreg (regs, 1), m68k_dreg (regs, 2),
648 		m68k_areg (regs, 0), m68k_areg (regs, 1));
649 }
650 
651 /* getsockname(s, hostname, namelen)(d0/a0/a1) */
bsdsocklib_getsockname(TrapContext * context)652 static uae_u32 REGPARAM2 bsdsocklib_getsockname (TrapContext *context)
653 {
654 	struct socketbase *sb = get_socketbase (context);
655 	return host_getsockname (sb, m68k_dreg (regs, 0), m68k_areg (regs, 0), m68k_areg (regs, 1));
656 }
657 
658 /* getpeername(s, hostname, namelen)(d0/a0/a1) */
bsdsocklib_getpeername(TrapContext * context)659 static uae_u32 REGPARAM2 bsdsocklib_getpeername (TrapContext *context)
660 {
661 	struct socketbase *sb = get_socketbase (context);
662 	return host_getpeername (sb, m68k_dreg (regs, 0), m68k_areg (regs, 0), m68k_areg (regs, 1));
663 }
664 
665 /* *------ generic system calls related to sockets */
666 /* IoctlSocket(d, request, argp)(d0/d1/a0) */
bsdsocklib_IoctlSocket(TrapContext * context)667 static uae_u32 REGPARAM2 bsdsocklib_IoctlSocket (TrapContext *context)
668 {
669 	struct socketbase *sb = get_socketbase (context);
670 	return host_IoctlSocket (context, sb, m68k_dreg (regs, 0), m68k_dreg (regs, 1), m68k_areg (regs, 0));
671 }
672 
673 /* *------ AmiTCP/IP specific stuff */
674 /* CloseSocket(d)(d0) */
bsdsocklib_CloseSocket(TrapContext * context)675 static uae_u32 REGPARAM2 bsdsocklib_CloseSocket (TrapContext *context)
676 {
677 	struct socketbase *sb = get_socketbase (context);
678 	return host_CloseSocket (context, sb, m68k_dreg (regs, 0));
679 }
680 
681 /* WaitSelect(nfds, readfds, writefds, execptfds, timeout, maskp)(d0/a0/a1/a2/a3/d1) */
bsdsocklib_WaitSelect(TrapContext * context)682 static uae_u32 REGPARAM2 bsdsocklib_WaitSelect (TrapContext *context)
683 {
684 	struct socketbase *sb = get_socketbase (context);
685 	host_WaitSelect (context, sb, m68k_dreg (regs, 0), m68k_areg (regs, 0), m68k_areg (regs, 1),
686 		m68k_areg (regs, 2), m68k_areg (regs, 3), m68k_dreg (regs, 1));
687 	return sb->resultval;
688 }
689 
690 /* SetSocketSignals(SIGINTR, SIGIO, SIGURG)(d0/d1/d2) */
bsdsocklib_SetSocketSignals(TrapContext * context)691 static uae_u32 REGPARAM2 bsdsocklib_SetSocketSignals (TrapContext *context)
692 {
693 	struct socketbase *sb = get_socketbase (context);
694 
695 	BSDTRACE ((_T("SetSocketSignals(0x%08x,0x%08x,0x%08x) -> "), m68k_dreg (regs, 0), m68k_dreg (regs, 1), m68k_dreg (regs, 2)));
696 	sb->eintrsigs = m68k_dreg (regs, 0);
697 	sb->eventsigs = m68k_dreg (regs, 1);
698 
699 	return 0;
700 }
701 
702 /* SetDTableSize(size)(d0) */
bsdsocklib_SetDTableSize(SB,int newSize)703 static uae_u32 bsdsocklib_SetDTableSize (SB, int newSize)
704 {
705 	int *newdtable;
706 	int *newftable;
707 	unsigned int *newmtable;
708 	int i;
709 
710 	if (newSize < sb->dtablesize) {
711 		/* I don't support lowering the size */
712 		return 0;
713 	}
714 
715 	newdtable = xcalloc (int, newSize);
716 	newftable = xcalloc (int, newSize);
717 	newmtable = xcalloc (unsigned int, newSize);
718 
719 	if (newdtable == NULL || newftable == NULL || newmtable == NULL) {
720 		sb->resultval = -1;
721 		bsdsocklib_seterrno(sb, ENOMEM);
722 		free (newdtable);
723 		free (newftable);
724 		free (newmtable);
725 		return -1;
726 	}
727 
728 	memcpy (newdtable, sb->dtable, sb->dtablesize * sizeof(*sb->dtable));
729 	memcpy (newftable, sb->ftable, sb->dtablesize * sizeof(*sb->ftable));
730 	memcpy (newmtable, sb->mtable, sb->dtablesize * sizeof(*sb->mtable));
731 	for (i = sb->dtablesize + 1; i < newSize; i++)
732 		newdtable[i] = -1;
733 
734 	sb->dtablesize = newSize;
735 	free(sb->dtable);
736 	free(sb->ftable);
737 	free(sb->mtable);
738 	sb->dtable = (SOCKET*)newdtable;
739 	sb->ftable = newftable;
740 	sb->mtable = newmtable;
741 	sb->resultval = 0;
742 	return 0;
743 }
744 
sockpoolindex(long id)745 static int sockpoolindex (long id)
746 {
747 	int i;
748 
749 	for (i = 0; i < SOCKPOOLSIZE; i++)
750 		if (sockdata->sockpoolids[i] == id)
751 			return i;
752 
753 	return -1;
754 }
755 
756 /* ObtainSocket(id, domain, type, protocol)(d0/d1/d2/d3) */
bsdsocklib_ObtainSocket(TrapContext * context)757 static uae_u32 REGPARAM2 bsdsocklib_ObtainSocket (TrapContext *context)
758 {
759 	struct socketbase *sb = get_socketbase (context);
760 	int sd;
761 	int id;
762 	SOCKET_TYPE s;
763 	int i;
764 
765 	id = m68k_dreg (regs, 0);
766 
767 	BSDTRACE ((_T("ObtainSocket(%d,%d,%d,%d) -> "), id, m68k_dreg (regs, 1), m68k_dreg (regs, 2), m68k_dreg (regs, 3)));
768 
769 	i = sockpoolindex (id);
770 
771 	if (i == -1) {
772 		BSDTRACE ((_T("[invalid key]\n")));
773 		return -1;
774 	}
775 	s = sockdata->sockpoolsocks[i];
776 
777 	sd = getsd (context, sb, s);
778 
779 	BSDTRACE ((_T(" -> Socket=%d\n"), sd));
780 
781 	if (sd != -1) {
782 		sb->ftable[sd - 1] = sockdata->sockpoolflags[i];
783 		callfdcallback (context, sb, sd - 1, FDCB_ALLOC);
784 		sockdata->sockpoolids[i] = UNIQUE_ID;
785 		return sd - 1;
786 	}
787 
788 	return -1;
789 }
790 
791 /* ReleaseSocket(fd, id)(d0/d1) */
bsdsocklib_ReleaseSocket(TrapContext * context)792 static uae_u32 REGPARAM2 bsdsocklib_ReleaseSocket (TrapContext *context)
793 {
794 	struct socketbase *sb = get_socketbase (context);
795 	int sd;
796 	int id;
797 	SOCKET_TYPE s;
798 	int i;
799 	uae_u32 flags;
800 
801 	sd = m68k_dreg (regs, 0);
802 	id = m68k_dreg (regs, 1);
803 
804 	sd++;
805 	BSDTRACE ((_T("ReleaseSocket(%d,%d) -> "), sd, id));
806 
807 	s = getsock (sb, sd);
808 
809 	if (s != -1) {
810 		flags = sb->ftable[sd - 1];
811 
812 		if (flags & REP_ALL) {
813 			write_log (_T("bsdsocket: ERROR: ReleaseSocket() is not supported for sockets with async event notification enabled!\n"));
814 			return -1;
815 		}
816 		releasesock (context, sb, sd);
817 
818 		if (id == UNIQUE_ID) {
819 			for (;;) {
820 				if (sockpoolindex (curruniqid) == -1)
821 					break;
822 				curruniqid += 129;
823 				if ((unsigned long) (curruniqid + 1) < 65536)
824 					curruniqid += 65537;
825 			}
826 
827 			id = curruniqid;
828 		} else if (id < 0 && id > 65535) {
829 			if (sockpoolindex (id) != -1) {
830 				BSDTRACE ((_T("[unique ID already exists]\n")));
831 				return -1;
832 			}
833 		}
834 		i = sockpoolindex (-1);
835 
836 		if (i == -1) {
837 			BSDTRACE ((_T("-1\n")));
838 			write_log (_T("bsdsocket: ERROR: Global socket pool overflow\n"));
839 			return -1;
840 		}
841 		sockdata->sockpoolids[i] = id;
842 		sockdata->sockpoolsocks[i] = s;
843 		sockdata->sockpoolflags[i] = flags;
844 
845 		BSDTRACE ((_T("id %d s 0x%x\n"), id,s));
846 	} else {
847 		BSDTRACE ((_T("[invalid socket descriptor]\n")));
848 		return -1;
849 	}
850 
851 	return id;
852 }
853 
854 /* ReleaseCopyOfSocket(fd, id)(d0/d1) */
bsdsocklib_ReleaseCopyOfSocket(TrapContext * context)855 static uae_u32 REGPARAM2 bsdsocklib_ReleaseCopyOfSocket (TrapContext *context)
856 {
857 	struct socketbase *sb = get_socketbase (context);
858 	int sd;
859 	int id;
860 	SOCKET_TYPE s;
861 	int i;
862 	uae_u32 flags;
863 
864 	sd = m68k_dreg (regs, 0);
865 	id = m68k_dreg (regs, 1);
866 
867 	sd++;
868 	BSDTRACE ((_T("ReleaseSocket(%d,%d) -> "), sd, id));
869 
870 	s = getsock (sb, sd);
871 
872 	if (s != -1) {
873 		flags = sb->ftable[sd - 1];
874 
875 		if (flags & REP_ALL) {
876 			write_log (_T("bsdsocket: ERROR: ReleaseCopyOfSocket() is not supported for sockets with async event notification enabled!\n"));
877 			return -1;
878 		}
879 		if (id == UNIQUE_ID) {
880 			for (;;) {
881 				if (sockpoolindex (curruniqid) == -1)
882 					break;
883 				curruniqid += 129;
884 				if ((unsigned long) (curruniqid + 1) < 65536)
885 					curruniqid += 65537;
886 			}
887 			id = curruniqid;
888 		} else if (id < 0 && id > 65535) {
889 			if (sockpoolindex (id) != -1) {
890 				BSDTRACE ((_T("[unique ID already exists]\n")));
891 				return -1;
892 			}
893 		}
894 		i = sockpoolindex (-1);
895 
896 		if (i == -1) {
897 			BSDTRACE ((_T("-1\n")));
898 			write_log (_T("bsdsocket: ERROR: Global socket pool overflow\n"));
899 			return -1;
900 		}
901 		sockdata->sockpoolids[i] = id;
902 		sockdata->sockpoolsocks[i] = s;
903 		sockdata->sockpoolflags[i] = flags;
904 
905 		BSDTRACE ((_T("id %d s 0x%x\n"), id,s));
906 
907 	} else {
908 
909 		BSDTRACE ((_T("[invalid socket descriptor]\n")));
910 		return -1;
911 	}
912 
913 	return id;
914 }
915 
916 /* Errno()() */
bsdsocklib_Errno(TrapContext * context)917 static uae_u32 REGPARAM2 bsdsocklib_Errno (TrapContext *context)
918 {
919 	struct socketbase *sb = get_socketbase (context);
920 	BSDTRACE ((_T("Errno() -> %d\n"), sb->sb_errno));
921 	return sb->sb_errno;
922 }
923 
924 /* SetErrnoPtr(errno_p, size)(a0/d0) */
bsdsocklib_SetErrnoPtr(TrapContext * context)925 static uae_u32 REGPARAM2 bsdsocklib_SetErrnoPtr (TrapContext *context)
926 {
927 	struct socketbase *sb = get_socketbase (context);
928 	uae_u32 errnoptr = m68k_areg (regs, 0), size = m68k_dreg (regs, 0);
929 
930 	BSDTRACE ((_T("SetErrnoPtr(0x%08x,%d) -> "), errnoptr, size));
931 
932 	if (size == 1 || size == 2 || size == 4) {
933 		sb->errnoptr = errnoptr;
934 		sb->errnosize = size;
935 		BSDTRACE ((_T("OK\n")));
936 		return 0;
937 	}
938 	bsdsocklib_seterrno (sb, 22); /* EINVAL */
939 
940 	return -1;
941 }
942 
943 /* *------ inet library calls related to inet address manipulation */
944 /* Inet_NtoA(in)(d0) */
bsdsocklib_Inet_NtoA(TrapContext * context)945 static uae_u32 REGPARAM2 bsdsocklib_Inet_NtoA (TrapContext *context)
946 {
947 	struct socketbase *sb = get_socketbase (context);
948 	return host_Inet_NtoA (context, sb, m68k_dreg (regs, 0));
949 }
950 
951 /* inet_addr(cp)(a0) */
bsdsocklib_inet_addr(TrapContext * context)952 static uae_u32 REGPARAM2 bsdsocklib_inet_addr (TrapContext *context)
953 {
954 	return host_inet_addr (m68k_areg (regs, 0));
955 }
956 
957 /* Inet_LnaOf(in)(d0) */
bsdsocklib_Inet_LnaOf(TrapContext * context)958 static uae_u32 REGPARAM2 bsdsocklib_Inet_LnaOf (TrapContext *context)
959 {
960 	write_log (_T("bsdsocket: UNSUPPORTED: Inet_LnaOf()\n"));
961 	return 0;
962 }
963 
964 /* Inet_NetOf(in)(d0) */
bsdsocklib_Inet_NetOf(TrapContext * context)965 static uae_u32 REGPARAM2 bsdsocklib_Inet_NetOf (TrapContext *context)
966 {
967 	write_log (_T("bsdsocket: UNSUPPORTED: Inet_NetOf()\n"));
968 	return 0;
969 }
970 
971 /* Inet_MakeAddr(net, host)(d0/d1) */
bsdsocklib_Inet_MakeAddr(TrapContext * context)972 static uae_u32 REGPARAM2 bsdsocklib_Inet_MakeAddr (TrapContext *context)
973 {
974 	write_log (_T("bsdsocket: UNSUPPORTED: Inet_MakeAddr()\n"));
975 	return 0;
976 }
977 
978 /* inet_network(cp)(a0) */
bsdsocklib_inet_network(TrapContext * context)979 static uae_u32 REGPARAM2 bsdsocklib_inet_network (TrapContext *context)
980 {
981 	return host_inet_addr (m68k_areg (regs, 0));
982 }
983 
984 /* *------ gethostbyname etc */
985 /* gethostbyname(name)(a0) */
bsdsocklib_gethostbyname(TrapContext * context)986 static uae_u32 REGPARAM2 bsdsocklib_gethostbyname (TrapContext *context)
987 {
988 	struct socketbase *sb = get_socketbase (context);
989 	host_gethostbynameaddr (context, sb, m68k_areg (regs, 0), 0, -1);
990 	return sb->sb_herrno ? 0 : sb->hostent;
991 }
992 
993 /* gethostbyaddr(addr, len, type)(a0/d0/d1) */
bsdsocklib_gethostbyaddr(TrapContext * context)994 static uae_u32 REGPARAM2 bsdsocklib_gethostbyaddr (TrapContext *context)
995 {
996 	struct socketbase *sb = get_socketbase (context);
997 	host_gethostbynameaddr (context, sb, m68k_areg (regs, 0), m68k_dreg (regs, 0), m68k_dreg (regs, 1));
998 	return sb->sb_herrno ? 0 : sb->hostent;
999 }
1000 
1001 /* getnetbyname(name)(a0) */
bsdsocklib_getnetbyname(TrapContext * context)1002 static uae_u32 REGPARAM2 bsdsocklib_getnetbyname (TrapContext *context)
1003 {
1004 	write_log (_T("bsdsocket: UNSUPPORTED: getnetbyname()\n"));
1005 	return 0;
1006 }
1007 
1008 /* getnetbyaddr(net, type)(d0/d1) */
bsdsocklib_getnetbyaddr(TrapContext * context)1009 static uae_u32 REGPARAM2 bsdsocklib_getnetbyaddr (TrapContext *context)
1010 {
1011 	write_log (_T("bsdsocket: UNSUPPORTED: getnetbyaddr()\n"));
1012 	return 0;
1013 }
1014 
1015 /* getservbyname(name, proto)(a0/a1) */
bsdsocklib_getservbyname(TrapContext * context)1016 static uae_u32 REGPARAM2 bsdsocklib_getservbyname (TrapContext *context)
1017 {
1018 	struct socketbase *sb = get_socketbase (context);
1019 	host_getservbynameport (context, sb, m68k_areg (regs, 0), m68k_areg (regs, 1), 0);
1020 	return sb->sb_errno ? 0 : sb->servent;
1021 }
1022 
1023 /* getservbyport(port, proto)(d0/a0) */
bsdsocklib_getservbyport(TrapContext * context)1024 static uae_u32 REGPARAM2 bsdsocklib_getservbyport (TrapContext *context)
1025 {
1026 	struct socketbase *sb = get_socketbase (context);
1027 	host_getservbynameport (context, sb, m68k_dreg (regs, 0), m68k_areg (regs, 0), 1);
1028 	return sb->sb_errno ? 0 : sb->servent;
1029 }
1030 
1031 /* getprotobyname(name)(a0) */
bsdsocklib_getprotobyname(TrapContext * context)1032 static uae_u32 REGPARAM2 bsdsocklib_getprotobyname (TrapContext *context)
1033 {
1034 	struct socketbase *sb = get_socketbase (context);
1035 	host_getprotobyname (context, sb, m68k_areg (regs, 0));
1036 	return sb->sb_errno ? 0 : sb->protoent;
1037 }
1038 
1039 /* getprotobynumber(proto)(d0)  */
bsdsocklib_getprotobynumber(TrapContext * context)1040 static uae_u32 REGPARAM2 bsdsocklib_getprotobynumber (TrapContext *context)
1041 {
1042 	struct socketbase *sb = get_socketbase (context);
1043 	host_getprotobynumber (context, sb, m68k_dreg (regs, 0));
1044 	return sb->sb_errno ? 0 : sb->protoent;
1045 }
1046 
1047 /* *------ AmiTCP/IP 1.1 extensions */
1048 /* Dup2Socket(fd1, fd2)(d0/d1) */
bsdsocklib_Dup2Socket(TrapContext * context)1049 static uae_u32 REGPARAM2 bsdsocklib_Dup2Socket (TrapContext *context)
1050 {
1051 	struct socketbase *sb = get_socketbase (context);
1052 	return host_dup2socket (context, sb, m68k_dreg (regs, 0), m68k_dreg (regs, 1));
1053 }
1054 
bsdsocklib_sendmsg(TrapContext * context)1055 static uae_u32 REGPARAM2 bsdsocklib_sendmsg (TrapContext *context)
1056 {
1057 	write_log (_T("bsdsocket: UNSUPPORTED: sendmsg()\n"));
1058 	return 0;
1059 }
1060 
bsdsocklib_recvmsg(TrapContext * context)1061 static uae_u32 REGPARAM2 bsdsocklib_recvmsg (TrapContext *context)
1062 {
1063 	write_log (_T("bsdsocket: UNSUPPORTED: recvmsg()\n"));
1064 	return 0;
1065 }
1066 
bsdsocklib_gethostname(TrapContext * context)1067 static uae_u32 REGPARAM2 bsdsocklib_gethostname (TrapContext *context)
1068 {
1069 	return host_gethostname (m68k_areg (regs, 0), m68k_dreg (regs, 0));
1070 }
1071 
bsdsocklib_gethostid(TrapContext * context)1072 static uae_u32 REGPARAM2 bsdsocklib_gethostid (TrapContext *context)
1073 {
1074 	write_log (_T("bsdsocket: WARNING: Process '%s' calls deprecated function gethostid() - returning 127.0.0.1\n"),
1075 		get_real_address (get_long (gettask (context) + 10)));
1076 	return 0x7f000001;
1077 }
1078 
1079 static const TCHAR *errortexts[] =
1080 {_T("No error"), _T("Operation not permitted"), _T("No such file or directory"),
1081 _T("No such process"), _T("Interrupted system call"), _T("Input/output error"), _T("Device not configured"),
1082 _T("Argument list too long"), _T("Exec format error"), _T("Bad file descriptor"), _T("No child processes"),
1083 _T("Resource deadlock avoided"), _T("Cannot allocate memory"), _T("Permission denied"), _T("Bad address"),
1084 _T("Block device required"), _T("Device busy"), _T("Object exists"), _T("Cross-device link"),
1085 _T("Operation not supported by device"), _T("Not a directory"), _T("Is a directory"), _T("Invalid argument"),
1086 _T("Too many open files in system"), _T("Too many open files"), _T("Inappropriate ioctl for device"),
1087 _T("Text file busy"), _T("File too large"), _T("No space left on device"), _T("Illegal seek"),
1088 _T("Read-only file system"), _T("Too many links"), _T("Broken pipe"), _T("Numerical argument out of domain"),
1089 _T("Result too large"), _T("Resource temporarily unavailable"), _T("Operation now in progress"),
1090 _T("Operation already in progress"), _T("Socket operation on non-socket"), _T("Destination address required"),
1091 _T("Message too long"), _T("Protocol wrong type for socket"), _T("Protocol not available"),
1092 _T("Protocol not supported"), _T("Socket type not supported"), _T("Operation not supported"),
1093 _T("Protocol family not supported"), _T("Address family not supported by protocol family"),
1094 _T("Address already in use"), _T("Can't assign requested address"), _T("Network is down"),
1095 _T("Network is unreachable"), _T("Network dropped connection on reset"), _T("Software caused connection abort"),
1096 _T("Connection reset by peer"), _T("No buffer space available"), _T("Socket is already connected"),
1097 _T("Socket is not connected"), _T("Can't send after socket shutdown"), _T("Too many references: can't splice"),
1098 _T("Connection timed out"), _T("Connection refused"), _T("Too many levels of symbolic links"),
1099 _T("File name too long"), _T("Host is down"), _T("No route to host"), _T("Directory not empty"),
1100 _T("Too many processes"), _T("Too many users"), _T("Disc quota exceeded"), _T("Stale NFS file handle"),
1101 _T("Too many levels of remote in path"), _T("RPC struct is bad"), _T("RPC version wrong"),
1102 _T("RPC prog. not avail"), _T("Program version wrong"), _T("Bad procedure for program"), _T("No locks available"),
1103 _T("Function not implemented"), _T("Inappropriate file type or format"), _T("PError 0")};
1104 
1105 static uae_u32 errnotextptrs[sizeof (errortexts) / sizeof (*errortexts)];
1106 static const uae_u32 number_sys_error = sizeof (errortexts) / sizeof (*errortexts);
1107 
1108 
1109 /* *------ syslog functions */
1110 /* Syslog(level, format, ap)(d0/a0/a1) */
bsdsocklib_vsyslog(TrapContext * context)1111 static uae_u32 REGPARAM2 bsdsocklib_vsyslog (TrapContext *context)
1112 {
1113 #if 0
1114 	struct socketbase *sb = get_socketbase (context);
1115 	uae_char format_dst[512];
1116 	char out[256];
1117 	TCHAR *s;
1118 	uae_u8 paramtable[32 * 4];
1119 	int paramcnt, len;
1120 	uae_char *found = NULL;
1121 
1122 	uae_u32 level = m68k_dreg (regs, 0);
1123 	uaecptr format = m68k_areg (regs, 0);
1124 	uaecptr params = m68k_areg (regs, 1);
1125 
1126 	strcpyah_safe (format_dst, format, sizeof format_dst);
1127 
1128 	((uae_u8**)paramtable)[0] = (uae_u8*)format_dst;
1129 	paramcnt = 4;
1130 	for (int i = 0; format_dst[i]; i++) {
1131 		if (format_dst[i] == '%') {
1132 			if (found)
1133 				found = NULL;
1134 			else
1135 				found = &format_dst[i];
1136 			len = 4;
1137 		} else if (found) {
1138 			char c = toupper (format_dst[i]);
1139 			if (c < 'A' || c > 'Z')
1140 				continue;
1141 			if (c == 'H') {
1142 				len = 2;
1143 				continue;
1144 			}
1145 			if (c == 'M') {
1146 				int err = sb->sb_errno;
1147 				if (sb->sb_errno < 0 || sb->sb_errno >= sizeof (errortexts) / sizeof (*errortexts))
1148 					err = sizeof (errortexts) / sizeof (*errortexts) - 1;
1149 				int errlen = _tcslen (errortexts[err]) - (&format_dst[i] - found);
1150 				memmove (&format_dst[i] + errlen, &format_dst[i] + 1, strlen (&format_dst[i] + 1) + 1);
1151 				ua_copy (found, sizeof format_dst, errortexts[err]);
1152 				i += errlen - 1;
1153 				continue;
1154 			}
1155 
1156 			if (c == 'P' || c == 'S' || c == 'N') {
1157 				uaecptr pt = get_long (params);
1158 				if (!valid_address (pt, 2))
1159 					goto end;
1160 				((uae_u8**)(paramtable + paramcnt))[0] = get_real_address (pt);
1161 				params += 4;
1162 				paramcnt += sizeof (uae_u8*);
1163 			} else {
1164 				if (len == 2)
1165 					((uae_u16*)(paramtable + paramcnt))[0] = get_word (params);
1166 				else
1167 					((uae_u32*)(paramtable + paramcnt))[0] = get_long (params);
1168 				params += len;
1169 				paramcnt += len;
1170 			}
1171 			found = NULL;
1172 		}
1173 	}
1174 
1175 	va_list parms;
1176 	va_start (parms, paramtable);
1177 	_vsnprintf (out, sizeof out, format_dst, parms);
1178 	va_end (parms);
1179 
1180 	s = au (out);
1181 	write_log (_T("SYSLOG: %s\n"), s);
1182 	xfree (s);
1183 
1184 end:
1185 #endif
1186 	return 0;
1187 }
1188 
1189 static const TCHAR *herrortexts[] =
1190 {_T("No error"), _T("Unknown host"), _T("Host name lookup failure"), _T("Unknown server error"),
1191 _T("No address associated with name")};
1192 
1193 static uae_u32 herrnotextptrs[sizeof (herrortexts) / sizeof (*herrortexts)];
1194 static const uae_u32 number_host_error = sizeof (herrortexts) / sizeof (*herrortexts);
1195 
1196 
1197 static const TCHAR *sana2io_errlist[] =
1198 {
1199   _T("No error"),				/* S2ERR_NO_ERROR */
1200   _T("Resource allocation failure"),	/* S2ERR_NO_RESOURCES */
1201   _T("Unknown error code (2)"),
1202   _T("Invalid argument"),			/* S2ERR_BAD_ARGUMENT */
1203   _T("Inappropriate state"),		/* S2ERR_BAD_STATE */
1204   _T("Invalid address"),			/* S2ERR_BAD_ADDRESS */
1205   _T("Requested packet too large"),		/* S2ERR_MTU_EXCEEDED */
1206   _T("Unknown error (7)"),
1207   _T("Command is not supporter"),		/* S2ERR_NOT_SUPPORTED */
1208   _T("Driver software error detected"),	/* S2ERR_SOFTWARE */
1209   _T("Device driver is offline"),		/* S2ERR_OUTOFSERVICE */
1210   _T("Transmission attempt failed")		/* S2ERR_TX_FAILURE */
1211 };
1212 
1213 static uae_u32 sana2iotextptrs[sizeof (sana2io_errlist) / sizeof (*sana2io_errlist)];
1214 static const uae_u32 number_sana2io_error = sizeof (sana2io_errlist) / sizeof (*sana2io_errlist);
1215 
1216 
1217 static const TCHAR *sana2wire_errlist[] =
1218 {
1219   _T("Generic error: 0"),                   /* S2WERR_GENERIC_ERROR */
1220   _T("Unit not configured"),		/* S2WERR_NOT_CONFIGURED */
1221   _T("Unit is currently online"),		/* S2WERR_UNIT_ONLINE */
1222   _T("Unit is currently offline"),		/* S2WERR_UNIT_OFFLINE */
1223   _T("Protocol already tracked"),		/* S2WERR_ALREADY_TRACKED */
1224   _T("Protocol not tracked"),		/* S2WERR_NOT_TRACKED */
1225   _T("Buff management function error"),	/* S2WERR_BUFF_ERROR */
1226   _T("Source address error"),		/* S2WERR_SRC_ADDRESS */
1227   _T("Destination address error"),		/* S2WERR_DST_ADDRESS */
1228   _T("Broadcast address error"),		/* S2WERR_BAD_BROADCAST */
1229   _T("Multicast address error"),		/* S2WERR_BAD_MULTICAST */
1230   _T("Multicast address list full"),	/* S2WERR_MULTICAST_FULL */
1231   _T("Unsupported event class"),		/* S2WERR_BAD_EVENT */
1232   _T("Statdata failed sanity check"),	/* S2WERR_BAD_STATDATA */
1233   _T("Unknown wire error (14)"),
1234   _T("Attempt to config twice"),		/* S2WERR_IS_CONFIGURED */
1235   _T("Null pointer detected"),		/* S2WERR_NULL_POINTER */
1236   _T("tx failed - too many retries"),	/* S2WERR_TOO_MANY_RETIRES */
1237   _T("Driver fixable HW error")		/* S2WERR_RCVREL_HDW_ERR */
1238 };
1239 
1240 static uae_u32 sana2wiretextptrs[sizeof (sana2wire_errlist) / sizeof (*sana2wire_errlist)];
1241 static const uae_u32 number_sana2wire_error = sizeof (sana2wire_errlist) / sizeof (*sana2wire_errlist);
1242 
1243 
1244 static const TCHAR *io_errlist[] =
1245 {
1246   _T("Unknown error"),			/* 0 */
1247   _T("Device or unit failed to open"),	/* IOERR_OPENFAIL */
1248   _T("Request aborted"),			/* IOERR_ABORTED */
1249   _T("Command not supported by device"),	/* IOERR_NOCMD */
1250   _T("Invalid length"),			/* IOERR_BADLENGTH */
1251   _T("Invalid address"),			/* IOERR_BADADDRESS */
1252   _T("Requested unit is busy"),		/* IOERR_UNITBUSY */
1253   _T("Hardware self-test failed")		/* IOERR_SELFTEST */
1254 };
1255 
1256 static uae_u32 iotextptrs[sizeof (io_errlist) / sizeof (*io_errlist)];
1257 static const uae_u32 number_io_error = sizeof (io_errlist) / sizeof (*io_errlist);
1258 
1259 
1260 static const TCHAR * const strErr = _T("Errlist lookup error");
1261 static uae_u32 strErrptr;
1262 
1263 
1264 #define TAG_DONE   (0L)		/* terminates array of TagItems. ti_Data unused */
1265 #define TAG_IGNORE (1L)		/* ignore this item, not end of array */
1266 #define TAG_MORE   (2L)		/* ti_Data is pointer to another array of TagItems */
1267 #define TAG_SKIP   (3L)		/* skip this and the next ti_Data items */
1268 #define TAG_USER   ((uae_u32)(1L << 31))
1269 
1270 #define SBTF_VAL 0x0000
1271 #define SBTF_REF 0x8000
1272 #define SBTB_CODE 1
1273 #define SBTS_CODE 0x3FFF
1274 #define SBTM_CODE(tag) ((((UWORD)(tag)) >> SBTB_CODE) & SBTS_CODE)
1275 #define SBTF_GET  0x0
1276 #define SBTF_SET  0x1
1277 #define SBTM_GETREF(code) \
1278 	(TAG_USER | SBTF_REF | (((code) & SBTS_CODE) << SBTB_CODE))
1279 #define SBTM_GETVAL(code) (TAG_USER | (((code) & SBTS_CODE) << SBTB_CODE))
1280 #define SBTM_SETREF(code) \
1281 	(TAG_USER | SBTF_REF | (((code) & SBTS_CODE) << SBTB_CODE) | SBTF_SET)
1282 #define SBTM_SETVAL(code) \
1283 	(TAG_USER | (((code) & SBTS_CODE) << SBTB_CODE) | SBTF_SET)
1284 #define SBTC_BREAKMASK	    1
1285 #define SBTC_SIGIOMASK	    2
1286 #define SBTC_SIGURGMASK	    3
1287 #define SBTC_SIGEVENTMASK   4
1288 #define SBTC_ERRNO	    6
1289 #define SBTC_HERRNO	    7
1290 #define SBTC_DTABLESIZE	    8
1291 #define SBTC_FDCALLBACK	    9
1292 #define SBTC_LOGSTAT	    10
1293 #define SBTC_LOGTAGPTR	    11
1294 #define SBTC_LOGFACILITY    12
1295 #define SBTC_LOGMASK	    13
1296 #define SBTC_ERRNOSTRPTR    14 /* <sys/errno.h> */
1297 #define SBTC_HERRNOSTRPTR   15 /* <netdb.h> */
1298 #define SBTC_IOERRNOSTRPTR  16 /* <exec/errors.h> */
1299 #define SBTC_S2ERRNOSTRPTR  17 /* <devices/sana2.h> */
1300 #define SBTC_S2WERRNOSTRPTR 18 /* <devices/sana2.h> */
1301 #define SBTC_ERRNOBYTEPTR   21
1302 #define SBTC_ERRNOWORDPTR   22
1303 #define SBTC_ERRNOLONGPTR   24
1304 #define SBTC_HERRNOLONGPTR  25
1305 #define SBTC_RELEASESTRPTR  29
1306 
1307 #define LOG_FACMASK     0x03f8
1308 
tagcopy(uae_u32 currtag,uae_u32 currval,uae_u32 tagptr,uae_u32 * ptr)1309 static void tagcopy (uae_u32 currtag, uae_u32 currval, uae_u32 tagptr, uae_u32 * ptr)
1310 {
1311 	switch (currtag & 0x8001)
1312 	{
1313 		case 0x0000:	/* SBTM_GETVAL */
1314 		put_long (tagptr + 4, ptr ? *ptr : 0);
1315 		break;
1316 		case 0x8000:	/* SBTM_GETREF */
1317 		put_long (currval, ptr ? *ptr : 0);
1318 		break;
1319 		case 0x0001:	/* SBTM_SETVAL */
1320 		if (ptr)
1321 			*ptr = currval;
1322 		break;
1323 		default:		/* SBTM_SETREF */
1324 		if (ptr)
1325 			*ptr = get_long (currval);
1326 		break;
1327 	}
1328 }
1329 
bsdsocklib_SocketBaseTagList(TrapContext * context)1330 static uae_u32 REGPARAM2 bsdsocklib_SocketBaseTagList (TrapContext *context)
1331 {
1332 	struct socketbase *sb = get_socketbase (context);
1333 	uae_u32 tagptr = m68k_areg (regs, 0);
1334 	uae_u32 tagsprocessed = 0;
1335 	uae_u32 currtag;
1336 	uae_u32 currval;
1337 
1338 	BSDTRACE ((_T("SocketBaseTagList(")));
1339 
1340 	for (;;) {
1341 		currtag = get_long (tagptr);
1342 		currval = get_long (tagptr + 4);
1343 		tagsprocessed++;
1344 
1345 		if (!(currtag & TAG_USER)) {
1346 
1347 			switch (currtag)
1348 			{
1349 				case TAG_DONE:
1350 					BSDTRACE ((_T("TAG_DONE")));
1351 					tagsprocessed = 0;
1352 					goto done;
1353 				case TAG_IGNORE:
1354 					BSDTRACE ((_T("TAG_IGNORE")));
1355 					break;
1356 				case TAG_MORE:
1357 					BSDTRACE ((_T("TAG_MORE(0x%x)"), currval));
1358 					tagptr = currval;
1359 					break;
1360 				case TAG_SKIP:
1361 					BSDTRACE ((_T("TAG_SKIP(%d)"), currval));
1362 					tagptr += currval * 8;
1363 					break;
1364 				default:
1365 					write_log (_T("bsdsocket: WARNING: Unsupported tag type (%08x) in SocketBaseTagList(%x)\n"),
1366 						currtag, m68k_areg (regs, 0));
1367 					goto done;
1368 			}
1369 
1370 		} else {
1371 
1372 			BSDTRACE ((_T("SBTM_")));
1373 			BSDTRACE ((currtag & 0x0001 ? _T("SET") : _T("GET")));
1374 			BSDTRACE ((currtag & 0x8000 ? _T("REF(") : _T("VAL(")));
1375 
1376 			switch ((currtag >> 1) & SBTS_CODE)
1377 			{
1378 				case SBTC_BREAKMASK:
1379 					BSDTRACE ((_T("SBTC_BREAKMASK),0x%x,0x%x"), currval, sb->eintrsigs));
1380 					tagcopy (currtag, currval, tagptr, &sb->eintrsigs);
1381 					break;
1382 				case SBTC_SIGIOMASK:
1383 					BSDTRACE ((_T("SBTC_SIGIOMASK),0x%x,0x%x"), currval, sb->eventsigs));
1384 					tagcopy (currtag, currval, tagptr, &sb->eventsigs);
1385 					break;
1386 				case SBTC_SIGURGMASK:
1387 					BSDTRACE ((_T("SBTC_SIGURGMASK),0x%x"), currval));
1388 					break;
1389 				case SBTC_SIGEVENTMASK:
1390 					BSDTRACE ((_T("SBTC_SIGEVENTMASK),0x%x,0x%x"), currval, sb->eventsigs));
1391 					tagcopy (currtag, currval, tagptr, &sb->eventsigs);
1392 					break;
1393 				case SBTC_ERRNO:
1394 					BSDTRACE ((_T("SBTC_ERRNO),%x,%d"), currval, sb->sb_errno));
1395 					tagcopy (currtag, currval, tagptr, (uae_u32*)&sb->sb_errno);
1396 					break;
1397 				case SBTC_HERRNO:
1398 					BSDTRACE ((_T("SBTC_HERRNO),%x,%d"), currval, sb->sb_herrno));
1399 					tagcopy (currtag, currval, tagptr, (uae_u32*)&sb->sb_herrno);
1400 					break;
1401 				case SBTC_DTABLESIZE:
1402 					BSDTRACE ((_T("SBTC_DTABLESIZE),0x%x"), currval));
1403 					if (currtag & 1) {
1404 						bsdsocklib_SetDTableSize(sb, currval);
1405 					} else {
1406 						put_long (tagptr + 4, sb->dtablesize);
1407 					}
1408 					break;
1409 
1410 				case SBTC_FDCALLBACK:
1411 					BSDTRACE ((_T("SBTC_FDCALLBACK),%08x"), currval));
1412 					tagcopy (currtag, currval, tagptr, &sb->fdcallback);
1413 					break;
1414 
1415 				case SBTC_LOGSTAT:
1416 					BSDTRACE ((_T("SBTC_LOGSTAT),%08x"), currval));
1417 					tagcopy (currtag, currval, tagptr, &sb->logstat);
1418 					sb->logstat &= 0xff;
1419 					break;
1420 				case SBTC_LOGTAGPTR:
1421 					BSDTRACE ((_T("SBTC_LOGTAGPTR),%08x"), currval));
1422 					tagcopy (currtag, currval, tagptr, &sb->logptr);
1423 					break;
1424 				case SBTC_LOGFACILITY:
1425 					BSDTRACE ((_T("SBTC_LOGFACILITY),%08x"), currval));
1426 					if (((currtag & 1) && currval != 0 && (currval & ~LOG_FACMASK)) || !(currtag & 1))
1427 						tagcopy (currtag, currval, tagptr, &sb->logfacility);
1428 					break;
1429 				case SBTC_LOGMASK:
1430 					BSDTRACE ((_T("SBTC_LOGMASK),%08x"), currval));
1431 					tagcopy (currtag, currval, tagptr, &sb->logmask);
1432 					sb->logmask &= 0xff;
1433 					break;
1434 
1435 				case SBTC_IOERRNOSTRPTR:
1436 					if (currtag & 1) {
1437 						BSDTRACE ((_T("IOERRNOSTRPTR),invalid")));
1438 						goto done;
1439 					} else {
1440 						unsigned long ulTmp;
1441 						if (currtag & 0x8000) { /* SBTM_GETREF */
1442 							ulTmp = get_long (currval);
1443 						} else { /* SBTM_GETVAL */
1444 							ulTmp = currval;
1445 						}
1446 						BSDTRACE ((_T("IOERRNOSTRPTR),%lu"), ulTmp));
1447 						if (ulTmp < number_sys_error) {
1448 							tagcopy (currtag, currval, tagptr, &iotextptrs[ulTmp]);
1449 						} else {
1450 							tagcopy (currtag, currval, tagptr, &strErrptr);
1451 						}
1452 					}
1453 					break;
1454 				case SBTC_S2ERRNOSTRPTR:
1455 					if (currtag & 1) {
1456 						BSDTRACE ((_T("S2ERRNOSTRPTR),invalid")));
1457 						goto done;
1458 					} else {
1459 						unsigned long ulTmp;
1460 						if (currtag & 0x8000) { /* SBTM_GETREF */
1461 							ulTmp = get_long (currval);
1462 						} else { /* SBTM_GETVAL */
1463 							ulTmp = currval;
1464 						}
1465 						BSDTRACE ((_T("S2ERRNOSTRPTR),%lu"), ulTmp));
1466 						if (ulTmp < number_sys_error) {
1467 							tagcopy (currtag, currval, tagptr, &sana2iotextptrs[ulTmp]);
1468 						} else {
1469 							tagcopy (currtag, currval, tagptr, &strErrptr);
1470 						}
1471 					}
1472 					break;
1473 				case SBTC_S2WERRNOSTRPTR:
1474 					if (currtag & 1) {
1475 						BSDTRACE ((_T("S2WERRNOSTRPTR),invalid")));
1476 						goto done;
1477 					} else {
1478 						unsigned long ulTmp;
1479 						if (currtag & 0x8000) { /* SBTM_GETREF */
1480 							ulTmp = get_long (currval);
1481 						} else { /* SBTM_GETVAL */
1482 							ulTmp = currval;
1483 						}
1484 						BSDTRACE ((_T("S2WERRNOSTRPTR),%lu"), ulTmp));
1485 						if (ulTmp < number_sys_error) {
1486 							tagcopy (currtag, currval, tagptr, &sana2wiretextptrs[ulTmp]);
1487 						} else {
1488 							tagcopy (currtag, currval, tagptr, &strErrptr);
1489 						}
1490 					}
1491 					break;
1492 				case SBTC_ERRNOSTRPTR:
1493 					if (currtag & 1) {
1494 						BSDTRACE ((_T("ERRNOSTRPTR),invalid")));
1495 						goto done;
1496 					} else {
1497 						unsigned long ulTmp;
1498 						if (currtag & 0x8000) { /* SBTM_GETREF */
1499 							ulTmp = get_long (currval);
1500 						} else { /* SBTM_GETVAL */
1501 							ulTmp = currval;
1502 						}
1503 						BSDTRACE ((_T("ERRNOSTRPTR),%lu"), ulTmp));
1504 						if (ulTmp < number_sys_error) {
1505 							tagcopy (currtag, currval, tagptr, &errnotextptrs[ulTmp]);
1506 						} else {
1507 							tagcopy (currtag, currval, tagptr, &strErrptr);
1508 						}
1509 					}
1510 					break;
1511 				case SBTC_HERRNOSTRPTR:
1512 					if (currtag & 1) {
1513 						BSDTRACE ((_T("HERRNOSTRPTR),invalid")));
1514 						goto done;
1515 					} else {
1516 						unsigned long ulTmp;
1517 						if (currtag & 0x8000) { /* SBTM_GETREF */
1518 							ulTmp = get_long (currval);
1519 						} else { /* SBTM_GETVAL */
1520 							ulTmp = currval;
1521 						}
1522 						BSDTRACE ((_T("HERRNOSTRPTR),%lu"), ulTmp));
1523 						if (ulTmp < number_host_error) {
1524 							tagcopy (currtag, currval, tagptr, &herrnotextptrs[ulTmp]);
1525 						} else {
1526 							tagcopy (currtag, currval, tagptr, &strErrptr);
1527 						}
1528 					}
1529 					break;
1530 
1531 				case SBTC_ERRNOBYTEPTR:
1532 					BSDTRACE ((_T("SBTC_ERRNOBYTEPTR),0x%x"), currval));
1533 					tagcopy (currtag, currval, tagptr, &sb->errnoptr);
1534 					sb->errnosize = 1;
1535 					break;
1536 				case SBTC_ERRNOWORDPTR:
1537 					BSDTRACE ((_T("SBTC_ERRNOWORDPTR),0x%x"), currval));
1538 					tagcopy (currtag, currval, tagptr, &sb->errnoptr);
1539 					sb->errnosize = 2;
1540 					break;
1541 				case SBTC_ERRNOLONGPTR:
1542 					BSDTRACE ((_T("SBTC_ERRNOLONGPTR),0x%x"), currval));
1543 					tagcopy (currtag, currval, tagptr, &sb->errnoptr);
1544 					sb->errnosize = 4;
1545 					break;
1546 				case SBTC_HERRNOLONGPTR:
1547 					BSDTRACE ((_T("SBTC_HERRNOLONGPTR),0x%x"), currval));
1548 					tagcopy (currtag, currval, tagptr, &sb->herrnoptr);
1549 					sb->herrnosize = 4;
1550 					break;
1551 				default:
1552 					write_log (_T("bsdsocket: WARNING: Unsupported tag type (%08x=%d) in SocketBaseTagList(%x)\n"),
1553 						currtag, (currtag / 2) & SBTS_CODE, m68k_areg (regs, 0));
1554 					goto done;
1555 			}
1556 		}
1557 
1558 		BSDTRACE ((_T(",")));
1559 		tagptr += 8;
1560 	}
1561 
1562 done:
1563 	BSDTRACE ((_T(") -> %d\n"), tagsprocessed));
1564 
1565 	return tagsprocessed;
1566 }
1567 
bsdsocklib_GetSocketEvents(TrapContext * context)1568 static uae_u32 REGPARAM2 bsdsocklib_GetSocketEvents (TrapContext *context)
1569 {
1570 #ifdef _WIN32
1571 	struct socketbase *sb = get_socketbase (context);
1572 	int i;
1573 	int flags;
1574 	uae_u32 ptr = m68k_areg (regs, 0);
1575 
1576 	BSDTRACE ((_T("GetSocketEvents(0x%x) -> "), ptr));
1577 
1578 	for (i = sb->dtablesize; i--; sb->eventindex++) {
1579 		if (sb->eventindex >= sb->dtablesize)
1580 			sb->eventindex = 0;
1581 
1582 		if (sb->mtable[sb->eventindex]) {
1583 			flags = sb->ftable[sb->eventindex] & SET_ALL;
1584 			if (flags) {
1585 				sb->ftable[sb->eventindex] &= ~SET_ALL;
1586 				put_long (m68k_areg (regs, 0), flags >> 8);
1587 				BSDTRACE ((_T("%d (0x%x)\n"), sb->eventindex + 1, flags >> 8));
1588 				return sb->eventindex; // xxx
1589 			}
1590 		}
1591 	}
1592 #endif
1593 	BSDTRACE ((_T("-1\n")));
1594 	return -1;
1595 }
1596 
bsdsocklib_getdtablesize(TrapContext * context)1597 static uae_u32 REGPARAM2 bsdsocklib_getdtablesize (TrapContext *context)
1598 {
1599 	return get_socketbase (context)->dtablesize;
1600 }
1601 
bsdsocklib_null(TrapContext * context)1602 static uae_u32 REGPARAM2 bsdsocklib_null (TrapContext *context)
1603 {
1604 	return 0;
1605 }
1606 
bsdsocklib_init(TrapContext * context)1607 static uae_u32 REGPARAM2 bsdsocklib_init (TrapContext *context)
1608 {
1609 #ifdef FSUAE
1610     write_log("bsdsock - bsdsocklib_init context = %p\n", context);
1611 #endif
1612 	uae_u32 tmp1;
1613 	int i;
1614 
1615 	write_log (_T("Creating UAE bsdsocket.library 4.1\n"));
1616 	if (SockLibBase)
1617 		bsdlib_reset ();
1618 
1619 	m68k_areg (regs, 0) = functable;
1620 	m68k_areg (regs, 1) = datatable;
1621 	m68k_areg (regs, 2) = 0;
1622 	m68k_dreg (regs, 0) = LIBRARY_SIZEOF;
1623 	m68k_dreg (regs, 1) = 0;
1624 	tmp1 = CallLib (context, m68k_areg (regs, 6), -0x54); /* MakeLibrary */
1625 
1626 	if (!tmp1) {
1627 		write_log (_T("bsdoscket: FATAL: Cannot create bsdsocket.library!\n"));
1628 		return 0;
1629 	}
1630 	m68k_areg (regs, 1) = tmp1;
1631 	CallLib (context, m68k_areg (regs, 6), -0x18c); /* AddLibrary */
1632 	SockLibBase = tmp1;
1633 
1634 	/* Install error strings in Amiga memory */
1635 	tmp1 = 0;
1636 	for (i = number_sys_error; i--;)
1637 		tmp1 += _tcslen (errortexts[i]) + 1;
1638 	for (i = number_host_error; i--;)
1639 		tmp1 += _tcslen (herrortexts[i]) + 1;
1640 	for (i = number_sana2io_error; i--;)
1641 		tmp1 += _tcslen (sana2io_errlist[i]) + 1;
1642 	for (i = number_sana2wire_error; i--;)
1643 		tmp1 += _tcslen (sana2wire_errlist[i]) + 1;
1644 	tmp1 += _tcslen (strErr) + 1;
1645 
1646 	m68k_dreg (regs, 0) = tmp1;
1647 	m68k_dreg (regs, 1) = 0;
1648 	tmp1 = CallLib (context, m68k_areg (regs, 6), -0xC6); /* AllocMem */
1649 
1650 	if (!tmp1) {
1651 		write_log (_T("bsdsocket: FATAL: Ran out of memory while creating bsdsocket.library!\n"));
1652 		return 0;
1653 	}
1654 
1655 	for (i = 0; i < (int) (number_sys_error); i++)
1656 		errnotextptrs[i] = addstr (&tmp1, errortexts[i]);
1657 	for (i = 0; i < (int) (number_host_error); i++)
1658 		herrnotextptrs[i] = addstr (&tmp1, herrortexts[i]);
1659 	for (i = 0; i < (int) (number_sana2io_error); i++)
1660 		sana2iotextptrs[i] = addstr (&tmp1, sana2io_errlist[i]);
1661 	for (i = 0; i < (int) (number_sana2wire_error); i++)
1662 		sana2wiretextptrs[i] = addstr (&tmp1, sana2wire_errlist[i]);
1663 	strErrptr = addstr (&tmp1, strErr);
1664 
1665 #if 0
1666 	/* @@@ someone please implement a proper interrupt handler setup here :) */
1667 	tmp1 = here ();
1668 	calltrap (deftrap2 (bsdsock_int_handler, TRAPFLAG_EXTRA_STACK | TRAPFLAG_NO_RETVAL, "bsdsock_int_handler"));
1669 	dw (0x4ef9);
1670 	dl (get_long (context->regs.vbr + 0x78));
1671 	put_long (context->regs.vbr + 0x78, tmp1);
1672 #endif
1673 
1674 	m68k_dreg (regs, 0) = 1;
1675 	return 0;
1676 }
1677 
bsdlib_reset(void)1678 void bsdlib_reset (void)
1679 {
1680 	SB, *nsb;
1681 	int i;
1682 
1683 	if (!SockLibBase)
1684 		return;
1685 
1686 	SockLibBase = 0;
1687 
1688 	write_log (_T("BSDSOCK: cleanup start..\n"));
1689 	host_sbcleanup (NULL);
1690 	for (sb = socketbases; sb; sb = nsb) {
1691 		nsb = sb->next;
1692 
1693 		write_log (_T("BSDSOCK: cleanup start socket %p\n"), sb);
1694 		host_sbcleanup (sb);
1695 
1696 		free (sb->dtable);
1697 		free (sb->ftable);
1698 
1699 		free (sb);
1700 	}
1701 	write_log (_T("BSDSOCK: cleanup end\n"));
1702 
1703 	socketbases = NULL;
1704 #if 1
1705 	sbsigqueue = NULL;
1706 #endif
1707 
1708 	for (i = 0; i < SOCKPOOLSIZE; i++) {
1709 		if (sockdata->sockpoolids[i] != UNIQUE_ID) {
1710 			sockdata->sockpoolids[i] = UNIQUE_ID;
1711 			host_closesocketquick (sockdata->sockpoolsocks[i]);
1712 		}
1713 	}
1714 
1715 	host_sbreset ();
1716 	write_log (_T("BSDSOCK: cleanup finished\n"));
1717 }
1718 
1719 static const TrapHandler sockfuncs[] = {
1720 	bsdsocklib_init, bsdsocklib_Open, bsdsocklib_Close, bsdsocklib_Expunge,
1721 	bsdsocklib_socket, bsdsocklib_bind, bsdsocklib_listen, bsdsocklib_accept,
1722 	bsdsocklib_connect, bsdsocklib_sendto, bsdsocklib_send, bsdsocklib_recvfrom, bsdsocklib_recv,
1723 	bsdsocklib_shutdown, bsdsocklib_setsockopt, bsdsocklib_getsockopt, bsdsocklib_getsockname,
1724 	bsdsocklib_getpeername, bsdsocklib_IoctlSocket, bsdsocklib_CloseSocket, bsdsocklib_WaitSelect,
1725 	bsdsocklib_SetSocketSignals, bsdsocklib_getdtablesize, bsdsocklib_ObtainSocket, bsdsocklib_ReleaseSocket,
1726 	bsdsocklib_ReleaseCopyOfSocket, bsdsocklib_Errno, bsdsocklib_SetErrnoPtr, bsdsocklib_Inet_NtoA,
1727 	bsdsocklib_inet_addr, bsdsocklib_Inet_LnaOf, bsdsocklib_Inet_NetOf, bsdsocklib_Inet_MakeAddr,
1728 	bsdsocklib_inet_network, bsdsocklib_gethostbyname, bsdsocklib_gethostbyaddr, bsdsocklib_getnetbyname,
1729 	bsdsocklib_getnetbyaddr, bsdsocklib_getservbyname, bsdsocklib_getservbyport, bsdsocklib_getprotobyname,
1730 	bsdsocklib_getprotobynumber, bsdsocklib_vsyslog, bsdsocklib_Dup2Socket, bsdsocklib_sendmsg,
1731 	bsdsocklib_recvmsg, bsdsocklib_gethostname, bsdsocklib_gethostid, bsdsocklib_SocketBaseTagList,
1732 	bsdsocklib_GetSocketEvents
1733 };
1734 
1735 static const TCHAR * const funcnames[] = {
1736 	_T("bsdsocklib_init"), _T("bsdsocklib_Open"), _T("bsdsocklib_Close"), _T("bsdsocklib_Expunge"),
1737 	_T("bsdsocklib_socket"), _T("bsdsocklib_bind"), _T("bsdsocklib_listen"), _T("bsdsocklib_accept"),
1738 	_T("bsdsocklib_connect"), _T("bsdsocklib_sendto"), _T("bsdsocklib_send"), _T("bsdsocklib_recvfrom"), _T("bsdsocklib_recv"),
1739 	_T("bsdsocklib_shutdown"), _T("bsdsocklib_setsockopt"), _T("bsdsocklib_getsockopt"), _T("bsdsocklib_getsockname"),
1740 	_T("bsdsocklib_getpeername"), _T("bsdsocklib_IoctlSocket"), _T("bsdsocklib_CloseSocket"), _T("bsdsocklib_WaitSelect"),
1741 	_T("bsdsocklib_SetSocketSignals"), _T("bsdsocklib_getdtablesize"), _T("bsdsocklib_ObtainSocket"), _T("bsdsocklib_ReleaseSocket"),
1742 	_T("bsdsocklib_ReleaseCopyOfSocket"), _T("bsdsocklib_Errno"), _T("bsdsocklib_SetErrnoPtr"), _T("bsdsocklib_Inet_NtoA"),
1743 	_T("bsdsocklib_inet_addr"), _T("bsdsocklib_Inet_LnaOf"), _T("bsdsocklib_Inet_NetOf"), _T("bsdsocklib_Inet_MakeAddr"),
1744 	_T("bsdsocklib_inet_network"), _T("bsdsocklib_gethostbyname"), _T("bsdsocklib_gethostbyaddr"), _T("bsdsocklib_getnetbyname"),
1745 	_T("bsdsocklib_getnetbyaddr"), _T("bsdsocklib_getservbyname"), _T("bsdsocklib_getservbyport"), _T("bsdsocklib_getprotobyname"),
1746 	_T("bsdsocklib_getprotobynumber"), _T("bsdsocklib_vsyslog"), _T("bsdsocklib_Dup2Socket"), _T("bsdsocklib_sendmsg"),
1747 	_T("bsdsocklib_recvmsg"), _T("bsdsocklib_gethostname"), _T("bsdsocklib_gethostid"), _T("bsdsocklib_SocketBaseTagList"),
1748 	_T("bsdsocklib_GetSocketEvents")
1749 };
1750 
1751 static uae_u32 sockfuncvecs[sizeof (sockfuncs) / sizeof (*sockfuncs)];
1752 
1753 static uae_u32 res_name, res_id, res_init;
1754 
bsdlib_startup(uaecptr resaddr)1755 uaecptr bsdlib_startup (uaecptr resaddr)
1756 {
1757 	if (res_name == 0 || !currprefs.socket_emu)
1758 		return resaddr;
1759 	put_word (resaddr + 0x0, 0x4AFC);
1760 	put_long (resaddr + 0x2, resaddr);
1761 	put_long (resaddr + 0x6, resaddr + 0x1A); /* Continue scan here */
1762 	put_word (resaddr + 0xA, 0x8004); /* RTF_AUTOINIT, RT_VERSION */
1763 	put_word (resaddr + 0xC, 0x0970); /* NT_LIBRARY, RT_PRI */
1764 	put_long (resaddr + 0xE, res_name);
1765 	put_long (resaddr + 0x12, res_id);
1766 	put_long (resaddr + 0x16, res_init);
1767 	resaddr += 0x1A;
1768 	return resaddr;
1769 }
1770 
bsdlib_install(void)1771 void bsdlib_install (void)
1772 {
1773 	int i;
1774 
1775 	if (!sockdata) {
1776 		sockdata = xcalloc (struct sockd, 1);
1777 		for (i = 0; i < SOCKPOOLSIZE; i++)
1778 			sockdata->sockpoolids[i] = UNIQUE_ID;
1779 	}
1780 
1781 	if (!init_socket_layer ())
1782 		return;
1783 
1784 	res_name = ds (_T("bsdsocket.library"));
1785 	res_id = ds (_T("UAE bsdsocket.library 4.1"));
1786 
1787 	for (i = 0; i < (int) (sizeof (sockfuncs) / sizeof (sockfuncs[0])); i++) {
1788 		sockfuncvecs[i] = here ();
1789 		calltrap (deftrap2 (sockfuncs[i], TRAPFLAG_EXTRA_STACK, funcnames[i]));
1790 		dw (RTS);
1791 	}
1792 
1793 	/* FuncTable */
1794 	functable = here ();
1795 	for (i = 1; i < 4; i++)
1796 		dl (sockfuncvecs[i]);	/* Open / Close / Expunge */
1797 	dl (EXPANSION_nullfunc);	/* Null */
1798 	for (i = 4; i < (int) (sizeof (sockfuncs) / sizeof (sockfuncs[0])); i++)
1799 		dl (sockfuncvecs[i]);
1800 	dl (0xFFFFFFFF);		/* end of table */
1801 
1802 	/* DataTable */
1803 	datatable = here ();
1804 	dw (0xE000);		/* INITBYTE */
1805 	dw (0x0008);		/* LN_TYPE */
1806 	dw (0x0900);		/* NT_LIBRARY */
1807 	dw (0xE000);		/* INITBYTE */
1808 	dw (0x0009);		/* LN_PRI */
1809 	dw (0xCE00);		/* -50 */
1810 	dw (0xC000);		/* INITLONG */
1811 	dw (0x000A);		/* LN_NAME */
1812 	dl (res_name);
1813 	dw (0xE000);		/* INITBYTE */
1814 	dw (0x000E);		/* LIB_FLAGS */
1815 	dw (0x0600);		/* LIBF_SUMUSED | LIBF_CHANGED */
1816 	dw (0xD000);		/* INITWORD */
1817 	dw (0x0014);		/* LIB_VERSION */
1818 	dw (0x0004);
1819 	dw (0xD000);
1820 	dw (0x0016);		/* LIB_REVISION */
1821 	dw (0x0001);
1822 	dw (0xC000);
1823 	dw (0x0018);		/* LIB_IDSTRING */
1824 	dl (res_id);
1825 	dl (0x00000000);		/* end of table */
1826 
1827 	res_init = here ();
1828 	dl (512);
1829 	dl (functable);
1830 	dl (datatable);
1831 	dl (*sockfuncvecs);
1832 
1833 	write_log (_T("bsdsocket.library installed\n"));
1834 }
1835 
1836 #endif /* ! BSDSOCKET */
1837