syslimits.h fix for OSX
[vde.git] / vde-2 / slirpvde / misc.c
blobefa24fe58bcb125f8eb0e029d80431c9d02559e8
1 /*
2 * Copyright (c) 1995 Danny Gasparovski.
3 *
4 * Please read the file COPYRIGHT for the
5 * terms and conditions of the copyright.
6 */
8 #define WANT_SYS_IOCTL_H
9 #include <config.h>
10 #include <slirp.h>
12 u_int curtime, time_fasttimo, last_slowtimo, detach_time;
13 u_int detach_wait = 600000; /* 10 minutes */
15 int x_port = -1;
16 int x_display = 0;
17 int x_screen = 0;
19 int
20 show_x()
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);
33 return 0;
38 * XXX Allow more than one X redirection?
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;
47 int i;
49 if (x_port >= 0) {
50 lprint("X Redir: X already being redirected.\r\n");
51 show_x();
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();
60 return;
63 lprint("X Redir: Error: Couldn't redirect a port for X. Weird.\r\n");
67 void redir_tcp(inaddr, port, lport)
68 u_int32_t inaddr;
69 int port;
70 int lport;
72 struct socket *so;
74 if ((so=solisten(htons(lport), inaddr, htons(port), 0)) != NULL) {
75 lprint("Redirecting TCP port %d to %s:%d\r\n",
76 ntohs(so->so_fport), inet_ntoa(so->so_laddr), port);
77 } else
78 lprint("Redirection failed: %s\r\n", strerror(errno));
81 #ifndef HAVE_INET_ATON
82 int
83 inet_aton(cp, ia)
84 const char *cp;
85 struct in_addr *ia;
87 u_int32_t addr = inet_addr(cp);
88 if (addr == 0xffffffff)
89 return 0;
90 ia->s_addr = addr;
91 return 1;
93 #endif
96 * Get our IP address and put it in our_addr
98 void
99 getouraddr()
101 char buff[256];
102 struct hostent *he;
104 if (gethostname(buff,256) < 0)
105 return;
107 if ((he = gethostbyname(buff)) == NULL)
108 return;
110 our_addr = *(struct in_addr *)he->h_addr;
113 #if SIZEOF_CHAR_P == 8
115 struct quehead_32 {
116 u_int32_t qh_link;
117 u_int32_t qh_rlink;
120 inline void
121 insque_32(a, b)
122 void *a;
123 void *b;
125 register struct quehead_32 *element = (struct quehead_32 *) a;
126 register struct quehead_32 *head = (struct quehead_32 *) b;
127 element->qh_link = head->qh_link;
128 head->qh_link = (u_int32_t)element;
129 element->qh_rlink = (u_int32_t)head;
130 ((struct quehead_32 *)(element->qh_link))->qh_rlink
131 = (u_int32_t)element;
134 inline void
135 remque_32(void *a)
137 register struct quehead_32 *element = (struct quehead_32 *) a;
138 ((struct quehead_32 *)(element->qh_link))->qh_rlink = element->qh_rlink;
139 ((struct quehead_32 *)(element->qh_rlink))->qh_link = element->qh_link;
140 element->qh_rlink = 0;
143 #endif /* SIZEOF_CHAR_P == 8 */
145 struct quehead {
146 struct quehead *qh_link;
147 struct quehead *qh_rlink;
150 inline void
151 insque(a, b)
152 void *a, *b;
154 register struct quehead *element = (struct quehead *) a;
155 register struct quehead *head = (struct quehead *) b;
156 element->qh_link = head->qh_link;
157 head->qh_link = (struct quehead *)element;
158 element->qh_rlink = (struct quehead *)head;
159 ((struct quehead *)(element->qh_link))->qh_rlink
160 = (struct quehead *)element;
163 inline void
164 remque(a)
165 void *a;
167 register struct quehead *element = (struct quehead *) a;
168 ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
169 ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
170 element->qh_rlink = NULL;
171 /* element->qh_link = NULL; TCP FIN1 crashes if you do this. Why ? */
174 /* #endif */
178 add_exec(ex_ptr, do_pty, exec, addr, port)
179 struct ex_list **ex_ptr;
180 int do_pty;
181 char *exec;
182 int addr;
183 int port;
185 struct ex_list *tmp_ptr;
187 /* First, check if the port is "bound" */
188 for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
189 if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
190 return -1;
193 tmp_ptr = *ex_ptr;
194 *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
195 (*ex_ptr)->ex_fport = port;
196 (*ex_ptr)->ex_addr = addr;
197 (*ex_ptr)->ex_pty = do_pty;
198 (*ex_ptr)->ex_exec = strdup(exec);
199 (*ex_ptr)->ex_next = tmp_ptr;
200 return 0;
203 #ifndef HAVE_STRERROR
206 * For systems with no strerror
209 extern int sys_nerr;
210 extern char *sys_errlist[];
212 char *
213 strerror(error)
214 int error;
216 if (error < sys_nerr)
217 return sys_errlist[error];
218 else
219 return "Unknown error.";
222 #endif
225 #if 0
227 openpty(amaster, aslave)
228 int *amaster, *aslave;
230 register int master, slave;
232 #ifdef HAVE_GRANTPT
233 char *ptr;
235 if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
236 grantpt(master) < 0 ||
237 unlockpt(master) < 0 ||
238 (ptr = ptsname(master)) == NULL) {
239 close(master);
240 return -1;
243 if ((slave = open(ptr, O_RDWR)) < 0 ||
244 ioctl(slave, I_PUSH, "ptem") < 0 ||
245 ioctl(slave, I_PUSH, "ldterm") < 0 ||
246 ioctl(slave, I_PUSH, "ttcompat") < 0) {
247 close(master);
248 close(slave);
249 return -1;
252 *amaster = master;
253 *aslave = slave;
254 return 0;
256 #else
258 static char line[] = "/dev/ptyXX";
259 register const char *cp1, *cp2;
261 for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
262 line[8] = *cp1;
263 for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
264 line[9] = *cp2;
265 if ((master = open(line, O_RDWR, 0)) == -1) {
266 if (errno == ENOENT)
267 return (-1); /* out of ptys */
268 } else {
269 line[5] = 't';
270 /* These will fail */
271 (void) chown(line, getuid(), 0);
272 (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
273 #ifdef HAVE_REVOKE
274 (void) revoke(line);
275 #endif
276 if ((slave = open(line, O_RDWR, 0)) != -1) {
277 *amaster = master;
278 *aslave = slave;
279 return 0;
281 (void) close(master);
282 line[5] = 'p';
286 errno = ENOENT; /* out of ptys */
287 return (-1);
288 #endif
292 * XXX This is ugly
293 * We create and bind a socket, then fork off to another
294 * process, which connects to this socket, after which we
295 * exec the wanted program. If something (strange) happens,
296 * the accept() call could block us forever.
298 * do_pty = 0 Fork/exec inetd style
299 * do_pty = 1 Fork/exec using slirp.telnetd
300 * do_ptr = 2 Fork/exec using pty
303 fork_exec(so, ex, do_pty)
304 struct socket *so;
305 char *ex;
306 int do_pty;
308 int s;
309 struct sockaddr_in addr;
310 int addrlen = sizeof(addr);
311 int opt;
312 int master;
313 char *argv[256];
314 char buff[256];
315 /* don't want to clobber the original */
316 char *bptr;
317 char *curarg;
318 int c, i;
320 DEBUG_CALL("fork_exec");
321 DEBUG_ARG("so = %lx", (long)so);
322 DEBUG_ARG("ex = %lx", (long)ex);
323 DEBUG_ARG("do_pty = %lx", (long)do_pty);
325 if (do_pty == 2) {
326 if (openpty(&master, &s) == -1) {
327 lprint("Error: openpty failed: %s\n", strerror(errno));
328 return 0;
330 } else {
331 addr.sin_family = AF_INET;
332 addr.sin_port = 0;
333 addr.sin_addr.s_addr = INADDR_ANY;
335 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
336 bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
337 listen(s, 1) < 0) {
338 lprint("Error: inet socket: %s\n", strerror(errno));
339 close(s);
341 return 0;
345 switch(fork()) {
346 case -1:
347 lprint("Error: fork failed: %s\n", strerror(errno));
348 close(s);
349 if (do_pty == 2)
350 close(master);
351 return 0;
353 case 0:
354 /* Set the DISPLAY */
355 if (do_pty == 2) {
356 (void) close(master);
357 #ifdef TIOCSCTTY /* XXXXX */
358 (void) setsid();
359 ioctl(s, TIOCSCTTY, (char *)NULL);
360 #endif
361 } else {
362 getsockname(s, (struct sockaddr *)&addr, &addrlen);
363 close(s);
365 * Connect to the socket
366 * XXX If any of these fail, we're in trouble!
368 s = socket(AF_INET, SOCK_STREAM, 0);
369 addr.sin_addr = loopback_addr;
370 connect(s, (struct sockaddr *)&addr, addrlen);
373 if (x_port >= 0) {
374 #ifdef HAVE_SETENV
375 sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
376 setenv("DISPLAY", buff, 1);
377 #else
378 sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
379 putenv(buff);
380 #endif
383 dup2(s, 0);
384 dup2(s, 1);
385 dup2(s, 2);
386 for (s = 3; s <= 255; s++)
387 close(s);
389 i = 0;
390 bptr = strdup(ex); /* No need to free() this */
391 if (do_pty == 1) {
392 /* Setup "slirp.telnetd -x" */
393 argv[i++] = "slirp.telnetd";
394 argv[i++] = "-x";
395 argv[i++] = bptr;
396 } else
397 do {
398 /* Change the string into argv[] */
399 curarg = bptr;
400 while (*bptr != ' ' && *bptr != (char)0)
401 bptr++;
402 c = *bptr;
403 *bptr++ = (char)0;
404 argv[i++] = strdup(curarg);
405 } while (c);
407 argv[i] = 0;
408 execvp(argv[0], argv);
410 /* Ooops, failed, let's tell the user why */
412 char buff[256];
414 sprintf(buff, "Error: execvp of %s failed: %s\n",
415 argv[0], strerror(errno));
416 write(2, buff, strlen(buff)+1);
418 close(0); close(1); close(2); /* XXX */
419 exit(1);
421 default:
422 if (do_pty == 2) {
423 close(s);
424 so->s = master;
425 } else {
427 * XXX this could block us...
428 * XXX Should set a timer here, and if accept() doesn't
429 * return after X seconds, declare it a failure
430 * The only reason this will block forever is if socket()
431 * of connect() fail in the child process
433 so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
434 close(s);
435 opt = 1;
436 setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
437 opt = 1;
438 setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
440 fd_nonblock(so->s);
442 /* Append the telnet options now */
443 if (so->so_m != 0 && do_pty == 1) {
444 sbappend(so, so->so_m);
445 so->so_m = 0;
448 return 1;
451 #endif
453 #ifndef HAVE_STRDUP
454 char *
455 strdup(str)
456 const char *str;
458 char *bptr;
460 bptr = (char *)malloc(strlen(str)+1);
461 strcpy(bptr, str);
463 return bptr;
465 #endif
467 #if 0
468 void
469 snooze_hup(num)
470 int num;
472 int s, ret;
473 #ifndef NO_UNIX_SOCKETS
474 struct sockaddr_un sock_un;
475 #endif
476 struct sockaddr_in sock_in;
477 char buff[256];
479 ret = -1;
480 if (slirp_socket_passwd) {
481 s = socket(AF_INET, SOCK_STREAM, 0);
482 if (s < 0)
483 slirp_exit(1);
484 sock_in.sin_family = AF_INET;
485 sock_in.sin_addr.s_addr = slirp_socket_addr;
486 sock_in.sin_port = htons(slirp_socket_port);
487 if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0)
488 slirp_exit(1); /* just exit...*/
489 sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit);
490 write(s, buff, strlen(buff)+1);
492 #ifndef NO_UNIX_SOCKETS
493 else {
494 s = socket(AF_UNIX, SOCK_STREAM, 0);
495 if (s < 0)
496 slirp_exit(1);
497 sock_un.sun_family = AF_UNIX;
498 strcpy(sock_un.sun_path, socket_path);
499 if (connect(s, (struct sockaddr *)&sock_un,
500 sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0)
501 slirp_exit(1);
502 sprintf(buff, "kill none:%d", slirp_socket_unit);
503 write(s, buff, strlen(buff)+1);
505 #endif
506 slirp_exit(0);
510 void
511 snooze()
513 sigset_t s;
514 int i;
516 /* Don't need our data anymore */
517 /* XXX This makes SunOS barf */
518 /* brk(0); */
520 /* Close all fd's */
521 for (i = 255; i >= 0; i--)
522 close(i);
524 signal(SIGQUIT, slirp_exit);
525 signal(SIGHUP, snooze_hup);
526 sigemptyset(&s);
528 /* Wait for any signal */
529 sigsuspend(&s);
531 /* Just in case ... */
532 exit(255);
535 void
536 relay(s)
537 int s;
539 char buf[8192];
540 int n;
541 fd_set readfds;
542 struct ttys *ttyp;
544 /* Don't need our data anymore */
545 /* XXX This makes SunOS barf */
546 /* brk(0); */
548 signal(SIGQUIT, slirp_exit);
549 signal(SIGHUP, slirp_exit);
550 signal(SIGINT, slirp_exit);
551 signal(SIGTERM, slirp_exit);
553 /* Fudge to get term_raw and term_restore to work */
554 if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
555 lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
556 slirp_exit (1);
558 ttyp->fd = 0;
559 ttyp->flags |= TTY_CTTY;
560 term_raw(ttyp);
562 while (1) {
563 FD_ZERO(&readfds);
565 FD_SET(0, &readfds);
566 FD_SET(s, &readfds);
568 n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
570 if (n <= 0)
571 slirp_exit(0);
573 if (FD_ISSET(0, &readfds)) {
574 n = read(0, buf, 8192);
575 if (n <= 0)
576 slirp_exit(0);
577 n = writen(s, buf, n);
578 if (n <= 0)
579 slirp_exit(0);
582 if (FD_ISSET(s, &readfds)) {
583 n = read(s, buf, 8192);
584 if (n <= 0)
585 slirp_exit(0);
586 n = writen(0, buf, n);
587 if (n <= 0)
588 slirp_exit(0);
592 /* Just in case.... */
593 exit(1);
595 #endif
597 int (*lprint_print) _P((void *, const char *, va_list));
598 char *lprint_ptr, *lprint_ptr2, **lprint_arg;
600 void
601 #ifdef __STDC__
602 lprint(const char *format, ...)
603 #else
604 lprint(va_alist) va_dcl
605 #endif
607 va_list args;
609 #ifdef __STDC__
610 va_start(args, format);
611 #else
612 char *format;
613 va_start(args);
614 format = va_arg(args, char *);
615 #endif
616 #if 0
617 /* If we're printing to an sbuf, make sure there's enough room */
618 /* XXX +100? */
619 if (lprint_sb) {
620 if ((lprint_ptr - lprint_sb->sb_wptr) >=
621 (lprint_sb->sb_datalen - (strlen(format) + 100))) {
622 int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data;
623 int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data;
624 int deltap = lprint_ptr - lprint_sb->sb_data;
626 lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
627 lprint_sb->sb_datalen + TCP_SNDSPACE);
629 /* Adjust all values */
630 lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw;
631 lprint_sb->sb_rptr = lprint_sb->sb_data + deltar;
632 lprint_ptr = lprint_sb->sb_data + deltap;
634 lprint_sb->sb_datalen += TCP_SNDSPACE;
637 #endif
638 if (lprint_print)
639 lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
641 /* Check if they want output to be logged to file as well */
642 if (lfd) {
644 * Remove \r's
645 * otherwise you'll get ^M all over the file
647 int len = strlen(format);
648 char *bptr1, *bptr2;
650 bptr1 = bptr2 = strdup(format);
652 while (len--) {
653 if (*bptr1 == '\r')
654 memcpy(bptr1, bptr1+1, len+1);
655 else
656 bptr1++;
658 vfprintf(lfd, bptr2, args);
659 free(bptr2);
661 va_end(args);
664 void
665 add_emu(buff)
666 char *buff;
668 u_int lport, fport;
669 u_int8_t tos = 0, emu = 0;
670 char buff1[256], buff2[256], buff4[128];
671 char *buff3 = buff4;
672 struct emu_t *emup;
673 struct socket *so;
675 if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
676 lprint("Error: Bad arguments\r\n");
677 return;
680 if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) {
681 lport = 0;
682 if (sscanf(buff1, "%d", &fport) != 1) {
683 lprint("Error: Bad first argument\r\n");
684 return;
688 if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) {
689 buff3 = 0;
690 if (sscanf(buff2, "%256s", buff1) != 1) {
691 lprint("Error: Bad second argument\r\n");
692 return;
696 if (buff3) {
697 if (strcmp(buff3, "lowdelay") == 0)
698 tos = IPTOS_LOWDELAY;
699 else if (strcmp(buff3, "throughput") == 0)
700 tos = IPTOS_THROUGHPUT;
701 else {
702 lprint("Error: Expecting \"lowdelay\"/\"throughput\"\r\n");
703 return;
707 if (strcmp(buff1, "ftp") == 0)
708 emu = EMU_FTP;
709 else if (strcmp(buff1, "irc") == 0)
710 emu = EMU_IRC;
711 else if (strcmp(buff1, "none") == 0)
712 emu = EMU_NONE; /* ie: no emulation */
713 else {
714 lprint("Error: Unknown service\r\n");
715 return;
718 /* First, check that it isn't already emulated */
719 for (emup = tcpemu; emup; emup = emup->next) {
720 if (emup->lport == lport && emup->fport == fport) {
721 lprint("Error: port already emulated\r\n");
722 return;
726 /* link it */
727 emup = (struct emu_t *)malloc(sizeof (struct emu_t));
728 emup->lport = (u_int16_t)lport;
729 emup->fport = (u_int16_t)fport;
730 emup->tos = tos;
731 emup->emu = emu;
732 emup->next = tcpemu;
733 tcpemu = emup;
735 /* And finally, mark all current sessions, if any, as being emulated */
736 for (so = tcb.so_next; so != &tcb; so = so->so_next) {
737 if ((lport && lport == ntohs(so->so_lport)) ||
738 (fport && fport == ntohs(so->so_fport))) {
739 if (emu)
740 so->so_emu = emu;
741 if (tos)
742 so->so_iptos = tos;
746 lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
749 #ifdef BAD_SPRINTF
751 #undef vsprintf
752 #undef sprintf
755 * Some BSD-derived systems have a sprintf which returns char *
759 vsprintf_len(string, format, args)
760 char *string;
761 const char *format;
762 va_list args;
764 vsprintf(string, format, args);
765 return strlen(string);
769 #ifdef __STDC__
770 sprintf_len(char *string, const char *format, ...)
771 #else
772 sprintf_len(va_alist) va_dcl
773 #endif
775 va_list args;
776 #ifdef __STDC__
777 va_start(args, format);
778 #else
779 char *string;
780 char *format;
781 va_start(args);
782 string = va_arg(args, char *);
783 format = va_arg(args, char *);
784 #endif
785 vsprintf(string, format, args);
786 return strlen(string);
789 #endif
791 void
792 u_sleep(usec)
793 int usec;
795 struct timeval t;
796 fd_set fdset;
798 FD_ZERO(&fdset);
800 t.tv_sec = 0;
801 t.tv_usec = usec * 1000;
803 select(0, &fdset, &fdset, &fdset, &t);
807 * Set fd blocking and non-blocking
810 void
811 fd_nonblock(fd)
812 int fd;
814 #ifdef FIONBIO
815 int opt = 1;
817 ioctl(fd, FIONBIO, &opt);
818 #else
819 int opt;
821 opt = fcntl(fd, F_GETFL, 0);
822 opt |= O_NONBLOCK;
823 fcntl(fd, F_SETFL, opt);
824 #endif
827 void
828 fd_block(fd)
829 int fd;
831 #ifdef FIONBIO
832 int opt = 0;
834 ioctl(fd, FIONBIO, &opt);
835 #else
836 int opt;
838 opt = fcntl(fd, F_GETFL, 0);
839 opt &= ~O_NONBLOCK;
840 fcntl(fd, F_SETFL, opt);
841 #endif
845 #if 0
847 * invoke RSH
850 rsh_exec(so,ns, user, host, args)
851 struct socket *so;
852 struct socket *ns;
853 char *user;
854 char *host;
855 char *args;
857 int fd[2];
858 int fd0[2];
859 int s;
860 char buff[256];
862 DEBUG_CALL("rsh_exec");
863 DEBUG_ARG("so = %lx", (long)so);
865 if (pipe(fd)<0) {
866 lprint("Error: pipe failed: %s\n", strerror(errno));
867 return 0;
869 /* #ifdef HAVE_SOCKETPAIR */
870 #if 1
871 if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) {
872 close(fd[0]);
873 close(fd[1]);
874 lprint("Error: openpty failed: %s\n", strerror(errno));
875 return 0;
877 #else
878 if (openpty(&fd0[0], &fd0[1]) == -1) {
879 close(fd[0]);
880 close(fd[1]);
881 lprint("Error: openpty failed: %s\n", strerror(errno));
882 return 0;
884 #endif
886 switch(fork()) {
887 case -1:
888 lprint("Error: fork failed: %s\n", strerror(errno));
889 close(fd[0]);
890 close(fd[1]);
891 close(fd0[0]);
892 close(fd0[1]);
893 return 0;
895 case 0:
896 close(fd[0]);
897 close(fd0[0]);
899 /* Set the DISPLAY */
900 if (x_port >= 0) {
901 #ifdef HAVE_SETENV
902 sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
903 setenv("DISPLAY", buff, 1);
904 #else
905 sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
906 putenv(buff);
907 #endif
910 dup2(fd0[1], 0);
911 dup2(fd0[1], 1);
912 dup2(fd[1], 2);
913 for (s = 3; s <= 255; s++)
914 close(s);
916 execlp("rsh","rsh","-l", user, host, args, NULL);
918 /* Ooops, failed, let's tell the user why */
920 sprintf(buff, "Error: execlp of %s failed: %s\n",
921 "rsh", strerror(errno));
922 write(2, buff, strlen(buff)+1);
923 close(0); close(1); close(2); /* XXX */
924 exit(1);
926 default:
927 close(fd[1]);
928 close(fd0[1]);
929 ns->s=fd[0];
930 so->s=fd0[0];
932 return 1;
935 #endif