Revert "Update to 7.44.0"
[platform/upstream/curl.git] / src / tool_getpass.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2012, 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 #include "tool_setup.h"
23
24 #ifndef HAVE_GETPASS_R
25 /* this file is only for systems without getpass_r() */
26
27 #ifdef HAVE_FCNTL_H
28 #  include <fcntl.h>
29 #endif
30
31 #ifdef HAVE_TERMIOS_H
32 #  include <termios.h>
33 #elif defined(HAVE_TERMIO_H)
34 #  include <termio.h>
35 #endif
36
37 #ifdef __VMS
38 #  include descrip
39 #  include starlet
40 #  include iodef
41 #endif
42
43 #ifdef WIN32
44 #  include <conio.h>
45 #endif
46
47 #ifdef NETWARE
48 #  ifdef __NOVELL_LIBC__
49 #    include <screen.h>
50 #  else
51 #    include <nwconio.h>
52 #  endif
53 #endif
54
55 #define _MPRINTF_REPLACE
56 #include <curl/mprintf.h>
57
58 #include "tool_getpass.h"
59
60 #include "memdebug.h" /* keep this as LAST include */
61
62 #ifdef __VMS
63 /* VMS implementation */
64 char *getpass_r(const char *prompt, char *buffer, size_t buflen)
65 {
66   long sts;
67   short chan;
68
69   /* MSK, 23-JAN-2004, iosbdef.h wasn't in VAX V7.2 or CC 6.4  */
70   /* distribution so I created this.  May revert back later to */
71   /* struct _iosb iosb;                                        */
72   struct _iosb
73      {
74      short int iosb$w_status; /* status     */
75      short int iosb$w_bcnt;   /* byte count */
76      int       unused;        /* unused     */
77      } iosb;
78
79   $DESCRIPTOR(ttdesc, "TT");
80
81   buffer[0] = '\0';
82   sts = sys$assign(&ttdesc, &chan, 0, 0);
83   if(sts & 1) {
84     sts = sys$qiow(0, chan,
85                    IO$_READPROMPT | IO$M_NOECHO,
86                    &iosb, 0, 0, buffer, buflen, 0, 0,
87                    prompt, strlen(prompt));
88
89     if((sts & 1) && (iosb.iosb$w_status & 1))
90       buffer[iosb.iosb$w_bcnt] = '\0';
91
92     sts = sys$dassgn(chan);
93   }
94   return buffer; /* we always return success */
95 }
96 #define DONE
97 #endif /* __VMS */
98
99 #ifdef __SYMBIAN32__
100 #  define getch() getchar()
101 #endif
102
103 #if defined(WIN32) || defined(__SYMBIAN32__)
104
105 char *getpass_r(const char *prompt, char *buffer, size_t buflen)
106 {
107   size_t i;
108   fputs(prompt, stderr);
109
110   for(i = 0; i < buflen; i++) {
111     buffer[i] = (char)getch();
112     if(buffer[i] == '\r' || buffer[i] == '\n') {
113       buffer[i] = '\0';
114       break;
115     }
116     else
117       if(buffer[i] == '\b')
118         /* remove this letter and if this is not the first key, remove the
119            previous one as well */
120         i = i - (i >= 1 ? 2 : 1);
121   }
122 #ifndef __SYMBIAN32__
123   /* since echo is disabled, print a newline */
124   fputs("\n", stderr);
125 #endif
126   /* if user didn't hit ENTER, terminate buffer */
127   if(i == buflen)
128     buffer[buflen-1] = '\0';
129
130   return buffer; /* we always return success */
131 }
132 #define DONE
133 #endif /* WIN32 || __SYMBIAN32__ */
134
135 #ifdef NETWARE
136 /* NetWare implementation */
137 #ifdef __NOVELL_LIBC__
138 char *getpass_r(const char *prompt, char *buffer, size_t buflen)
139 {
140   return getpassword(prompt, buffer, buflen);
141 }
142 #else
143 char *getpass_r(const char *prompt, char *buffer, size_t buflen)
144 {
145   size_t i = 0;
146
147   printf("%s", prompt);
148   do {
149     buffer[i++] = getch();
150     if(buffer[i-1] == '\b') {
151       /* remove this letter and if this is not the first key,
152          remove the previous one as well */
153       if(i > 1) {
154         printf("\b \b");
155         i = i - 2;
156       }
157       else {
158         RingTheBell();
159         i = i - 1;
160       }
161     }
162     else if(buffer[i-1] != 13)
163       putchar('*');
164
165   } while((buffer[i-1] != 13) && (i < buflen));
166   buffer[i-1] = '\0';
167   printf("\r\n");
168   return buffer;
169 }
170 #endif /* __NOVELL_LIBC__ */
171 #define DONE
172 #endif /* NETWARE */
173
174 #ifndef DONE /* not previously provided */
175
176 #ifdef HAVE_TERMIOS_H
177 #  define struct_term  struct termios
178 #elif defined(HAVE_TERMIO_H)
179 #  define struct_term  struct termio
180 #else
181 #  undef  struct_term
182 #endif
183
184 static bool ttyecho(bool enable, int fd)
185 {
186 #ifdef struct_term
187   static struct_term withecho;
188   static struct_term noecho;
189 #endif
190   if(!enable) {
191     /* disable echo by extracting the current 'withecho' mode and remove the
192        ECHO bit and set back the struct */
193 #ifdef HAVE_TERMIOS_H
194     tcgetattr(fd, &withecho);
195     noecho = withecho;
196     noecho.c_lflag &= ~ECHO;
197     tcsetattr(fd, TCSANOW, &noecho);
198 #elif defined(HAVE_TERMIO_H)
199     ioctl(fd, TCGETA, &withecho);
200     noecho = withecho;
201     noecho.c_lflag &= ~ECHO;
202     ioctl(fd, TCSETA, &noecho);
203 #else
204     /* neither HAVE_TERMIO_H nor HAVE_TERMIOS_H, we can't disable echo! */
205     (void)fd;
206     return FALSE; /* not disabled */
207 #endif
208     return TRUE; /* disabled */
209   }
210   else {
211     /* re-enable echo, assumes we disabled it before (and set the structs we
212        now use to reset the terminal status) */
213 #ifdef HAVE_TERMIOS_H
214     tcsetattr(fd, TCSAFLUSH, &withecho);
215 #elif defined(HAVE_TERMIO_H)
216     ioctl(fd, TCSETA, &withecho);
217 #else
218     return FALSE; /* not enabled */
219 #endif
220     return TRUE; /* enabled */
221   }
222 }
223
224 char *getpass_r(const char *prompt, /* prompt to display */
225                 char *password,     /* buffer to store password in */
226                 size_t buflen)      /* size of buffer to store password in */
227 {
228   ssize_t nread;
229   bool disabled;
230   int fd = open("/dev/tty", O_RDONLY);
231   if(-1 == fd)
232     fd = 1; /* use stdin if the tty couldn't be used */
233
234   disabled = ttyecho(FALSE, fd); /* disable terminal echo */
235
236   fputs(prompt, stderr);
237   nread = read(fd, password, buflen);
238   if(nread > 0)
239     password[--nread] = '\0'; /* zero terminate where enter is stored */
240   else
241     password[0] = '\0'; /* got nothing */
242
243   if(disabled) {
244     /* if echo actually was disabled, add a newline */
245     fputs("\n", stderr);
246     (void)ttyecho(TRUE, fd); /* enable echo */
247   }
248
249   if(1 != fd)
250     close(fd);
251
252   return password; /* return pointer to buffer */
253 }
254
255 #endif /* DONE */
256 #endif /* HAVE_GETPASS_R */