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