我想用它来掩盖我的密码*
.我使用Linux GCC代码.我知道一个解决方案是使用这样的getch()
功能
#include <conio.h>
int main()
{
char c,password[10];
int i;
while( (c=getch())!= '\n');{
password[i] = c;
printf("*");
i++;
}
return 1;
}
Run Code Online (Sandbox Code Playgroud)
但问题是GCC
不包含conio.h
文件所以getch()
对我来说没用.有没有人有办法解决吗?
小智 47
在Linux世界中,屏蔽通常不用星号来完成,通常只是关闭回声并且终端显示空白例如,如果您使用su
或登录虚拟终端等.
有一个库函数来处理获取密码,它不会用星号掩盖密码,但会禁用到终端的密码回显.我把它从我的Linux书中删除了.我相信它是posix标准的一部分
Run Code Online (Sandbox Code Playgroud)#include <unistd.h> char *getpass(const char *prompt); /*Returns pointer to statically allocated input password string on success, or NULL on error*/
getpass()函数首先禁用回显和终端特殊字符的所有处理(例如中断字符,通常是Control-C).
然后它打印由prompt指向的字符串,并读取一行输入,返回以null结尾的输入字符串,并删除尾随的换行符作为其函数结果.
谷歌搜索getpass()有一个GNU实现的引用(应该在大多数Linux发行版中)和一些示例代码,如果需要,可以实现自己的
http://www.gnu.org/s/hello/manual/libc/getpass.html
他们推出自己的例子:
#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;
}
Run Code Online (Sandbox Code Playgroud)
如果需要,您可以使用此作为基础修改它以显示星号.
Dav*_*ica 11
不getch
依赖和避免过时getpass
,推荐的方法是通过termios
使用禁用终端ECHO .经过几次搜索找到一个固定的灵活密码例程后,我很惊讶很少有人单独使用C语言而不是简单地getch
使用termios c_lflag
选项进行重新编码,稍微更通用的方法只需要一些添加.除了替换getch
任何例程之外,还应强制执行指定的最大长度以防止溢出,如果用户尝试输入超出最大值,则截断,并在以某种方式发生截断时发出警告.
下面,添加将允许从任何FILE *
输入流读取,将长度限制为指定长度,在获取输入时提供最小编辑(退格)能力,允许完全指定或禁用字符掩码,最后返回密码的长度进入.输入的密码被截断为最大或指定长度时,会添加警告.
希望通过这个问题寻找类似的解决方案对其他人有用:
#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 */
}
Run Code Online (Sandbox Code Playgroud)
显示该用途的简单程序如下.如果使用静态字符数组来保存密码,只需确保将指针传递给函数即可.
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;
}
Run Code Online (Sandbox Code Playgroud)
示例输出
$ ./bin/getpasswd2
Enter password: ******
you entered : 123456 (6 chars)
Enter password:
you entered : abcdef (6 chars)
Run Code Online (Sandbox Code Playgroud)
的功能getch
(这是一个非标准的,视窗函数)可以与该代码进行仿真:
#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;
}
Run Code Online (Sandbox Code Playgroud)
请注意,您的方法并不完美 - 最好使用像ncurses或其他终端库这样的东西来处理这些事情.
您可以通过getch()
这种方式在Linux上创建自己的功能.
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;
}
Run Code Online (Sandbox Code Playgroud)
演示代码:
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;
}
Run Code Online (Sandbox Code Playgroud)