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 
    331 			  snprintf(buff, sizeof(buff),
    332                                    "Error: execvp of %s failed: %s\n",
    333                                    argv[0], strerror(errno));
    334 			  write(2, buff, strlen(buff)+1);
    335 		  }
    336 		close(0); close(1); close(2); /* XXX */
    337 		exit(1);
    338 
    339 	 default:
    340 		if (do_pty == 2) {
    341 			close(s);
    342 			so->s = master;
    343 		} else {
    344 			/*
    345 			 * XXX this could block us...
    346 			 * XXX Should set a timer here, and if accept() doesn't
    347 		 	 * return after X seconds, declare it a failure
    348 		 	 * The only reason this will block forever is if socket()
    349 		 	 * of connect() fail in the child process
    350 		 	 */
    351              so->s = socket_accept(s, NULL);
    352 			 socket_set_xreuseaddr(so->s);
    353              socket_set_oobinline(so->s);
    354 		}
    355 		socket_set_nonblock(so->s);
    356 
    357 		/* Append the telnet options now */
    358                 if (so->so_m != NULL && do_pty == 1)  {
    359 			sbappend(so, so->so_m);
    360                         so->so_m = NULL;
    361 		}
    362 
    363 		return 1;
    364 	}
    365 }
    366 #endif
    367 
    368 #ifndef HAVE_STRDUP
    369 char *
    370 strdup(const char*  str)
    371 {
    372 	char *bptr;
    373 	int   len = strlen(str);
    374 
    375 	bptr = (char *)malloc(len+1);
    376 	memcpy(bptr, str, len+1);
    377 
    378 	return bptr;
    379 }
    380 #endif
    381 
    382 #if 0
    383 void
    384 snooze_hup(num)
    385 	int num;
    386 {
    387 	int s, ret;
    388 #ifndef NO_UNIX_SOCKETS
    389 	struct sockaddr_un sock_un;
    390 #endif
    391 	struct sockaddr_in sock_in;
    392 	char buff[256];
    393 
    394 	ret = -1;
    395 	if (slirp_socket_passwd) {
    396 		s = socket(AF_INET, SOCK_STREAM, 0);
    397 		if (s < 0)
    398 		   slirp_exit(1);
    399 		sock_in.sin_family = AF_INET;
    400 		sock_in.sin_addr.s_addr = slirp_socket_addr;
    401 		sock_in.sin_port = htons(slirp_socket_port);
    402 		if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0)
    403 		   slirp_exit(1); /* just exit...*/
    404 		sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit);
    405 		write(s, buff, strlen(buff)+1);
    406 	}
    407 #ifndef NO_UNIX_SOCKETS
    408 	  else {
    409 		s = socket(AF_UNIX, SOCK_STREAM, 0);
    410 		if (s < 0)
    411 		   slirp_exit(1);
    412 		sock_un.sun_family = AF_UNIX;
    413 		strcpy(sock_un.sun_path, socket_path);
    414 		if (connect(s, (struct sockaddr *)&sock_un,
    415 			      sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0)
    416 		   slirp_exit(1);
    417 		sprintf(buff, "kill none:%d", slirp_socket_unit);
    418 		write(s, buff, strlen(buff)+1);
    419 	}
    420 #endif
    421 	slirp_exit(0);
    422 }
    423 
    424 
    425 void
    426 snooze()
    427 {
    428 	sigset_t s;
    429 	int i;
    430 
    431 	/* Don't need our data anymore */
    432 	/* XXX This makes SunOS barf */
    433 /*	brk(0); */
    434 
    435 	/* Close all fd's */
    436 	for (i = 255; i >= 0; i--)
    437 	   close(i);
    438 
    439 	signal(SIGQUIT, slirp_exit);
    440 	signal(SIGHUP, snooze_hup);
    441 	sigemptyset(&s);
    442 
    443 	/* Wait for any signal */
    444 	sigsuspend(&s);
    445 
    446 	/* Just in case ... */
    447 	exit(255);
    448 }
    449 
    450 void
    451 relay(s)
    452 	int s;
    453 {
    454 	char buf[8192];
    455 	int n;
    456 	fd_set readfds;
    457 	struct ttys *ttyp;
    458 
    459 	/* Don't need our data anymore */
    460 	/* XXX This makes SunOS barf */
    461 /*	brk(0); */
    462 
    463 	signal(SIGQUIT, slirp_exit);
    464 	signal(SIGHUP, slirp_exit);
    465         signal(SIGINT, slirp_exit);
    466 	signal(SIGTERM, slirp_exit);
    467 
    468 	/* Fudge to get term_raw and term_restore to work */
    469 	if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
    470          lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
    471          slirp_exit (1);
    472     }
    473 	ttyp->fd = 0;
    474 	ttyp->flags |= TTY_CTTY;
    475 	term_raw(ttyp);
    476 
    477 	while (1) {
    478 		FD_ZERO(&readfds);
    479 
    480 		FD_SET(0, &readfds);
    481 		FD_SET(s, &readfds);
    482 
    483 		n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
    484 
    485 		if (n <= 0)
    486 		   slirp_exit(0);
    487 
    488 		if (FD_ISSET(0, &readfds)) {
    489 			n = read(0, buf, 8192);
    490 			if (n <= 0)
    491 			   slirp_exit(0);
    492 			n = writen(s, buf, n);
    493 			if (n <= 0)
    494 			   slirp_exit(0);
    495 		}
    496 
    497 		if (FD_ISSET(s, &readfds)) {
    498 			n = read(s, buf, 8192);
    499 			if (n <= 0)
    500 			   slirp_exit(0);
    501 			n = writen(0, buf, n);
    502 			if (n <= 0)
    503 			   slirp_exit(0);
    504 		}
    505 	}
    506 
    507 	/* Just in case.... */
    508 	exit(1);
    509 }
    510 #endif
    511 
    512 #ifdef CONFIG_QEMU
    513 #include "monitor.h"
    514 
    515 void lprint(const char *format, ...)
    516 {
    517     va_list args;
    518 
    519     va_start(args, format);
    520     monitor_vprintf(cur_mon, format, args);
    521     va_end(args);
    522 }
    523 #else
    524 int (*lprint_print) _P((void *, const char *, va_list));
    525 char *lprint_ptr, *lprint_ptr2, **lprint_arg;
    526 
    527 void
    528 #ifdef __STDC__
    529 lprint(const char *format, ...)
    530 #else
    531 lprint(va_alist) va_dcl
    532 #endif
    533 {
    534 	va_list args;
    535 
    536 #ifdef __STDC__
    537         va_start(args, format);
    538 #else
    539         char *format;
    540         va_start(args);
    541         format = va_arg(args, char *);
    542 #endif
    543 #if 0
    544 	/* If we're printing to an sbuf, make sure there's enough room */
    545 	/* XXX +100? */
    546 	if (lprint_sb) {
    547 		if ((lprint_ptr - lprint_sb->sb_wptr) >=
    548 		    (lprint_sb->sb_datalen - (strlen(format) + 100))) {
    549 			int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
    550 			int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data;
    551 			int deltap = lprint_ptr -         lprint_sb->sb_data;
    552 
    553 			lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
    554 							     lprint_sb->sb_datalen + TCP_SNDSPACE);
    555 
    556 			/* Adjust all values */
    557 			lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
    558 			lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
    559 			lprint_ptr =         lprint_sb->sb_data + deltap;
    560 
    561 			lprint_sb->sb_datalen += TCP_SNDSPACE;
    562 		}
    563 	}
    564 #endif
    565 	if (lprint_print)
    566 	   lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
    567 
    568 	/* Check if they want output to be logged to file as well */
    569 	if (lfd) {
    570 		/*
    571 		 * Remove \r's
    572 		 * otherwise you'll get ^M all over the file
    573 		 */
    574 		int len = strlen(format);
    575 		char *bptr1, *bptr2;
    576 
    577 		bptr1 = bptr2 = strdup(format);
    578 
    579 		while (len--) {
    580 			if (*bptr1 == '\r')
    581 			   memcpy(bptr1, bptr1+1, len+1);
    582 			else
    583 			   bptr1++;
    584 		}
    585 		vfprintf(lfd, bptr2, args);
    586 		free(bptr2);
    587 	}
    588 	va_end(args);
    589 }
    590 
    591 void
    592 add_emu(buff)
    593 	char *buff;
    594 {
    595 	u_int lport, fport;
    596 	u_int8_t tos = 0, emu = 0;
    597 	char buff1[256], buff2[256], buff4[128];
    598 	char *buff3 = buff4;
    599 	struct emu_t *emup;
    600 	struct socket *so;
    601 
    602 	if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
    603 		lprint("Error: Bad arguments\r\n");
    604 		return;
    605 	}
    606 
    607 	if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
    608 		lport = 0;
    609 		if (sscanf(buff1, "%d", &fport) != 1) {
    610 			lprint("Error: Bad first argument\r\n");
    611 			return;
    612 		}
    613 	}
    614 
    615 	if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
    616 		buff3 = 0;
    617 		if (sscanf(buff2, "%256s", buff1) != 1) {
    618 			lprint("Error: Bad second argument\r\n");
    619 			return;
    620 		}
    621 	}
    622 
    623 	if (buff3) {
    624 		if (strcmp(buff3, "lowdelay") == 0)
    625 		   tos = IPTOS_LOWDELAY;
    626 		else if (strcmp(buff3, "throughput") == 0)
    627 		   tos = IPTOS_THROUGHPUT;
    628 		else {
    629 			lprint("Error: Expecting \"lowdelay\"/\"throughput\"\r\n");
    630 			return;
    631 		}
    632 	}
    633 
    634 	if (strcmp(buff1, "ftp") == 0)
    635 	   emu = EMU_FTP;
    636 	else if (strcmp(buff1, "irc") == 0)
    637 	   emu = EMU_IRC;
    638 	else if (strcmp(buff1, "none") == 0)
    639 	   emu = EMU_NONE; /* ie: no emulation */
    640 	else {
    641 		lprint("Error: Unknown service\r\n");
    642 		return;
    643 	}
    644 
    645 	/* First, check that it isn't already emulated */
    646 	for (emup = tcpemu; emup; emup = emup->next) {
    647 		if (emup->lport == lport && emup->fport == fport) {
    648 			lprint("Error: port already emulated\r\n");
    649 			return;
    650 		}
    651 	}
    652 
    653 	/* link it */
    654 	emup = (struct emu_t *)malloc(sizeof (struct emu_t));
    655 	emup->lport = (u_int16_t)lport;
    656 	emup->fport = (u_int16_t)fport;
    657 	emup->tos = tos;
    658 	emup->emu = emu;
    659 	emup->next = tcpemu;
    660 	tcpemu = emup;
    661 
    662 	/* And finally, mark all current sessions, if any, as being emulated */
    663 	for (so = tcb.so_next; so != &tcb; so = so->so_next) {
    664 		if ((lport && lport == so->so_laddr_port) ||
    665 		    (fport && fport == so->so_faddr_port)) {
    666 			if (emu)
    667 			   so->so_emu = emu;
    668 			if (tos)
    669 			   so->so_iptos = tos;
    670 		}
    671 	}
    672 
    673 	lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
    674 }
    675 #endif
    676 
    677 #ifdef BAD_SPRINTF
    678 
    679 #undef vsprintf
    680 #undef sprintf
    681 
    682 /*
    683  * Some BSD-derived systems have a sprintf which returns char *
    684  */
    685 
    686 int
    687 vsprintf_len(string, format, args)
    688 	char *string;
    689 	const char *format;
    690 	va_list args;
    691 {
    692 	vsprintf(string, format, args);
    693 	return strlen(string);
    694 }
    695 
    696 int
    697 #ifdef __STDC__
    698 sprintf_len(char *string, const char *format, ...)
    699 #else
    700 sprintf_len(va_alist) va_dcl
    701 #endif
    702 {
    703 	va_list args;
    704 #ifdef __STDC__
    705 	va_start(args, format);
    706 #else
    707 	char *string;
    708 	char *format;
    709 	va_start(args);
    710 	string = va_arg(args, char *);
    711 	format = va_arg(args, char *);
    712 #endif
    713 	vsprintf(string, format, args);
    714 	return strlen(string);
    715 }
    716 
    717 #endif
    718 
    719 #if 0
    720 void
    721 u_sleep(int usec)
    722 {
    723 	struct timeval t;
    724 	fd_set fdset;
    725 
    726 	FD_ZERO(&fdset);
    727 
    728 	t.tv_sec = 0;
    729 	t.tv_usec = usec * 1000;
    730 
    731 	select(0, &fdset, &fdset, &fdset, &t);
    732 }
    733 #endif
    734 
    735 /*
    736  * Set fd blocking and non-blocking
    737  */
    738 
    739 void
    740 fd_nonblock(int fd)
    741 {
    742 #ifdef FIONBIO
    743 #ifdef _WIN32
    744         unsigned long opt = 1;
    745 #else
    746         int opt = 1;
    747 #endif
    748 
    749 	ioctlsocket(fd, FIONBIO, &opt);
    750 #else
    751 	int opt;
    752 
    753 	opt = fcntl(fd, F_GETFL, 0);
    754 	opt |= O_NONBLOCK;
    755 	fcntl(fd, F_SETFL, opt);
    756 #endif
    757 }
    758 
    759 void
    760 fd_block(int fd)
    761 {
    762 #ifdef FIONBIO
    763 #ifdef _WIN32
    764         unsigned long opt = 0;
    765 #else
    766 	int opt = 0;
    767 #endif
    768 
    769 	ioctlsocket(fd, FIONBIO, &opt);
    770 #else
    771 	int opt;
    772 
    773 	opt = fcntl(fd, F_GETFL, 0);
    774 	opt &= ~O_NONBLOCK;
    775 	fcntl(fd, F_SETFL, opt);
    776 #endif
    777 }
    778 
    779 
    780 #if 0
    781 /*
    782  * invoke RSH
    783  */
    784 int
    785 rsh_exec(so,ns, user, host, args)
    786 	struct socket *so;
    787 	struct socket *ns;
    788 	char *user;
    789 	char *host;
    790 	char *args;
    791 {
    792 	int fd[2];
    793 	int fd0[2];
    794 	int s;
    795 	char buff[256];
    796 
    797 	DEBUG_CALL("rsh_exec");
    798 	DEBUG_ARG("so = %lx", (long)so);
    799 
    800 	if (pipe(fd)<0) {
    801           lprint("Error: pipe failed: %s\n", strerror(errno));
    802           return 0;
    803 	}
    804 /* #ifdef HAVE_SOCKETPAIR */
    805 #if 1
    806         if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) {
    807           close(fd[0]);
    808           close(fd[1]);
    809           lprint("Error: openpty failed: %s\n", strerror(errno));
    810           return 0;
    811         }
    812 #else
    813         if (slirp_openpty(&fd0[0], &fd0[1]) == -1) {
    814           close(fd[0]);
    815           close(fd[1]);
    816           lprint("Error: openpty failed: %s\n", strerror(errno));
    817           return 0;
    818         }
    819 #endif
    820 
    821 	switch(fork()) {
    822 	 case -1:
    823            lprint("Error: fork failed: %s\n", strerror(errno));
    824            close(fd[0]);
    825            close(fd[1]);
    826            close(fd0[0]);
    827            close(fd0[1]);
    828            return 0;
    829 
    830 	 case 0:
    831            close(fd[0]);
    832            close(fd0[0]);
    833 
    834 		/* Set the DISPLAY */
    835            if (x_port >= 0) {
    836 #ifdef HAVE_SETENV
    837              sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
    838              setenv("DISPLAY", buff, 1);
    839 #else
    840              sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
    841              putenv(buff);
    842 #endif
    843            }
    844 
    845            dup2(fd0[1], 0);
    846            dup2(fd0[1], 1);
    847            dup2(fd[1], 2);
    848            for (s = 3; s <= 255; s++)
    849              close(s);
    850 
    851            execlp("rsh","rsh","-l", user, host, args, NULL);
    852 
    853            /* Ooops, failed, let's tell the user why */
    854 
    855            sprintf(buff, "Error: execlp of %s failed: %s\n",
    856                    "rsh", strerror(errno));
    857            write(2, buff, strlen(buff)+1);
    858            close(0); close(1); close(2); /* XXX */
    859            exit(1);
    860 
    861         default:
    862           close(fd[1]);
    863           close(fd0[1]);
    864           ns->s=fd[0];
    865           so->s=fd0[0];
    866 
    867           return 1;
    868 	}
    869 }
    870 #endif
    871