mirror of
https://github.com/emqx/neuron.git
synced 2026-10-19 23:02:33 +08:00
Refactor neuron command line argument parser into separate module
This commit is contained in:
@@ -94,6 +94,7 @@ set(PERSIST_SOURCES
|
||||
src/persist/json/persist_json_subs.c)
|
||||
set(NEURON_SOURCES
|
||||
src/main.c
|
||||
src/argparse.c
|
||||
src/config.c
|
||||
src/core/message.c
|
||||
src/core/databuf.c
|
||||
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* NEURON IIoT System for Industry 4.0
|
||||
* Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**/
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "argparse.h"
|
||||
|
||||
#define OPTIONAL_ARGUMENT_IS_PRESENT \
|
||||
((optarg == NULL && optind < argc && argv[optind][0] != '-') \
|
||||
? (bool) (optarg = argv[optind++]) \
|
||||
: (optarg != NULL))
|
||||
|
||||
#define STRDUP(var, str) \
|
||||
do { \
|
||||
(var) = strdup(str); \
|
||||
if (NULL == (var)) { \
|
||||
fprintf( \
|
||||
stderr, \
|
||||
"Neuron argument parser fail strdup string: %s, reason: %s\n", \
|
||||
(str), strerror(errno)); \
|
||||
goto quit; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// clang-format off
|
||||
const char *usage_text =
|
||||
"USAGE:\n"
|
||||
" neuron [OPTIONS]\n\n"
|
||||
"OPTIONS:\n"
|
||||
" -c, --config <FILE> neuron configuration file\n"
|
||||
" without this option, default from ./config/neuron.yaml\n"
|
||||
" -d, --daemon run as daemon process\n"
|
||||
" -h, --help show this help message\n"
|
||||
" --log [FILE] log to the given file, or stdout if no FILE argument\n"
|
||||
" without this option, default log to ./logs/neuron.log\n"
|
||||
"\n";
|
||||
// clang-format on
|
||||
|
||||
static inline void usage()
|
||||
{
|
||||
fprintf(stderr, "%s", usage_text);
|
||||
}
|
||||
|
||||
void neu_cli_args_init(neu_cli_args_t *args, int argc, char *argv[])
|
||||
{
|
||||
char * opts = "c:dh";
|
||||
struct option long_options[] = {
|
||||
{ "help", no_argument, NULL, 1 },
|
||||
{ "config", required_argument, NULL, 'c' },
|
||||
{ "daemon", no_argument, NULL, 'd' },
|
||||
{ "log", optional_argument, NULL, 'l' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
||||
memset(args, 0, sizeof(*args));
|
||||
|
||||
int c = 0;
|
||||
while ((c = getopt_long(argc, argv, opts, long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'h':
|
||||
usage();
|
||||
exit(0);
|
||||
case 'd':
|
||||
args->daemonized = true;
|
||||
break;
|
||||
case ':':
|
||||
fprintf(stderr, "%s: option '-%c' requires an argument\n", argv[0],
|
||||
optopt);
|
||||
usage();
|
||||
goto quit;
|
||||
case 'c':
|
||||
STRDUP(args->conf_file, optarg);
|
||||
break;
|
||||
case 'l':
|
||||
if (OPTIONAL_ARGUMENT_IS_PRESENT) {
|
||||
// log to file
|
||||
STRDUP(args->log_file, optarg);
|
||||
} else {
|
||||
// log to stdout
|
||||
STRDUP(args->log_file, NEU_LOG_STDOUT_FNAME);
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
fprintf(stderr, "%s: option '-%c' is invalid: ignored\n", argv[0],
|
||||
optopt);
|
||||
usage();
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == args->conf_file) {
|
||||
STRDUP(args->conf_file, "./config/neuron.yaml");
|
||||
}
|
||||
|
||||
if (NULL == args->log_file) {
|
||||
STRDUP(args->log_file, "./logs/neuron.log");
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
quit:
|
||||
neu_cli_args_fini(args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void neu_cli_args_fini(neu_cli_args_t *args)
|
||||
{
|
||||
free(args->conf_file);
|
||||
args->conf_file = NULL;
|
||||
free(args->log_file);
|
||||
args->log_file = NULL;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* NEURON IIoT System for Industry 4.0
|
||||
* Copyright (C) 2020-2022 EMQ Technologies Co., Ltd All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
**/
|
||||
|
||||
#define NEU_LOG_STDOUT_FNAME "/dev/stdout"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/** Neuron command line arguments.
|
||||
*/
|
||||
typedef struct {
|
||||
bool daemonized; // flag indicating whether to run as daemon process
|
||||
char *conf_file; // configuration file path
|
||||
char *log_file; // log file path
|
||||
} neu_cli_args_t;
|
||||
|
||||
/** Parse command line arguments.
|
||||
*/
|
||||
void neu_cli_args_init(neu_cli_args_t *args, int argc, char *argv[]);
|
||||
|
||||
/** Clean up the command line arguments.
|
||||
*/
|
||||
void neu_cli_args_fini(neu_cli_args_t *args);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
+9
-89
@@ -28,6 +28,7 @@
|
||||
#include <nng/protocol/pair1/pair.h>
|
||||
#include <nng/supplemental/util/platform.h>
|
||||
|
||||
#include "argparse.h"
|
||||
#include "config.h"
|
||||
#include "core/message.h"
|
||||
#include "core/neu_manager.h"
|
||||
@@ -36,33 +37,12 @@
|
||||
#include "neu_panic.h"
|
||||
#include "restful/rest.h"
|
||||
|
||||
#define STDOUT_FILE "/dev/stdout"
|
||||
|
||||
#define OPTIONAL_ARGUMENT_IS_PRESENT \
|
||||
((optarg == NULL && optind < argc && argv[optind][0] != '-') \
|
||||
? (bool) (optarg = argv[optind++]) \
|
||||
: (optarg != NULL))
|
||||
|
||||
static neu_manager_t *manager = NULL;
|
||||
static nng_socket main_sock = { 0 };
|
||||
|
||||
static nng_mtx *log_mtx;
|
||||
FILE * g_logfile;
|
||||
|
||||
// clang-format off
|
||||
const char *usage_text =
|
||||
"USAGE:\n"
|
||||
" neuron [OPTIONS]\n\n"
|
||||
"OPTIONS:\n"
|
||||
" -c, --config <FILE> neuron configuration file\n"
|
||||
" without this option, default from ./config/neuron.yaml\n"
|
||||
" -d, --daemon run as daemon process\n"
|
||||
" -h, --help show this help message\n"
|
||||
" --log [FILE] log to the given file, or stdout if no FILE argument\n"
|
||||
" without this option, default log to ./logs/neuron.log\n"
|
||||
"\n";
|
||||
// clang-format on
|
||||
|
||||
static void log_lock(bool lock, void *udata)
|
||||
{
|
||||
nng_mtx *mutex = (nng_mtx *) (udata);
|
||||
@@ -78,7 +58,7 @@ static void init(const char *log_file)
|
||||
nng_mtx_alloc(&log_mtx);
|
||||
log_set_lock(log_lock, log_mtx);
|
||||
log_set_level(NEU_LOG_DEBUG);
|
||||
if (0 == strcmp(log_file, STDOUT_FILE)) {
|
||||
if (0 == strcmp(log_file, NEU_LOG_STDOUT_FNAME)) {
|
||||
g_logfile = stdout;
|
||||
} else {
|
||||
g_logfile = fopen(log_file, "a");
|
||||
@@ -99,11 +79,6 @@ static void uninit()
|
||||
nng_mtx_free(log_mtx);
|
||||
}
|
||||
|
||||
static void usage()
|
||||
{
|
||||
fprintf(stderr, "%s", usage_text);
|
||||
}
|
||||
|
||||
static int read_neuron_config(const char *config)
|
||||
{
|
||||
return neu_config_init(config);
|
||||
@@ -165,68 +140,14 @@ static void unbind_main_adapter(nng_pipe p, nng_pipe_ev ev, void *arg)
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rv = 0;
|
||||
neu_cli_args_t args = { 0 };
|
||||
|
||||
int rv = 0;
|
||||
bool is_daemon = false;
|
||||
char *config_file = NULL;
|
||||
char *log_file = NULL;
|
||||
neu_cli_args_init(&args, argc, argv);
|
||||
|
||||
char * opts = "c:dh";
|
||||
struct option long_options[] = {
|
||||
{ "help", no_argument, NULL, 1 },
|
||||
{ "config", required_argument, NULL, 'c' },
|
||||
{ "daemon", no_argument, NULL, 'd' },
|
||||
{ "log", optional_argument, NULL, 'l' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
init(args.log_file);
|
||||
|
||||
int c;
|
||||
|
||||
while ((c = getopt_long(argc, argv, opts, long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'h':
|
||||
usage();
|
||||
exit(0);
|
||||
case 'd':
|
||||
is_daemon = true;
|
||||
break;
|
||||
case ':':
|
||||
fprintf(stderr, "%s: option '-%c' requires an argument\n", argv[0],
|
||||
optopt);
|
||||
usage();
|
||||
exit(0);
|
||||
case 'c':
|
||||
config_file = strdup(optarg);
|
||||
break;
|
||||
case 'l':
|
||||
if (OPTIONAL_ARGUMENT_IS_PRESENT) {
|
||||
// log to file
|
||||
log_file = strdup(optarg);
|
||||
} else {
|
||||
// log to stdout
|
||||
log_file = strdup(STDOUT_FILE);
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
fprintf(stderr, "%s: option '-%c' is invalid: ignored\n", argv[0],
|
||||
optopt);
|
||||
usage();
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (config_file == NULL) {
|
||||
config_file = strdup("./config/neuron.yaml");
|
||||
}
|
||||
|
||||
if (log_file == NULL) {
|
||||
log_file = strdup("./logs/neuron.log");
|
||||
}
|
||||
|
||||
init(log_file);
|
||||
|
||||
rv = read_neuron_config(config_file);
|
||||
rv = read_neuron_config(args.conf_file);
|
||||
if (rv < 0) {
|
||||
log_error("Failed to get neuron configuration.");
|
||||
goto main_end;
|
||||
@@ -236,7 +157,7 @@ int main(int argc, char *argv[])
|
||||
signal(SIGTERM, sig_handler);
|
||||
signal(SIGABRT, sig_handler);
|
||||
|
||||
log_info("running neuron main process, daemon: %d", is_daemon);
|
||||
log_info("running neuron main process, daemon: %d", args.daemonized);
|
||||
manager = neu_manager_create();
|
||||
if (manager == NULL) {
|
||||
log_error("Failed to create neuron manager, exit!");
|
||||
@@ -271,7 +192,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
main_end:
|
||||
uninit();
|
||||
free(config_file);
|
||||
free(log_file);
|
||||
neu_cli_args_fini(&args);
|
||||
return rv;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user