初始化状态机实现
main.h
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
typedef enum {
NOT_INIT,
INIT_PWD_FIRST,
INIT_PWD_SECOND,
INIT_COMPARE_PWD,
INIT_DONE,
INIT_FAILED
} INIT_STATE_FINAL;
void read_pwd(char* pwd, size_t len);
int compare_str(char* str1, char* str2);
void read_password(char *password, size_t size) {
struct termios old_termios, new_termios;
// 获取当前终端属性
tcgetattr(STDIN_FILENO, &old_termios);
new_termios = old_termios;
// 禁用回显功能
new_termios.c_lflag &= ~ECHO;
// 设置新的终端属性
tcsetattr(STDIN_FILENO, TCSAFLUSH, &new_termios);
// 提示用户输入密码
printf("请输入密码: ");
fgets(password, size, stdin);
// 恢复原来的终端属性
tcsetattr(STDIN_FILENO, TCSAFLUSH, &old_termios);
// 去除换行符
size_t len = 0;
while (password[len] != '\0' && password[len] != '\n') {
len++;
}
password[len] = '\0';
}
typedef enum{
STATE_NOT_INIT,
STATE_INITING,
STATE_INIT_DONE
} INIT_STATE;
typedef enum{
EVENT_PROMPRT,
EVENT_UNAME,
EVENT_PWD,
EVENT_DONE
} INIT_EVENT;
void read_uname(char* uname, size_t* out_len)
{
char buffer[100];
if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
// fgets 会读取换行符,如果需要可以去掉
size_t len = strlen(buffer);
if (len > 0 && buffer[len-1] == '\n') {
buffer[len-1] = '\0'; // 去掉换行符
}
printf("You entered: %s\n", buffer);
strncpy(uname, buffer, sizeof(buffer) - 1);
} else {
printf("Error reading input.\n");
}
}
void process_init(INIT_STATE* cur_state, INIT_EVENT cur_event, char* str, size_t len)
{
switch (*cur_state) {
case STATE_NOT_INIT:
if (cur_event == EVENT_PROMPRT) {
printf("enter init\n");
*cur_state = STATE_INITING;
}
break;
case STATE_INITING:
if (cur_event == EVENT_UNAME) {
printf("please input uname:");
char uname[100] = {0};
//获取用户名
read_uname(uname, sizeof(uname));
strncpy(str, uname, sizeof(uname));
//*cur_state = STATE_INITING;
}else if (cur_event == EVENT_PWD) {
char pwd01[100] = {0};
read_pwd(pwd01, sizeof(pwd01));
//状态未变化
strncpy(str, pwd01, sizeof(pwd01) - 1);
memset(pwd01, 0, sizeof(pwd01));
}else if (cur_event == EVENT_DONE) {
printf("init success\n");
*cur_state = STATE_INIT_DONE;
}
break;
case STATE_INIT_DONE:
if (cur_event == EVENT_DONE) {
printf("init done\n");
}
break;
default:
break;
}
}
void test_switch()
{
char uname[100] = {0};
char pwd[100] = {0};
char confirm_pwd[100] = {0};
INIT_STATE cur_state = STATE_NOT_INIT;
// 提示
process_init(&cur_state, EVENT_PROMPRT, NULL, 0);
process_init(&cur_state, EVENT_UNAME, uname, sizeof(uname));
process_init(&cur_state, EVENT_PWD, pwd, sizeof(pwd));
process_init(&cur_state, EVENT_PWD, confirm_pwd, sizeof(confirm_pwd));
if (0 == compare_str(pwd, confirm_pwd)) {
printf("pwd is equal\n");
}else {
printf("pwd is not equal\n");
}
process_init(&cur_state, EVENT_DONE, NULL, 0);
process_init(&cur_state, EVENT_DONE, NULL, 0);
printf("uname is [%s], pwd is [%s]\n", uname, pwd);
}
int compare_str(char* str1, char* str2)
{
if(str1[0] == '\0' || str2[0] == '\0') {
return -1;
}
int i = 0;
while (str1[i] != '\0') {
if (str1[i] != str2[i]) {
break;
}
++i;
if(str1[i] == '\0' && str2[i] == '\0') {
return 0;
} else if(str1[i] == '\0' || str2[i] == '\0') {
break;
}
}
return -1;
}
void read_pwd(char* pwd, size_t len)
{
const char* tmpPasswd = NULL;
tmpPasswd = getpass("please input passwd:");
strncpy(pwd, tmpPasswd, len);
printf("pwd is [%s]\n", pwd);
if (tmpPasswd[0] != '\0') {
//避免memset被编译器优化
volatile char *volatile_password = (volatile char *)tmpPasswd;
memset((void *)volatile_password, 0, strlen(tmpPasswd));
}
}
void read_pwd_twice()
{
const char* tmpPasswd = NULL;
char passwd[2][128] = {{0}};
tmpPasswd = getpass("please input passwd:");
//密码复杂度检查
strncpy(passwd[0], tmpPasswd, sizeof(passwd[0]) - 1);
// volatile char *volatile_password = (volatile char *)tmpPasswd;
// memset((void *)volatile_password, 0, strlen(volatile_password));
printf("pwd01 [%s]\n", passwd[0]);
tmpPasswd = NULL;
tmpPasswd = getpass("please input confirm passwd:");
strncpy(passwd[1], tmpPasswd, sizeof(passwd[0]) - 1);
printf("pwd02 [%s]\n", passwd[1]);
if (compare_str(passwd[0], passwd[1])) { //密码不匹配
//重新读取密码
}
}
void init_machine()
{
int init_flag = 1;
int max_init_times = 3;
INIT_STATE_FINAL cur_state = NOT_INIT;
char pwd01[100] = {0};
char pwd02[100] = {0};
while (init_flag) { // init done or reach max retry
if (max_init_times == 0) {
printf("block\n");
break;
}
switch (cur_state) {
case NOT_INIT:
printf("enter init\n");
cur_state = INIT_PWD_FIRST;
break;
case INIT_PWD_FIRST:
read_pwd(pwd01, sizeof(pwd01));
cur_state = INIT_PWD_SECOND;
break;
case INIT_PWD_SECOND:
read_pwd(pwd02, sizeof(pwd02));
cur_state = INIT_COMPARE_PWD;
break;
case INIT_COMPARE_PWD:
if (compare_str(pwd01, pwd02)) {
//重新输入密码
printf("password set failed\n");
cur_state = INIT_FAILED;
}
else {
printf("password set success\n");
cur_state = INIT_DONE;
}
break;
case INIT_DONE:
init_flag = 0;
max_init_times = 0;
printf("init success\n");
break;
case INIT_FAILED:
max_init_times--;
cur_state = INIT_PWD_FIRST;
memset(pwd01, 0, sizeof(pwd01));
memset(pwd02, 0, sizeof(pwd02));
break;
default:
break;
}
}
}
main.c
#include "main.h"
#include <stdio.h>
#include <unistd.h>
int main()
{
#if 0
// 方式1: 修改终端属性
char passwd[100] = {0};
read_password(passwd, sizeof(passwd));
printf("\npasswd [%s]\n", passwd);
#else
// 方式2:调用系统接口
// const char* pwd = NULL;
// pwd = getpass("please input passwd:");
// printf("pwd is %s\n", pwd);
/*
char pwd01[100] = {0};
char pwd02[100] = {0};
read_pwd(pwd01, sizeof(pwd01));
read_pwd(pwd02, sizeof(pwd02));
if (compare_str(pwd01, pwd02)) {
//重新输入密码
printf("password set failed\n");
}
else {
printf("password set success\n");
}*/
#endif
// 进程间通信
// init_machine();
// 进程间通信
test_switch();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现