]> andersk Git - openssh.git/blob - cli.c
missed sshconnect.c part of:
[openssh.git] / cli.c
1 #include "includes.h"
2 RCSID("$OpenBSD: cli.c,v 1.9 2001/02/10 12:44:02 markus Exp $");
3
4 #include "xmalloc.h"
5 #include "log.h"
6 #include "cli.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(_PATH_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(void)
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(int sig)
58 {
59         intr = 1;
60 }
61
62 static void
63 cli_echo_disable(void)
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(void)
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(const 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' || buf[i] == '\r')
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                         xfree(output);
151                         return -1;
152                 }
153         }
154         xfree(output);
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(const 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 }
This page took 0.165004 seconds and 5 git commands to generate.