Home | History | Annotate | Download | only in src
      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