Annotation of src/usr.bin/ssh/cli.c, Revision 1.3
1.1 markus 1: #include "includes.h"
1.3 ! markus 2: RCSID("$OpenBSD: cli.c,v 1.2 2000/10/16 09:38:44 djm 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) {
! 150: xfree(output)
1.1 markus 151: return -1;
1.3 ! markus 152: }
1.1 markus 153: }
1.3 ! 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: }