Annotation of src/usr.bin/ssh/cli.c, Revision 1.6
1.1 markus 1: #include "includes.h"
1.6 ! markus 2: RCSID("$OpenBSD: cli.c,v 1.5 2001/01/08 08:50:29 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++) {
141: if (buf[i] == '\n')
142: *p++ = buf[i];
143: else
144: p = vis(p, buf[i], 0, 0);
145: }
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: }