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