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