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 <stdlib.h>
10 #include "slirp.h"
11
12 u_int curtime, time_fasttimo, last_slowtimo, detach_time;
13 u_int detach_wait = 600000; /* 10 minutes */
14
15 #if 0
16 int x_port = -1;
17 int x_display = 0;
18 int x_screen = 0;
19
20 int
21 show_x(buff, inso)
22 char *buff;
23 struct SLIRPsocket *inso;
24 {
25 if (x_port < 0) {
26 lprint("X Redir: X not being redirected.\r\n");
27 } else {
28 lprint("X Redir: In sh/bash/zsh/etc. type: DISPLAY=%s:%d.%d; export DISPLAY\r\n",
29 inet_ntoa(our_addr), x_port, x_screen);
30 lprint("X Redir: In csh/tcsh/etc. type: setenv DISPLAY %s:%d.%d\r\n",
31 inet_ntoa(our_addr), x_port, x_screen);
32 if (x_display)
33 lprint("X Redir: Redirecting to display %d\r\n", x_display);
34 }
35
36 return CFG_OK;
37 }
38
39
40 /*
41 * XXX Allow more than one X redirection?
42 */
43 void
44 redir_x(inaddr, start_port, display, screen)
45 u_int32_t inaddr;
46 int start_port;
47 int display;
48 int screen;
49 {
50 int i;
51
52 if (x_port >= 0) {
53 lprint("X Redir: X already being redirected.\r\n");
54 show_x(0, 0);
55 } else {
56 for (i = 6001 + (start_port-1); i <= 6100; i++) {
57 if (solisten(htons(i), inaddr, htons(6000 + display), 0)) {
58 /* Success */
59 x_port = i - 6000;
60 x_display = display;
61 x_screen = screen;
62 show_x(0, 0);
63 return;
64 }
65 }
66 lprint("X Redir: Error: Couldn't redirect a port for X. Weird.\r\n");
67 }
68 }
69 #endif
70
71 #ifndef HAVE_INET_ATON
72 int
inet_aton(cp,ia)73 inet_aton(cp, ia)
74 const char *cp;
75 struct in_addr *ia;
76 {
77 u_int32_t addr = inet_addr(cp);
78 if (addr == 0xffffffff)
79 return 0;
80 ia->s_addr = addr;
81 return 1;
82 }
83 #endif
84
85 /*
86 * Get our IP address and put it in our_addr
87 */
88 void
getouraddr()89 getouraddr()
90 {
91 char buff[512];
92 struct hostent *he = NULL;
93 #define ANCIENT
94 #ifdef ANCIENT
95 if (gethostname(&buff,500) == 0)
96 he = gethostbyname(&buff);
97 if (he)
98 our_addr = *(struct in_addr *)he->h_addr;
99 if (our_addr.s_addr == 0)
100 our_addr.s_addr = loopback_addr.s_addr;
101 #else
102 if (gethostname(buff,256) == 0)
103 {
104 struct addrinfo hints = { 0 };
105 hints.ai_flags = AI_NUMERICHOST;
106 hints.ai_family = AF_INET;
107 struct addrinfo* ai;
108 if (getaddrinfo(buff, NULL, &hints, &ai) == 0)
109 {
110 our_addr = *(struct in_addr *)ai->ai_addr->sa_data;
111 freeaddrinfo(ai);
112 }
113 }
114 if (our_addr.s_addr == 0)
115 our_addr.s_addr = loopback_addr.s_addr;
116 #endif
117 #undef ANCIENT
118 }
119
120 struct quehead {
121 struct quehead *qh_link;
122 struct quehead *qh_rlink;
123 };
124
125 void
insque(a,b)126 insque(a, b)
127 void *a, *b;
128 {
129 register struct quehead *element = (struct quehead *) a;
130 register struct quehead *head = (struct quehead *) b;
131 element->qh_link = head->qh_link;
132 head->qh_link = (struct quehead *)element;
133 element->qh_rlink = (struct quehead *)head;
134 ((struct quehead *)(element->qh_link))->qh_rlink
135 = (struct quehead *)element;
136 }
137
138 void
remque(a)139 remque(a)
140 void *a;
141 {
142 register struct quehead *element = (struct quehead *) a;
143 ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
144 ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
145 element->qh_rlink = NULL;
146 /* element->qh_link = NULL; TCP FIN1 crashes if you do this. Why ? */
147 }
148
149 /* #endif */
150
151
152 int
add_exec(ex_ptr,do_pty,exec,addr,port)153 add_exec(ex_ptr, do_pty, exec, addr, port)
154 struct ex_list **ex_ptr;
155 int do_pty;
156 char *exec;
157 int addr;
158 int port;
159 {
160 struct ex_list *tmp_ptr;
161
162 /* First, check if the port is "bound" */
163 for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
164 if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr)
165 return -1;
166 }
167
168 tmp_ptr = *ex_ptr;
169 *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list));
170 (*ex_ptr)->ex_fport = port;
171 (*ex_ptr)->ex_addr = addr;
172 (*ex_ptr)->ex_pty = do_pty;
173 (*ex_ptr)->ex_exec = strdup(exec);
174 (*ex_ptr)->ex_next = tmp_ptr;
175 return 0;
176 }
177
178 #ifndef HAVE_STRERROR
179
180 /*
181 * For systems with no strerror
182 */
183
184 #ifdef WIN32
185 //extern int sys_nerr;
186 //extern char *sys_errlist[];
187 #endif
188
189 char *
SLIRPstrerror(error)190 SLIRPstrerror(error)
191 int error;
192 {
193 if (error < sys_nerr)
194 return sys_errlist[error];
195 else
196 return "Unknown error.";
197 }
198
199 #endif
200
201
202 #ifdef _WIN32
203
204 int
fork_exec(so,ex,do_pty)205 fork_exec(so, ex, do_pty)
206 struct SLIRPsocket *so;
207 char *ex;
208 int do_pty;
209 {
210 /* not implemented */
211 return 0;
212 }
213
214 #else
215
216 int
slirp_openpty(amaster,aslave)217 slirp_openpty(amaster, aslave)
218 int *amaster, *aslave;
219 {
220 register int master, slave;
221
222 #ifdef HAVE_GRANTPT
223 char *ptr;
224
225 if ((master = open("/dev/ptmx", O_RDWR)) < 0 ||
226 grantpt(master) < 0 ||
227 unlockpt(master) < 0 ||
228 (ptr = ptsname(master)) == NULL) {
229 close(master);
230 return -1;
231 }
232
233 if ((slave = open(ptr, O_RDWR)) < 0 ||
234 ioctl(slave, I_PUSH, "ptem") < 0 ||
235 ioctl(slave, I_PUSH, "ldterm") < 0 ||
236 ioctl(slave, I_PUSH, "ttcompat") < 0) {
237 close(master);
238 close(slave);
239 return -1;
240 }
241
242 *amaster = master;
243 *aslave = slave;
244 return 0;
245
246 #else
247
248 static char line[] = "/dev/ptyXX";
249 register const char *cp1, *cp2;
250
251 for (cp1 = "pqrsPQRS"; *cp1; cp1++) {
252 line[8] = *cp1;
253 for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) {
254 line[9] = *cp2;
255 if ((master = open(line, O_RDWR, 0)) == -1) {
256 if (errno == ENOENT)
257 return (-1); /* out of ptys */
258 } else {
259 line[5] = 't';
260 /* These will fail */
261 (void) chown(line, getuid(), 0);
262 (void) chmod(line, S_IRUSR|S_IWUSR|S_IWGRP);
263 #ifdef HAVE_REVOKE
264 (void) revoke(line);
265 #endif
266 if ((slave = open(line, O_RDWR, 0)) != -1) {
267 *amaster = master;
268 *aslave = slave;
269 return 0;
270 }
271 (void) close(master);
272 line[5] = 'p';
273 }
274 }
275 }
276 errno = ENOENT; /* out of ptys */
277 return (-1);
278 #endif
279 }
280
281 /*
282 * XXX This is ugly
283 * We create and bind a socket, then fork off to another
284 * process, which connects to this socket, after which we
285 * exec the wanted program. If something (strange) happens,
286 * the accept() call could block us forever.
287 *
288 * do_pty = 0 Fork/exec inetd style
289 * do_pty = 1 Fork/exec using slirp.telnetd
290 * do_ptr = 2 Fork/exec using pty
291 */
292 int
fork_exec(so,ex,do_pty)293 fork_exec(so, ex, do_pty)
294 struct SLIRPsocket *so;
295 char *ex;
296 int do_pty;
297 {
298 int s;
299 struct sockaddr_in addr;
300 socklen_t addrlen = sizeof(addr);
301 int opt;
302 int master;
303 char *argv[256];
304 #if 0
305 char buff[256];
306 #endif
307 /* don't want to clobber the original */
308 char *bptr;
309 char *curarg;
310 int c, i, ret;
311
312 DEBUG_CALL("fork_exec");
313 DEBUG_ARG("so = %lx", (long)so);
314 DEBUG_ARG("ex = %lx", (long)ex);
315 DEBUG_ARG("do_pty = %lx", (long)do_pty);
316
317 if (do_pty == 2) {
318 if (slirp_openpty(&master, &s) == -1) {
319 lprint("Error: openpty failed: %s\n", strerror(errno));
320 return 0;
321 }
322 } else {
323 memset(&addr, 0, sizeof(struct sockaddr_in));
324 addr.sin_family = AF_INET;
325 addr.sin_port = 0;
326 addr.sin_addr.s_addr = INADDR_ANY;
327
328 if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
329 bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
330 listen(s, 1) < 0) {
331 lprint("Error: inet socket: %s\n", strerror(errno));
332 closesocket(s);
333
334 return 0;
335 }
336 }
337
338 switch(fork()) {
339 case -1:
340 lprint("Error: fork failed: %s\n", strerror(errno));
341 close(s);
342 if (do_pty == 2)
343 close(master);
344 return 0;
345
346 case 0:
347 /* Set the DISPLAY */
348 if (do_pty == 2) {
349 (void) close(master);
350 #ifdef TIOCSCTTY /* XXXXX */
351 (void) setsid();
352 ioctl(s, TIOCSCTTY, (char *)NULL);
353 #endif
354 } else {
355 getsockname(s, (struct sockaddr *)&addr, &addrlen);
356 close(s);
357 /*
358 * Connect to the socket
359 * XXX If any of these fail, we're in trouble!
360 */
361 s = socket(AF_INET, SOCK_STREAM, 0);
362 addr.sin_addr = loopback_addr;
363 do {
364 ret = connect(s, (struct sockaddr *)&addr, addrlen);
365 } while (ret < 0 && errno == EINTR);
366 }
367
368 #if 0
369 if (x_port >= 0) {
370 #ifdef HAVE_SETENV
371 sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
372 setenv("DISPLAY", buff, 1);
373 #else
374 sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
375 putenv(buff);
376 #endif
377 }
378 #endif
379 dup2(s, 0);
380 dup2(s, 1);
381 dup2(s, 2);
382 for (s = 3; s <= 255; s++)
383 close(s);
384
385 i = 0;
386 bptr = strdup(ex); /* No need to free() this */
387 if (do_pty == 1) {
388 /* Setup "slirp.telnetd -x" */
389 argv[i++] = "slirp.telnetd";
390 argv[i++] = "-x";
391 argv[i++] = bptr;
392 } else
393 do {
394 /* Change the string into argv[] */
395 curarg = bptr;
396 while (*bptr != ' ' && *bptr != (char)0)
397 bptr++;
398 c = *bptr;
399 *bptr++ = (char)0;
400 argv[i++] = strdup(curarg);
401 } while (c);
402
403 argv[i] = 0;
404 execvp(argv[0], argv);
405
406 /* Ooops, failed, let's tell the user why */
407 {
408 char buff[256];
409
410 sprintf(buff, "Error: execvp of %s failed: %s\n",
411 argv[0], strerror(errno));
412 write(2, buff, strlen(buff)+1);
413 }
414 close(0); close(1); close(2); /* XXX */
415 exit(1);
416
417 default:
418 if (do_pty == 2) {
419 close(s);
420 so->s = master;
421 } else {
422 /*
423 * XXX this could block us...
424 * XXX Should set a timer here, and if accept() doesn't
425 * return after X seconds, declare it a failure
426 * The only reason this will block forever is if socket()
427 * of connect() fail in the child process
428 */
429 do {
430 so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
431 } while (so->s < 0 && errno == EINTR);
432 closesocket(s);
433 opt = 1;
434 setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
435 opt = 1;
436 setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
437 }
438 fd_nonblock(so->s);
439
440 /* Append the telnet options now */
441 if (so->so_m != 0 && do_pty == 1) {
442 sbappend(so, so->so_m);
443 so->so_m = 0;
444 }
445
446 return 1;
447 }
448 }
449 #endif
450
451 #ifndef HAVE_STRDUP
strdup(char * str)452 char * strdup(char *str)
453 {
454 char *bptr;
455
456 bptr = (char *)malloc(strlen(str)+1);
457 strcpy(bptr, str);
458
459 return bptr;
460 }
461 #endif
462
463 #if 0
464 void
465 snooze_hup(num)
466 int num;
467 {
468 int s, ret;
469 #ifndef NO_UNIX_SOCKETS
470 struct sockaddr_un sock_un;
471 #endif
472 struct sockaddr_in sock_in;
473 char buff[256];
474
475 ret = -1;
476 if (slirp_socket_passwd) {
477 s = socket(AF_INET, SOCK_STREAM, 0);
478 if (s < 0)
479 slirp_exit(1);
480 sock_in.sin_family = AF_INET;
481 sock_in.sin_addr.s_addr = slirp_socket_addr;
482 sock_in.sin_port = htons(slirp_socket_port);
483 if (connect(s, (struct sockaddr *)&sock_in, sizeof(sock_in)) != 0)
484 slirp_exit(1); /* just exit...*/
485 sprintf(buff, "kill %s:%d", slirp_socket_passwd, slirp_socket_unit);
486 write(s, buff, strlen(buff)+1);
487 }
488 #ifndef NO_UNIX_SOCKETS
489 else {
490 s = socket(AF_UNIX, SOCK_STREAM, 0);
491 if (s < 0)
492 slirp_exit(1);
493 sock_un.sun_family = AF_UNIX;
494 strcpy(sock_un.sun_path, socket_path);
495 if (connect(s, (struct sockaddr *)&sock_un,
496 sizeof(sock_un.sun_family) + sizeof(sock_un.sun_path)) != 0)
497 slirp_exit(1);
498 sprintf(buff, "kill none:%d", slirp_socket_unit);
499 write(s, buff, strlen(buff)+1);
500 }
501 #endif
502 slirp_exit(0);
503 }
504
505
506 void
507 snooze()
508 {
509 sigset_t s;
510 int i;
511
512 /* Don't need our data anymore */
513 /* XXX This makes SunOS barf */
514 /* brk(0); */
515
516 /* Close all fd's */
517 for (i = 255; i >= 0; i--)
518 close(i);
519
520 signal(SIGQUIT, slirp_exit);
521 signal(SIGHUP, snooze_hup);
522 sigemptyset(&s);
523
524 /* Wait for any signal */
525 sigsuspend(&s);
526
527 /* Just in case ... */
528 exit(255);
529 }
530
531 void
532 relay(s)
533 int s;
534 {
535 char buf[8192];
536 int n;
537 fd_set readfds;
538 struct ttys *ttyp;
539
540 /* Don't need our data anymore */
541 /* XXX This makes SunOS barf */
542 /* brk(0); */
543
544 signal(SIGQUIT, slirp_exit);
545 signal(SIGHUP, slirp_exit);
546 signal(SIGINT, slirp_exit);
547 signal(SIGTERM, slirp_exit);
548
549 /* Fudge to get term_raw and term_restore to work */
550 if (NULL == (ttyp = tty_attach (0, slirp_tty))) {
551 lprint ("Error: tty_attach failed in misc.c:relay()\r\n");
552 slirp_exit (1);
553 }
554 ttyp->fd = 0;
555 ttyp->flags |= TTY_CTTY;
556 term_raw(ttyp);
557
558 while (1) {
559 FD_ZERO(&readfds);
560
561 FD_SET(0, &readfds);
562 FD_SET(s, &readfds);
563
564 n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
565
566 if (n <= 0)
567 slirp_exit(0);
568
569 if (FD_ISSET(0, &readfds)) {
570 n = read(0, buf, 8192);
571 if (n <= 0)
572 slirp_exit(0);
573 n = writen(s, buf, n);
574 if (n <= 0)
575 slirp_exit(0);
576 }
577
578 if (FD_ISSET(s, &readfds)) {
579 n = read(s, buf, 8192);
580 if (n <= 0)
581 slirp_exit(0);
582 n = writen(0, buf, n);
583 if (n <= 0)
584 slirp_exit(0);
585 }
586 }
587
588 /* Just in case.... */
589 exit(1);
590 }
591 #endif
592
593 int (*lprint_print) _P((void *, const char *, va_list));
594 char *lprint_ptr, *lprint_ptr2, **lprint_arg;
595
596 #ifdef _MSC_VER //aren't we
597 #define __STDC__
598 #endif
599
600 void
601 #ifdef __STDC__
lprint(const char * format,...)602 lprint(const char *format, ...)
603 #else
604 lprint(va_alist) va_dcl
605 #endif
606 {
607 va_list args;
608
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;
625
626 lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data,
627 lprint_sb->sb_datalen + TCP_SNDSPACE);
628
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;
633
634 lprint_sb->sb_datalen += TCP_SNDSPACE;
635 }
636 }
637 #endif
638 if (lprint_print)
639 lprint_ptr += (*lprint_print)(*lprint_arg, format, args);
640
641 /* Check if they want output to be logged to file as well */
642 if (lfd) {
643 /*
644 * Remove \r's
645 * otherwise you'll get ^M all over the file
646 */
647 int len = strlen(format);
648 char *bptr1, *bptr2;
649
650 bptr1 = bptr2 = strdup(format);
651
652 while (len--) {
653 if (*bptr1 == '\r')
654 memcpy(bptr1, bptr1+1, len+1);
655 else
656 bptr1++;
657 }
658 vfprintf(lfd, bptr2, args);
659 free(bptr2);
660 }
661 va_end(args);
662 }
663
664 void
add_emu(buff)665 add_emu(buff)
666 char *buff;
667 {
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 SLIRPsocket *so;
674
675 if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) {
676 lprint("Error: Bad arguments\r\n");
677 return;
678 }
679
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;
685 }
686 }
687
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;
693 }
694 }
695
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;
704 }
705 }
706
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;
716 }
717
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;
723 }
724 }
725
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;
734
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;
743 }
744 }
745
746 lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport);
747 }
748
749 #ifdef BAD_SPRINTF
750
751 #undef vsprintf
752 #undef sprintf
753
754 /*
755 * Some BSD-derived systems have a sprintf which returns char *
756 */
757
758 int
vsprintf_len(string,format,args)759 vsprintf_len(string, format, args)
760 char *string;
761 const char *format;
762 va_list args;
763 {
764 vsprintf(string, format, args);
765 return strlen(string);
766 }
767
768 int
769 #ifdef __STDC__
sprintf_len(char * string,const char * format,...)770 sprintf_len(char *string, const char *format, ...)
771 #else
772 sprintf_len(va_alist) va_dcl
773 #endif
774 {
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);
787 }
788
789 #endif
790
791 void
u_sleep(usec)792 u_sleep(usec)
793 int usec;
794 {
795 struct timeval t;
796 fd_set fdset;
797
798 FD_ZERO(&fdset);
799
800 t.tv_sec = 0;
801 t.tv_usec = usec * 1000;
802
803 select(0, &fdset, &fdset, &fdset, &t);
804 }
805
806 /*
807 * Set fd blocking and non-blocking
808 */
809
810 void
fd_nonblock(fd)811 fd_nonblock(fd)
812 int fd;
813 {
814 #if defined USE_FIONBIO && defined FIONBIO
815 ioctlsockopt_t opt = 1;
816
817 ioctlsocket(fd, FIONBIO, &opt);
818 #else
819 int opt;
820
821 opt = fcntl(fd, F_GETFL, 0);
822 opt |= O_NONBLOCK;
823 fcntl(fd, F_SETFL, opt);
824 #endif
825 }
826
827 void
fd_block(fd)828 fd_block(fd)
829 int fd;
830 {
831 #if defined USE_FIONBIO && defined FIONBIO
832 ioctlsockopt_t opt = 0;
833
834 ioctlsocket(fd, FIONBIO, &opt);
835 #else
836 int opt;
837
838 opt = fcntl(fd, F_GETFL, 0);
839 opt &= ~O_NONBLOCK;
840 fcntl(fd, F_SETFL, opt);
841 #endif
842 }
843
844
845 #if 0
846 /*
847 * invoke RSH
848 */
849 int
850 rsh_exec(so,ns, user, host, args)
851 struct SLIRPsocket *so;
852 struct SLIRPsocket *ns;
853 char *user;
854 char *host;
855 char *args;
856 {
857 int fd[2];
858 int fd0[2];
859 int s;
860 char buff[256];
861
862 DEBUG_CALL("rsh_exec");
863 DEBUG_ARG("so = %lx", (long)so);
864
865 if (pipe(fd)<0) {
866 lprint("Error: pipe failed: %s\n", strerror(errno));
867 return 0;
868 }
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;
876 }
877 #else
878 if (slirp_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;
883 }
884 #endif
885
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;
894
895 case 0:
896 close(fd[0]);
897 close(fd0[0]);
898
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
908 }
909
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);
915
916 execlp("rsh","rsh","-l", user, host, args, NULL);
917
918 /* Ooops, failed, let's tell the user why */
919
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);
925
926 default:
927 close(fd[1]);
928 close(fd0[1]);
929 ns->s=fd[0];
930 so->s=fd0[0];
931
932 return 1;
933 }
934 }
935 #endif
936