Revision 5fafdf24 slirp/misc.c
b/slirp/misc.c | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* Copyright (c) 1995 Danny Gasparovski. |
3 |
*
|
|
3 |
* |
|
4 | 4 |
* Please read the file COPYRIGHT for the |
5 | 5 |
* terms and conditions of the copyright. |
6 | 6 |
*/ |
... | ... | |
31 | 31 |
if (x_display) |
32 | 32 |
lprint("X Redir: Redirecting to display %d\r\n", x_display); |
33 | 33 |
} |
34 |
|
|
34 |
|
|
35 | 35 |
return CFG_OK; |
36 | 36 |
} |
37 | 37 |
|
... | ... | |
47 | 47 |
int screen; |
48 | 48 |
{ |
49 | 49 |
int i; |
50 |
|
|
50 |
|
|
51 | 51 |
if (x_port >= 0) { |
52 | 52 |
lprint("X Redir: X already being redirected.\r\n"); |
53 | 53 |
show_x(0, 0); |
... | ... | |
89 | 89 |
{ |
90 | 90 |
char buff[256]; |
91 | 91 |
struct hostent *he = NULL; |
92 |
|
|
92 |
|
|
93 | 93 |
if (gethostname(buff,256) == 0) |
94 | 94 |
he = gethostbyname(buff); |
95 | 95 |
if (he) |
... | ... | |
172 | 172 |
int port; |
173 | 173 |
{ |
174 | 174 |
struct ex_list *tmp_ptr; |
175 |
|
|
175 |
|
|
176 | 176 |
/* First, check if the port is "bound" */ |
177 | 177 |
for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) { |
178 | 178 |
if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr) |
179 | 179 |
return -1; |
180 | 180 |
} |
181 |
|
|
181 |
|
|
182 | 182 |
tmp_ptr = *ex_ptr; |
183 | 183 |
*ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list)); |
184 | 184 |
(*ex_ptr)->ex_fport = port; |
... | ... | |
233 | 233 |
|
234 | 234 |
#ifdef HAVE_GRANTPT |
235 | 235 |
char *ptr; |
236 |
|
|
236 |
|
|
237 | 237 |
if ((master = open("/dev/ptmx", O_RDWR)) < 0 || |
238 | 238 |
grantpt(master) < 0 || |
239 | 239 |
unlockpt(master) < 0 || |
... | ... | |
241 | 241 |
close(master); |
242 | 242 |
return -1; |
243 | 243 |
} |
244 |
|
|
244 |
|
|
245 | 245 |
if ((slave = open(ptr, O_RDWR)) < 0 || |
246 | 246 |
ioctl(slave, I_PUSH, "ptem") < 0 || |
247 | 247 |
ioctl(slave, I_PUSH, "ldterm") < 0 || |
... | ... | |
250 | 250 |
close(slave); |
251 | 251 |
return -1; |
252 | 252 |
} |
253 |
|
|
253 |
|
|
254 | 254 |
*amaster = master; |
255 | 255 |
*aslave = slave; |
256 | 256 |
return 0; |
257 |
|
|
257 |
|
|
258 | 258 |
#else |
259 |
|
|
259 |
|
|
260 | 260 |
static char line[] = "/dev/ptyXX"; |
261 | 261 |
register const char *cp1, *cp2; |
262 |
|
|
262 |
|
|
263 | 263 |
for (cp1 = "pqrsPQRS"; *cp1; cp1++) { |
264 | 264 |
line[8] = *cp1; |
265 | 265 |
for (cp2 = "0123456789abcdefghijklmnopqrstuv"; *cp2; cp2++) { |
... | ... | |
296 | 296 |
* process, which connects to this socket, after which we |
297 | 297 |
* exec the wanted program. If something (strange) happens, |
298 | 298 |
* the accept() call could block us forever. |
299 |
*
|
|
299 |
* |
|
300 | 300 |
* do_pty = 0 Fork/exec inetd style |
301 | 301 |
* do_pty = 1 Fork/exec using slirp.telnetd |
302 | 302 |
* do_ptr = 2 Fork/exec using pty |
... | ... | |
320 | 320 |
char *bptr; |
321 | 321 |
char *curarg; |
322 | 322 |
int c, i, ret; |
323 |
|
|
323 |
|
|
324 | 324 |
DEBUG_CALL("fork_exec"); |
325 | 325 |
DEBUG_ARG("so = %lx", (long)so); |
326 | 326 |
DEBUG_ARG("ex = %lx", (long)ex); |
327 | 327 |
DEBUG_ARG("do_pty = %lx", (long)do_pty); |
328 |
|
|
328 |
|
|
329 | 329 |
if (do_pty == 2) { |
330 | 330 |
if (slirp_openpty(&master, &s) == -1) { |
331 | 331 |
lprint("Error: openpty failed: %s\n", strerror(errno)); |
... | ... | |
335 | 335 |
addr.sin_family = AF_INET; |
336 | 336 |
addr.sin_port = 0; |
337 | 337 |
addr.sin_addr.s_addr = INADDR_ANY; |
338 |
|
|
338 |
|
|
339 | 339 |
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 || |
340 | 340 |
bind(s, (struct sockaddr *)&addr, addrlen) < 0 || |
341 | 341 |
listen(s, 1) < 0) { |
342 | 342 |
lprint("Error: inet socket: %s\n", strerror(errno)); |
343 | 343 |
closesocket(s); |
344 |
|
|
344 |
|
|
345 | 345 |
return 0; |
346 | 346 |
} |
347 | 347 |
} |
348 |
|
|
348 |
|
|
349 | 349 |
switch(fork()) { |
350 | 350 |
case -1: |
351 | 351 |
lprint("Error: fork failed: %s\n", strerror(errno)); |
... | ... | |
353 | 353 |
if (do_pty == 2) |
354 | 354 |
close(master); |
355 | 355 |
return 0; |
356 |
|
|
356 |
|
|
357 | 357 |
case 0: |
358 | 358 |
/* Set the DISPLAY */ |
359 | 359 |
if (do_pty == 2) { |
... | ... | |
375 | 375 |
ret = connect(s, (struct sockaddr *)&addr, addrlen); |
376 | 376 |
} while (ret < 0 && errno == EINTR); |
377 | 377 |
} |
378 |
|
|
378 |
|
|
379 | 379 |
#if 0 |
380 | 380 |
if (x_port >= 0) { |
381 | 381 |
#ifdef HAVE_SETENV |
... | ... | |
386 | 386 |
putenv(buff); |
387 | 387 |
#endif |
388 | 388 |
} |
389 |
#endif
|
|
389 |
#endif |
|
390 | 390 |
dup2(s, 0); |
391 | 391 |
dup2(s, 1); |
392 | 392 |
dup2(s, 2); |
393 | 393 |
for (s = 3; s <= 255; s++) |
394 | 394 |
close(s); |
395 |
|
|
395 |
|
|
396 | 396 |
i = 0; |
397 | 397 |
bptr = strdup(ex); /* No need to free() this */ |
398 | 398 |
if (do_pty == 1) { |
... | ... | |
410 | 410 |
*bptr++ = (char)0; |
411 | 411 |
argv[i++] = strdup(curarg); |
412 | 412 |
} while (c); |
413 |
|
|
413 |
|
|
414 | 414 |
argv[i] = 0; |
415 | 415 |
execvp(argv[0], argv); |
416 |
|
|
416 |
|
|
417 | 417 |
/* Ooops, failed, let's tell the user why */ |
418 | 418 |
{ |
419 | 419 |
char buff[256]; |
420 |
|
|
421 |
sprintf(buff, "Error: execvp of %s failed: %s\n",
|
|
420 |
|
|
421 |
sprintf(buff, "Error: execvp of %s failed: %s\n", |
|
422 | 422 |
argv[0], strerror(errno)); |
423 | 423 |
write(2, buff, strlen(buff)+1); |
424 | 424 |
} |
425 | 425 |
close(0); close(1); close(2); /* XXX */ |
426 | 426 |
exit(1); |
427 |
|
|
427 |
|
|
428 | 428 |
default: |
429 | 429 |
if (do_pty == 2) { |
430 | 430 |
close(s); |
... | ... | |
447 | 447 |
setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); |
448 | 448 |
} |
449 | 449 |
fd_nonblock(so->s); |
450 |
|
|
450 |
|
|
451 | 451 |
/* Append the telnet options now */ |
452 | 452 |
if (so->so_m != 0 && do_pty == 1) { |
453 | 453 |
sbappend(so, so->so_m); |
454 | 454 |
so->so_m = 0; |
455 | 455 |
} |
456 |
|
|
456 |
|
|
457 | 457 |
return 1; |
458 | 458 |
} |
459 | 459 |
} |
... | ... | |
465 | 465 |
const char *str; |
466 | 466 |
{ |
467 | 467 |
char *bptr; |
468 |
|
|
468 |
|
|
469 | 469 |
bptr = (char *)malloc(strlen(str)+1); |
470 | 470 |
strcpy(bptr, str); |
471 |
|
|
471 |
|
|
472 | 472 |
return bptr; |
473 | 473 |
} |
474 | 474 |
#endif |
... | ... | |
484 | 484 |
#endif |
485 | 485 |
struct sockaddr_in sock_in; |
486 | 486 |
char buff[256]; |
487 |
|
|
487 |
|
|
488 | 488 |
ret = -1; |
489 | 489 |
if (slirp_socket_passwd) { |
490 | 490 |
s = socket(AF_INET, SOCK_STREAM, 0); |
... | ... | |
514 | 514 |
#endif |
515 | 515 |
slirp_exit(0); |
516 | 516 |
} |
517 |
|
|
518 |
|
|
517 |
|
|
518 |
|
|
519 | 519 |
void |
520 | 520 |
snooze() |
521 | 521 |
{ |
522 | 522 |
sigset_t s; |
523 | 523 |
int i; |
524 |
|
|
524 |
|
|
525 | 525 |
/* Don't need our data anymore */ |
526 | 526 |
/* XXX This makes SunOS barf */ |
527 | 527 |
/* brk(0); */ |
528 |
|
|
528 |
|
|
529 | 529 |
/* Close all fd's */ |
530 | 530 |
for (i = 255; i >= 0; i--) |
531 | 531 |
close(i); |
532 |
|
|
532 |
|
|
533 | 533 |
signal(SIGQUIT, slirp_exit); |
534 | 534 |
signal(SIGHUP, snooze_hup); |
535 | 535 |
sigemptyset(&s); |
536 |
|
|
536 |
|
|
537 | 537 |
/* Wait for any signal */ |
538 | 538 |
sigsuspend(&s); |
539 |
|
|
539 |
|
|
540 | 540 |
/* Just in case ... */ |
541 | 541 |
exit(255); |
542 | 542 |
} |
... | ... | |
549 | 549 |
int n; |
550 | 550 |
fd_set readfds; |
551 | 551 |
struct ttys *ttyp; |
552 |
|
|
552 |
|
|
553 | 553 |
/* Don't need our data anymore */ |
554 | 554 |
/* XXX This makes SunOS barf */ |
555 | 555 |
/* brk(0); */ |
556 |
|
|
556 |
|
|
557 | 557 |
signal(SIGQUIT, slirp_exit); |
558 | 558 |
signal(SIGHUP, slirp_exit); |
559 | 559 |
signal(SIGINT, slirp_exit); |
560 | 560 |
signal(SIGTERM, slirp_exit); |
561 |
|
|
561 |
|
|
562 | 562 |
/* Fudge to get term_raw and term_restore to work */ |
563 | 563 |
if (NULL == (ttyp = tty_attach (0, slirp_tty))) { |
564 | 564 |
lprint ("Error: tty_attach failed in misc.c:relay()\r\n"); |
... | ... | |
567 | 567 |
ttyp->fd = 0; |
568 | 568 |
ttyp->flags |= TTY_CTTY; |
569 | 569 |
term_raw(ttyp); |
570 |
|
|
570 |
|
|
571 | 571 |
while (1) { |
572 | 572 |
FD_ZERO(&readfds); |
573 |
|
|
573 |
|
|
574 | 574 |
FD_SET(0, &readfds); |
575 | 575 |
FD_SET(s, &readfds); |
576 |
|
|
576 |
|
|
577 | 577 |
n = select(s+1, &readfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0); |
578 |
|
|
578 |
|
|
579 | 579 |
if (n <= 0) |
580 | 580 |
slirp_exit(0); |
581 |
|
|
581 |
|
|
582 | 582 |
if (FD_ISSET(0, &readfds)) { |
583 | 583 |
n = read(0, buf, 8192); |
584 | 584 |
if (n <= 0) |
... | ... | |
587 | 587 |
if (n <= 0) |
588 | 588 |
slirp_exit(0); |
589 | 589 |
} |
590 |
|
|
590 |
|
|
591 | 591 |
if (FD_ISSET(s, &readfds)) { |
592 | 592 |
n = read(s, buf, 8192); |
593 | 593 |
if (n <= 0) |
... | ... | |
597 | 597 |
slirp_exit(0); |
598 | 598 |
} |
599 | 599 |
} |
600 |
|
|
600 |
|
|
601 | 601 |
/* Just in case.... */ |
602 | 602 |
exit(1); |
603 | 603 |
} |
... | ... | |
614 | 614 |
#endif |
615 | 615 |
{ |
616 | 616 |
va_list args; |
617 |
|
|
617 |
|
|
618 | 618 |
#ifdef __STDC__ |
619 | 619 |
va_start(args, format); |
620 | 620 |
#else |
... | ... | |
631 | 631 |
int deltaw = lprint_sb->sb_wptr - lprint_sb->sb_data; |
632 | 632 |
int deltar = lprint_sb->sb_rptr - lprint_sb->sb_data; |
633 | 633 |
int deltap = lprint_ptr - lprint_sb->sb_data; |
634 |
|
|
634 |
|
|
635 | 635 |
lprint_sb->sb_data = (char *)realloc(lprint_sb->sb_data, |
636 | 636 |
lprint_sb->sb_datalen + TCP_SNDSPACE); |
637 |
|
|
637 |
|
|
638 | 638 |
/* Adjust all values */ |
639 | 639 |
lprint_sb->sb_wptr = lprint_sb->sb_data + deltaw; |
640 | 640 |
lprint_sb->sb_rptr = lprint_sb->sb_data + deltar; |
641 | 641 |
lprint_ptr = lprint_sb->sb_data + deltap; |
642 |
|
|
642 |
|
|
643 | 643 |
lprint_sb->sb_datalen += TCP_SNDSPACE; |
644 | 644 |
} |
645 | 645 |
} |
646 |
#endif
|
|
646 |
#endif |
|
647 | 647 |
if (lprint_print) |
648 | 648 |
lprint_ptr += (*lprint_print)(*lprint_arg, format, args); |
649 |
|
|
649 |
|
|
650 | 650 |
/* Check if they want output to be logged to file as well */ |
651 | 651 |
if (lfd) { |
652 |
/*
|
|
652 |
/* |
|
653 | 653 |
* Remove \r's |
654 | 654 |
* otherwise you'll get ^M all over the file |
655 | 655 |
*/ |
656 | 656 |
int len = strlen(format); |
657 | 657 |
char *bptr1, *bptr2; |
658 |
|
|
658 |
|
|
659 | 659 |
bptr1 = bptr2 = strdup(format); |
660 |
|
|
660 |
|
|
661 | 661 |
while (len--) { |
662 | 662 |
if (*bptr1 == '\r') |
663 | 663 |
memcpy(bptr1, bptr1+1, len+1); |
... | ... | |
680 | 680 |
char *buff3 = buff4; |
681 | 681 |
struct emu_t *emup; |
682 | 682 |
struct socket *so; |
683 |
|
|
683 |
|
|
684 | 684 |
if (sscanf(buff, "%256s %256s", buff2, buff1) != 2) { |
685 | 685 |
lprint("Error: Bad arguments\r\n"); |
686 | 686 |
return; |
687 | 687 |
} |
688 |
|
|
688 |
|
|
689 | 689 |
if (sscanf(buff1, "%d:%d", &lport, &fport) != 2) { |
690 | 690 |
lport = 0; |
691 | 691 |
if (sscanf(buff1, "%d", &fport) != 1) { |
... | ... | |
693 | 693 |
return; |
694 | 694 |
} |
695 | 695 |
} |
696 |
|
|
696 |
|
|
697 | 697 |
if (sscanf(buff2, "%128[^:]:%128s", buff1, buff3) != 2) { |
698 | 698 |
buff3 = 0; |
699 | 699 |
if (sscanf(buff2, "%256s", buff1) != 1) { |
... | ... | |
701 | 701 |
return; |
702 | 702 |
} |
703 | 703 |
} |
704 |
|
|
704 |
|
|
705 | 705 |
if (buff3) { |
706 | 706 |
if (strcmp(buff3, "lowdelay") == 0) |
707 | 707 |
tos = IPTOS_LOWDELAY; |
... | ... | |
712 | 712 |
return; |
713 | 713 |
} |
714 | 714 |
} |
715 |
|
|
715 |
|
|
716 | 716 |
if (strcmp(buff1, "ftp") == 0) |
717 | 717 |
emu = EMU_FTP; |
718 | 718 |
else if (strcmp(buff1, "irc") == 0) |
... | ... | |
723 | 723 |
lprint("Error: Unknown service\r\n"); |
724 | 724 |
return; |
725 | 725 |
} |
726 |
|
|
726 |
|
|
727 | 727 |
/* First, check that it isn't already emulated */ |
728 | 728 |
for (emup = tcpemu; emup; emup = emup->next) { |
729 | 729 |
if (emup->lport == lport && emup->fport == fport) { |
... | ... | |
731 | 731 |
return; |
732 | 732 |
} |
733 | 733 |
} |
734 |
|
|
734 |
|
|
735 | 735 |
/* link it */ |
736 | 736 |
emup = (struct emu_t *)malloc(sizeof (struct emu_t)); |
737 | 737 |
emup->lport = (u_int16_t)lport; |
... | ... | |
740 | 740 |
emup->emu = emu; |
741 | 741 |
emup->next = tcpemu; |
742 | 742 |
tcpemu = emup; |
743 |
|
|
743 |
|
|
744 | 744 |
/* And finally, mark all current sessions, if any, as being emulated */ |
745 | 745 |
for (so = tcb.so_next; so != &tcb; so = so->so_next) { |
746 | 746 |
if ((lport && lport == ntohs(so->so_lport)) || |
... | ... | |
751 | 751 |
so->so_iptos = tos; |
752 | 752 |
} |
753 | 753 |
} |
754 |
|
|
754 |
|
|
755 | 755 |
lprint("Adding emulation for %s to port %d/%d\r\n", buff1, emup->lport, emup->fport); |
756 | 756 |
} |
757 | 757 |
|
... | ... | |
803 | 803 |
{ |
804 | 804 |
struct timeval t; |
805 | 805 |
fd_set fdset; |
806 |
|
|
806 |
|
|
807 | 807 |
FD_ZERO(&fdset); |
808 |
|
|
808 |
|
|
809 | 809 |
t.tv_sec = 0; |
810 | 810 |
t.tv_usec = usec * 1000; |
811 |
|
|
811 |
|
|
812 | 812 |
select(0, &fdset, &fdset, &fdset, &t); |
813 | 813 |
} |
814 | 814 |
|
... | ... | |
822 | 822 |
{ |
823 | 823 |
#ifdef FIONBIO |
824 | 824 |
int opt = 1; |
825 |
|
|
825 |
|
|
826 | 826 |
ioctlsocket(fd, FIONBIO, &opt); |
827 | 827 |
#else |
828 | 828 |
int opt; |
829 |
|
|
829 |
|
|
830 | 830 |
opt = fcntl(fd, F_GETFL, 0); |
831 | 831 |
opt |= O_NONBLOCK; |
832 | 832 |
fcntl(fd, F_SETFL, opt); |
... | ... | |
839 | 839 |
{ |
840 | 840 |
#ifdef FIONBIO |
841 | 841 |
int opt = 0; |
842 |
|
|
842 |
|
|
843 | 843 |
ioctlsocket(fd, FIONBIO, &opt); |
844 | 844 |
#else |
845 | 845 |
int opt; |
846 |
|
|
846 |
|
|
847 | 847 |
opt = fcntl(fd, F_GETFL, 0); |
848 | 848 |
opt &= ~O_NONBLOCK; |
849 | 849 |
fcntl(fd, F_SETFL, opt); |
... | ... | |
867 | 867 |
int fd0[2]; |
868 | 868 |
int s; |
869 | 869 |
char buff[256]; |
870 |
|
|
870 |
|
|
871 | 871 |
DEBUG_CALL("rsh_exec"); |
872 | 872 |
DEBUG_ARG("so = %lx", (long)so); |
873 |
|
|
873 |
|
|
874 | 874 |
if (pipe(fd)<0) { |
875 | 875 |
lprint("Error: pipe failed: %s\n", strerror(errno)); |
876 | 876 |
return 0; |
... | ... | |
891 | 891 |
return 0; |
892 | 892 |
} |
893 | 893 |
#endif |
894 |
|
|
894 |
|
|
895 | 895 |
switch(fork()) { |
896 | 896 |
case -1: |
897 | 897 |
lprint("Error: fork failed: %s\n", strerror(errno)); |
... | ... | |
900 | 900 |
close(fd0[0]); |
901 | 901 |
close(fd0[1]); |
902 | 902 |
return 0; |
903 |
|
|
903 |
|
|
904 | 904 |
case 0: |
905 | 905 |
close(fd[0]); |
906 | 906 |
close(fd0[0]); |
907 |
|
|
907 |
|
|
908 | 908 |
/* Set the DISPLAY */ |
909 | 909 |
if (x_port >= 0) { |
910 | 910 |
#ifdef HAVE_SETENV |
... | ... | |
915 | 915 |
putenv(buff); |
916 | 916 |
#endif |
917 | 917 |
} |
918 |
|
|
918 |
|
|
919 | 919 |
dup2(fd0[1], 0); |
920 | 920 |
dup2(fd0[1], 1); |
921 | 921 |
dup2(fd[1], 2); |
922 | 922 |
for (s = 3; s <= 255; s++) |
923 | 923 |
close(s); |
924 |
|
|
924 |
|
|
925 | 925 |
execlp("rsh","rsh","-l", user, host, args, NULL); |
926 |
|
|
926 |
|
|
927 | 927 |
/* Ooops, failed, let's tell the user why */ |
928 |
|
|
929 |
sprintf(buff, "Error: execlp of %s failed: %s\n",
|
|
928 |
|
|
929 |
sprintf(buff, "Error: execlp of %s failed: %s\n", |
|
930 | 930 |
"rsh", strerror(errno)); |
931 | 931 |
write(2, buff, strlen(buff)+1); |
932 | 932 |
close(0); close(1); close(2); /* XXX */ |
933 | 933 |
exit(1); |
934 |
|
|
934 |
|
|
935 | 935 |
default: |
936 | 936 |
close(fd[1]); |
937 | 937 |
close(fd0[1]); |
938 | 938 |
ns->s=fd[0]; |
939 | 939 |
so->s=fd0[0]; |
940 |
|
|
940 |
|
|
941 | 941 |
return 1; |
942 | 942 |
} |
943 | 943 |
} |
Also available in: Unified diff