/***************************************************************************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_FCNTL_H33# include <fcntl.h>34#endif3536#ifdef HAVE_TERMIOS_H37# include <termios.h>38#elif defined(HAVE_TERMIO_H)39# include <termio.h>40#endif4142#ifdef __VMS43# include descrip44# include starlet45# include iodef46#endif4748#if defined(_WIN32) && !defined(UNDER_CE)49# include <conio.h>50#endif5152#ifdef HAVE_UNISTD_H53#include <unistd.h>54#endif55#include "tool_getpass.h"5657#include <memdebug.h> /* keep this as LAST include */5859#ifdef __VMS60/* VMS implementation */61char *getpass_r(const char *prompt, char *buffer, size_t buflen)62{63long sts;64short chan;6566/* MSK, 23-JAN-2004, iosbdef.h was not in VAX V7.2 or CC 6.4 */67/* distribution so I created this. May revert back later to */68/* struct _iosb iosb; */69struct _iosb70{71short int iosb$w_status; /* status */72short int iosb$w_bcnt; /* byte count */73int unused; /* unused */74} iosb;7576$DESCRIPTOR(ttdesc, "TT");7778buffer[0] = '\0';79sts = sys$assign(&ttdesc, &chan, 0, 0);80if(sts & 1) {81sts = sys$qiow(0, chan,82IO$_READPROMPT | IO$M_NOECHO,83&iosb, 0, 0, buffer, buflen, 0, 0,84prompt, strlen(prompt));8586if((sts & 1) && (iosb.iosb$w_status & 1))87buffer[iosb.iosb$w_bcnt] = '\0';8889sys$dassgn(chan);90}91return buffer; /* we always return success */92}93#define DONE94#endif /* __VMS */9596#ifdef _WIN329798char *getpass_r(const char *prompt, char *buffer, size_t buflen)99{100size_t i;101fputs(prompt, tool_stderr);102103for(i = 0; i < buflen; i++) {104buffer[i] = (char)_getch();105if(buffer[i] == '\r' || buffer[i] == '\n') {106buffer[i] = '\0';107break;108}109else110if(buffer[i] == '\b')111/* remove this letter and if this is not the first key, remove the112previous one as well */113i = i - (i >= 1 ? 2 : 1);114}115/* since echo is disabled, print a newline */116fputs("\n", tool_stderr);117/* if user did not hit ENTER, terminate buffer */118if(i == buflen)119buffer[buflen-1] = '\0';120121return buffer; /* we always return success */122}123#define DONE124#endif /* _WIN32 && !UNDER_CE */125126#ifndef DONE /* not previously provided */127128#ifdef HAVE_TERMIOS_H129# define struct_term struct termios130#elif defined(HAVE_TERMIO_H)131# define struct_term struct termio132#else133# undef struct_term134#endif135136static bool ttyecho(bool enable, int fd)137{138#ifdef struct_term139static struct_term withecho;140static struct_term noecho;141#endif142if(!enable) {143/* disable echo by extracting the current 'withecho' mode and remove the144ECHO bit and set back the struct */145#ifdef HAVE_TERMIOS_H146tcgetattr(fd, &withecho);147noecho = withecho;148noecho.c_lflag &= ~(tcflag_t)ECHO;149tcsetattr(fd, TCSANOW, &noecho);150#elif defined(HAVE_TERMIO_H)151ioctl(fd, TCGETA, &withecho);152noecho = withecho;153noecho.c_lflag &= ~(tcflag_t)ECHO;154ioctl(fd, TCSETA, &noecho);155#else156/* neither HAVE_TERMIO_H nor HAVE_TERMIOS_H, we cannot disable echo! */157(void)fd;158return FALSE; /* not disabled */159#endif160return TRUE; /* disabled */161}162/* re-enable echo, assumes we disabled it before (and set the structs we163now use to reset the terminal status) */164#ifdef HAVE_TERMIOS_H165tcsetattr(fd, TCSAFLUSH, &withecho);166#elif defined(HAVE_TERMIO_H)167ioctl(fd, TCSETA, &withecho);168#else169return FALSE; /* not enabled */170#endif171return TRUE; /* enabled */172}173174char *getpass_r(const char *prompt, /* prompt to display */175char *password, /* buffer to store password in */176size_t buflen) /* size of buffer to store password in */177{178ssize_t nread;179bool disabled;180int fd = open("/dev/tty", O_RDONLY);181if(-1 == fd)182fd = STDIN_FILENO; /* use stdin if the tty could not be used */183184disabled = ttyecho(FALSE, fd); /* disable terminal echo */185186fputs(prompt, tool_stderr);187nread = read(fd, password, buflen);188if(nread > 0)189password[--nread] = '\0'; /* null-terminate where enter is stored */190else191password[0] = '\0'; /* got nothing */192193if(disabled) {194/* if echo actually was disabled, add a newline */195fputs("\n", tool_stderr);196(void)ttyecho(TRUE, fd); /* enable echo */197}198199if(STDIN_FILENO != fd)200close(fd);201202return password; /* return pointer to buffer */203}204205#endif /* DONE */206#endif /* HAVE_GETPASS_R */207208209