[BACK]Return to cli.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

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: }