1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel (at) 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 https://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 */ 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 = 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