From 274a4a4447b13f89f8237156a887d05a24a73cc6 Mon Sep 17 00:00:00 2001 From: ajs Date: Tue, 7 Dec 2004 15:39:31 +0000 Subject: 2004-12-07 Andrew J. Schorr * bgp_main.c: (main) The 2nd argument to openzlog has been removed. * isis_main.c: (main) The 2nd argument to openzlog has been removed. * ospf6_main.c: (main) The 2nd argument to openzlog has been removed. Note that stdout logging will no longer be enabled by default when not running as a daemon. * ospf_main.c: (main) The 2nd argument to openzlog has been removed. * rip_main.c: (main) The 2nd argument to openzlog has been removed. * ripng_main.c: (main) The 2nd argument to openzlog has been removed. * main.c: (main) The 2nd argument to openzlog has been removed. So stdout logging will no longer be enabled by default. * irdp_main.c: (irdp_finish) Reduce severity of shutdown message from LOG_WARNING to LOG_INFO. * vtysh.c: Make several functions static instead of global. Added several commands to support destination-specific logging levels. (vtysh_completion) This function is unused, so comment it out. * basic.texi: Document new logging features. Separate basic config commands from basic VTY commands. * log.h: Replace struct zlog flags and maskpri fields with maxlvl array to support individual logging levels for each destination. Remove the 2nd argument to openzlog since the default logging config should be standardized inside the library. Replaced the zlog_set_flag and zlog_reset_flag functions with zlog_set_level. And zlog_set_file now requires an additional log_level argument. Declare zlog_proto_names for use inside command.c in the "show logging" command. Added defines useful for command construction. * log.c: (vzlog) Decide where to send the message based on the individual logging levels configured for each destination. Remove support for ZLOG_STDERR since it was never actually used. Support record-priority for terminal monitors. (zlog_signal,zlog_backtrace_sigsafe) Support destination-specific logging levels. Remove stderr support (was never used). Added support for terminal monitor logging. (_zlog_assert_failed) Increase message severity to LOG_EMERG. (openzlog) Remove 2nd argument since default config should be standardized in library. By default, terminal monitoring is set to debug, and all other logging is disabled. (zlog_set_flag,zlog_reset_flag) Removed. (zlog_set_level) New function to replace zlog_set_flag and zlog_reset_flag. Supports destination-specific logging levels. (zlog_set_file,zlog_reset_file) Support file-specific logging level. (zlog_rotate) Log an error message if fopen fails, and support new file-specific logging level. * command.h: Change DEFUN_CMD_FUNC_DECL and DEFUN_CMD_FUNC_TEXT so that command functions will be static instead of global. Remove declarations for config_exit and config_help. Define new macros DEFUNSH_ATTR, DEFUNSH_HIDDEN, and DEFUNSH_DEPRECATED so we can have deprecated commands in vtysh. Similarly, for completeness, define macros ALIAS_SH, ALIAS_SH_HIDDEN, and ALIAS_SH_DEPRECATED. Also, fix bug in ALIAS_ATTR macro (didn't matter because it was never used). * command.c: Make many functions static instead of global. (facility_name,facility_match,level_match) New functions to support enhanced destination-specific logging levels. (config_write_host) Support new destination-specific logging levels. (config_logmsg) Added new "logmsg" command to help test logging system. (show_logging) Added "show logging" command to show the current configuration of the logging system. (config_log_stdout_level) Support explicit stdout logging level. (no_config_log_stdout) Now takes optional LEVEL arg. (config_log_monitor,config_log_monitor_level,no_config_log_monitor) New commands creating new "log monitor" commands to set terminal monitoring log level. (config_log_file_level) Support explicit file logging level. (config_log_syslog_level) Support explicit syslog logging level. (config_log_facility,no_config_log_facility) Implement new "log facility" command. (cmd_init) Add hooks for new commands: "show logging", "logmsg", "log stdout ", "log monitor", "log monitor ", "no log monitor", "log file ", "no log file ", "log syslog ", "log facility", and "no log facility". * vty.h: Added a "level" argument to vty_log so it can support "log record-priority". Declare new function vty_log_fixed for use in signal handlers. * vty.c: (vty_log,vty_log_out) Added a "level" argument to support "log record-priority" for vty terminal monitors. (vty_down_level) Use config_exit_cmd.func instead of calling config_exit directly (since command functions will now be static instead of global). (vty_log_fixed) New function to send terminal monitor messages from inside a signal handler. --- lib/ChangeLog | 69 +++++++ lib/command.c | 636 +++++++++++++++++++++++++++++++++++++--------------------- lib/command.h | 29 ++- lib/log.c | 167 +++++++-------- lib/log.h | 82 ++++++-- lib/vty.c | 36 +++- lib/vty.h | 6 +- 7 files changed, 672 insertions(+), 353 deletions(-) (limited to 'lib') diff --git a/lib/ChangeLog b/lib/ChangeLog index 79062cae..986c67aa 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,72 @@ +2004-12-07 Andrew J. Schorr + + * log.h: Replace struct zlog flags and maskpri fields with maxlvl + array to support individual logging levels for each destination. + Remove the 2nd argument to openzlog since the default logging config + should be standardized inside the library. Replaced the + zlog_set_flag and zlog_reset_flag functions with zlog_set_level. + And zlog_set_file now requires an additional log_level argument. + Declare zlog_proto_names for use inside command.c in the + "show logging" command. Added defines useful for command + construction. + * log.c: (vzlog) Decide where to send the message based on the + individual logging levels configured for each destination. + Remove support for ZLOG_STDERR since it was never actually used. + Support record-priority for terminal monitors. + (zlog_signal,zlog_backtrace_sigsafe) Support destination-specific + logging levels. Remove stderr support (was never used). Added + support for terminal monitor logging. + (_zlog_assert_failed) Increase message severity to LOG_EMERG. + (openzlog) Remove 2nd argument since default config should be + standardized in library. By default, terminal monitoring + is set to debug, and all other logging is disabled. + (zlog_set_flag,zlog_reset_flag) Removed. + (zlog_set_level) New function to replace zlog_set_flag and + zlog_reset_flag. Supports destination-specific logging levels. + (zlog_set_file,zlog_reset_file) Support file-specific logging level. + (zlog_rotate) Log an error message if fopen fails, and support + new file-specific logging level. + * command.h: Change DEFUN_CMD_FUNC_DECL and DEFUN_CMD_FUNC_TEXT so that + command functions will be static instead of global. Remove + declarations for config_exit and config_help. Define new macros + DEFUNSH_ATTR, DEFUNSH_HIDDEN, and DEFUNSH_DEPRECATED so we can + have deprecated commands in vtysh. Similarly, for completeness, + define macros ALIAS_SH, ALIAS_SH_HIDDEN, and ALIAS_SH_DEPRECATED. + Also, fix bug in ALIAS_ATTR macro (didn't matter because it + was never used). + * command.c: Make many functions static instead of global. + (facility_name,facility_match,level_match) New functions + to support enhanced destination-specific logging levels. + (config_write_host) Support new destination-specific logging levels. + (config_logmsg) Added new "logmsg" command to help test logging + system. + (show_logging) Added "show logging" command to show the current + configuration of the logging system. + (config_log_stdout_level) Support explicit stdout logging level. + (no_config_log_stdout) Now takes optional LEVEL arg. + (config_log_monitor,config_log_monitor_level,no_config_log_monitor) + New commands creating new "log monitor" commands to set terminal + monitoring log level. + (config_log_file_level) Support explicit file logging level. + (config_log_syslog_level) Support explicit syslog logging level. + (config_log_facility,no_config_log_facility) Implement new + "log facility" command. + (cmd_init) Add hooks for new commands: "show logging", "logmsg", + "log stdout ", "log monitor", "log monitor ", + "no log monitor", "log file ", + "no log file ", "log syslog ", + "log facility", and "no log facility". + * vty.h: Added a "level" argument to vty_log so it can support + "log record-priority". Declare new function vty_log_fixed for + use in signal handlers. + * vty.c: (vty_log,vty_log_out) Added a "level" argument to support + "log record-priority" for vty terminal monitors. + (vty_down_level) Use config_exit_cmd.func instead of calling + config_exit directly (since command functions will now be static + instead of global). + (vty_log_fixed) New function to send terminal monitor messages + from inside a signal handler. + 2004-12-03 Andrew J. Schorr * log.h: Document appropriate use of syslog logging priorities diff --git a/lib/command.c b/lib/command.c index 99036d17..18829672 100644 --- a/lib/command.c +++ b/lib/command.c @@ -1,4 +1,7 @@ -/* Command interpreter routine for virtual terminal [aka TeletYpe] +/* + $Id: command.c,v 1.28 2004/12/07 15:39:32 ajs Exp $ + + Command interpreter routine for virtual terminal [aka TeletYpe] Copyright (C) 1997, 98, 99 Kunihiro Ishiguro This file is part of GNU Zebra. @@ -75,6 +78,70 @@ Hello, this is " QUAGGA_PROGNAME " (version " QUAGGA_VERSION ").\r\n\ " QUAGGA_COPYRIGHT "\r\n\ \r\n"; + +static struct facility_map { + int facility; + const char *name; + size_t match; +} syslog_facilities[] = + { + { LOG_KERN, "kern", 1 }, + { LOG_USER, "user", 2 }, + { LOG_MAIL, "mail", 1 }, + { LOG_DAEMON, "daemon", 1 }, + { LOG_AUTH, "auth", 1 }, + { LOG_SYSLOG, "syslog", 1 }, + { LOG_LPR, "lpr", 2 }, + { LOG_NEWS, "news", 1 }, + { LOG_UUCP, "uucp", 2 }, + { LOG_CRON, "cron", 1 }, +#ifdef LOG_FTP + { LOG_FTP, "ftp", 1 }, +#endif + { LOG_LOCAL0, "local0", 6 }, + { LOG_LOCAL1, "local1", 6 }, + { LOG_LOCAL2, "local2", 6 }, + { LOG_LOCAL3, "local3", 6 }, + { LOG_LOCAL4, "local4", 6 }, + { LOG_LOCAL5, "local5", 6 }, + { LOG_LOCAL6, "local6", 6 }, + { LOG_LOCAL7, "local7", 6 }, + { 0, NULL, 0 }, + }; + +static const char * +facility_name(int facility) +{ + struct facility_map *fm; + + for (fm = syslog_facilities; fm->name; fm++) + if (fm->facility == facility) + return fm->name; + return ""; +} + +static int +facility_match(const char *str) +{ + struct facility_map *fm; + + for (fm = syslog_facilities; fm->name; fm++) + if (!strncmp(str,fm->name,fm->match)) + return fm->facility; + return -1; +} + +static int +level_match(const char *s) +{ + int level ; + + for ( level = 0 ; zlog_priority [level] != NULL ; level ++ ) + if (!strncmp (s, zlog_priority[level], 2)) + return level; + return ZLOG_DISABLED; +} + void print_version (const char *progname) { @@ -128,7 +195,7 @@ install_node (struct cmd_node *node, } /* Compare two command's string. Used in sort_node (). */ -int +static int cmp_node (const void *p, const void *q) { struct cmd_element *a = *(struct cmd_element **)p; @@ -137,7 +204,7 @@ cmp_node (const void *p, const void *q) return strcmp (a->string, b->string); } -int +static int cmp_desc (const void *p, const void *q) { struct desc *a = *(struct desc **)p; @@ -241,7 +308,7 @@ cmd_free_strvec (vector v) } /* Fetch next description. Used in cmd_make_descvec(). */ -char * +static char * cmd_desc_str (const char **string) { const char *cp, *start; @@ -277,7 +344,7 @@ cmd_desc_str (const char **string) } /* New string vector. */ -vector +static vector cmd_make_descvec (const char *string, const char *descstr) { int multiple = 0; @@ -370,7 +437,7 @@ cmd_make_descvec (const char *string, const char *descstr) /* Count mandantory string vector size. This is to determine inputed command has enough command length. */ -int +static int cmd_cmdsize (vector strvec) { unsigned int i; @@ -430,7 +497,7 @@ install_element (enum node_type ntype, struct cmd_element *cmd) static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -void +static void to64(char *s, long v, int n) { while (--n >= 0) @@ -440,7 +507,8 @@ to64(char *s, long v, int n) } } -char *zencrypt (const char *passwd) +static char * +zencrypt (const char *passwd) { char salt[6]; struct timeval tv; @@ -455,73 +523,8 @@ char *zencrypt (const char *passwd) return crypt (passwd, salt); } -const char * -syslog_facility_print (int facility) -{ - switch (facility) - { - case LOG_KERN: - return "kern"; - break; - case LOG_USER: - return "user"; - break; - case LOG_MAIL: - return "mail"; - break; - case LOG_DAEMON: - return "daemon"; - break; - case LOG_AUTH: - return "auth"; - break; - case LOG_SYSLOG: - return "syslog"; - break; - case LOG_LPR: - return "lpr"; - break; - case LOG_NEWS: - return "news"; - break; - case LOG_UUCP: - return "uucp"; - break; - case LOG_CRON: - return "cron"; - break; - case LOG_LOCAL0: - return "local0"; - break; - case LOG_LOCAL1: - return "local1"; - break; - case LOG_LOCAL2: - return "local2"; - break; - case LOG_LOCAL3: - return "local3"; - break; - case LOG_LOCAL4: - return "local4"; - break; - case LOG_LOCAL5: - return "local5"; - break; - case LOG_LOCAL6: - return "local6"; - break; - case LOG_LOCAL7: - return "local7"; - break; - default: - break; - } - return ""; -} - /* This function write configuration of this host. */ -int +static int config_write_host (struct vty *vty) { if (host.name) @@ -542,21 +545,46 @@ config_write_host (struct vty *vty) vty_out (vty, "enable password %s%s", host.enable, VTY_NEWLINE); } - if (host.logfile) - vty_out (vty, "log file %s%s", host.logfile, VTY_NEWLINE); + if (zlog_default->default_lvl != LOG_DEBUG) + vty_out (vty, "log trap %s%s", + zlog_priority[zlog_default->default_lvl], VTY_NEWLINE); + + if (host.logfile && (zlog_default->maxlvl[ZLOG_DEST_FILE] != ZLOG_DISABLED)) + { + vty_out (vty, "log file %s", host.logfile); + if (zlog_default->maxlvl[ZLOG_DEST_FILE] != zlog_default->default_lvl) + vty_out (vty, " %s", + zlog_priority[zlog_default->maxlvl[ZLOG_DEST_FILE]]); + vty_out (vty, "%s", VTY_NEWLINE); + } + + if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != ZLOG_DISABLED) + { + vty_out (vty, "log stdout"); + if (zlog_default->maxlvl[ZLOG_DEST_STDOUT] != zlog_default->default_lvl) + vty_out (vty, " %s", + zlog_priority[zlog_default->maxlvl[ZLOG_DEST_STDOUT]]); + vty_out (vty, "%s", VTY_NEWLINE); + } - if (zlog_default->flags & ZLOG_STDOUT) - vty_out (vty, "log stdout%s", VTY_NEWLINE); + if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) + vty_out(vty,"no log monitor%s",VTY_NEWLINE); + else if (zlog_default->maxlvl[ZLOG_DEST_MONITOR] != zlog_default->default_lvl) + vty_out(vty,"log monitor %s%s", + zlog_priority[zlog_default->maxlvl[ZLOG_DEST_MONITOR]],VTY_NEWLINE); - if (zlog_default->flags & ZLOG_SYSLOG) + if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != ZLOG_DISABLED) { vty_out (vty, "log syslog"); - if (zlog_default->facility != LOG_DAEMON) - vty_out (vty, " facility %s", syslog_facility_print (zlog_default->facility)); + if (zlog_default->maxlvl[ZLOG_DEST_SYSLOG] != zlog_default->default_lvl) + vty_out (vty, " %s", + zlog_priority[zlog_default->maxlvl[ZLOG_DEST_SYSLOG]]); vty_out (vty, "%s", VTY_NEWLINE); } - if (zlog_default->maskpri != LOG_DEBUG) - vty_out (vty, "log trap %s%s", zlog_priority[zlog_default->maskpri], VTY_NEWLINE); + + if (zlog_default->facility != LOG_DAEMON) + vty_out (vty, "log facility %s%s", + facility_name(zlog_default->facility), VTY_NEWLINE); if (zlog_default->record_priority == 1) vty_out (vty, "log record-priority%s", VTY_NEWLINE); @@ -578,15 +606,17 @@ config_write_host (struct vty *vty) } /* Utility function for getting command vector. */ -vector +static vector cmd_node_vector (vector v, enum node_type ntype) { struct cmd_node *cnode = vector_slot (v, ntype); return cnode->cmd_vector; } -/* Filter command vector by symbol */ -int +#if 0 +/* Filter command vector by symbol. This function is not actually used; + * should it be deleted? */ +static int cmd_filter_by_symbol (char *command, char *symbol) { int i, lim; @@ -629,6 +659,7 @@ cmd_filter_by_symbol (char *command, char *symbol) } return 0; } +#endif /* Completion match types. */ enum match_type @@ -645,7 +676,7 @@ enum match_type exact_match }; -enum match_type +static enum match_type cmd_ipv4_match (const char *str) { const char *sp; @@ -702,7 +733,7 @@ cmd_ipv4_match (const char *str) return exact_match; } -enum match_type +static enum match_type cmd_ipv4_prefix_match (const char *str) { const char *sp; @@ -793,7 +824,7 @@ cmd_ipv4_prefix_match (const char *str) #ifdef HAVE_IPV6 -enum match_type +static enum match_type cmd_ipv6_match (const char *str) { int state = STATE_START; @@ -899,7 +930,7 @@ cmd_ipv6_match (const char *str) return exact_match; } -enum match_type +static enum match_type cmd_ipv6_prefix_match (const char *str) { int state = STATE_START; @@ -1034,7 +1065,7 @@ cmd_ipv6_prefix_match (const char *str) #define DECIMAL_STRLEN_MAX 10 -int +static int cmd_range_match (const char *range, const char *str) { char *p; @@ -1080,7 +1111,7 @@ cmd_range_match (const char *range, const char *str) } /* Make completion match and return match type flag. */ -enum match_type +static enum match_type cmd_filter_by_completion (char *command, vector v, unsigned int index) { unsigned int i; @@ -1195,7 +1226,7 @@ cmd_filter_by_completion (char *command, vector v, unsigned int index) } /* Filter vector by command character with index. */ -enum match_type +static enum match_type cmd_filter_by_string (char *command, vector v, unsigned int index) { unsigned int i; @@ -1303,7 +1334,7 @@ cmd_filter_by_string (char *command, vector v, unsigned int index) } /* Check ambiguous match */ -int +static int is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) { unsigned int i; @@ -1400,7 +1431,7 @@ is_cmd_ambiguous (char *command, vector v, int index, enum match_type type) } /* If src matches dst return dst string, otherwise return NULL */ -const char * +static const char * cmd_entry_function (const char *src, const char *dst) { /* Skip variable arguments. */ @@ -1422,7 +1453,7 @@ cmd_entry_function (const char *src, const char *dst) /* If src matches dst return dst string, otherwise return NULL */ /* This version will return the dst string always if it is CMD_VARIABLE for '?' key processing */ -const char * +static const char * cmd_entry_function_desc (const char *src, const char *dst) { if (CMD_VARARG (dst)) @@ -1486,7 +1517,7 @@ cmd_entry_function_desc (const char *src, const char *dst) /* Check same string element existence. If it isn't there return 1. */ -int +static int cmd_unique_string (vector v, const char *str) { unsigned int i; @@ -1501,7 +1532,7 @@ cmd_unique_string (vector v, const char *str) /* Compare string to description vector. If there is same string return 1 else return 0. */ -int +static int desc_unique_string (vector v, const char *str) { unsigned int i; @@ -1514,7 +1545,7 @@ desc_unique_string (vector v, const char *str) return 0; } -int +static int cmd_try_do_shortcut (enum node_type node, char* first_word) { if ( first_word != NULL && node != AUTH_NODE && @@ -1527,7 +1558,7 @@ cmd_try_do_shortcut (enum node_type node, char* first_word) { } /* '?' describe command support. */ -vector +static vector cmd_describe_command_real (vector vline, struct vty *vty, int *status) { unsigned int i; @@ -1690,7 +1721,7 @@ cmd_describe_command (vector vline, struct vty *vty, int *status) /* Check LCD of matched command. */ -int +static int cmd_lcd (char **matched) { int i; @@ -1723,7 +1754,7 @@ cmd_lcd (char **matched) } /* Command line completion support. */ -char ** +static char ** cmd_complete_command_real (vector vline, struct vty *vty, int *status) { unsigned int i; @@ -1905,7 +1936,8 @@ cmd_complete_command (vector vline, struct vty *vty, int *status) /* return parent node */ /* MUST eventually converge on CONFIG_NODE */ -enum node_type node_parent ( enum node_type node ) +static enum node_type +node_parent ( enum node_type node ) { enum node_type ret; @@ -1930,7 +1962,7 @@ enum node_type node_parent ( enum node_type node ) } /* Execute command by argument vline vector. */ -int +static int cmd_execute_command_real (vector vline, struct vty *vty, struct cmd_element **cmd) { unsigned int i; @@ -2959,40 +2991,158 @@ DEFUN (no_service_terminal_length, no_service_terminal_length_cmd, return CMD_SUCCESS; } +DEFUN (config_logmsg, + config_logmsg_cmd, + "logmsg "LOG_LEVELS" .MESSAGE", + "Send a message to enabled logging destinations\n" + LOG_LEVEL_DESC + "The message to send\n") +{ + int level; + char *message; + + if ((level = level_match(argv[0])) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + + zlog(NULL, level, (message = argv_concat(argv, argc, 1))); + XFREE(MTYPE_TMP, message); + return CMD_SUCCESS; +} + +DEFUN (show_logging, + show_logging_cmd, + "show logging", + SHOW_STR + "Show current logging configuration\n") +{ + struct zlog *zl = zlog_default; + + vty_out (vty, "Syslog logging: "); + if (zl->maxlvl[ZLOG_DEST_SYSLOG] == ZLOG_DISABLED) + vty_out (vty, "disabled"); + else + vty_out (vty, "level %s, facility %s, ident %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_SYSLOG]], + facility_name(zl->facility), zl->ident); + vty_out (vty, "%s", VTY_NEWLINE); + + vty_out (vty, "Stdout logging: "); + if (zl->maxlvl[ZLOG_DEST_STDOUT] == ZLOG_DISABLED) + vty_out (vty, "disabled"); + else + vty_out (vty, "level %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_STDOUT]]); + vty_out (vty, "%s", VTY_NEWLINE); + + vty_out (vty, "Monitor logging: "); + if (zl->maxlvl[ZLOG_DEST_MONITOR] == ZLOG_DISABLED) + vty_out (vty, "disabled"); + else + vty_out (vty, "level %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_MONITOR]]); + vty_out (vty, "%s", VTY_NEWLINE); + + vty_out (vty, "File logging: "); + if ((zl->maxlvl[ZLOG_DEST_FILE] == ZLOG_DISABLED) || + !zl->fp) + vty_out (vty, "disabled"); + else + vty_out (vty, "level %s, filename %s", + zlog_priority[zl->maxlvl[ZLOG_DEST_FILE]], + zl->filename); + vty_out (vty, "%s", VTY_NEWLINE); + + vty_out (vty, "Protocol name: %s%s", + zlog_proto_names[zl->protocol], VTY_NEWLINE); + vty_out (vty, "Record priority: %s%s", + (zl->record_priority ? "enabled" : "disabled"), VTY_NEWLINE); + + return CMD_SUCCESS; +} + DEFUN (config_log_stdout, config_log_stdout_cmd, "log stdout", "Logging control\n" - "Logging goes to stdout\n") + "Set stdout logging level\n") { - zlog_set_flag (NULL, ZLOG_STDOUT); + zlog_set_level (NULL, ZLOG_DEST_STDOUT, zlog_default->default_lvl); + return CMD_SUCCESS; +} + +DEFUN (config_log_stdout_level, + config_log_stdout_level_cmd, + "log stdout "LOG_LEVELS, + "Logging control\n" + "Set stdout logging level\n" + LOG_LEVEL_DESC) +{ + int level; + + if ((level = level_match(argv[0])) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + zlog_set_level (NULL, ZLOG_DEST_STDOUT, level); return CMD_SUCCESS; } DEFUN (no_config_log_stdout, no_config_log_stdout_cmd, - "no log stdout", + "no log stdout [LEVEL]", NO_STR "Logging control\n" - "Cancel logging to stdout\n") + "Cancel logging to stdout\n" + "Logging level\n") { - zlog_reset_flag (NULL, ZLOG_STDOUT); + zlog_set_level (NULL, ZLOG_DEST_STDOUT, ZLOG_DISABLED); return CMD_SUCCESS; } -DEFUN (config_log_file, - config_log_file_cmd, - "log file FILENAME", +DEFUN (config_log_monitor, + config_log_monitor_cmd, + "log monitor", "Logging control\n" - "Logging to file\n" - "Logging filename\n") + "Set terminal line (monitor) logging level\n") +{ + zlog_set_level (NULL, ZLOG_DEST_MONITOR, zlog_default->default_lvl); + return CMD_SUCCESS; +} + +DEFUN (config_log_monitor_level, + config_log_monitor_level_cmd, + "log monitor "LOG_LEVELS, + "Logging control\n" + "Set terminal line (monitor) logging level\n" + LOG_LEVEL_DESC) +{ + int level; + + if ((level = level_match(argv[0])) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + zlog_set_level (NULL, ZLOG_DEST_MONITOR, level); + return CMD_SUCCESS; +} + +DEFUN (no_config_log_monitor, + no_config_log_monitor_cmd, + "no log monitor [LEVEL]", + NO_STR + "Logging control\n" + "Disable terminal line (monitor) logging\n" + "Logging level\n") +{ + zlog_set_level (NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED); + return CMD_SUCCESS; +} + +static int +set_log_file(struct vty *vty, const char *fname, int loglevel) { int ret; char *p = NULL; const char *fullpath; /* Path detection. */ - if (! IS_DIRECTORY_SEP (*argv[0])) + if (! IS_DIRECTORY_SEP (*fname)) { char cwd[MAXPATHLEN+1]; cwd[MAXPATHLEN] = '\0'; @@ -3003,37 +3153,62 @@ DEFUN (config_log_file, return CMD_WARNING; } - if ( (p = XMALLOC (MTYPE_TMP, strlen (cwd) + strlen (argv[0]) + 2)) + if ( (p = XMALLOC (MTYPE_TMP, strlen (cwd) + strlen (fname) + 2)) == NULL) { zlog_err ("config_log_file: Unable to alloc mem!"); return CMD_WARNING; } - sprintf (p, "%s/%s", cwd, argv[0]); + sprintf (p, "%s/%s", cwd, fname); fullpath = p; } else - fullpath = argv[0]; + fullpath = fname; - ret = zlog_set_file (NULL, fullpath); + ret = zlog_set_file (NULL, fullpath, loglevel); if (p) XFREE (MTYPE_TMP, p); if (!ret) { - vty_out (vty, "can't open logfile %s\n", argv[0]); + vty_out (vty, "can't open logfile %s\n", fname); return CMD_WARNING; } if (host.logfile) XFREE (MTYPE_TMP, host.logfile); - host.logfile = XSTRDUP (MTYPE_TMP, argv[0]); + host.logfile = XSTRDUP (MTYPE_TMP, fname); return CMD_SUCCESS; } +DEFUN (config_log_file, + config_log_file_cmd, + "log file FILENAME", + "Logging control\n" + "Logging to file\n" + "Logging filename\n") +{ + return set_log_file(vty, argv[0], zlog_default->default_lvl); +} + +DEFUN (config_log_file_level, + config_log_file_level_cmd, + "log file FILENAME "LOG_LEVELS, + "Logging control\n" + "Logging to file\n" + "Logging filename\n" + LOG_LEVEL_DESC) +{ + int level; + + if ((level = level_match(argv[1])) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + return set_log_file(vty, argv[0], level); +} + DEFUN (no_config_log_file, no_config_log_file_cmd, "no log file [FILENAME]", @@ -3052,154 +3227,135 @@ DEFUN (no_config_log_file, return CMD_SUCCESS; } +ALIAS (no_config_log_file, + no_config_log_file_level_cmd, + "no log file FILENAME LEVEL", + NO_STR + "Logging control\n" + "Cancel logging to file\n" + "Logging file name\n" + "Logging level\n") + DEFUN (config_log_syslog, config_log_syslog_cmd, "log syslog", "Logging control\n" - "Logging goes to syslog\n") + "Set syslog logging level\n") { - zlog_set_flag (NULL, ZLOG_SYSLOG); - zlog_default->facility = LOG_DAEMON; + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); return CMD_SUCCESS; } -DEFUN (config_log_syslog_facility, - config_log_syslog_facility_cmd, - "log syslog facility (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)", +DEFUN (config_log_syslog_level, + config_log_syslog_level_cmd, + "log syslog "LOG_LEVELS, "Logging control\n" - "Logging goes to syslog\n" - "Facility parameter for syslog messages\n" - "Kernel\n" - "User process\n" - "Mail system\n" - "System daemons\n" - "Authorization system\n" - "Syslog itself\n" - "Line printer system\n" - "USENET news\n" - "Unix-to-Unix copy system\n" - "Cron/at facility\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n") -{ - int facility = LOG_DAEMON; - - zlog_set_flag (NULL, ZLOG_SYSLOG); - - if (strncmp (argv[0], "kern", 1) == 0) - facility = LOG_KERN; - else if (strncmp (argv[0], "user", 2) == 0) - facility = LOG_USER; - else if (strncmp (argv[0], "mail", 1) == 0) - facility = LOG_MAIL; - else if (strncmp (argv[0], "daemon", 1) == 0) - facility = LOG_DAEMON; - else if (strncmp (argv[0], "auth", 1) == 0) - facility = LOG_AUTH; - else if (strncmp (argv[0], "syslog", 1) == 0) - facility = LOG_SYSLOG; - else if (strncmp (argv[0], "lpr", 2) == 0) - facility = LOG_LPR; - else if (strncmp (argv[0], "news", 1) == 0) - facility = LOG_NEWS; - else if (strncmp (argv[0], "uucp", 2) == 0) - facility = LOG_UUCP; - else if (strncmp (argv[0], "cron", 1) == 0) - facility = LOG_CRON; - else if (strncmp (argv[0], "local0", 6) == 0) - facility = LOG_LOCAL0; - else if (strncmp (argv[0], "local1", 6) == 0) - facility = LOG_LOCAL1; - else if (strncmp (argv[0], "local2", 6) == 0) - facility = LOG_LOCAL2; - else if (strncmp (argv[0], "local3", 6) == 0) - facility = LOG_LOCAL3; - else if (strncmp (argv[0], "local4", 6) == 0) - facility = LOG_LOCAL4; - else if (strncmp (argv[0], "local5", 6) == 0) - facility = LOG_LOCAL5; - else if (strncmp (argv[0], "local6", 6) == 0) - facility = LOG_LOCAL6; - else if (strncmp (argv[0], "local7", 6) == 0) - facility = LOG_LOCAL7; + "Set syslog logging level\n" + LOG_LEVEL_DESC) +{ + int level; - zlog_default->facility = facility; + if ((level = level_match(argv[0])) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, level); + return CMD_SUCCESS; +} + +DEFUN_DEPRECATED (config_log_syslog_facility, + config_log_syslog_facility_cmd, + "log syslog facility "LOG_FACILITIES, + "Logging control\n" + "Logging goes to syslog\n" + "(Deprecated) Facility parameter for syslog messages\n" + LOG_FACILITY_DESC) +{ + int facility; + + if ((facility = facility_match(argv[0])) < 0) + return CMD_ERR_NO_MATCH; + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, zlog_default->default_lvl); + zlog_default->facility = facility; return CMD_SUCCESS; } DEFUN (no_config_log_syslog, no_config_log_syslog_cmd, - "no log syslog", + "no log syslog [LEVEL]", NO_STR "Logging control\n" - "Cancel logging to syslog\n") + "Cancel logging to syslog\n" + "Logging level\n") { - zlog_reset_flag (NULL, ZLOG_SYSLOG); - zlog_default->facility = LOG_DAEMON; + zlog_set_level (NULL, ZLOG_DEST_SYSLOG, ZLOG_DISABLED); return CMD_SUCCESS; } ALIAS (no_config_log_syslog, no_config_log_syslog_facility_cmd, - "no log syslog facility (kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)", + "no log syslog facility "LOG_FACILITIES, NO_STR "Logging control\n" "Logging goes to syslog\n" "Facility parameter for syslog messages\n" - "Kernel\n" - "User process\n" - "Mail system\n" - "System daemons\n" - "Authorization system\n" - "Syslog itself\n" - "Line printer system\n" - "USENET news\n" - "Unix-to-Unix copy system\n" - "Cron/at facility\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n" - "Local use\n") - -DEFUN (config_log_trap, - config_log_trap_cmd, - "log trap (emergencies|alerts|critical|errors|warnings|notifications|informational|debugging)", + LOG_FACILITY_DESC) + +DEFUN (config_log_facility, + config_log_facility_cmd, + "log facility "LOG_FACILITIES, "Logging control\n" - "Limit logging to specifed level\n") + "Facility parameter for syslog messages\n" + LOG_FACILITY_DESC) { - int new_level ; - - for ( new_level = 0 ; zlog_priority [new_level] != NULL ; new_level ++ ) - { - if ( strcmp ( argv[0], zlog_priority [new_level] ) == 0 ) - /* found new logging level */ - { - zlog_default->maskpri = new_level; - return CMD_SUCCESS; - } - } - return CMD_ERR_NO_MATCH; + int facility; + + if ((facility = facility_match(argv[0])) < 0) + return CMD_ERR_NO_MATCH; + zlog_default->facility = facility; + return CMD_SUCCESS; } -DEFUN (no_config_log_trap, - no_config_log_trap_cmd, - "no log trap", +DEFUN (no_config_log_facility, + no_config_log_facility_cmd, + "no log facility [FACILITY]", NO_STR "Logging control\n" - "Permit all logging information\n") + "Reset syslog facility to default (daemon)\n" + "Syslog facility\n") +{ + zlog_default->facility = LOG_DAEMON; + return CMD_SUCCESS; +} + +DEFUN_DEPRECATED (config_log_trap, + config_log_trap_cmd, + "log trap "LOG_LEVELS, + "Logging control\n" + "(Deprecated) Set logging level and default for all destinations\n" + LOG_LEVEL_DESC) +{ + int new_level ; + int i; + + if ((new_level = level_match(argv[0])) == ZLOG_DISABLED) + return CMD_ERR_NO_MATCH; + + zlog_default->default_lvl = new_level; + for (i = 0; i < ZLOG_NUM_DESTS; i++) + if (zlog_default->maxlvl[i] != ZLOG_DISABLED) + zlog_default->maxlvl[i] = new_level; + return CMD_SUCCESS; +} + +DEFUN_DEPRECATED (no_config_log_trap, + no_config_log_trap_cmd, + "no log trap [LEVEL]", + NO_STR + "Logging control\n" + "Permit all logging information\n" + "Logging level\n") { - zlog_default->maskpri = LOG_DEBUG; + zlog_default->default_lvl = LOG_DEBUG; return CMD_SUCCESS; } @@ -3304,6 +3460,7 @@ cmd_init (int terminal) install_element (VIEW_NODE, &config_enable_cmd); install_element (VIEW_NODE, &config_terminal_length_cmd); install_element (VIEW_NODE, &config_terminal_no_length_cmd); + install_element (VIEW_NODE, &show_logging_cmd); } if (terminal) @@ -3320,6 +3477,8 @@ cmd_init (int terminal) { install_element (ENABLE_NODE, &config_terminal_length_cmd); install_element (ENABLE_NODE, &config_terminal_no_length_cmd); + install_element (ENABLE_NODE, &show_logging_cmd); + install_element (ENABLE_NODE, &config_logmsg_cmd); install_default (CONFIG_NODE); } @@ -3336,13 +3495,22 @@ cmd_init (int terminal) install_element (CONFIG_NODE, &no_enable_password_cmd); install_element (CONFIG_NODE, &config_log_stdout_cmd); + install_element (CONFIG_NODE, &config_log_stdout_level_cmd); install_element (CONFIG_NODE, &no_config_log_stdout_cmd); + install_element (CONFIG_NODE, &config_log_monitor_cmd); + install_element (CONFIG_NODE, &config_log_monitor_level_cmd); + install_element (CONFIG_NODE, &no_config_log_monitor_cmd); install_element (CONFIG_NODE, &config_log_file_cmd); + install_element (CONFIG_NODE, &config_log_file_level_cmd); install_element (CONFIG_NODE, &no_config_log_file_cmd); + install_element (CONFIG_NODE, &no_config_log_file_level_cmd); install_element (CONFIG_NODE, &config_log_syslog_cmd); + install_element (CONFIG_NODE, &config_log_syslog_level_cmd); install_element (CONFIG_NODE, &config_log_syslog_facility_cmd); install_element (CONFIG_NODE, &no_config_log_syslog_cmd); install_element (CONFIG_NODE, &no_config_log_syslog_facility_cmd); + install_element (CONFIG_NODE, &config_log_facility_cmd); + install_element (CONFIG_NODE, &no_config_log_facility_cmd); install_element (CONFIG_NODE, &config_log_trap_cmd); install_element (CONFIG_NODE, &no_config_log_trap_cmd); install_element (CONFIG_NODE, &config_log_record_priority_cmd); diff --git a/lib/command.h b/lib/command.h index 52cfded9..c8699e10 100644 --- a/lib/command.h +++ b/lib/command.h @@ -177,10 +177,10 @@ struct desc }; #define DEFUN_CMD_FUNC_DECL(funcname) \ - int funcname (struct cmd_element *, struct vty *, int, const char *[]); \ + static int funcname (struct cmd_element *, struct vty *, int, const char *[]); \ #define DEFUN_CMD_FUNC_TEXT(funcname) \ - int funcname \ + static int funcname \ (struct cmd_element *self, struct vty *vty, int argc, const char *argv[]) /* DEFUN for vty command interafce. Little bit hacky ;-). */ @@ -214,12 +214,24 @@ struct desc DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) \ DEFUN_CMD_FUNC_TEXT(funcname) +/* DEFUN + DEFSH with attributes */ +#define DEFUNSH_ATTR(daemon, funcname, cmdname, cmdstr, helpstr, attr) \ + DEFUN_CMD_FUNC_DECL(funcname) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, daemon) \ + DEFUN_CMD_FUNC_TEXT(funcname) + +#define DEFUNSH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN) + +#define DEFUNSH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUNSH_ATTR (daemon, funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED) + /* ALIAS macro which define existing command's alias. */ #define ALIAS(funcname, cmdname, cmdstr, helpstr) \ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, 0) #define ALIAS_ATTR(funcname, cmdname, cmdstr, helpstr, attr) \ - DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, daemon) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, attr, 0) #define ALIAS_HIDDEN(funcname, cmdname, cmdstr, helpstr) \ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, 0) @@ -227,6 +239,15 @@ struct desc #define ALIAS_DEPRECATED(funcname, cmdname, cmdstr, helpstr) \ DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, 0) +#define ALIAS_SH(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, 0, daemon) + +#define ALIAS_SH_HIDDEN(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_HIDDEN, daemon) + +#define ALIAS_SH_DEPRECATED(daemon, funcname, cmdname, cmdstr, helpstr) \ + DEFUN_CMD_ELEMENT(funcname, cmdname, cmdstr, helpstr, CMD_ATTR_DEPRECATED, daemon) + #endif /* VTYSH_EXTRACT_PL */ /* Some macroes */ @@ -319,8 +340,6 @@ extern struct cmd_element config_exit_cmd; extern struct cmd_element config_quit_cmd; extern struct cmd_element config_help_cmd; extern struct cmd_element config_list_cmd; -int config_exit (struct cmd_element *, struct vty *, int, const char *[]); -int config_help (struct cmd_element *, struct vty *, int, const char *[]); char *host_config_file (); void host_config_set (char *); diff --git a/lib/log.c b/lib/log.c index d3106cb4..b68896ca 100644 --- a/lib/log.c +++ b/lib/log.c @@ -1,4 +1,7 @@ -/* Logging of zebra +/* + * $Id: log.c,v 1.17 2004/12/07 15:39:32 ajs Exp $ + * + * Logging of zebra * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro * * This file is part of GNU Zebra. @@ -104,12 +107,8 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) return; } - /* only log this information if it has not been masked out */ - if ( priority > zl->maskpri ) - return ; - /* Syslog output */ - if (zl->flags & ZLOG_SYSLOG) + if (priority <= zl->maxlvl[ZLOG_DEST_SYSLOG]) { va_list ac; va_copy(ac, args); @@ -118,7 +117,7 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) } /* File output. */ - if (zl->flags & ZLOG_FILE) + if ((priority <= zl->maxlvl[ZLOG_DEST_FILE]) && zl->fp) { va_list ac; time_print (zl->fp); @@ -133,7 +132,7 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) } /* stdout output. */ - if (zl->flags & ZLOG_STDOUT) + if (priority <= zl->maxlvl[ZLOG_DEST_STDOUT]) { va_list ac; time_print (stdout); @@ -147,23 +146,10 @@ vzlog (struct zlog *zl, int priority, const char *format, va_list args) fflush (stdout); } - /* stderr output. */ - if (zl->flags & ZLOG_STDERR) - { - va_list ac; - time_print (stderr); - if (zl->record_priority) - fprintf (stderr, "%s: ", zlog_priority[priority]); - fprintf (stderr, "%s: ", zlog_proto_names[zl->protocol]); - va_copy(ac, args); - vfprintf (stderr, format, ac); - va_end(ac); - fprintf (stderr, "\n"); - fflush (stderr); - } - /* Terminal monitor. */ - vty_log (zlog_proto_names[zl->protocol], format, args); + if (priority <= zl->maxlvl[ZLOG_DEST_MONITOR]) + vty_log ((zl->record_priority ? zlog_priority[priority] : NULL), + zlog_proto_names[zl->protocol], format, args); } static char * @@ -297,26 +283,29 @@ zlog_signal(int signo, const char *action) if (s < buf+sizeof(buf)) *s++ = '\n'; + /* N.B. implicit priority is most severe */ +#define PRI LOG_EMERG + #define DUMP(FP) write(fileno(FP),buf,s-buf); if (!zlog_default) DUMP(stderr) else { - if ((zlog_default->flags & ZLOG_FILE) && zlog_default->fp) + if ((PRI <= zlog_default->maxlvl[ZLOG_DEST_FILE]) && zlog_default->fp) DUMP(zlog_default->fp) - if (zlog_default->flags & ZLOG_STDOUT) + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_STDOUT]) DUMP(stdout) - if (zlog_default->flags & ZLOG_STDERR) - DUMP(stderr) - if (zlog_default->flags & ZLOG_SYSLOG) - { - *--s = '\0'; - syslog_sigsafe(LOG_ERR|zlog_default->facility,msgstart,s-msgstart); - } + /* Remove trailing '\n' for monitor and syslog */ + *--s = '\0'; + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) + vty_log_fixed(buf,s-buf); + if (PRI <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) + syslog_sigsafe(PRI|zlog_default->facility,msgstart,s-msgstart); } #undef DUMP - zlog_backtrace_sigsafe(LOG_ERR); + zlog_backtrace_sigsafe(PRI); +#undef PRI #undef LOC } @@ -332,10 +321,6 @@ zlog_backtrace_sigsafe(int priority) char *s; #define LOC s,buf+sizeof(buf)-s - /* only log this information if it has not been masked out */ - if (zlog_default && (priority > zlog_default->maskpri)) - return; - if (((size = backtrace(array,sizeof(array)/sizeof(array[0]))) <= 0) || ((size_t)size > sizeof(array)/sizeof(array[0]))) return; @@ -353,29 +338,34 @@ zlog_backtrace_sigsafe(int priority) DUMP(stderr) else { - if ((zlog_default->flags & ZLOG_FILE) && zlog_default->fp) + if ((priority <= zlog_default->maxlvl[ZLOG_DEST_FILE]) && + zlog_default->fp) DUMP(zlog_default->fp) - if (zlog_default->flags & ZLOG_STDOUT) + if (priority <= zlog_default->maxlvl[ZLOG_DEST_STDOUT]) DUMP(stdout) - if (zlog_default->flags & ZLOG_STDERR) - DUMP(stderr) - if (zlog_default->flags & ZLOG_SYSLOG) - { - int i; - *--s = '\0'; - syslog_sigsafe(priority|zlog_default->facility,buf,s-buf); - /* Just print the function addresses. */ - for (i = 0; i < size; i++) - { - s = buf; - s = str_append(LOC,"[bt "); - s = num_append(LOC,i); - s = str_append(LOC,"] 0x"); - s = hex_append(LOC,(u_long)(array[i])); - *s = '\0'; + /* Remove trailing '\n' for monitor and syslog */ + *--s = '\0'; + if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) + vty_log_fixed(buf,s-buf); + if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) + syslog_sigsafe(priority|zlog_default->facility,buf,s-buf); + { + int i; + /* Just print the function addresses. */ + for (i = 0; i < size; i++) + { + s = buf; + s = str_append(LOC,"[bt "); + s = num_append(LOC,i); + s = str_append(LOC,"] 0x"); + s = hex_append(LOC,(u_long)(array[i])); + *s = '\0'; + if (priority <= zlog_default->maxlvl[ZLOG_DEST_MONITOR]) + vty_log_fixed(buf,s-buf); + if (priority <= zlog_default->maxlvl[ZLOG_DEST_SYSLOG]) syslog_sigsafe(priority|zlog_default->facility,buf,s-buf); - } - } + } + } } #undef DUMP #undef LOC @@ -476,29 +466,32 @@ _zlog_assert_failed (const char *assertion, const char *file, { zlog_err("Assertion `%s' failed in file %s, line %u, function %s", assertion,file,line,(function ? function : "?")); - zlog_backtrace(LOG_ERR); + zlog_backtrace(LOG_EMERG); abort(); } /* Open log stream */ struct zlog * -openzlog (const char *progname, int flags, zlog_proto_t protocol, +openzlog (const char *progname, zlog_proto_t protocol, int syslog_flags, int syslog_facility) { struct zlog *zl; + u_int i; - zl = XMALLOC(MTYPE_ZLOG, sizeof (struct zlog)); - memset (zl, 0, sizeof (struct zlog)); + zl = XCALLOC(MTYPE_ZLOG, sizeof (struct zlog)); zl->ident = progname; - zl->flags = flags; zl->protocol = protocol; zl->facility = syslog_facility; - zl->maskpri = LOG_DEBUG; - zl->record_priority = 0; zl->syslog_options = syslog_flags; + /* Set default logging levels. */ + for (i = 0; i < sizeof(zl->maxlvl)/sizeof(zl->maxlvl[0]); i++) + zl->maxlvl[i] = ZLOG_DISABLED; + zl->maxlvl[ZLOG_DEST_MONITOR] = LOG_DEBUG; + zl->default_lvl = LOG_DEBUG; + openlog (progname, syslog_flags, zl->facility); return zl; @@ -515,25 +508,16 @@ closezlog (struct zlog *zl) /* Called from command.c. */ void -zlog_set_flag (struct zlog *zl, int flags) +zlog_set_level (struct zlog *zl, zlog_dest_t dest, int log_level) { if (zl == NULL) zl = zlog_default; - zl->flags |= flags; -} - -void -zlog_reset_flag (struct zlog *zl, int flags) -{ - if (zl == NULL) - zl = zlog_default; - - zl->flags &= ~flags; + zl->maxlvl[dest] = log_level; } int -zlog_set_file (struct zlog *zl, const char *filename) +zlog_set_file (struct zlog *zl, const char *filename, int log_level) { FILE *fp; mode_t oldumask; @@ -548,16 +532,13 @@ zlog_set_file (struct zlog *zl, const char *filename) /* Open file. */ oldumask = umask (0777 & ~LOGFILE_MASK); fp = fopen (filename, "a"); - if (fp == NULL) - { - umask(oldumask); - return 0; - } umask(oldumask); + if (fp == NULL) + return 0; /* Set flags. */ zl->filename = strdup (filename); - zl->flags |= ZLOG_FILE; + zl->maxlvl[ZLOG_DEST_FILE] = log_level; zl->fp = fp; return 1; @@ -570,11 +551,10 @@ zlog_reset_file (struct zlog *zl) if (zl == NULL) zl = zlog_default; - zl->flags &= ~ZLOG_FILE; - if (zl->fp) fclose (zl->fp); zl->fp = NULL; + zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED; if (zl->filename) free (zl->filename); @@ -587,7 +567,7 @@ zlog_reset_file (struct zlog *zl) int zlog_rotate (struct zlog *zl) { - FILE *fp; + int level; if (zl == NULL) zl = zlog_default; @@ -595,20 +575,25 @@ zlog_rotate (struct zlog *zl) if (zl->fp) fclose (zl->fp); zl->fp = NULL; + level = zl->maxlvl[ZLOG_DEST_FILE]; + zl->maxlvl[ZLOG_DEST_FILE] = ZLOG_DISABLED; if (zl->filename) { mode_t oldumask; + int save_errno; oldumask = umask (0777 & ~LOGFILE_MASK); - fp = fopen (zl->filename, "a"); - if (fp == NULL) + zl->fp = fopen (zl->filename, "a"); + save_errno = errno; + umask(oldumask); + if (zl->fp == NULL) { - umask(oldumask); + zlog_err("Log rotate failed: cannot open file %s for append: %s", + zl->filename, safe_strerror(save_errno)); return -1; } - umask(oldumask); - zl->fp = fp; + zl->maxlvl[ZLOG_DEST_FILE] = level; } return 1; diff --git a/lib/log.h b/lib/log.h index 26ff902b..1f9f23cd 100644 --- a/lib/log.h +++ b/lib/log.h @@ -1,4 +1,7 @@ -/* Zebra logging funcions. +/* + * $Id: log.h,v 1.14 2004/12/07 15:39:32 ajs Exp $ + * + * Zebra logging funcions. * Copyright (C) 1997, 1998, 1999 Kunihiro Ishiguro * * This file is part of GNU Zebra. @@ -40,12 +43,6 @@ * please use LOG_ERR instead. */ -#define ZLOG_NOLOG 0x00 -#define ZLOG_FILE 0x01 -#define ZLOG_SYSLOG 0x02 -#define ZLOG_STDOUT 0x04 -#define ZLOG_STDERR 0x08 - typedef enum { ZLOG_NONE, @@ -60,14 +57,28 @@ typedef enum ZLOG_MASC } zlog_proto_t; +/* If maxlvl is set to ZLOG_DISABLED, then no messages will be sent + to that logging destination. */ +#define ZLOG_DISABLED (LOG_EMERG-1) + +typedef enum +{ + ZLOG_DEST_SYSLOG = 0, + ZLOG_DEST_STDOUT, + ZLOG_DEST_MONITOR, + ZLOG_DEST_FILE +} zlog_dest_t; +#define ZLOG_NUM_DESTS (ZLOG_DEST_FILE+1) + struct zlog { const char *ident; /* daemon name (first arg to openlog) */ zlog_proto_t protocol; - int flags; /* mask indicating which destinations to log to */ + int maxlvl[ZLOG_NUM_DESTS]; /* maximum priority to send to associated + logging destination */ + int default_lvl; /* maxlvl to use if none is specified */ FILE *fp; char *filename; - int maskpri; /* discard messages with priority > maskpri */ int facility; /* as per syslog facility */ int record_priority; /* should messages logged through stdio include the priority of the message? */ @@ -85,7 +96,8 @@ struct message extern struct zlog *zlog_default; /* Open zlog function */ -struct zlog *openzlog (const char *, int, zlog_proto_t, int, int); +struct zlog *openzlog (const char *progname, zlog_proto_t protocol, + int syslog_options, int syslog_facility); /* Close zlog function. */ void closezlog (struct zlog *zl); @@ -114,12 +126,15 @@ void plog_info (struct zlog *, const char *format, ...); void plog_notice (struct zlog *, const char *format, ...); void plog_debug (struct zlog *, const char *format, ...); -/* Set zlog flags. */ -void zlog_set_flag (struct zlog *zl, int flags); -void zlog_reset_flag (struct zlog *zl, int flags); +/* Set logging level for the given destination. If the log_level + argument is ZLOG_DISABLED, then the destination is disabled. + This function should not be used for file logging (use zlog_set_file + or zlog_reset_file instead). */ +void zlog_set_level (struct zlog *zl, zlog_dest_t, int log_level); -/* Set zlog filename. */ -int zlog_set_file (struct zlog *zl, const char *filename); +/* Set logging to the given filename at the specified level. */ +int zlog_set_file (struct zlog *zl, const char *filename, int log_level); +/* Disable file logging. */ int zlog_reset_file (struct zlog *zl); /* Rotate log. */ @@ -132,6 +147,7 @@ const char *lookup (struct message *, int); const char *mes_lookup (struct message *meslist, int max, int index); extern const char *zlog_priority[]; +extern const char *zlog_proto_names[]; /* Safe version of strerror -- never returns NULL. */ extern const char *safe_strerror(int errnum); @@ -147,4 +163,40 @@ extern void zlog_backtrace(int priority); up the state of zlog file pointers. */ extern void zlog_backtrace_sigsafe(int priority); +/* Defines for use in command construction: */ + +#define LOG_LEVELS "(emergencies|alerts|critical|errors|warnings|notifications|informational|debugging)" + +#define LOG_LEVEL_DESC \ + "System is unusable\n" \ + "Immediate action needed\n" \ + "Critical conditions\n" \ + "Error conditions\n" \ + "Warning conditions\n" \ + "Normal but significant conditions\n" \ + "Informational messages\n" \ + "Debugging messages\n" + +#define LOG_FACILITIES "(kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7)" + +#define LOG_FACILITY_DESC \ + "Kernel\n" \ + "User process\n" \ + "Mail system\n" \ + "System daemons\n" \ + "Authorization system\n" \ + "Syslog itself\n" \ + "Line printer system\n" \ + "USENET news\n" \ + "Unix-to-Unix copy system\n" \ + "Cron/at facility\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" \ + "Local use\n" + #endif /* _ZEBRA_LOG_H */ diff --git a/lib/vty.c b/lib/vty.c index bf1eec38..25366fb4 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -148,14 +148,17 @@ vty_out (struct vty *vty, const char *format, ...) } static int -vty_log_out (struct vty *vty, const char *proto_str, const char *format, - va_list va) +vty_log_out (struct vty *vty, const char *level, const char *proto_str, + const char *format, va_list va) { int len; char buf[1024]; - snprintf (buf, sizeof buf, "%s: ", proto_str); - write (vty->fd, buf, strlen (proto_str) + 2); + if (level) + snprintf (buf, sizeof buf, "%s: %s: ", level, proto_str); + else + snprintf (buf, sizeof buf, "%s: ", proto_str); + write (vty->fd, buf, strlen (buf)); len = vsnprintf (buf, sizeof buf, format, va); if (len < 0) @@ -602,7 +605,7 @@ static void vty_down_level (struct vty *vty) { vty_out (vty, "%s", VTY_NEWLINE); - config_exit (NULL, vty, 0, NULL); + (*config_exit_cmd.func)(NULL, vty, 0, NULL); vty_prompt (vty); vty->cp = 0; } @@ -2273,7 +2276,8 @@ vty_read_config (char *config_file, /* Small utility function which output log to the VTY. */ void -vty_log (const char *proto_str, const char *format, va_list va) +vty_log (const char *level, const char *proto_str, + const char *format, va_list va) { unsigned int i; struct vty *vty; @@ -2284,11 +2288,29 @@ vty_log (const char *proto_str, const char *format, va_list va) { va_list ac; va_copy(ac, va); - vty_log_out (vty, proto_str, format, ac); + vty_log_out (vty, level, proto_str, format, ac); va_end(ac); } } +/* Async-signal-safe version of vty_log for fixed strings. */ +void +vty_log_fixed (const char *buf, size_t len) +{ + unsigned int i; + + for (i = 0; i < vector_max (vtyvec); i++) + { + struct vty *vty; + if ((vty = vector_slot (vtyvec, i)) != NULL) + if (vty->monitor) + { + write(vty->fd, buf, len); + write(vty->fd, "\r\n", 2); + } + } +} + int vty_config_lock (struct vty *vty) { diff --git a/lib/vty.h b/lib/vty.h index c3221e2a..8cd2b4e3 100644 --- a/lib/vty.h +++ b/lib/vty.h @@ -180,11 +180,15 @@ void vty_time_print (struct vty *, int); void vty_serv_sock (const char *, unsigned short, const char *); void vty_close (struct vty *); char *vty_get_cwd (void); -void vty_log (const char *, const char *, va_list); +void vty_log (const char *level, const char *proto, const char *fmt, va_list); int vty_config_lock (struct vty *); int vty_config_unlock (struct vty *); int vty_shell (struct vty *); int vty_shell_serv (struct vty *); void vty_hello (struct vty *); +/* Send a fixed-size message to all vty terminal monitors; this should be + an async-signal-safe function. */ +extern void vty_log_fixed (const char *buf, size_t len); + #endif /* _ZEBRA_VTY_H */ -- cgit v1.2.1