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