Skip to content
Snippets Groups Projects
getpass.c 6.35 KiB
Newer Older
  • Learn to ignore specific revisions
  • /***************************************************************************
     *                                  _   _ ____  _
     *  Project                     ___| | | |  _ \| |
     *                             / __| | | | |_) | |
     *                            | (__| |_| |  _ <| |___
     *                             \___|\___/|_| \_\_____|
    
     * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
    
     * This software is licensed as described in the file COPYING, which
     * you should have received as part of this distribution. The terms
     * are also available at http://curl.haxx.se/docs/copyright.html.
    
     * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     * copies of the Software, and permit persons to whom the Software is
     * furnished to do so, under the terms of the COPYING file.
    
     * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     * KIND, either express or implied.
    
     * $Id$
     ***************************************************************************/
    
    /* This file is a reimplementation of the previous one, due to license
       problems. */
    
    #ifndef HAVE_GETPASS_R
    /* this file is only for systems without getpass_r() */
    
    #include <stdio.h>
    #include <string.h>
    
    
    #ifdef HAVE_UNISTD_H
    #include <unistd.h>
    #endif
    
    #include "getpass.h"
    
    #ifdef HAVE_FCNTL_H
    #include <fcntl.h>
    #endif
    #ifdef HAVE_TERMIOS_H
    #include <termios.h>
    #else
    #ifdef HAVE_TERMIO_H
    #include <termio.h>
    #endif
    #endif
    
    /* The last #include file should be: */
    #if defined(CURLDEBUG) && defined(CURLTOOLDEBUG)
    #include "memdebug.h"
    #endif
    
    #ifdef VMS
    /* VMS implementation */
    
    #include descrip
    #include starlet
    #include iodef
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    /* #include iosbdef */
    
    char *getpass_r(const char *prompt, char *buffer, size_t buflen)
    {
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      /* MSK, 23-JAN-2004, iosbdef.h wasn't in VAX V7.2 or CC 6.4  */
      /* distribution so I created this.  May revert back later to */
      /* struct _iosb iosb;                                        */
      struct _iosb
         {
         short int iosb$w_status; /* status     */
         short int iosb$w_bcnt;   /* byte count */
         int       unused;        /* unused     */
         } iosb;
    
    
      $DESCRIPTOR(ttdesc, "TT");
    
      buffer[0]='\0';
      sts = sys$assign(&ttdesc, &chan,0,0);
      if (sts & 1) {
        sts = sys$qiow(0, chan,
                       IO$_READPROMPT | IO$M_NOECHO,
                       &iosb, 0, 0, buffer, buflen, 0, 0,
                       prompt, strlen(prompt));
    
        if((sts & 1) && (iosb.iosb$w_status&1))
          buffer[iosb.iosb$w_bcnt] = '\0';
    
        sts = sys$dassgn(chan);
      }
      return buffer; /* we always return success */
    
    char *getpass_r(const char *prompt, char *buffer, size_t buflen)
    
      for(i=0; i<buflen; i++) {
        buffer[i] = getch();
        if ( buffer[i] == '\r' ) {
          buffer[i] = 0;
          break;
        }
    
        else
          if ( buffer[i] == '\b')
            /* remove this letter and if this is not the first key, remove the
               previous one as well */
            i = i - (i>=1?2:1);
    
      }
      /* if user didn't hit ENTER, terminate buffer */
      if (i==buflen)
        buffer[buflen-1]=0;
    
      return buffer; /* we always return success */
    }
    
    #ifdef NETWARE
    /* NetWare implementation */
    
    #ifdef __NOVELL_LIBC__
    
    #include <screen.h>
    char *getpass_r(const char *prompt, char *buffer, size_t buflen)
    {
    
      return getpassword(prompt, buffer, buflen);
    
    #else
    #include <nwconio.h>
    char *getpass_r(const char *prompt, char *buffer, size_t buflen)
    {
    
        buffer[i++] = getch();
        if (buffer[i-1] == '\b') {
          /* remove this letter and if this is not the first key,
             remove the previous one as well */
          if (i > 1) {   
            printf("\b \b");
            i = i - 2;
          } else {
            RingTheBell();
            i = i - 1;
          }
        } else if (buffer[i-1] != 13) {
          putchar('*');
    
      } while ((buffer[i-1] != 13) && (i < buflen));
      buffer[i-1] = 0;
      printf("\r\n");
    
      return buffer;
    }
    #endif /* __NOVELL_LIBC__ */
    
    Guenter Knauf's avatar
    Guenter Knauf committed
    #endif /* NETWARE */
    
    #ifndef DONE /* not previously provided */
    
    #ifdef HAVE_TERMIOS_H
    #define struct_term struct termios
    #else
    #ifdef HAVE_TERMIO_H
    #define struct_term  struct termio
    #else
    #undef struct_term
    #endif
    
    static bool ttyecho(bool enable, int fd)
    {
    #ifdef struct_term
      static struct_term withecho;
      static struct_term noecho;
    #endif
      if(!enable) {
      /* dissable echo by extracting the current 'withecho' mode and remove the
         ECHO bit and set back the struct */
    #ifdef HAVE_TERMIOS_H
        tcgetattr(fd, &withecho);
        noecho = withecho;
        noecho.c_lflag &= ~ECHO;
        tcsetattr(fd, TCSANOW, &noecho);
    #else /* HAVE_TERMIOS_H */
    #ifdef HAVE_TERMIO_H
        ioctl(fd, TCGETA, &withecho);
        noecho = withecho;
        noecho.c_lflag &= ~ECHO;
        ioctl(fd, TCSETA, &noecho);
    #else /* HAVE_TERMIO_H */
    /* neither HAVE_TERMIO_H nor HAVE_TERMIOS_H, we can't disable echo! */
        (void)fd; /* prevent compiler warning on unused variable */
        return FALSE; /* not disabled */
    #endif
    #endif
        return TRUE; /* disabled */
      }
      else {
        /* re-enable echo, assumes we disabled it before (and set the structs we
           now use to reset the terminal status) */
    #ifdef HAVE_TERMIOS_H
        tcsetattr(fd, TCSAFLUSH, &withecho);
    #else /* HAVE_TERMIOS_H */
    #ifdef HAVE_TERMIO_H
        ioctl(fd, TCSETA, &withecho);
    #else
    /* neither HAVE_TERMIO_H nor HAVE_TERMIOS_H */
        return FALSE; /* not enabled */
    #endif
    #endif
        return TRUE; /* enabled */
      }
    }
    
    char *getpass_r(const char *prompt, /* prompt to display */
                    char *password,     /* buffer to store password in */
                    size_t buflen)      /* size of buffer to store password in */
    
      ssize_t nread;
      bool disabled;
      int fd=open("/dev/tty", O_RDONLY);
      if(-1 == fd)
        fd = 1; /* use stdin if the tty couldn't be used */
    
      disabled = ttyecho(FALSE, fd); /* disable terminal echo */
    
      fputs(prompt, stderr);
      nread=read(fd, password, buflen);
      if(nread > 0)
        password[--nread]=0; /* zero terminate where enter is stored */
      else
        password[0]=0; /* got nothing */
    
      if(disabled) {
        /* if echo actually was disabled, add a newline */
        fputs("\n", stderr);
    
        (void)ttyecho(TRUE, fd); /* enable echo */
    
      }
    
      if(1 != fd)
        close(fd);
    
      return password; /* return pointer to buffer */
    
    Gisle Vanem's avatar
    Gisle Vanem committed
    #endif /* DONE */