C 在终端上隐藏密码输入
我想在使用C 在终端上隐藏密码输入,c,linux,C,Linux,我想在使用*写入密码时屏蔽密码。 我使用LinuxGCC来编写这段代码。 我知道一个解决方案是像这样使用getch()函数 #include <conio.h> int main() { char c,password[10]; int i; while( (c=getch())!= '\n');{ password[i] = c; printf("*"); i++; } return 1;
*
写入密码时屏蔽密码。
我使用LinuxGCC来编写这段代码。
我知道一个解决方案是像这样使用getch()
函数
#include <conio.h>
int main()
{
char c,password[10];
int i;
while( (c=getch())!= '\n');{
password[i] = c;
printf("*");
i++;
}
return 1;
}
#包括
int main()
{
字符c,密码[10];
int i;
而((c=getch())!='\n'){
密码[i]=c;
printf(“*”);
i++;
}
返回1;
}
但问题是,GCC
不包括conio.h
文件,因此,getch()
对我来说是无用的。
有人有解决方案吗?您可以用这种方式在Linux上创建自己的
getch()
函数
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;
}
演示代码:
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;
}
可以使用以下代码模拟
getch
(这是一个非标准的Windows函数)的功能:
#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;
}
#包括
#包括
int getch(){
结构termios oldt,NETT;
int-ch;
tcgetattr(标准文件号和旧文件号);
newt=oldt;
newt.c|lflag&=~(ICANON | ECHO);
tcsetattr(标准文件号、TCSANOW和NETT);
ch=getchar();
tcsetattr(标准文件号、TCSANOW和oldt);
返回ch;
}
请注意,您的方法并不完美-最好使用ncurses或其他终端库来处理这些事情。不幸的是,在C标准库中,没有现成的函数。也许在第三方图书馆
一个选项是使用ANSI转义序列在控制台中将背景色设置为前景色以隐藏密码。请尝试。您的方法是正确的,但是在输入密码时,您需要关闭terminal echo:
#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);
}
#包括
void echo_off()
{
结构sgttyb状态;
(无效)ioctl(0,(int)TIOCGETP,(char*)和state);
state.sg_标志&=~ECHO;
(无效)ioctl(0,(int)TIOCSETP,(char*)和state);
}
void echo_on()
{
结构sgttyb状态;
(无效)ioctl(0,(int)TIOCGETP,(char*)和state);
state.sg_flags |=ECHO;
(无效)ioctl(0,(int)TIOCSETP,(char*)和state);
}
与其使用
getch()
,为什么不直接使用getc()
?如果不需要将ncurses.h移植到Windows上,您可以使用它,但这里有一种更“可移植”的版本:
如果不需要便携,我会为您提供一个ncurses解决方案
便携式Getch.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
/*portablegetch.h*/
#ifndef PGETCH
#定义PGETCH
#ifdef\uuuuunix__
#包括
#包括
静态结构术语n_术语;
静态结构术语;
静态整数
cbreak(内部fd)
{
if((tcgetattr(fd,&o_项))=-1)
返回-1;
n_项=o_项;
n_term.c_lflag=n_term.c_lflag&~(ECHO | ICANON);
n_项c_cc[VMIN]=1;
n_term.c_cc[VTIME]=0;
if((tcsetattr(fd、TCSAFLUSH和n_项))=-1)
返回-1;
返回1;
}
int
getch()
{
int-cinput;
如果(cbreak(标准文件号)=-1){
fprintf(标准,“cbreak故障,正在退出”);
退出(退出失败);
}
cinput=getchar();
tcsetattr(标准文件号、TCSANOW和o条款);
回输;
}
#elif | MSC | VER | | | | | | | WIN32 | | | | | MS | u DOS__
#包括
#恩迪夫
#恩迪夫
还有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;
}
#包括
#包括
#包括“portablegetch.h”
int
主(内部argc,字符**argv)
{
int输入;
printf(“请输入密码:\t”);
而((input=getch())!='\n')
printf(“*”);
printf(“\n”);
返回退出成功;
}
这应该适合你的问题
希望有帮助。通过扫描字符,您可以将其放入缓冲区。如果按backspace,还需要编写代码,并适当地更正插入的密码 这是我曾经用诅咒写过的一段代码。使用gcc file.c-o pass\u 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;
}
#包括
#包括
#包括
#定义足够大的\u大小256
#在1上定义ECHO_
#定义ECHO_OFF 0
#定义后空间127
char*my_getpass(int echo_状态);
内部主(空)
{
字符*通行证;
initscr();
printw(“输入密码:”);
通过=我的获取通过(回显打开);
printw(“\n输入的密码:%s”,通过);
刷新();
getch();
endwin();
返回0;
}
char*my_getpass(int echo_状态)
{
char*pass,c;
int i=0;
pass=malloc(sizeof(char)*足够的大小);
if(pass==NULL)
{
佩罗(“退出”);
出口(1);
}
cbreak();
noecho();
而((c=getch())!='\n')
{
if(c==返回空间)
{
/*不要让缓冲区下溢*/
如果(i>0)
{
我--;
if(回显状态==回显开启)
printw(“\b\b”);
}
}
else如果(c=='\t')
;/*忽略选项卡*/
其他的
{
通过[i]=c;
i=(i>=足够大小)?足够大小-1:i+1;
if(回显状态==回显开启)
printw(“*”);
}
}
echo();
nocbreak();
/*用NUL终止密码字符串*/
通过[i]='\0';
endwin();
回程通行证;
}
在Linux世界中,屏蔽通常不使用星号,通常只关闭回声,终端显示空白,例如,如果您使用su
或登录到虚拟终端等
有一个处理获取密码的库函数,它不会用星号屏蔽密码,但会禁用向终端回显密码。我从我的一本linux书中找到了这个。我相信这是posix标准的一部分
#包括
char*getpass(const char*prompt);
/*返回指向静态分配的输入密码字符串的指针
成功时为空,错误时为空*/
函数的作用是:首先禁用回显和对
终端特殊字符(如中断字符,通常为
对照组(C)
然后它打印提示符指向的字符串,并读取一行
输入,返回以null结尾的输入字符串,并带有尾随字符
换行符剥离,作为其功能结果
google对getpass()的搜索引用了GNU实现(应该在大多数linux发行版中),如果需要,还提供了一些示例代码来实现您自己的实现
他们的榜样
#include <unistd.h>
char *getpass(const char *prompt);
/*Returns pointer to statically allocated input password string
on success, or NULL on error*/
#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;
}
#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;
}
#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;
}
#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;
}
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
#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 */
}
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;
}
$ ./bin/getpasswd2
Enter password: ******
you entered : 123456 (6 chars)
Enter password:
you entered : abcdef (6 chars)
# 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 */
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';