• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
inet_strtoip(const char * str,uint32_t * ip)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 
inet_iptostr(uint32_t ip)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
getouraddr()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
insque(void * a,void * b)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
remque(void * a)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
add_exec(struct ex_list ** ex_ptr,int do_pty,char * exec,int addr,int port)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 *
strerror(error)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
fork_exec(struct socket * so,const char * ex,int do_pty)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
slirp_openpty(amaster,aslave)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
fork_exec(struct socket * so,const char * ex,int do_pty)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 *
strdup(const char * str)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.h"
517 
lprint(const char * format,...)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__
lprint(const char * format,...)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
add_emu(buff)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
vsprintf_len(string,format,args)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__
sprintf_len(char * string,const char * format,...)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
fd_nonblock(int fd)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
fd_block(int fd)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