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

1.1       markus      1: #include "includes.h"
1.5     ! markus      2: RCSID("$OpenBSD: cli.c,v 1.4 2001/01/07 21:26:55 markus Exp $");
1.1       markus      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);
1.3       markus    149:                if (ret == -1) {
1.4       markus    150:                        xfree(output);
1.1       markus    151:                        return -1;
1.3       markus    152:                }
1.1       markus    153:        }
1.5     ! markus    154:        xfree(output);
1.1       markus    155:        return 0;
                    156: }
                    157:
                    158: /*
                    159:  * Presents a prompt and returns the response allocated with xmalloc().
                    160:  * Uses /dev/tty or stdin/out depending on arg.  Optionally disables echo
                    161:  * of response depending on arg.  Tries to ensure that no other userland
                    162:  * buffer is storing the response.
                    163:  */
                    164: char*
                    165: cli_read_passphrase(char* prompt, int from_stdin, int echo_enable)
                    166: {
                    167:        char    buf[BUFSIZ];
                    168:        char*   p;
                    169:
                    170:        if (!cli_open(from_stdin))
                    171:                fatal("Cannot read passphrase.");
                    172:
                    173:        fflush(stdout);
                    174:
                    175:        cli_write(prompt, strlen(prompt));
                    176:        cli_read(buf, sizeof buf, echo_enable);
                    177:
                    178:        cli_close();
                    179:
                    180:        p = xstrdup(buf);
                    181:        memset(buf, 0, sizeof(buf));
                    182:        return (p);
                    183: }
                    184:
                    185: char*
                    186: cli_prompt(char* prompt, int echo_enable)
                    187: {
                    188:        return cli_read_passphrase(prompt, 0, echo_enable);
                    189: }
                    190:
                    191: void
                    192: cli_mesg(char* mesg)
                    193: {
                    194:        cli_open(0);
                    195:        cli_write(mesg, strlen(mesg));
                    196:        cli_write("\n", strlen("\n"));
                    197:        cli_close();
                    198:        return;
                    199: }