e->usage =
"Usage: core stop now\n"
" Shuts down a running Asterisk immediately, hanging up all active calls .\n";
+ ast_cli_allow_at_shutdown(e);
return NULL;
case CLI_GENERATE:
return NULL;
"Usage: core stop gracefully\n"
" Causes Asterisk to not accept new calls, and exit when all\n"
" active calls have terminated normally.\n";
+ ast_cli_allow_at_shutdown(e);
return NULL;
case CLI_GENERATE:
return NULL;
e->usage =
"Usage: core stop when convenient\n"
" Causes Asterisk to perform a shutdown when all active calls have ended.\n";
+ ast_cli_allow_at_shutdown(e);
return NULL;
case CLI_GENERATE:
return NULL;
"Usage: core restart now\n"
" Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
" restart.\n";
+ ast_cli_allow_at_shutdown(e);
return NULL;
case CLI_GENERATE:
return NULL;
"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";
+ ast_cli_allow_at_shutdown(e);
return NULL;
case CLI_GENERATE:
return NULL;
e->usage =
"Usage: core restart when convenient\n"
" Causes Asterisk to perform a cold restart when all active calls have ended.\n";
+ ast_cli_allow_at_shutdown(e);
return NULL;
case CLI_GENERATE:
return NULL;
"Usage: core abort shutdown\n"
" Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
" call operations.\n";
+ ast_cli_allow_at_shutdown(e);
return NULL;
case CLI_GENERATE:
return NULL;
#include "asterisk/bridge.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_bridges.h"
+#include "asterisk/vector.h"
/*!
* \brief List of restrictions per user.
AST_THREADSTORAGE(ast_cli_buf);
+AST_RWLOCK_DEFINE_STATIC(shutdown_commands_lock);
+static AST_VECTOR(, struct ast_cli_entry *) shutdown_commands;
+
/*! \brief Initial buffer size for resulting strings in ast_cli() */
#define AST_CLI_INITLEN 256
/*! \brief initialize the _full_cmd string in * each of the builtins. */
void ast_builtins_init(void)
{
+ AST_VECTOR_INIT(&shutdown_commands, 0);
ast_cli_register_multiple(cli_cli, ARRAY_LEN(cli_cli));
ast_register_cleanup(cli_shutdown);
}
return 0;
}
+static void remove_shutdown_command(struct ast_cli_entry *e)
+{
+ ast_rwlock_wrlock(&shutdown_commands_lock);
+ AST_VECTOR_REMOVE_ELEM_UNORDERED(&shutdown_commands, e, AST_VECTOR_ELEM_CLEANUP_NOOP);
+ ast_rwlock_unlock(&shutdown_commands_lock);
+}
+
int ast_cli_unregister(struct ast_cli_entry *e)
{
if (e->inuse) {
AST_RWLIST_WRLOCK(&helpers);
AST_RWLIST_REMOVE(&helpers, e, list);
AST_RWLIST_UNLOCK(&helpers);
+ remove_shutdown_command(e);
ast_free(e->_full_cmd);
e->_full_cmd = NULL;
if (e->handler) {
return __ast_cli_generator(text, word, state, 1);
}
+static int allowed_on_shutdown(struct ast_cli_entry *e)
+{
+ int found = 0;
+ int i;
+
+ ast_rwlock_rdlock(&shutdown_commands_lock);
+ for (i = 0; i < AST_VECTOR_SIZE(&shutdown_commands); ++i) {
+ if (e == AST_VECTOR_GET(&shutdown_commands, i)) {
+ found = 1;
+ break;
+ }
+ }
+ ast_rwlock_unlock(&shutdown_commands_lock);
+
+ return found;
+}
+
int ast_cli_command_full(int uid, int gid, int fd, const char *s)
{
const char *args[AST_MAX_ARGS + 1];
- struct ast_cli_entry *e;
+ struct ast_cli_entry *e = NULL;
int x;
char *duplicate = parse_args(s, &x, args + 1, AST_MAX_ARGS, NULL);
char tmp[AST_MAX_ARGS + 1];
goto done;
}
+ if (ast_shutting_down() && !allowed_on_shutdown(e)) {
+ ast_cli(fd, "Command '%s' cannot be run during shutdown\n", s);
+ goto done;
+ }
+
ast_join(tmp, sizeof(tmp), args + 1);
/* Check if the user has rights to run this command. */
if (!cli_has_permissions(uid, gid, tmp)) {
} else if (retval == CLI_FAILURE) {
ast_cli(fd, "Command '%s' failed.\n", s);
}
- ast_atomic_fetchadd_int(&e->inuse, -1);
+
done:
+ if (e) {
+ ast_atomic_fetchadd_int(&e->inuse, -1);
+ }
ast_free(duplicate);
return retval == CLI_SUCCESS ? RESULT_SUCCESS : RESULT_FAILURE;
}
{
print_uptimestr(fd, ast_tv(seconds, 0), prefix, 0);
}
+
+int ast_cli_allow_at_shutdown(struct ast_cli_entry *e)
+{
+ int res;
+
+ ast_rwlock_wrlock(&shutdown_commands_lock);
+ res = AST_VECTOR_APPEND(&shutdown_commands, e);
+ ast_rwlock_unlock(&shutdown_commands_lock);
+
+ return res;
+}