diff --git a/src/main.c b/src/main.c index 8baad3d1..bda15c4b 100644 --- a/src/main.c +++ b/src/main.c @@ -36,12 +36,32 @@ #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 (default ./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); @@ -52,12 +72,16 @@ static void log_lock(bool lock, void *udata) } } -static void init() +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); - g_logfile = fopen("./logs/neuron.log", "a"); + if (0 == strcmp(log_file, STDOUT_FILE)) { + g_logfile = stdout; + } else { + g_logfile = fopen(log_file, "a"); + } if (g_logfile == NULL) { fprintf(stderr, "Failed to open logfile when" @@ -76,7 +100,7 @@ static void uninit() static void usage() { - fprintf(stderr, "neuron [--help] [--config] [--daemon]\n"); + fprintf(stderr, usage_text); } static int read_neuron_config(const char *config) @@ -144,14 +168,14 @@ int main(int argc, char *argv[]) int rv = 0; bool is_daemon = false; char *config_file = NULL; - - init(); + char *log_file = NULL; char * opts = "c::hd:W;"; struct option long_options[] = { { "help", no_argument, NULL, 1 }, { "config", optional_argument, NULL, 'c' }, { "daemon", required_argument, NULL, 1 }, + { "log", optional_argument, NULL, 'l' }, { NULL, 0, NULL, 0 }, }; @@ -175,6 +199,15 @@ int main(int argc, char *argv[]) config_file = strdup(argv[2]); } 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], @@ -188,6 +221,12 @@ int main(int argc, char *argv[]) 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); if (rv < 0) { log_error("Failed to get neuron configuration."); @@ -234,5 +273,6 @@ int main(int argc, char *argv[]) main_end: uninit(); free(config_file); + free(log_file); return rv; } diff --git a/src/utils/log.c b/src/utils/log.c index aafef79e..5e73d6d3 100644 --- a/src/utils/log.c +++ b/src/utils/log.c @@ -154,7 +154,8 @@ int log_add_callback(log_LogFn fn, void *udata, int level) int log_add_fp(FILE *fp, int level) { - return log_add_callback(file_callback, fp, level); + log_LogFn callback = (stdout == fp) ? stdout_callback : file_callback; + return log_add_callback(callback, fp, level); } static void init_event(log_Event *ev, void *udata) @@ -190,14 +191,7 @@ void log_log(int level, const char *file, int line, const char *func, lock(); - init_event(&ev, stderr); - va_start(ev.ap, fmt); - stdout_callback(&ev); - va_end(ev.ap); - - va_start(ev.ap, fmt); - syslog_callback(&ev); - va_end(ev.ap); + (void) syslog_callback; // mitigate unused warning for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++) { Callback *cb = &L.callbacks[i];