/***************************************************************************1* _ _ ____ _2* Project ___| | | | _ \| |3* / __| | | | |_) | |4* | (__| |_| | _ <| |___5* \___|\___/|_| \_\_____|6*7* Copyright (C) Daniel Stenberg, <[email protected]>, et al.8*9* This software is licensed as described in the file COPYING, which10* you should have received as part of this distribution. The terms11* are also available at https://curl.se/docs/copyright.html.12*13* You may opt to use, copy, modify, merge, publish, distribute and/or sell14* copies of the Software, and permit persons to whom the Software is15* furnished to do so, under the terms of the COPYING file.16*17* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY18* KIND, either express or implied.19*20* SPDX-License-Identifier: curl21*22***************************************************************************/23#include "tool_setup.h"2425#if defined(__AMIGA__) && !defined(__amigaos4__)26# undef HAVE_TERMIOS_H27#endif2829#ifndef HAVE_GETPASS_R30/* this file is only for systems without getpass_r() */3132#ifdef HAVE_TERMIOS_H33# include <termios.h>34#elif defined(HAVE_TERMIO_H)35# include <termio.h>36#endif3738#ifdef __VMS39# include descrip40# include starlet41# include iodef42#endif4344#if defined(_WIN32) && !defined(UNDER_CE)45# include <conio.h>46#endif4748#ifdef HAVE_UNISTD_H49#include <unistd.h>50#endif51#include "tool_getpass.h"5253#include "memdebug.h" /* keep this as LAST include */5455#ifdef __VMS56/* VMS implementation */57char *getpass_r(const char *prompt, char *buffer, size_t buflen)58{59long sts;60short chan;6162/* MSK, 23-JAN-2004, iosbdef.h was not in VAX V7.2 or CC 6.4 */63/* distribution so I created this. May revert back later to */64/* struct _iosb iosb; */65struct _iosb66{67short int iosb$w_status; /* status */68short int iosb$w_bcnt; /* byte count */69int unused; /* unused */70} iosb;7172$DESCRIPTOR(ttdesc, "TT");7374buffer[0] = '\0';75sts = sys$assign(&ttdesc, &chan, 0, 0);76if(sts & 1) {77sts = sys$qiow(0, chan,78IO$_READPROMPT | IO$M_NOECHO,79&iosb, 0, 0, buffer, buflen, 0, 0,80prompt, strlen(prompt));8182if((sts & 1) && (iosb.iosb$w_status & 1))83buffer[iosb.iosb$w_bcnt] = '\0';8485sys$dassgn(chan);86}87return buffer; /* we always return success */88}89#define DONE90#endif /* __VMS */9192#ifdef _WIN329394char *getpass_r(const char *prompt, char *buffer, size_t buflen)95{96size_t i;97fputs(prompt, tool_stderr);9899for(i = 0; i < buflen; i++) {100buffer[i] = (char)_getch();101if(buffer[i] == '\r' || buffer[i] == '\n') {102buffer[i] = '\0';103break;104}105else106if(buffer[i] == '\b')107/* remove this letter and if this is not the first key, remove the108previous one as well */109i = i - (i >= 1 ? 2 : 1);110}111/* since echo is disabled, print a newline */112fputs("\n", tool_stderr);113/* if user did not hit ENTER, terminate buffer */114if(i == buflen)115buffer[buflen-1] = '\0';116117return buffer; /* we always return success */118}119#define DONE120#endif /* _WIN32 && !UNDER_CE */121122#ifndef DONE /* not previously provided */123124#ifdef HAVE_TERMIOS_H125# define struct_term struct termios126#elif defined(HAVE_TERMIO_H)127# define struct_term struct termio128#else129# undef struct_term130#endif131132static bool ttyecho(bool enable, int fd)133{134#ifdef struct_term135static struct_term withecho;136static struct_term noecho;137#endif138if(!enable) {139/* disable echo by extracting the current 'withecho' mode and remove the140ECHO bit and set back the struct */141#ifdef HAVE_TERMIOS_H142tcgetattr(fd, &withecho);143noecho = withecho;144noecho.c_lflag &= ~(tcflag_t)ECHO;145tcsetattr(fd, TCSANOW, &noecho);146#elif defined(HAVE_TERMIO_H)147ioctl(fd, TCGETA, &withecho);148noecho = withecho;149noecho.c_lflag &= ~(tcflag_t)ECHO;150ioctl(fd, TCSETA, &noecho);151#else152/* neither HAVE_TERMIO_H nor HAVE_TERMIOS_H, we cannot disable echo! */153(void)fd;154return FALSE; /* not disabled */155#endif156return TRUE; /* disabled */157}158/* re-enable echo, assumes we disabled it before (and set the structs we159now use to reset the terminal status) */160#ifdef HAVE_TERMIOS_H161tcsetattr(fd, TCSAFLUSH, &withecho);162#elif defined(HAVE_TERMIO_H)163ioctl(fd, TCSETA, &withecho);164#else165return FALSE; /* not enabled */166#endif167return TRUE; /* enabled */168}169170char *getpass_r(const char *prompt, /* prompt to display */171char *password, /* buffer to store password in */172size_t buflen) /* size of buffer to store password in */173{174ssize_t nread;175bool disabled;176int fd = curlx_open("/dev/tty", O_RDONLY);177if(fd == -1)178fd = STDIN_FILENO; /* use stdin if the tty could not be used */179180disabled = ttyecho(FALSE, fd); /* disable terminal echo */181182fputs(prompt, tool_stderr);183nread = read(fd, password, buflen);184if(nread > 0)185password[--nread] = '\0'; /* null-terminate where enter is stored */186else187password[0] = '\0'; /* got nothing */188189if(disabled) {190/* if echo actually was disabled, add a newline */191fputs("\n", tool_stderr);192(void)ttyecho(TRUE, fd); /* enable echo */193}194195if(STDIN_FILENO != fd)196close(fd);197198return password; /* return pointer to buffer */199}200201#endif /* DONE */202#endif /* HAVE_GETPASS_R */203204205