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