diff options
| -rw-r--r-- | include/osmocom/vty/logging.h | 5 | ||||
| -rw-r--r-- | include/osmocore/logging.h | 6 | ||||
| -rw-r--r-- | src/logging.c | 138 | ||||
| -rw-r--r-- | src/vty/logging_vty.c | 56 | 
4 files changed, 128 insertions, 77 deletions
| diff --git a/include/osmocom/vty/logging.h b/include/osmocom/vty/logging.h index f4e28f88..e0011bf9 100644 --- a/include/osmocom/vty/logging.h +++ b/include/osmocom/vty/logging.h @@ -4,8 +4,9 @@  #define LOGGING_STR	"Configure log message to this terminal\n"  #define FILTER_STR	"Filter log messages\n" -void logging_vty_add_cmds(void); - +struct log_info; +void logging_vty_add_cmds(const struct log_info *cat); +struct vty;  struct log_target *osmo_log_vty2tgt(struct vty *vty);  #endif /* _VTY_LOGGING_H */ diff --git a/include/osmocore/logging.h b/include/osmocore/logging.h index a2c63e9a..fd458440 100644 --- a/include/osmocore/logging.h +++ b/include/osmocore/logging.h @@ -144,9 +144,9 @@ int log_target_file_reopen(struct log_target *tgt);  void log_add_target(struct log_target *target);  void log_del_target(struct log_target *target); -/* Gernerate command argument strings for VTY use */ -const char *log_vty_category_string(struct log_info *info); -const char *log_vty_level_string(struct log_info *info); +/* Generate command string for VTY use */ +const char *log_vty_command_string(const struct log_info *info); +const char *log_vty_command_description(const struct log_info *info);  struct log_target *log_target_find(int type, const char *fname);  extern struct llist_head osmo_log_target_list; diff --git a/src/logging.c b/src/logging.c index 876a3526..89ca6ced 100644 --- a/src/logging.c +++ b/src/logging.c @@ -26,6 +26,7 @@  #include <stdlib.h>  #include <stdio.h>  #include <string.h> +#include <ctype.h>  #ifdef HAVE_STRINGS_H  #include <strings.h> @@ -37,13 +38,17 @@  #include <osmocore/utils.h>  #include <osmocore/logging.h> +#include <osmocom/vty/logging.h>	/* for LOGGING_STR. */ +  const struct log_info *osmo_log_info;  static struct log_context log_context;  static void *tall_log_ctx = NULL;  LLIST_HEAD(osmo_log_target_list); -static const struct value_string loglevel_strs[] = { +#define LOGLEVEL_DEFS	6	/* Number of loglevels.*/ + +static const struct value_string loglevel_strs[LOGLEVEL_DEFS+1] = {  	{ 0,		"EVERYTHING" },  	{ LOGL_DEBUG,	"DEBUG" },  	{ LOGL_INFO,	"INFO" }, @@ -53,6 +58,17 @@ static const struct value_string loglevel_strs[] = {  	{ 0, NULL },  }; +/* You have to keep this in sync with the structure loglevel_strs. */ +const char *loglevel_descriptions[LOGLEVEL_DEFS+1] = { +	"Log simply everything", +	"Log debug messages and higher levels", +	"Log informational messages and higher levels", +	"Log noticable messages and higher levels", +	"Log error messages and higher levels", +	"Log only fatal messages", +	NULL, +}; +  int log_parse_level(const char *lvl)  {  	return get_string_value(loglevel_strs, lvl); @@ -418,49 +434,125 @@ int log_target_file_reopen(struct log_target *target)  	return 0;  } -const char *log_vty_level_string(struct log_info *info) +/* This can go into some header file so others can benefit from it. */ +#define SNPRINTF_FAILURE(ret, rem, offset, len)			\ +do {								\ +	len += ret;						\ +	if (ret > rem)						\ +		ret = rem;					\ +	offset += ret;						\ +	rem -= ret;						\ +} while (0) + +/* This generates the logging command string for VTY. */ +const char *log_vty_command_string(const struct log_info *info)  { -	const struct value_string *vs; -	unsigned int len = 3; /* ()\0 */ +	int len = 0, offset = 0, ret, i, rem; +	int size = strlen("logging level () ()") + 1;  	char *str; -	for (vs = loglevel_strs; vs->value || vs->str; vs++) -		len += strlen(vs->str) + 1; +	for (i = 0; i < info->num_cat; i++) +		size += strlen(info->cat[i].name) + 1; -	str = talloc_zero_size(NULL, len); +	for (i = 0; i < LOGLEVEL_DEFS; i++) +		size += strlen(loglevel_strs[i].str) + 1; + +	rem = size; +	str = talloc_zero_size(NULL, size);  	if (!str)  		return NULL; -	str[0] = '('; -	for (vs = loglevel_strs; vs->value || vs->str; vs++) { -		strcat(str, vs->str); -		strcat(str, "|"); -	} -	str[strlen(str)-1] = ')'; +	ret = snprintf(str + offset, rem, "logging level ("); +	if (ret < 0) +		goto err; +	SNPRINTF_FAILURE(ret, rem, offset, len); + +	for (i = 0; i < info->num_cat; i++) { +		int j, name_len = strlen(info->cat[i].name)+1; +		char name[name_len]; +		for (j = 0; j < name_len; j++) +			name[j] = tolower(info->cat[i].name[j]); + +		name[name_len-1] = '\0'; +		ret = snprintf(str + offset, rem, "%s|", name+1); +		if (ret < 0) +			goto err; +		SNPRINTF_FAILURE(ret, rem, offset, len); +	} +	offset--;	/* to remove the trailing | */ +	rem++; + +	ret = snprintf(str + offset, rem, ") ("); +	if (ret < 0) +		goto err; +	SNPRINTF_FAILURE(ret, rem, offset, len); + +	for (i = 0; i < LOGLEVEL_DEFS; i++) { +		int j, loglevel_str_len = strlen(loglevel_strs[i].str)+1; +		char loglevel_str[loglevel_str_len]; + +		for (j = 0; j < loglevel_str_len; j++) +			loglevel_str[j] = tolower(loglevel_strs[i].str[j]); + +		loglevel_str[loglevel_str_len-1] = '\0'; +		ret = snprintf(str + offset, rem, "%s|", loglevel_str); +		if (ret < 0) +			goto err; +		SNPRINTF_FAILURE(ret, rem, offset, len); +	} +	offset--;	/* to remove the trailing | */ +	rem++; + +	ret = snprintf(str + offset, rem, ")"); +	if (ret < 0) +		goto err; +	SNPRINTF_FAILURE(ret, rem, offset, len); +err:  	return str;  } -const char *log_vty_category_string(struct log_info *info) +/* This generates the logging command description for VTY. */ +const char *log_vty_command_description(const struct log_info *info)  { -	unsigned int len = 3;	/* "()\0" */ -	unsigned int i;  	char *str; +	int i, ret, len = 0, offset = 0, rem; +	unsigned int size = +		strlen(LOGGING_STR +		       "Set the log level for a specified category\n") + 1;  	for (i = 0; i < info->num_cat; i++) -		len += strlen(info->cat[i].name) + 1; +		size += strlen(info->cat[i].description) + 1; -	str = talloc_zero_size(NULL, len); +	for (i = 0; i < LOGLEVEL_DEFS; i++) +		size += strlen(loglevel_descriptions[i]) + 1; + +	rem = size; +	str = talloc_zero_size(NULL, size);  	if (!str)  		return NULL; -	str[0] = '('; +	ret = snprintf(str + offset, rem, LOGGING_STR +			"Set the log level for a specified category\n"); +	if (ret < 0) +		goto err; +	SNPRINTF_FAILURE(ret, rem, offset, len); +  	for (i = 0; i < info->num_cat; i++) { -		strcat(str, info->cat[i].name+1); -		strcat(str, "|"); +		ret = snprintf(str + offset, rem, "%s\n", +				info->cat[i].description); +		if (ret < 0) +			goto err; +		SNPRINTF_FAILURE(ret, rem, offset, len);  	} -	str[strlen(str)-1] = ')'; - +	for (i = 0; i < LOGLEVEL_DEFS; i++) { +		ret = snprintf(str + offset, rem, "%s\n", +				loglevel_descriptions[i]); +		if (ret < 0) +			goto err; +		SNPRINTF_FAILURE(ret, rem, offset, len); +	} +err:  	return str;  } diff --git a/src/vty/logging_vty.c b/src/vty/logging_vty.c index 904f8fec..1b356c9f 100644 --- a/src/vty/logging_vty.c +++ b/src/vty/logging_vty.c @@ -149,56 +149,10 @@ DEFUN(logging_prnt_timestamp,  	return CMD_SUCCESS;  } -/* FIXME: those have to be kept in sync with the log levels and categories */ -#define VTY_DEBUG_CATEGORIES "(rll|cc|mm|rr|rsl|nm|sms|pag|mncc|inp|mi|mib|mux|meas|sccp|msc|mgcp|ho|db|ref|gprs|ns|bssgp|llc|sndcp|isup|m2ua|pcap|nat|all)" -#define CATEGORIES_HELP	\ -	"A-bis Radio Link Layer (RLL)\n"			\ -	"Layer3 Call Control (CC)\n"				\ -	"Layer3 Mobility Management (MM)\n"			\ -	"Layer3 Radio Resource (RR)\n"				\ -	"A-bis Radio Signalling Link (RSL)\n"			\ -	"A-bis Network Management / O&M (NM/OML)\n"		\ -	"Layer3 Short Messagaging Service (SMS)\n"		\ -	"Paging Subsystem\n"					\ -	"MNCC API for Call Control application\n"		\ -	"A-bis Input Subsystem\n"				\ -	"A-bis Input Driver for Signalling\n"			\ -	"A-bis Input Driver for B-Channel (voice data)\n"	\ -	"A-bis B-Channel / Sub-channel Multiplexer\n"		\ -	"Radio Measurements\n"					\ -	"SCCP\n"						\ -	"Mobile Switching Center\n"				\ -	"Media Gateway Control Protocol\n"			\ -	"Hand-over\n"						\ -	"Database Layer\n"					\ -	"Reference Counting\n"					\ -	"GPRS Core\n"						\ -	"GPRS Network Service (NS)\n"				\ -	"GPRS BSS Gateway Protocol (BSSGP)\n"			\ -	"GPRS Logical Link Control Protocol (LLC)\n"		\ -	"GPRS Sub-Network Dependent Control Protocol (SNDCP)\n"	\ -	"ISDN User Part (ISUP)\n"				\ -	"SCTP M2UA\n"						\ -	"Trace message IO\n"					\ -	"BSC NAT\n"						\ -	"Global setting for all subsytems\n" - -#define VTY_DEBUG_LEVELS "(everything|debug|info|notice|error|fatal)" -#define LEVELS_HELP	\ -	"Log simply everything\n"				\ -	"Log debug messages and higher levels\n"		\ -	"Log informational messages and higher levels\n"	\ -	"Log noticable messages and higher levels\n"		\ -	"Log error messages and higher levels\n"		\ -	"Log only fatal messages\n" -  DEFUN(logging_level,        logging_level_cmd, -      "logging level " VTY_DEBUG_CATEGORIES " " VTY_DEBUG_LEVELS, -      LOGGING_STR -      "Set the log level for a specified category\n" -      CATEGORIES_HELP -      LEVELS_HELP) +      NULL, /* cmdstr is dynamically set in logging_vty_add_cmds(). */ +      NULL) /* same thing for helpstr. */  {  	int category = log_parse_category(argv[0]);  	int level = log_parse_level(argv[1]); @@ -596,7 +550,7 @@ static int config_write_log(struct vty *vty)  	return 1;  } -void logging_vty_add_cmds() +void logging_vty_add_cmds(const struct log_info *cat)  {  	install_element_ve(&enable_logging_cmd);  	install_element_ve(&disable_logging_cmd); @@ -604,6 +558,10 @@ void logging_vty_add_cmds()  	install_element_ve(&logging_use_clr_cmd);  	install_element_ve(&logging_prnt_timestamp_cmd);  	install_element_ve(&logging_set_category_mask_cmd); + +	/* Logging level strings are generated dynamically. */ +	logging_level_cmd.string = log_vty_command_string(cat); +	logging_level_cmd.doc = log_vty_command_description(cat);  	install_element_ve(&logging_level_cmd);  	install_element_ve(&show_logging_vty_cmd); | 
