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

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