fix OneNAND erase/write
[qemu] / slirp / misc.c
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
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
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
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
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 *
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
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
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
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 *
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
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__
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
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
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__
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
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
777 fd_nonblock(int fd)
778 {
779 #ifdef FIONBIO
780 #ifdef _WIN32
781         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
797 fd_block(int fd)
798 {
799 #ifdef FIONBIO
800         int opt = 0;
801
802         ioctlsocket(fd, FIONBIO, &opt);
803 #else
804         int opt;
805
806         opt = fcntl(fd, F_GETFL, 0);
807         opt &= ~O_NONBLOCK;
808         fcntl(fd, F_SETFL, opt);
809 #endif
810 }
811
812
813 #if 0
814 /*
815  * invoke RSH
816  */
817 int
818 rsh_exec(so,ns, user, host, args)
819         struct socket *so;
820         struct socket *ns;
821         char *user;
822         char *host;
823         char *args;
824 {
825         int fd[2];
826         int fd0[2];
827         int s;
828         char buff[256];
829
830         DEBUG_CALL("rsh_exec");
831         DEBUG_ARG("so = %lx", (long)so);
832
833         if (pipe(fd)<0) {
834           lprint("Error: pipe failed: %s\n", strerror(errno));
835           return 0;
836         }
837 /* #ifdef HAVE_SOCKETPAIR */
838 #if 1
839         if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) {
840           close(fd[0]);
841           close(fd[1]);
842           lprint("Error: openpty failed: %s\n", strerror(errno));
843           return 0;
844         }
845 #else
846         if (slirp_openpty(&fd0[0], &fd0[1]) == -1) {
847           close(fd[0]);
848           close(fd[1]);
849           lprint("Error: openpty failed: %s\n", strerror(errno));
850           return 0;
851         }
852 #endif
853
854         switch(fork()) {
855          case -1:
856            lprint("Error: fork failed: %s\n", strerror(errno));
857            close(fd[0]);
858            close(fd[1]);
859            close(fd0[0]);
860            close(fd0[1]);
861            return 0;
862
863          case 0:
864            close(fd[0]);
865            close(fd0[0]);
866
867                 /* Set the DISPLAY */
868            if (x_port >= 0) {
869 #ifdef HAVE_SETENV
870              sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
871              setenv("DISPLAY", buff, 1);
872 #else
873              sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
874              putenv(buff);
875 #endif
876            }
877
878            dup2(fd0[1], 0);
879            dup2(fd0[1], 1);
880            dup2(fd[1], 2);
881            for (s = 3; s <= 255; s++)
882              close(s);
883
884            execlp("rsh","rsh","-l", user, host, args, NULL);
885
886            /* Ooops, failed, let's tell the user why */
887
888            sprintf(buff, "Error: execlp of %s failed: %s\n",
889                    "rsh", strerror(errno));
890            write(2, buff, strlen(buff)+1);
891            close(0); close(1); close(2); /* XXX */
892            exit(1);
893
894         default:
895           close(fd[1]);
896           close(fd0[1]);
897           ns->s=fd[0];
898           so->s=fd0[0];
899
900           return 1;
901         }
902 }
903 #endif