Newer
Older
case CLI_GENERATE:
return NULL;
if (a->argc == e->args) {
if (!strcasecmp(a->argv[e->args-1],"concise"))
else if (!strcasecmp(a->argv[e->args-1],"verbose"))
else if (!strcasecmp(a->argv[e->args-1],"count"))
Joshua Colp
committed
count = 1;
} else if (a->argc != e->args - 1)
Mark Spencer
committed
if (!(channels = stasis_cache_dump(ast_channel_cache_by_name(), ast_channel_snapshot_type()))) {
ast_cli(a->fd, "Failed to retrieve cached channels\n");
return CLI_SUCCESS;
}
Joshua Colp
committed
if (!count) {
if (!concise && !verbose)
ast_cli(a->fd, FORMAT_STRING2, "Channel", "Location", "State", "Application(Data)");
Joshua Colp
committed
else if (verbose)
ast_cli(a->fd, VERBOSE_FORMAT_STRING2, "Channel", "Context", "Extension", "Priority", "State", "Application", "Data",
Richard Mudgett
committed
"CallerID", "Duration", "Accountcode", "PeerAccount", "BridgeID");
Joshua Colp
committed
}
it_chans = ao2_iterator_init(channels, 0);
for (; (msg = ao2_iterator_next(&it_chans)); ao2_ref(msg, -1)) {
struct ast_channel_snapshot *cs = stasis_message_data(msg);
char durbuf[10] = "-";
Joshua Colp
committed
if (!count) {
if ((concise || verbose) && !ast_tvzero(cs->creationtime)) {
int duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->creationtime) / 1000);
Joshua Colp
committed
if (verbose) {
int durh = duration / 3600;
int durm = (duration % 3600) / 60;
int durs = duration % 60;
snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
} else {
snprintf(durbuf, sizeof(durbuf), "%d", duration);
Joshua Colp
committed
}
if (concise) {
ast_cli(a->fd, CONCISE_FORMAT_STRING, cs->name, cs->context, cs->exten, cs->priority, ast_state2str(cs->state),
S_OR(cs->appl, "(None)"),
cs->data,
cs->caller_number,
cs->accountcode,
cs->peeraccount,
cs->amaflags,
Joshua Colp
committed
durbuf,
cs->bridgeid,
cs->uniqueid);
Joshua Colp
committed
} else if (verbose) {
ast_cli(a->fd, VERBOSE_FORMAT_STRING, cs->name, cs->context, cs->exten, cs->priority, ast_state2str(cs->state),
S_OR(cs->appl, "(None)"),
S_OR(cs->data, "(Empty)"),
cs->caller_number,
Joshua Colp
committed
durbuf,
cs->accountcode,
cs->peeraccount,
cs->bridgeid);
Mark Spencer
committed
} else {
Joshua Colp
committed
char locbuf[40] = "(None)";
char appdata[40] = "(None)";
if (!ast_strlen_zero(cs->context) && !ast_strlen_zero(cs->exten)) {
snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", cs->exten, cs->context, cs->priority);
}
if (!ast_strlen_zero(cs->appl)) {
snprintf(appdata, sizeof(appdata), "%s(%s)", cs->appl, S_OR(cs->data, ""));
}
ast_cli(a->fd, FORMAT_STRING, cs->name, locbuf, ast_state2str(cs->state), appdata);
Joshua Colp
committed
}
Mark Spencer
committed
}
}
ao2_iterator_destroy(&it_chans);
Mark Spencer
committed
if (!concise) {
numchans = ast_active_channels();
ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
ast_cli(a->fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
ast_active_calls(), ast_option_maxcalls, ESS(ast_active_calls()),
((double)ast_active_calls() / (double)ast_option_maxcalls) * 100.0);
ast_cli(a->fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
Jason Parker
committed
ast_cli(a->fd, "%d call%s processed\n", ast_processed_calls(), ESS(ast_processed_calls()));
Mark Spencer
committed
#undef FORMAT_STRING
#undef FORMAT_STRING2
#undef CONCISE_FORMAT_STRING
#undef VERBOSE_FORMAT_STRING
#undef VERBOSE_FORMAT_STRING2
static char *handle_softhangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
struct ast_channel *c = NULL;
static const char * const completions[] = { "all", NULL };
char *complete;
switch (cmd) {
case CLI_INIT:
e->command = "channel request hangup";
e->usage =
"Usage: channel request hangup <channel>|<all>\n"
" Request that a channel be hung up. The hangup takes effect\n"
" the next time the driver reads or writes from the channel.\n"
" If 'all' is specified instead of a channel name, all channels\n"
" will see the hangup request.\n";
return NULL;
case CLI_GENERATE:
if (a->pos != e->args) {
return NULL;
}
complete = ast_cli_complete(a->word, completions, a->n);
if (!complete) {
complete = ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
}
return complete;
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
if (!strcasecmp(a->argv[3], "all")) {
struct ast_channel_iterator *iter = NULL;
if (!(iter = ast_channel_iterator_all_new())) {
return CLI_FAILURE;
}
for (; iter && (c = ast_channel_iterator_next(iter)); ast_channel_unref(c)) {
ast_channel_lock(c);
ast_cli(a->fd, "Requested Hangup on channel '%s'\n", ast_channel_name(c));
ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
ast_channel_unlock(c);
}
ast_channel_iterator_destroy(iter);
} else if ((c = ast_channel_get_by_name(a->argv[3]))) {
ast_channel_lock(c);
ast_cli(a->fd, "Requested Hangup on channel '%s'\n", ast_channel_name(c));
Kevin P. Fleming
committed
ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
ast_channel_unlock(c);
c = ast_channel_unref(c);
} else {
ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
}
return CLI_SUCCESS;
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
/*! \brief handles CLI command 'cli show permissions' */
static char *handle_cli_show_permissions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct usergroup_cli_perm *cp;
struct cli_perm *perm;
struct passwd *pw = NULL;
struct group *gr = NULL;
switch (cmd) {
case CLI_INIT:
e->command = "cli show permissions";
e->usage =
"Usage: cli show permissions\n"
" Shows CLI configured permissions.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
AST_RWLIST_RDLOCK(&cli_perms);
AST_LIST_TRAVERSE(&cli_perms, cp, list) {
if (cp->uid >= 0) {
pw = getpwuid(cp->uid);
if (pw) {
ast_cli(a->fd, "user: %s [uid=%d]\n", pw->pw_name, cp->uid);
}
} else {
gr = getgrgid(cp->gid);
if (gr) {
ast_cli(a->fd, "group: %s [gid=%d]\n", gr->gr_name, cp->gid);
}
}
ast_cli(a->fd, "Permissions:\n");
if (cp->perms) {
AST_LIST_TRAVERSE(cp->perms, perm, list) {
ast_cli(a->fd, "\t%s -> %s\n", perm->permit ? "permit" : "deny", perm->command);
}
}
ast_cli(a->fd, "\n");
}
AST_RWLIST_UNLOCK(&cli_perms);
return CLI_SUCCESS;
}
/*! \brief handles CLI command 'cli reload permissions' */
static char *handle_cli_reload_permissions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
switch (cmd) {
case CLI_INIT:
e->command = "cli reload permissions";
e->usage =
"Usage: cli reload permissions\n"
" Reload the 'cli_permissions.conf' file.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
ast_cli_perms_init(1);
return CLI_SUCCESS;
}
/*! \brief handles CLI command 'cli check permissions' */
static char *handle_cli_check_permissions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct passwd *pw = NULL;
struct group *gr;
int gid = -1, uid = -1;
char command[AST_MAX_ARGS] = "";
struct ast_cli_entry *ce = NULL;
int found = 0;
char *group, *tmp;
switch (cmd) {
case CLI_INIT:
e->command = "cli check permissions";
e->usage =
"Usage: cli check permissions {<username>|@<groupname>|<username>@<groupname>} [<command>]\n"
" Check permissions config for a user@group or list the allowed commands for the specified user.\n"
" The username or the groupname may be omitted.\n";
return NULL;
case CLI_GENERATE:
if (a->pos >= 4) {
return ast_cli_generator(a->line + strlen("cli check permissions") + strlen(a->argv[3]) + 1, a->word, a->n);
}
return NULL;
}
if (a->argc < 4) {
return CLI_SHOWUSAGE;
}
tmp = ast_strdupa(a->argv[3]);
group = strchr(tmp, '@');
if (group) {
gr = getgrnam(&group[1]);
if (!gr) {
ast_cli(a->fd, "Unknown group '%s'\n", &group[1]);
return CLI_FAILURE;
}
group[0] = '\0';
gid = gr->gr_gid;
}
if (!group && ast_strlen_zero(tmp)) {
ast_cli(a->fd, "You didn't supply a username\n");
} else if (!ast_strlen_zero(tmp) && !(pw = getpwnam(tmp))) {
ast_cli(a->fd, "Unknown user '%s'\n", tmp);
return CLI_FAILURE;
} else if (pw) {
uid = pw->pw_uid;
}
if (a->argc == 4) {
while ((ce = cli_next(ce))) {
/* Hide commands that start with '_' */
if (ce->_full_cmd[0] == '_') {
continue;
}
if (cli_has_permissions(uid, gid, ce->_full_cmd)) {
ast_cli(a->fd, "%30.30s %s\n", ce->_full_cmd, S_OR(ce->summary, "<no description available>"));
found++;
}
}
if (!found) {
ast_cli(a->fd, "You are not allowed to run any command on Asterisk\n");
}
} else {
ast_join(command, sizeof(command), a->argv + 4);
ast_cli(a->fd, "%s '%s%s%s' is %s to run command: '%s'\n", uid >= 0 ? "User" : "Group", tmp,
group && uid >= 0 ? "@" : "",
group ? &group[1] : "",
cli_has_permissions(uid, gid, command) ? "allowed" : "not allowed", command);
}
return CLI_SUCCESS;
}
Russell Bryant
committed
static char *__ast_cli_generator(const char *text, const char *word, int state, int lock);
static char *handle_commandmatchesarray(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
int buflen = 2048;
switch (cmd) {
case CLI_INIT:
e->command = "_command matchesarray";
"Usage: _command matchesarray \"<line>\" text \n"
" This function is used internally to help with command completion and should.\n"
" never be called by the user directly.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 4)
return CLI_SHOWUSAGE;
Russell Bryant
committed
if (!(buf = ast_malloc(buflen)))
return CLI_FAILURE;
matches = ast_cli_completion_matches(a->argv[2], a->argv[3]);
matchlen = strlen(matches[x]) + 1;
if (len + matchlen >= buflen) {
buflen += matchlen * 3;
obuf = buf;
if (!(buf = ast_realloc(obuf, buflen)))
Russell Bryant
committed
/* Memory allocation failure... Just free old buffer and be done */
Tilghman Lesher
committed
ast_free(obuf);
}
if (buf)
len += sprintf( buf + len, "%s ", matches[x]);
Tilghman Lesher
committed
ast_free(matches[x]);
Tilghman Lesher
committed
ast_free(matches);
ast_cli(a->fd, "%s%s",buf, AST_CLI_COMPLETE_EOF);
Tilghman Lesher
committed
ast_free(buf);
ast_cli(a->fd, "NULL\n");
return CLI_SUCCESS;
static char *handle_commandnummatches(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
switch (cmd) {
case CLI_INIT:
e->command = "_command nummatches";
"Usage: _command nummatches \"<line>\" text \n"
" This function is used internally to help with command completion and should.\n"
" never be called by the user directly.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 4)
return CLI_SHOWUSAGE;
matches = ast_cli_generatornummatches(a->argv[2], a->argv[3]);
ast_cli(a->fd, "%d", matches);
return CLI_SUCCESS;
static char *handle_commandcomplete(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
switch (cmd) {
case CLI_INIT:
e->command = "_command complete";
"Usage: _command complete \"<line>\" text state\n"
" This function is used internally to help with command completion and should.\n"
" never be called by the user directly.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc != 5)
return CLI_SHOWUSAGE;
buf = __ast_cli_generator(a->argv[2], a->argv[3], atoi(a->argv[4]), 0);
ast_cli(a->fd, "%s", buf);
Tilghman Lesher
committed
ast_free(buf);
ast_cli(a->fd, "NULL\n");
return CLI_SUCCESS;
struct channel_set_debug_args {
int fd;
int is_off;
};
static int channel_set_debug(void *obj, void *arg, void *data, int flags)
{
struct ast_channel *chan = obj;
struct channel_set_debug_args *args = data;
ast_channel_lock(chan);
if (!(ast_channel_fin(chan) & DEBUGCHAN_FLAG) || !(ast_channel_fout(chan) & DEBUGCHAN_FLAG)) {
if (args->is_off) {
ast_channel_fin_set(chan, ast_channel_fin(chan) & ~DEBUGCHAN_FLAG);
ast_channel_fout_set(chan, ast_channel_fout(chan) & ~DEBUGCHAN_FLAG);
} else {
ast_channel_fin_set(chan, ast_channel_fin(chan) | DEBUGCHAN_FLAG);
ast_channel_fout_set(chan, ast_channel_fout(chan) | DEBUGCHAN_FLAG);
}
ast_cli(args->fd, "Debugging %s on channel %s\n", args->is_off ? "disabled" : "enabled",
ast_channel_name(chan));
}
ast_channel_unlock(chan);
return 0;
}
static char *handle_core_set_debug_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
struct ast_channel *c = NULL;
static const char * const completions_all[] = { "all", NULL };
static const char * const completions_off[] = { "off", NULL };
struct channel_set_debug_args args = {
.fd = a->fd,
};
switch (cmd) {
case CLI_INIT:
e->command = "core set debug channel";
e->usage =
"Usage: core set debug channel <all|channel> [off]\n"
" Enables/disables debugging on all or on a specific channel.\n";
return NULL;
case CLI_GENERATE:
if (a->pos == 4) {
char *complete = ast_cli_complete(a->word, completions_all, a->n);
if (!complete) {
complete = ast_complete_channels(a->line, a->word, a->pos, a->n - 1, e->args);
}
return complete;
} else if (a->pos == 5) {
return ast_cli_complete(a->word, completions_off, a->n);
}
if (cmd == (CLI_HANDLER + 1000)) {
/* called from handle_nodebugchan_deprecated */
args.is_off = 1;
} else if (a->argc == e->args + 2) {
/* 'core set debug channel {all|chan_id}' */
if (!strcasecmp(a->argv[e->args + 1], "off"))
args.is_off = 1;
else
return CLI_SHOWUSAGE;
} else if (a->argc != e->args + 1) {
return CLI_SHOWUSAGE;
}
if (!strcasecmp("all", a->argv[e->args])) {
if (args.is_off) {
global_fin &= ~DEBUGCHAN_FLAG;
global_fout &= ~DEBUGCHAN_FLAG;
} else {
global_fin |= DEBUGCHAN_FLAG;
global_fout |= DEBUGCHAN_FLAG;
}
ast_channel_callback(channel_set_debug, NULL, &args, OBJ_NODATA | OBJ_MULTIPLE);
if ((c = ast_channel_get_by_name(a->argv[e->args]))) {
channel_set_debug(c, NULL, &args, 0);
ast_channel_unref(c);
} else {
ast_cli(a->fd, "No such channel %s\n", a->argv[e->args]);
ast_cli(a->fd, "Debugging on new channels is %s\n", args.is_off ? "disabled" : "enabled");
return CLI_SUCCESS;
static char *handle_nodebugchan_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
switch (cmd) {
case CLI_INIT:
e->command = "no debug channel";
return NULL;
case CLI_HANDLER:
/* exit out of switch statement */
break;
default:
return NULL;
}
if (a->argc != e->args + 1)
return CLI_SHOWUSAGE;
/* add a 'magic' value to the CLI_HANDLER command so that
* handle_core_set_debug_channel() will act as if 'off'
* had been specified as part of the command
*/
res = handle_core_set_debug_channel(e, CLI_HANDLER + 1000, a);
return res;
static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
struct ast_channel *chan;
Mark Spencer
committed
char cdrtime[256];
struct ast_str *obuf;/*!< Buffer for CDR variables. */
Richard Mudgett
committed
struct ast_str *output;/*!< Accumulation buffer for all output. */
int hour=0, min=0, sec=0;
struct ast_var_t *var;
struct ast_str *write_transpath = ast_str_alloca(256);
struct ast_str *read_transpath = ast_str_alloca(256);
Alexander Traud
committed
struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
struct ast_bridge *bridge;
ast_callid callid;
char callid_buf[32];
switch (cmd) {
case CLI_INIT:
e->command = "core show channel";
"Usage: core show channel <channel>\n"
" Shows lots of information about the specified channel.\n";
return NULL;
case CLI_GENERATE:
return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
Richard Mudgett
committed
obuf = ast_str_thread_get(&ast_str_thread_global_buf, 16);
if (!obuf) {
return CLI_FAILURE;
}
Richard Mudgett
committed
output = ast_str_create(8192);
if (!output) {
return CLI_FAILURE;
}
chan = ast_channel_get_by_name(a->argv[3]);
if (!chan) {
ast_cli(a->fd, "%s is not a known channel\n", a->argv[3]);
return CLI_SUCCESS;
}
now = ast_tvnow();
ast_channel_lock(chan);
if (!ast_tvzero(ast_channel_creationtime(chan))) {
elapsed_seconds = now.tv_sec - ast_channel_creationtime(chan).tv_sec;
Kevin P. Fleming
committed
hour = elapsed_seconds / 3600;
min = (elapsed_seconds % 3600) / 60;
sec = elapsed_seconds % 60;
snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
} else {
}
ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath);
ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath);
bridge = ast_channel_get_bridge(chan);
callid_buf[0] = '\0';
callid = ast_channel_callid(chan);
if (callid) {
ast_callid_strnprint(callid_buf, sizeof(callid_buf), callid);
}
Richard Mudgett
committed
ast_str_append(&output, 0,
Kevin P. Fleming
committed
" -- General --\n"
" Name: %s\n"
" Type: %s\n"
" UniqueID: %s\n"
" LinkedID: %s\n"
Kevin P. Fleming
committed
" Caller ID: %s\n"
" Caller ID Name: %s\n"
"Connected Line ID: %s\n"
"Connected Line ID Name: %s\n"
Richard Mudgett
committed
"Eff. Connected Line ID: %s\n"
"Eff. Connected Line ID Name: %s\n"
Kevin P. Fleming
committed
" DNID Digits: %s\n"
Russell Bryant
committed
" Language: %s\n"
" NativeFormats: %s\n"
" WriteFormat: %s\n"
" ReadFormat: %s\n"
" WriteTranscode: %s %s\n"
" ReadTranscode: %s %s\n"
Kevin P. Fleming
committed
" Time to Hangup: %ld\n"
" Elapsed Time: %s\n"
Richard Mudgett
committed
" Bridge ID: %s\n"
Kevin P. Fleming
committed
" -- PBX --\n"
" Context: %s\n"
" Extension: %s\n"
" Priority: %d\n"
" Call Group: %llu\n"
" Pickup Group: %llu\n"
Kevin P. Fleming
committed
" Application: %s\n"
" Data: %s\n"
Jonathan Rose
committed
" Call Identifer: %s\n",
ast_channel_name(chan),
ast_channel_tech(chan)->type,
ast_channel_uniqueid(chan),
ast_channel_linkedid(chan),
S_COR(ast_channel_caller(chan)->id.number.valid,
ast_channel_caller(chan)->id.number.str, "(N/A)"),
S_COR(ast_channel_caller(chan)->id.name.valid,
ast_channel_caller(chan)->id.name.str, "(N/A)"),
S_COR(ast_channel_connected(chan)->id.number.valid,
ast_channel_connected(chan)->id.number.str, "(N/A)"),
S_COR(ast_channel_connected(chan)->id.name.valid,
ast_channel_connected(chan)->id.name.str, "(N/A)"),
S_COR(ast_channel_connected_effective_id(chan).number.valid,
ast_channel_connected_effective_id(chan).number.str, "(N/A)"),
S_COR(ast_channel_connected_effective_id(chan).name.valid,
ast_channel_connected_effective_id(chan).name.str, "(N/A)"),
S_OR(ast_channel_dialed(chan)->number.str, "(N/A)"),
ast_channel_language(chan),
ast_state2str(ast_channel_state(chan)),
ast_channel_state(chan),
ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf),
ast_format_get_name(ast_channel_writeformat(chan)),
ast_format_get_name(ast_channel_readformat(chan)),
ast_str_strlen(write_transpath) ? "Yes" : "No",
ast_str_buffer(write_transpath),
ast_str_strlen(read_transpath) ? "Yes" : "No",
ast_str_buffer(read_transpath),
(long)ast_channel_whentohangup(chan)->tv_sec,
Richard Mudgett
committed
cdrtime,
bridge ? bridge->uniqueid : "(Not bridged)",
ast_channel_context(chan),
ast_channel_exten(chan),
ast_channel_priority(chan),
ast_channel_callgroup(chan),
ast_channel_pickupgroup(chan),
S_OR(ast_channel_appl(chan), "(N/A)"),
S_OR(ast_channel_data(chan), "(Empty)"),
S_OR(callid_buf, "(None)")
);
ast_str_append(&output, 0, " Variables:\n");
AST_LIST_TRAVERSE(ast_channel_varshead(chan), var, entries) {
ast_str_append(&output, 0, "%s=%s\n", ast_var_name(var), ast_var_value(var));
Richard Mudgett
committed
}
if (!(ast_channel_tech(chan)->properties & AST_CHAN_TP_INTERNAL)
&& ast_cdr_serialize_variables(ast_channel_name(chan), &obuf, '=', '\n')) {
ast_str_append(&output, 0, " CDR Variables:\n%s\n", ast_str_buffer(obuf));
}
ast_str_append(&output, 0, " -- Streams --\n");
for (stream_num = 0; stream_num < ast_stream_topology_get_count(ast_channel_get_stream_topology(chan)); stream_num++) {
struct ast_stream *stream = ast_stream_topology_get_stream(ast_channel_get_stream_topology(chan), stream_num);
ast_str_append(&output, 0,
"Name: %s\n"
" Type: %s\n"
" State: %s\n"
" Formats: %s\n",
ast_stream_get_name(stream),
ast_codec_media_type2str(ast_stream_get_type(stream)),
ast_stream_state2str(ast_stream_get_state(stream)),
ast_format_cap_get_names(ast_stream_get_formats(stream), &codec_buf)
);
}
ast_channel_unlock(chan);
Richard Mudgett
committed
ast_cli(a->fd, "%s", ast_str_buffer(output));
ast_free(output);
ao2_cleanup(bridge);
ast_channel_unref(chan);
return CLI_SUCCESS;
/*
* helper function to generate CLI matches from a fixed set of values.
* A NULL word is acceptable.
*/
char *ast_cli_complete(const char *word, const char * const choices[], int state)
Mark Spencer
committed
{
int i, which = 0, len;
len = ast_strlen_zero(word) ? 0 : strlen(word);
for (i = 0; choices[i]; i++) {
if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state)
return ast_strdup(choices[i]);
Mark Spencer
committed
}
return NULL;
}
char *ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
int wordlen = strlen(word), which = 0;
RAII_VAR(struct ao2_container *, cached_channels, NULL, ao2_cleanup);
char *ret = NULL;
struct ao2_iterator iter;
struct stasis_message *msg;
Kevin P. Fleming
committed
if (pos != rpos) {
}
if (!(cached_channels = stasis_cache_dump(ast_channel_cache(), ast_channel_snapshot_type()))) {
return NULL;
}
iter = ao2_iterator_init(cached_channels, 0);
for (; (msg = ao2_iterator_next(&iter)); ao2_ref(msg, -1)) {
struct ast_channel_snapshot *snapshot = stasis_message_data(msg);
if (!strncasecmp(word, snapshot->name, wordlen) && (++which > state)) {
ret = ast_strdup(snapshot->name);
ao2_ref(msg, -1);
break;
}
ao2_iterator_destroy(&iter);
return ret;
static char *group_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Russell Bryant
committed
{
#define FORMAT_STRING "%-25s %-20s %-20s\n"
struct ast_group_info *gi = NULL;
Russell Bryant
committed
int numchans = 0;
regex_t regexbuf;
int havepattern = 0;
switch (cmd) {
case CLI_INIT:
e->command = "group show channels";
"Usage: group show channels [pattern]\n"
" Lists all currently active channels with channel group(s) specified.\n"
" Optional regular expression pattern is matched to group names for each\n"
" channel.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc < 3 || a->argc > 4)
return CLI_SHOWUSAGE;
if (a->argc == 4) {
if (regcomp(®exbuf, a->argv[3], REG_EXTENDED | REG_NOSUB))
return CLI_SHOWUSAGE;
Russell Bryant
committed
havepattern = 1;
}
ast_cli(a->fd, FORMAT_STRING, "Channel", "Group", "Category");
ast_app_group_list_rdlock();
gi = ast_app_group_list_head();
while (gi) {
if (!havepattern || !regexec(®exbuf, gi->group, 0, NULL, 0)) {
ast_cli(a->fd, FORMAT_STRING, ast_channel_name(gi->chan), gi->group, (ast_strlen_zero(gi->category) ? "(default)" : gi->category));
Russell Bryant
committed
}
gi = AST_LIST_NEXT(gi, group_list);
Russell Bryant
committed
}
Russell Bryant
committed
if (havepattern)
regfree(®exbuf);
ast_cli(a->fd, "%d active channel%s\n", numchans, ESS(numchans));
return CLI_SUCCESS;
Russell Bryant
committed
#undef FORMAT_STRING
}
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
static char *handle_cli_wait_fullybooted(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
switch (cmd) {
case CLI_INIT:
e->command = "core waitfullybooted";
e->usage =
"Usage: core waitfullybooted\n"
" Wait until Asterisk has fully booted.\n";
return NULL;
case CLI_GENERATE:
return NULL;
}
while (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
usleep(100);
}
ast_cli(a->fd, "Asterisk has fully booted.\n");
return CLI_SUCCESS;
}
static char *handle_help(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a);
static struct ast_cli_entry cli_cli[] = {
/* Deprecated, but preferred command is now consolidated (and already has a deprecated command for it). */
Jason Parker
committed
AST_CLI_DEFINE(handle_commandcomplete, "Command complete"),
AST_CLI_DEFINE(handle_commandnummatches, "Returns number of command matches"),
AST_CLI_DEFINE(handle_commandmatchesarray, "Returns command matches array"),
Russell Bryant
committed
Jason Parker
committed
AST_CLI_DEFINE(handle_nodebugchan_deprecated, "Disable debugging on channel(s)"),
Jason Parker
committed
AST_CLI_DEFINE(handle_chanlist, "Display information on channels"),
Jason Parker
committed
AST_CLI_DEFINE(handle_showcalls, "Display information on calls"),
Jason Parker
committed
AST_CLI_DEFINE(handle_showchan, "Display information on a specific channel"),
AST_CLI_DEFINE(handle_core_set_debug_channel, "Enable/disable debugging on a channel"),
AST_CLI_DEFINE(handle_debug, "Set level of debug chattiness"),
AST_CLI_DEFINE(handle_verbose, "Set level of verbose chattiness"),
Jason Parker
committed
AST_CLI_DEFINE(group_show_channels, "Display active channels with group(s)"),
Jason Parker
committed
AST_CLI_DEFINE(handle_help, "Display help list, or specific help on a command"),
Jason Parker
committed
AST_CLI_DEFINE(handle_logger_mute, "Toggle logging output to a console"),
Jason Parker
committed
AST_CLI_DEFINE(handle_modlist, "List modules and info"),
AST_CLI_DEFINE(handle_load, "Load a module by name"),
AST_CLI_DEFINE(handle_reload, "Reload configuration for a module"),
AST_CLI_DEFINE(handle_core_reload, "Global reload"),
AST_CLI_DEFINE(handle_unload, "Unload a module by name"),
Jason Parker
committed
AST_CLI_DEFINE(handle_showuptime, "Show uptime information"),
Jason Parker
committed
AST_CLI_DEFINE(handle_softhangup, "Request a hangup on a given channel"),
AST_CLI_DEFINE(handle_cli_reload_permissions, "Reload CLI permissions config"),
AST_CLI_DEFINE(handle_cli_show_permissions, "Show CLI permissions"),
AST_CLI_DEFINE(handle_cli_check_permissions, "Try a permissions config for a user"),
AST_CLI_DEFINE(handle_cli_wait_fullybooted, "Wait for Asterisk to be fully booted"),
/*!
* Some regexp characters in cli arguments are reserved and used as separators.
*/
static const char cli_rsvd[] = "[]{}|*%";
/*!
* initialize the _full_cmd string and related parameters,
* return 0 on success, -1 on error.
*/
static int set_full_cmd(struct ast_cli_entry *e)
{
int i;
char buf[80];
ast_join(buf, sizeof(buf), e->cmda);
e->_full_cmd = ast_strdup(buf);
if (!e->_full_cmd) {
ast_log(LOG_WARNING, "-- cannot allocate <%s>\n", buf);
return -1;
}
e->cmdlen = strcspn(e->_full_cmd, cli_rsvd);
for (i = 0; e->cmda[i]; i++)
;
e->args = i;
return 0;
}
/*! \brief cleanup (free) cli_perms linkedlist. */
static void destroy_user_perms(void)
struct cli_perm *perm;
struct usergroup_cli_perm *user_perm;
AST_RWLIST_WRLOCK(&cli_perms);
while ((user_perm = AST_LIST_REMOVE_HEAD(&cli_perms, list))) {
while ((perm = AST_LIST_REMOVE_HEAD(user_perm->perms, list))) {
ast_free(perm->command);
ast_free(perm);
}
ast_free(user_perm);
}
AST_RWLIST_UNLOCK(&cli_perms);
int ast_cli_perms_init(int reload)
{
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
struct ast_config *cfg;
char *cat = NULL;
struct ast_variable *v;
struct usergroup_cli_perm *user_group, *cp_entry;
struct cli_perm *perm = NULL;
struct passwd *pw;
struct group *gr;
if (ast_mutex_trylock(&permsconfiglock)) {
ast_log(LOG_NOTICE, "You must wait until last 'cli reload permissions' command finish\n");
return 1;
}
cfg = ast_config_load2(perms_config, "" /* core, can't reload */, config_flags);
if (!cfg) {
ast_mutex_unlock(&permsconfiglock);
return 1;
} else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
ast_mutex_unlock(&permsconfiglock);
return 0;
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
/* free current structures. */
destroy_user_perms();
while ((cat = ast_category_browse(cfg, cat))) {
if (!strcasecmp(cat, "general")) {
/* General options */
for (v = ast_variable_browse(cfg, cat); v; v = v->next) {
if (!strcasecmp(v->name, "default_perm")) {
cli_default_perm = (!strcasecmp(v->value, "permit")) ? 1: 0;
}
}
continue;
}
/* users or groups */
gr = NULL, pw = NULL;
if (cat[0] == '@') {
/* This is a group */
gr = getgrnam(&cat[1]);
if (!gr) {
ast_log (LOG_WARNING, "Unknown group '%s'\n", &cat[1]);
continue;
}
} else {
/* This is a user */
pw = getpwnam(cat);
if (!pw) {
ast_log (LOG_WARNING, "Unknown user '%s'\n", cat);
continue;
}
}
user_group = NULL;
/* Check for duplicates */
AST_RWLIST_WRLOCK(&cli_perms);
AST_LIST_TRAVERSE(&cli_perms, cp_entry, list) {
if ((pw && cp_entry->uid == pw->pw_uid) || (gr && cp_entry->gid == gr->gr_gid)) {
/* if it is duplicated, just added this new settings, to
the current list. */
user_group = cp_entry;
break;
}
}
AST_RWLIST_UNLOCK(&cli_perms);
if (!user_group) {
/* alloc space for the new user config. */
user_group = ast_calloc(1, sizeof(*user_group));