diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/ChangeLog | 69 | ||||
| -rw-r--r-- | lib/command.c | 636 | ||||
| -rw-r--r-- | lib/command.h | 29 | ||||
| -rw-r--r-- | lib/log.c | 167 | ||||
| -rw-r--r-- | lib/log.h | 82 | ||||
| -rw-r--r-- | lib/vty.c | 36 | ||||
| -rw-r--r-- | lib/vty.h | 6 | 
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 *); @@ -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; @@ -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 */ @@ -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)  { @@ -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 */ | 
