1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, 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 } 163 else { 164 RingTheBell(); 165 i = i - 1; 166 } 167 } 168 else if(buffer[i-1] != 13) 169 putchar('*'); 170 171 } while((buffer[i-1] != 13) && (i < buflen)); 172 buffer[i-1] = 0; 173 printf("\r\n"); 174 return buffer; 175} 176#endif /* __NOVELL_LIBC__ */ 177#define DONE 178#endif /* NETWARE */ 179 180#ifndef DONE /* not previously provided */ 181 182#ifdef HAVE_TERMIOS_H 183#define struct_term struct termios 184#else 185#ifdef HAVE_TERMIO_H 186#define struct_term struct termio 187#else 188#undef struct_term 189#endif 190#endif 191 192static bool ttyecho(bool enable, int fd) 193{ 194#ifdef struct_term 195 static struct_term withecho; 196 static struct_term noecho; 197#endif 198 if(!enable) { 199 /* disable echo by extracting the current 'withecho' mode and remove the 200 ECHO bit and set back the struct */ 201#ifdef HAVE_TERMIOS_H 202 tcgetattr(fd, &withecho); 203 noecho = withecho; 204 noecho.c_lflag &= ~ECHO; 205 tcsetattr(fd, TCSANOW, &noecho); 206#else /* HAVE_TERMIOS_H */ 207#ifdef HAVE_TERMIO_H 208 ioctl(fd, TCGETA, &withecho); 209 noecho = withecho; 210 noecho.c_lflag &= ~ECHO; 211 ioctl(fd, TCSETA, &noecho); 212#else /* HAVE_TERMIO_H */ 213/* neither HAVE_TERMIO_H nor HAVE_TERMIOS_H, we can't disable echo! */ 214 (void)fd; /* prevent compiler warning on unused variable */ 215 return FALSE; /* not disabled */ 216#endif 217#endif 218 return TRUE; /* disabled */ 219 } 220 else { 221 /* re-enable echo, assumes we disabled it before (and set the structs we 222 now use to reset the terminal status) */ 223#ifdef HAVE_TERMIOS_H 224 tcsetattr(fd, TCSAFLUSH, &withecho); 225#else /* HAVE_TERMIOS_H */ 226#ifdef HAVE_TERMIO_H 227 ioctl(fd, TCSETA, &withecho); 228#else 229/* neither HAVE_TERMIO_H nor HAVE_TERMIOS_H */ 230 return FALSE; /* not enabled */ 231#endif 232#endif 233 return TRUE; /* enabled */ 234 } 235} 236 237char *getpass_r(const char *prompt, /* prompt to display */ 238 char *password, /* buffer to store password in */ 239 size_t buflen) /* size of buffer to store password in */ 240{ 241 ssize_t nread; 242 bool disabled; 243 int fd=open("/dev/tty", O_RDONLY); 244 if(-1 == fd) 245 fd = 1; /* use stdin if the tty couldn't be used */ 246 247 disabled = ttyecho(FALSE, fd); /* disable terminal echo */ 248 249 fputs(prompt, stderr); 250 nread=read(fd, password, buflen); 251 if(nread > 0) 252 password[--nread]=0; /* zero terminate where enter is stored */ 253 else 254 password[0]=0; /* got nothing */ 255 256 if(disabled) { 257 /* if echo actually was disabled, add a newline */ 258 fputs("\n", stderr); 259 (void)ttyecho(TRUE, fd); /* enable echo */ 260 } 261 262 if(1 != fd) 263 close(fd); 264 265 return password; /* return pointer to buffer */ 266} 267 268#endif /* DONE */ 269#endif /* HAVE_GETPASS_R */ 270