1 /*
2  * Copyright (c) 1995 Danny Gasparovski.
3  *
4  * Please read the file COPYRIGHT for the
5  * terms and conditions of the copyright.
6  */
7 
8 #define WANT_SYS_IOCTL_H
9 #include <stdlib.h>
10 #include "slirp.h"
11 
12 u_int curtime, time_fasttimo, last_slowtimo, detach_time;
13 u_int detach_wait = 600000;	/* 10 minutes */
14 
15 #if 0
16 int x_port = -1;
17 int x_display = 0;
18 int x_screen = 0;
19 
20 int
21 show_x(buff, inso)
22 	char *buff;
23 	struct SLIRPsocket *inso;
24 {
25 	if (x_port < 0) {
26 		lprint("X Redir: X not being redirected.\r\n");
27 	} else {
28 		lprint("X Redir: In sh/bash/zsh/etc. type: DISPLAY=%s:%d.%d; export DISPLAY\r\n",
29 		      inet_ntoa(our_addr), x_port, x_screen);
30 		lprint("X Redir: In csh/tcsh/etc. type:    setenv DISPLAY %s:%d.%d\r\n",
31 		      inet_ntoa(our_addr), x_port, x_screen);
32 		if (x_display)
33 		   lprint("X Redir: Redirecting to display %d\r\n", x_display);
34 	}
35 
36 	return CFG_OK;
37 }
38 
39 
40 /*
41  * XXX Allow more than one X redirection?
42  */
43 void
44 redir_x(inaddr, start_port, display, screen)
45 	u_int32_t inaddr;
46 	int start_port;
47 	int display;
48 	int screen;
49 {
50 	int i;
51 
52 	if (x_port >= 0) {
53 		lprint("X Redir: X already being redirected.\r\n");
54 		show_x(0, 0);
55 	} else {
56 		for (i = 6001 + (start_port-1); i <= 6100; i++) {
57 			if (solisten(htons(i), inaddr, htons(6000 + display), 0)) {
58 				/* Success */
59 				x_port = i - 6000;
60 				x_display = display;
61 				x_screen = screen;
62 				show_x(0, 0);
63 				return;
64 			}
65 		}
66 		lprint("X Redir: Error: Couldn't redirect a port for X. Weird.\r\n");
67 	}
68 }
69 #endif
70 
71 #ifndef HAVE_INET_ATON
72 int
inet_aton(cp,ia)73 inet_aton(cp, ia)
74 	const char *cp;
75 	struct in_addr *ia;
76 {
77 	u_int32_t addr = inet_addr(cp);
78 	if (addr == 0xffffffff)
79 		return 0;
80 	ia->s_addr = addr;
81 	return 1;
82 }
83 #endif
84 
85 /*
86  * Get our IP address and put it in our_addr
87  */
88 void
getouraddr()89 getouraddr()
90 {
91 	char buff[512];
92 	struct hostent *he = NULL;
93 #define ANCIENT
94 	#ifdef ANCIENT
95 	if (gethostname(&buff,500) == 0)
96             he = gethostbyname(&buff);
97         if (he)
98             our_addr = *(struct in_addr *)he->h_addr;
99         if (our_addr.s_addr == 0)
100             our_addr.s_addr = loopback_addr.s_addr;
101 	#else
102  	if (gethostname(buff,256) == 0)
103 	{
104 		struct addrinfo hints = { 0 };
105 		hints.ai_flags = AI_NUMERICHOST;
106 		hints.ai_family = AF_INET;
107 		struct addrinfo* ai;
108 		if (getaddrinfo(buff, NULL, &hints, &ai) == 0)
109 		{
110 			our_addr = *(struct in_addr *)ai->ai_addr->sa_data;
111 			freeaddrinfo(ai);
112 		}
113 	}
114     if (our_addr.s_addr == 0)
115         our_addr.s_addr = loopback_addr.s_addr;
116 	#endif
117 	#undef ANCIENT
118 }
119 
120 struct quehead {
121 	struct quehead *qh_link;
122 	struct quehead *qh_rlink;
123 };
124 
125 void
insque(a,b)126 insque(a, b)
127 	void *a, *b;
128 {
129 	register struct quehead *element = (struct quehead *) a;
130 	register struct quehead *head = (struct quehead *) b;
131 	element->qh_link = head->qh_link;
132 	head->qh_link = (struct quehead *)element;
133 	element->qh_rlink = (struct quehead *)head;
134 	((struct quehead *)(element->qh_link))->qh_rlink
135 	= (struct quehead *)element;
136 }
137 
138 void
remque(a)139 remque(a)
140      void *a;
141 {
142   register struct quehead *element = (struct quehead *) a;
143   ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
144   ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
145   element->qh_rlink = NULL;
146   /*  element->qh_link = NULL;  TCP FIN1 crashes if you do this.  Why ? */
147 }
148 
149 /* #endif */
150 
151 
152 int
add_exec(ex_ptr,do_pty,exec,addr,port)153 add_exec(ex_ptr, do_pty, exec, addr, port)
154 	struct ex_list **ex_ptr;
155 	int do_pty;
156 	char *exec;
157 	int addr;
158 	int port;
159 {
160 	struct ex_list *tmp_ptr;
161 
162 	/* First, check if the port is "bound" */
163 	for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
164 		if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
165 		   return -1;
166 	}
167 
168 	tmp_ptr = *ex_ptr;
169 	*ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
170 	(*ex_ptr)->ex_fport = port;
171 	(*ex_ptr)->ex_addr = addr;
172 	(*ex_ptr)->ex_pty = do_pty;
173 	(*ex_ptr)->ex_exec = strdup(exec);
174 	(*ex_ptr)->ex_next = tmp_ptr;
175 	return 0;
176 }
177 
178 #ifndef HAVE_STRERROR
179 
180 /*
181  * For systems with no strerror
182  */
183 
184 #ifdef WIN32
185 //extern int sys_nerr;
186 //extern char *sys_errlist[];
187 #endif
188 
189 char *
SLIRPstrerror(error)190 SLIRPstrerror(error)
191 	int error;
192 {
193 	if (error < sys_nerr)
194 	   return sys_errlist[error];
195 	else
196 	   return "Unknown error.";
197 }
198 
199 #endif
200 
201 
202 #ifdef _WIN32
203 
204 int
fork_exec(so,ex,do_pty)205 fork_exec(so, ex, do_pty)
206 	struct SLIRPsocket *so;
207 	char *ex;
208 	int do_pty;
209 {
210     /* not implemented */
211     return 0;
212 }
213 
214 #else
215 
216 int
slirp_openpty(amaster,aslave)217 slirp_openpty(amaster, aslave)
218      int *amaster, *aslave;
219 {
220 	register int master, slave;
221 
222 #ifdef HAVE_GRANTPT
223 	char *ptr;
224 
225 	if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
226 	    grantpt(master) < 0 ||
227 	    unlockpt(master) < 0 ||
228 	    (ptr = ptsname(master)) == NULL)  {
229 		close(master);
230 		return -1;
231 	}
232 
233 	if ((slave = open(ptr, O_RDWR)) < 0 ||
234 	    ioctl(slave, I_PUSH, "ptem") < 0 ||
235 	    ioctl(slave, I_PUSH, "ldterm") < 0 ||
236 	    ioctl(slave, I_PUSH, "ttcompat") < 0) {
237 		close(master);
238 		close(slave);
239 		return -1;
240 	}
241 
242 	*amaster = master;
243 	*aslave = slave;
244 	return 0;
245 
246 #else
247 
248 	static char line[] = "/dev/ptyXX";
249 	register const char *cp1, *cp2;
250 
251 	for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
252 		line[8] = *cp1;
253 		for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
254 			line[9] = *cp2;
255 			if ((master = open(line, O_RDWR, 0)) == -1) {
256 				if (errno == ENOENT)
257 				   return (-1);    /* out of ptys */
258 			} else {
259 				line[5] = 't';
260 				/* These will fail */
261 				(void) chown(line, getuid(), 0);
262 				(void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
263 #ifdef HAVE_REVOKE
264 				(void) revoke(line);
265 #endif
266 				if ((slave = open(line, O_RDWR, 0)) != -1) {
267 					*amaster = master;
268 					*aslave = slave;
269 					return 0;
270 				}
271 				(void) close(master);
272 				line[5] = 'p';
273 			}
274 		}
275 	}
276 	errno = ENOENT; /* out of ptys */
277 	return (-1);
278 #endif
279 }
280 
281 /*
282  * XXX This is ugly
283  * We create and bind a socket, then fork off to another
284  * process, which connects to this socket, after which we
285  * exec the wanted program.  If something (strange) happens,
286  * the accept() call could block us forever.
287  *
288  * do_pty = 0   Fork/exec inetd style
289  * do_pty = 1   Fork/exec using slirp.telnetd
290  * do_ptr = 2   Fork/exec using pty
291  */
292 int
fork_exec(so,ex,do_pty)293 fork_exec(so, ex, do_pty)
294 	struct SLIRPsocket *so;
295 	char *ex;
296 	int do_pty;
297 {
298 	int s;
299 	struct sockaddr_in addr;
300 	socklen_t addrlen = sizeof(addr);
301 	int opt;
302         int master;
303 	char *argv[256];
304 #if 0
305 	char buff[256];
306 #endif
307 	/* don't want to clobber the original */
308 	char *bptr;
309 	char *curarg;
310 	int c, i, ret;
311 
312 	DEBUG_CALL("fork_exec");
313 	DEBUG_ARG("so = %lx", (long)so);
314 	DEBUG_ARG("ex = %lx", (long)ex);
315 	DEBUG_ARG("do_pty = %lx", (long)do_pty);
316 
317 	if (do_pty == 2) {
318 		if (slirp_openpty(&master, &s) == -1) {
319 			lprint("Error: openpty failed: %s\n", strerror(errno));
320 			return 0;
321 		}
322 	} else {
323 		memset(&addr, 0, sizeof(struct sockaddr_in));
324 		addr.sin_family = AF_INET;
325 		addr.sin_port = 0;
326 		addr.sin_addr.s_addr = INADDR_ANY;
327 
328 		if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
329 		    bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
330 		    listen(s, 1) < 0) {
331 			lprint("Error: inet socket: %s\n", strerror(errno));
332 			closesocket(s);
333 
334 			return 0;
335 		}
336 	}
337 
338 	switch(fork()) {
339 	 case -1:
340 		lprint("Error: fork failed: %s\n", strerror(errno));
341 		close(s);
342 		if (do_pty == 2)
343 		   close(master);
344 		return 0;
345 
346 	 case 0:
347 		/* Set the DISPLAY */
348 		if (do_pty == 2) {
349 			(void) close(master);
350 #ifdef TIOCSCTTY /* XXXXX */
351 			(void) setsid();
352 			ioctl(s, TIOCSCTTY, (char *)NULL);
353 #endif
354 		} else {
355 			getsockname(s, (struct sockaddr *)&addr, &addrlen);
356 			close(s);
357 			/*
358 			 * Connect to the socket
359 			 * XXX If any of these fail, we're in trouble!
360 	 		 */
361 			s = socket(AF_INET, SOCK_STREAM, 0);
362 			addr.sin_addr = loopback_addr;
363                         do {
364                             ret = connect(s, (struct sockaddr *)&addr, addrlen);
365                         } while (ret < 0 && errno == EINTR);
366 		}
367 
368 #if 0
369 		if (x_port >= 0) {
370 #ifdef HAVE_SETENV
371 			sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
372 			setenv("DISPLAY", buff, 1);
373 #else
374 			sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
375 			putenv(buff);
376 #endif
377 		}
378 #endif
379 		dup2(s, 0);
380 		dup2(s, 1);
381 		dup2(s, 2);
382 		for (s = 3; s <= 255; s++)
383 		   close(s);
384 
385 		i = 0;
386 		bptr = strdup(ex); /* No need to free() this */
387 		if (do_pty == 1) {
388 			/* Setup "slirp.telnetd -x" */
389 			argv[i++] = "slirp.telnetd";
390 			argv[i++] = "-x";
391 			argv[i++] = bptr;
392 		} else
393 		   do {
394 			/* Change the string into argv[] */
395 			curarg = bptr;
396 			while (*bptr != ' ' && *bptr != (char)0)
397 			   bptr++;
398 			c = *bptr;
399 			*bptr++ = (char)0;
400 			argv[i++] = strdup(curarg);
401 		   } while (c);
402 
403 		argv[i] = 0;
404 		execvp(argv[0], argv);
405 
406 		/* Ooops, failed, let's tell the user why */
407 		  {
408 			  char buff[256];
409 
410 			  sprintf(buff, "Error: execvp of %s failed: %s\n",
411 				  argv[0], strerror(errno));
412 			  write(2, buff, strlen(buff)+1);
413 		  }
414 		close(0); close(1); close(2); /* XXX */
415 		exit(1);
416 
417 	 default:
418 		if (do_pty == 2) {
419 			close(s);
420 			so->s = master;
421 		} else {
422 			/*
423 			 * XXX this could block us...
424 			 * XXX Should set a timer here, and if accept() doesn't
425 		 	 * return after X seconds, declare it a failure
426 		 	 * The only reason this will block forever is if socket()
427 		 	 * of connect() fail in the child process
428 		 	 */
429                         do {
430                             so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
431                         } while (so->s < 0 && errno == EINTR);
432                         closesocket(s);
433 			opt = 1;
434 			setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
435 			opt = 1;
436 			setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
437 		}
438 		fd_nonblock(so->s);
439 
440 		/* Append the telnet options now */
441 		if (so->so_m != 0 && do_pty == 1)  {
442 			sbappend(so, so->so_m);
443 			so->so_m = 0;
444 		}
445 
446 		return 1;
447 	}
448 }
449 #endif
450 
451 #ifndef HAVE_STRDUP
strdup(char * str)452 char * strdup(char *str)
453 {
454 	char *bptr;
455 
456 	bptr = (char *)malloc(strlen(str)+1);
457 	strcpy(bptr, str);
458 
459 	return bptr;
460 }
461 #endif
462 
463 #if 0
464 void
465 snooze_hup(num)
466 	int num;
467 {
468 	int s, ret;
469 #ifndef NO_UNIX_SOCKETS
470 	struct sockaddr_un sock_un;
471 #endif
472 	struct sockaddr_in sock_in;
473 	char buff[256];
474 
475 	ret = -1;
476 	if (slirp_socket_passwd) {
477 		s = socket(AF_INET, SOCK_STREAM, 0);
478 		if (s < 0)
479 		   slirp_exit(1);
480 		sock_in.sin_family = AF_INET;
481 		sock_in.sin_addr.s_addr = slirp_socket_addr;
482 		sock_in.sin_port = htons(slirp_socket_port);
483 		if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0)
484 		   slirp_exit(1); /* just exit...*/
485 		sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit);
486 		write(s, buff, strlen(buff)+1);
487 	}
488 #ifndef NO_UNIX_SOCKETS
489 	  else {
490 		s = socket(AF_UNIX, SOCK_STREAM, 0);
491 		if (s < 0)
492 		   slirp_exit(1);
493 		sock_un.sun_family = AF_UNIX;
494 		strcpy(sock_un.sun_path, socket_path);
495 		if (connect(s, (struct sockaddr *)&sock_un,
496 			      sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0)
497 		   slirp_exit(1);
498 		sprintf(buff, "kill none:%d", slirp_socket_unit);
499 		write(s, buff, strlen(buff)+1);
500 	}
501 #endif
502 	slirp_exit(0);
503 }
504 
505 
506 void
507 snooze()
508 {
509 	sigset_t s;
510 	int i;
511 
512 	/* Don't need our data anymore */
513 	/* XXX This makes SunOS barf */
514 /*	brk(0); */
515 
516 	/* Close all fd's */
517 	for (i = 255; i >= 0; i--)
518 	   close(i);
519 
520 	signal(SIGQUIT, slirp_exit);
521 	signal(SIGHUP, snooze_hup);
522 	sigemptyset(&s);
523 
524 	/* Wait for any signal */
525 	sigsuspend(&s);
526 
527 	/* Just in case ... */
528 	exit(255);
529 }
530 
531 void
532 relay(s)
533 	int s;
534 {
535 	char buf[8192];
536 	int n;
537 	fd_set readfds;
538 	struct ttys *ttyp;
539 
540 	/* Don't need our data anymore */
541 	/* XXX This makes SunOS barf */
542 /*	brk(0); */
543 
544 	signal(SIGQUIT, slirp_exit);
545 	signal(SIGHUP, slirp_exit);
546         signal(SIGINT, slirp_exit);
547 	signal(SIGTERM, slirp_exit);
548 
549 	/* Fudge to get term_raw and term_restore to work */
550 	if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
551          lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
552          slirp_exit (1);
553     }
554 	ttyp->fd = 0;
555 	ttyp->flags |= TTY_CTTY;
556 	term_raw(ttyp);
557 
558 	while (1) {
559 		FD_ZERO(&readfds);
560 
561 		FD_SET(0, &readfds);
562 		FD_SET(s, &readfds);
563 
564 		n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
565 
566 		if (n <= 0)
567 		   slirp_exit(0);
568 
569 		if (FD_ISSET(0, &readfds)) {
570 			n = read(0, buf, 8192);
571 			if (n <= 0)
572 			   slirp_exit(0);
573 			n = writen(s, buf, n);
574 			if (n <= 0)
575 			   slirp_exit(0);
576 		}
577 
578 		if (FD_ISSET(s, &readfds)) {
579 			n = read(s, buf, 8192);
580 			if (n <= 0)
581 			   slirp_exit(0);
582 			n = writen(0, buf, n);
583 			if (n <= 0)
584 			   slirp_exit(0);
585 		}
586 	}
587 
588 	/* Just in case.... */
589 	exit(1);
590 }
591 #endif
592 
593 int (*lprint_print) _P((void *, const char *, va_list));
594 char *lprint_ptr, *lprint_ptr2, **lprint_arg;
595 
596 #ifdef _MSC_VER			//aren't we
597 #define __STDC__
598 #endif
599 
600 void
601 #ifdef __STDC__
lprint(const char * format,...)602 lprint(const char *format, ...)
603 #else
604 lprint(va_alist) va_dcl
605 #endif
606 {
607 	va_list args;
608 
609 #ifdef __STDC__
610         va_start(args, format);
611 #else
612         char *format;
613         va_start(args);
614         format = va_arg(args, char *);
615 #endif
616 #if 0
617 	/* If we're printing to an sbuf, make sure there's enough room */
618 	/* XXX +100? */
619 	if (lprint_sb) {
620 		if ((lprint_ptr - lprint_sb->sb_wptr) >=
621 		    (lprint_sb->sb_datalen - (strlen(format) + 100))) {
622 			int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
623 			int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data;
624 			int deltap = lprint_ptr -         lprint_sb->sb_data;
625 
626 			lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
627 							     lprint_sb->sb_datalen + TCP_SNDSPACE);
628 
629 			/* Adjust all values */
630 			lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
631 			lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
632 			lprint_ptr =         lprint_sb->sb_data + deltap;
633 
634 			lprint_sb->sb_datalen += TCP_SNDSPACE;
635 		}
636 	}
637 #endif
638 	if (lprint_print)
639 	   lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
640 
641 	/* Check if they want output to be logged to file as well */
642 	if (lfd) {
643 		/*
644 		 * Remove \r's
645 		 * otherwise you'll get ^M all over the file
646 		 */
647 		int len = strlen(format);
648 		char *bptr1, *bptr2;
649 
650 		bptr1 = bptr2 = strdup(format);
651 
652 		while (len--) {
653 			if (*bptr1 == '\r')
654 			   memcpy(bptr1, bptr1+1, len+1);
655 			else
656 			   bptr1++;
657 		}
658 		vfprintf(lfd, bptr2, args);
659 		free(bptr2);
660 	}
661 	va_end(args);
662 }
663 
664 void
add_emu(buff)665 add_emu(buff)
666 	char *buff;
667 {
668 	u_int lport, fport;
669 	u_int8_t tos = 0, emu = 0;
670 	char buff1[256], buff2[256], buff4[128];
671 	char *buff3 = buff4;
672 	struct emu_t *emup;
673 	struct SLIRPsocket *so;
674 
675 	if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
676 		lprint("Error: Bad arguments\r\n");
677 		return;
678 	}
679 
680 	if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
681 		lport = 0;
682 		if (sscanf(buff1, "%d", &fport) != 1) {
683 			lprint("Error: Bad first argument\r\n");
684 			return;
685 		}
686 	}
687 
688 	if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
689 		buff3 = 0;
690 		if (sscanf(buff2, "%256s", buff1) != 1) {
691 			lprint("Error: Bad second argument\r\n");
692 			return;
693 		}
694 	}
695 
696 	if (buff3) {
697 		if (strcmp(buff3, "lowdelay") == 0)
698 		   tos = IPTOS_LOWDELAY;
699 		else if (strcmp(buff3, "throughput") == 0)
700 		   tos = IPTOS_THROUGHPUT;
701 		else {
702 			lprint("Error: Expecting \"lowdelay\"/\"throughput\"\r\n");
703 			return;
704 		}
705 	}
706 
707 	if (strcmp(buff1, "ftp") == 0)
708 	   emu = EMU_FTP;
709 	else if (strcmp(buff1, "irc") == 0)
710 	   emu = EMU_IRC;
711 	else if (strcmp(buff1, "none") == 0)
712 	   emu = EMU_NONE; /* ie: no emulation */
713 	else {
714 		lprint("Error: Unknown service\r\n");
715 		return;
716 	}
717 
718 	/* First, check that it isn't already emulated */
719 	for (emup = tcpemu; emup; emup = emup->next) {
720 		if (emup->lport == lport && emup->fport == fport) {
721 			lprint("Error: port already emulated\r\n");
722 			return;
723 		}
724 	}
725 
726 	/* link it */
727 	emup = (struct emu_t *)malloc(sizeof (struct emu_t));
728 	emup->lport = (u_int16_t)lport;
729 	emup->fport = (u_int16_t)fport;
730 	emup->tos = tos;
731 	emup->emu = emu;
732 	emup->next = tcpemu;
733 	tcpemu = emup;
734 
735 	/* And finally, mark all current sessions, if any, as being emulated */
736 	for (so = tcb.so_next; so != &tcb; so = so->so_next) {
737 		if ((lport && lport == ntohs(so->so_lport)) ||
738 		    (fport && fport == ntohs(so->so_fport))) {
739 			if (emu)
740 			   so->so_emu = emu;
741 			if (tos)
742 			   so->so_iptos = tos;
743 		}
744 	}
745 
746 	lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
747 }
748 
749 #ifdef BAD_SPRINTF
750 
751 #undef vsprintf
752 #undef sprintf
753 
754 /*
755  * Some BSD-derived systems have a sprintf which returns char *
756  */
757 
758 int
vsprintf_len(string,format,args)759 vsprintf_len(string, format, args)
760 	char *string;
761 	const char *format;
762 	va_list args;
763 {
764 	vsprintf(string, format, args);
765 	return strlen(string);
766 }
767 
768 int
769 #ifdef __STDC__
sprintf_len(char * string,const char * format,...)770 sprintf_len(char *string, const char *format, ...)
771 #else
772 sprintf_len(va_alist) va_dcl
773 #endif
774 {
775 	va_list args;
776 #ifdef __STDC__
777 	va_start(args, format);
778 #else
779 	char *string;
780 	char *format;
781 	va_start(args);
782 	string = va_arg(args, char *);
783 	format = va_arg(args, char *);
784 #endif
785 	vsprintf(string, format, args);
786 	return strlen(string);
787 }
788 
789 #endif
790 
791 void
u_sleep(usec)792 u_sleep(usec)
793 	int usec;
794 {
795 	struct timeval t;
796 	fd_set fdset;
797 
798 	FD_ZERO(&fdset);
799 
800 	t.tv_sec = 0;
801 	t.tv_usec = usec * 1000;
802 
803 	select(0, &fdset, &fdset, &fdset, &t);
804 }
805 
806 /*
807  * Set fd blocking and non-blocking
808  */
809 
810 void
fd_nonblock(fd)811 fd_nonblock(fd)
812 	int fd;
813 {
814 #if defined USE_FIONBIO && defined FIONBIO
815 	ioctlsockopt_t opt = 1;
816 
817 	ioctlsocket(fd, FIONBIO, &opt);
818 #else
819 	int opt;
820 
821 	opt = fcntl(fd, F_GETFL, 0);
822 	opt |= O_NONBLOCK;
823 	fcntl(fd, F_SETFL, opt);
824 #endif
825 }
826 
827 void
fd_block(fd)828 fd_block(fd)
829 	int fd;
830 {
831 #if defined USE_FIONBIO && defined FIONBIO
832 	ioctlsockopt_t opt = 0;
833 
834 	ioctlsocket(fd, FIONBIO, &opt);
835 #else
836 	int opt;
837 
838 	opt = fcntl(fd, F_GETFL, 0);
839 	opt &= ~O_NONBLOCK;
840 	fcntl(fd, F_SETFL, opt);
841 #endif
842 }
843 
844 
845 #if 0
846 /*
847  * invoke RSH
848  */
849 int
850 rsh_exec(so,ns, user, host, args)
851 	struct SLIRPsocket *so;
852 	struct SLIRPsocket *ns;
853 	char *user;
854 	char *host;
855 	char *args;
856 {
857 	int fd[2];
858 	int fd0[2];
859 	int s;
860 	char buff[256];
861 
862 	DEBUG_CALL("rsh_exec");
863 	DEBUG_ARG("so = %lx", (long)so);
864 
865 	if (pipe(fd)<0) {
866           lprint("Error: pipe failed: %s\n", strerror(errno));
867           return 0;
868 	}
869 /* #ifdef HAVE_SOCKETPAIR */
870 #if 1
871         if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) {
872           close(fd[0]);
873           close(fd[1]);
874           lprint("Error: openpty failed: %s\n", strerror(errno));
875           return 0;
876         }
877 #else
878         if (slirp_openpty(&fd0[0], &fd0[1]) == -1) {
879           close(fd[0]);
880           close(fd[1]);
881           lprint("Error: openpty failed: %s\n", strerror(errno));
882           return 0;
883         }
884 #endif
885 
886 	switch(fork()) {
887 	 case -1:
888            lprint("Error: fork failed: %s\n", strerror(errno));
889            close(fd[0]);
890            close(fd[1]);
891            close(fd0[0]);
892            close(fd0[1]);
893            return 0;
894 
895 	 case 0:
896            close(fd[0]);
897            close(fd0[0]);
898 
899 		/* Set the DISPLAY */
900            if (x_port >= 0) {
901 #ifdef HAVE_SETENV
902              sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
903              setenv("DISPLAY", buff, 1);
904 #else
905              sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
906              putenv(buff);
907 #endif
908            }
909 
910            dup2(fd0[1], 0);
911            dup2(fd0[1], 1);
912            dup2(fd[1], 2);
913            for (s = 3; s <= 255; s++)
914              close(s);
915 
916            execlp("rsh","rsh","-l", user, host, args, NULL);
917 
918            /* Ooops, failed, let's tell the user why */
919 
920            sprintf(buff, "Error: execlp of %s failed: %s\n",
921                    "rsh", strerror(errno));
922            write(2, buff, strlen(buff)+1);
923            close(0); close(1); close(2); /* XXX */
924            exit(1);
925 
926         default:
927           close(fd[1]);
928           close(fd0[1]);
929           ns->s=fd[0];
930           so->s=fd0[0];
931 
932           return 1;
933 	}
934 }
935 #endif
936