00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00029
00030 #include <unistd.h>
00031 #include <stdlib.h>
00032 #include <sys/signal.h>
00033 #include <stdio.h>
00034 #include <signal.h>
00035 #include <string.h>
00036 #include <ctype.h>
00037 #include <regex.h>
00038
00039 #include "asterisk/logger.h"
00040 #include "asterisk/options.h"
00041 #include "asterisk/cli.h"
00042 #include "asterisk/linkedlists.h"
00043 #include "asterisk/module.h"
00044 #include "asterisk/pbx.h"
00045 #include "asterisk/channel.h"
00046 #include "asterisk/utils.h"
00047 #include "asterisk/app.h"
00048 #include "asterisk/lock.h"
00049 #include "editline/readline/readline.h"
00050 #include "asterisk/threadstorage.h"
00051
00052 extern unsigned long global_fin, global_fout;
00053
00054 AST_THREADSTORAGE(ast_cli_buf, ast_cli_buf_init);
00055
00056
00057 #define AST_CLI_INITLEN 256
00058
00059 void ast_cli(int fd, char *fmt, ...)
00060 {
00061 int res;
00062 struct ast_dynamic_str *buf;
00063 va_list ap;
00064
00065 if (!(buf = ast_dynamic_str_thread_get(&ast_cli_buf, AST_CLI_INITLEN)))
00066 return;
00067
00068 va_start(ap, fmt);
00069 res = ast_dynamic_str_thread_set_va(&buf, 0, &ast_cli_buf, fmt, ap);
00070 va_end(ap);
00071
00072 if (res != AST_DYNSTR_BUILD_FAILED)
00073 ast_carefulwrite(fd, buf->str, strlen(buf->str), 100);
00074 }
00075
00076 static AST_LIST_HEAD_STATIC(helpers, ast_cli_entry);
00077
00078 static char load_help[] =
00079 "Usage: module load <module name>\n"
00080 " Loads the specified module into Asterisk.\n";
00081
00082 static char unload_help[] =
00083 "Usage: module unload [-f|-h] <module name>\n"
00084 " Unloads the specified module from Asterisk. The -f\n"
00085 " option causes the module to be unloaded even if it is\n"
00086 " in use (may cause a crash) and the -h module causes the\n"
00087 " module to be unloaded even if the module says it cannot, \n"
00088 " which almost always will cause a crash.\n";
00089
00090 static char help_help[] =
00091 "Usage: help [topic]\n"
00092 " When called with a topic as an argument, displays usage\n"
00093 " information on the given command. If called without a\n"
00094 " topic, it provides a list of commands.\n";
00095
00096 static char chanlist_help[] =
00097 "Usage: core show channels [concise|verbose]\n"
00098 " Lists currently defined channels and some information about them. If\n"
00099 " 'concise' is specified, the format is abridged and in a more easily\n"
00100 " machine parsable format. If 'verbose' is specified, the output includes\n"
00101 " more and longer fields.\n";
00102
00103 static char reload_help[] =
00104 "Usage: module reload [module ...]\n"
00105 " Reloads configuration files for all listed modules which support\n"
00106 " reloading, or for all supported modules if none are listed.\n";
00107
00108 static char verbose_help[] =
00109 "Usage: core set verbose <level>\n"
00110 " Sets level of verbose messages to be displayed. 0 means\n"
00111 " no messages should be displayed. Equivalent to -v[v[v...]]\n"
00112 " on startup\n";
00113
00114 static char debug_help[] =
00115 "Usage: core set debug <level> [filename]\n"
00116 " Sets level of core debug messages to be displayed. 0 means\n"
00117 " no messages should be displayed. Equivalent to -d[d[d...]]\n"
00118 " on startup. If filename is specified, debugging will be\n"
00119 " limited to just that file.\n";
00120
00121 static char nodebug_help[] =
00122 "Usage: core set debug off\n"
00123 " Turns off core debug messages.\n";
00124
00125 static char logger_mute_help[] =
00126 "Usage: logger mute\n"
00127 " Disables logging output to the current console, making it possible to\n"
00128 " gather information without being disturbed by scrolling lines.\n";
00129
00130 static char softhangup_help[] =
00131 "Usage: soft hangup <channel>\n"
00132 " Request that a channel be hung up. The hangup takes effect\n"
00133 " the next time the driver reads or writes from the channel\n";
00134
00135 static char group_show_channels_help[] =
00136 "Usage: group show channels [pattern]\n"
00137 " Lists all currently active channels with channel group(s) specified.\n"
00138 " Optional regular expression pattern is matched to group names for each\n"
00139 " channel.\n";
00140
00141 static int handle_load_deprecated(int fd, int argc, char *argv[])
00142 {
00143 if (argc != 2)
00144 return RESULT_SHOWUSAGE;
00145 if (ast_load_resource(argv[1])) {
00146 ast_cli(fd, "Unable to load module %s\n", argv[1]);
00147 return RESULT_FAILURE;
00148 }
00149 return RESULT_SUCCESS;
00150 }
00151
00152 static int handle_load(int fd, int argc, char *argv[])
00153 {
00154 if (argc != 3)
00155 return RESULT_SHOWUSAGE;
00156 if (ast_load_resource(argv[2])) {
00157 ast_cli(fd, "Unable to load module %s\n", argv[2]);
00158 return RESULT_FAILURE;
00159 }
00160 return RESULT_SUCCESS;
00161 }
00162
00163 static int handle_reload_deprecated(int fd, int argc, char *argv[])
00164 {
00165 int x;
00166 int res;
00167 if (argc < 1)
00168 return RESULT_SHOWUSAGE;
00169 if (argc > 1) {
00170 for (x = 1; x < argc; x++) {
00171 res = ast_module_reload(argv[x]);
00172 switch(res) {
00173 case 0:
00174 ast_cli(fd, "No such module '%s'\n", argv[x]);
00175 break;
00176 case 1:
00177 ast_cli(fd, "Module '%s' does not support reload\n", argv[x]);
00178 break;
00179 }
00180 }
00181 } else
00182 ast_module_reload(NULL);
00183 return RESULT_SUCCESS;
00184 }
00185
00186 static int handle_reload(int fd, int argc, char *argv[])
00187 {
00188 int x;
00189 int res;
00190 if (argc < 2)
00191 return RESULT_SHOWUSAGE;
00192 if (argc > 2) {
00193 for (x = 2; x < argc; x++) {
00194 res = ast_module_reload(argv[x]);
00195 switch(res) {
00196 case 0:
00197 ast_cli(fd, "No such module '%s'\n", argv[x]);
00198 break;
00199 case 1:
00200 ast_cli(fd, "Module '%s' does not support reload\n", argv[x]);
00201 break;
00202 }
00203 }
00204 } else
00205 ast_module_reload(NULL);
00206 return RESULT_SUCCESS;
00207 }
00208
00209 static int handle_set_verbose_deprecated(int fd, int argc, char *argv[])
00210 {
00211 int val = 0;
00212 int oldval = option_verbose;
00213
00214
00215 if (argc == 3)
00216 option_verbose = atoi(argv[2]);
00217 else if (argc == 4) {
00218 if (strcasecmp(argv[2], "atleast"))
00219 return RESULT_SHOWUSAGE;
00220 val = atoi(argv[3]);
00221 if (val > option_verbose)
00222 option_verbose = val;
00223 } else
00224 return RESULT_SHOWUSAGE;
00225
00226 if (oldval != option_verbose && option_verbose > 0)
00227 ast_cli(fd, "Verbosity was %d and is now %d\n", oldval, option_verbose);
00228 else if (oldval > 0 && option_verbose > 0)
00229 ast_cli(fd, "Verbosity is at least %d\n", option_verbose);
00230 else if (oldval > 0 && option_verbose == 0)
00231 ast_cli(fd, "Verbosity is now OFF\n");
00232
00233 return RESULT_SUCCESS;
00234 }
00235
00236 static int handle_verbose(int fd, int argc, char *argv[])
00237 {
00238 int oldval = option_verbose;
00239 int newlevel;
00240 int atleast = 0;
00241
00242 if ((argc < 4) || (argc > 5))
00243 return RESULT_SHOWUSAGE;
00244
00245 if (!strcasecmp(argv[3], "atleast"))
00246 atleast = 1;
00247
00248 if (!atleast) {
00249 if (argc > 4)
00250 return RESULT_SHOWUSAGE;
00251
00252 option_verbose = atoi(argv[3]);
00253 } else {
00254 if (argc < 5)
00255 return RESULT_SHOWUSAGE;
00256
00257 newlevel = atoi(argv[4]);
00258 if (newlevel > option_verbose)
00259 option_verbose = newlevel;
00260 }
00261 if (oldval > 0 && option_verbose == 0)
00262 ast_cli(fd, "Verbosity is now OFF\n");
00263 else if (option_verbose > 0) {
00264 if (oldval == option_verbose)
00265 ast_cli(fd, "Verbosity is at least %d\n", option_verbose);
00266 else
00267 ast_cli(fd, "Verbosity was %d and is now %d\n", oldval, option_verbose);
00268 }
00269
00270 return RESULT_SUCCESS;
00271 }
00272
00273 static int handle_set_debug_deprecated(int fd, int argc, char *argv[])
00274 {
00275 int val = 0;
00276 int oldval = option_debug;
00277
00278
00279 if (argc == 3)
00280 option_debug = atoi(argv[2]);
00281 else if (argc == 4) {
00282 if (strcasecmp(argv[2], "atleast"))
00283 return RESULT_SHOWUSAGE;
00284 val = atoi(argv[3]);
00285 if (val > option_debug)
00286 option_debug = val;
00287 } else
00288 return RESULT_SHOWUSAGE;
00289
00290 if (oldval != option_debug && option_debug > 0)
00291 ast_cli(fd, "Core debug was %d and is now %d\n", oldval, option_debug);
00292 else if (oldval > 0 && option_debug > 0)
00293 ast_cli(fd, "Core debug is at least %d\n", option_debug);
00294 else if (oldval > 0 && option_debug == 0)
00295 ast_cli(fd, "Core debug is now OFF\n");
00296
00297 return RESULT_SUCCESS;
00298 }
00299
00300 static int handle_set_debug(int fd, int argc, char *argv[])
00301 {
00302 int oldval = option_debug;
00303 int newlevel;
00304 int atleast = 0;
00305 char *filename = '\0';
00306
00307
00308
00309
00310
00311
00312 if ((argc < 4) || (argc > 6))
00313 return RESULT_SHOWUSAGE;
00314
00315 if (!strcasecmp(argv[3], "atleast"))
00316 atleast = 1;
00317
00318 if (!atleast) {
00319 if (argc > 5)
00320 return RESULT_SHOWUSAGE;
00321
00322 if (sscanf(argv[3], "%d", &newlevel) != 1)
00323 return RESULT_SHOWUSAGE;
00324
00325 if (argc == 4) {
00326 debug_filename[0] = '\0';
00327 } else {
00328 filename = argv[4];
00329 ast_copy_string(debug_filename, filename, sizeof(debug_filename));
00330 }
00331
00332 option_debug = newlevel;
00333 } else {
00334 if (argc < 5 || argc > 6)
00335 return RESULT_SHOWUSAGE;
00336
00337 if (sscanf(argv[4], "%d", &newlevel) != 1)
00338 return RESULT_SHOWUSAGE;
00339
00340 if (argc == 5) {
00341 debug_filename[0] = '\0';
00342 } else {
00343 filename = argv[5];
00344 ast_copy_string(debug_filename, filename, sizeof(debug_filename));
00345 }
00346
00347 if (newlevel > option_debug)
00348 option_debug = newlevel;
00349 }
00350
00351 if (oldval > 0 && option_debug == 0)
00352 ast_cli(fd, "Core debug is now OFF\n");
00353 else if (option_debug > 0) {
00354 if (filename) {
00355 if (oldval == option_debug)
00356 ast_cli(fd, "Core debug is at least %d, file '%s'\n", option_debug, filename);
00357 else
00358 ast_cli(fd, "Core debug was %d and is now %d, file '%s'\n", oldval, option_debug, filename);
00359 } else {
00360 if (oldval == option_debug)
00361 ast_cli(fd, "Core debug is at least %d\n", option_debug);
00362 else
00363 ast_cli(fd, "Core debug was %d and is now %d\n", oldval, option_debug);
00364 }
00365 }
00366
00367 return RESULT_SUCCESS;
00368 }
00369
00370 static int handle_nodebug(int fd, int argc, char *argv[])
00371 {
00372 int oldval = option_debug;
00373 if (argc != 4)
00374 return RESULT_SHOWUSAGE;
00375
00376 option_debug = 0;
00377 debug_filename[0] = '\0';
00378
00379 if (oldval > 0)
00380 ast_cli(fd, "Core debug is now OFF\n");
00381 return RESULT_SUCCESS;
00382 }
00383
00384 static int handle_debuglevel_deprecated(int fd, int argc, char *argv[])
00385 {
00386 int newlevel;
00387 char *filename = "<any>";
00388 if ((argc < 3) || (argc > 4))
00389 return RESULT_SHOWUSAGE;
00390 if (sscanf(argv[2], "%d", &newlevel) != 1)
00391 return RESULT_SHOWUSAGE;
00392 option_debug = newlevel;
00393 if (argc == 4) {
00394 filename = argv[3];
00395 ast_copy_string(debug_filename, filename, sizeof(debug_filename));
00396 } else {
00397 debug_filename[0] = '\0';
00398 }
00399 ast_cli(fd, "Debugging level set to %d, file '%s'\n", newlevel, filename);
00400 return RESULT_SUCCESS;
00401 }
00402
00403 static int handle_logger_mute(int fd, int argc, char *argv[])
00404 {
00405 if (argc != 2)
00406 return RESULT_SHOWUSAGE;
00407 ast_console_toggle_mute(fd);
00408 return RESULT_SUCCESS;
00409 }
00410
00411 static int handle_unload_deprecated(int fd, int argc, char *argv[])
00412 {
00413 int x;
00414 int force = AST_FORCE_SOFT;
00415 if (argc < 2)
00416 return RESULT_SHOWUSAGE;
00417 for (x = 1; x < argc; x++) {
00418 if (argv[x][0] == '-') {
00419 switch(argv[x][1]) {
00420 case 'f':
00421 force = AST_FORCE_FIRM;
00422 break;
00423 case 'h':
00424 force = AST_FORCE_HARD;
00425 break;
00426 default:
00427 return RESULT_SHOWUSAGE;
00428 }
00429 } else if (x != argc - 1)
00430 return RESULT_SHOWUSAGE;
00431 else if (ast_unload_resource(argv[x], force)) {
00432 ast_cli(fd, "Unable to unload resource %s\n", argv[x]);
00433 return RESULT_FAILURE;
00434 }
00435 }
00436 return RESULT_SUCCESS;
00437 }
00438
00439 static int handle_unload(int fd, int argc, char *argv[])
00440 {
00441 int x;
00442 int force = AST_FORCE_SOFT;
00443 if (argc < 3)
00444 return RESULT_SHOWUSAGE;
00445 for (x = 2; x < argc; x++) {
00446 if (argv[x][0] == '-') {
00447 switch(argv[x][1]) {
00448 case 'f':
00449 force = AST_FORCE_FIRM;
00450 break;
00451 case 'h':
00452 force = AST_FORCE_HARD;
00453 break;
00454 default:
00455 return RESULT_SHOWUSAGE;
00456 }
00457 } else if (x != argc - 1)
00458 return RESULT_SHOWUSAGE;
00459 else if (ast_unload_resource(argv[x], force)) {
00460 ast_cli(fd, "Unable to unload resource %s\n", argv[x]);
00461 return RESULT_FAILURE;
00462 }
00463 }
00464 return RESULT_SUCCESS;
00465 }
00466
00467 #define MODLIST_FORMAT "%-30s %-40.40s %-10d\n"
00468 #define MODLIST_FORMAT2 "%-30s %-40.40s %-10s\n"
00469
00470 AST_MUTEX_DEFINE_STATIC(climodentrylock);
00471 static int climodentryfd = -1;
00472
00473 static int modlist_modentry(const char *module, const char *description, int usecnt, const char *like)
00474 {
00475
00476 if (strcasestr(module, like) ) {
00477 ast_cli(climodentryfd, MODLIST_FORMAT, module, description, usecnt);
00478 return 1;
00479 }
00480 return 0;
00481 }
00482
00483 static char modlist_help[] =
00484 "Usage: module show [like <keyword>]\n"
00485 " Shows Asterisk modules currently in use, and usage statistics.\n";
00486
00487 static char uptime_help[] =
00488 "Usage: core show uptime [seconds]\n"
00489 " Shows Asterisk uptime information.\n"
00490 " The seconds word returns the uptime in seconds only.\n";
00491
00492 static void print_uptimestr(int fd, time_t timeval, const char *prefix, int printsec)
00493 {
00494 int x;
00495 char timestr[256]="", *s = timestr;
00496 size_t maxbytes = sizeof(timestr);
00497
00498 #define SECOND (1)
00499 #define MINUTE (SECOND*60)
00500 #define HOUR (MINUTE*60)
00501 #define DAY (HOUR*24)
00502 #define WEEK (DAY*7)
00503 #define YEAR (DAY*365)
00504 #define ESS(x) ((x == 1) ? "" : "s")
00505 #define NEEDCOMMA(x) ((x)? ",": "")
00506 if (timeval < 0)
00507 return;
00508 if (printsec) {
00509 ast_build_string(&s, &maxbytes, "%lu", (u_long)timeval);
00510 timeval = 0;
00511 }
00512 if (timeval > YEAR) {
00513 x = (timeval / YEAR);
00514 timeval -= (x * YEAR);
00515 ast_build_string(&s, &maxbytes, "%d year%s%s ", x, ESS(x),NEEDCOMMA(timeval));
00516 }
00517 if (timeval > WEEK) {
00518 x = (timeval / WEEK);
00519 timeval -= (x * WEEK);
00520 ast_build_string(&s, &maxbytes, "%d week%s%s ", x, ESS(x),NEEDCOMMA(timeval));
00521 }
00522 if (timeval > DAY) {
00523 x = (timeval / DAY);
00524 timeval -= (x * DAY);
00525 ast_build_string(&s, &maxbytes, "%d day%s%s ", x, ESS(x),NEEDCOMMA(timeval));
00526 }
00527 if (timeval > HOUR) {
00528 x = (timeval / HOUR);
00529 timeval -= (x * HOUR);
00530 ast_build_string(&s, &maxbytes, "%d hour%s%s ", x, ESS(x),NEEDCOMMA(timeval));
00531 }
00532 if (timeval > MINUTE) {
00533 x = (timeval / MINUTE);
00534 timeval -= (x * MINUTE);
00535 ast_build_string(&s, &maxbytes, "%d minute%s%s ", x, ESS(x),NEEDCOMMA(timeval));
00536 }
00537 x = timeval;
00538 if (x > 0)
00539 ast_build_string(&s, &maxbytes, "%d second%s ", x, ESS(x));
00540 if (timestr[0] != '\0')
00541 ast_cli(fd, "%s: %s\n", prefix, timestr);
00542 }
00543
00544 static int handle_showuptime_deprecated(int fd, int argc, char *argv[])
00545 {
00546
00547 time_t curtime = time(NULL);
00548 int printsec = (argc == 3 && !strcasecmp(argv[2],"seconds"));
00549
00550 if (argc != 2 && !printsec)
00551 return RESULT_SHOWUSAGE;
00552 if (ast_startuptime)
00553 print_uptimestr(fd, curtime - ast_startuptime, "System uptime", printsec);
00554 if (ast_lastreloadtime)
00555 print_uptimestr(fd, curtime - ast_lastreloadtime, "Last reload", printsec);
00556 return RESULT_SUCCESS;
00557 }
00558
00559 static int handle_showuptime(int fd, int argc, char *argv[])
00560 {
00561
00562 time_t curtime = time(NULL);
00563 int printsec = (argc == 4 && !strcasecmp(argv[3],"seconds"));
00564
00565 if (argc != 3 && !printsec)
00566 return RESULT_SHOWUSAGE;
00567 if (ast_startuptime)
00568 print_uptimestr(fd, curtime - ast_startuptime, "System uptime", printsec);
00569 if (ast_lastreloadtime)
00570 print_uptimestr(fd, curtime - ast_lastreloadtime, "Last reload", printsec);
00571 return RESULT_SUCCESS;
00572 }
00573
00574 static int handle_modlist(int fd, int argc, char *argv[])
00575 {
00576 char *like = "";
00577 if (argc == 3)
00578 return RESULT_SHOWUSAGE;
00579 else if (argc >= 4) {
00580 if (strcmp(argv[2],"like"))
00581 return RESULT_SHOWUSAGE;
00582 like = argv[3];
00583 }
00584
00585 ast_mutex_lock(&climodentrylock);
00586 climodentryfd = fd;
00587 ast_cli(fd, MODLIST_FORMAT2, "Module", "Description", "Use Count");
00588 ast_cli(fd,"%d modules loaded\n", ast_update_module_list(modlist_modentry, like));
00589 climodentryfd = -1;
00590 ast_mutex_unlock(&climodentrylock);
00591 return RESULT_SUCCESS;
00592 }
00593 #undef MODLIST_FORMAT
00594 #undef MODLIST_FORMAT2
00595
00596 #define FORMAT_STRING "%-20.20s %-20.20s %-7.7s %-30.30s\n"
00597 #define FORMAT_STRING2 "%-20.20s %-20.20s %-7.7s %-30.30s\n"
00598 #define CONCISE_FORMAT_STRING "%s!%s!%s!%d!%s!%s!%s!%s!%s!%d!%s!%s\n"
00599 #define VERBOSE_FORMAT_STRING "%-20.20s %-20.20s %-16.16s %4d %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-20.20s\n"
00600 #define VERBOSE_FORMAT_STRING2 "%-20.20s %-20.20s %-16.16s %-4.4s %-7.7s %-12.12s %-25.25s %-15.15s %8.8s %-11.11s %-20.20s\n"
00601
00602 static int handle_chanlist_deprecated(int fd, int argc, char *argv[])
00603 {
00604 struct ast_channel *c = NULL;
00605 char durbuf[10] = "-";
00606 char locbuf[40];
00607 char appdata[40];
00608 int duration;
00609 int durh, durm, durs;
00610 int numchans = 0, concise = 0, verbose = 0;
00611
00612 concise = (argc == 3 && (!strcasecmp(argv[2],"concise")));
00613 verbose = (argc == 3 && (!strcasecmp(argv[2],"verbose")));
00614
00615 if (argc < 2 || argc > 3 || (argc == 3 && !concise && !verbose))
00616 return RESULT_SHOWUSAGE;
00617
00618 if (!concise && !verbose)
00619 ast_cli(fd, FORMAT_STRING2, "Channel", "Location", "State", "Application(Data)");
00620 else if (verbose)
00621 ast_cli(fd, VERBOSE_FORMAT_STRING2, "Channel", "Context", "Extension", "Priority", "State", "Application", "Data",
00622 "CallerID", "Duration", "Accountcode", "BridgedTo");
00623
00624 while ((c = ast_channel_walk_locked(c)) != NULL) {
00625 struct ast_channel *bc = ast_bridged_channel(c);
00626 if ((concise || verbose) && c->cdr && !ast_tvzero(c->cdr->start)) {
00627 duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
00628 if (verbose) {
00629 durh = duration / 3600;
00630 durm = (duration % 3600) / 60;
00631 durs = duration % 60;
00632 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
00633 } else {
00634 snprintf(durbuf, sizeof(durbuf), "%d", duration);
00635 }
00636 } else {
00637 durbuf[0] = '\0';
00638 }
00639 if (concise) {
00640 ast_cli(fd, CONCISE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
00641 c->appl ? c->appl : "(None)",
00642 S_OR(c->data, ""),
00643 S_OR(c->cid.cid_num, ""),
00644 S_OR(c->accountcode, ""),
00645 c->amaflags,
00646 durbuf,
00647 bc ? bc->name : "(None)");
00648 } else if (verbose) {
00649 ast_cli(fd, VERBOSE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
00650 c->appl ? c->appl : "(None)",
00651 c->data ? S_OR(c->data, "(Empty)" ): "(None)",
00652 S_OR(c->cid.cid_num, ""),
00653 durbuf,
00654 S_OR(c->accountcode, ""),
00655 bc ? bc->name : "(None)");
00656 } else {
00657 if (!ast_strlen_zero(c->context) && !ast_strlen_zero(c->exten))
00658 snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", c->exten, c->context, c->priority);
00659 else
00660 strcpy(locbuf, "(None)");
00661 if (c->appl)
00662 snprintf(appdata, sizeof(appdata), "%s(%s)", c->appl, c->data ? c->data : "");
00663 else
00664 strcpy(appdata, "(None)");
00665 ast_cli(fd, FORMAT_STRING, c->name, locbuf, ast_state2str(c->_state), appdata);
00666 }
00667 numchans++;
00668 ast_channel_unlock(c);
00669 }
00670 if (!concise) {
00671 ast_cli(fd, "%d active channel%s\n", numchans, ESS(numchans));
00672 if (option_maxcalls)
00673 ast_cli(fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
00674 ast_active_calls(), option_maxcalls, ESS(ast_active_calls()),
00675 ((double)ast_active_calls() / (double)option_maxcalls) * 100.0);
00676 else
00677 ast_cli(fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
00678 }
00679 return RESULT_SUCCESS;
00680 }
00681
00682 static int handle_chanlist(int fd, int argc, char *argv[])
00683 {
00684 struct ast_channel *c = NULL;
00685 char durbuf[10] = "-";
00686 char locbuf[40];
00687 char appdata[40];
00688 int duration;
00689 int durh, durm, durs;
00690 int numchans = 0, concise = 0, verbose = 0;
00691
00692 concise = (argc == 4 && (!strcasecmp(argv[3],"concise")));
00693 verbose = (argc == 4 && (!strcasecmp(argv[3],"verbose")));
00694
00695 if (argc < 3 || argc > 4 || (argc == 4 && !concise && !verbose))
00696 return RESULT_SHOWUSAGE;
00697
00698 if (!concise && !verbose)
00699 ast_cli(fd, FORMAT_STRING2, "Channel", "Location", "State", "Application(Data)");
00700 else if (verbose)
00701 ast_cli(fd, VERBOSE_FORMAT_STRING2, "Channel", "Context", "Extension", "Priority", "State", "Application", "Data",
00702 "CallerID", "Duration", "Accountcode", "BridgedTo");
00703
00704 while ((c = ast_channel_walk_locked(c)) != NULL) {
00705 struct ast_channel *bc = ast_bridged_channel(c);
00706 if ((concise || verbose) && c->cdr && !ast_tvzero(c->cdr->start)) {
00707 duration = (int)(ast_tvdiff_ms(ast_tvnow(), c->cdr->start) / 1000);
00708 if (verbose) {
00709 durh = duration / 3600;
00710 durm = (duration % 3600) / 60;
00711 durs = duration % 60;
00712 snprintf(durbuf, sizeof(durbuf), "%02d:%02d:%02d", durh, durm, durs);
00713 } else {
00714 snprintf(durbuf, sizeof(durbuf), "%d", duration);
00715 }
00716 } else {
00717 durbuf[0] = '\0';
00718 }
00719 if (concise) {
00720 ast_cli(fd, CONCISE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
00721 c->appl ? c->appl : "(None)",
00722 S_OR(c->data, ""),
00723 S_OR(c->cid.cid_num, ""),
00724 S_OR(c->accountcode, ""),
00725 c->amaflags,
00726 durbuf,
00727 bc ? bc->name : "(None)");
00728 } else if (verbose) {
00729 ast_cli(fd, VERBOSE_FORMAT_STRING, c->name, c->context, c->exten, c->priority, ast_state2str(c->_state),
00730 c->appl ? c->appl : "(None)",
00731 c->data ? S_OR(c->data, "(Empty)" ): "(None)",
00732 S_OR(c->cid.cid_num, ""),
00733 durbuf,
00734 S_OR(c->accountcode, ""),
00735 bc ? bc->name : "(None)");
00736 } else {
00737 if (!ast_strlen_zero(c->context) && !ast_strlen_zero(c->exten))
00738 snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", c->exten, c->context, c->priority);
00739 else
00740 strcpy(locbuf, "(None)");
00741 if (c->appl)
00742 snprintf(appdata, sizeof(appdata), "%s(%s)", c->appl, c->data ? c->data : "");
00743 else
00744 strcpy(appdata, "(None)");
00745 ast_cli(fd, FORMAT_STRING, c->name, locbuf, ast_state2str(c->_state), appdata);
00746 }
00747 numchans++;
00748 ast_channel_unlock(c);
00749 }
00750 if (!concise) {
00751 ast_cli(fd, "%d active channel%s\n", numchans, ESS(numchans));
00752 if (option_maxcalls)
00753 ast_cli(fd, "%d of %d max active call%s (%5.2f%% of capacity)\n",
00754 ast_active_calls(), option_maxcalls, ESS(ast_active_calls()),
00755 ((double)ast_active_calls() / (double)option_maxcalls) * 100.0);
00756 else
00757 ast_cli(fd, "%d active call%s\n", ast_active_calls(), ESS(ast_active_calls()));
00758 }
00759 return RESULT_SUCCESS;
00760 }
00761
00762 #undef FORMAT_STRING
00763 #undef FORMAT_STRING2
00764 #undef CONCISE_FORMAT_STRING
00765 #undef VERBOSE_FORMAT_STRING
00766 #undef VERBOSE_FORMAT_STRING2
00767
00768 static char showchan_help[] =
00769 "Usage: core show channel <channel>\n"
00770 " Shows lots of information about the specified channel.\n";
00771
00772 static char debugchan_help[] =
00773 "Usage: core set debug channel <channel> [off]\n"
00774 " Enables/disables debugging on a specific channel.\n";
00775
00776 static char commandcomplete_help[] =
00777 "Usage: _command complete \"<line>\" text state\n"
00778 " This function is used internally to help with command completion and should.\n"
00779 " never be called by the user directly.\n";
00780
00781 static char commandnummatches_help[] =
00782 "Usage: _command nummatches \"<line>\" text \n"
00783 " This function is used internally to help with command completion and should.\n"
00784 " never be called by the user directly.\n";
00785
00786 static char commandmatchesarray_help[] =
00787 "Usage: _command matchesarray \"<line>\" text \n"
00788 " This function is used internally to help with command completion and should.\n"
00789 " never be called by the user directly.\n";
00790
00791 static int handle_softhangup(int fd, int argc, char *argv[])
00792 {
00793 struct ast_channel *c=NULL;
00794 if (argc != 3)
00795 return RESULT_SHOWUSAGE;
00796 c = ast_get_channel_by_name_locked(argv[2]);
00797 if (c) {
00798 ast_cli(fd, "Requested Hangup on channel '%s'\n", c->name);
00799 ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
00800 ast_channel_unlock(c);
00801 } else
00802 ast_cli(fd, "%s is not a known channel\n", argv[2]);
00803 return RESULT_SUCCESS;
00804 }
00805
00806 static char *__ast_cli_generator(const char *text, const char *word, int state, int lock);
00807
00808 static int handle_commandmatchesarray(int fd, int argc, char *argv[])
00809 {
00810 char *buf, *obuf;
00811 int buflen = 2048;
00812 int len = 0;
00813 char **matches;
00814 int x, matchlen;
00815
00816 if (argc != 4)
00817 return RESULT_SHOWUSAGE;
00818 if (!(buf = ast_malloc(buflen)))
00819 return RESULT_FAILURE;
00820 buf[len] = '\0';
00821 matches = ast_cli_completion_matches(argv[2], argv[3]);
00822 if (matches) {
00823 for (x=0; matches[x]; x++) {
00824 matchlen = strlen(matches[x]) + 1;
00825 if (len + matchlen >= buflen) {
00826 buflen += matchlen * 3;
00827 obuf = buf;
00828 if (!(buf = ast_realloc(obuf, buflen)))
00829
00830 free(obuf);
00831 }
00832 if (buf)
00833 len += sprintf( buf + len, "%s ", matches[x]);
00834 free(matches[x]);
00835 matches[x] = NULL;
00836 }
00837 free(matches);
00838 }
00839
00840 if (buf) {
00841 ast_cli(fd, "%s%s",buf, AST_CLI_COMPLETE_EOF);
00842 free(buf);
00843 } else
00844 ast_cli(fd, "NULL\n");
00845
00846 return RESULT_SUCCESS;
00847 }
00848
00849
00850
00851 static int handle_commandnummatches(int fd, int argc, char *argv[])
00852 {
00853 int matches = 0;
00854
00855 if (argc != 4)
00856 return RESULT_SHOWUSAGE;
00857
00858 matches = ast_cli_generatornummatches(argv[2], argv[3]);
00859
00860 ast_cli(fd, "%d", matches);
00861
00862 return RESULT_SUCCESS;
00863 }
00864
00865 static int handle_commandcomplete(int fd, int argc, char *argv[])
00866 {
00867 char *buf;
00868
00869 if (argc != 5)
00870 return RESULT_SHOWUSAGE;
00871 buf = __ast_cli_generator(argv[2], argv[3], atoi(argv[4]), 0);
00872 if (buf) {
00873 ast_cli(fd, buf);
00874 free(buf);
00875 } else
00876 ast_cli(fd, "NULL\n");
00877 return RESULT_SUCCESS;
00878 }
00879
00880 static int handle_debugchan_deprecated(int fd, int argc, char *argv[])
00881 {
00882 struct ast_channel *c=NULL;
00883 int is_all;
00884
00885
00886 if (argc != 3)
00887 return RESULT_SHOWUSAGE;
00888
00889 is_all = !strcasecmp("all", argv[2]);
00890 if (is_all) {
00891 global_fin |= DEBUGCHAN_FLAG;
00892 global_fout |= DEBUGCHAN_FLAG;
00893 c = ast_channel_walk_locked(NULL);
00894 } else {
00895 c = ast_get_channel_by_name_locked(argv[2]);
00896 if (c == NULL)
00897 ast_cli(fd, "No such channel %s\n", argv[2]);
00898 }
00899 while (c) {
00900 if (!(c->fin & DEBUGCHAN_FLAG) || !(c->fout & DEBUGCHAN_FLAG)) {
00901 c->fin |= DEBUGCHAN_FLAG;
00902 c->fout |= DEBUGCHAN_FLAG;
00903 ast_cli(fd, "Debugging enabled on channel %s\n", c->name);
00904 }
00905 ast_channel_unlock(c);
00906 if (!is_all)
00907 break;
00908 c = ast_channel_walk_locked(c);
00909 }
00910 ast_cli(fd, "Debugging on new channels is enabled\n");
00911 return RESULT_SUCCESS;
00912 }
00913
00914 static int handle_core_set_debug_channel(int fd, int argc, char *argv[])
00915 {
00916 struct ast_channel *c = NULL;
00917 int is_all, is_off = 0;
00918
00919
00920 if (argc == 6 && strcmp(argv[5], "off") == 0)
00921 is_off = 1;
00922 else if (argc != 5)
00923 return RESULT_SHOWUSAGE;
00924
00925 is_all = !strcasecmp("all", argv[4]);
00926 if (is_all) {
00927 if (is_off) {
00928 global_fin &= ~DEBUGCHAN_FLAG;
00929 global_fout &= ~DEBUGCHAN_FLAG;
00930 } else {
00931 global_fin |= DEBUGCHAN_FLAG;
00932 global_fout |= DEBUGCHAN_FLAG;
00933 }
00934 c = ast_channel_walk_locked(NULL);
00935 } else {
00936 c = ast_get_channel_by_name_locked(argv[4]);
00937 if (c == NULL)
00938 ast_cli(fd, "No such channel %s\n", argv[4]);
00939 }
00940 while (c) {
00941 if (!(c->fin & DEBUGCHAN_FLAG) || !(c->fout & DEBUGCHAN_FLAG)) {
00942 if (is_off) {
00943 c->fin &= ~DEBUGCHAN_FLAG;
00944 c->fout &= ~DEBUGCHAN_FLAG;
00945 } else {
00946 c->fin |= DEBUGCHAN_FLAG;
00947 c->fout |= DEBUGCHAN_FLAG;
00948 }
00949 ast_cli(fd, "Debugging %s on channel %s\n", is_off ? "disabled" : "enabled", c->name);
00950 }
00951 ast_channel_unlock(c);
00952 if (!is_all)
00953 break;
00954 c = ast_channel_walk_locked(c);
00955 }
00956 ast_cli(fd, "Debugging on new channels is %s\n", is_off ? "disabled" : "enabled");
00957 return RESULT_SUCCESS;
00958 }
00959
00960 static int handle_nodebugchan_deprecated(int fd, int argc, char *argv[])
00961 {
00962 struct ast_channel *c=NULL;
00963 int is_all;
00964
00965 if (argc != 4)
00966 return RESULT_SHOWUSAGE;
00967 is_all = !strcasecmp("all", argv[3]);
00968 if (is_all) {
00969 global_fin &= ~DEBUGCHAN_FLAG;
00970 global_fout &= ~DEBUGCHAN_FLAG;
00971 c = ast_channel_walk_locked(NULL);
00972 } else {
00973 c = ast_get_channel_by_name_locked(argv[3]);
00974 if (c == NULL)
00975 ast_cli(fd, "No such channel %s\n", argv[3]);
00976 }
00977 while(c) {
00978 if ((c->fin & DEBUGCHAN_FLAG) || (c->fout & DEBUGCHAN_FLAG)) {
00979 c->fin &= ~DEBUGCHAN_FLAG;
00980 c->fout &= ~DEBUGCHAN_FLAG;
00981 ast_cli(fd, "Debugging disabled on channel %s\n", c->name);
00982 }
00983 ast_channel_unlock(c);
00984 if (!is_all)
00985 break;
00986 c = ast_channel_walk_locked(c);
00987 }
00988 ast_cli(fd, "Debugging on new channels is disabled\n");
00989 return RESULT_SUCCESS;
00990 }
00991
00992 static int handle_showchan_deprecated(int fd, int argc, char *argv[])
00993 {
00994 struct ast_channel *c=NULL;
00995 struct timeval now;
00996 char buf[2048];
00997 char cdrtime[256];
00998 char nf[256], wf[256], rf[256];
00999 long elapsed_seconds=0;
01000 int hour=0, min=0, sec=0;
01001
01002 if (argc != 3)
01003 return RESULT_SHOWUSAGE;
01004 now = ast_tvnow();
01005 c = ast_get_channel_by_name_locked(argv[2]);
01006 if (!c) {
01007 ast_cli(fd, "%s is not a known channel\n", argv[2]);
01008 return RESULT_SUCCESS;
01009 }
01010 if(c->cdr) {
01011 elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
01012 hour = elapsed_seconds / 3600;
01013 min = (elapsed_seconds % 3600) / 60;
01014 sec = elapsed_seconds % 60;
01015 snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
01016 } else
01017 strcpy(cdrtime, "N/A");
01018 ast_cli(fd,
01019 " -- General --\n"
01020 " Name: %s\n"
01021 " Type: %s\n"
01022 " UniqueID: %s\n"
01023 " Caller ID: %s\n"
01024 " Caller ID Name: %s\n"
01025 " DNID Digits: %s\n"
01026 " State: %s (%d)\n"
01027 " Rings: %d\n"
01028 " NativeFormats: %s\n"
01029 " WriteFormat: %s\n"
01030 " ReadFormat: %s\n"
01031 " WriteTranscode: %s\n"
01032 " ReadTranscode: %s\n"
01033 "1st File Descriptor: %d\n"
01034 " Frames in: %d%s\n"
01035 " Frames out: %d%s\n"
01036 " Time to Hangup: %ld\n"
01037 " Elapsed Time: %s\n"
01038 " Direct Bridge: %s\n"
01039 "Indirect Bridge: %s\n"
01040 " -- PBX --\n"
01041 " Context: %s\n"
01042 " Extension: %s\n"
01043 " Priority: %d\n"
01044 " Call Group: %llu\n"
01045 " Pickup Group: %llu\n"
01046 " Application: %s\n"
01047 " Data: %s\n"
01048 " Blocking in: %s\n",
01049 c->name, c->tech->type, c->uniqueid,
01050 S_OR(c->cid.cid_num, "(N/A)"),
01051 S_OR(c->cid.cid_name, "(N/A)"),
01052 S_OR(c->cid.cid_dnid, "(N/A)"), ast_state2str(c->_state), c->_state, c->rings,
01053 ast_getformatname_multiple(nf, sizeof(nf), c->nativeformats),
01054 ast_getformatname_multiple(wf, sizeof(wf), c->writeformat),
01055 ast_getformatname_multiple(rf, sizeof(rf), c->readformat),
01056 c->writetrans ? "Yes" : "No",
01057 c->readtrans ? "Yes" : "No",
01058 c->fds[0],
01059 c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
01060 c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
01061 (long)c->whentohangup,
01062 cdrtime, c->_bridge ? c->_bridge->name : "<none>", ast_bridged_channel(c) ? ast_bridged_channel(c)->name : "<none>",
01063 c->context, c->exten, c->priority, c->callgroup, c->pickupgroup, ( c->appl ? c->appl : "(N/A)" ),
01064 ( c-> data ? S_OR(c->data, "(Empty)") : "(None)"),
01065 (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
01066
01067 if(pbx_builtin_serialize_variables(c,buf,sizeof(buf)))
01068 ast_cli(fd," Variables:\n%s\n",buf);
01069 if(c->cdr && ast_cdr_serialize_variables(c->cdr,buf, sizeof(buf), '=', '\n', 1))
01070 ast_cli(fd," CDR Variables:\n%s\n",buf);
01071
01072 ast_channel_unlock(c);
01073 return RESULT_SUCCESS;
01074 }
01075
01076 static int handle_showchan(int fd, int argc, char *argv[])
01077 {
01078 struct ast_channel *c=NULL;
01079 struct timeval now;
01080 char buf[2048];
01081 char cdrtime[256];
01082 char nf[256], wf[256], rf[256];
01083 long elapsed_seconds=0;
01084 int hour=0, min=0, sec=0;
01085
01086 if (argc != 4)
01087 return RESULT_SHOWUSAGE;
01088 now = ast_tvnow();
01089 c = ast_get_channel_by_name_locked(argv[3]);
01090 if (!c) {
01091 ast_cli(fd, "%s is not a known channel\n", argv[3]);
01092 return RESULT_SUCCESS;
01093 }
01094 if(c->cdr) {
01095 elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
01096 hour = elapsed_seconds / 3600;
01097 min = (elapsed_seconds % 3600) / 60;
01098 sec = elapsed_seconds % 60;
01099 snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
01100 } else
01101 strcpy(cdrtime, "N/A");
01102 ast_cli(fd,
01103 " -- General --\n"
01104 " Name: %s\n"
01105 " Type: %s\n"
01106 " UniqueID: %s\n"
01107 " Caller ID: %s\n"
01108 " Caller ID Name: %s\n"
01109 " DNID Digits: %s\n"
01110 " State: %s (%d)\n"
01111 " Rings: %d\n"
01112 " NativeFormats: %s\n"
01113 " WriteFormat: %s\n"
01114 " ReadFormat: %s\n"
01115 " WriteTranscode: %s\n"
01116 " ReadTranscode: %s\n"
01117 "1st File Descriptor: %d\n"
01118 " Frames in: %d%s\n"
01119 " Frames out: %d%s\n"
01120 " Time to Hangup: %ld\n"
01121 " Elapsed Time: %s\n"
01122 " Direct Bridge: %s\n"
01123 "Indirect Bridge: %s\n"
01124 " -- PBX --\n"
01125 " Context: %s\n"
01126 " Extension: %s\n"
01127 " Priority: %d\n"
01128 " Call Group: %llu\n"
01129 " Pickup Group: %llu\n"
01130 " Application: %s\n"
01131 " Data: %s\n"
01132 " Blocking in: %s\n",
01133 c->name, c->tech->type, c->uniqueid,
01134 S_OR(c->cid.cid_num, "(N/A)"),
01135 S_OR(c->cid.cid_name, "(N/A)"),
01136 S_OR(c->cid.cid_dnid, "(N/A)"), ast_state2str(c->_state), c->_state, c->rings,
01137 ast_getformatname_multiple(nf, sizeof(nf), c->nativeformats),
01138 ast_getformatname_multiple(wf, sizeof(wf), c->writeformat),
01139 ast_getformatname_multiple(rf, sizeof(rf), c->readformat),
01140 c->writetrans ? "Yes" : "No",
01141 c->readtrans ? "Yes" : "No",
01142 c->fds[0],
01143 c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
01144 c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
01145 (long)c->whentohangup,
01146 cdrtime, c->_bridge ? c->_bridge->name : "<none>", ast_bridged_channel(c) ? ast_bridged_channel(c)->name : "<none>",
01147 c->context, c->exten, c->priority, c->callgroup, c->pickupgroup, ( c->appl ? c->appl : "(N/A)" ),
01148 ( c-> data ? S_OR(c->data, "(Empty)") : "(None)"),
01149 (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
01150
01151 if(pbx_builtin_serialize_variables(c,buf,sizeof(buf)))
01152 ast_cli(fd," Variables:\n%s\n",buf);
01153 if(c->cdr && ast_cdr_serialize_variables(c->cdr,buf, sizeof(buf), '=', '\n', 1))
01154 ast_cli(fd," CDR Variables:\n%s\n",buf);
01155
01156 ast_channel_unlock(c);
01157 return RESULT_SUCCESS;
01158 }
01159
01160
01161
01162
01163
01164 char *ast_cli_complete(const char *word, char *const choices[], int state)
01165 {
01166 int i, which = 0, len;
01167 len = ast_strlen_zero(word) ? 0 : strlen(word);
01168
01169 for (i = 0; choices[i]; i++) {
01170 if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state)
01171 return ast_strdup(choices[i]);
01172 }
01173 return NULL;
01174 }
01175
01176 static char *complete_show_channels_deprecated(const char *line, const char *word, int pos, int state)
01177 {
01178 static char *choices[] = { "concise", "verbose", NULL };
01179
01180 return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
01181 }
01182
01183 static char *complete_show_channels(const char *line, const char *word, int pos, int state)
01184 {
01185 static char *choices[] = { "concise", "verbose", NULL };
01186
01187 return (pos != 3) ? NULL : ast_cli_complete(word, choices, state);
01188 }
01189
01190 char *ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
01191 {
01192 struct ast_channel *c = NULL;
01193 int which = 0;
01194 int wordlen;
01195 char notfound = '\0';
01196 char *ret = ¬found;
01197
01198 if (pos != rpos)
01199 return NULL;
01200
01201 wordlen = strlen(word);
01202
01203 while (ret == ¬found && (c = ast_channel_walk_locked(c))) {
01204 if (!strncasecmp(word, c->name, wordlen) && ++which > state)
01205 ret = ast_strdup(c->name);
01206 ast_channel_unlock(c);
01207 }
01208 return ret == ¬found ? NULL : ret;
01209 }
01210
01211 static char *complete_ch_3(const char *line, const char *word, int pos, int state)
01212 {
01213 return ast_complete_channels(line, word, pos, state, 2);
01214 }
01215
01216 static char *complete_ch_4(const char *line, const char *word, int pos, int state)
01217 {
01218 return ast_complete_channels(line, word, pos, state, 3);
01219 }
01220
01221 static char *complete_ch_5(const char *line, const char *word, int pos, int state)
01222 {
01223 return ast_complete_channels(line, word, pos, state, 4);
01224 }
01225
01226 static char *complete_mod_2(const char *line, const char *word, int pos, int state)
01227 {
01228 return ast_module_helper(line, word, pos, state, 1, 1);
01229 }
01230
01231 static char *complete_mod_3_nr(const char *line, const char *word, int pos, int state)
01232 {
01233 return ast_module_helper(line, word, pos, state, 2, 0);
01234 }
01235
01236 static char *complete_mod_3(const char *line, const char *word, int pos, int state)
01237 {
01238 return ast_module_helper(line, word, pos, state, 2, 1);
01239 }
01240
01241 static char *complete_mod_4(const char *line, const char *word, int pos, int state)
01242 {
01243 return ast_module_helper(line, word, pos, state, 3, 0);
01244 }
01245
01246 static char *complete_fn_2(const char *line, const char *word, int pos, int state)
01247 {
01248 char *c;
01249 char filename[256];
01250
01251 if (pos != 1)
01252 return NULL;
01253
01254 if (word[0] == '/')
01255 ast_copy_string(filename, word, sizeof(filename));
01256 else
01257 snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
01258
01259 c = filename_completion_function(filename, state);
01260
01261 if (c && word[0] != '/')
01262 c += (strlen(ast_config_AST_MODULE_DIR) + 1);
01263
01264 return c ? strdup(c) : c;
01265 }
01266
01267 static char *complete_fn_3(const char *line, const char *word, int pos, int state)
01268 {
01269 char *c;
01270 char filename[256];
01271
01272 if (pos != 2)
01273 return NULL;
01274
01275 if (word[0] == '/')
01276 ast_copy_string(filename, word, sizeof(filename));
01277 else
01278 snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
01279
01280 c = filename_completion_function(filename, state);
01281
01282 if (c && word[0] != '/')
01283 c += (strlen(ast_config_AST_MODULE_DIR) + 1);
01284
01285 return c ? strdup(c) : c;
01286 }
01287
01288 static int group_show_channels(int fd, int argc, char *argv[])
01289 {
01290 #define FORMAT_STRING "%-25s %-20s %-20s\n"
01291
01292 struct ast_group_info *gi = NULL;
01293 int numchans = 0;
01294 regex_t regexbuf;
01295 int havepattern = 0;
01296
01297 if (argc < 3 || argc > 4)
01298 return RESULT_SHOWUSAGE;
01299
01300 if (argc == 4) {
01301 if (regcomp(®exbuf, argv[3], REG_EXTENDED | REG_NOSUB))
01302 return RESULT_SHOWUSAGE;
01303 havepattern = 1;
01304 }
01305
01306 ast_cli(fd, FORMAT_STRING, "Channel", "Group", "Category");
01307
01308 ast_app_group_list_lock();
01309
01310 gi = ast_app_group_list_head();
01311 while (gi) {
01312 if (!havepattern || !regexec(®exbuf, gi->group, 0, NULL, 0)) {
01313 ast_cli(fd, FORMAT_STRING, gi->chan->name, gi->group, (ast_strlen_zero(gi->category) ? "(default)" : gi->category));
01314 numchans++;
01315 }
01316 gi = AST_LIST_NEXT(gi, list);
01317 }
01318
01319 ast_app_group_list_unlock();
01320
01321 if (havepattern)
01322 regfree(®exbuf);
01323
01324 ast_cli(fd, "%d active channel%s\n", numchans, (numchans != 1) ? "s" : "");
01325 return RESULT_SUCCESS;
01326 #undef FORMAT_STRING
01327 }
01328
01329 static int handle_help(int fd, int argc, char *argv[]);
01330
01331 static char * complete_help(const char *text, const char *word, int pos, int state)
01332 {
01333
01334 int l = strlen(text);
01335
01336 if (l > 5)
01337 l = 5;
01338 text += l;
01339
01340 return __ast_cli_generator(text, word, state, 0);
01341 }
01342
01343
01344
01345
01346
01347 static struct ast_cli_entry builtins[] = {
01348
01349 { { "_command", "complete", NULL },
01350 handle_commandcomplete, "Command complete",
01351 commandcomplete_help },
01352
01353 { { "_command", "nummatches", NULL },
01354 handle_commandnummatches, "Returns number of command matches",
01355 commandnummatches_help },
01356
01357 { { "_command", "matchesarray", NULL },
01358 handle_commandmatchesarray, "Returns command matches array",
01359 commandmatchesarray_help },
01360
01361 { { NULL }, NULL, NULL, NULL }
01362 };
01363
01364 static struct ast_cli_entry cli_debug_channel_deprecated = {
01365 { "debug", "channel", NULL },
01366 handle_debugchan_deprecated, NULL,
01367 NULL, complete_ch_3 };
01368
01369 static struct ast_cli_entry cli_debug_level_deprecated = {
01370 { "debug", "level", NULL },
01371 handle_debuglevel_deprecated, NULL,
01372 NULL };
01373
01374 static struct ast_cli_entry cli_set_debug_deprecated = {
01375 { "set", "debug", NULL },
01376 handle_set_debug_deprecated, NULL,
01377 NULL, NULL, &cli_debug_level_deprecated };
01378
01379 static struct ast_cli_entry cli_set_verbose_deprecated = {
01380 { "set", "verbose", NULL },
01381 handle_set_verbose_deprecated, NULL,
01382 NULL };
01383
01384 static struct ast_cli_entry cli_show_channel_deprecated = {
01385 { "show", "channel", NULL },
01386 handle_showchan_deprecated, NULL,
01387 NULL, complete_ch_3 };
01388
01389 static struct ast_cli_entry cli_show_channels_deprecated = {
01390 { "show", "channels", NULL },
01391 handle_chanlist_deprecated, NULL,
01392 NULL, complete_show_channels_deprecated };
01393
01394 static struct ast_cli_entry cli_show_modules_deprecated = {
01395 { "show", "modules", NULL },
01396 handle_modlist, NULL,
01397 NULL };
01398
01399 static struct ast_cli_entry cli_show_modules_like_deprecated = {
01400 { "show", "modules", "like", NULL },
01401 handle_modlist, NULL,
01402 NULL, complete_mod_4 };
01403
01404 static struct ast_cli_entry cli_module_load_deprecated = {
01405 { "load", NULL },
01406 handle_load_deprecated, NULL,
01407 NULL, complete_fn_2 };
01408
01409 static struct ast_cli_entry cli_module_reload_deprecated = {
01410 { "reload", NULL },
01411 handle_reload_deprecated, NULL,
01412 NULL, complete_mod_2 };
01413
01414 static struct ast_cli_entry cli_module_unload_deprecated = {
01415 { "unload", NULL },
01416 handle_unload_deprecated, NULL,
01417 NULL, complete_mod_2 };
01418
01419 static struct ast_cli_entry cli_show_uptime_deprecated = {
01420 { "show", "uptime", NULL },
01421 handle_showuptime_deprecated, "Show uptime information",
01422 NULL };
01423
01424 static struct ast_cli_entry cli_cli[] = {
01425
01426 { { "no", "debug", "channel", NULL },
01427 handle_nodebugchan_deprecated, NULL,
01428 NULL, complete_ch_4 },
01429
01430 { { "core", "show", "channels", NULL },
01431 handle_chanlist, "Display information on channels",
01432 chanlist_help, complete_show_channels, &cli_show_channels_deprecated },
01433
01434 { { "core", "show", "channel", NULL },
01435 handle_showchan, "Display information on a specific channel",
01436 showchan_help, complete_ch_4, &cli_show_channel_deprecated },
01437
01438 { { "core", "set", "debug", "channel", NULL },
01439 handle_core_set_debug_channel, "Enable/disable debugging on a channel",
01440 debugchan_help, complete_ch_5, &cli_debug_channel_deprecated },
01441
01442 { { "core", "set", "debug", NULL },
01443 handle_set_debug, "Set level of debug chattiness",
01444 debug_help, NULL, &cli_set_debug_deprecated },
01445
01446 { { "core", "set", "debug", "off", NULL },
01447 handle_nodebug, "Turns off debug chattiness",
01448 nodebug_help },
01449
01450 { { "core", "set", "verbose", NULL },
01451 handle_verbose, "Set level of verboseness",
01452 verbose_help, NULL, &cli_set_verbose_deprecated },
01453
01454 { { "group", "show", "channels", NULL },
01455 group_show_channels, "Display active channels with group(s)",
01456 group_show_channels_help },
01457
01458 { { "help", NULL },
01459 handle_help, "Display help list, or specific help on a command",
01460 help_help, complete_help },
01461
01462 { { "logger", "mute", NULL },
01463 handle_logger_mute, "Toggle logging output to a console",
01464 logger_mute_help },
01465
01466 { { "module", "show", NULL },
01467 handle_modlist, "List modules and info",
01468 modlist_help, NULL, &cli_show_modules_deprecated },
01469
01470 { { "module", "show", "like", NULL },
01471 handle_modlist, "List modules and info",
01472 modlist_help, complete_mod_4, &cli_show_modules_like_deprecated },
01473
01474 { { "module", "load", NULL },
01475 handle_load, "Load a module by name",
01476 load_help, complete_fn_3, &cli_module_load_deprecated },
01477
01478 { { "module", "reload", NULL },
01479 handle_reload, "Reload configuration",
01480 reload_help, complete_mod_3, &cli_module_reload_deprecated },
01481
01482 { { "module", "unload", NULL },
01483 handle_unload, "Unload a module by name",
01484 unload_help, complete_mod_3_nr, &cli_module_unload_deprecated },
01485
01486 { { "core", "show", "uptime", NULL },
01487 handle_showuptime, "Show uptime information",
01488 uptime_help, NULL, &cli_show_uptime_deprecated },
01489
01490 { { "soft", "hangup", NULL },
01491 handle_softhangup, "Request a hangup on a given channel",
01492 softhangup_help, complete_ch_3 },
01493 };
01494
01495
01496 void ast_builtins_init(void)
01497 {
01498 struct ast_cli_entry *e;
01499
01500 for (e = builtins; e->cmda[0] != NULL; e++) {
01501 char buf[80];
01502 ast_join(buf, sizeof(buf), e->cmda);
01503 e->_full_cmd = strdup(buf);
01504 if (!e->_full_cmd)
01505 ast_log(LOG_WARNING, "-- cannot allocate <%s>\n", buf);
01506 }
01507
01508 ast_cli_register_multiple(cli_cli, sizeof(cli_cli) / sizeof(struct ast_cli_entry));
01509 }
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520 struct cli_iterator {
01521 struct ast_cli_entry *builtins;
01522 struct ast_cli_entry *helpers;
01523 };
01524
01525 static struct ast_cli_entry *cli_next(struct cli_iterator *i)
01526 {
01527 struct ast_cli_entry *e;
01528
01529 if (i->builtins == NULL && i->helpers == NULL) {
01530
01531 i->builtins = builtins;
01532 i->helpers = AST_LIST_FIRST(&helpers);
01533 }
01534 e = i->builtins;
01535 if (!e->cmda[0] || (i->helpers &&
01536 strcmp(i->helpers->_full_cmd, e->_full_cmd) < 0)) {
01537
01538 e = i->helpers;
01539 if (e)
01540 i->helpers = AST_LIST_NEXT(e, list);
01541 } else {
01542 (i->builtins)++;
01543 }
01544 return e;
01545 }
01546
01547
01548
01549
01550
01551
01552
01553
01554 static struct ast_cli_entry *find_cli(char *const cmds[], int match_type)
01555 {
01556 int matchlen = -1;
01557 struct ast_cli_entry *cand = NULL, *e=NULL;
01558 struct cli_iterator i = { NULL, NULL};
01559
01560 while( (e = cli_next(&i)) ) {
01561 int y;
01562 for (y = 0 ; cmds[y] && e->cmda[y]; y++) {
01563 if (strcasecmp(e->cmda[y], cmds[y]))
01564 break;
01565 }
01566 if (e->cmda[y] == NULL) {
01567 if (cmds[y] == NULL)
01568 break;
01569
01570 if (match_type != 0)
01571 continue;
01572
01573 } else {
01574 if (cmds[y] == NULL)
01575 continue;
01576
01577 if (match_type == 0)
01578 continue;
01579 if (match_type == 1)
01580 continue;
01581 if (cmds[y+1] != NULL || e->cmda[y+1] != NULL)
01582 continue;
01583
01584 }
01585 if (y > matchlen) {
01586 matchlen = y;
01587 cand = e;
01588 }
01589 }
01590 return e ? e : cand;
01591 }
01592
01593 static char *find_best(char *argv[])
01594 {
01595 static char cmdline[80];
01596 int x;
01597
01598 char *myargv[AST_MAX_CMD_LEN];
01599 for (x=0;x<AST_MAX_CMD_LEN;x++)
01600 myargv[x]=NULL;
01601 AST_LIST_LOCK(&helpers);
01602 for (x=0;argv[x];x++) {
01603 myargv[x] = argv[x];
01604 if (!find_cli(myargv, -1))
01605 break;
01606 }
01607 AST_LIST_UNLOCK(&helpers);
01608 ast_join(cmdline, sizeof(cmdline), myargv);
01609 return cmdline;
01610 }
01611
01612 static int __ast_cli_unregister(struct ast_cli_entry *e, struct ast_cli_entry *ed)
01613 {
01614 if (e->deprecate_cmd) {
01615 __ast_cli_unregister(e->deprecate_cmd, e);
01616 }
01617 if (e->inuse) {
01618 ast_log(LOG_WARNING, "Can't remove command that is in use\n");
01619 } else {
01620 AST_LIST_LOCK(&helpers);
01621 AST_LIST_REMOVE(&helpers, e, list);
01622 AST_LIST_UNLOCK(&helpers);
01623 free(e->_full_cmd);
01624 }
01625 return 0;
01626 }
01627
01628 static int __ast_cli_register(struct ast_cli_entry *e, struct ast_cli_entry *ed)
01629 {
01630 struct ast_cli_entry *cur;
01631 char fulle[80] ="";
01632 int lf, ret = -1;
01633
01634 ast_join(fulle, sizeof(fulle), e->cmda);
01635 AST_LIST_LOCK(&helpers);
01636
01637 if (find_cli(e->cmda, 1)) {
01638 ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n", fulle);
01639 goto done;
01640 }
01641 e->_full_cmd = ast_strdup(fulle);
01642 if (!e->_full_cmd)
01643 goto done;
01644
01645 if (ed) {
01646 e->deprecated = 1;
01647 e->summary = ed->summary;
01648 e->usage = ed->usage;
01649
01650
01651
01652
01653
01654 e->_deprecated_by = S_OR(ed->_deprecated_by, ed->_full_cmd);
01655 } else {
01656 e->deprecated = 0;
01657 }
01658
01659 lf = strlen(fulle);
01660 AST_LIST_TRAVERSE_SAFE_BEGIN(&helpers, cur, list) {
01661 int len = strlen(cur->_full_cmd);
01662 if (lf < len)
01663 len = lf;
01664 if (strncasecmp(fulle, cur->_full_cmd, len) < 0) {
01665 AST_LIST_INSERT_BEFORE_CURRENT(&helpers, e, list);
01666 break;
01667 }
01668 }
01669 AST_LIST_TRAVERSE_SAFE_END;
01670
01671 if (!cur)
01672 AST_LIST_INSERT_TAIL(&helpers, e, list);
01673 ret = 0;
01674
01675 done:
01676 AST_LIST_UNLOCK(&helpers);
01677
01678 if (e->deprecate_cmd) {
01679
01680 __ast_cli_register(e->deprecate_cmd, e);
01681 }
01682
01683 return ret;
01684 }
01685
01686
01687 int ast_cli_unregister(struct ast_cli_entry *e)
01688 {
01689 return __ast_cli_unregister(e, NULL);
01690 }
01691
01692
01693 int ast_cli_register(struct ast_cli_entry *e)
01694 {
01695 return __ast_cli_register(e, NULL);
01696 }
01697
01698
01699
01700
01701 void ast_cli_register_multiple(struct ast_cli_entry *e, int len)
01702 {
01703 int i;
01704
01705 for (i = 0; i < len; i++)
01706 ast_cli_register(e + i);
01707 }
01708
01709 void ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
01710 {
01711 int i;
01712
01713 for (i = 0; i < len; i++)
01714 ast_cli_unregister(e + i);
01715 }
01716
01717
01718
01719
01720
01721
01722
01723 static int help1(int fd, char *match[], int locked)
01724 {
01725 char matchstr[80] = "";
01726 struct ast_cli_entry *e;
01727 int len = 0;
01728 int found = 0;
01729 struct cli_iterator i = { NULL, NULL};
01730
01731 if (match) {
01732 ast_join(matchstr, sizeof(matchstr), match);
01733 len = strlen(matchstr);
01734 }
01735 if (!locked)
01736 AST_LIST_LOCK(&helpers);
01737 while ( (e = cli_next(&i)) ) {
01738
01739 if (e->_full_cmd[0] == '_')
01740 continue;
01741
01742 if (e->deprecated)
01743 continue;
01744 if (match && strncasecmp(matchstr, e->_full_cmd, len))
01745 continue;
01746 ast_cli(fd, "%25.25s %s\n", e->_full_cmd, S_OR(e->summary, ""));
01747 found++;
01748 }
01749 AST_LIST_UNLOCK(&helpers);
01750 if (!locked && !found && matchstr[0])
01751 ast_cli(fd, "No such command '%s'.\n", matchstr);
01752 return 0;
01753 }
01754
01755 static int help_workhorse(int fd, char *match[])
01756 {
01757 return help1(fd, match, 0 );
01758 }
01759
01760 static int handle_help(int fd, int argc, char *argv[])
01761 {
01762 char fullcmd[80];
01763 struct ast_cli_entry *e;
01764
01765 if (argc < 1)
01766 return RESULT_SHOWUSAGE;
01767 if (argc == 1)
01768 return help_workhorse(fd, NULL);
01769
01770 AST_LIST_LOCK(&helpers);
01771 e = find_cli(argv + 1, 1);
01772 if (!e)
01773 return help1(fd, argv + 1, 1 );
01774 if (e->usage)
01775 ast_cli(fd, "%s", e->usage);
01776 else {
01777 ast_join(fullcmd, sizeof(fullcmd), argv+1);
01778 ast_cli(fd, "No help text available for '%s'.\n", fullcmd);
01779 }
01780 AST_LIST_UNLOCK(&helpers);
01781 return RESULT_SUCCESS;
01782 }
01783
01784 static char *parse_args(const char *s, int *argc, char *argv[], int max, int *trailingwhitespace)
01785 {
01786 char *dup, *cur;
01787 int x = 0;
01788 int quoted = 0;
01789 int escaped = 0;
01790 int whitespace = 1;
01791
01792 *trailingwhitespace = 0;
01793 if (s == NULL)
01794 return NULL;
01795
01796 if (!(dup = ast_strdup(s)))
01797 return NULL;
01798
01799 cur = dup;
01800
01801 for (; *s ; s++) {
01802 if (x >= max - 1) {
01803 ast_log(LOG_WARNING, "Too many arguments, truncating at %s\n", s);
01804 break;
01805 }
01806 if (*s == '"' && !escaped) {
01807 quoted = !quoted;
01808 if (quoted && whitespace) {
01809
01810 argv[x++] = cur;
01811 whitespace = 0;
01812 }
01813 } else if ((*s == ' ' || *s == '\t') && !(quoted || escaped)) {
01814
01815
01816
01817
01818 if (!whitespace) {
01819 *cur++ = '\0';
01820 whitespace = 1;
01821 }
01822 } else if (*s == '\\' && !escaped) {
01823 escaped = 1;
01824 } else {
01825 if (whitespace) {
01826
01827 argv[x++] = cur;
01828 whitespace = 0;
01829 }
01830 *cur++ = *s;
01831 escaped = 0;
01832 }
01833 }
01834
01835 *cur++ = '\0';
01836
01837
01838
01839
01840 argv[x] = NULL;
01841 *argc = x;
01842 *trailingwhitespace = whitespace;
01843 return dup;
01844 }
01845
01846
01847 int ast_cli_generatornummatches(const char *text, const char *word)
01848 {
01849 int matches = 0, i = 0;
01850 char *buf = NULL, *oldbuf = NULL;
01851
01852 while ((buf = ast_cli_generator(text, word, i++))) {
01853 if (!oldbuf || strcmp(buf,oldbuf))
01854 matches++;
01855 if (oldbuf)
01856 free(oldbuf);
01857 oldbuf = buf;
01858 }
01859 if (oldbuf)
01860 free(oldbuf);
01861 return matches;
01862 }
01863
01864 char **ast_cli_completion_matches(const char *text, const char *word)
01865 {
01866 char **match_list = NULL, *retstr, *prevstr;
01867 size_t match_list_len, max_equal, which, i;
01868 int matches = 0;
01869
01870
01871 match_list_len = 1;
01872 while ((retstr = ast_cli_generator(text, word, matches)) != NULL) {
01873 if (matches + 1 >= match_list_len) {
01874 match_list_len <<= 1;
01875 if (!(match_list = ast_realloc(match_list, match_list_len * sizeof(*match_list))))
01876 return NULL;
01877 }
01878 match_list[++matches] = retstr;
01879 }
01880
01881 if (!match_list)
01882 return match_list;
01883
01884
01885
01886
01887 prevstr = match_list[1];
01888 max_equal = strlen(prevstr);
01889 for (which = 2; which <= matches; which++) {
01890 for (i = 0; i < max_equal && toupper(prevstr[i]) == toupper(match_list[which][i]); i++)
01891 continue;
01892 max_equal = i;
01893 }
01894
01895 if (!(retstr = ast_malloc(max_equal + 1)))
01896 return NULL;
01897
01898 ast_copy_string(retstr, match_list[1], max_equal + 1);
01899 match_list[0] = retstr;
01900
01901
01902 if (matches + 1 >= match_list_len) {
01903 if (!(match_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(*match_list))))
01904 return NULL;
01905 }
01906 match_list[matches + 1] = NULL;
01907
01908 return match_list;
01909 }
01910
01911 static char *__ast_cli_generator(const char *text, const char *word, int state, int lock)
01912 {
01913 char *argv[AST_MAX_ARGS];
01914 struct ast_cli_entry *e;
01915 struct cli_iterator i = { NULL, NULL };
01916 int x = 0, argindex, matchlen;
01917 int matchnum=0;
01918 char *ret = NULL;
01919 char matchstr[80] = "";
01920 int tws = 0;
01921 char *dup = parse_args(text, &x, argv, sizeof(argv) / sizeof(argv[0]), &tws);
01922
01923 if (!dup)
01924 return NULL;
01925 argindex = (!ast_strlen_zero(word) && x>0) ? x-1 : x;
01926
01927 ast_join(matchstr, sizeof(matchstr)-1, argv);
01928 matchlen = strlen(matchstr);
01929 if (tws) {
01930 strcat(matchstr, " ");
01931 if (matchlen)
01932 matchlen++;
01933 }
01934 if (lock)
01935 AST_LIST_LOCK(&helpers);
01936 while( !ret && (e = cli_next(&i)) ) {
01937 int lc = strlen(e->_full_cmd);
01938 if (e->_full_cmd[0] != '_' && lc > 0 && matchlen <= lc &&
01939 !strncasecmp(matchstr, e->_full_cmd, matchlen)) {
01940
01941 if (e->cmda[argindex] && ++matchnum > state)
01942 ret = strdup(e->cmda[argindex]);
01943 } else if (e->generator && !strncasecmp(matchstr, e->_full_cmd, lc) && matchstr[lc] < 33) {
01944
01945
01946 ret = e->generator(matchstr, word, argindex, state);
01947 }
01948 }
01949 if (lock)
01950 AST_LIST_UNLOCK(&helpers);
01951 free(dup);
01952 return ret;
01953 }
01954
01955 char *ast_cli_generator(const char *text, const char *word, int state)
01956 {
01957 return __ast_cli_generator(text, word, state, 1);
01958 }
01959
01960 int ast_cli_command(int fd, const char *s)
01961 {
01962 char *argv[AST_MAX_ARGS];
01963 struct ast_cli_entry *e;
01964 int x;
01965 char *dup;
01966 int tws;
01967
01968 if (!(dup = parse_args(s, &x, argv, sizeof(argv) / sizeof(argv[0]), &tws)))
01969 return -1;
01970
01971
01972 if (x > 0) {
01973 AST_LIST_LOCK(&helpers);
01974 e = find_cli(argv, 0);
01975 if (e)
01976 e->inuse++;
01977 AST_LIST_UNLOCK(&helpers);
01978 if (e) {
01979 switch(e->handler(fd, x, argv)) {
01980 case RESULT_SHOWUSAGE:
01981 if (e->usage)
01982 ast_cli(fd, "%s", e->usage);
01983 else
01984 ast_cli(fd, "Invalid usage, but no usage information available.\n");
01985 AST_LIST_LOCK(&helpers);
01986 if (e->deprecated)
01987 ast_cli(fd, "The '%s' command is deprecated and will be removed in a future release. Please use '%s' instead.\n", e->_full_cmd, e->_deprecated_by);
01988 AST_LIST_UNLOCK(&helpers);
01989 break;
01990 default:
01991 AST_LIST_LOCK(&helpers);
01992 if (e->deprecated == 1) {
01993 ast_cli(fd, "The '%s' command is deprecated and will be removed in a future release. Please use '%s' instead.\n", e->_full_cmd, e->_deprecated_by);
01994 e->deprecated = 2;
01995 }
01996 AST_LIST_UNLOCK(&helpers);
01997 break;
01998 }
01999 } else
02000 ast_cli(fd, "No such command '%s' (type 'help' for help)\n", find_best(argv));
02001 if (e)
02002 ast_atomic_fetchadd_int(&e->inuse, -1);
02003 }
02004 free(dup);
02005
02006 return 0;
02007 }