Newer
Older
}
ast_verb(1, "Setting %s thread priority on all threads\n", policy_str);
AST_RWLIST_RDLOCK(&thread_list);
AST_RWLIST_TRAVERSE(&thread_list, cur, list) {
/* Don't care about the return value. It should work. */
sched_setscheduler(cur->lwp, policy, &sched);
}
AST_RWLIST_UNLOCK(&thread_list);
return 0;
#endif
}
/*! \brief We set ourselves to a high priority, that we might pre-empt
* everything else. If your PBX has heavy activity on it, this is a
* good thing.
*/
Kevin P. Fleming
committed
int ast_set_priority(int pri)
sched.sched_priority = 10;
if (sched_setscheduler(0, SCHED_RR, &sched)) {
ast_log(LOG_WARNING, "Unable to set high priority\n");
return -1;
ast_verb(1, "Set to realtime thread\n");
/* According to the manpage, these parameters can never fail. */
sched_setscheduler(0, SCHED_OTHER, &sched);
#else
if (pri) {
if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
ast_log(LOG_WARNING, "Unable to set high priority\n");
return -1;
} else
/* According to the manpage, these parameters can never fail. */
setpriority(PRIO_PROCESS, 0, 0);
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
int ast_shutdown_final(void)
{
return shuttingdown == SHUTTING_DOWN_FINAL;
}
int ast_shutting_down(void)
{
return shutdown_pending;
}
int ast_cancel_shutdown(void)
{
int shutdown_aborted = 0;
ast_mutex_lock(&safe_system_lock);
if (shuttingdown >= SHUTDOWN_FAST) {
shuttingdown = NOT_SHUTTING_DOWN;
shutdown_pending = 0;
shutdown_aborted = 1;
}
ast_mutex_unlock(&safe_system_lock);
return shutdown_aborted;
}
/*!
* \internal
* \brief Initiate system shutdown -- prevents new channels from being allocated.
*/
static void ast_begin_shutdown(void)
{
ast_mutex_lock(&safe_system_lock);
if (shuttingdown != NOT_SHUTTING_DOWN) {
shutdown_pending = 1;
}
ast_mutex_unlock(&safe_system_lock);
}
static int can_safely_quit(shutdown_nice_t niceness, int restart);
static void really_quit(int num, shutdown_nice_t niceness, int restart);
static void quit_handler(int num, shutdown_nice_t niceness, int restart)
if (can_safely_quit(niceness, restart)) {
really_quit(num, niceness, restart);
/* No one gets here. */
}
/* It wasn't our time. */
}
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
#define SHUTDOWN_TIMEOUT 15 /* Seconds */
/*!
* \internal
* \brief Wait for all channels to die, a timeout, or shutdown cancelled.
* \since 13.3.0
*
* \param niceness Shutdown niceness in effect
* \param seconds Number of seconds to wait or less than zero if indefinitely.
*
* \retval zero if waiting wasn't necessary. We were idle.
* \retval non-zero if we had to wait.
*/
static int wait_for_channels_to_die(shutdown_nice_t niceness, int seconds)
{
time_t start;
time_t now;
int waited = 0;
time(&start);
for (;;) {
if (!ast_undestroyed_channels() || shuttingdown != niceness) {
break;
}
if (seconds < 0) {
/* No timeout so just poll every second */
sleep(1);
} else {
time(&now);
/* Wait up to the given seconds for all channels to go away */
if (seconds < (now - start)) {
break;
}
/* Sleep 1/10 of a second */
usleep(100000);
}
waited = 1;
}
return waited;
}
static int can_safely_quit(shutdown_nice_t niceness, int restart)
{
int waited = 0;
/* Check if someone else isn't already doing this. */
ast_mutex_lock(&safe_system_lock);
if (shuttingdown != NOT_SHUTTING_DOWN && niceness >= shuttingdown) {
/* Already in progress and other request was less nice. */
ast_mutex_unlock(&safe_system_lock);
ast_verbose("Ignoring asterisk %s request, already in progress.\n", restart ? "restart" : "shutdown");
return 0;
}
shuttingdown = niceness;
ast_mutex_unlock(&safe_system_lock);
/* Try to get as many CDRs as possible submitted to the backend engines
* (if in batch mode). really_quit happens to call it again when running
* the atexit handlers, otherwise this would be a bit early. */
ast_cdr_engine_term();
/*
* Shutdown the message queue for the technology agnostic message channel.
* This has to occur before we pause shutdown pending ast_undestroyed_channels.
*
* XXX This is not reversed on shutdown cancel.
*/
ast_msg_shutdown();
if (niceness == SHUTDOWN_NORMAL) {
/* Begin shutdown routine, hanging up active channels */
ast_begin_shutdown();
if (ast_opt_console) {
ast_verb(0, "Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
ast_softhangup_all();
waited |= wait_for_channels_to_die(niceness, SHUTDOWN_TIMEOUT);
} else if (niceness >= SHUTDOWN_NICE) {
if (niceness != SHUTDOWN_REALLY_NICE) {
ast_begin_shutdown();
ast_verb(0, "Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
waited |= wait_for_channels_to_die(niceness, -1);
/* Re-acquire lock and check if someone changed the niceness, in which
* case someone else has taken over the shutdown.
*/
ast_mutex_lock(&safe_system_lock);
if (shuttingdown != niceness) {
if (shuttingdown == NOT_SHUTTING_DOWN && ast_opt_console) {
ast_verb(0, "Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
ast_mutex_unlock(&safe_system_lock);
return 0;
}
if (niceness >= SHUTDOWN_REALLY_NICE) {
shuttingdown = SHUTTING_DOWN;
ast_mutex_unlock(&safe_system_lock);
/* No more Mr. Nice guy. We are committed to shutting down now. */
ast_begin_shutdown();
ast_softhangup_all();
waited |= wait_for_channels_to_die(SHUTTING_DOWN, SHUTDOWN_TIMEOUT);
ast_mutex_lock(&safe_system_lock);
}
shuttingdown = SHUTTING_DOWN_FINAL;
ast_mutex_unlock(&safe_system_lock);
if (niceness >= SHUTDOWN_NORMAL && waited) {
/*
* We were not idle. Give things in progress a chance to
* recognize the final shutdown phase.
*/
sleep(1);
}
return 1;
}
/*! Called when exiting is certain. */
static void really_quit(int num, shutdown_nice_t niceness, int restart)
{
int run_cleanups = niceness >= SHUTDOWN_NICE;
if (run_cleanups && modules_shutdown()) {
ast_verb(0, "Some modules could not be unloaded, switching to fast shutdown\n");
run_cleanups = 0;
if (!restart) {
ast_sd_notify("STOPPING=1");
}
if (ast_opt_console || (ast_opt_remote && !ast_opt_exec)) {
ast_el_write_default_histfile();
if (consolethread == AST_PTHREADT_NULL || consolethread == pthread_self()) {
/* Only end if we are the consolethread, otherwise there's a race with that thread. */
if (el != NULL) {
el_end(el);
}
if (el_hist != NULL) {
history_end(el_hist);
}
} else if (mon_sig_flags == pthread_self()) {
if (consolethread != AST_PTHREADT_NULL) {
pthread_kill(consolethread, SIGURG);
}
/* Don't publish messages if we're a remote console - we won't have all of the Stasis
* topics or message types
*/
if (!ast_opt_remote) {
json_object = ast_json_pack("{s: s, s: s}",
"Shutdown", active_channels ? "Uncleanly" : "Cleanly",
"Restart", restart ? "True" : "False");
ast_manager_publish_event("Shutdown", EVENT_FLAG_SYSTEM, json_object);
ast_verb(0, "Asterisk %s ending (%d).\n",
active_channels ? "uncleanly" : "cleanly", num);
ast_verb(0, "Executing last minute cleanups\n");
ast_run_atexits(run_cleanups);
ast_debug(1, "Asterisk ending (%d).\n", num);
Kevin P. Fleming
committed
unlink(ast_config_AST_SOCKET);
pthread_kill(lthread, SIGURG);
pthread_join(lthread, NULL);
Russell Bryant
committed
if (!ast_opt_remote)
unlink(ast_config_AST_PID);
if (sig_alert_pipe[0])
close(sig_alert_pipe[0]);
if (sig_alert_pipe[1])
close(sig_alert_pipe[1]);
printf("%s", term_quit());
int i;
ast_verb(0, "Preparing for Asterisk restart...\n");
for (i = 3; i < 32768; i++) {
fcntl(i, F_SETFD, FD_CLOEXEC);
ast_verb(0, "Asterisk is now restarting...\n");
restartnow = 1;
/* close logger */
close_logger();
/* If there is a consolethread running send it a SIGHUP
so it can execvp, otherwise we can do it ourselves */
if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
pthread_kill(consolethread, SIGHUP);
/* Give the signal handler some time to complete */
sleep(2);
} else
execvp(_argv[0], _argv);
} else {
/* close logger */
close_logger();
}
exit(0);
}
static void __quit_handler(int num)
{
int a = 0;
sig_flags.need_quit = 1;
Kevin P. Fleming
committed
if (sig_alert_pipe[1] != -1) {
if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
fprintf(stderr, "quit_handler: write() failed: %s\n", strerror(errno));
Kevin P. Fleming
committed
}
}
/* There is no need to restore the signal handler here, since the app
* is going to exit */
static void __remote_quit_handler(int num)
{
sig_flags.need_quit = 1;
}
static void set_header(char *outbuf, int maxout, char level)
char date[40];
case 0: cmp = NULL;
break;
case 1: cmp = VERBOSE_PREFIX_1;
break;
case 2: cmp = VERBOSE_PREFIX_2;
break;
case 3: cmp = VERBOSE_PREFIX_3;
break;
default: cmp = VERBOSE_PREFIX_4;
break;
}
if (ast_opt_timestamp) {
struct ast_tm tm;
struct timeval now = ast_tvnow();
ast_localtime(&now, &tm, NULL);
ast_strftime(date, sizeof(date), ast_logger_get_dateformat(), &tm);
snprintf(outbuf, maxout, "%s%s%s%s%s%s",
ast_opt_timestamp ? "[" : "",
ast_opt_timestamp ? date : "",
ast_opt_timestamp ? "] " : "",
cmp ? ast_term_color(COLOR_GRAY, 0) : "",
cmp ? cmp : "",
cmp ? ast_term_reset() : "");
struct console_state_data {
char verbose_line_level;
};
static int console_state_init(void *ptr)
{
struct console_state_data *state = ptr;
state->verbose_line_level = 0;
return 0;
}
AST_THREADSTORAGE_CUSTOM(console_state, console_state_init, ast_free_ptr);
static int console_print(const char *s, int local)
struct console_state_data *state =
ast_threadstorage_get(&console_state, sizeof(*state));
char prefix[80];
do {
if (VERBOSE_HASMAGIC(s)) {
/* always use the given line's level, otherwise
we'll use the last line's level */
state->verbose_line_level = VERBOSE_MAGIC2LEVEL(s);
set_header(prefix, sizeof(prefix), state->verbose_line_level);
/* for a given line separate on verbose magic, newline, and eol */
if ((s = strchr(c, '\n'))) {
newline = 1;
} else {
s = strchr(c, '\0');
newline = 0;
}
/* check if we should write this line after calculating begin/end
so we process the case of a higher level line embedded within
two lower level lines */
if (state->verbose_line_level > option_verbose) {
continue;
}
if (!ast_strlen_zero(prefix)) {
num = s - c;
if (fwrite(c, sizeof(char), num, stdout) < num) {
break;
}
if (!res) {
/* if at least some info has been written
we'll want to return true */
res = 1;
}
} while (*s);
if (newline) {
/* if ending on a newline then reset last level to zero
since what follows may be not be logging output */
state->verbose_line_level = 0;
}
return res;
}
static void console_verboser(const char *s)
{
/* Wake up a poll()ing console */
Tilghman Lesher
committed
if (ast_opt_console && consolethread != AST_PTHREADT_NULL) {
pthread_kill(consolethread, SIGURG);
Tilghman Lesher
committed
}
static int ast_all_zeros(const char *s)
Olle Johansson
committed
while (*s) {
if (*s > 32)
return 0;
}
return 1;
}
/* This is the main console CLI command handler. Run by the main() thread. */
static void consolehandler(const char *s)
printf("%s", term_end());
/* The real handler for bang */
if (s[0] == '!') {
if (s[1])
ast_safe_system(s+1);
else
ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
static int remoteconsolehandler(const char *s)
while (isspace(*s)) {
s++;
}
/* The real handler for bang */
if (s[0] == '!') {
if (s[1])
ast_safe_system(s+1);
else
ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
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;
static char *handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Russell Bryant
committed
{
switch (cmd) {
case CLI_INIT:
e->command = "core show version";
"Usage: core show version\n"
" Shows Asterisk version information.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 3)
return CLI_SHOWUSAGE;
ast_cli(a->fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
Russell Bryant
committed
ast_get_version(), ast_build_user, ast_build_hostname,
Russell Bryant
committed
ast_build_machine, ast_build_os, ast_build_date);
return CLI_SUCCESS;
Russell Bryant
committed
}
static char *handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
switch (cmd) {
case CLI_INIT:
e->command = "core stop now";
"Usage: core stop now\n"
" Shuts down a running Asterisk immediately, hanging up all active calls .\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != e->args)
return CLI_SHOWUSAGE;
quit_handler(0, SHUTDOWN_NORMAL, 0 /* not restart */);
return CLI_SUCCESS;
static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
switch (cmd) {
case CLI_INIT:
e->command = "core stop gracefully";
"Usage: core stop gracefully\n"
" Causes Asterisk to not accept new calls, and exit when all\n"
" active calls have terminated normally.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != e->args)
return CLI_SHOWUSAGE;
quit_handler(0, SHUTDOWN_NICE, 0 /* no restart */);
return CLI_SUCCESS;
static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
switch (cmd) {
case CLI_INIT:
e->command = "core stop when convenient";
"Usage: core stop when convenient\n"
" Causes Asterisk to perform a shutdown when all active calls have ended.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != e->args)
return CLI_SHOWUSAGE;
ast_cli(a->fd, "Waiting for inactivity to perform halt\n");
quit_handler(0, SHUTDOWN_REALLY_NICE, 0 /* don't restart */);
return CLI_SUCCESS;
static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
switch (cmd) {
case CLI_INIT:
e->command = "core restart now";
"Usage: core restart now\n"
" Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
" restart.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != e->args)
return CLI_SHOWUSAGE;
quit_handler(0, SHUTDOWN_NORMAL, 1 /* restart */);
return CLI_SUCCESS;
static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
switch (cmd) {
case CLI_INIT:
e->command = "core restart gracefully";
"Usage: core restart gracefully\n"
" Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
" restart when all active calls have ended.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != e->args)
return CLI_SHOWUSAGE;
quit_handler(0, SHUTDOWN_NICE, 1 /* restart */);
return CLI_SUCCESS;
static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
switch (cmd) {
case CLI_INIT:
e->command = "core restart when convenient";
"Usage: core restart when convenient\n"
" Causes Asterisk to perform a cold restart when all active calls have ended.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != e->args)
return CLI_SHOWUSAGE;
ast_cli(a->fd, "Waiting for inactivity to perform restart\n");
quit_handler(0, SHUTDOWN_REALLY_NICE, 1 /* restart */);
return CLI_SUCCESS;
static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
switch (cmd) {
case CLI_INIT:
e->command = "core abort shutdown";
"Usage: core abort shutdown\n"
" Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
" call operations.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != e->args)
return CLI_SHOWUSAGE;
ast_cancel_shutdown();
return CLI_SUCCESS;
static char *handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
switch (cmd) {
case CLI_INIT:
e->command = "!";
"Usage: !<command>\n"
" Executes a given shell command\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
return CLI_SUCCESS;
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
static const char warranty_lines[] = {
"\n"
" NO WARRANTY\n"
"\n"
"BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
"FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n"
"OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
"PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
"OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
"MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n"
"TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n"
"PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
"REPAIR OR CORRECTION.\n"
"\n"
"IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
"WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
"REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
"INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
"OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
"TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
"YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
"PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
"POSSIBILITY OF SUCH DAMAGES.\n"
static char *show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
switch (cmd) {
case CLI_INIT:
e->command = "core show warranty";
"Usage: core show warranty\n"
" Shows the warranty (if any) for this copy of Asterisk.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
Kevin P. Fleming
committed
ast_cli(a->fd, "%s", warranty_lines);
return CLI_SUCCESS;
static const char license_lines[] = {
"\n"
"This program is free software; you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License version 2 as\n"
"published by the Free Software Foundation.\n"
"\n"
"This program also contains components licensed under other licenses.\n"
"They include:\n"
"\n"
"This program is distributed in the hope that it will be useful,\n"
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
"GNU General Public License for more details.\n"
"\n"
"You should have received a copy of the GNU General Public License\n"
"along with this program; if not, write to the Free Software\n"
"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
switch (cmd) {
case CLI_INIT:
e->command = "core show license";
"Usage: core show license\n"
" Shows the license(s) for this copy of Asterisk.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
Kevin P. Fleming
committed
ast_cli(a->fd, "%s", license_lines);
return CLI_SUCCESS;
/*!
* \brief Shutdown Asterisk CLI commands.
*
* \note These CLI commands cannot be unregistered at shutdown
* because one of them is likely the reason for the shutdown.
* The CLI generates a warning if a command is in-use when it is
* unregistered.
*/
static struct ast_cli_entry cli_asterisk_shutdown[] = {
AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"),
AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"),
AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"),
AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"),
AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
};
static struct ast_cli_entry cli_asterisk[] = {
AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
Jason Parker
committed
AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"),
AST_CLI_DEFINE(handle_version, "Display version info"),
AST_CLI_DEFINE(handle_bang, "Execute a shell command"),
Jason Parker
committed
AST_CLI_DEFINE(handle_show_version_files, "List versions of files used to build Asterisk"),
AST_CLI_DEFINE(handle_show_threads, "Show running threads"),
Michiel van Baak
committed
#if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
Jason Parker
committed
AST_CLI_DEFINE(handle_show_sysinfo, "Show System Information"),
Dwayne M. Hubbard
committed
#endif
Jason Parker
committed
AST_CLI_DEFINE(handle_show_profile, "Display profiling info"),
AST_CLI_DEFINE(handle_show_settings, "Show some core settings"),
AST_CLI_DEFINE(handle_clear_profile, "Clear profiling info"),
#endif /* ! LOW_MEMORY */
Kevin P. Fleming
committed
};
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);
}
/* Leave verbose filtering to the server. */
option_verbose = INT_MAX;
if (!ast_opt_mute) {
fdsend(ast_consock, "logger mute silent");
} else {
printf("log and verbose output currently muted ('logger mute' to unmute)\n");
}
}
#ifdef HAVE_LIBEDIT_IS_UNICODE
static int ast_el_read_char(EditLine *editline, wchar_t *cp)
#else
static int ast_el_read_char(EditLine *editline, char *cp)
Olle Johansson
committed
int num_read = 0;
int lastpos = 0;
struct pollfd fds[2];
#define EL_BUF_SIZE 512
char buf[EL_BUF_SIZE];
max = 1;
fds[0].fd = ast_consock;
fds[0].events = POLLIN;
Russell Bryant
committed
if (!ast_opt_exec) {
fds[1].fd = STDIN_FILENO;
fds[1].events = POLLIN;
max++;
res = ast_poll(fds, max, -1);
if (sig_flags.need_quit || sig_flags.need_quit_handler)
Matthew Jordan
committed
fprintf(stderr, "poll failed: %s\n", strerror(errno));
Russell Bryant
committed
if (!ast_opt_exec && fds[1].revents) {
char c = '\0';
num_read = read(STDIN_FILENO, &c, 1);
Tilghman Lesher
committed
} else {
#ifdef HAVE_LIBEDIT_IS_UNICODE
*cp = btowc(c);
#else
*cp = c;
#endif
Tilghman Lesher
committed
}
if (fds[0].revents) {
res = read(ast_consock, buf, sizeof(buf) - 1);
/* if the remote side disappears exit */
if (res < 1) {
fprintf(stderr, "\nDisconnected from Asterisk server\n");
Russell Bryant
committed
if (!ast_opt_reconnect) {
quit_handler(0, SHUTDOWN_FAST, 0);
} else {
int tries;
int reconnects_per_second = 20;
fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
for (tries = 0; tries < 30 * reconnects_per_second; tries++) {
if (ast_tryconnect()) {
fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
printf("%s", term_quit());
send_rasterisk_connect_commands();
break;
usleep(1000000 / reconnects_per_second);
}
fprintf(stderr, "Failed to reconnect for 30 seconds. Quitting.\n");
quit_handler(0, SHUTDOWN_FAST, 0);
}
}
continue;
/* Write over the CLI prompt */
Kevin P. Fleming
committed
if (!ast_opt_exec && !lastpos) {
if (write(STDOUT_FILENO, "\r[0K", 5) < 0) {
Kevin P. Fleming
committed
}
}
if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (res >= 2 && buf[res-2] == '\n'))) {
#ifdef HAVE_LIBEDIT_IS_UNICODE
*cp = btowc(CC_REFRESH);
#else
#ifdef HAVE_LIBEDIT_IS_UNICODE
*cp = btowc('\0');
#else
static struct ast_str *prompt = NULL;
static char *cli_prompt(EditLine *editline)
char tmp[100];
char *pfmt;
Olle Johansson
committed
int color_used = 0;
static int cli_prompt_changes = 0;
struct passwd *pw;
struct group *gr;
if (prompt == NULL) {
prompt = ast_str_create(100);
} else if (!cli_prompt_changes) {
return ast_str_buffer(prompt);
} else {
ast_str_reset(prompt);
}
if ((pfmt = getenv("ASTERISK_PROMPT"))) {
char *t = pfmt;
struct timeval ts = ast_tvnow();
while (*t != '\0') {
if (*t == '%') {
char hostname[MAXHOSTNAMELEN] = "";
int i, which;
Tilghman Lesher
committed
struct ast_tm tm = { 0, };
int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
t++;
switch (*t) {
Olle Johansson
committed
case 'C': /* color */
t++;
if (sscanf(t, "%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
ast_term_color_code(&prompt, fgcolor, bgcolor);
Olle Johansson
committed
t += i - 1;