1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2015, 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#ifdef HAVE_UNISTD_H 56#include <unistd.h> 57#endif 58#include "tool_getpass.h" 59 60#include "memdebug.h" /* keep this as LAST include */ 61 62#ifdef __VMS 63/* VMS implementation */ 64char *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 105char *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__ 138char *getpass_r(const char *prompt, char *buffer, size_t buflen) 139{ 140 return getpassword(prompt, buffer, buflen); 141} 142#else 143char *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 184static 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 224char *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 = STDIN_FILENO; /* 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(STDIN_FILENO != fd) 250 close(fd); 251 252 return password; /* return pointer to buffer */ 253} 254 255#endif /* DONE */ 256#endif /* HAVE_GETPASS_R */ 257