summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ChangeLog69
-rw-r--r--lib/command.c636
-rw-r--r--lib/command.h29
-rw-r--r--lib/log.c167
-rw-r--r--lib/log.h82
-rw-r--r--lib/vty.c36
-rw-r--r--lib/vty.h6
7 files changed, 672 insertions, 353 deletions
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 <ajschorr@alumni.princeton.edu>
+
+ * 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 <level>", "log monitor", "log monitor <level>",
+ "no log monitor", "log file <filename> <level>",
+ "no log file <filename> <level>", "log syslog <level>",
+ "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 <ajschorr@alumni.princeton.edu>
* 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 */