Update tag value for tizen 2.0 build
[external/curl.git] / src / getpass.c
1 /***************************************************************************
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 */
62 char *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
109 char *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>
143 char *getpass_r(const char *prompt, char *buffer, size_t buflen)
144 {
145   return getpassword(prompt, buffer, buflen);
146 }
147 #else
148 #include <nwconio.h>
149 char *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
190 static 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
235 char *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 */