58 #include "asterisk/logger_category.h"
61 #include "asterisk/stasis_channels.h"
62 #include "asterisk/stasis_bridges.h"
100 AST_RWLIST_ENTRY(module_level)
entry;
112 AST_RWLOCK_DEFINE_STATIC(shutdown_commands_lock);
116 #define AST_CLI_INITLEN 256
118 void ast_cli(
int fd,
const char *fmt, ...)
139 unsigned int res = 0;
143 if (!strcasecmp(ml->module, module)) {
156 unsigned int res = 0;
160 if (!strcasecmp(ml->module, module)) {
183 static int cli_has_permissions(
int uid,
int gid,
const char *command)
185 struct usergroup_cli_perm *user_perm;
186 struct cli_perm *perm;
194 if ((uid == CLI_NO_PERMS && gid == CLI_NO_PERMS) || command[0] ==
'_') {
198 if (gid < 0 && uid < 0) {
204 if (user_perm->
gid != gid && user_perm->
uid != uid) {
208 if (strcasecmp(perm->
command,
"all") && strncasecmp(perm->
command, command, strlen(perm->
command))) {
210 ispattern = !regcomp(®exbuf, perm->
command, REG_EXTENDED | REG_NOSUB | REG_ICASE);
211 if (ispattern && regexec(®exbuf, command, 0, NULL, 0)) {
220 if (user_perm->
uid == uid) {
247 "Usage: module load <module name>\n"
248 " Loads the specified module into Asterisk.\n";
252 if (a->pos != e->
args) {
257 if (a->argc != e->
args + 1) {
258 return CLI_SHOWUSAGE;
261 ast_cli(a->fd,
"Unable to load module %s\n", a->argv[e->
args]);
264 ast_cli(a->fd,
"Loaded %s\n", a->argv[e->
args]);
276 "Usage: module reload [module ...]\n"
277 " Reloads configuration files for all listed modules which support\n"
278 " reloading, or for all supported modules if none are listed.\n";
284 if (a->argc == e->
args) {
288 for (x = e->
args; x < a->argc; x++) {
292 ast_cli(a->fd,
"No such module '%s'\n", a->argv[x]);
295 ast_cli(a->fd,
"The module '%s' does not support reloads\n", a->argv[x]);
298 ast_cli(a->fd,
"Asterisk cannot reload a module yet; request queued\n");
301 ast_cli(a->fd,
"The module '%s' reported a reload failure\n", a->argv[x]);
304 ast_cli(a->fd,
"A module reload request is already in progress; please be patient\n");
307 ast_cli(a->fd,
"The module '%s' was not properly initialized. Before reloading"
308 " the module, you must run \"module load %s\" and fix whatever is"
309 " preventing the module from being initialized.\n", a->argv[x], a->argv[x]);
312 ast_cli(a->fd,
"Module '%s' reloaded successfully.\n", a->argv[x]);
325 "Usage: core reload\n"
326 " Execute a global reload.\n";
333 if (a->argc != e->
args) {
334 return CLI_SHOWUSAGE;
356 if (!strcasecmp(ml->module, module))
363 static char *complete_number(
const char *partial,
unsigned int min,
unsigned int max,
int n)
366 unsigned int prospective[2];
367 unsigned int part = strtoul(partial, NULL, 10);
370 if (part < min || part > max) {
374 for (i = 0; i < 21; i++) {
376 prospective[0] = prospective[1] = part;
377 }
else if (part == 0 && !ast_strlen_zero(partial)) {
380 prospective[0] = prospective[1] = part * 10 + (i - 1);
382 prospective[0] = (part * 10 + (i - 11)) * 10;
383 prospective[1] = prospective[0] + 9;
385 if (i < 11 && (prospective[0] < min || prospective[0] > max)) {
387 }
else if (prospective[1] < min || prospective[0] > max) {
393 snprintf(next,
sizeof(next),
"%u", prospective[0]);
395 snprintf(next,
sizeof(next),
"%u...", prospective[0] / 10);
403 #define DEBUG_HANDLER 0
404 #define TRACE_HANDLER 1
405 #define VERBOSE_HANDLER 2
407 static void status_debug_verbose(
struct ast_cli_args *a,
int handler,
int old_val,
int cur_val)
411 const char *what =
"";
420 case VERBOSE_HANDLER:
421 what =
"Console verbose";
426 snprintf(was_buf,
sizeof(was_buf),
"%d", old_val);
432 if (old_val == cur_val) {
433 ast_cli(a->fd,
"%s is still %s.\n", what, was);
439 snprintf(now_buf,
sizeof(now_buf),
"%d", cur_val);
445 ast_cli(a->fd,
"%s was %s and is now %s.\n", what, was, now);
456 unsigned int module_option;
458 const char *handler_name;
460 if (a->argc <= e->
args) {
461 return CLI_SHOWUSAGE;
464 if (handler == DEBUG_HANDLER) {
468 handler_name =
"debug";
470 modules = &trace_modules;
473 handler_name =
"trace";
476 if (a->argc == e->
args + 1 && !strcasecmp(a->argv[e->
args],
"off")) {
479 if (!strcasecmp(a->argv[e->
args],
"atleast")) {
483 if (a->argc != e->
args + atleast + 1 && a->argc != e->
args + atleast + 2) {
484 return CLI_SHOWUSAGE;
487 if (sscanf(a->argv[e->
args + atleast],
"%30d", &newlevel) != 1) {
488 return CLI_SHOWUSAGE;
491 if (a->argc == e->
args + atleast + 2) {
494 int mod_len = strlen(mod);
496 if (3 < mod_len && !strcasecmp(mod + mod_len - 3,
".so")) {
497 mod[mod_len - 3] =
'\0';
507 ast_cli(a->fd,
"Core %s is still 0 for '%s'.\n", handler_name, mod);
510 AST_RWLIST_REMOVE(modules, ml,
entry);
511 if (AST_RWLIST_EMPTY(modules)) {
512 ast_clear_flag(&ast_options, module_option);
515 ast_cli(a->fd,
"Core %s was %u and has been set to 0 for '%s'.\n", handler_name,
522 if ((atleast && newlevel < ml->level) || ml->level == newlevel) {
523 ast_cli(a->fd,
"Core %s is still %u for '%s'.\n", handler_name, ml->level, mod);
528 ml->level = newlevel;
530 ml =
ast_calloc(1,
sizeof(*ml) + strlen(mod) + 1);
536 ml->level = newlevel;
537 strcpy(ml->module, mod);
538 AST_RWLIST_INSERT_TAIL(modules, ml,
entry);
540 ast_set_flag(&ast_options, module_option);
542 ast_cli(a->fd,
"Core %s was %d and has been set to %u for '%s'.\n", handler_name,
543 oldval, ml->level, ml->module);
555 while ((ml = AST_RWLIST_REMOVE_HEAD(modules,
entry))) {
561 oldval = *core_option;
562 if (!atleast || newlevel > *core_option) {
563 *core_option = newlevel;
567 status_debug_verbose(a, handler, oldval, *core_option);
575 const char *argv3 = a->argv ?
S_OR(a->argv[3],
"") :
"";
581 "Usage: core set debug [atleast] <level> [module]\n"
582 " core set debug off\n"
584 " Sets level of debug messages to be displayed or\n"
585 " sets a module name to display debug messages from.\n"
586 " 0 or off means no messages should be displayed.\n"
587 " Equivalent to -d[d[...]] on startup\n";
591 if (!strcasecmp(argv3,
"category")) {
595 if (!strcasecmp(argv3,
"atleast")) {
598 if (a->pos == 3 || (a->pos == 4 && atleast)) {
599 const char *pos = a->pos == 3 ? argv3 :
S_OR(a->argv[4],
"");
600 int numbermatch = (ast_strlen_zero(pos) || strchr(
"123456789", pos[0])) ? 0 : 21;
602 if (a->n < 21 && numbermatch == 0) {
603 return complete_number(pos, 0, 0x7fffffff, a->n);
604 }
else if (pos[0] ==
'0') {
608 }
else if (a->n == (21 - numbermatch)) {
609 if (a->pos == 3 && !strncasecmp(argv3,
"off", strlen(argv3))) {
611 }
else if (a->pos == 3 && !strncasecmp(argv3,
"atleast", strlen(argv3))) {
614 }
else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) {
617 }
else if ((a->pos == 4 && !atleast && strcasecmp(argv3,
"off") && strcasecmp(argv3,
"channel"))
618 || (a->pos == 5 && atleast)) {
627 return handle_debug_or_trace(DEBUG_HANDLER, e, cmd, a);
633 const char *argv3 = a->argv ?
S_OR(a->argv[3],
"") :
"";
639 "Usage: core set trace [atleast] <level> [module]\n"
640 " core set trace off\n"
642 " Sets level of trace messages to be displayed or\n"
643 " sets a module name to display trace messages from.\n"
644 " 0 or off means no messages should be displayed.\n";
648 if (!strcasecmp(argv3,
"atleast")) {
651 if (a->pos == 3 || (a->pos == 4 && atleast)) {
652 const char *pos = a->pos == 3 ? argv3 :
S_OR(a->argv[4],
"");
653 int numbermatch = (ast_strlen_zero(pos) || strchr(
"123456789", pos[0])) ? 0 : 21;
655 if (a->n < 21 && numbermatch == 0) {
656 return complete_number(pos, 0, 0x7fffffff, a->n);
657 }
else if (pos[0] ==
'0') {
661 }
else if (a->n == (21 - numbermatch)) {
662 if (a->pos == 3 && !strncasecmp(argv3,
"off", strlen(argv3))) {
664 }
else if (a->pos == 3 && !strncasecmp(argv3,
"atleast", strlen(argv3))) {
667 }
else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) {
670 }
else if ((a->pos == 4 && !atleast && strcasecmp(argv3,
"off") && strcasecmp(argv3,
"channel"))
671 || (a->pos == 5 && atleast)) {
680 return handle_debug_or_trace(TRACE_HANDLER, e, cmd, a);
689 const char *argv3 = a->argv ?
S_OR(a->argv[3],
"") :
"";
693 e->
command =
"core set verbose";
695 "Usage: core set verbose [atleast] <level> [silent]\n"
696 " core set verbose off\n"
698 " Sets level of verbose messages to be displayed.\n"
699 " 0 or off means no verbose messages should be displayed.\n"
700 " The silent option means the command does not report what\n"
701 " happened to the verbose level.\n"
702 " Equivalent to -v[v[...]] on startup\n";
706 if (!strcasecmp(argv3,
"atleast")) {
709 if (a->pos == 3 || (a->pos == 4 && atleast)) {
710 const char *pos = a->pos == 3 ? argv3 :
S_OR(a->argv[4],
"");
711 int numbermatch = (ast_strlen_zero(pos) || strchr(
"123456789", pos[0])) ? 0 : 21;
713 if (a->n < 21 && numbermatch == 0) {
714 return complete_number(pos, 0, 0x7fffffff, a->n);
715 }
else if (pos[0] ==
'0') {
719 }
else if (a->n == (21 - numbermatch)) {
720 if (a->pos == 3 && !strncasecmp(argv3,
"off", strlen(argv3))) {
722 }
else if (a->pos == 3 && !strncasecmp(argv3,
"atleast", strlen(argv3))) {
725 }
else if (a->n == (22 - numbermatch) && a->pos == 3 && ast_strlen_zero(argv3)) {
728 }
else if ((a->pos == 4 && !atleast && strcasecmp(argv3,
"off"))
729 || (a->pos == 5 && atleast)) {
730 const char *pos =
S_OR(a->argv[a->pos],
"");
732 if (a->n == 0 && !strncasecmp(pos,
"silent", strlen(pos))) {
742 if (a->argc <= e->
args) {
743 return CLI_SHOWUSAGE;
746 if (a->argc == e->
args + 1 && !strcasecmp(a->argv[e->
args],
"off")) {
749 if (!strcasecmp(a->argv[e->
args],
"atleast")) {
752 if (a->argc == e->
args + atleast + 2
753 && !strcasecmp(a->argv[e->
args + atleast + 1],
"silent")) {
756 if (a->argc != e->
args + atleast + silent + 1) {
757 return CLI_SHOWUSAGE;
759 if (sscanf(a->argv[e->
args + atleast],
"%30d", &newlevel) != 1) {
760 return CLI_SHOWUSAGE;
766 if (!atleast || newlevel > oldval) {
778 status_debug_verbose(a, VERBOSE_HANDLER, oldval, newlevel);
789 "Usage: logger mute\n"
790 " Disables logging output to the current console, making it possible to\n"
791 " gather information without being disturbed by scrolling lines.\n";
797 if (a->argc < 2 || a->argc > 3)
798 return CLI_SHOWUSAGE;
800 if (a->argc == 3 && !strcasecmp(a->argv[2],
"silent"))
810 static const char *
const completions[] = {
"recursively", NULL };
817 "Usage: module refresh <module name> [recursively]\n"
818 " Unloads and loads the specified module into Asterisk.\n"
819 " 'recursively' will attempt to unload any modules with\n"
820 " dependencies on this module for you and load them again\n"
825 if (a->pos == e->
args) {
827 }
else if (a->pos == e->
args + 1) {
832 if (a->argc < 3 || a->argc > 4) {
833 return CLI_SHOWUSAGE;
838 ast_cli(a->fd,
"Unable to %s resource %s\n", res > 0 ?
"unload" :
"load", a->argv[e->
args]);
841 ast_cli(a->fd,
"Unloaded and loaded %s\n", a->argv[e->
args]);
856 "Usage: module unload [-f|-h] <module_1> [<module_2> ... ]\n"
857 " Unloads the specified module from Asterisk. The -f\n"
858 " option causes the module to be unloaded even if it is\n"
859 " in use (may cause a crash) and the -h module causes the\n"
860 " module to be unloaded even if the module says it cannot, \n"
861 " which almost always will cause a crash.\n";
867 if (a->argc < e->
args + 1)
868 return CLI_SHOWUSAGE;
874 else if (s[1] ==
'h')
877 return CLI_SHOWUSAGE;
878 if (a->argc < e->
args + 2)
879 return CLI_SHOWUSAGE;
883 for (; x < a->argc; x++) {
885 ast_cli(a->fd,
"Unable to unload resource %s\n", a->argv[x]);
888 ast_cli(a->fd,
"Unloaded %s\n", a->argv[x]);
894 #define MODLIST_FORMAT "%-30s %-40.40s %-10d %-11s %13s\n"
895 #define MODLIST_FORMAT2 "%-30s %-40.40s %-10s %-11s %13s\n"
897 AST_MUTEX_DEFINE_STATIC(climodentrylock);
898 static int climodentryfd = -1;
900 static int modlist_modentry(
const char *module,
const char *description,
901 int usecnt,
const char *status,
const char *like,
902 enum ast_module_support_level support_level)
905 if (strcasestr(module, like) ) {
906 ast_cli(climodentryfd, MODLIST_FORMAT, module, description, usecnt,
907 status, ast_module_support_level_to_string(support_level));
913 static void print_uptimestr(
int fd,
struct timeval timeval,
const char *prefix,
int printsec)
919 #define MINUTE (SECOND*60)
920 #define HOUR (MINUTE*60)
921 #define DAY (HOUR*24)
923 #define YEAR (DAY*365)
924 #define NEEDCOMMA(x) ((x) ? ", " : "")
925 if (timeval.tv_sec < 0)
929 ast_cli(fd,
"%s%lu\n", prefix, (u_long)timeval.tv_sec);
932 out = ast_str_alloca(256);
933 if (timeval.tv_sec > YEAR) {
934 x = (timeval.tv_sec / YEAR);
935 timeval.tv_sec -= (x * YEAR);
938 if (timeval.tv_sec > WEEK) {
939 x = (timeval.tv_sec / WEEK);
940 timeval.tv_sec -= (x * WEEK);
943 if (timeval.tv_sec > DAY) {
944 x = (timeval.tv_sec / DAY);
945 timeval.tv_sec -= (x * DAY);
948 if (timeval.tv_sec > HOUR) {
949 x = (timeval.tv_sec / HOUR);
950 timeval.tv_sec -= (x * HOUR);
953 if (timeval.tv_sec > MINUTE) {
954 x = (timeval.tv_sec / MINUTE);
955 timeval.tv_sec -= (x * MINUTE);
982 e->
command =
"core show uptime [seconds]";
984 "Usage: core show uptime [seconds]\n"
985 " Shows Asterisk uptime information.\n"
986 " The seconds word returns the uptime in seconds only.\n";
993 if (a->argc == e->
args && !strcasecmp(a->argv[e->
args-1],
"seconds"))
995 else if (a->argc == e->
args-1)
998 return CLI_SHOWUSAGE;
999 if (ast_startuptime.tv_sec) {
1000 print_uptimestr(a->fd,
ast_tvsub(curtime, ast_startuptime),
"System uptime: ", printsec);
1002 if (ast_lastreloadtime.tv_sec) {
1003 print_uptimestr(a->fd,
ast_tvsub(curtime, ast_lastreloadtime),
"Last reload: ", printsec);
1014 e->
command =
"module show [like]";
1016 "Usage: module show [like keyword]\n"
1017 " Shows Asterisk modules currently in use, and usage statistics.\n";
1021 if (a->pos == e->
args) {
1030 if (a->argc == e->
args - 1)
1032 else if (a->argc == e->
args + 1 && !strcasecmp(a->argv[e->
args-1],
"like") )
1033 like = a->argv[e->
args];
1035 return CLI_SHOWUSAGE;
1037 ast_mutex_lock(&climodentrylock);
1038 climodentryfd = a->fd;
1039 ast_cli(a->fd, MODLIST_FORMAT2,
"Module",
"Description",
"Use Count",
"Status",
"Support Level");
1042 ast_mutex_unlock(&climodentrylock);
1045 #undef MODLIST_FORMAT
1046 #undef MODLIST_FORMAT2
1050 static const char *
const completions[] = {
"seconds", NULL };
1052 int showuptime, printsec;
1056 e->
command =
"core show calls [uptime]";
1058 "Usage: core show calls [uptime [seconds]]\n"
1059 " Lists number of currently active calls and total number of calls\n"
1060 " processed through PBX since last restart. If 'uptime' is specified\n"
1061 " the system uptime is also displayed. If 'seconds' is specified in\n"
1062 " addition to 'uptime', the system uptime is displayed in seconds.\n";
1066 if (a->pos != e->
args)
1072 if (a->argc >= e->
args && !strcasecmp(a->argv[e->
args-1],
"uptime")) {
1075 if (a->argc == e->
args+1 && !strcasecmp(a->argv[e->
args],
"seconds"))
1077 else if (a->argc == e->
args)
1080 return CLI_SHOWUSAGE;
1081 }
else if (a->argc == e->
args-1) {
1085 return CLI_SHOWUSAGE;
1088 ast_cli(a->fd,
"%d of %d max active call%s (%5.2f%% of capacity)\n",
1097 if (ast_startuptime.tv_sec && showuptime) {
1098 print_uptimestr(a->fd,
ast_tvsub(curtime, ast_startuptime),
"System uptime: ", printsec);
1101 return RESULT_SUCCESS;
1106 #define FORMAT_STRING "%-64.64s %-32.32s %-7.7s %-30.30s\n"
1107 #define FORMAT_STRING2 "%-64.64s %-32.32s %-7.7s %-30.30s\n"
1108 #define CONCISE_FORMAT_STRING "%s!%s!%s!%d!%s!%s!%s!%s!%s!%s!%d!%s!%s!%s\n"
1109 #define VERBOSE_FORMAT_STRING "%-80.80s %-24.24s %-24.24s %4d %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-11.11s %-20.20s\n"
1110 #define VERBOSE_FORMAT_STRING2 "%-80.80s %-24.24s %-24.24s %-4.4s %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-11.11s %-20.20s\n"
1115 int numchans = 0, concise = 0, verbose = 0, count = 0;
1119 e->
command =
"core show channels [concise|verbose|count]";
1121 "Usage: core show channels [concise|verbose|count]\n"
1122 " Lists currently defined channels and some information about them. If\n"
1123 " 'concise' is specified, the format is abridged and in a more easily\n"
1124 " machine parsable format. If 'verbose' is specified, the output includes\n"
1125 " more and longer fields. If 'count' is specified only the channel and call\n"
1126 " count is output.\n";
1133 if (a->argc == e->
args) {
1134 if (!strcasecmp(a->argv[e->
args-1],
"concise"))
1136 else if (!strcasecmp(a->argv[e->
args-1],
"verbose"))
1138 else if (!strcasecmp(a->argv[e->
args-1],
"count"))
1141 return CLI_SHOWUSAGE;
1142 }
else if (a->argc != e->
args - 1)
1143 return CLI_SHOWUSAGE;
1148 if (!concise && !verbose)
1149 ast_cli(a->fd, FORMAT_STRING2,
"Channel",
"Location",
"State",
"Application(Data)");
1151 ast_cli(a->fd, VERBOSE_FORMAT_STRING2,
"Channel",
"Context",
"Extension",
"Priority",
"State",
"Application",
"Data",
1152 "CallerID",
"Duration",
"Accountcode",
"PeerAccount",
"BridgeID");
1156 for (; (cs = ao2_iterator_next(&it_chans));
ao2_ref(cs, -1)) {
1157 char durbuf[16] =
"-";
1163 int durh = duration / 3600;
1164 int durm = (duration % 3600) / 60;
1165 int durs = duration % 60;
1166 snprintf(durbuf,
sizeof(durbuf),
"%02d:%02d:%02d", durh, durm, durs);
1168 snprintf(durbuf,
sizeof(durbuf),
"%d", duration);
1182 }
else if (verbose) {
1192 char locbuf[40] =
"(None)";
1193 char appdata[40] =
"(None)";
1209 ast_cli(a->fd,
"%d active channel%s\n", numchans,
ESS(numchans));
1211 ast_cli(a->fd,
"%d of %d max active call%s (%5.2f%% of capacity)\n",
1223 #undef FORMAT_STRING
1224 #undef FORMAT_STRING2
1225 #undef CONCISE_FORMAT_STRING
1226 #undef VERBOSE_FORMAT_STRING
1227 #undef VERBOSE_FORMAT_STRING2
1233 static const char *
const completions[] = {
"all", NULL };
1238 e->
command =
"channel request hangup";
1240 "Usage: channel request hangup <channel>|<all>\n"
1241 " Request that a channel be hung up. The hangup takes effect\n"
1242 " the next time the driver reads or writes from the channel.\n"
1243 " If 'all' is specified instead of a channel name, all channels\n"
1244 " will see the hangup request.\n";
1247 if (a->pos != e->
args) {
1258 return CLI_SHOWUSAGE;
1261 if (!strcasecmp(a->argv[3],
"all")) {
1267 ast_channel_lock(c);
1268 ast_cli(a->fd,
"Requested Hangup on channel '%s'\n", ast_channel_name(c));
1270 ast_channel_unlock(c);
1274 ast_channel_lock(c);
1275 ast_cli(a->fd,
"Requested Hangup on channel '%s'\n", ast_channel_name(c));
1277 ast_channel_unlock(c);
1280 ast_cli(a->fd,
"%s is not a known channel\n", a->argv[3]);
1289 struct usergroup_cli_perm *cp;
1290 struct cli_perm *perm;
1291 struct passwd *pw = NULL;
1292 struct group *gr = NULL;
1296 e->
command =
"cli show permissions";
1298 "Usage: cli show permissions\n"
1299 " Shows CLI configured permissions.\n";
1308 pw = getpwuid(cp->
uid);
1310 ast_cli(a->fd,
"user: %s [uid=%d]\n", pw->pw_name, cp->
uid);
1313 gr = getgrgid(cp->
gid);
1315 ast_cli(a->fd,
"group: %s [gid=%d]\n", gr->gr_name, cp->
gid);
1318 ast_cli(a->fd,
"Permissions:\n");
1321 ast_cli(a->fd,
"\t%s -> %s\n", perm->
permit ?
"permit" :
"deny", perm->
command);
1324 ast_cli(a->fd,
"\n");
1336 e->
command =
"cli reload permissions";
1338 "Usage: cli reload permissions\n"
1339 " Reload the 'cli_permissions.conf' file.\n";
1353 struct passwd *pw = NULL;
1355 int gid = -1, uid = -1;
1356 char command[AST_MAX_ARGS] =
"";
1363 e->
command =
"cli check permissions";
1365 "Usage: cli check permissions {<username>|@<groupname>|<username>@<groupname>} [<command>]\n"
1366 " Check permissions config for a user@group or list the allowed commands for the specified user.\n"
1367 " The username or the groupname may be omitted.\n";
1371 return ast_cli_generator(a->line + strlen(
"cli check permissions") + strlen(a->argv[3]) + 1, a->word, a->n);
1377 return CLI_SHOWUSAGE;
1381 group = strchr(tmp,
'@');
1383 gr = getgrnam(&group[1]);
1385 ast_cli(a->fd,
"Unknown group '%s'\n", &group[1]);
1392 if (!group && ast_strlen_zero(tmp)) {
1393 ast_cli(a->fd,
"You didn't supply a username\n");
1394 }
else if (!ast_strlen_zero(tmp) && !(pw = getpwnam(tmp))) {
1395 ast_cli(a->fd,
"Unknown user '%s'\n", tmp);
1402 while ((ce = cli_next(ce))) {
1407 if (cli_has_permissions(uid, gid, ce->
_full_cmd)) {
1408 ast_cli(a->fd,
"%30.30s %s\n", ce->
_full_cmd,
S_OR(ce->
summary,
"<no description available>"));
1413 ast_cli(a->fd,
"You are not allowed to run any command on Asterisk\n");
1416 ast_join(command,
sizeof(command), a->argv + 4);
1417 ast_cli(a->fd,
"%s '%s%s%s' is %s to run command: '%s'\n", uid >= 0 ?
"User" :
"Group", tmp,
1418 group && uid >= 0 ?
"@" :
"",
1419 group ? &group[1] :
"",
1420 cli_has_permissions(uid, gid, command) ?
"allowed" :
"not allowed", command);
1426 static char *__ast_cli_generator(
const char *text,
const char *word,
int state,
int lock);
1438 e->
command =
"_command matchesarray";
1440 "Usage: _command matchesarray \"<line>\" text \n"
1441 " This function is used internally to help with command completion and should.\n"
1442 " never be called by the user directly.\n";
1449 return CLI_SHOWUSAGE;
1455 for (x=0; matches[x]; x++) {
1456 matchlen = strlen(matches[x]) + 1;
1457 if (len + matchlen >= buflen) {
1458 buflen += matchlen * 3;
1465 len += sprintf( buf + len,
"%s ", matches[x]);
1466 ast_free(matches[x]);
1473 ast_cli(a->fd,
"%s%s",buf, AST_CLI_COMPLETE_EOF);
1476 ast_cli(a->fd,
"NULL\n");
1487 static int channel_set_debug(
void *obj,
void *arg,
void *data,
int flags)
1492 ast_channel_lock(chan);
1494 if (!(ast_channel_fin(chan) &
DEBUGCHAN_FLAG) || !(ast_channel_fout(chan) & DEBUGCHAN_FLAG)) {
1496 ast_channel_fin_set(chan, ast_channel_fin(chan) & ~DEBUGCHAN_FLAG);
1497 ast_channel_fout_set(chan, ast_channel_fout(chan) & ~DEBUGCHAN_FLAG);
1499 ast_channel_fin_set(chan, ast_channel_fin(chan) | DEBUGCHAN_FLAG);
1500 ast_channel_fout_set(chan, ast_channel_fout(chan) | DEBUGCHAN_FLAG);
1502 ast_cli(args->fd,
"Debugging %s on channel %s\n", args->is_off ?
"disabled" :
"enabled",
1503 ast_channel_name(chan));
1506 ast_channel_unlock(chan);
1514 static const char *
const completions_all[] = {
"all", NULL };
1515 static const char *
const completions_off[] = {
"off", NULL };
1522 e->
command =
"core set debug channel";
1524 "Usage: core set debug channel <all|channel> [off]\n"
1525 " Enables/disables debugging on all or on a specific channel.\n";
1534 }
else if (a->pos == 5) {
1541 if (cmd == (CLI_HANDLER + 1000)) {
1544 }
else if (a->argc == e->
args + 2) {
1546 if (!strcasecmp(a->argv[e->
args + 1],
"off"))
1549 return CLI_SHOWUSAGE;
1550 }
else if (a->argc != e->
args + 1) {
1551 return CLI_SHOWUSAGE;
1554 if (!strcasecmp(
"all", a->argv[e->
args])) {
1557 global_fout &= ~DEBUGCHAN_FLAG;
1565 channel_set_debug(c, NULL, &args, 0);
1568 ast_cli(a->fd,
"No such channel %s\n", a->argv[e->
args]);
1572 ast_cli(a->fd,
"Debugging on new channels is %s\n", args.is_off ?
"disabled" :
"enabled");
1579 const char *argv4 = a->argv ?
S_OR(a->argv[4],
"") :
"";
1580 int offset = strncasecmp(argv4,
"off", strlen(argv4)) ? 0 : 1;
1584 e->
command =
"core set debug category";
1586 "Usage: core set debug category <category>[:<sublevel>] [category[:<sublevel] ...]\n"
1587 " core set debug category off [<category> [<category>] ...]\n\n"
1588 " Allows enabling and disabling debug logging categories.\n"
1589 " When a category is enabled all relevant debug messages are logged\n"
1590 " for a given category. However, if a sublevel is specified only\n"
1591 " those categorized messages at or below the coded debug sublevel\n"
1596 if (a->pos < e->
args) {
1600 if (a->pos == 4 && offset) {
1604 return ast_debug_category_complete(a->argv + 4,
1605 a->pos - e->
args, a->word, a->n - 1);
1608 if (a->argc <= e->
args) {
1609 return CLI_SHOWUSAGE;
1612 ast_debug_category_set_sublevels(a->argv + e->
args + offset, a->argc - e->
args - offset,
1613 offset ? AST_LOG_CATEGORY_DISABLED : AST_LOG_CATEGORY_ENABLED);
1624 e->
command =
"no debug channel";
1633 if (a->argc != e->
args + 1)
1634 return CLI_SHOWUSAGE;
1640 res = handle_core_set_debug_channel(e, CLI_HANDLER + 1000, a);
1652 long elapsed_seconds=0;
1653 int hour=0, min=0, sec=0;
1655 struct ast_str *write_transpath = ast_str_alloca(256);
1656 struct ast_str *read_transpath = ast_str_alloca(256);
1660 char callid_buf[32];
1665 e->
command =
"core show channel";
1667 "Usage: core show channel <channel>\n"
1668 " Shows lots of information about the specified channel.\n";
1675 return CLI_SHOWUSAGE;
1685 ast_cli(a->fd,
"%s is not a known channel\n", a->argv[3]);
1698 ast_channel_lock(chan);
1700 if (!
ast_tvzero(ast_channel_creationtime(chan))) {
1701 elapsed_seconds = now.tv_sec - ast_channel_creationtime(chan).tv_sec;
1702 hour = elapsed_seconds / 3600;
1703 min = (elapsed_seconds % 3600) / 60;
1704 sec = elapsed_seconds % 60;
1705 snprintf(cdrtime,
sizeof(cdrtime),
"%dh%dm%ds", hour, min, sec);
1707 strcpy(cdrtime,
"N/A");
1714 callid_buf[0] =
'\0';
1715 callid = ast_channel_callid(chan);
1727 " Caller ID Name: %s\n"
1728 "Connected Line ID: %s\n"
1729 "Connected Line ID Name: %s\n"
1730 "Eff. Connected Line ID: %s\n"
1731 "Eff. Connected Line ID Name: %s\n"
1732 " DNID Digits: %s\n"
1735 " NativeFormats: %s\n"
1736 " WriteFormat: %s\n"
1738 " WriteTranscode: %s %s\n"
1739 " ReadTranscode: %s %s\n"
1740 " Time to Hangup: %ld\n"
1741 " Elapsed Time: %s\n"
1747 " Call Group: %llu\n"
1748 " Pickup Group: %llu\n"
1749 " Application: %s\n"
1751 " Call Identifer: %s\n",
1752 ast_channel_name(chan),
1754 ast_channel_uniqueid(chan),
1755 ast_channel_linkedid(chan),
1757 ast_channel_caller(chan)->
id.
number.str,
"(N/A)"),
1758 S_COR(ast_channel_caller(chan)->
id.
name.valid,
1759 ast_channel_caller(chan)->
id.
name.str,
"(N/A)"),
1760 S_COR(ast_channel_connected(chan)->
id.
number.valid,
1761 ast_channel_connected(chan)->
id.
number.str,
"(N/A)"),
1762 S_COR(ast_channel_connected(chan)->
id.
name.valid,
1763 ast_channel_connected(chan)->
id.
name.str,
"(N/A)"),
1764 S_COR(ast_channel_connected_effective_id(chan).
number.valid,
1765 ast_channel_connected_effective_id(chan).
number.str,
"(N/A)"),
1766 S_COR(ast_channel_connected_effective_id(chan).
name.valid,
1767 ast_channel_connected_effective_id(chan).
name.str,
"(N/A)"),
1768 S_OR(ast_channel_dialed(chan)->
number.str,
"(N/A)"),
1769 ast_channel_language(chan),
1779 (
long)ast_channel_whentohangup(chan)->tv_sec,
1781 bridge ? bridge->
uniqueid :
"(Not bridged)",
1782 ast_channel_context(chan),
1783 ast_channel_exten(chan),
1784 ast_channel_priority(chan),
1785 ast_channel_callgroup(chan),
1786 ast_channel_pickupgroup(chan),
1787 S_OR(ast_channel_appl(chan),
"(N/A)"),
1788 S_OR(ast_channel_data(chan),
"(Empty)"),
1789 S_OR(callid_buf,
"(None)")
1795 ast_str_append(&output, 0,
"%s=%s\n", ast_var_name(var), ast_var_value(var));
1824 for(v = metadata; v; v = v->
next) {
1831 ast_channel_unlock(chan);
1836 ao2_cleanup(bridge);
1848 int i, which = 0, len;
1849 len = ast_strlen_zero(word) ? 0 : strlen(word);
1851 for (i = 0; choices[i]; i++) {
1852 if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state) {
1867 int wordlen = strlen(word), which = 0;
1877 cached_channels = ast_channel_cache_all();
1880 for (; (snapshot = ao2_iterator_next(&iter));
ao2_ref(snapshot, -1)) {
1881 if (!strncasecmp(word, snapshot->
base->
name, wordlen) && (++which >
state)) {
1902 #define FORMAT_STRING "%-25s %-20s %-20s\n"
1907 int havepattern = 0;
1911 e->
command =
"group show channels";
1913 "Usage: group show channels [pattern]\n"
1914 " Lists all currently active channels with channel group(s) specified.\n"
1915 " Optional regular expression pattern is matched to group names for each\n"
1922 if (a->argc < 3 || a->argc > 4)
1923 return CLI_SHOWUSAGE;
1926 if (regcomp(®exbuf, a->argv[3], REG_EXTENDED | REG_NOSUB))
1927 return CLI_SHOWUSAGE;
1931 ast_cli(a->fd, FORMAT_STRING,
"Channel",
"Group",
"Category");
1937 if (!havepattern || !regexec(®exbuf, gi->group, 0, NULL, 0)) {
1938 ast_cli(a->fd, FORMAT_STRING, ast_channel_name(gi->chan), gi->group, (ast_strlen_zero(gi->category) ?
"(default)" : gi->category));
1949 ast_cli(a->fd,
"%d active channel%s\n", numchans,
ESS(numchans));
1951 #undef FORMAT_STRING
1958 e->
command =
"core waitfullybooted";
1960 "Usage: core waitfullybooted\n"
1961 " Wait until Asterisk has fully booted.\n";
1971 ast_cli(a->fd,
"Asterisk has fully booted.\n");
1977 #ifdef HAVE_MALLOC_TRIM
1993 extern int malloc_trim(
size_t __pad) __THROW;
1999 "Usage: malloc trim\n"
2000 " Try to give excess memory back to the OS.\n";
2006 if (malloc_trim(0)) {
2007 ast_cli(a->fd,
"Returned some memory to the OS.\n");
2009 ast_cli(a->fd,
"No memory returned to the OS.\n");
2020 AST_CLI_DEFINE(handle_commandmatchesarray,
"Returns command matches array"),
2022 AST_CLI_DEFINE(handle_debug_category,
"Enable/disable debugging categories"),
2024 AST_CLI_DEFINE(handle_debug,
"Set level of debug chattiness"),
2025 AST_CLI_DEFINE(handle_trace,
"Set level of trace chattiness"),
2026 AST_CLI_DEFINE(handle_verbose,
"Set level of verbose chattiness"),
2028 AST_CLI_DEFINE(handle_help,
"Display help list, or specific help on a command"),
2029 AST_CLI_DEFINE(handle_logger_mute,
"Toggle logging output to a console"),
2031 AST_CLI_DEFINE(handle_modlist,
"List modules and info"),
2032 AST_CLI_DEFINE(handle_load,
"Load a module by name"),
2033 AST_CLI_DEFINE(handle_reload,
"Reload configuration for a module"),
2034 AST_CLI_DEFINE(handle_core_reload,
"Global reload"),
2035 AST_CLI_DEFINE(handle_unload,
"Unload a module by name"),
2036 AST_CLI_DEFINE(handle_refresh,
"Completely unloads and loads a module by name"),
2038 AST_CLI_DEFINE(handle_showuptime,
"Show uptime information"),
2043 AST_CLI_DEFINE(handle_cli_wait_fullybooted,
"Wait for Asterisk to be fully booted"),
2045 #ifdef HAVE_MALLOC_TRIM
2046 AST_CLI_DEFINE(handle_cli_malloc_trim,
"Return excess memory to the OS"),
2052 AST_CLI_DEFINE(handle_nodebugchan_deprecated,
"Disable debugging on channel(s)"),
2053 AST_CLI_DEFINE(handle_chanlist,
"Display information on channels"),
2054 AST_CLI_DEFINE(handle_showcalls,
"Display information on calls"),
2055 AST_CLI_DEFINE(
handle_showchan,
"Display information on a specific channel"),
2056 AST_CLI_DEFINE(handle_core_set_debug_channel,
"Enable/disable debugging on a channel"),
2057 AST_CLI_DEFINE(group_show_channels,
"Display active channels with group(s)"),
2058 AST_CLI_DEFINE(handle_softhangup,
"Request a hangup on a given channel"),
2078 ast_log(LOG_WARNING,
"-- cannot allocate <%s>\n", buf);
2082 for (i = 0; e->
cmda[i]; i++)
2091 struct cli_perm *perm;
2092 struct usergroup_cli_perm *user_perm;
2100 ast_free(user_perm);
2111 struct usergroup_cli_perm *user_group, *cp_entry;
2112 struct cli_perm *perm = NULL;
2117 ast_log(LOG_NOTICE,
"You must wait until last 'cli reload permissions' command finish\n");
2125 }
else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
2134 if (!strcasecmp(cat,
"general")) {
2136 for (v = ast_variable_browse(cfg, cat); v; v = v->
next) {
2137 if (!strcasecmp(v->
name,
"default_perm")) {
2145 gr = NULL, pw = NULL;
2146 if (cat[0] ==
'@') {
2148 gr = getgrnam(&cat[1]);
2150 ast_log (LOG_WARNING,
"Unknown group '%s'\n", &cat[1]);
2157 ast_log (LOG_WARNING,
"Unknown user '%s'\n", cat);
2165 if ((pw && cp_entry->
uid == pw->pw_uid) || (gr && cp_entry->
gid == gr->gr_gid)) {
2168 user_group = cp_entry;
2176 user_group =
ast_calloc(1,
sizeof(*user_group));
2180 user_group->
uid = (pw ? pw->pw_uid : -1);
2181 user_group->
gid = (gr ? gr->gr_gid : -1);
2183 if (!user_group->
perms) {
2184 ast_free(user_group);
2188 for (v = ast_variable_browse(cfg, cat); v; v = v->
next) {
2189 if (ast_strlen_zero(v->
value)) {
2191 ast_log(LOG_WARNING,
"Empty permit/deny option in user '%s'\n", cat);
2194 if (!strcasecmp(v->
name,
"permit")) {
2200 }
else if (!strcasecmp(v->
name,
"deny")) {
2208 ast_log(LOG_WARNING,
"Unknown '%s' option\n", v->
name);
2218 AST_RWLIST_INSERT_TAIL(&
cli_perms, user_group, list);
2227 static void cli_shutdown(
void)
2232 static void cli_channels_shutdown(
void)
2267 if (ast_strlen_zero(cmd) || ast_strlen_zero(cli_word))
2269 if (!strchr(cli_rsvd, cli_word[0]))
2270 return (strcasecmp(cmd, cli_word) == 0) ? 1 : -1;
2273 if (l > 0 && cli_word[0] ==
'%') {
2278 pos = strcasestr(cli_word, cmd);
2286 if (pos != cli_word && strchr(cli_rsvd, pos[-1]) && strchr(cli_rsvd, pos[l])) {
2291 pos = strcasestr(pos + 1, cmd);
2302 int pos,
int *actual)
2308 if (ast_strlen_zero(token))
2310 if (ast_strlen_zero(word))
2313 if (strcspn(word, cli_rsvd) != lw)
2315 if (strchr(cli_rsvd, token[0]) == NULL) {
2316 if (strncasecmp(token, word, lw))
2319 return (pos != 0) ? NULL :
ast_strdup(token);
2326 while (pos >= 0 && (s = strsep(&t1, cli_rsvd)) && *s) {
2329 if (strncasecmp(s, word, lw))
2351 static struct ast_cli_entry *find_cli(
const char *
const cmds[],
int match_type)
2356 while ( (e = cli_next(e)) ) {
2358 const char *
const *src = cmds;
2359 const char *
const *dst = e->cmda;
2361 for (;; dst++, src += n) {
2366 if (ast_strlen_zero(*dst) || ((*dst)[0] ==
'[' && ast_strlen_zero(dst[1]))) {
2368 if (ast_strlen_zero(*src))
2371 if (match_type != 0)
2375 if (ast_strlen_zero(*src))
2381 if (match_type != -1 || !ast_strlen_zero(src[1]) ||
2382 !ast_strlen_zero(dst[1]))
2386 if (src - cmds > matchlen) {
2387 matchlen = src - cmds;
2392 return e ? e : cand;
2395 static char *
find_best(
const char *argv[])
2397 static char cmdline[80];
2400 const char *myargv[AST_MAX_CMD_LEN] = { NULL, };
2403 for (x = 0; argv[x]; x++) {
2404 myargv[x] = argv[x];
2405 if (!find_cli(myargv, -1))
2409 ast_join(cmdline,
sizeof(cmdline), myargv);
2417 while ((cur = cli_next(cur))) {
2425 static void remove_shutdown_command(
struct ast_cli_entry *e)
2427 ast_rwlock_wrlock(&shutdown_commands_lock);
2429 ast_rwlock_unlock(&shutdown_commands_lock);
2435 ast_log(LOG_WARNING,
"Can't remove command that is in use\n");
2438 AST_RWLIST_REMOVE(&
helpers, e, list);
2440 remove_shutdown_command(e);
2446 memset(cmda,
'\0',
sizeof(e->
cmda));
2458 int i, lf, ret = -1;
2461 char **dst = (
char **)e->
cmda;
2466 if (cli_is_registered(e)) {
2467 ast_log(LOG_WARNING,
"Command '%s' already registered (the same ast_cli_entry)\n",
2473 memset(&a,
'\0',
sizeof(a));
2477 e->handler(e, CLI_INIT, &a);
2482 for (i=0; !ast_strlen_zero(s) && i < AST_MAX_CMD_LEN-1; i++) {
2492 if (find_cli(e->
cmda, 1)) {
2493 ast_log(LOG_WARNING,
"Command '%s' already registered (or something close enough)\n",
2498 ast_log(LOG_WARNING,
"Error registering CLI Command '%s'\n",
2504 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&
helpers, cur, list) {
2509 AST_RWLIST_INSERT_BEFORE_CURRENT(e, list);
2513 AST_RWLIST_TRAVERSE_SAFE_END;
2516 AST_RWLIST_INSERT_TAIL(&
helpers, e, list);
2536 for (i = 0; i < len; i++) {
2537 res |= __ast_cli_register(e + i, module);
2547 for (i = 0; i < len; i++)
2557 static char *
help1(
int fd,
const char *
const match[],
int locked)
2559 char matchstr[80] =
"";
2565 ast_join(matchstr,
sizeof(matchstr), match);
2566 len = strlen(matchstr);
2570 while ( (e = cli_next(e)) ) {
2574 if (match && strncasecmp(matchstr, e->
_full_cmd, len))
2576 ast_cli(fd,
"%-30s -- %s\n", e->
_full_cmd,
2582 if (!found && matchstr[0])
2583 ast_cli(fd,
"No such command '%s'.\n", matchstr);
2591 char *res = CLI_SUCCESS;
2593 if (cmd == CLI_INIT) {
2594 e->
command =
"core show help";
2596 "Usage: core show help [topic]\n"
2597 " When called with a topic as an argument, displays usage\n"
2598 " information on the given command. If called without a\n"
2599 " topic, it provides a list of commands.\n";
2602 }
else if (cmd == CLI_GENERATE) {
2604 int l = strlen(a->line);
2610 return __ast_cli_generator(a->line + l, a->word, a->n, 0);
2612 if (a->argc == e->
args) {
2613 return help1(a->fd, NULL, 0);
2617 my_e = find_cli(a->argv + 3, 1);
2619 res =
help1(a->fd, a->argv + 3, 1 );
2624 ast_cli(a->fd,
"%s", my_e->
usage);
2626 ast_join(fullcmd,
sizeof(fullcmd), a->argv + 3);
2627 ast_cli(a->fd,
"No help text available for '%s'.\n", fullcmd);
2633 static char *parse_args(
const char *s,
int *argc,
const char *argv[],
int max,
int *trailingwhitespace)
2635 char *duplicate, *cur;
2642 if (trailingwhitespace == NULL)
2643 trailingwhitespace = &dummy;
2644 *trailingwhitespace = 0;
2654 while (isspace(*s)) {
2662 ast_log(LOG_WARNING,
"Too many arguments, truncating at %s\n", s);
2665 if (*s ==
'"' && !escaped) {
2667 if (quoted && whitespace) {
2672 }
else if ((*s ==
' ' || *s ==
'\t') && !(quoted || escaped)) {
2681 }
else if (*s ==
'\\' && !escaped) {
2701 *trailingwhitespace = whitespace;
2740 static int cli_completion_vector_add(
struct ast_vector_string *vec,
char *value)
2768 char *retstr, *prevstr;
2781 ast_log(LOG_ERROR,
"Failed to initialize threadstorage for completion.\n");
2788 if (cli_completion_vector_add(vec, retstr)) {
2791 goto vector_cleanup;
2806 max_equal = strlen(prevstr);
2817 if (!strcasecmp(prevstr, retstr)) {
2824 while (i < max_equal && toupper(prevstr[i]) == toupper(retstr[i])) {
2838 goto vector_cleanup;
2854 for (i = 0; dst[i]; i++) {
2855 if (dst[i][0] !=
'[')
2864 static char *__ast_cli_generator(
const char *text,
const char *word,
int state,
int lock)
2866 const char *argv[AST_MAX_ARGS];
2868 int x = 0, argindex, matchlen;
2871 char matchstr[80] =
"";
2874 char *duplicate = parse_args(text, &x, argv, ARRAY_LEN(argv), &tws);
2880 argindex = (!ast_strlen_zero(word) && x>0) ? x-1 : x;
2883 ast_join(matchstr,
sizeof(matchstr)-1, argv);
2884 matchlen = strlen(matchstr);
2886 strcat(matchstr,
" ");
2892 while ( (e = cli_next(e)) ) {
2894 int src = 0, dst = 0, n = 0;
2903 for (;src < argindex; dst++, src += n) {
2911 ret =
is_prefix(argv[src], e->
cmda[dst], state - matchnum, &n);
2918 if (matchnum > state)
2922 }
else if (ast_strlen_zero(e->
cmda[dst])) {
2930 .line = matchstr, .word = word,
2932 .n = state - matchnum,
2938 ret = e->handler(e, CLI_GENERATE, &a);
2948 ast_free(duplicate);
2954 return __ast_cli_generator(text, word, state, 1);
2962 ast_rwlock_rdlock(&shutdown_commands_lock);
2969 ast_rwlock_unlock(&shutdown_commands_lock);
2976 const char *args[AST_MAX_ARGS + 1];
2979 char *duplicate = parse_args(s, &x, args + 1, AST_MAX_ARGS, NULL);
2980 char tmp[AST_MAX_ARGS + 1];
2981 char *retval = CLI_FAILURE;
2983 .fd = fd, .argc = x, .argv = args+1 };
2985 if (duplicate == NULL)
2986 return RESULT_FAILURE;
2992 e = find_cli(args + 1, 0);
2997 ast_cli(fd,
"No such command '%s' (type 'core show help %s' for other possible commands)\n", s,
find_best(args + 1));
3002 ast_cli(fd,
"Command '%s' cannot be run during shutdown\n", s);
3006 ast_join(tmp,
sizeof(tmp), args + 1);
3008 if (!cli_has_permissions(uid, gid, tmp)) {
3009 ast_cli(fd,
"You don't have permissions to run '%s' command\n", tmp);
3017 args[0] = (
char *)e;
3021 retval = e->handler(e, CLI_HANDLER, &a);
3025 if (retval == CLI_SHOWUSAGE) {
3026 ast_cli(fd,
"%s",
S_OR(e->
usage,
"Invalid usage, but no usage information available.\n"));
3027 }
else if (retval == CLI_FAILURE) {
3028 ast_cli(fd,
"Command '%s' failed.\n", s);
3035 ast_free(duplicate);
3036 return retval == CLI_SUCCESS ? RESULT_SUCCESS : RESULT_FAILURE;
3042 int x, y = 0, count = 0;
3044 for (x = 0; x < size; x++) {
3058 print_uptimestr(fd,
ast_tv(seconds, 0), prefix, 0);
3065 ast_rwlock_wrlock(&shutdown_commands_lock);
3067 ast_rwlock_unlock(&shutdown_commands_lock);
char * ast_cli_generator(const char *text, const char *word, int state)
Readline madness Useful for readline, that's about it.
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
struct ast_variable * next
struct ao2_container * ast_channel_cache_by_name(void)
Secondary channel cache, indexed by name.
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
const ast_string_field data
static struct module_level_list debug_modules
char * ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
Command completion for the list of active channels.
static struct module_level * find_module_level(const char *module, struct module_level_list *mll)
Find the module level setting.
Main Channel structure associated with a channel.
#define AST_VECTOR_ADD_SORTED(vec, elem, cmp)
Add an element into a sorted vector.
struct ast_channel_snapshot_base * base
Asterisk locking-related definitions:
Channels with this particular technology are an implementation detail of Asterisk and should generall...
struct ast_channel * ast_channel_iterator_next(struct ast_channel_iterator *i)
Get the next channel for a channel iterator.
Asterisk main include file. File version handling, generic pbx functions.
int ast_shutting_down(void)
#define AST_VECTOR_REMOVE_ELEM_UNORDERED(vec, elem, cleanup)
Remove an element from a vector.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
const ast_string_field uniqueid
#define ast_realloc(p, len)
A wrapper for realloc()
char * ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, enum ast_module_helper_type type)
Match modules names for the Asterisk cli.
int ast_active_calls(void)
Retrieve the number of active calls.
enum ast_module_load_result ast_load_resource(const char *resource_name)
Load a module.
unsigned int ast_trace_get_by_module(const char *module)
Get the trace level for a module.
struct ast_stream_topology * ast_channel_get_stream_topology(const struct ast_channel *chan)
Retrieve the topology of streams on a channel.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
#define ast_join(s, len, w)
Join an array of strings into a single string.
int ast_stream_get_group(const struct ast_stream *stream)
Get the stream group that a stream is part of.
struct ast_group_info * ast_app_group_list_head(void)
Get the head of the group count list.
#define ast_channel_unref(c)
Decrease channel reference count.
Support for translation of data formats. translate.c.
int ast_carefulwrite(int fd, char *s, int len, int timeoutms)
Try to write string, but wait no more than ms milliseconds before timing out.
int ast_softhangup(struct ast_channel *chan, int cause)
Softly hangup up a channel.
enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
Get the media type of a stream.
enum ast_module_reload_result ast_module_reload(const char *name)
Reload asterisk modules.
ast_module_reload_result
Possible return types for ast_module_reload.
descriptor for a cli entry.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
const ast_string_field name
#define AST_RWLIST_HEAD_INIT_VALUE
Defines initial values for a declaration of AST_RWLIST_HEAD.
const char * ast_codec_media_type2str(enum ast_media_type type)
Conversion function to take a media type and turn it into a string.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
static ast_mutex_t permsconfiglock
mutex used to prevent a user from running the 'cli reload permissions' command while it is already ru...
Structure for variables, used for configurations and for channel variables.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Structure representing a snapshot of channel state.
static int more_words(const char *const *dst)
returns true if there are more words to match
int ast_str_set_va(struct ast_str **buf, ssize_t max_len, const char *fmt, va_list ap)
Set a dynamic string from a va_list.
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
AST_THREADSTORAGE_RAW(in_intercept_routine)
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
ast_channel_state
ast_channel states
const ast_string_field accountcode
static const char perms_config[]
CLI permissions config file.
const ast_string_field uniqueid
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
static char * help1(int fd, const char *const match[], int locked)
helper for final part of handle_help if locked = 1, assume the list is already locked ...
int ast_verb_console_get(void)
Get this thread's console verbosity level.
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
int ast_refresh_resource(const char *resource_name, enum ast_module_unload_mode force, int recursive)
Unload and load a module again.
void ast_cli_channels_init(void)
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
map a debug or verbose level to a module name
#define ast_strdup(str)
A wrapper for strdup()
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
struct ast_stream * ast_stream_topology_get_stream(const struct ast_stream_topology *topology, unsigned int position)
Get a specific stream from the topology.
Definitions to aid in the use of thread local storage.
struct ast_channel_snapshot_dialplan * dialplan
char * ast_skip_nonblanks(const char *str)
Gets a pointer to first whitespace character in a string.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
int args
This gets set in ast_cli_register()
All configuration options for http media cache.
static int cli_default_perm
Default permissions value 1=Permit 0=Deny.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
const ast_string_field context
int ast_update_module_list(int(*modentry)(const char *module, const char *description, int usecnt, const char *status, const char *like, enum ast_module_support_level support_level), const char *like)
Ask for a list of modules, descriptions, use counts and status.
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
General Asterisk PBX channel definitions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Asterisk file paths, configured in asterisk.conf.
int ast_threadstorage_set_ptr(struct ast_threadstorage *ts, void *ptr)
Set a raw pointer from threadstorage.
const ast_string_field appl
#define AST_VECTOR_ELEM_CLEANUP_NOOP(elem)
Vector element cleanup that does nothing.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define ast_strdupa(s)
duplicate a string in memory from the stack
int ast_cli_allow_at_shutdown(struct ast_cli_entry *e)
Allow a CLI command to be executed while Asterisk is shutting down.
struct cli_perm_head * perms
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
struct ast_variable * ast_stream_get_metadata_list(const struct ast_stream *stream)
Get all stream metadata keys.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
const ast_string_field exten
struct timeval creationtime
static struct callattempt * find_best(struct callattempt *outgoing)
find the entry with the best metric, or NULL
A set of macros to manage forward-linked lists.
#define ast_malloc(len)
A wrapper for malloc()
#define AST_VECTOR_STEAL_ELEMENTS(vec)
Steal the elements from a vector and reinitialize.
void ast_cli_print_timestr_fromseconds(int fd, int seconds, const char *prefix)
Print on cli a duration in seconds in format s year(s), s week(s), s day(s), s hour(s), s second(s)
#define AST_VECTOR(name, type)
Define a vector structure.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
const struct ast_format_cap * ast_stream_get_formats(const struct ast_stream *stream)
Get the current negotiated formats of a stream.
static char * handle_cli_reload_permissions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
handles CLI command 'cli reload permissions'
#define AST_CLI_INITLEN
Initial buffer size for resulting strings in ast_cli()
Structure to describe a channel "technology", ie a channel driver See for examples: ...
static char * handle_cli_show_permissions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
handles CLI command 'cli show permissions'
Core PBX routines and definitions.
struct ast_channel * ast_channel_callback(ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
Call a function with every active channel.
List of restrictions per user.
struct ast_channel_snapshot_caller * caller
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Structure that contains information about a bridge.
struct ast_vector_string * ast_cli_completion_vector(const char *text, const char *word)
Generates a vector of strings for CLI completion.
int ast_processed_calls(void)
Retrieve the total number of calls processed through the PBX since last restart.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
list of users to apply restrictions.
Support for dynamic strings.
int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode)
Unload a module.
static char * handle_cli_check_permissions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
handles CLI command 'cli check permissions'
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
#define ast_strndup(str, len)
A wrapper for strndup()
char ** ast_cli_completion_matches(const char *text, const char *word)
Generates a NULL-terminated array of strings that 1) begin with the string in the second parameter...
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
int ast_app_group_list_unlock(void)
Unlock the group count list.
#define ast_calloc(num, len)
A wrapper for calloc()
char * ast_cli_complete(const char *word, const char *const choices[], int state)
Prototypes for public functions only of internal interest,.
Vector container support.
enum ast_channel_state state
void * ast_threadstorage_get_ptr(struct ast_threadstorage *ts)
Retrieve a raw pointer from threadstorage.
int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
Get the number of streams in a topology.
#define AST_VECTOR_PTR_FREE(vec)
Deallocates this vector pointer.
Structure used to handle boolean flags.
#define AST_RWLIST_HEAD(name, type)
Defines a structure to be used to hold a read/write list of specified type.
#define ast_module_unref(mod)
Release a reference to the module.
unsigned int ast_debug_get_by_module(const char *module)
Get the debug level for a module.
#define ast_module_running_ref(mod)
Hold a reference to the module if it is running.
int ast_cli_command_multiple_full(int uid, int gid, int fd, size_t size, const char *s)
Executes multiple CLI commands Interpret strings separated by NULL and execute each one...
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
const char * ast_translate_path_to_str(struct ast_trans_pvt *t, struct ast_str **str)
Puts a string representation of the translation path into outbuf.
static const char cli_rsvd[]
const char *const summary
int ast_app_group_list_rdlock(void)
Read Lock the group count list.
static char * is_prefix(const char *word, const char *token, int pos, int *actual)
if word is a valid prefix for token, returns the pos-th match as a malloced string, or NULL otherwise. Always tell in *actual how many matches we got.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Standard Command Line Interface.
int ast_cli_command_full(int uid, int gid, int fd, const char *s)
Interprets a command Interpret a command s, sending output to fd if uid:gid has permissions to run th...
const ast_string_field number
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
struct ast_channel_snapshot_bridge * bridge
struct ast_channel_iterator * ast_channel_iterator_destroy(struct ast_channel_iterator *i)
Destroy a channel iterator.
const char * ast_stream_state2str(enum ast_stream_state state)
Convert the state of a stream into a string.
int ast_cli_perms_init(int reload)
void ast_verb_console_set(int verb_level)
Set this thread's console verbosity level.
int ast_cdr_serialize_variables(const char *channel_name, struct ast_str **buf, char delim, char sep)
Serializes all the data and variables for a current CDR record.
List of users and permissions.
#define AST_VECTOR_INSERT_AT(vec, idx, elem)
Insert an element at a specific position in a vector, growing the vector if needed.
static int word_match(const char *cmd, const char *cli_word)
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
void ast_console_toggle_mute(int fd, int silent)
mute or unmute a console from logging
String vector definitions.
void ast_callid_strnprint(char *buffer, size_t buffer_size, ast_callid callid)
copy a string representation of the callid into a target string
struct ast_channel_iterator * ast_channel_iterator_all_new(void)
Create a new channel iterator.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
struct ast_channel_snapshot_peer * peer
void ast_builtins_init(void)
initialize the _full_cmd string in * each of the builtins.
const char * ast_stream_get_name(const struct ast_stream *stream)
Get the name of a stream.
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
#define AST_VECTOR_REMOVE(vec, idx, preserve_ordered)
Remove an element from a vector by index.
const char *const cmda[AST_MAX_CMD_LEN]
Asterisk module definitions.
static void destroy_user_perms(void)
cleanup (free) cli_perms linkedlist.
int ast_active_channels(void)
returns number of active/allocated channels
const char * ast_state2str(enum ast_channel_state state)
Gives the string form of a given channel state.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
static char * handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
Get the current state of a stream.
static int set_full_cmd(struct ast_cli_entry *e)
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
struct ast_module * module
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
const ast_string_field name
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.