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