163 lines
5.0 KiB
C
163 lines
5.0 KiB
C
/*****************************************************************************
|
||
* @copyright 2024-2024, . POWER SUPPLY CO., LTD.
|
||
* @file argparse.c
|
||
* @brief 命令行参数解析实现
|
||
* @author Gary
|
||
* @date 2024/09/20
|
||
*****************************************************************************/
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <getopt.h>
|
||
#include <errno.h>
|
||
#include <string.h>
|
||
#include <inttypes.h>
|
||
#include "kit_log.h"
|
||
#include "argparse.h"
|
||
|
||
// clang-format off
|
||
const char* usage_text =
|
||
"用法:\n"
|
||
"company_ems [选项]\n"
|
||
"选项:\n"
|
||
" -d, --daemon 以守护进程方式运行\n"
|
||
" -h, --help 显示帮助信息\n"
|
||
" stop 停止正在运行的 company_ems\n"
|
||
" --version 打印版本信息\n"
|
||
"\n";
|
||
// clang-format on
|
||
|
||
/*****************************************************************************
|
||
* @brief 显示命令行帮助信息
|
||
*****************************************************************************/
|
||
static void usage()
|
||
{
|
||
KITPTF(LOG_ARGPARSE_EN, INFO_EN, "%s", usage_text);
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* @brief 输出版本号
|
||
* @return
|
||
*****************************************************************************/
|
||
static void version()
|
||
{
|
||
printf("1.0.0\n");
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* @brief 加载特定命令行参数
|
||
* @param[in] argc:命令行参数个数
|
||
* @param[in] argv:命令行参数字符数组
|
||
* @param[out] args:命令行解析后装入的结构体
|
||
* @return 0 表示成功,其他值表示失败
|
||
*****************************************************************************/
|
||
static int load_spec_arg(int argc, char* argv[], cli_args_t* args)
|
||
{
|
||
if (argc > 1 && strcmp(argv[1], "stop") == 0)
|
||
{
|
||
args->stop = true;
|
||
}
|
||
return 0; // 这里返回0表示成功
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* @brief 解析重启策略字符串
|
||
* @param[in] s:重启策略字符串
|
||
* @param[out] out:解析后的重启策略值
|
||
* @return 0 表示成功,-1 表示失败
|
||
*****************************************************************************/
|
||
static int parse_restart_policy(const char* s, size_t* out)
|
||
{
|
||
if (strcmp(s, "always") == 0)
|
||
{
|
||
*out = RESTART_ALWAYS;
|
||
}
|
||
else if (strcmp(s, "never") == 0)
|
||
{
|
||
*out = RESTART_NEVER;
|
||
}
|
||
else if (strcmp(s, "on-failure") == 0)
|
||
{
|
||
*out = RESTART_ONFAILURE;
|
||
}
|
||
else
|
||
{
|
||
errno = 0;
|
||
char* end = NULL;
|
||
uintmax_t n = strtoumax(s, &end, 0);
|
||
// 检查整个字符串是否为有效数字
|
||
if (errno != 0 || *s == '\0' || *end != '\0' || n > RESTART_ALWAYS)
|
||
{
|
||
return -1; // 返回-1表示解析失败
|
||
}
|
||
*out = n;
|
||
}
|
||
|
||
return 0; // 返回0表示成功
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* @brief 初始化命令行参数解析
|
||
* @param[in] argc:命令行参数个数
|
||
* @param[in] argv:命令行参数字符数组
|
||
* @param[out] args:命令行解析后装入的结构体
|
||
*****************************************************************************/
|
||
void cliArgsInit(int argc, char* argv[], cli_args_t* args)
|
||
{
|
||
memset(args, 0, sizeof(*args)); // 初始化参数结构体
|
||
|
||
// 加载特定参数
|
||
if (load_spec_arg(argc, argv, args) < 0)
|
||
{
|
||
exit(1);
|
||
}
|
||
|
||
int c = 0;
|
||
int option_index = 0;
|
||
char* opts = "dh"; // 短选项字符串
|
||
struct option long_options[] = {
|
||
{"help", no_argument, NULL, 'h'},
|
||
{"daemon", no_argument, NULL, 'd'},
|
||
{"restart", required_argument, NULL, 'r'},
|
||
{"version", no_argument, NULL, 'v'},
|
||
{"stop", no_argument, NULL, 's'},
|
||
{NULL, 0, NULL, 0},
|
||
};
|
||
|
||
// 解析命令行选项
|
||
while ((c = getopt_long(argc, argv, opts, long_options, &option_index)) != -1)
|
||
{
|
||
switch (c)
|
||
{
|
||
case 'h':
|
||
usage();
|
||
exit(0);
|
||
case 'd':
|
||
args->daemonized = true;
|
||
break;
|
||
case 'r':
|
||
if (parse_restart_policy(optarg, &args->restart) != 0)
|
||
{
|
||
KITPTF(LOG_ARGPARSE_EN, ERROR_EN, "%s: 选项 '--restart' 无效策略: `%s`\n",
|
||
argv[0], optarg);
|
||
exit(1);
|
||
}
|
||
break;
|
||
case 'v':
|
||
version();
|
||
exit(0);
|
||
case '?':
|
||
default:
|
||
usage();
|
||
exit(1);
|
||
}
|
||
}
|
||
|
||
// 检查重启策略的有效性
|
||
if (!args->daemonized && args->restart != RESTART_NEVER)
|
||
{
|
||
KITPTF(LOG_ARGPARSE_EN, ERROR_EN, "%s: 选项 '--restart' 在没有 '--daemon' 的情况下无效\n",
|
||
argv[0]);
|
||
args->restart = RESTART_NEVER;
|
||
}
|
||
}
|