Hide password input on terminal - c
I want to mask my password while writing it with *.
I use Linux GCC for this code.
I know one solution is to use getch() function like this
#include <conio.h>
int main()
{
char c,password[10];
int i;
while( (c=getch())!= '\n');{
password[i] = c;
printf("*");
i++;
}
return 1;
}
but the problem is that GCC does not include conio.h file so, getch() is useless for me.
Does anyone have a solution?
In the Linux world, masking isn't usually done with asterisks, normally echoing is just turned off and the terminal displays blanks E.g. if you use su or log into a virtual terminal etc.
There is a library function to handle getting passwords, it won't mask the password with asterisks but will disable echoing of the password to terminal. I pulled this out of a linux book I have. I believe its part of the posix standard
#include <unistd.h>
char *getpass(const char *prompt);
/*Returns pointer to statically allocated input password string
on success, or NULL on error*/
The getpass() function first disables echoing and all processing of
terminal special characters (such as the interrupt character, normally
Control-C).
It then prints the string pointed to by prompt, and reads a line of
input, returning the null-terminated input string with the trailing
newline stripped, as its function result.
A google search for getpass() has a reference to the GNU implementation (should be in most linux distros) and some sample code for implementing your own if need be
http://www.gnu.org/s/hello/manual/libc/getpass.html
Their example for rolling your own:
#include <termios.h>
#include <stdio.h>
ssize_t
my_getpass (char **lineptr, size_t *n, FILE *stream)
{
struct termios old, new;
int nread;
/* Turn echoing off and fail if we can't. */
if (tcgetattr (fileno (stream), &old) != 0)
return -1;
new = old;
new.c_lflag &= ~ECHO;
if (tcsetattr (fileno (stream), TCSAFLUSH, &new) != 0)
return -1;
/* Read the password. */
nread = getline (lineptr, n, stream);
/* Restore terminal. */
(void) tcsetattr (fileno (stream), TCSAFLUSH, &old);
return nread;
}
If need be you could use this as the basis as modify it to display asterisks.
Without getch to rely on and avoiding the obsolete getpass, the recommended approach is to disable terminal ECHO through termios use. After a few searches to find a canned flexible password routine, I was surprised that very few for stand-alone use with C. Rather than simply recoding getch with termios c_lflag options, slightly more generalized approach takes just a few additions. Beyond replacing getch any routine should enforce a specified maximum length to prevent overflow, truncate if the user attempt to enter beyond the maximum, and warn if truncation occurs in some manner.
Below, the additions will allow reading from any FILE * input stream, limiting the length to a specified length, provide minimal editing (backspace) ability when taking input, allow the character mask to be specified or disabled completely, and finally return the length of the password entered. A warning was added when the password entered was truncated to the maximum or specified length.
Hopefully it will prove useful to others with this question looking for a similar solution:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#define MAXPW 32
/* read a string from fp into pw masking keypress with mask char.
getpasswd will read upto sz - 1 chars into pw, null-terminating
the resulting string. On success, the number of characters in
pw are returned, -1 otherwise.
*/
ssize_t getpasswd (char **pw, size_t sz, int mask, FILE *fp)
{
if (!pw || !sz || !fp) return -1; /* validate input */
#ifdef MAXPW
if (sz > MAXPW) sz = MAXPW;
#endif
if (*pw == NULL) { /* reallocate if no address */
void *tmp = realloc (*pw, sz * sizeof **pw);
if (!tmp)
return -1;
memset (tmp, 0, sz); /* initialize memory to 0 */
*pw = (char*) tmp;
}
size_t idx = 0; /* index, number of chars in read */
int c = 0;
struct termios old_kbd_mode; /* orig keyboard settings */
struct termios new_kbd_mode;
if (tcgetattr (0, &old_kbd_mode)) { /* save orig settings */
fprintf (stderr, "%s() error: tcgetattr failed.\n", __func__);
return -1;
} /* copy old to new */
memcpy (&new_kbd_mode, &old_kbd_mode, sizeof(struct termios));
new_kbd_mode.c_lflag &= ~(ICANON | ECHO); /* new kbd flags */
new_kbd_mode.c_cc[VTIME] = 0;
new_kbd_mode.c_cc[VMIN] = 1;
if (tcsetattr (0, TCSANOW, &new_kbd_mode)) {
fprintf (stderr, "%s() error: tcsetattr failed.\n", __func__);
return -1;
}
/* read chars from fp, mask if valid char specified */
while (((c = fgetc (fp)) != '\n' && c != EOF && idx < sz - 1) ||
(idx == sz - 1 && c == 127))
{
if (c != 127) {
if (31 < mask && mask < 127) /* valid ascii char */
fputc (mask, stdout);
(*pw)[idx++] = c;
}
else if (idx > 0) { /* handle backspace (del) */
if (31 < mask && mask < 127) {
fputc (0x8, stdout);
fputc (' ', stdout);
fputc (0x8, stdout);
}
(*pw)[--idx] = 0;
}
}
(*pw)[idx] = 0; /* null-terminate */
/* reset original keyboard */
if (tcsetattr (0, TCSANOW, &old_kbd_mode)) {
fprintf (stderr, "%s() error: tcsetattr failed.\n", __func__);
return -1;
}
if (idx == sz - 1 && c != '\n') /* warn if pw truncated */
fprintf (stderr, " (%s() warning: truncated at %zu chars.)\n",
__func__, sz - 1);
return idx; /* number of chars in passwd */
}
A simple program showing the use would be as follows. If using a static array of character for holding the password, just insure a pointer is passed to the function.
int main (void ) {
char pw[MAXPW] = {0};
char *p = pw;
FILE *fp = stdin;
ssize_t nchr = 0;
printf ( "\n Enter password: ");
nchr = getpasswd (&p, MAXPW, '*', fp);
printf ("\n you entered : %s (%zu chars)\n", p, nchr);
printf ( "\n Enter password: ");
nchr = getpasswd (&p, MAXPW, 0, fp);
printf ("\n you entered : %s (%zu chars)\n\n", p, nchr);
return 0;
}
Example Output
$ ./bin/getpasswd2
Enter password: ******
you entered : 123456 (6 chars)
Enter password:
you entered : abcdef (6 chars)
The functionality of getch (which is a non-standard, Windows function) can be emulated with this code:
#include <termios.h>
#include <unistd.h>
int getch() {
struct termios oldt, newt;
int ch;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newt);
ch = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
return ch;
}
Note that your approach is not perfect - it's better to use something like ncurses or another terminal library to handle these things.
You can create your own getch() function on Linux in this manner.
int getch() {
struct termios oldtc, newtc;
int ch;
tcgetattr(STDIN_FILENO, &oldtc);
newtc = oldtc;
newtc.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newtc);
ch=getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &oldtc);
return ch;
}
Demo code:
int main(int argc, char **argv) {
int ch;
printf("Press x to exit.\n\n");
for (;;) {
ch = getch();
printf("ch = %c (%d)\n", ch, ch);
if(ch == 'x')
break;
}
return 0;
}
Your method is correct, however you'll need to turn off terminal echo while the password is being entered:
#include <sgtty.h>
void echo_off()
{
struct sgttyb state;
(void)ioctl(0, (int)TIOCGETP, (char *)&state);
state.sg_flags &= ~ECHO;
(void)ioctl(0, (int)TIOCSETP, (char *)&state);
}
void echo_on()
{
struct sgttyb state;
(void)ioctl(0, (int)TIOCGETP, (char *)&state);
state.sg_flags |= ECHO;
(void)ioctl(0, (int)TIOCSETP, (char *)&state);
}
Instead of getch(), why not just use getc() instead?
Thanks all of you whose help & support to solve my problem.
I find a best way to hide my password in linux that fits me best.
To use getpass() function. It just need to include "unistd.h" file.
syntex of getpass function:
char * getpass (const char *prompt)
Parameters:
prompt: string pointer to print while asking for Password
Return Value:
string pointer of password
Example:
#include <stdio.h>
#include <unistd.h>
int main()
{
char *password; // password string pointer
password = getpass("Enter Password: "); // get a password
printf("%s\n",password); // this is just for conformation
// that password stored successfully
return 1;
}
output:
Enter Password:
heet
You might use ncurses.h if it is not necessary to be portable onto Windows for that, but here is some kind of a more "portable" version:
If it is not necessery to be portable ill point you to a ncurses solution
portablegetch.h
/*portablegetch.h*/
#ifndef PGETCH
#define PGETCH
#ifdef __unix__
#include <termios.h>
#include <unistd.h>
static struct termios n_term;
static struct termios o_term;
static int
cbreak(int fd)
{
if((tcgetattr(fd, &o_term)) == -1)
return -1;
n_term = o_term;
n_term.c_lflag = n_term.c_lflag & ~(ECHO|ICANON);
n_term.c_cc[VMIN] = 1;
n_term.c_cc[VTIME]= 0;
if((tcsetattr(fd, TCSAFLUSH, &n_term)) == -1)
return -1;
return 1;
}
int
getch()
{
int cinput;
if(cbreak(STDIN_FILENO) == -1) {
fprintf(stderr, "cbreak failure, exiting \n");
exit(EXIT_FAILURE);
}
cinput = getchar();
tcsetattr(STDIN_FILENO, TCSANOW, &o_term);
return cinput;
}
#elif _MSC_VER || __WIN32__ || __MS_DOS__
#include <conio.h>
#endif
#endif
And the c-file
whatever.c
#include <stdio.h>
#include <stdlib.h>
#include "portablegetch.h"
int
main(int argc, char **argv)
{
int input;
printf("Please Enter your Password:\t");
while(( input=getch() ) != '\n')
printf("*");
printf("\n");
return EXIT_SUCCESS;
}
That should fit to your problem.
Hope that helps.
#include <termios.h>
#include <stdio.h>
static struct termios old, new;
void initTermios(int echo) {
tcgetattr(0, &old);
new = old;
new.c_lflag &= ~ICANON;
new.c_lflag &= echo ? ECHO : ~ECHO;
tcsetattr(0, TCSANOW, &new);
}
void resetTermios(void) {
tcsetattr(0, TCSANOW, &old);
}
char getch_(int echo) {
char ch;
initTermios(echo);
ch = getchar();
resetTermios();
return ch;
}
char getch(void) {
return getch_(0);
}
int main(void) {
char c;
printf("(getch example) please type a letter...");
c = getch();
printf("\nYou typed: %c\n", c);
return 0;
}
Just copy these snippet and use it. Hope it helped
Just pass for it the char* that you want to set password in and its size and the function will do its job
void set_Password(char *get_in, int sz){
for (int i = 0; i < sz;) {
char ch = getch();
if (ch == 13) {
get_in[i] = '\0';
break;
}
else if(ch != 8){
get_in[i++] = ch;
putch('*');
}
else if(i > 0)
cout << "\b \b",get_in[i--] = '\0';
}
cout << "\n";
}
This is an example, run it on your compiler
Unfortunately in the C standard library there is no such function out of the box. Maybe in third party library.
One option is use ANSI escape sequences to set the background color to foreground color in the console to conceal the password. Try this link.
With scanning the characters you can take it into a buffer. Also you need to write code if backspace is pressed, and appropriately correct the inserted password.
Here is a code which once i wrote with the curses. Compile with gcc file.c -o pass_prog -lcurses
#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#define ENOUGH_SIZE 256
#define ECHO_ON 1
#define ECHO_OFF 0
#define BACK_SPACE 127
char *my_getpass (int echo_state);
int main (void)
{
char *pass;
initscr ();
printw ("Enter Password: ");
pass = my_getpass (ECHO_ON);
printw ("\nEntered Password: %s", pass);
refresh ();
getch ();
endwin ();
return 0;
}
char *my_getpass (int echo_state)
{
char *pass, c;
int i=0;
pass = malloc (sizeof (char) * ENOUGH_SIZE);
if (pass == NULL)
{
perror ("Exit");
exit (1);
}
cbreak ();
noecho ();
while ((c=getch()) != '\n')
{
if (c == BACK_SPACE)
{
/* Do not let the buffer underflow */
if (i > 0)
{
i--;
if (echo_state == ECHO_ON)
printw ("\b \b");
}
}
else if (c == '\t')
; /* Ignore tabs */
else
{
pass[i] = c;
i = (i >= ENOUGH_SIZE) ? ENOUGH_SIZE - 1 : i+1;
if (echo_state == ECHO_ON)
printw ("*");
}
}
echo ();
nocbreak ();
/* Terminate the password string with NUL */
pass[i] = '\0';
endwin ();
return pass;
}
In C you can use getpasswd() function which pretty much doing similar thing as stty in shell, example:
#include <stdio.h>
#include <string.h>
#include <pwd.h>
#include <unistd.h>
int main()
{
char acct[80], password[80];
printf(“Account: “);
fgets(acct, 80, stdin);
acct[strlen(acct)-1] = 0; /* remove carriage return */
strncpy(password, getpass(“Password: “), 80);
printf(“You entered acct %s and pass %s\n”, acct, password);
return 0;
}
Here is equivalent shell script which use stty (which changes the settings of your tty):
save_state=$(stty -g)
/bin/echo -n “Account: “
read acct
/bin/echo -n “Password: “
stty -echo
read password # this won’t echo
stty “$save_state”
echo “”
echo account = $acct and password = $password
Source: How can I read a password without echoing it in C?
man getpass
This function is obsolete. Do not use it. If you want to read input
without terminal echoing enabled, see the description of the ECHO flag
in termios(3)
# include <termios.h>
# include <unistd.h> /* needed for STDIN_FILENO which is an int file descriptor */
struct termios tp, save;
tcgetattr( STDIN_FILENO, &tp); /* get existing terminal properties */
save = tp; /* save existing terminal properties */
tp.c_lflag &= ~ECHO; /* only cause terminal echo off */
tcsetattr( STDIN_FILENO, TCSAFLUSH, &tp ); /* set terminal settings */
/*
now input by user in terminal will not be displayed
and cursor will not move
*/
tcsetattr( STDIN_FILENO, TCSANOW, &save); /* restore original terminal settings */
If you notice, most current linux distro's do not mask a password with asterisks. Doing so divulges the length of the password which is no way beneficial. It is easier and better to simply make the cursor not move when a password is typed in. If for whatever reason you require a * to be printed for every character that's typed then you would have to grab every keypress before Enter is hit and that's always been problematic.
printf("\nENTER PASSWORD: ");
while (1)
{
ch=getch();
if(ch==13) //ON ENTER PRESS
break;
else if(ch==8) //ON BACKSPACE PRESS REMOVES CHARACTER
{
if(i>0)
{
i--;
password[i]='\0';
printf("\b \b");
}
}
else if (ch==32 || ch==9) //ON PRESSING TAB OR SPACE KEY
continue;
else
{
password[i]=ch;
i++;
printf("*");
}
}
password[i]='\0';
Here is my idea, adapted from that of the C++ official site.
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
string getpass(const char *prompt, bool showchar = false, char echochar = '*')
{
struct termios oi, ni;
tcgetattr(STDIN_FILENO, &oi);
ni = oi;
ni.c_lflag &= ~(ICANON | ECHO);
const char DELETE = 127;
const char RETURN = 10;
string password;
unsigned char ch = 0;
cout << prompt;
tcsetattr(STDIN_FILENO, TCSANOW, &ni);
while (getchar() != RETURN) {
if (ch == DELETE) {
if(password.length != 0){
if (showchar) cout << "\b \b";
password.resize(password.length() - 1);
}
}else {
password += getchar();
if (showchar) cout << echochar;
}
}
tcsetattr(STDIN_FILENO,TCSANOW,&oi)
cout << endl;
return password;
}
It will read one character at once and add it to the string and supports showing another character.
note that the ICANON termios lflag turns off the processing carriagereturn/linefeed, and the negative ECHO termios setting turns off echo for STDIN.
when using this (with or without the echo being on) to read a password and print '*' for entered characters, it's not just a matter of reading characters until a newline/carriage return is encountered, you also have to process backspace in your 'string building routine' (else the backspaces end up in the actual string, and do not cause characters to be removed from it such as would be the case with the various string based input functions).
the same would happen in C in DOS with getch tho. that would also happily return 0x08 for backspace (or 127 or whatever your specific os uses as backspace)
keeping track of 'not deleting -before- the start of the string', replacing the 'new end of the string' with 0 and moving the current position counter back by one (unless you are at position 0) is up to the programmer with any of these functions (even the getch on dos C).
getpass() doesn't do what the user originally asked for btw, he wants *'s (which still disclose the length of the password to people standing behind him and looking at his screen, as well as in the scrollbuffer of the terminal if he doesn't close it after use). but without *'s is probably a better idea in 'non closed environments'.
Related
Making the input of scanf appear as asterisk on terminal [duplicate]
I want to mask my password while writing it with *. I use Linux GCC for this code. I know one solution is to use getch() function like this #include <conio.h> int main() { char c,password[10]; int i; while( (c=getch())!= '\n');{ password[i] = c; printf("*"); i++; } return 1; } but the problem is that GCC does not include conio.h file so, getch() is useless for me. Does anyone have a solution?
In the Linux world, masking isn't usually done with asterisks, normally echoing is just turned off and the terminal displays blanks E.g. if you use su or log into a virtual terminal etc. There is a library function to handle getting passwords, it won't mask the password with asterisks but will disable echoing of the password to terminal. I pulled this out of a linux book I have. I believe its part of the posix standard #include <unistd.h> char *getpass(const char *prompt); /*Returns pointer to statically allocated input password string on success, or NULL on error*/ The getpass() function first disables echoing and all processing of terminal special characters (such as the interrupt character, normally Control-C). It then prints the string pointed to by prompt, and reads a line of input, returning the null-terminated input string with the trailing newline stripped, as its function result. A google search for getpass() has a reference to the GNU implementation (should be in most linux distros) and some sample code for implementing your own if need be http://www.gnu.org/s/hello/manual/libc/getpass.html Their example for rolling your own: #include <termios.h> #include <stdio.h> ssize_t my_getpass (char **lineptr, size_t *n, FILE *stream) { struct termios old, new; int nread; /* Turn echoing off and fail if we can't. */ if (tcgetattr (fileno (stream), &old) != 0) return -1; new = old; new.c_lflag &= ~ECHO; if (tcsetattr (fileno (stream), TCSAFLUSH, &new) != 0) return -1; /* Read the password. */ nread = getline (lineptr, n, stream); /* Restore terminal. */ (void) tcsetattr (fileno (stream), TCSAFLUSH, &old); return nread; } If need be you could use this as the basis as modify it to display asterisks.
Without getch to rely on and avoiding the obsolete getpass, the recommended approach is to disable terminal ECHO through termios use. After a few searches to find a canned flexible password routine, I was surprised that very few for stand-alone use with C. Rather than simply recoding getch with termios c_lflag options, slightly more generalized approach takes just a few additions. Beyond replacing getch any routine should enforce a specified maximum length to prevent overflow, truncate if the user attempt to enter beyond the maximum, and warn if truncation occurs in some manner. Below, the additions will allow reading from any FILE * input stream, limiting the length to a specified length, provide minimal editing (backspace) ability when taking input, allow the character mask to be specified or disabled completely, and finally return the length of the password entered. A warning was added when the password entered was truncated to the maximum or specified length. Hopefully it will prove useful to others with this question looking for a similar solution: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <termios.h> #define MAXPW 32 /* read a string from fp into pw masking keypress with mask char. getpasswd will read upto sz - 1 chars into pw, null-terminating the resulting string. On success, the number of characters in pw are returned, -1 otherwise. */ ssize_t getpasswd (char **pw, size_t sz, int mask, FILE *fp) { if (!pw || !sz || !fp) return -1; /* validate input */ #ifdef MAXPW if (sz > MAXPW) sz = MAXPW; #endif if (*pw == NULL) { /* reallocate if no address */ void *tmp = realloc (*pw, sz * sizeof **pw); if (!tmp) return -1; memset (tmp, 0, sz); /* initialize memory to 0 */ *pw = (char*) tmp; } size_t idx = 0; /* index, number of chars in read */ int c = 0; struct termios old_kbd_mode; /* orig keyboard settings */ struct termios new_kbd_mode; if (tcgetattr (0, &old_kbd_mode)) { /* save orig settings */ fprintf (stderr, "%s() error: tcgetattr failed.\n", __func__); return -1; } /* copy old to new */ memcpy (&new_kbd_mode, &old_kbd_mode, sizeof(struct termios)); new_kbd_mode.c_lflag &= ~(ICANON | ECHO); /* new kbd flags */ new_kbd_mode.c_cc[VTIME] = 0; new_kbd_mode.c_cc[VMIN] = 1; if (tcsetattr (0, TCSANOW, &new_kbd_mode)) { fprintf (stderr, "%s() error: tcsetattr failed.\n", __func__); return -1; } /* read chars from fp, mask if valid char specified */ while (((c = fgetc (fp)) != '\n' && c != EOF && idx < sz - 1) || (idx == sz - 1 && c == 127)) { if (c != 127) { if (31 < mask && mask < 127) /* valid ascii char */ fputc (mask, stdout); (*pw)[idx++] = c; } else if (idx > 0) { /* handle backspace (del) */ if (31 < mask && mask < 127) { fputc (0x8, stdout); fputc (' ', stdout); fputc (0x8, stdout); } (*pw)[--idx] = 0; } } (*pw)[idx] = 0; /* null-terminate */ /* reset original keyboard */ if (tcsetattr (0, TCSANOW, &old_kbd_mode)) { fprintf (stderr, "%s() error: tcsetattr failed.\n", __func__); return -1; } if (idx == sz - 1 && c != '\n') /* warn if pw truncated */ fprintf (stderr, " (%s() warning: truncated at %zu chars.)\n", __func__, sz - 1); return idx; /* number of chars in passwd */ } A simple program showing the use would be as follows. If using a static array of character for holding the password, just insure a pointer is passed to the function. int main (void ) { char pw[MAXPW] = {0}; char *p = pw; FILE *fp = stdin; ssize_t nchr = 0; printf ( "\n Enter password: "); nchr = getpasswd (&p, MAXPW, '*', fp); printf ("\n you entered : %s (%zu chars)\n", p, nchr); printf ( "\n Enter password: "); nchr = getpasswd (&p, MAXPW, 0, fp); printf ("\n you entered : %s (%zu chars)\n\n", p, nchr); return 0; } Example Output $ ./bin/getpasswd2 Enter password: ****** you entered : 123456 (6 chars) Enter password: you entered : abcdef (6 chars)
The functionality of getch (which is a non-standard, Windows function) can be emulated with this code: #include <termios.h> #include <unistd.h> int getch() { struct termios oldt, newt; int ch; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newt); ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); return ch; } Note that your approach is not perfect - it's better to use something like ncurses or another terminal library to handle these things.
You can create your own getch() function on Linux in this manner. int getch() { struct termios oldtc, newtc; int ch; tcgetattr(STDIN_FILENO, &oldtc); newtc = oldtc; newtc.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newtc); ch=getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldtc); return ch; } Demo code: int main(int argc, char **argv) { int ch; printf("Press x to exit.\n\n"); for (;;) { ch = getch(); printf("ch = %c (%d)\n", ch, ch); if(ch == 'x') break; } return 0; }
Your method is correct, however you'll need to turn off terminal echo while the password is being entered: #include <sgtty.h> void echo_off() { struct sgttyb state; (void)ioctl(0, (int)TIOCGETP, (char *)&state); state.sg_flags &= ~ECHO; (void)ioctl(0, (int)TIOCSETP, (char *)&state); } void echo_on() { struct sgttyb state; (void)ioctl(0, (int)TIOCGETP, (char *)&state); state.sg_flags |= ECHO; (void)ioctl(0, (int)TIOCSETP, (char *)&state); } Instead of getch(), why not just use getc() instead?
Thanks all of you whose help & support to solve my problem. I find a best way to hide my password in linux that fits me best. To use getpass() function. It just need to include "unistd.h" file. syntex of getpass function: char * getpass (const char *prompt) Parameters: prompt: string pointer to print while asking for Password Return Value: string pointer of password Example: #include <stdio.h> #include <unistd.h> int main() { char *password; // password string pointer password = getpass("Enter Password: "); // get a password printf("%s\n",password); // this is just for conformation // that password stored successfully return 1; } output: Enter Password: heet
You might use ncurses.h if it is not necessary to be portable onto Windows for that, but here is some kind of a more "portable" version: If it is not necessery to be portable ill point you to a ncurses solution portablegetch.h /*portablegetch.h*/ #ifndef PGETCH #define PGETCH #ifdef __unix__ #include <termios.h> #include <unistd.h> static struct termios n_term; static struct termios o_term; static int cbreak(int fd) { if((tcgetattr(fd, &o_term)) == -1) return -1; n_term = o_term; n_term.c_lflag = n_term.c_lflag & ~(ECHO|ICANON); n_term.c_cc[VMIN] = 1; n_term.c_cc[VTIME]= 0; if((tcsetattr(fd, TCSAFLUSH, &n_term)) == -1) return -1; return 1; } int getch() { int cinput; if(cbreak(STDIN_FILENO) == -1) { fprintf(stderr, "cbreak failure, exiting \n"); exit(EXIT_FAILURE); } cinput = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &o_term); return cinput; } #elif _MSC_VER || __WIN32__ || __MS_DOS__ #include <conio.h> #endif #endif And the c-file whatever.c #include <stdio.h> #include <stdlib.h> #include "portablegetch.h" int main(int argc, char **argv) { int input; printf("Please Enter your Password:\t"); while(( input=getch() ) != '\n') printf("*"); printf("\n"); return EXIT_SUCCESS; } That should fit to your problem. Hope that helps.
#include <termios.h> #include <stdio.h> static struct termios old, new; void initTermios(int echo) { tcgetattr(0, &old); new = old; new.c_lflag &= ~ICANON; new.c_lflag &= echo ? ECHO : ~ECHO; tcsetattr(0, TCSANOW, &new); } void resetTermios(void) { tcsetattr(0, TCSANOW, &old); } char getch_(int echo) { char ch; initTermios(echo); ch = getchar(); resetTermios(); return ch; } char getch(void) { return getch_(0); } int main(void) { char c; printf("(getch example) please type a letter..."); c = getch(); printf("\nYou typed: %c\n", c); return 0; } Just copy these snippet and use it. Hope it helped
Just pass for it the char* that you want to set password in and its size and the function will do its job void set_Password(char *get_in, int sz){ for (int i = 0; i < sz;) { char ch = getch(); if (ch == 13) { get_in[i] = '\0'; break; } else if(ch != 8){ get_in[i++] = ch; putch('*'); } else if(i > 0) cout << "\b \b",get_in[i--] = '\0'; } cout << "\n"; } This is an example, run it on your compiler
Unfortunately in the C standard library there is no such function out of the box. Maybe in third party library. One option is use ANSI escape sequences to set the background color to foreground color in the console to conceal the password. Try this link.
With scanning the characters you can take it into a buffer. Also you need to write code if backspace is pressed, and appropriately correct the inserted password. Here is a code which once i wrote with the curses. Compile with gcc file.c -o pass_prog -lcurses #include <stdio.h> #include <stdlib.h> #include <curses.h> #define ENOUGH_SIZE 256 #define ECHO_ON 1 #define ECHO_OFF 0 #define BACK_SPACE 127 char *my_getpass (int echo_state); int main (void) { char *pass; initscr (); printw ("Enter Password: "); pass = my_getpass (ECHO_ON); printw ("\nEntered Password: %s", pass); refresh (); getch (); endwin (); return 0; } char *my_getpass (int echo_state) { char *pass, c; int i=0; pass = malloc (sizeof (char) * ENOUGH_SIZE); if (pass == NULL) { perror ("Exit"); exit (1); } cbreak (); noecho (); while ((c=getch()) != '\n') { if (c == BACK_SPACE) { /* Do not let the buffer underflow */ if (i > 0) { i--; if (echo_state == ECHO_ON) printw ("\b \b"); } } else if (c == '\t') ; /* Ignore tabs */ else { pass[i] = c; i = (i >= ENOUGH_SIZE) ? ENOUGH_SIZE - 1 : i+1; if (echo_state == ECHO_ON) printw ("*"); } } echo (); nocbreak (); /* Terminate the password string with NUL */ pass[i] = '\0'; endwin (); return pass; }
In C you can use getpasswd() function which pretty much doing similar thing as stty in shell, example: #include <stdio.h> #include <string.h> #include <pwd.h> #include <unistd.h> int main() { char acct[80], password[80]; printf(“Account: “); fgets(acct, 80, stdin); acct[strlen(acct)-1] = 0; /* remove carriage return */ strncpy(password, getpass(“Password: “), 80); printf(“You entered acct %s and pass %s\n”, acct, password); return 0; } Here is equivalent shell script which use stty (which changes the settings of your tty): save_state=$(stty -g) /bin/echo -n “Account: “ read acct /bin/echo -n “Password: “ stty -echo read password # this won’t echo stty “$save_state” echo “” echo account = $acct and password = $password Source: How can I read a password without echoing it in C?
man getpass This function is obsolete. Do not use it. If you want to read input without terminal echoing enabled, see the description of the ECHO flag in termios(3) # include <termios.h> # include <unistd.h> /* needed for STDIN_FILENO which is an int file descriptor */ struct termios tp, save; tcgetattr( STDIN_FILENO, &tp); /* get existing terminal properties */ save = tp; /* save existing terminal properties */ tp.c_lflag &= ~ECHO; /* only cause terminal echo off */ tcsetattr( STDIN_FILENO, TCSAFLUSH, &tp ); /* set terminal settings */ /* now input by user in terminal will not be displayed and cursor will not move */ tcsetattr( STDIN_FILENO, TCSANOW, &save); /* restore original terminal settings */ If you notice, most current linux distro's do not mask a password with asterisks. Doing so divulges the length of the password which is no way beneficial. It is easier and better to simply make the cursor not move when a password is typed in. If for whatever reason you require a * to be printed for every character that's typed then you would have to grab every keypress before Enter is hit and that's always been problematic.
printf("\nENTER PASSWORD: "); while (1) { ch=getch(); if(ch==13) //ON ENTER PRESS break; else if(ch==8) //ON BACKSPACE PRESS REMOVES CHARACTER { if(i>0) { i--; password[i]='\0'; printf("\b \b"); } } else if (ch==32 || ch==9) //ON PRESSING TAB OR SPACE KEY continue; else { password[i]=ch; i++; printf("*"); } } password[i]='\0';
Here is my idea, adapted from that of the C++ official site. #include <termios.h> #include <unistd.h> #include <stdio.h> #include <iostream> #include <string> using namespace std; string getpass(const char *prompt, bool showchar = false, char echochar = '*') { struct termios oi, ni; tcgetattr(STDIN_FILENO, &oi); ni = oi; ni.c_lflag &= ~(ICANON | ECHO); const char DELETE = 127; const char RETURN = 10; string password; unsigned char ch = 0; cout << prompt; tcsetattr(STDIN_FILENO, TCSANOW, &ni); while (getchar() != RETURN) { if (ch == DELETE) { if(password.length != 0){ if (showchar) cout << "\b \b"; password.resize(password.length() - 1); } }else { password += getchar(); if (showchar) cout << echochar; } } tcsetattr(STDIN_FILENO,TCSANOW,&oi) cout << endl; return password; } It will read one character at once and add it to the string and supports showing another character.
note that the ICANON termios lflag turns off the processing carriagereturn/linefeed, and the negative ECHO termios setting turns off echo for STDIN. when using this (with or without the echo being on) to read a password and print '*' for entered characters, it's not just a matter of reading characters until a newline/carriage return is encountered, you also have to process backspace in your 'string building routine' (else the backspaces end up in the actual string, and do not cause characters to be removed from it such as would be the case with the various string based input functions). the same would happen in C in DOS with getch tho. that would also happily return 0x08 for backspace (or 127 or whatever your specific os uses as backspace) keeping track of 'not deleting -before- the start of the string', replacing the 'new end of the string' with 0 and moving the current position counter back by one (unless you are at position 0) is up to the programmer with any of these functions (even the getch on dos C). getpass() doesn't do what the user originally asked for btw, he wants *'s (which still disclose the length of the password to people standing behind him and looking at his screen, as well as in the scrollbuffer of the terminal if he doesn't close it after use). but without *'s is probably a better idea in 'non closed environments'.
How to use C programming language creating a shell that can implement history capture up arrow?
I have saved the history of the previous commands in a two-dimensional array. But I don't know how to check the up arrow. How to use the C programming language implementing this feature (in Linux)?
Thanks to n.m. for good advice. The following is the example of usage libreadline: // rltest.c #include <stdio.h> #include <stdlib.h> #include <readline.h> #include <history.h> int main(void) { char* input, shell_prompt[100]; // Configure readline to auto-complete paths when the tab key is hit. rl_bind_key('\t', rl_complete); // while work is not 0 program executes the loop int work = 1; printf("Commands to use: name, ver, exit \n"); // loop for working with commands while(work) { // Build prompt string. snprintf(shell_prompt, sizeof(shell_prompt), "your command $ "); // Display prompt and read input input = readline(shell_prompt); // Check for EOF. if (!input) break; // Add input to history. add_history(input); // Command analysis and execution if( 0 == strcmp(input, "exit") ) { printf("Bye!\n"); work = 0; } if( 0 == strcmp(input, "name") ) { printf("I'm readline example\n"); } if( 0 == strcmp(input, "ver") ) { printf("My version is 0.1\n"); } // ... // Free input for future use free(input); } return 0; } to compile this example: 1) install readline library apt-get install libreadline-dev 2) compile program as gcc rltest.c -I/usr/include/readline -lreadline
Try the following example: #include <stdio.h> #include <termios.h> // constants for sizes #define LINES 5 #define MAX_LEN 50 // this is just for demonstration // read more about screen cleaning http://www.cplusplus.com/articles/4z18T05o/ void ClearScreen() { printf("\033[2J"); printf("\033[0;0f"); } // function based on termios library // see more at http://stackoverflow.com/questions/7469139/what-is-equivalent-to-getch-getche-in-linux static struct termios old, new; /* Initialize new terminal i/o settings */ void initTermios(int echo) { tcgetattr(0, &old); /* grab old terminal i/o settings */ new = old; /* make new settings same as old settings */ new.c_lflag &= ~ICANON; /* disable buffered i/o */ new.c_lflag &= echo ? ECHO : ~ECHO; /* set echo mode */ tcsetattr(0, TCSANOW, &new); /* use these new terminal i/o settings now */ } /* Restore old terminal i/o settings */ void resetTermios(void) { tcsetattr(0, TCSANOW, &old); } /* Read 1 character - echo defines echo mode */ char getch_(int echo) { char ch; initTermios(echo); ch = getchar(); resetTermios(); return ch; } int main(void) { char strBuff[LINES][MAX_LEN] = {"The first line", "This is the longest line in this buffer", "Just a middle line", "Short", "The last line"}; char ch; // one character input buffer int cnt = 0; // number of current line to be shown // loop for showing lines ClearScreen(); do{ // show current line printf("%s", strBuff[cnt]); // read input (arrows. characters, etc. ch = getch_(0); // arrows detection in input if(ch == 27) { ch = getch_(0); if( ch == 91) { ch = getch_(0); if(ch == 66) // up arrow { cnt++; if(cnt >= LINES) cnt = 0; } else if(ch == 65) // down arrow { cnt--; if(cnt < 0) cnt = LINES-1; } } } // cleaning screen before next output ClearScreen(); }while(ch != 'q'); // press 'q' for exit }
Disable echo in GNU readline to input a password [duplicate]
I could use getpass() to get a password. However, the man page says: This function is obsolete. Do not use it. What is the current way to get a password from the user's terminal without echoing it, in a POSIX-compliant way? [Originally I said "portably", but my intention was to avoid using an obsolete function.]
this should work on linux/macosx, a windows version should use Get/Set ConsoleMode #include <stdio.h> #include <stdlib.h> #include <termios.h> int main(int argc, char **argv) { struct termios oflags, nflags; char password[64]; /* disabling echo */ tcgetattr(fileno(stdin), &oflags); nflags = oflags; nflags.c_lflag &= ~ECHO; nflags.c_lflag |= ECHONL; if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { perror("tcsetattr"); return EXIT_FAILURE; } printf("password: "); fgets(password, sizeof(password), stdin); password[strlen(password) - 1] = 0; printf("you typed '%s'\n", password); /* restore terminal */ if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { perror("tcsetattr"); return EXIT_FAILURE; } return 0; }
You could use the ncurses library to read from standard input without echoing the results to the screen. (Call noecho() before getting any input). The library has been around for ages and works on a wide variety of platforms (the windows version can be found here)
Even though this is a very old question that has already been answered, here's what I've been using (which is very similar to the accepted answer): #include <termios.h> #include <cstdio> // // The following is a slightly modifed version taken from: // http://www.gnu.org/software/libc/manual/html_node/getpass.html // ssize_t my_getpass (char *prompt, char **lineptr, size_t *n, FILE *stream) { struct termios _old, _new; int nread; /* Turn echoing off and fail if we can’t. */ if (tcgetattr (fileno (stream), &_old) != 0) return -1; _new = _old; _new.c_lflag &= ~ECHO; if (tcsetattr (fileno (stream), TCSAFLUSH, &_new) != 0) return -1; /* Display the prompt */ if (prompt) printf("%s", prompt); /* Read the password. */ nread = getline (lineptr, n, stream); /* Remove the carriage return */ if (nread >= 1 && (*lineptr)[nread - 1] == '\n') { (*lineptr)[nread-1] = 0; nread--; } printf("\n"); /* Restore terminal. */ (void) tcsetattr (fileno (stream), TCSAFLUSH, &_old); return nread; } // // Test harness - demonstrate calling my_getpass(). // int main(int argc, char *argv[]) { size_t maxlen = 255; char pwd[maxlen]; char *pPwd = pwd; // <-- haven't figured out how to avoid this. int count = my_getpass((char*)"Enter Password: ", &pPwd, &maxlen, stdin); printf("Size of password: %d\nPassword in plaintext: %s\n", count, pwd); return 0; }
On windows, you can probably use the SetConsoleMode api, described here.
According to the University of Milwaukee's documentation it is obsolete because: The getpass() function is not threadsafe because it manipulates global signal state. The getpass() function is scheduled to be withdrawn from a future version of the X/Open CAE Specification.
Another simple solution for Windows. Include "conio.h" for (;;) { int c = _getch(); switch (c) { case '\r': case '\n': case EOF: _putch('\n'); break; default: _putch('*'); //mask thePassword += char(c); continue; } break; }
What to use instead of getpass (and why is getpass obsolete)? [duplicate]
I could use getpass() to get a password. However, the man page says: This function is obsolete. Do not use it. What is the current way to get a password from the user's terminal without echoing it, in a POSIX-compliant way? [Originally I said "portably", but my intention was to avoid using an obsolete function.]
this should work on linux/macosx, a windows version should use Get/Set ConsoleMode #include <stdio.h> #include <stdlib.h> #include <termios.h> int main(int argc, char **argv) { struct termios oflags, nflags; char password[64]; /* disabling echo */ tcgetattr(fileno(stdin), &oflags); nflags = oflags; nflags.c_lflag &= ~ECHO; nflags.c_lflag |= ECHONL; if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { perror("tcsetattr"); return EXIT_FAILURE; } printf("password: "); fgets(password, sizeof(password), stdin); password[strlen(password) - 1] = 0; printf("you typed '%s'\n", password); /* restore terminal */ if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { perror("tcsetattr"); return EXIT_FAILURE; } return 0; }
You could use the ncurses library to read from standard input without echoing the results to the screen. (Call noecho() before getting any input). The library has been around for ages and works on a wide variety of platforms (the windows version can be found here)
Even though this is a very old question that has already been answered, here's what I've been using (which is very similar to the accepted answer): #include <termios.h> #include <cstdio> // // The following is a slightly modifed version taken from: // http://www.gnu.org/software/libc/manual/html_node/getpass.html // ssize_t my_getpass (char *prompt, char **lineptr, size_t *n, FILE *stream) { struct termios _old, _new; int nread; /* Turn echoing off and fail if we can’t. */ if (tcgetattr (fileno (stream), &_old) != 0) return -1; _new = _old; _new.c_lflag &= ~ECHO; if (tcsetattr (fileno (stream), TCSAFLUSH, &_new) != 0) return -1; /* Display the prompt */ if (prompt) printf("%s", prompt); /* Read the password. */ nread = getline (lineptr, n, stream); /* Remove the carriage return */ if (nread >= 1 && (*lineptr)[nread - 1] == '\n') { (*lineptr)[nread-1] = 0; nread--; } printf("\n"); /* Restore terminal. */ (void) tcsetattr (fileno (stream), TCSAFLUSH, &_old); return nread; } // // Test harness - demonstrate calling my_getpass(). // int main(int argc, char *argv[]) { size_t maxlen = 255; char pwd[maxlen]; char *pPwd = pwd; // <-- haven't figured out how to avoid this. int count = my_getpass((char*)"Enter Password: ", &pPwd, &maxlen, stdin); printf("Size of password: %d\nPassword in plaintext: %s\n", count, pwd); return 0; }
On windows, you can probably use the SetConsoleMode api, described here.
According to the University of Milwaukee's documentation it is obsolete because: The getpass() function is not threadsafe because it manipulates global signal state. The getpass() function is scheduled to be withdrawn from a future version of the X/Open CAE Specification.
Another simple solution for Windows. Include "conio.h" for (;;) { int c = _getch(); switch (c) { case '\r': case '\n': case EOF: _putch('\n'); break; default: _putch('*'); //mask thePassword += char(c); continue; } break; }
Getting a password in C without using getpass (3)?
I could use getpass() to get a password. However, the man page says: This function is obsolete. Do not use it. What is the current way to get a password from the user's terminal without echoing it, in a POSIX-compliant way? [Originally I said "portably", but my intention was to avoid using an obsolete function.]
this should work on linux/macosx, a windows version should use Get/Set ConsoleMode #include <stdio.h> #include <stdlib.h> #include <termios.h> int main(int argc, char **argv) { struct termios oflags, nflags; char password[64]; /* disabling echo */ tcgetattr(fileno(stdin), &oflags); nflags = oflags; nflags.c_lflag &= ~ECHO; nflags.c_lflag |= ECHONL; if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { perror("tcsetattr"); return EXIT_FAILURE; } printf("password: "); fgets(password, sizeof(password), stdin); password[strlen(password) - 1] = 0; printf("you typed '%s'\n", password); /* restore terminal */ if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { perror("tcsetattr"); return EXIT_FAILURE; } return 0; }
You could use the ncurses library to read from standard input without echoing the results to the screen. (Call noecho() before getting any input). The library has been around for ages and works on a wide variety of platforms (the windows version can be found here)
Even though this is a very old question that has already been answered, here's what I've been using (which is very similar to the accepted answer): #include <termios.h> #include <cstdio> // // The following is a slightly modifed version taken from: // http://www.gnu.org/software/libc/manual/html_node/getpass.html // ssize_t my_getpass (char *prompt, char **lineptr, size_t *n, FILE *stream) { struct termios _old, _new; int nread; /* Turn echoing off and fail if we can’t. */ if (tcgetattr (fileno (stream), &_old) != 0) return -1; _new = _old; _new.c_lflag &= ~ECHO; if (tcsetattr (fileno (stream), TCSAFLUSH, &_new) != 0) return -1; /* Display the prompt */ if (prompt) printf("%s", prompt); /* Read the password. */ nread = getline (lineptr, n, stream); /* Remove the carriage return */ if (nread >= 1 && (*lineptr)[nread - 1] == '\n') { (*lineptr)[nread-1] = 0; nread--; } printf("\n"); /* Restore terminal. */ (void) tcsetattr (fileno (stream), TCSAFLUSH, &_old); return nread; } // // Test harness - demonstrate calling my_getpass(). // int main(int argc, char *argv[]) { size_t maxlen = 255; char pwd[maxlen]; char *pPwd = pwd; // <-- haven't figured out how to avoid this. int count = my_getpass((char*)"Enter Password: ", &pPwd, &maxlen, stdin); printf("Size of password: %d\nPassword in plaintext: %s\n", count, pwd); return 0; }
On windows, you can probably use the SetConsoleMode api, described here.
According to the University of Milwaukee's documentation it is obsolete because: The getpass() function is not threadsafe because it manipulates global signal state. The getpass() function is scheduled to be withdrawn from a future version of the X/Open CAE Specification.
Another simple solution for Windows. Include "conio.h" for (;;) { int c = _getch(); switch (c) { case '\r': case '\n': case EOF: _putch('\n'); break; default: _putch('*'); //mask thePassword += char(c); continue; } break; }