blob: b441a5ad9dcb9732d27d82ecb27e0aadf98007e6 [file] [log] [blame]
9487f7f2011-08-03 07:05:30 -07001/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23/* This file is a reimplementation of the previous one, due to license
24 problems. */
25
26#include "setup.h"
27
28#ifndef HAVE_GETPASS_R
29/* this file is only for systems without getpass_r() */
30
31#include <stdio.h>
32#include <string.h>
33
34#ifdef HAVE_UNISTD_H
35#include <unistd.h>
36#endif
37
38#include "getpass.h"
39
40#ifdef HAVE_FCNTL_H
41#include <fcntl.h>
42#endif
43#ifdef HAVE_TERMIOS_H
44#include <termios.h>
45#else
46#ifdef HAVE_TERMIO_H
47#include <termio.h>
48#endif
49#endif
50
51/* The last #include file should be: */
52#if defined(CURLDEBUG) && defined(CURLTOOLDEBUG)
53#include "memdebug.h"
54#endif
55
56#ifdef __VMS
57/* VMS implementation */
58#include descrip
59#include starlet
60#include iodef
61/* #include iosbdef */
62char *getpass_r(const char *prompt, char *buffer, size_t buflen)
63{
64 long sts;
65 short chan;
66
67 /* MSK, 23-JAN-2004, iosbdef.h wasn't in VAX V7.2 or CC 6.4 */
68 /* distribution so I created this. May revert back later to */
69 /* struct _iosb iosb; */
70 struct _iosb
71 {
72 short int iosb$w_status; /* status */
73 short int iosb$w_bcnt; /* byte count */
74 int unused; /* unused */
75 } iosb;
76
77 $DESCRIPTOR(ttdesc, "TT");
78
79 buffer[0]='\0';
80 sts = sys$assign(&ttdesc, &chan,0,0);
81 if (sts & 1) {
82 sts = sys$qiow(0, chan,
83 IO$_READPROMPT | IO$M_NOECHO,
84 &iosb, 0, 0, buffer, buflen, 0, 0,
85 prompt, strlen(prompt));
86
87 if((sts & 1) && (iosb.iosb$w_status&1))
88 buffer[iosb.iosb$w_bcnt] = '\0';
89
90 sts = sys$dassgn(chan);
91 }
92 return buffer; /* we always return success */
93}
94#define DONE
95#endif /* __VMS */
96
97
98#ifdef WIN32
99/* Windows implementation */
100#include <conio.h>
101#endif
102
103#ifdef __SYMBIAN32__
104#define getch() getchar()
105#endif
106
107#if defined(WIN32) || defined(__SYMBIAN32__)
108
109char *getpass_r(const char *prompt, char *buffer, size_t buflen)
110{
111 size_t i;
112 fputs(prompt, stderr);
113
114 for(i=0; i<buflen; i++) {
115 buffer[i] = (char)getch();
116 if ( buffer[i] == '\r' || buffer[i] == '\n' ) {
117 buffer[i] = 0;
118 break;
119 }
120 else
121 if ( buffer[i] == '\b')
122 /* remove this letter and if this is not the first key, remove the
123 previous one as well */
124 i = i - (i>=1?2:1);
125 }
126#ifndef __SYMBIAN32__
127 /* since echo is disabled, print a newline */
128 fputs("\n", stderr);
129#endif
130 /* if user didn't hit ENTER, terminate buffer */
131 if (i==buflen)
132 buffer[buflen-1]=0;
133
134 return buffer; /* we always return success */
135}
136#define DONE
137#endif /* WIN32 || __SYMBIAN32__ */
138
139#ifdef NETWARE
140/* NetWare implementation */
141#ifdef __NOVELL_LIBC__
142#include <screen.h>
143char *getpass_r(const char *prompt, char *buffer, size_t buflen)
144{
145 return getpassword(prompt, buffer, buflen);
146}
147#else
148#include <nwconio.h>
149char *getpass_r(const char *prompt, char *buffer, size_t buflen)
150{
151 size_t i = 0;
152
153 printf("%s", prompt);
154 do {
155 buffer[i++] = getch();
156 if (buffer[i-1] == '\b') {
157 /* remove this letter and if this is not the first key,
158 remove the previous one as well */
159 if (i > 1) {
160 printf("\b \b");
161 i = i - 2;
162 } else {
163 RingTheBell();
164 i = i - 1;
165 }
166 } else if (buffer[i-1] != 13) {
167 putchar('*');
168 }
169 } while ((buffer[i-1] != 13) && (i < buflen));
170 buffer[i-1] = 0;
171 printf("\r\n");
172 return buffer;
173}
174#endif /* __NOVELL_LIBC__ */
175#define DONE
176#endif /* NETWARE */
177
178#ifndef DONE /* not previously provided */
179
180#ifdef HAVE_TERMIOS_H
181#define struct_term struct termios
182#else
183#ifdef HAVE_TERMIO_H
184#define struct_term struct termio
185#else
186#undef struct_term
187#endif
188#endif
189
190static bool ttyecho(bool enable, int fd)
191{
192#ifdef struct_term
193 static struct_term withecho;
194 static struct_term noecho;
195#endif
196 if(!enable) {
197 /* disable echo by extracting the current 'withecho' mode and remove the
198 ECHO bit and set back the struct */
199#ifdef HAVE_TERMIOS_H
200 tcgetattr(fd, &withecho);
201 noecho = withecho;
202 noecho.c_lflag &= ~ECHO;
203 tcsetattr(fd, TCSANOW, &noecho);
204#else /* HAVE_TERMIOS_H */
205#ifdef HAVE_TERMIO_H
206 ioctl(fd, TCGETA, &withecho);
207 noecho = withecho;
208 noecho.c_lflag &= ~ECHO;
209 ioctl(fd, TCSETA, &noecho);
210#else /* HAVE_TERMIO_H */
211/* neither HAVE_TERMIO_H nor HAVE_TERMIOS_H, we can't disable echo! */
212 (void)fd; /* prevent compiler warning on unused variable */
213 return FALSE; /* not disabled */
214#endif
215#endif
216 return TRUE; /* disabled */
217 }
218 else {
219 /* re-enable echo, assumes we disabled it before (and set the structs we
220 now use to reset the terminal status) */
221#ifdef HAVE_TERMIOS_H
222 tcsetattr(fd, TCSAFLUSH, &withecho);
223#else /* HAVE_TERMIOS_H */
224#ifdef HAVE_TERMIO_H
225 ioctl(fd, TCSETA, &withecho);
226#else
227/* neither HAVE_TERMIO_H nor HAVE_TERMIOS_H */
228 return FALSE; /* not enabled */
229#endif
230#endif
231 return TRUE; /* enabled */
232 }
233}
234
235char *getpass_r(const char *prompt, /* prompt to display */
236 char *password, /* buffer to store password in */
237 size_t buflen) /* size of buffer to store password in */
238{
239 ssize_t nread;
240 bool disabled;
241 int fd=open("/dev/tty", O_RDONLY);
242 if(-1 == fd)
243 fd = 1; /* use stdin if the tty couldn't be used */
244
245 disabled = ttyecho(FALSE, fd); /* disable terminal echo */
246
247 fputs(prompt, stderr);
248 nread=read(fd, password, buflen);
249 if(nread > 0)
250 password[--nread]=0; /* zero terminate where enter is stored */
251 else
252 password[0]=0; /* got nothing */
253
254 if(disabled) {
255 /* if echo actually was disabled, add a newline */
256 fputs("\n", stderr);
257 (void)ttyecho(TRUE, fd); /* enable echo */
258 }
259
260 if(1 != fd)
261 close(fd);
262
263 return password; /* return pointer to buffer */
264}
265
266#endif /* DONE */
267#endif /* HAVE_GETPASS_R */