]> andersk Git - openssh.git/blob - cli.c
67a718b7ccc0b66b8cabaefa8210f51baf4a9bad
[openssh.git] / cli.c
1 #include "includes.h"
2 RCSID("$OpenBSD: cli.c,v 1.7 2001/02/04 15:32:23 stevesk Exp $");
3
4 #include "xmalloc.h"
5 #include "log.h"
6
7 static int cli_input = -1;
8 static int cli_output = -1;
9 static int cli_from_stdin = 0;
10
11 sigset_t oset;
12 sigset_t nset;
13 struct sigaction nsa;
14 struct sigaction osa;
15 struct termios ntio;
16 struct termios otio;
17 int echo_modified;
18
19 volatile int intr;
20
21 static int
22 cli_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
44 static void
45 cli_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
55 void
56 intrcatch()
57 {
58         intr = 1;
59 }
60
61 static void
62 cli_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
84 static void
85 cli_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
105 static int
106 cli_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
131 static int
132 cli_write(const char* buf, int size)
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++) {
139                 if (buf[i] == '\n')
140                         *p++ = buf[i];
141                 else
142                         p = vis(p, buf[i], 0, 0);
143         }
144         len = p - output;
145
146         for (pos = 0; pos < len; pos += ret) {
147                 ret = write(cli_output, output + pos, len - pos);
148                 if (ret == -1) {
149                         xfree(output);
150                         return -1;
151                 }
152         }
153         xfree(output);
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  */
163 char*
164 cli_read_passphrase(const char* prompt, int from_stdin, int echo_enable)
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
184 char*
185 cli_prompt(char* prompt, int echo_enable)
186 {
187         return cli_read_passphrase(prompt, 0, echo_enable);
188 }
189
190 void
191 cli_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.040233 seconds and 3 git commands to generate.