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