您的位置:首页 > 其它

How to use gnu readline to implement "reset password".

2017-01-10 15:28 417 查看
How to use gnu readline to implement "Reset password"
Using gnu readline to implement a shell style program is simple, but implementing
"Reset password" is a little hard, here is a very complete example .

#include <stdio.h>
#include <string.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <readline/readline.h>

#define MAX_PW_LEN (256)
#define RED "\e[0;31m"
#define GREEN "\e[0;32m"
#define NONE "\e[0m"
#define YELLOW "\e[1;33m"

static int input_pw_done = 0;
static int input_pw_is_retype = 0;
static char input_pw_real_text[MAX_PW_LEN];
static char input_pw_pw[MAX_PW_LEN] = {0};
static char input_pw_retype_pw[MAX_PW_LEN] = {0};
static int input_pw_result = -1;

#define PROMPT_MAX_LENGTH (256)
static char current_prompt[PROMPT_MAX_LENGTH] = {0};
static void reset_prompt()
{
snprintf(current_prompt, PROMPT_MAX_LENGTH, "%s%s%s", YELLOW, "dotphoenix@qq.com$ ", NONE);
}
static const char* get_prompt()
{
if (strlen(current_prompt) == 0){
reset_prompt();
}
return current_prompt;
}

static void set_prompt(const char* prmpt, const char* color)
{
const char* clr = color;
if (clr == NULL) {
clr = YELLOW;
}
snprintf(current_prompt, PROMPT_MAX_LENGTH, "%s%s%s", clr, prmpt, NONE);
}

static void init_readline()
{
/* Allow conditional parsing of the ~/.inputrc file. */
rl_readline_name = get_prompt();

/* Tell the completer that we want a crack first. */
//rl_attempted_completion_function = tab_completion;
//rl_completion_entry_function = rl_filename_completion_function_default;
//read_history(history_path);
}

static void uninit_readline()
{

}

static void input_pw_replace_pw_chars()
{
char* line;
int i = 0;
int saved_point = rl_point;;
line = rl_copy_text(0, rl_end);
if (strlen(line) > 0) {
if (strlen(input_pw_real_text) > strlen(line)) { //backspace ?
int offset = strlen(input_pw_real_text) - strlen(line);
i = 0;
while(i < offset) {
input_pw_real_text[strlen(line) + i] = 0;
i++;
}
}
else {
input_pw_real_text[strlen(line) - 1] = line[strlen(line) - 1];
}
for(i = 0; i < strlen(line); i++) {
line[i] = '*';
}
rl_replace_line("", 0);
rl_redisplay();
rl_replace_line(line, 0);
rl_point = saved_point;
rl_redisplay();
free(line);
}
else {
i = 0;
}
}

static void input_pw_handle_line(char* line)
{
if (input_pw_is_retype == 0) {
set_prompt("Retype new password:", GREEN);
rl_set_prompt(get_prompt());
strncpy(input_pw_pw, input_pw_real_text, MAX_PW_LEN);
}
else {
reset_prompt();
rl_set_prompt(get_prompt());
rl_callback_handler_remove();
strncpy(input_pw_retype_pw, input_pw_real_text, MAX_PW_LEN);

if (strcmp(input_pw_pw, input_pw_retype_pw) == 0) {
input_pw_result = 0;
}
else {
const char* p = "Password does not match.";
strcpy(input_pw_pw, p);
input_pw_result = -1;
}
}
input_pw_done = 1;
}
static int readline_input_pw(char* password)
{
memset(input_pw_real_text, sizeof(char) * MAX_PW_LEN, 0);
input_pw_done = 0;
input_pw_is_retype = 0;
set_prompt("New password:", GREEN);
rl_callback_handler_install(get_prompt(), input_pw_handle_line);

while (input_pw_done == 0) {
input_pw_replace_pw_chars();
rl_callback_read_char();
}

input_pw_done = 0;
input_pw_is_retype = 1;
while (input_pw_done == 0) {
input_pw_replace_pw_chars();
rl_callback_read_char();
}

strcpy(password, input_pw_pw);
return input_pw_result;
}

static void ssp_printf(const char* color, const char* format, ...)
{
va_list arg_ptr;
char msg[4096] = {0};
va_start(arg_ptr, format);

strcpy(msg, color);
vsnprintf(msg + strlen (msg), 4096 - 20, format, arg_ptr);
va_end(arg_ptr);
strcat(msg, NONE);
printf(msg);
}

int main(int argc, char **argv)
{
int done = 0;
(void)argc;
(void)argv;

init_readline(); /* Bind our completer. */

//tester();
/* Loop reading and executing lines until the user quits. */
while (done == 0)
{
char* line = readline(get_prompt());
char* cmd = line;
if(!line) { // ctrl + d
ssp_printf(GREEN, "\n");
continue;
}

if (strcmp(cmd, "quit!") == 0) {
done = 1;
}
else {
if (strcmp(cmd, "setpw") == 0) {
char pw[MAX_PW_LEN] = {0};
int cr = readline_input_pw(pw);
if (cr == 0) {
ssp_printf(GREEN, "Set successfully (%s). \n", pw);
}
else {
ssp_printf(RED, "%s \n", pw);
}
}
else {
if (strlen(cmd) > 0) {
ssp_printf(GREEN, "Run %s successfully !!!\n", cmd);
}
}
}
free (line);
}
uninit_readline();
}

Using command below to build:
gcc -o reset_pw input_pw.c -lreadline

The effect :

./reset_pw
dotphoenix@qq.com$ setpw
New password:****
Retype new password:****
Set successfully (1111).
dotphoenix@qq.com$ setpw
New password:*
Retype new password:**
Password does not match.
dotphoenix@qq.com$
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  gnu readline passwor