[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.2.2.1

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