ems/ems_c/argparse.c

163 lines
5.0 KiB
C
Raw Permalink Normal View History

2025-05-13 17:49:49 +08:00
/*****************************************************************************
* @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;
}
}