summaryrefslogtreecommitdiff
path: root/main/asterisk.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/asterisk.c')
-rw-r--r--main/asterisk.c190
1 files changed, 129 insertions, 61 deletions
diff --git a/main/asterisk.c b/main/asterisk.c
index 86667e061..e2e01a51f 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -319,6 +319,9 @@ int daemon(int, int); /* defined in libresolv of all places */
struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
struct ast_flags ast_compat = { 0 };
+/*! Maximum active system verbosity level. */
+int ast_verb_sys_level;
+
int option_verbose; /*!< Verbosity level */
int option_debug; /*!< Debug level */
double ast_option_maxload; /*!< Max load avg on system */
@@ -347,6 +350,8 @@ struct console {
int uid; /*!< Remote user ID. */
int gid; /*!< Remote group ID. */
int levels[NUMLOGLEVELS]; /*!< Which log levels are enabled for the console */
+ /*! Verbosity level of this console. */
+ int option_verbose;
};
struct ast_atexit {
@@ -609,7 +614,8 @@ static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_c
ast_cli(a->fd, " Maximum open file handles: %d\n", ast_option_maxfiles);
else
ast_cli(a->fd, " Maximum open file handles: Not set\n");
- ast_cli(a->fd, " Verbosity: %d\n", option_verbose);
+ ast_cli(a->fd, " Root console verbosity: %d\n", option_verbose);
+ ast_cli(a->fd, " Current console verbosity: %d\n", ast_verb_console_get());
ast_cli(a->fd, " Debug level: %d\n", option_debug);
ast_cli(a->fd, " Maximum load average: %lf\n", ast_option_maxload);
#if defined(HAVE_SYSINFO)
@@ -1331,29 +1337,33 @@ void ast_console_toggle_mute(int fd, int silent)
}
/*!
- * \brief log the string to all attached console clients
+ * \brief log the string to all attached network console clients
*/
static void ast_network_puts_mutable(const char *string, int level)
{
int x;
- for (x = 0;x < AST_MAX_CONNECTS; x++) {
- if (consoles[x].mute)
+
+ for (x = 0; x < AST_MAX_CONNECTS; ++x) {
+ if (consoles[x].fd < 0
+ || consoles[x].mute
+ || consoles[x].levels[level]) {
continue;
- if (consoles[x].fd > -1) {
- if (!consoles[x].levels[level])
- fdprint(consoles[x].p[1], string);
}
+ fdprint(consoles[x].p[1], string);
}
}
/*!
- * \brief log the string to the console, and all attached
- * console clients
+ * \brief log the string to the root console, and all attached
+ * network console clients
*/
void ast_console_puts_mutable(const char *string, int level)
{
+ /* Send to the root console */
fputs(string, stdout);
fflush(stdout);
+
+ /* Send to any network console clients */
ast_network_puts_mutable(string, level);
}
@@ -1363,26 +1373,45 @@ void ast_console_puts_mutable(const char *string, int level)
static void ast_network_puts(const char *string)
{
int x;
- for (x = 0; x < AST_MAX_CONNECTS; x++) {
- if (consoles[x].fd > -1)
- fdprint(consoles[x].p[1], string);
+
+ for (x = 0; x < AST_MAX_CONNECTS; ++x) {
+ if (consoles[x].fd < 0) {
+ continue;
+ }
+ fdprint(consoles[x].p[1], string);
}
}
/*!
- * \brief write the string to the console, and all attached
- * console clients
+ * \brief write the string to the root console, and all attached
+ * network console clients
*/
void ast_console_puts(const char *string)
{
+ /* Send to the root console */
fputs(string, stdout);
fflush(stdout);
+
+ /* Send to any network console clients */
ast_network_puts(string);
}
-static void network_verboser(const char *s)
+static void network_verboser(const char *string)
{
- ast_network_puts_mutable(s, __LOG_VERBOSE);
+ int x;
+ int verb_level;
+
+ /* Send to any network console clients if client verbocity allows. */
+ verb_level = VERBOSE_MAGIC2LEVEL(string);
+ for (x = 0; x < AST_MAX_CONNECTS; ++x) {
+ if (consoles[x].fd < 0
+ || consoles[x].mute
+ || consoles[x].levels[__LOG_VERBOSE]
+ || consoles[x].option_verbose < verb_level) {
+ continue;
+ }
+ fdprint(consoles[x].p[1], string);
+ }
}
static pthread_t lthread;
@@ -1446,6 +1475,7 @@ static int read_credentials(int fd, char *buffer, size_t size, struct console *c
return result;
}
+/* This is the thread running the remote console on the main process. */
static void *netconsole(void *vconsole)
{
struct console *con = vconsole;
@@ -1461,6 +1491,7 @@ static void *netconsole(void *vconsole)
ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
snprintf(outbuf, sizeof(outbuf), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ast_get_version());
fdprint(con->fd, outbuf);
+ ast_verb_console_register(&con->option_verbose);
for (;;) {
fds[0].fd = con->fd;
fds[0].events = POLLIN;
@@ -1523,6 +1554,7 @@ static void *netconsole(void *vconsole)
break;
}
}
+ ast_verb_console_unregister();
if (!ast_opt_hide_connect) {
ast_verb(3, "Remote UNIX connection disconnected\n");
}
@@ -1575,24 +1607,25 @@ static void *listener(void *unused)
}
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
- consoles[x].fd = -1;
fdprint(s, "Server failed to create pipe\n");
close(s);
break;
}
flags = fcntl(consoles[x].p[1], F_GETFL);
fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
- consoles[x].fd = s;
consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */
/* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
to know if the user didn't send the credentials. */
consoles[x].uid = -2;
consoles[x].gid = -2;
+ /* Server default of remote console verbosity level is OFF. */
+ consoles[x].option_verbose = 0;
+ consoles[x].fd = s;
if (ast_pthread_create_detached_background(&consoles[x].t, NULL, netconsole, &consoles[x])) {
+ consoles[x].fd = -1;
ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
close(consoles[x].p[0]);
close(consoles[x].p[1]);
- consoles[x].fd = -1;
fdprint(s, "Server failed to spawn thread\n");
close(s);
}
@@ -2074,12 +2107,6 @@ static int console_state_init(void *ptr)
AST_THREADSTORAGE_CUSTOM(console_state, console_state_init, ast_free_ptr);
-/* 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 int console_print(const char *s, int local)
{
struct console_state_data *state =
@@ -2174,6 +2201,7 @@ static int ast_all_zeros(char *s)
return 1;
}
+/* This is the main console CLI command handler. Run by the main() thread. */
static void consolehandler(char *s)
{
printf("%s", term_end());
@@ -2211,38 +2239,56 @@ static int remoteconsolehandler(char *s)
else
ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
ret = 1;
- } else if (strncasecmp(s, "core set verbose ", 17) == 0) {
- int old_verbose = option_verbose;
- if (strncasecmp(s + 17, "atleast ", 8) == 0) {
- int tmp;
- if (sscanf(s + 25, "%d", &tmp) != 1) {
- fprintf(stderr, "Usage: core set verbose [atleast] <level>\n");
- } else {
- if (tmp > option_verbose) {
- option_verbose = tmp;
- }
- if (old_verbose != option_verbose) {
- fprintf(stdout, "Set remote console verbosity from %d to %d\n", old_verbose, option_verbose);
- } else {
- fprintf(stdout, "Verbosity level unchanged.\n");
- }
+ } else if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
+ (s[4] == '\0' || isspace(s[4]))) {
+ quit_handler(0, SHUTDOWN_FAST, 0);
+ ret = 1;
+ } else if (s[0]) {
+ char *shrunk = ast_strdupa(s);
+ char *cur;
+ char *prev;
+
+ /*
+ * Remove duplicate spaces from shrunk for matching purposes.
+ *
+ * shrunk has at least one character in it to start with or we
+ * couldn't get here.
+ */
+ for (prev = shrunk, cur = shrunk + 1; *cur; ++cur) {
+ if (*prev == ' ' && *cur == ' ') {
+ /* Skip repeated space delimiter. */
+ continue;
}
- } else {
- if (sscanf(s + 17, "%d", &option_verbose) != 1) {
- fprintf(stderr, "Usage: core set verbose [atleast] <level>\n");
+ *++prev = *cur;
+ }
+ *++prev = '\0';
+
+ if (strncasecmp(shrunk, "core set verbose ", 17) == 0) {
+ /*
+ * We need to still set the rasterisk option_verbose in case we are
+ * talking to an earlier version which doesn't prefilter verbose
+ * levels. This is really a compromise as we should always take
+ * whatever the server sends.
+ */
+
+ if (!strncasecmp(shrunk + 17, "off", 3)) {
+ ast_verb_console_set(0);
} else {
- if (old_verbose != option_verbose) {
- fprintf(stdout, "Set remote console verbosity to %d\n", option_verbose);
- } else {
- fprintf(stdout, "Verbosity level unchanged.\n");
+ int verbose_new;
+ int atleast;
+
+ atleast = 8;
+ if (strncasecmp(shrunk + 17, "atleast ", atleast)) {
+ atleast = 0;
+ }
+
+ if (sscanf(shrunk + 17 + atleast, "%30d", &verbose_new) == 1) {
+ if (!atleast || ast_verb_console_get() < verbose_new) {
+ ast_verb_console_set(verbose_new);
+ }
}
}
}
- ret = 1;
- } else if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
- (s[4] == '\0' || isspace(s[4]))) {
- quit_handler(0, SHUTDOWN_FAST, 0);
- ret = 1;
}
return ret;
@@ -2564,6 +2610,31 @@ static struct ast_cli_entry cli_asterisk[] = {
#endif /* ! LOW_MEMORY */
};
+static void send_rasterisk_connect_commands(void)
+{
+ char buf[80];
+
+ /*
+ * Tell the server asterisk instance about the verbose level
+ * initially desired.
+ */
+ if (option_verbose) {
+ snprintf(buf, sizeof(buf), "core set verbose atleast %d silent", option_verbose);
+ fdsend(ast_consock, buf);
+ }
+
+ if (option_debug) {
+ snprintf(buf, sizeof(buf), "core set debug atleast %d", option_debug);
+ fdsend(ast_consock, buf);
+ }
+
+ if (!ast_opt_mute) {
+ fdsend(ast_consock, "logger mute silent");
+ } else {
+ printf("log and verbose output currently muted ('logger mute' to unmute)\n");
+ }
+}
+
static int ast_el_read_char(EditLine *editline, char *cp)
{
int num_read = 0;
@@ -2617,10 +2688,7 @@ static int ast_el_read_char(EditLine *editline, char *cp)
fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
printf("%s", term_quit());
WELCOME_MESSAGE;
- if (!ast_opt_mute)
- fdsend(ast_consock, "logger mute silent");
- else
- printf("log and verbose output currently muted ('logger mute' to unmute)\n");
+ send_rasterisk_connect_commands();
break;
} else
usleep(1000000 / reconnects_per_second);
@@ -3171,11 +3239,7 @@ static void ast_remotecontrol(char *data)
else
pid = -1;
if (!data) {
- if (!ast_opt_mute) {
- fdsend(ast_consock, "logger mute silent");
- } else {
- printf("log and verbose output currently muted ('logger mute' to unmute)\n");
- }
+ send_rasterisk_connect_commands();
}
if (ast_opt_exec && data) { /* hack to print output then exit if asterisk -rx is used */
@@ -3652,6 +3716,7 @@ static void canary_exit(void)
kill(canary_pid, SIGKILL);
}
+/* Execute CLI commands on startup. Run by main() thread. */
static void run_startup_commands(void)
{
int fd;
@@ -4082,6 +4147,9 @@ int main(int argc, char *argv[])
}
}
+ /* Initial value of the maximum active system verbosity level. */
+ ast_verb_sys_level = option_verbose;
+
if (ast_tryconnect()) {
/* One is already running */
if (ast_opt_remote) {