main+libcmd: 清理终端交互,保留命令注册机制

- main.c: 去掉 getopt/linenoise/system() 命令行交互,改为纯事件等待循环
- main.c: app_sys_init() 后自动调用 dc_save_out_signals_xml() 导出信号 XML
- libcmd: 精简头文件,去掉 Unix Socket/客户端代码
- libcmd: 保留 CMD_REGISTER 命令注册机制(被各模块使用)
- libcmd: 保留 cmd_find/cmd_manager_get_commands(webserver 依赖)
This commit is contained in:
ypc 2026-07-14 10:59:50 +08:00
parent b04cba095d
commit 62cf0cdc11
3 changed files with 72 additions and 83 deletions

View File

@ -1,8 +1,9 @@
/**
* @file myCmd.h
* @brief C
* @details // linenoise
* @details //
* `__attribute__((constructor))`
* WebSocket stdin
*/
#ifndef _MY_CMD_H_
#define _MY_CMD_H_
@ -42,21 +43,6 @@ void cmd_complete(const char *buf, char ***completions, int *ncomp);
void cmd_sub_complete(const char *buf, char ***completions, int *ncomp,
const char **subs, int sub_count);
/** 行编辑交互式输入 */
char *linenoise(const char *prompt);
/** 释放 linenoise 返回的内存 */
void linenoiseFree(void *ptr);
/** 添加历史记录 */
int linenoiseHistoryAdd(const char *line);
/** 释放所有历史 */
void linenoiseHistoryFree(void);
/** 设置自动补全回调 */
void lineniseSetCompletionCallback(void (*cb)(const char *, char ***, int *));
/** 注册命令宏(无补全) */
#define CMD_REGISTER(cmd_name, func_ptr, cmd_desc) \
__attribute__((constructor)) static void register_##func_ptr(void) \

View File

@ -14,6 +14,9 @@
extern "C"
{
/* ===== 内置命令 ===== */
CMD_REGISTER("help", cmd_help, "显示所有可用命令")
/* ===== 命令注册表 ===== */
static std::vector<stru_cmd> &get_cmd_list(void)
@ -182,6 +185,8 @@ void cmd_help(int argc, char *argv[])
{
printf("%-24s [%s]\n", cmd.name, cmd.desc);
}
fflush(stdout);
}
/* ===== 内置 linenoise ===== */
@ -199,6 +204,7 @@ static void (*g_completion_cb)(const char *, char ***, int *) = NULL;
static struct termios g_orig_termios;
static int g_raw_enabled = 0;
static void (*g_old_sigint)(int) = NULL;
static void disable_raw(void)
{
@ -209,24 +215,31 @@ static void disable_raw(void)
tcsetattr(STDIN_FILENO, TCSAFLUSH, &g_orig_termios);
g_raw_enabled = 0;
/* restore SIGINT handler */
if (g_old_sigint)
{
signal(SIGINT, g_old_sigint);
g_old_sigint = NULL;
}
}
static void sigint_handler(int sig)
{
(void)sig;
void (*old)(int) = g_old_sigint;
if (g_raw_enabled)
{
disable_raw();
}
printf("\n");
exit(0);
/* 先恢复 raw mode 再调用原始 handlermain.c 的 sig_handler 设 g_running=0 */
if (old)
{
old(sig);
}
}
static int enable_raw(void)
{
signal(SIGINT, sigint_handler);
g_old_sigint = signal(SIGINT, sigint_handler);
tcgetattr(STDIN_FILENO, &g_orig_termios);
atexit(disable_raw);
@ -424,24 +437,48 @@ static int linenoise_edit(char *buf, int bufsize, const char *prompt)
return 0;
}
void linenoiseSetCompletionCallback(void (*cb)(const char *, char ***, int *))
{
g_completion_cb = cb;
}
char *linenoise(const char *prompt)
{
char buf[1024];
/* 默认补全回调(首次调用或外部未设置时生效) */
if (!g_completion_cb)
{
g_completion_cb = cmd_complete;
}
if (0 != enable_raw())
{
return NULL;
/* stdin is not a TTY (pipe/redirect) — fallback to fgets */
if (prompt) SAFE_WRITE(STDOUT_FILENO, prompt, strlen(prompt));
if (!fgets(buf, (int)sizeof(buf), stdin))
{
return NULL; /* EOF */
}
/* strip trailing newline */
size_t len = strlen(buf);
while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r'))
{
buf[--len] = '\0';
}
return strdup(buf);
}
int n = linenoise_edit(buf, (int)sizeof(buf), prompt);
disable_raw();
if (n <= 0)
if (n < 0)
{
return NULL;
return NULL; /* read error or EOF */
}
/* empty line: return allocated empty string (not NULL) */
char *copy = strdup(buf);
return copy;
@ -471,6 +508,8 @@ void linenoiseHistoryFree(void)
{
free(g_history[j]);
}
g_history_len = 0;
}
void lineniseSetCompletionCallback(void (*cb)(const char *, char ***, int *))

View File

@ -14,46 +14,21 @@
#include "mySystem.h"
#include "myLog.h"
#include "myDatacenter.h"
#include "myModbus.h"
#include "myFunc.h"
#include "myCmd.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
static volatile int g_running = 1;
static void sig_handler(int sig)
{
(void)sig;
g_running = 0;
LOG_I("signal %d received, shutting down...", sig);
}
static void cmd_version(int argc, char *argv[])
{
(void)argc;
(void)argv;
printf("RTU_ALL_AI v1.0\n");
printf(" libmodbus v%d.%d.%d\n",
libmodbus_version_major, libmodbus_version_minor,
libmodbus_version_micro);
}
static void cmd_uptime(int argc, char *argv[])
{
(void)argc;
(void)argv;
printf("RTU uptime: (running)\n");
}
CMD_REGISTER("version", cmd_version, "show firmware version");
CMD_REGISTER("uptime", cmd_uptime, "show uptime");
int main(int argc, char *argv[])
{
(void)argc;
@ -65,11 +40,13 @@ int main(int argc, char *argv[])
signal(SIGTERM, sig_handler);
signal(SIGPIPE, SIG_IGN);
/* 日志初始化:控制台输出(调试可见),运行时可开文件输出 */
log_init(NULL);
LOG_I("RTU booting...");
/* 启动数据中心 */
dc_init(NULL);
/* X-Macro 驱动启动所有模块 */
if (app_sys_init() != 0)
{
LOG_E("app_sys_init failed, aborting");
@ -79,38 +56,25 @@ int main(int argc, char *argv[])
LOG_I("RTU running");
/* 导出 out 信号 XML 供前端 PLC Config 页面使用(所有模块 init1/init2 之后) */
{
char proc_dir[256] = {0};
if (0 == func_proc_self_dir(proc_dir, sizeof(proc_dir)))
{
char xml_path[512];
snprintf(xml_path, sizeof(xml_path), "%s/config/SYSTEM/datacenter_out.xml",
proc_dir);
dc_save_out_signals_xml(xml_path);
LOG_I("datacenter_out.xml exported to %s", xml_path);
}
}
/* 纯事件等待,命令交互走 Web 前端 */
while (g_running)
{
char *line = linenoise("RTU> ");
if (!line)
{
break;
}
if (line[0] != '\0')
{
linenoiseHistoryAdd(line);
char *argv_buf[16];
uint8_t argc = 0;
if (func_str2argv(line, &argc, argv_buf, 16) == 0 && argc > 0)
{
stru_cmd *cmd = cmd_find(argv_buf[0]);
if (cmd)
{
cmd->func((int)argc, argv_buf);
}
else
{
printf("unknown command: %s (type 'help')\n", argv_buf[0]);
}
}
}
linenoiseFree(line);
sleep(1);
}
LOG_I("shutting down...");