home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume14 / 3bconnect / connect.c < prev    next >
C/C++ Source or Header  |  1988-05-08  |  6KB  |  271 lines

  1. /*
  2.  * Copyright (C) 1988 Dave Settle. All rights reserved.
  3.  * Permission is granted to use, copy and modify this software, providing
  4.  * that it is not sold for profit, and that this copyright notice is retained
  5.  * in any copies of the source.
  6.  */
  7. /*
  8.  * connect.c: connect tty to remote host.
  9.  */
  10.  
  11. #include <sys/types.h> 
  12. #include <sys/signal.h>
  13. #include <sys/errno.h>
  14. #include <sys/utsname.h>
  15. #include <termio.h>
  16. #include <pwd.h>
  17.  
  18. struct passwd *getpwuid(), *getpwnam();
  19. char *getlogin();
  20. int (*signal())();
  21.  
  22. extern int errno;
  23. #include <stdio.h>
  24.  
  25. #define MAIN
  26. #include "ni.h"
  27.  
  28. char remoteshell[] = {0,0,0,0,0,0};
  29.  
  30. struct request request;
  31.  
  32. int reader, writer;            /* Processes */
  33.  
  34. int login = 0;                /* Are we doing a login? */
  35.  
  36. #define COOKED 0
  37. #define RAW 1
  38. struct termio raw, cooked;        /* To allow screen mode changes */
  39. int screenmode = COOKED, toggle(), trap();
  40.  
  41. wakeup(){
  42.     signal(SIGALRM, wakeup);
  43. }
  44. /*
  45.  * Got a signal - die. Writer is child process here.
  46.  */
  47. die(sig){
  48.     if(sig) printf("Connection closed.\r\n");
  49.     if((getpid() == writer) && reader) kill(reader, SIGTERM);
  50.     else if(writer) terminate(writer);
  51.     send(&request, 0, TERMINATE, server);
  52.     if(cooked.c_oflag) ioctl(fileno(stdout), TCSETA, &cooked);
  53.     exit(0);
  54. }
  55.  
  56. sendsig(sig)
  57. {
  58.     struct request request;
  59.     signal(sig, sendsig);
  60.     if(sig == SIGINT) send(&request, 0, RMTSIGINT, server);
  61.     if(sig == SIGQUIT) send(&request, 0, RMTSIGQUIT, server);
  62. }
  63.     
  64.  
  65. main(argc, argv)
  66. char **argv;
  67.  
  68. {
  69.     struct utsname uts;
  70.     register char *sys = argv[argc - 1];
  71.     int i;
  72.     if(argc < 2) {
  73.         printf("usage: %s hostname\n", argv[0]);
  74.         exit(1);
  75.     }
  76.     uname(&uts);
  77.     for(i=1;i<argc;i++) if(*argv[i] == '-') switch(argv[i][1]) {
  78.     case 'l':
  79.         login = 1;
  80.         break;
  81.     case 'd':
  82.         debug = 1;
  83.         break;
  84.     }
  85.     signal(SIGALRM, wakeup);
  86.     signal(SIGTERM, SIG_IGN);
  87.     if(configure(client, 3, getpid()) == -1) exit(1);
  88.     if((i = hostaddr(argv[argc - 1])) == -1) {
  89.         printf("Host '%s' not known\n", argv[argc - 1]);
  90.         exit(1);
  91.     }
  92.     else server[NODE] = i;
  93.     connect(server, sys);
  94.     return(0);
  95. }
  96. /*
  97.  * connect(addr): set up connection to ethernet address 'addr' (system 'sys')
  98.  */
  99. connect(addr, sys)
  100. char *addr, *sys;
  101. {
  102.     register struct request *r = &request;
  103.     char *shell, *user;
  104.     int n;
  105.     struct passwd *pw;
  106. /*
  107.  * send off our login name and uid to remote host.
  108.  * also send timezone.
  109.  */
  110.      if((user = getlogin()) == NULL) 
  111.          pw = getpwuid(getuid());
  112.      else
  113.          pw = getpwnam(user);
  114.      if(pw == NULL) {
  115.          printf("Can't determine your user name!\n");
  116.          exit(1);
  117.      }
  118.      if(*pw->pw_name == 0) {
  119.          printf("Your user name is NULL! You seem to be %s\n",
  120.              user ? user : "unknown");
  121.          exit(1);
  122.      }
  123.     printf("Trying to connect to %s ... ", ipaddr(addr));
  124.      fflush(stdout);
  125.     sprintf(r->r_data, "%d %s TERM=%s", 
  126.         pw->pw_uid, pw->pw_name, getenv("TERM"));
  127.     n = strlen(r->r_data);
  128.     send(r, n, REQUEST, addr);
  129.     recv(r);
  130.      if(r->r_type == TERMINATE) {
  131.          printf("rejected!\n%s: %s\n", sys, r->r_data);
  132.          exit(0);
  133.      }
  134.     memcpy(server, r->r_port.srcaddr, ETHERSIZE);
  135. /*
  136.  * trap signals from here on, so that we can terminate the remote side.
  137.  */
  138.     signal(SIGQUIT, toggle);
  139.     signal(SIGINT, sendsig);
  140.     signal(SIGHUP, die);
  141.     printf("OK\nStarting remote %s ... ", login ? "login" : "shell");
  142.     fflush(stdout);
  143.     if(login) n = sprintf(r->r_data, "login");
  144.      else {
  145.          shell = getenv("SHELL");
  146.          if(shell == 0) shell = "/bin/sh";
  147.          n = sprintf(r->r_data, "%s -i", shell);
  148.     }
  149.      send(r, n, REQUEST, server);
  150.      recv(r);
  151.      if(r->r_type == TERMINATE) {
  152.          printf("rejected!\n%s: %s\n", sys, r->r_data);
  153.          exit(0);
  154.      }
  155.      printf("OK\nConnection complete ... server is %s\n", ipaddr(server));
  156. /*
  157.  * Set up the termio structures needed for mode swapping
  158.  */
  159.      ioctl(fileno(stdin), TCGETA, &cooked);
  160.      ioctl(fileno(stdin), TCGETA, &raw);
  161.      raw.c_oflag &= ~OPOST;
  162.      raw.c_cc[VMIN] = 1;
  163.      raw.c_cc[VTIME] = 0;
  164.      raw.c_iflag = 0;
  165.      raw.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
  166.      screenmode = COOKED;
  167. /*
  168.  * fork for reader and writer processes.
  169.  */
  170.     reader = getpid();
  171.      if(writer = fork()) {
  172. /*
  173.  * If we are starting a remote login via a ptty, then the remote host will
  174.  * echo, so set to raw mode. SIGQUIT will close the connection.
  175.  */
  176.          if(login) {
  177.              screenmode = RAW;
  178.             ioctl(fileno(stdin), TCSETA, &raw);
  179.             signal(SIGQUIT, die);
  180.             signal(SIGINT, trap);
  181.         }
  182.         else {
  183. /*
  184.  * Send the remote shell an initial newline, so that the user sees a prompt.
  185.  */
  186.             r->r_data[0] = '\n';
  187.             send(r, 1, DATA, server);
  188.         }
  189.          while(n = read(fileno(stdin), r->r_data, sizeof r->r_data)) {
  190.              if(n == -1) {
  191.                  if(errno == EINTR) continue;
  192.                  else break;
  193.              }
  194. if(debug) {
  195.             printf("client: sent [");
  196.             write(fileno(stdout), r->r_data, n);
  197.             printf("] to %s\n", ipaddr(server));
  198. }
  199.              send(r, n, DATA, server);
  200.          }
  201.          send(r, 0, TERMINATE, server);
  202.          terminate(writer);
  203.          ioctl(fileno(stdout), TCSETA, &cooked);
  204.          exit(0);
  205.      }
  206.     else {
  207.          signal(SIGINT, SIG_IGN);
  208.          signal(SIGQUIT, SIG_IGN);
  209.          while(1) {
  210.             recv(r);
  211. if(debug) {
  212.              printf("client: got [");
  213.             write(fileno(stdout), r->r_data, r->r_size);
  214.              printf("] from %s\n", ipaddr(r->r_port.srcaddr));
  215. }
  216.              if(r->r_type == TERMINATE) {
  217.                  printf("Lost remote connection [");
  218.                  fflush(stdout);
  219.                  write(fileno(stdout), r->r_data, r->r_size);
  220.                  printf("]\n");
  221.                 kill(reader, SIGTERM);
  222.                 ioctl(fileno(stdout), TCSETA, &cooked);
  223.                  exit(0);
  224.              }
  225.              write(fileno(stdout), r->r_data, r->r_size);
  226.          }
  227.      }
  228. }
  229. /*
  230.  * toggle: change screen mode from RAW <-> COOKED
  231.  */
  232. toggle(sig){
  233.     static int (*handler)();
  234.     signal(sig, toggle);
  235.     switch(screenmode) {
  236.     case COOKED:
  237.         handler = signal(SIGINT, trap);
  238.         ioctl(fileno(stdin), TCSETA, &raw);
  239.         putchar(07);        /* beep */
  240.         fflush(stdout);
  241.         screenmode = RAW;
  242.         break;
  243.     case RAW:
  244.         if(handler) signal(SIGINT, handler);
  245.         ioctl(fileno(stdin), TCSETA, &cooked);
  246.         printf("[cooked]");
  247.         fflush(stdout);
  248.         screenmode = COOKED;
  249.         break;
  250.     }
  251. }
  252. /*
  253.  * trap interrupts in raw mode, substitute 'del' char
  254.  * We can't just ignore interrupts, otherwise we can't switch out of raw mode.
  255.  */
  256. trap(sig){
  257.     struct request r;
  258.     signal(sig, trap);
  259.     switch(sig) {
  260.     default:
  261.     case SIGINT:
  262.         r.r_data[0] = cooked.c_cc[VINTR];
  263.         break;
  264.     case SIGQUIT:
  265.         r.r_data[0] = cooked.c_cc[VQUIT];
  266.         break;
  267.     }
  268.     send(&r, 1, DATA, server);
  269. }
  270.  
  271.