home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1988 Dave Settle. All rights reserved.
- * Permission is granted to use, copy and modify this software, providing
- * that it is not sold for profit, and that this copyright notice is retained
- * in any copies of the source.
- */
- /*
- * connect.c: connect tty to remote host.
- */
-
- #include <sys/types.h>
- #include <sys/signal.h>
- #include <sys/errno.h>
- #include <sys/utsname.h>
- #include <termio.h>
- #include <pwd.h>
-
- struct passwd *getpwuid(), *getpwnam();
- char *getlogin();
- int (*signal())();
-
- extern int errno;
- #include <stdio.h>
-
- #define MAIN
- #include "ni.h"
-
- char remoteshell[] = {0,0,0,0,0,0};
-
- struct request request;
-
- int reader, writer; /* Processes */
-
- int login = 0; /* Are we doing a login? */
-
- #define COOKED 0
- #define RAW 1
- struct termio raw, cooked; /* To allow screen mode changes */
- int screenmode = COOKED, toggle(), trap();
-
- wakeup(){
- signal(SIGALRM, wakeup);
- }
- /*
- * Got a signal - die. Writer is child process here.
- */
- die(sig){
- if(sig) printf("Connection closed.\r\n");
- if((getpid() == writer) && reader) kill(reader, SIGTERM);
- else if(writer) terminate(writer);
- send(&request, 0, TERMINATE, server);
- if(cooked.c_oflag) ioctl(fileno(stdout), TCSETA, &cooked);
- exit(0);
- }
-
- sendsig(sig)
- {
- struct request request;
- signal(sig, sendsig);
- if(sig == SIGINT) send(&request, 0, RMTSIGINT, server);
- if(sig == SIGQUIT) send(&request, 0, RMTSIGQUIT, server);
- }
-
-
- main(argc, argv)
- char **argv;
-
- {
- struct utsname uts;
- register char *sys = argv[argc - 1];
- int i;
- if(argc < 2) {
- printf("usage: %s hostname\n", argv[0]);
- exit(1);
- }
- uname(&uts);
- for(i=1;i<argc;i++) if(*argv[i] == '-') switch(argv[i][1]) {
- case 'l':
- login = 1;
- break;
- case 'd':
- debug = 1;
- break;
- }
- signal(SIGALRM, wakeup);
- signal(SIGTERM, SIG_IGN);
- if(configure(client, 3, getpid()) == -1) exit(1);
- if((i = hostaddr(argv[argc - 1])) == -1) {
- printf("Host '%s' not known\n", argv[argc - 1]);
- exit(1);
- }
- else server[NODE] = i;
- connect(server, sys);
- return(0);
- }
- /*
- * connect(addr): set up connection to ethernet address 'addr' (system 'sys')
- */
- connect(addr, sys)
- char *addr, *sys;
- {
- register struct request *r = &request;
- char *shell, *user;
- int n;
- struct passwd *pw;
- /*
- * send off our login name and uid to remote host.
- * also send timezone.
- */
- if((user = getlogin()) == NULL)
- pw = getpwuid(getuid());
- else
- pw = getpwnam(user);
- if(pw == NULL) {
- printf("Can't determine your user name!\n");
- exit(1);
- }
- if(*pw->pw_name == 0) {
- printf("Your user name is NULL! You seem to be %s\n",
- user ? user : "unknown");
- exit(1);
- }
- printf("Trying to connect to %s ... ", ipaddr(addr));
- fflush(stdout);
- sprintf(r->r_data, "%d %s TERM=%s",
- pw->pw_uid, pw->pw_name, getenv("TERM"));
- n = strlen(r->r_data);
- send(r, n, REQUEST, addr);
- recv(r);
- if(r->r_type == TERMINATE) {
- printf("rejected!\n%s: %s\n", sys, r->r_data);
- exit(0);
- }
- memcpy(server, r->r_port.srcaddr, ETHERSIZE);
- /*
- * trap signals from here on, so that we can terminate the remote side.
- */
- signal(SIGQUIT, toggle);
- signal(SIGINT, sendsig);
- signal(SIGHUP, die);
- printf("OK\nStarting remote %s ... ", login ? "login" : "shell");
- fflush(stdout);
- if(login) n = sprintf(r->r_data, "login");
- else {
- shell = getenv("SHELL");
- if(shell == 0) shell = "/bin/sh";
- n = sprintf(r->r_data, "%s -i", shell);
- }
- send(r, n, REQUEST, server);
- recv(r);
- if(r->r_type == TERMINATE) {
- printf("rejected!\n%s: %s\n", sys, r->r_data);
- exit(0);
- }
- printf("OK\nConnection complete ... server is %s\n", ipaddr(server));
- /*
- * Set up the termio structures needed for mode swapping
- */
- ioctl(fileno(stdin), TCGETA, &cooked);
- ioctl(fileno(stdin), TCGETA, &raw);
- raw.c_oflag &= ~OPOST;
- raw.c_cc[VMIN] = 1;
- raw.c_cc[VTIME] = 0;
- raw.c_iflag = 0;
- raw.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
- screenmode = COOKED;
- /*
- * fork for reader and writer processes.
- */
- reader = getpid();
- if(writer = fork()) {
- /*
- * If we are starting a remote login via a ptty, then the remote host will
- * echo, so set to raw mode. SIGQUIT will close the connection.
- */
- if(login) {
- screenmode = RAW;
- ioctl(fileno(stdin), TCSETA, &raw);
- signal(SIGQUIT, die);
- signal(SIGINT, trap);
- }
- else {
- /*
- * Send the remote shell an initial newline, so that the user sees a prompt.
- */
- r->r_data[0] = '\n';
- send(r, 1, DATA, server);
- }
- while(n = read(fileno(stdin), r->r_data, sizeof r->r_data)) {
- if(n == -1) {
- if(errno == EINTR) continue;
- else break;
- }
- if(debug) {
- printf("client: sent [");
- write(fileno(stdout), r->r_data, n);
- printf("] to %s\n", ipaddr(server));
- }
- send(r, n, DATA, server);
- }
- send(r, 0, TERMINATE, server);
- terminate(writer);
- ioctl(fileno(stdout), TCSETA, &cooked);
- exit(0);
- }
- else {
- signal(SIGINT, SIG_IGN);
- signal(SIGQUIT, SIG_IGN);
- while(1) {
- recv(r);
- if(debug) {
- printf("client: got [");
- write(fileno(stdout), r->r_data, r->r_size);
- printf("] from %s\n", ipaddr(r->r_port.srcaddr));
- }
- if(r->r_type == TERMINATE) {
- printf("Lost remote connection [");
- fflush(stdout);
- write(fileno(stdout), r->r_data, r->r_size);
- printf("]\n");
- kill(reader, SIGTERM);
- ioctl(fileno(stdout), TCSETA, &cooked);
- exit(0);
- }
- write(fileno(stdout), r->r_data, r->r_size);
- }
- }
- }
- /*
- * toggle: change screen mode from RAW <-> COOKED
- */
- toggle(sig){
- static int (*handler)();
- signal(sig, toggle);
- switch(screenmode) {
- case COOKED:
- handler = signal(SIGINT, trap);
- ioctl(fileno(stdin), TCSETA, &raw);
- putchar(07); /* beep */
- fflush(stdout);
- screenmode = RAW;
- break;
- case RAW:
- if(handler) signal(SIGINT, handler);
- ioctl(fileno(stdin), TCSETA, &cooked);
- printf("[cooked]");
- fflush(stdout);
- screenmode = COOKED;
- break;
- }
- }
- /*
- * trap interrupts in raw mode, substitute 'del' char
- * We can't just ignore interrupts, otherwise we can't switch out of raw mode.
- */
- trap(sig){
- struct request r;
- signal(sig, trap);
- switch(sig) {
- default:
- case SIGINT:
- r.r_data[0] = cooked.c_cc[VINTR];
- break;
- case SIGQUIT:
- r.r_data[0] = cooked.c_cc[VQUIT];
- break;
- }
- send(&r, 1, DATA, server);
- }
-
-