diff --git a/CHANGELOG.md b/CHANGELOG.md index 45ba4a4f..58ff9e5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,12 @@ ### Major New features ### API changes on existing features (you may need to change your code) +* clixon_netconf -S is obsolete. Use clixon_netconf -l s instead. ### Minor changes -* Added clicon_log_init(.., CLICON_LOG_FILE) option and clicon_log_file() for cases where neither syslog or stderr is useful. +* Unified log handling for all clicon applications using -l e|o|s|f. + * The options stand for e:stderr, o:stdout, s: syslog, f:file + * Added file logging (-l f)for cases where neither syslog nor stderr is useful. * Obsoleted COMPAT_CLIV and COMPAT_XSL that were optional in 3.7 * Added -l option for clixon_backend for directing syslog to stderr or stdout if running in foreground diff --git a/apps/backend/backend_main.c b/apps/backend/backend_main.c index 0785adf5..76391b10 100644 --- a/apps/backend/backend_main.c +++ b/apps/backend/backend_main.c @@ -75,6 +75,8 @@ /* Command line options to be passed to getopt(3) */ #define BACKEND_OPTS "hD:f:d:b:Fzu:a:P:1s:c:g:l:y:x:" /* substitute s: for IRCc:r */ +#define BACKEND_LOGFILE "/usr/local/var/clixon_backend.log" + /*! Terminate. Cannot use h after this */ static int backend_terminate(clicon_handle h) @@ -556,10 +558,10 @@ main(int argc, int xml_pretty; char *xml_format; char *nacm_mode; - int logdst = CLICON_LOG_SYSLOG; + int logdst = CLICON_LOG_SYSLOG|CLICON_LOG_STDERR; /* In the startup, logs to stderr & syslog and debug flag set later */ - clicon_log_init(__PROGRAM__, LOG_INFO, CLICON_LOG_STDERR|CLICON_LOG_SYSLOG); + clicon_log_init(__PROGRAM__, LOG_INFO, logdst); /* Initiate CLICON handle */ if ((h = backend_handle_init()) == NULL) return -1; @@ -594,20 +596,9 @@ main(int argc, clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg); break; case 'l': /* Log destination: s|e|o */ - switch (optarg[0]){ - case 's': - logdst = CLICON_LOG_SYSLOG; - break; - case 'e': - logdst = CLICON_LOG_STDERR; - break; - case 'o': - logdst = CLICON_LOG_STDOUT; - break; - default: - usage(h, argv[0]); - } - break; + if ((logdst = clicon_log_opt(optarg[0])) < 0) + usage(h, argv[0]); + break; } /* * Here we have the debug flag settings, use that. @@ -616,6 +607,8 @@ main(int argc, * XXX: if started in a start-daemon script, there will be irritating * double syslogs until fork below. */ + if ((logdst & CLICON_LOG_FILE) && clicon_log_file(BACKEND_LOGFILE) < 0) + goto done; clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, logdst); clicon_debug_init(debug, NULL); diff --git a/apps/backend/backend_plugin.c b/apps/backend/backend_plugin.c index 6dd23d4d..e193b876 100644 --- a/apps/backend/backend_plugin.c +++ b/apps/backend/backend_plugin.c @@ -259,7 +259,7 @@ plugin_transaction_begin(clicon_handle h, clicon_log(LOG_NOTICE, "%s: Plugin '%s' transaction_begin callback does not make clicon_err call on error", __FUNCTION__, cp->cp_name); - break; + break; } } return retval; diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index e2e2bb8f..7c8e4559 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -73,6 +73,8 @@ /* Command line options to be passed to getopt(3) */ #define CLI_OPTS "hD:f:xl:F:1a:u:d:m:qpGLy:c:U:" +#define CLI_LOGFILE "/tmp/clixon_cli.log" + /*! terminate cli application */ static int cli_terminate(clicon_handle h) @@ -297,25 +299,16 @@ main(int argc, char **argv) case 'x': /* dump config file as xml (migration from .conf file)*/ dump_configfile_xml++; break; - case 'l': /* Log destination: s|e|o */ - switch (optarg[0]){ - case 's': - logdst = CLICON_LOG_SYSLOG; - break; - case 'e': - logdst = CLICON_LOG_STDERR; - break; - case 'o': - logdst = CLICON_LOG_STDOUT; - break; - default: - usage(h, argv[0]); - } - break; + case 'l': /* Log destination: s|e|o */ + if ((logdst = clicon_log_opt(optarg[0])) < 0) + usage(h, argv[0]); + break; } /* * Logs, error and debug to stderr or syslog, set debug level */ + if ((logdst & CLICON_LOG_FILE) && clicon_log_file(CLI_LOGFILE) < 0) + goto done; clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, logdst); clicon_debug_init(debug, NULL); diff --git a/apps/netconf/netconf_main.c b/apps/netconf/netconf_main.c index 543f015e..0942986b 100644 --- a/apps/netconf/netconf_main.c +++ b/apps/netconf/netconf_main.c @@ -71,7 +71,9 @@ #include "netconf_rpc.h" /* Command line options to be passed to getopt(3) */ -#define NETCONF_OPTS "hDqf:a:u:d:Sy:U:" +#define NETCONF_OPTS "hDf:l:qa:u:d:y:U:" + +#define NETCONF_LOGFILE "/tmp/clixon_netconf.log" /*! Process incoming packet * @param[in] h Clicon handle @@ -297,10 +299,11 @@ usage(clicon_handle h, "\t-D\t\tDebug\n" "\t-q\t\tQuiet: dont send hello prompt\n" "\t-f \tConfiguration file (mandatory)\n" + "\t-l \tLog on (s)yslog, (f)ile (syslog is default)\n" "\t-a UNIX|IPv4|IPv6\tInternal backend socket family\n" "\t-u \tInternal socket domain path or IP addr (see -a)\n" "\t-d \tSpecify netconf plugin directory dir (default: %s)\n" - "\t-S\t\tLog on syslog\n" + "\t-y \tOverride yang spec file (dont include .yang suffix)\n" "\t-U \tOver-ride unix user with a pseudo user for NACM.\n", argv0, @@ -318,15 +321,12 @@ main(int argc, char *argv0 = argv[0]; int quiet = 0; clicon_handle h; - int use_syslog; char *dir; + int logdst = CLICON_LOG_STDERR; struct passwd *pw; - /* Defaults */ - use_syslog = 0; - /* In the startup, logs to stderr & debug flag set later */ - clicon_log_init(__PROGRAM__, LOG_INFO, CLICON_LOG_STDERR); + clicon_log_init(__PROGRAM__, LOG_INFO, logdst); /* Create handle */ if ((h = clicon_handle_init()) == NULL) return -1; @@ -352,15 +352,17 @@ main(int argc, usage(h, argv[0]); clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg); break; - case 'S': /* Log on syslog */ - use_syslog = 1; + case 'l': /* Log destination: s|e|o */ + if ((logdst = clicon_log_opt(optarg[0])) < 0) + usage(h, argv[0]); break; } /* * Logs, error and debug to stderr or syslog, set debug level */ - clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, - use_syslog?CLICON_LOG_SYSLOG:CLICON_LOG_STDERR); + if ((logdst & CLICON_LOG_FILE) && clicon_log_file(NETCONF_LOGFILE) < 0) + goto done; + clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, logdst); clicon_debug_init(debug, NULL); /* Find and read configfile */ @@ -374,8 +376,8 @@ main(int argc, switch (c) { case 'h' : /* help */ case 'D' : /* debug */ - case 'f': /* config file */ - case 'S': /* Log on syslog */ + case 'f': /* config file */ + case 'l': /* log */ break; /* see above */ case 'a': /* internal backend socket address family */ clicon_option_str_set(h, "CLICON_SOCK_FAMILY", optarg); @@ -410,8 +412,6 @@ main(int argc, argc -= optind; argv += optind; - - /* Parse yang database spec file */ if (yang_spec_main(h) == NULL) goto done; diff --git a/apps/restconf/restconf_main.c b/apps/restconf/restconf_main.c index b4390016..66350486 100644 --- a/apps/restconf/restconf_main.c +++ b/apps/restconf/restconf_main.c @@ -74,7 +74,7 @@ #include "restconf_methods.h" /* Command line options to be passed to getopt(3) */ -#define RESTCONF_OPTS "hDf:p:y:a:u:l:" +#define RESTCONF_OPTS "hDf:l:p:y:a:u:" /* RESTCONF enables deployments to specify where the RESTCONF API is located. The client discovers this by getting the "/.well-known/host-meta" @@ -490,11 +490,11 @@ usage(clicon_handle h, "\t-h \t\tHelp\n" "\t-D \t\tDebug. Log to syslog\n" "\t-f \tConfiguration file (mandatory)\n" + "\t-l \tLog on (s)yslog, (f)ile (syslog is default)\n" "\t-d \tSpecify restconf plugin directory dir (default: %s)\n" "\t-y \tOverride yang spec file (dont include .yang suffix)\n" "\t-a UNIX|IPv4|IPv6\tInternal backend socket family\n" - "\t-u \tInternal socket domain path or IP addr (see -a)\n" - "\t-l \tLog on (s)yslog, (f)ile (syslog is default)\n", + "\t-u \tInternal socket domain path or IP addr (see -a)\n", argv0, clicon_restconf_dir(h) ); @@ -540,6 +540,45 @@ main(int argc, usage(h, argv[0]); clicon_option_str_set(h, "CLICON_CONFIGFILE", optarg); break; + case 'l': /* Log destination: s|e|o */ + if ((logdst = clicon_log_opt(optarg[0])) < 0) + usage(h, argv[0]); + break; + } /* switch getopt */ + argc -= optind; + argv += optind; + + /* + * Logs, error and debug to stderr or syslog, set debug level + */ + if ((logdst & CLICON_LOG_FILE) && clicon_log_file(RESTCONF_LOGFILE) < 0) + goto done; + clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, logdst); + + clicon_debug_init(debug, NULL); + clicon_log(LOG_NOTICE, "%s: %u Started", __PROGRAM__, getpid()); + if (set_signal(SIGTERM, restconf_sig_term, NULL) < 0){ + clicon_err(OE_DEMON, errno, "Setting signal"); + goto done; + } + if (set_signal(SIGINT, restconf_sig_term, NULL) < 0){ + clicon_err(OE_DEMON, errno, "Setting signal"); + goto done; + } + /* Find and read configfile */ + if (clicon_options_main(h) < 0) + goto done; + + /* Now rest of options, some overwrite option file */ + optind = 1; + opterr = 0; + while ((c = getopt(argc, argv, RESTCONF_OPTS)) != -1) + switch (c) { + case 'h' : /* help */ + case 'D' : /* debug */ + case 'f': /* config file */ + case 'l': /* log */ + break; /* see above */ case 'd': /* Plugin directory */ if (!strlen(optarg)) usage(h, argv[0]); @@ -556,42 +595,10 @@ main(int argc, usage(h, argv[0]); clicon_option_str_set(h, "CLICON_SOCK", optarg); break; - case 'l': /* Log destination: s|e|o */ - switch (optarg[0]){ - case 's': - logdst = CLICON_LOG_SYSLOG; - break; - case 'f': - logdst = CLICON_LOG_FILE; - if (clicon_log_file(RESTCONF_LOGFILE) < 0) - goto done; - break; - default: - usage(h, argv[0]); - } - break; - default: - usage(h, argv[0]); - break; - } /* switch getopt */ - argc -= optind; - argv += optind; - - clicon_log_init(__PROGRAM__, debug?LOG_DEBUG:LOG_INFO, logdst); - clicon_debug_init(debug, NULL); - clicon_log(LOG_NOTICE, "%s: %u Started", __PROGRAM__, getpid()); - if (set_signal(SIGTERM, restconf_sig_term, NULL) < 0){ - clicon_err(OE_DEMON, errno, "Setting signal"); - goto done; - } - if (set_signal(SIGINT, restconf_sig_term, NULL) < 0){ - clicon_err(OE_DEMON, errno, "Setting signal"); - goto done; - } - - /* Find and read configfile */ - if (clicon_options_main(h) < 0) - goto done; + default: + usage(h, argv[0]); + break; + } /* Overwrite yang module with -y option */ if (yangspec) diff --git a/lib/clixon/clixon_log.h b/lib/clixon/clixon_log.h index 026d9ba4..4524bcd7 100644 --- a/lib/clixon/clixon_log.h +++ b/lib/clixon/clixon_log.h @@ -61,6 +61,7 @@ extern int debug; */ int clicon_log_init(char *ident, int upto, int flags); int clicon_log_exit(void); +int clicon_log_opt(char c); int clicon_log_file(char *filename); int clicon_get_logflags(void); int clicon_log_str(int level, char *msg); diff --git a/lib/src/clixon_log.c b/lib/src/clixon_log.c index 7b3d2b75..1815c121 100644 --- a/lib/src/clixon_log.c +++ b/lib/src/clixon_log.c @@ -105,7 +105,36 @@ clicon_log_exit(void) return 0; } -/* If log flags include CLICON_LOG_FILE, set the file +/*! Utility function to set log destination/flag using command-line option + * @param[in] c Log option,one of s,f,e,o + * @retval -1 No match + * @retval 0 One of CLICON_LOG_SYSLOG|STDERR|STDOUT|FILE + */ +int +clicon_log_opt(char c) +{ + int logdst = -1; + + switch (c){ + case 's': + logdst = CLICON_LOG_SYSLOG; + break; + case 'e': + logdst = CLICON_LOG_STDERR; + break; + case 'o': + logdst = CLICON_LOG_STDOUT; + break; + case 'f': + logdst = CLICON_LOG_FILE; + break; + default: + break; + } + return logdst; +} + +/*! If log flags include CLICON_LOG_FILE, set the file * @param[in] filename File to log to * @retval 0 OK * @retval -1 Error diff --git a/lib/src/clixon_xpath.c b/lib/src/clixon_xpath.c index e4c9513a..2900562e 100644 --- a/lib/src/clixon_xpath.c +++ b/lib/src/clixon_xpath.c @@ -1070,10 +1070,10 @@ xpath_vec_ctx(cxobj *xcur, clicon_err(OE_XML, 0, "XPATH parser error with no error code (should not happen)"); goto done; } - if (debug){ + if (debug > 1){ cbuf *cb = cbuf_new(); xpath_tree_print(cb, xy.xy_top); - clicon_debug(1, "xpath parse tree:\n%s", cbuf_get(cb)); + clicon_debug(2, "xpath parse tree:\n%s", cbuf_get(cb)); cbuf_free(cb); } xc.xc_type = XT_NODESET;