Annotation of src/usr.bin/ssh/cli.c, Revision 1.1
1.1 ! markus 1: #include "includes.h"
! 2: RCSID("$Id$");
! 3:
! 4: #include "xmalloc.h"
! 5: #include "ssh.h"
! 6: #include <vis.h>
! 7:
! 8: static int cli_input = -1;
! 9: static int cli_output = -1;
! 10: static int cli_from_stdin = 0;
! 11:
! 12: sigset_t oset;
! 13: sigset_t nset;
! 14: struct sigaction nsa;
! 15: struct sigaction osa;
! 16: struct termios ntio;
! 17: struct termios otio;
! 18: int echo_modified;
! 19:
! 20: volatile int intr;
! 21:
! 22: static int
! 23: cli_open(int from_stdin)
! 24: {
! 25: if (cli_input >= 0 && cli_output >= 0 && cli_from_stdin == from_stdin)
! 26: return 1;
! 27:
! 28: if (from_stdin) {
! 29: if (!cli_from_stdin && cli_input >= 0) {
! 30: (void)close(cli_input);
! 31: }
! 32: cli_input = STDIN_FILENO;
! 33: cli_output = STDERR_FILENO;
! 34: } else {
! 35: cli_input = cli_output = open("/dev/tty", O_RDWR);
! 36: if (cli_input < 0)
! 37: fatal("You have no controlling tty. Cannot read passphrase.");
! 38: }
! 39:
! 40: cli_from_stdin = from_stdin;
! 41:
! 42: return cli_input >= 0 && cli_output >= 0 && cli_from_stdin == from_stdin;
! 43: }
! 44:
! 45: static void
! 46: cli_close()
! 47: {
! 48: if (!cli_from_stdin && cli_input >= 0)
! 49: close(cli_input);
! 50: cli_input = -1;
! 51: cli_output = -1;
! 52: cli_from_stdin = 0;
! 53: return;
! 54: }
! 55:
! 56: void
! 57: intrcatch()
! 58: {
! 59: intr = 1;
! 60: }
! 61:
! 62: static void
! 63: cli_echo_disable()
! 64: {
! 65: sigemptyset(&nset);
! 66: sigaddset(&nset, SIGTSTP);
! 67: (void) sigprocmask(SIG_BLOCK, &nset, &oset);
! 68:
! 69: intr = 0;
! 70:
! 71: memset(&nsa, 0, sizeof(nsa));
! 72: nsa.sa_handler = intrcatch;
! 73: (void) sigaction(SIGINT, &nsa, &osa);
! 74:
! 75: echo_modified = 0;
! 76: if (tcgetattr(cli_input, &otio) == 0 && (otio.c_lflag & ECHO)) {
! 77: echo_modified = 1;
! 78: ntio = otio;
! 79: ntio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
! 80: (void) tcsetattr(cli_input, TCSANOW, &ntio);
! 81: }
! 82: return;
! 83: }
! 84:
! 85: static void
! 86: cli_echo_restore()
! 87: {
! 88: if (echo_modified != 0) {
! 89: tcsetattr(cli_input, TCSANOW, &otio);
! 90: echo_modified = 0;
! 91: }
! 92:
! 93: (void) sigprocmask(SIG_SETMASK, &oset, NULL);
! 94: (void) sigaction(SIGINT, &osa, NULL);
! 95:
! 96: if (intr != 0) {
! 97: kill(getpid(), SIGINT);
! 98: sigemptyset(&nset);
! 99: /* XXX tty has not neccessarily drained by now? */
! 100: sigsuspend(&nset);
! 101: intr = 0;
! 102: }
! 103: return;
! 104: }
! 105:
! 106: static int
! 107: cli_read(char* buf, int size, int echo)
! 108: {
! 109: char ch = 0;
! 110: int i = 0;
! 111:
! 112: if (!echo)
! 113: cli_echo_disable();
! 114:
! 115: while (ch != '\n') {
! 116: if (read(cli_input, &ch, 1) != 1)
! 117: break;
! 118: if (ch == '\n' || intr != 0)
! 119: break;
! 120: if (i < size)
! 121: buf[i++] = ch;
! 122: }
! 123: buf[i] = '\0';
! 124:
! 125: if (!echo)
! 126: cli_echo_restore();
! 127: if (!intr && !echo)
! 128: (void) write(cli_output, "\n", 1);
! 129: return i;
! 130: }
! 131:
! 132: static int
! 133: cli_write(char* buf, int size)
! 134: {
! 135: int i, len, pos, ret = 0;
! 136: char *output, *p;
! 137:
! 138: output = xmalloc(4*size);
! 139: for (p = output, i = 0; i < size; i++) {
! 140: if (buf[i] == '\n')
! 141: *p++ = buf[i];
! 142: else
! 143: p = vis(p, buf[i], 0, 0);
! 144: }
! 145: len = p - output;
! 146:
! 147: for (pos = 0; pos < len; pos += ret) {
! 148: ret = write(cli_output, output + pos, len - pos);
! 149: if (ret == -1)
! 150: return -1;
! 151: }
! 152: return 0;
! 153: }
! 154:
! 155: /*
! 156: * Presents a prompt and returns the response allocated with xmalloc().
! 157: * Uses /dev/tty or stdin/out depending on arg. Optionally disables echo
! 158: * of response depending on arg. Tries to ensure that no other userland
! 159: * buffer is storing the response.
! 160: */
! 161: char*
! 162: cli_read_passphrase(char* prompt, int from_stdin, int echo_enable)
! 163: {
! 164: char buf[BUFSIZ];
! 165: char* p;
! 166:
! 167: if (!cli_open(from_stdin))
! 168: fatal("Cannot read passphrase.");
! 169:
! 170: fflush(stdout);
! 171:
! 172: cli_write(prompt, strlen(prompt));
! 173: cli_read(buf, sizeof buf, echo_enable);
! 174:
! 175: cli_close();
! 176:
! 177: p = xstrdup(buf);
! 178: memset(buf, 0, sizeof(buf));
! 179: return (p);
! 180: }
! 181:
! 182: char*
! 183: cli_prompt(char* prompt, int echo_enable)
! 184: {
! 185: return cli_read_passphrase(prompt, 0, echo_enable);
! 186: }
! 187:
! 188: void
! 189: cli_mesg(char* mesg)
! 190: {
! 191: cli_open(0);
! 192: cli_write(mesg, strlen(mesg));
! 193: cli_write("\n", strlen("\n"));
! 194: cli_close();
! 195: return;
! 196: }