static void process_cmdline(void) { void (*handler)(int); char *s, *cmd; u_short fwd_port, fwd_host_port; char buf[1024], sfwd_port[6], sfwd_host_port[6]; int local = 0; leave_raw_mode(); handler = signal(SIGINT, SIG_IGN); cmd = s = read_passphrase("\r\nssh> ", RP_ECHO); if (s == NULL) goto out; while (*s && isspace(*s)) s++; if (*s == 0) goto out; if (strlen(s) < 2 || s[0] != '-' || !(s[1] == 'L' || s[1] == 'R')) { logit("Invalid command."); goto out; } if (s[1] == 'L') local = 1; if (!local && !compat20) { logit("Not supported for SSH protocol version 1."); goto out; } s += 2; while (*s && isspace(*s)) s++; if (sscanf(s, "%5[0-9]:%255[^:]:%5[0-9]", sfwd_port, buf, sfwd_host_port) != 3 && sscanf(s, "%5[0-9]/%255[^/]/%5[0-9]", sfwd_port, buf, sfwd_host_port) != 3) { logit("Bad forwarding specification."); goto out; } if ((fwd_port = a2port(sfwd_port)) == 0 || (fwd_host_port = a2port(sfwd_host_port)) == 0) { logit("Bad forwarding port(s)."); goto out; } if (local) { if (channel_setup_local_fwd_listener(fwd_port, buf, fwd_host_port, options.gateway_ports) < 0) { logit("Port forwarding failed."); goto out; } } else channel_request_remote_forwarding(fwd_port, buf, fwd_host_port); logit("Forwarding port."); out: signal(SIGINT, handler); enter_raw_mode(); if (cmd) xfree(cmd); }
/* * suspendSelf * * Put ourself in the background * * param bRestoreTty specifies whether we will put our self back * in raw mode when we resume */ static void suspendSelf(int bRestoreTty) { leave_raw_mode(); kill(getpid(), SIGTSTP); if (bRestoreTty) enter_raw_mode(); }
static void suspend_self(int restore_tty) { leave_raw_mode(); kill(getpid(), SIGTSTP); if (restore_tty) { enter_raw_mode(); } }
static void do_terminal_cleanup(void) { if (_saved_winsize.ws_row > 0 && _saved_winsize.ws_col > 0) ioctl(fileno(stdout), TIOCSWINSZ, &_saved_winsize); leave_raw_mode(); if (errno) lprintf(LOG_ERR, "Exiting due to error %d -> %s", errno, strerror(errno)); }
static void client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr) { struct winsize oldws, newws; /* Flush stdout and stderr buffers. */ if (buffer_len(bout) > 0) atomicio(vwrite, fileno(stdout), buffer_ptr(bout), buffer_len(bout)); if (buffer_len(berr) > 0) atomicio(vwrite, fileno(stderr), buffer_ptr(berr), buffer_len(berr)); leave_raw_mode(); /* * Free (and clear) the buffer to reduce the amount of data that gets * written to swap. */ buffer_free(bin); buffer_free(bout); buffer_free(berr); /* Save old window size. */ ioctl(fileno(stdin), TIOCGWINSZ, &oldws); /* Send the suspend signal to the program itself. */ kill(getpid(), SIGTSTP); /* Check if the window size has changed. */ if (ioctl(fileno(stdin), TIOCGWINSZ, &newws) >= 0 && (oldws.ws_row != newws.ws_row || oldws.ws_col != newws.ws_col || oldws.ws_xpixel != newws.ws_xpixel || oldws.ws_ypixel != newws.ws_ypixel)) received_window_change_signal = 1; /* OK, we have been continued by the user. Reinitialize buffers. */ buffer_init(bin); buffer_init(bout); buffer_init(berr); enter_raw_mode(); }
/* process the characters one by one */ static int process_escapes(Buffer *bin, Buffer *bout, Buffer *berr, char *buf, int len) { char string[1024]; pid_t pid; int bytes = 0; u_int i; u_char ch; char *s; for (i = 0; i < len; i++) { /* Get one character at a time. */ ch = buf[i]; if (escape_pending) { /* We have previously seen an escape character. */ /* Clear the flag now. */ escape_pending = 0; /* Process the escaped character. */ switch (ch) { case '.': /* Terminate the connection. */ snprintf(string, sizeof string, "%c.\r\n", escape_char); buffer_append(berr, string, strlen(string)); quit_pending = 1; return -1; case 'Z' - 64: /* Suspend the program. */ /* Print a message to that effect to the user. */ snprintf(string, sizeof string, "%c^Z [suspend ssh]\r\n", escape_char); buffer_append(berr, string, strlen(string)); /* Restore terminal modes and suspend. */ client_suspend_self(bin, bout, berr); /* We have been continued. */ continue; case 'B': if (compat20) { snprintf(string, sizeof string, "%cB\r\n", escape_char); buffer_append(berr, string, strlen(string)); channel_request_start(session_ident, "break", 0); packet_put_int(1000); packet_send(); } continue; case 'R': if (compat20) { if (datafellows & SSH_BUG_NOREKEY) logit("Server does not support re-keying"); else need_rekeying = 1; } continue; case '&': /* * Detach the program (continue to serve connections, * but put in background and no more new connections). */ /* Restore tty modes. */ leave_raw_mode(); /* Stop listening for new connections. */ channel_stop_listening(); snprintf(string, sizeof string, "%c& [backgrounded]\n", escape_char); buffer_append(berr, string, strlen(string)); /* Fork into background. */ pid = fork(); if (pid < 0) { error("fork: %.100s", strerror(errno)); continue; } if (pid != 0) { /* This is the parent. */ /* The parent just exits. */ exit(0); } /* The child continues serving connections. */ if (compat20) { buffer_append(bin, "\004", 1); /* fake EOF on stdin */ return -1; } else if (!stdin_eof) { /* * Sending SSH_CMSG_EOF alone does not always appear * to be enough. So we try to send an EOF character * first. */ packet_start(SSH_CMSG_STDIN_DATA); packet_put_string("\004", 1); packet_send(); /* Close stdin. */ stdin_eof = 1; if (buffer_len(bin) == 0) { packet_start(SSH_CMSG_EOF); packet_send(); } } continue; case '?': snprintf(string, sizeof string, "%c?\r\n\ Supported escape sequences:\r\n\ %c. - terminate connection\r\n\ %cB - send a BREAK to the remote system\r\n\ %cC - open a command line\r\n\ %cR - Request rekey (SSH protocol 2 only)\r\n\ %c^Z - suspend ssh\r\n\ %c# - list forwarded connections\r\n\ %c& - background ssh (when waiting for connections to terminate)\r\n\ %c? - this message\r\n\ %c%c - send the escape character by typing it twice\r\n\ (Note that escapes are only recognized immediately after newline.)\r\n", escape_char, escape_char, escape_char, escape_char, escape_char, escape_char, escape_char, escape_char, escape_char, escape_char, escape_char); buffer_append(berr, string, strlen(string)); continue; case '#': snprintf(string, sizeof string, "%c#\r\n", escape_char); buffer_append(berr, string, strlen(string)); s = channel_open_message(); buffer_append(berr, s, strlen(s)); xfree(s); continue; case 'C': process_cmdline(); continue; default: if (ch != escape_char) { buffer_put_char(bin, escape_char); bytes++; } /* Escaped characters fall through here */ break; } } else { /* * The previous character was not an escape char. Check if this * is an escape. */ if (last_was_cr && ch == escape_char) { /* It is. Set the flag and continue to next character. */ escape_pending = 1; continue; } } /* * Normal character. Record whether it was a newline, * and append it to the buffer. */ last_was_cr = (ch == '\r' || ch == '\n'); buffer_put_char(bin, ch); bytes++; }
/* * ipmi_isol_red_pill */ static int ipmi_isol_red_pill(struct ipmi_intf * intf) { char * buffer; int numRead; int bShouldExit = 0; int bBmcClosedSession = 0; fd_set read_fds; struct timeval tv; int retval; int buffer_size = 255; int timedout = 0; buffer = (char*)malloc(buffer_size); if (buffer == NULL) { lprintf(LOG_ERR, "ipmitool: malloc failure"); return -1; } enter_raw_mode(); while (! bShouldExit) { FD_ZERO(&read_fds); FD_SET(0, &read_fds); FD_SET(intf->fd, &read_fds); /* Wait up to half a second */ tv.tv_sec = 0; tv.tv_usec = 500000; retval = select(intf->fd + 1, &read_fds, NULL, NULL, &tv); if (retval) { if (retval == -1) { /* ERROR */ perror("select"); return -1; } timedout = 0; /* * Process input from the user */ if (FD_ISSET(0, &read_fds)) { memset(buffer, 0, buffer_size); numRead = read(fileno(stdin), buffer, buffer_size); if (numRead > 0) { int rc = processiSolUserInput(intf, buffer, numRead); if (rc) { if (rc < 0) bShouldExit = bBmcClosedSession = 1; else bShouldExit = 1; } } else { bShouldExit = 1; } } /* * Process input from the BMC */ else if (FD_ISSET(intf->fd, &read_fds)) { struct ipmi_rs * rs = intf->recv_sol(intf); if (! rs) { bShouldExit = bBmcClosedSession = 1; } else output(rs); } /* * ERROR in select */ else { lprintf(LOG_ERR, "Error: Select returned with nothing to read"); bShouldExit = 1; } } else { if ((++timedout) == 20) /* Every 10 seconds we send a keepalive */ { intf->keepalive(intf); timedout = 0; } } } leave_raw_mode(); if (bBmcClosedSession) { lprintf(LOG_ERR, "SOL session closed by BMC"); } else ipmi_isol_deactivate(intf); return 0; }