diff options
author | Tilghman Lesher <tilghman@meg.abyt.es> | 2011-11-29 18:43:16 +0000 |
---|---|---|
committer | Tilghman Lesher <tilghman@meg.abyt.es> | 2011-11-29 18:43:16 +0000 |
commit | 77b670c4ab62db2fa2386e15aa6ae4860bb401c9 (patch) | |
tree | fba9c5d22c4c3dea695dac6c51a49316f6381b4d /main | |
parent | d7dec4f14fc018d18ed480358f9a265b81b230b9 (diff) |
Allow each logging destination and console to have its own notion of the verbosity level.
Review: https://reviewboard.asterisk.org/r/1599
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@346391 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r-- | main/asterisk.c | 147 | ||||
-rw-r--r-- | main/bridging.c | 8 | ||||
-rw-r--r-- | main/cli.c | 16 | ||||
-rw-r--r-- | main/dial.c | 3 | ||||
-rw-r--r-- | main/logger.c | 83 | ||||
-rw-r--r-- | main/say.c | 10 |
6 files changed, 184 insertions, 83 deletions
diff --git a/main/asterisk.c b/main/asterisk.c index 16f3efa0e..acddc96d9 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -1749,11 +1749,6 @@ static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp { const char *c; - /* Check for verboser preamble */ - if (*s == 127) { - s++; - } - if (!strncmp(s, cmp, strlen(cmp))) { c = s + strlen(cmp); term_color(outbuf, cmp, COLOR_GRAY, 0, maxout); @@ -1762,10 +1757,25 @@ static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp return NULL; } +/* These gymnastics are due to platforms which designate char as unsigned by + * default. Level is the negative character -- offset by 1, because \0 is the + * EOS delimiter. */ +#define VERBOSE_MAGIC2LEVEL(x) (((char) -*(signed char *) (x)) - 1) +#define VERBOSE_HASMAGIC(x) (*(signed char *) (x) < 0) + static void console_verboser(const char *s) { char tmp[80]; const char *c = NULL; + char level = 0; + + if (VERBOSE_HASMAGIC(s)) { + level = VERBOSE_MAGIC2LEVEL(s); + s++; + if (level > option_verbose) { + return; + } + } if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) || (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) || @@ -1774,17 +1784,15 @@ static void console_verboser(const char *s) fputs(tmp, stdout); fputs(c, stdout); } else { - if (*s == 127) { - s++; - } fputs(s, stdout); } fflush(stdout); - + /* Wake up a poll()ing console */ - if (ast_opt_console && consolethread != AST_PTHREADT_NULL) + if (ast_opt_console && consolethread != AST_PTHREADT_NULL) { pthread_kill(consolethread, SIGURG); + } } static int ast_all_zeros(char *s) @@ -1829,8 +1837,26 @@ static int remoteconsolehandler(char *s) else ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh"); ret = 1; - } - if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) && + } else if (strncasecmp(s, "remote set verbose ", 19) == 0) { + if (strncasecmp(s + 19, "atleast ", 8) == 0) { + int tmp; + if (sscanf(s + 27, "%d", &tmp) != 1) { + fprintf(stderr, "Usage: remote set verbose [atleast] <level>\n"); + } else { + if (tmp > option_verbose) { + option_verbose = tmp; + } + fprintf(stdout, "Set remote console verbosity to %d\n", option_verbose); + } + } else { + if (sscanf(s + 19, "%d", &option_verbose) != 1) { + fprintf(stderr, "Usage: remote set verbose [atleast] <level>\n"); + } else { + fprintf(stdout, "Set remote console verbosity to %d\n", option_verbose); + } + } + ret = 1; + } else if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) && (s[4] == '\0' || isspace(s[4]))) { quit_handler(0, 0, 0, 0); ret = 1; @@ -2133,6 +2159,23 @@ static struct ast_cli_entry cli_asterisk[] = { #endif /* ! LOW_MEMORY */ }; +struct el_read_char_state_struct { + unsigned int line_full:1; + unsigned int prev_line_full:1; + char prev_line_verbosity; +}; + +static int el_read_char_state_init(void *ptr) +{ + struct el_read_char_state_struct *state = ptr; + state->line_full = 1; + state->prev_line_full = 1; + state->prev_line_verbosity = 0; + return 0; +} + +AST_THREADSTORAGE_CUSTOM(el_read_char_state, el_read_char_state_init, ast_free_ptr); + static int ast_el_read_char(EditLine *editline, char *cp) { int num_read = 0; @@ -2142,6 +2185,7 @@ static int ast_el_read_char(EditLine *editline, char *cp) int max; #define EL_BUF_SIZE 512 char buf[EL_BUF_SIZE]; + struct el_read_char_state_struct *state = ast_threadstorage_get(&el_read_char_state, sizeof(*state)); for (;;) { max = 1; @@ -2166,11 +2210,13 @@ static int ast_el_read_char(EditLine *editline, char *cp) num_read = read(STDIN_FILENO, cp, 1); if (num_read < 1) { break; - } else + } else { return (num_read); + } } if (fds[0].revents) { - char *tmp; + char level = 0; + char *curline = buf, *nextline; res = read(ast_consock, buf, sizeof(buf) - 1); /* if the remote side disappears exit */ if (res < 1) { @@ -2203,22 +2249,35 @@ static int ast_el_read_char(EditLine *editline, char *cp) buf[res] = '\0'; - /* Strip preamble from asynchronous events, too */ - for (tmp = buf; *tmp; tmp++) { - if (*tmp == 127) { - memmove(tmp, tmp + 1, strlen(tmp)); - tmp--; - res--; - } - } - /* Write over the CLI prompt */ if (!ast_opt_exec && !lastpos) { if (write(STDOUT_FILENO, "\r[0K", 5) < 0) { } } - if (write(STDOUT_FILENO, buf, res) < 0) { - } + + do { + state->prev_line_full = state->line_full; + if ((nextline = strchr(curline, '\n'))) { + state->line_full = 1; + nextline++; + } else { + state->line_full = 0; + nextline = strchr(curline, '\0'); + } + + if (state->prev_line_full && VERBOSE_HASMAGIC(curline)) { + level = VERBOSE_MAGIC2LEVEL(curline); + curline++; + } + if ((!state->prev_line_full && state->prev_line_verbosity <= option_verbose) || (state->prev_line_full && level <= option_verbose)) { + if (write(STDOUT_FILENO, curline, nextline - curline) < 0) { + } + } + + state->prev_line_verbosity = level; + curline = nextline; + } while (!ast_strlen_zero(curline)); + if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (buf[res-2] == '\n'))) { *cp = CC_REFRESH; return(1); @@ -2729,22 +2788,20 @@ static void ast_remotecontrol(char *data) else pid = -1; if (!data) { - char tmp[80]; - snprintf(tmp, sizeof(tmp), "core set verbose atleast %d", option_verbose); - fdsend(ast_consock, tmp); - snprintf(tmp, sizeof(tmp), "core set debug atleast %d", option_debug); - fdsend(ast_consock, tmp); - if (!ast_opt_mute) + if (!ast_opt_mute) { fdsend(ast_consock, "logger mute silent"); - else + } else { printf("log and verbose output currently muted ('logger mute' to unmute)\n"); + } } if (ast_opt_exec && data) { /* hack to print output then exit if asterisk -rx is used */ + int linefull = 1, prev_linefull = 1, prev_line_verbose = 0; struct pollfd fds; fds.fd = ast_consock; fds.events = POLLIN; fds.revents = 0; + while (ast_poll(&fds, 1, 60000) > 0) { char buffer[512] = "", *curline = buffer, *nextline; int not_written = 1; @@ -2758,18 +2815,34 @@ static void ast_remotecontrol(char *data) } do { + prev_linefull = linefull; if ((nextline = strchr(curline, '\n'))) { + linefull = 1; nextline++; } else { + linefull = 0; nextline = strchr(curline, '\0'); } /* Skip verbose lines */ - if (*curline != 127) { + /* Prev line full? | Line is verbose | Last line verbose? | Print + * TRUE | TRUE* | TRUE | FALSE + * TRUE | TRUE* | FALSE | FALSE + * TRUE | FALSE* | TRUE | TRUE + * TRUE | FALSE* | FALSE | TRUE + * FALSE | TRUE | TRUE* | FALSE + * FALSE | TRUE | FALSE* | TRUE + * FALSE | FALSE | TRUE* | FALSE + * FALSE | FALSE | FALSE* | TRUE + */ + if ((!prev_linefull && !prev_line_verbose) || (prev_linefull && *curline > 0)) { + prev_line_verbose = 0; not_written = 0; if (write(STDOUT_FILENO, curline, nextline - curline) < 0) { ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); } + } else { + prev_line_verbose = 1; } curline = nextline; } while (!ast_strlen_zero(curline)); @@ -2808,14 +2881,6 @@ static void ast_remotecontrol(char *data) if (ebuf[strlen(ebuf)-1] == '\n') ebuf[strlen(ebuf)-1] = '\0'; if (!remoteconsolehandler(ebuf)) { - /* Strip preamble from output */ - char *temp; - for (temp = ebuf; *temp; temp++) { - if (*temp == 127) { - memmove(temp, temp + 1, strlen(temp)); - temp--; - } - } res = write(ast_consock, ebuf, strlen(ebuf) + 1); if (res < 1) { ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno)); diff --git a/main/bridging.c b/main/bridging.c index 503e86509..5ae861785 100644 --- a/main/bridging.c +++ b/main/bridging.c @@ -87,9 +87,7 @@ int __ast_bridge_technology_register(struct ast_bridge_technology *technology, s AST_RWLIST_UNLOCK(&bridge_technologies); - if (option_verbose > 1) { - ast_verbose(VERBOSE_PREFIX_2 "Registered bridge technology %s\n", technology->name); - } + ast_verb(2, "Registered bridge technology %s\n", technology->name); return 0; } @@ -104,9 +102,7 @@ int ast_bridge_technology_unregister(struct ast_bridge_technology *technology) AST_RWLIST_TRAVERSE_SAFE_BEGIN(&bridge_technologies, current, entry) { if (current == technology) { AST_RWLIST_REMOVE_CURRENT(entry); - if (option_verbose > 1) { - ast_verbose(VERBOSE_PREFIX_2 "Unregistered bridge technology %s\n", technology->name); - } + ast_verb(2, "Unregistered bridge technology %s\n", technology->name); break; } } diff --git a/main/cli.c b/main/cli.c index c35b941d1..9c66b6767 100644 --- a/main/cli.c +++ b/main/cli.c @@ -382,6 +382,20 @@ static char *complete_number(const char *partial, unsigned int min, unsigned int return NULL; } +static char *handle_localverbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) +{ + switch (cmd) { + case CLI_INIT: + e->command = "remote set verbose"; + e->usage = "Usage: remote set verbose <level>\n"; + return NULL; + case CLI_GENERATE: + return NULL; + } + ast_cli(a->fd, "This is the main console. Use 'core set verbose' instead.\n"); + return CLI_FAILURE; +} + static char *handle_verbose(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { int oldval; @@ -1668,6 +1682,8 @@ static struct ast_cli_entry cli_cli[] = { AST_CLI_DEFINE(handle_showchan, "Display information on a specific channel"), + AST_CLI_DEFINE(handle_localverbose, "Set level of remote console verbosity"), + AST_CLI_DEFINE(handle_core_set_debug_channel, "Enable/disable debugging on a channel"), AST_CLI_DEFINE(handle_verbose, "Set level of debug/verbose chattiness"), diff --git a/main/dial.c b/main/dial.c index 6faf8f5d5..420ce1995 100644 --- a/main/dial.c +++ b/main/dial.c @@ -432,8 +432,7 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel ast_indicate(chan, AST_CONTROL_VIDUPDATE); break; case AST_CONTROL_SRCUPDATE: - if (option_verbose > 2) - ast_verbose (VERBOSE_PREFIX_3 "%s requested a source update, passing it to %s\n", channel->owner->name, chan->name); + ast_verb(3, "%s requested a source update, passing it to %s\n", channel->owner->name, chan->name); ast_indicate(chan, AST_CONTROL_SRCUPDATE); break; case AST_CONTROL_CONNECTED_LINE: diff --git a/main/logger.c b/main/logger.c index 6fc36df00..74b7dd190 100644 --- a/main/logger.c +++ b/main/logger.c @@ -101,6 +101,8 @@ struct logchannel { int disabled; /*! syslog facility */ int facility; + /*! Verbosity level */ + int verbosity; /*! Type of log channel */ enum logtypes type; /*! logfile logging file pointer */ @@ -209,19 +211,24 @@ AST_THREADSTORAGE(log_buf); static void logger_queue_init(void); -static unsigned int make_components(const char *s, int lineno) +static unsigned int make_components(const char *s, int lineno, int *verbosity) { char *w; unsigned int res = 0; char *stringp = ast_strdupa(s); unsigned int x; + *verbosity = 3; + while ((w = strsep(&stringp, ","))) { w = ast_skip_blanks(w); if (!strcmp(w, "*")) { res = 0xFFFFFFFF; break; + } else if (!strncasecmp(w, "verbose(", 8) && sscanf(w + 8, "%d)", verbosity) == 1) { + res |= (1 << __LOG_VERBOSE); + break; } else for (x = 0; x < ARRAY_LEN(levels); x++) { if (levels[x] && !strcasecmp(w, levels[x])) { res |= (1 << x); @@ -300,7 +307,7 @@ static struct logchannel *make_logchannel(const char *channel, const char *compo } chan->type = LOGTYPE_FILE; } - chan->logmask = make_components(chan->components, lineno); + chan->logmask = make_components(chan->components, lineno, &chan->verbosity); return chan; } @@ -434,11 +441,6 @@ void ast_child_verbose(int level, const char *fmt, ...) va_list ap, aq; int size; - /* Don't bother, if the level isn't that high */ - if (option_verbose < level) { - return; - } - va_start(ap, fmt); va_copy(aq, ap); if ((size = vsnprintf(msg, 0, fmt, ap)) < 0) { @@ -968,15 +970,23 @@ static void ast_log_vsyslog(struct logmsg *msg) syslog(syslog_level, "%s", buf); } +/* These gymnastics are due to platforms which designate char as unsigned by + * default. Level is the negative character -- offset by 1, because \0 is the + * EOS delimiter. */ +#define VERBOSE_MAGIC2LEVEL(x) (((char) -*(signed char *) (x)) - 1) +#define VERBOSE_HASMAGIC(x) (*(signed char *) (x) < 0) + /*! \brief Print a normal log message to the channels */ static void logger_print_normal(struct logmsg *logmsg) { struct logchannel *chan = NULL; char buf[BUFSIZ]; struct verb *v = NULL; + int level = 0; if (logmsg->level == __LOG_VERBOSE) { char *tmpmsg = ast_strdupa(logmsg->message + 1); + level = VERBOSE_MAGIC2LEVEL(logmsg->message); /* Iterate through the list of verbosers and pass them the log message string */ AST_RWLIST_RDLOCK(&verbosers); AST_RWLIST_TRAVERSE(&verbosers, v, list) @@ -990,8 +1000,13 @@ static void logger_print_normal(struct logmsg *logmsg) if (!AST_RWLIST_EMPTY(&logchannels)) { AST_RWLIST_TRAVERSE(&logchannels, chan, list) { /* If the channel is disabled, then move on to the next one */ - if (chan->disabled) + if (chan->disabled) { + continue; + } + if (logmsg->level == __LOG_VERBOSE && level > chan->verbosity) { continue; + } + /* Check syslog channels */ if (chan->type == LOGTYPE_SYSLOG && (chan->logmask & (1 << logmsg->level))) { ast_log_vsyslog(logmsg); @@ -1219,20 +1234,11 @@ void ast_log(int level, const char *file, int line, const char *function, const } return; } - - /* don't display LOG_DEBUG messages unless option_verbose _or_ option_debug - are non-zero; LOG_DEBUG messages can still be displayed if option_debug - is zero, if option_verbose is non-zero (this allows for 'level zero' - LOG_DEBUG messages to be displayed, if the logmask on any channel - allows it) - */ - if (!option_verbose && !option_debug && (level == __LOG_DEBUG)) - return; /* Ignore anything that never gets logged anywhere */ if (level != __LOG_VERBOSE && !(global_logmask & (1 << level))) return; - + /* Build string */ va_start(ap, fmt); res = ast_str_set_va(&buf, BUFSIZ, fmt, ap); @@ -1492,13 +1498,31 @@ void ast_backtrace(void) #endif /* defined(HAVE_BKTR) */ } -void __ast_verbose_ap(const char *file, int line, const char *func, const char *fmt, va_list ap) +void __ast_verbose_ap(const char *file, int line, const char *func, int level, const char *fmt, va_list ap) { struct ast_str *buf = NULL; int res = 0; + const char *prefix = level >= 4 ? VERBOSE_PREFIX_4 : level == 3 ? VERBOSE_PREFIX_3 : level == 2 ? VERBOSE_PREFIX_2 : level == 1 ? VERBOSE_PREFIX_1 : ""; + signed char magic = level > 127 ? -128 : -level - 1; /* 0 => -1, 1 => -2, etc. Can't pass NUL, as it is EOS-delimiter */ + + /* For compatibility with modules still calling ast_verbose() directly instead of using ast_verb() */ + if (level < 0) { + if (!strncmp(fmt, VERBOSE_PREFIX_4, strlen(VERBOSE_PREFIX_4))) { + magic = -5; + } else if (!strncmp(fmt, VERBOSE_PREFIX_3, strlen(VERBOSE_PREFIX_3))) { + magic = -4; + } else if (!strncmp(fmt, VERBOSE_PREFIX_2, strlen(VERBOSE_PREFIX_2))) { + magic = -3; + } else if (!strncmp(fmt, VERBOSE_PREFIX_1, strlen(VERBOSE_PREFIX_1))) { + magic = -2; + } else { + magic = -1; + } + } - if (!(buf = ast_str_thread_get(&verbose_buf, VERBOSE_BUF_INIT_SIZE))) + if (!(buf = ast_str_thread_get(&verbose_buf, VERBOSE_BUF_INIT_SIZE))) { return; + } if (ast_opt_timestamp) { struct timeval now; @@ -1509,12 +1533,12 @@ void __ast_verbose_ap(const char *file, int line, const char *func, const char * now = ast_tvnow(); ast_localtime(&now, &tm, NULL); ast_strftime(date, sizeof(date), dateformat, &tm); - datefmt = alloca(strlen(date) + 3 + strlen(fmt) + 1); - sprintf(datefmt, "%c[%s] %s", 127, date, fmt); + datefmt = alloca(strlen(date) + 3 + strlen(prefix) + strlen(fmt) + 1); + sprintf(datefmt, "%c[%s] %s%s", (char) magic, date, prefix, fmt); fmt = datefmt; } else { - char *tmp = alloca(strlen(fmt) + 2); - sprintf(tmp, "%c%s", 127, fmt); + char *tmp = alloca(strlen(prefix) + strlen(fmt) + 2); + sprintf(tmp, "%c%s%s", (char) magic, prefix, fmt); fmt = tmp; } @@ -1522,18 +1546,19 @@ void __ast_verbose_ap(const char *file, int line, const char *func, const char * res = ast_str_set_va(&buf, 0, fmt, ap); /* If the build failed then we can drop this allocated message */ - if (res == AST_DYNSTR_BUILD_FAILED) + if (res == AST_DYNSTR_BUILD_FAILED) { return; + } ast_log(__LOG_VERBOSE, file, line, func, "%s", ast_str_buffer(buf)); } -void __ast_verbose(const char *file, int line, const char *func, const char *fmt, ...) +void __ast_verbose(const char *file, int line, const char *func, int level, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - __ast_verbose_ap(file, line, func, fmt, ap); + __ast_verbose_ap(file, line, func, level, fmt, ap); va_end(ap); } @@ -1545,7 +1570,7 @@ void ast_verbose(const char *fmt, ...) va_list ap; va_start(ap, fmt); - __ast_verbose_ap("", 0, "", fmt, ap); + __ast_verbose_ap("", 0, "", 0, fmt, ap); va_end(ap); } @@ -1592,7 +1617,7 @@ static void update_logchannels(void) global_logmask = 0; AST_RWLIST_TRAVERSE(&logchannels, cur, list) { - cur->logmask = make_components(cur->components, cur->lineno); + cur->logmask = make_components(cur->components, cur->lineno, &cur->verbosity); global_logmask |= cur->logmask; } diff --git a/main/say.c b/main/say.c index e242b655d..4c04b7957 100644 --- a/main/say.c +++ b/main/say.c @@ -1233,7 +1233,7 @@ static int ast_say_number_full_he(struct ast_channel *chan, int num, const char char fn[SAY_NUM_BUF_SIZE] = ""; - ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: started. num: %d, options=\"%s\"\n", num, options); + ast_verb(3, "ast_say_digits_full: started. num: %d, options=\"%s\"\n", num, options); if (!num) { return ast_say_digits_full(chan, 0, ints, language, audiofd, ctrlfd); @@ -1241,7 +1241,7 @@ static int ast_say_number_full_he(struct ast_channel *chan, int num, const char if (options && !strncasecmp(options, "m", 1)) { mf = 1; } - ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: num: %d, state=%d, options=\"%s\", mf=%d\n", num, state, options, mf); + ast_verb(3, "ast_say_digits_full: num: %d, state=%d, options=\"%s\", mf=%d\n", num, state, options, mf); /* Do we have work to do? */ while (!res && (num || (state > 0))) { @@ -1252,7 +1252,7 @@ static int ast_say_number_full_he(struct ast_channel *chan, int num, const char * state==0 is the normal mode and it means that we continue * to check if the number num has yet anything left. */ - ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: num: %d, state=%d, options=\"%s\", mf=%d, tmpnum=%d\n", num, state, options, mf, tmpnum); + ast_verb(3, "ast_say_digits_full: num: %d, state=%d, options=\"%s\", mf=%d, tmpnum=%d\n", num, state, options, mf, tmpnum); if (state == 1) { state = 0; @@ -3200,13 +3200,13 @@ static int ast_say_enumeration_full_he(struct ast_channel *chan, int num, const int res = 0; char fn[256] = ""; int mf = -1; /* +1 = Masculin; -1 = Feminin */ - ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: started. num: %d, options=\"%s\"\n", num, options); + ast_verb(3, "ast_say_digits_full: started. num: %d, options=\"%s\"\n", num, options); if (options && !strncasecmp(options, "m", 1)) { mf = -1; } - ast_verbose(VERBOSE_PREFIX_3 "ast_say_digits_full: num: %d, options=\"%s\", mf=%d\n", num, options, mf); + ast_verb(3, "ast_say_digits_full: num: %d, options=\"%s\", mf=%d\n", num, options, mf); while (!res && num) { if (num < 0) { |