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