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 char cg[256], pg[256];
01007 long elapsed_seconds=0;
01008 int hour=0, min=0, sec=0;
01009
01010 if (argc != 3)
01011 return RESULT_SHOWUSAGE;
01012 now = ast_tvnow();
01013 c = ast_get_channel_by_name_locked(argv[2]);
01014 if (!c) {
01015 ast_cli(fd, "%s is not a known channel\n", argv[2]);
01016 return RESULT_SUCCESS;
01017 }
01018 if(c->cdr) {
01019 elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
01020 hour = elapsed_seconds / 3600;
01021 min = (elapsed_seconds % 3600) / 60;
01022 sec = elapsed_seconds % 60;
01023 snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
01024 } else
01025 strcpy(cdrtime, "N/A");
01026 ast_cli(fd,
01027 " -- General --\n"
01028 " Name: %s\n"
01029 " Type: %s\n"
01030 " UniqueID: %s\n"
01031 " Caller ID: %s\n"
01032 " Caller ID Name: %s\n"
01033 " DNID Digits: %s\n"
01034 " State: %s (%d)\n"
01035 " Rings: %d\n"
01036 " NativeFormats: %s\n"
01037 " WriteFormat: %s\n"
01038 " ReadFormat: %s\n"
01039 " WriteTranscode: %s\n"
01040 " ReadTranscode: %s\n"
01041 "1st File Descriptor: %d\n"
01042 " Frames in: %d%s\n"
01043 " Frames out: %d%s\n"
01044 " Time to Hangup: %ld\n"
01045 " Elapsed Time: %s\n"
01046 " Direct Bridge: %s\n"
01047 "Indirect Bridge: %s\n"
01048 " -- PBX --\n"
01049 " Context: %s\n"
01050 " Extension: %s\n"
01051 " Priority: %d\n"
01052 " Call Group: %s\n"
01053 " Pickup Group: %s\n"
01054 " Application: %s\n"
01055 " Data: %s\n"
01056 " Blocking in: %s\n",
01057 c->name, c->tech->type, c->uniqueid,
01058 S_OR(c->cid.cid_num, "(N/A)"),
01059 S_OR(c->cid.cid_name, "(N/A)"),
01060 S_OR(c->cid.cid_dnid, "(N/A)"), ast_state2str(c->_state), c->_state, c->rings,
01061 ast_getformatname_multiple(nf, sizeof(nf), c->nativeformats),
01062 ast_getformatname_multiple(wf, sizeof(wf), c->writeformat),
01063 ast_getformatname_multiple(rf, sizeof(rf), c->readformat),
01064 c->writetrans ? "Yes" : "No",
01065 c->readtrans ? "Yes" : "No",
01066 c->fds[0],
01067 c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
01068 c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
01069 (long)c->whentohangup,
01070 cdrtime, c->_bridge ? c->_bridge->name : "<none>", ast_bridged_channel(c) ? ast_bridged_channel(c)->name : "<none>",
01071 c->context, c->exten, c->priority, ast_print_group(cg, sizeof(cg), &c->callgroup), ast_print_group(pg, sizeof(pg), &c->pickupgroup),
01072 ( c->appl ? c->appl : "(N/A)" ), ( c-> data ? S_OR(c->data, "(Empty)") : "(None)"),
01073 (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
01074
01075 if(pbx_builtin_serialize_variables(c,buf,sizeof(buf)))
01076 ast_cli(fd," Variables:\n%s\n",buf);
01077 if(c->cdr && ast_cdr_serialize_variables(c->cdr,buf, sizeof(buf), '=', '\n', 1))
01078 ast_cli(fd," CDR Variables:\n%s\n",buf);
01079
01080 ast_channel_unlock(c);
01081 return RESULT_SUCCESS;
01082 }
01083
01084 static int handle_showchan(int fd, int argc, char *argv[])
01085 {
01086 struct ast_channel *c=NULL;
01087 struct timeval now;
01088 char buf[2048];
01089 char cdrtime[256];
01090 char nf[256], wf[256], rf[256];
01091 char cg[256], pg[256];
01092 long elapsed_seconds=0;
01093 int hour=0, min=0, sec=0;
01094
01095 if (argc != 4)
01096 return RESULT_SHOWUSAGE;
01097 now = ast_tvnow();
01098 c = ast_get_channel_by_name_locked(argv[3]);
01099 if (!c) {
01100 ast_cli(fd, "%s is not a known channel\n", argv[3]);
01101 return RESULT_SUCCESS;
01102 }
01103 if(c->cdr) {
01104 elapsed_seconds = now.tv_sec - c->cdr->start.tv_sec;
01105 hour = elapsed_seconds / 3600;
01106 min = (elapsed_seconds % 3600) / 60;
01107 sec = elapsed_seconds % 60;
01108 snprintf(cdrtime, sizeof(cdrtime), "%dh%dm%ds", hour, min, sec);
01109 } else
01110 strcpy(cdrtime, "N/A");
01111 ast_cli(fd,
01112 " -- General --\n"
01113 " Name: %s\n"
01114 " Type: %s\n"
01115 " UniqueID: %s\n"
01116 " Caller ID: %s\n"
01117 " Caller ID Name: %s\n"
01118 " DNID Digits: %s\n"
01119 " State: %s (%d)\n"
01120 " Rings: %d\n"
01121 " NativeFormats: %s\n"
01122 " WriteFormat: %s\n"
01123 " ReadFormat: %s\n"
01124 " WriteTranscode: %s\n"
01125 " ReadTranscode: %s\n"
01126 "1st File Descriptor: %d\n"
01127 " Frames in: %d%s\n"
01128 " Frames out: %d%s\n"
01129 " Time to Hangup: %ld\n"
01130 " Elapsed Time: %s\n"
01131 " Direct Bridge: %s\n"
01132 "Indirect Bridge: %s\n"
01133 " -- PBX --\n"
01134 " Context: %s\n"
01135 " Extension: %s\n"
01136 " Priority: %d\n"
01137 " Call Group: %s\n"
01138 " Pickup Group: %s\n"
01139 " Application: %s\n"
01140 " Data: %s\n"
01141 " Blocking in: %s\n",
01142 c->name, c->tech->type, c->uniqueid,
01143 S_OR(c->cid.cid_num, "(N/A)"),
01144 S_OR(c->cid.cid_name, "(N/A)"),
01145 S_OR(c->cid.cid_dnid, "(N/A)"), ast_state2str(c->_state), c->_state, c->rings,
01146 ast_getformatname_multiple(nf, sizeof(nf), c->nativeformats),
01147 ast_getformatname_multiple(wf, sizeof(wf), c->writeformat),
01148 ast_getformatname_multiple(rf, sizeof(rf), c->readformat),
01149 c->writetrans ? "Yes" : "No",
01150 c->readtrans ? "Yes" : "No",
01151 c->fds[0],
01152 c->fin & ~DEBUGCHAN_FLAG, (c->fin & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
01153 c->fout & ~DEBUGCHAN_FLAG, (c->fout & DEBUGCHAN_FLAG) ? " (DEBUGGED)" : "",
01154 (long)c->whentohangup,
01155 cdrtime, c->_bridge ? c->_bridge->name : "<none>", ast_bridged_channel(c) ? ast_bridged_channel(c)->name : "<none>",
01156 c->context, c->exten, c->priority, ast_print_group(cg, sizeof(cg), &c->callgroup), ast_print_group(pg, sizeof(pg), &c->pickupgroup),
01157 ( c->appl ? c->appl : "(N/A)" ), ( c-> data ? S_OR(c->data, "(Empty)") : "(None)"),
01158 (ast_test_flag(c, AST_FLAG_BLOCKING) ? c->blockproc : "(Not Blocking)"));
01159
01160 if(pbx_builtin_serialize_variables(c,buf,sizeof(buf)))
01161 ast_cli(fd," Variables:\n%s\n",buf);
01162 if(c->cdr && ast_cdr_serialize_variables(c->cdr,buf, sizeof(buf), '=', '\n', 1))
01163 ast_cli(fd," CDR Variables:\n%s\n",buf);
01164
01165 ast_channel_unlock(c);
01166 return RESULT_SUCCESS;
01167 }
01168
01169
01170
01171
01172
01173 char *ast_cli_complete(const char *word, char *const choices[], int state)
01174 {
01175 int i, which = 0, len;
01176 len = ast_strlen_zero(word) ? 0 : strlen(word);
01177
01178 for (i = 0; choices[i]; i++) {
01179 if ((!len || !strncasecmp(word, choices[i], len)) && ++which > state)
01180 return ast_strdup(choices[i]);
01181 }
01182 return NULL;
01183 }
01184
01185 static char *complete_show_channels_deprecated(const char *line, const char *word, int pos, int state)
01186 {
01187 static char *choices[] = { "concise", "verbose", NULL };
01188
01189 return (pos != 2) ? NULL : ast_cli_complete(word, choices, state);
01190 }
01191
01192 static char *complete_show_channels(const char *line, const char *word, int pos, int state)
01193 {
01194 static char *choices[] = { "concise", "verbose", NULL };
01195
01196 return (pos != 3) ? NULL : ast_cli_complete(word, choices, state);
01197 }
01198
01199 char *ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
01200 {
01201 struct ast_channel *c = NULL;
01202 int which = 0;
01203 int wordlen;
01204 char notfound = '\0';
01205 char *ret = ¬found;
01206
01207 if (pos != rpos)
01208 return NULL;
01209
01210 wordlen = strlen(word);
01211
01212 while (ret == ¬found && (c = ast_channel_walk_locked(c))) {
01213 if (!strncasecmp(word, c->name, wordlen) && ++which > state)
01214 ret = ast_strdup(c->name);
01215 ast_channel_unlock(c);
01216 }
01217 return ret == ¬found ? NULL : ret;
01218 }
01219
01220 static char *complete_ch_3(const char *line, const char *word, int pos, int state)
01221 {
01222 return ast_complete_channels(line, word, pos, state, 2);
01223 }
01224
01225 static char *complete_ch_4(const char *line, const char *word, int pos, int state)
01226 {
01227 return ast_complete_channels(line, word, pos, state, 3);
01228 }
01229
01230 static char *complete_ch_5(const char *line, const char *word, int pos, int state)
01231 {
01232 return ast_complete_channels(line, word, pos, state, 4);
01233 }
01234
01235 static char *complete_mod_2(const char *line, const char *word, int pos, int state)
01236 {
01237 return ast_module_helper(line, word, pos, state, 1, 1);
01238 }
01239
01240 static char *complete_mod_2_nr(const char *line, const char *word, int pos, int state)
01241 {
01242 return ast_module_helper(line, word, pos, state, 1, 0);
01243 }
01244
01245 static char *complete_mod_3_nr(const char *line, const char *word, int pos, int state)
01246 {
01247 return ast_module_helper(line, word, pos, state, 2, 0);
01248 }
01249
01250 static char *complete_mod_3(const char *line, const char *word, int pos, int state)
01251 {
01252 return ast_module_helper(line, word, pos, state, 2, 1);
01253 }
01254
01255 static char *complete_mod_4(const char *line, const char *word, int pos, int state)
01256 {
01257 return ast_module_helper(line, word, pos, state, 3, 0);
01258 }
01259
01260 static char *complete_fn_2(const char *line, const char *word, int pos, int state)
01261 {
01262 char *c, *d;
01263 char filename[PATH_MAX];
01264
01265 if (pos != 1)
01266 return NULL;
01267
01268 if (word[0] == '/')
01269 ast_copy_string(filename, word, sizeof(filename));
01270 else
01271 snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
01272
01273 c = d = filename_completion_function(filename, state);
01274
01275 if (c && word[0] != '/')
01276 c += (strlen(ast_config_AST_MODULE_DIR) + 1);
01277 if (c)
01278 c = strdup(c);
01279 free(d);
01280
01281 return c;
01282 }
01283
01284 static char *complete_fn_3(const char *line, const char *word, int pos, int state)
01285 {
01286 char *c, *d;
01287 char filename[PATH_MAX];
01288
01289 if (pos != 2)
01290 return NULL;
01291
01292 if (word[0] == '/')
01293 ast_copy_string(filename, word, sizeof(filename));
01294 else
01295 snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word);
01296
01297 c = d = filename_completion_function(filename, state);
01298
01299 if (c && word[0] != '/')
01300 c += (strlen(ast_config_AST_MODULE_DIR) + 1);
01301 if (c)
01302 c = strdup(c);
01303
01304 free(d);
01305
01306 return c;
01307 }
01308
01309 static int group_show_channels(int fd, int argc, char *argv[])
01310 {
01311 #define FORMAT_STRING "%-25s %-20s %-20s\n"
01312
01313 struct ast_group_info *gi = NULL;
01314 int numchans = 0;
01315 regex_t regexbuf;
01316 int havepattern = 0;
01317
01318 if (argc < 3 || argc > 4)
01319 return RESULT_SHOWUSAGE;
01320
01321 if (argc == 4) {
01322 if (regcomp(®exbuf, argv[3], REG_EXTENDED | REG_NOSUB))
01323 return RESULT_SHOWUSAGE;
01324 havepattern = 1;
01325 }
01326
01327 ast_cli(fd, FORMAT_STRING, "Channel", "Group", "Category");
01328
01329 ast_app_group_list_lock();
01330
01331 gi = ast_app_group_list_head();
01332 while (gi) {
01333 if (!havepattern || !regexec(®exbuf, gi->group, 0, NULL, 0)) {
01334 ast_cli(fd, FORMAT_STRING, gi->chan->name, gi->group, (ast_strlen_zero(gi->category) ? "(default)" : gi->category));
01335 numchans++;
01336 }
01337 gi = AST_LIST_NEXT(gi, list);
01338 }
01339
01340 ast_app_group_list_unlock();
01341
01342 if (havepattern)
01343 regfree(®exbuf);
01344
01345 ast_cli(fd, "%d active channel%s\n", numchans, (numchans != 1) ? "s" : "");
01346 return RESULT_SUCCESS;
01347 #undef FORMAT_STRING
01348 }
01349
01350 static int handle_cli_wait_fullybooted(int fd, int argc, char *argv[])
01351 {
01352 while (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
01353 usleep(100);
01354 }
01355
01356 ast_cli(fd, "Asterisk has fully booted.\n");
01357
01358 return RESULT_SUCCESS;
01359 }
01360
01361 static int handle_help(int fd, int argc, char *argv[]);
01362
01363 static char * complete_help(const char *text, const char *word, int pos, int state)
01364 {
01365
01366 int l = strlen(text);
01367
01368 if (l > 5)
01369 l = 5;
01370 text += l;
01371
01372 return __ast_cli_generator(text, word, state, 0);
01373 }
01374
01375
01376
01377
01378
01379 static struct ast_cli_entry builtins[] = {
01380
01381 { { "_command", "complete", NULL },
01382 handle_commandcomplete, "Command complete",
01383 commandcomplete_help },
01384
01385 { { "_command", "nummatches", NULL },
01386 handle_commandnummatches, "Returns number of command matches",
01387 commandnummatches_help },
01388
01389 { { "_command", "matchesarray", NULL },
01390 handle_commandmatchesarray, "Returns command matches array",
01391 commandmatchesarray_help },
01392
01393 { { NULL }, NULL, NULL, NULL }
01394 };
01395
01396 static struct ast_cli_entry cli_debug_channel_deprecated = {
01397 { "debug", "channel", NULL },
01398 handle_debugchan_deprecated, NULL,
01399 NULL, complete_ch_3 };
01400
01401 static struct ast_cli_entry cli_debug_level_deprecated = {
01402 { "debug", "level", NULL },
01403 handle_debuglevel_deprecated, NULL,
01404 NULL };
01405
01406 static struct ast_cli_entry cli_set_debug_deprecated = {
01407 { "set", "debug", NULL },
01408 handle_set_debug_deprecated, NULL,
01409 NULL, NULL, &cli_debug_level_deprecated };
01410
01411 static struct ast_cli_entry cli_set_verbose_deprecated = {
01412 { "set", "verbose", NULL },
01413 handle_set_verbose_deprecated, NULL,
01414 NULL };
01415
01416 static struct ast_cli_entry cli_show_channel_deprecated = {
01417 { "show", "channel", NULL },
01418 handle_showchan_deprecated, NULL,
01419 NULL, complete_ch_3 };
01420
01421 static struct ast_cli_entry cli_show_channels_deprecated = {
01422 { "show", "channels", NULL },
01423 handle_chanlist_deprecated, NULL,
01424 NULL, complete_show_channels_deprecated };
01425
01426 static struct ast_cli_entry cli_show_modules_deprecated = {
01427 { "show", "modules", NULL },
01428 handle_modlist, NULL,
01429 NULL };
01430
01431 static struct ast_cli_entry cli_show_modules_like_deprecated = {
01432 { "show", "modules", "like", NULL },
01433 handle_modlist, NULL,
01434 NULL, complete_mod_4 };
01435
01436 static struct ast_cli_entry cli_module_load_deprecated = {
01437 { "load", NULL },
01438 handle_load_deprecated, NULL,
01439 NULL, complete_fn_2 };
01440
01441 static struct ast_cli_entry cli_module_reload_deprecated = {
01442 { "reload", NULL },
01443 handle_reload_deprecated, NULL,
01444 NULL, complete_mod_2 };
01445
01446 static struct ast_cli_entry cli_module_unload_deprecated = {
01447 { "unload", NULL },
01448 handle_unload_deprecated, NULL,
01449 NULL, complete_mod_2_nr };
01450
01451 static struct ast_cli_entry cli_show_uptime_deprecated = {
01452 { "show", "uptime", NULL },
01453 handle_showuptime_deprecated, "Show uptime information",
01454 NULL };
01455
01456 static struct ast_cli_entry cli_cli[] = {
01457
01458 { { "no", "debug", "channel", NULL },
01459 handle_nodebugchan_deprecated, NULL,
01460 NULL, complete_ch_4 },
01461
01462 { { "core", "show", "channels", NULL },
01463 handle_chanlist, "Display information on channels",
01464 chanlist_help, complete_show_channels, &cli_show_channels_deprecated },
01465
01466 { { "core", "show", "channel", NULL },
01467 handle_showchan, "Display information on a specific channel",
01468 showchan_help, complete_ch_4, &cli_show_channel_deprecated },
01469
01470 { { "core", "set", "debug", "channel", NULL },
01471 handle_core_set_debug_channel, "Enable/disable debugging on a channel",
01472 debugchan_help, complete_ch_5, &cli_debug_channel_deprecated },
01473
01474 { { "core", "set", "debug", NULL },
01475 handle_set_debug, "Set level of debug chattiness",
01476 debug_help, NULL, &cli_set_debug_deprecated },
01477
01478 { { "core", "set", "debug", "off", NULL },
01479 handle_nodebug, "Turns off debug chattiness",
01480 nodebug_help },
01481
01482 { { "core", "set", "verbose", NULL },
01483 handle_verbose, "Set level of verboseness",
01484 verbose_help, NULL, &cli_set_verbose_deprecated },
01485
01486 { { "group", "show", "channels", NULL },
01487 group_show_channels, "Display active channels with group(s)",
01488 group_show_channels_help },
01489
01490 { { "help", NULL },
01491 handle_help, "Display help list, or specific help on a command",
01492 help_help, complete_help },
01493
01494 { { "logger", "mute", NULL },
01495 handle_logger_mute, "Toggle logging output to a console",
01496 logger_mute_help },
01497
01498 { { "module", "show", NULL },
01499 handle_modlist, "List modules and info",
01500 modlist_help, NULL, &cli_show_modules_deprecated },
01501
01502 { { "module", "show", "like", NULL },
01503 handle_modlist, "List modules and info",
01504 modlist_help, complete_mod_4, &cli_show_modules_like_deprecated },
01505
01506 { { "module", "load", NULL },
01507 handle_load, "Load a module by name",
01508 load_help, complete_fn_3, &cli_module_load_deprecated },
01509
01510 { { "module", "reload", NULL },
01511 handle_reload, "Reload configuration",
01512 reload_help, complete_mod_3, &cli_module_reload_deprecated },
01513
01514 { { "module", "unload", NULL },
01515 handle_unload, "Unload a module by name",
01516 unload_help, complete_mod_3_nr, &cli_module_unload_deprecated },
01517
01518 { { "core", "show", "uptime", NULL },
01519 handle_showuptime, "Show uptime information",
01520 uptime_help, NULL, &cli_show_uptime_deprecated },
01521
01522 { { "soft", "hangup", NULL },
01523 handle_softhangup, "Request a hangup on a given channel",
01524 softhangup_help, complete_ch_3 },
01525
01526 { { "core", "waitfullybooted", NULL },
01527 handle_cli_wait_fullybooted, "Wait until Asterisk has fully booted.",
01528 core_wait_fullybooted_help },
01529 };
01530
01531
01532 void ast_builtins_init(void)
01533 {
01534 struct ast_cli_entry *e;
01535
01536 for (e = builtins; e->cmda[0] != NULL; e++) {
01537 char buf[80];
01538 ast_join(buf, sizeof(buf), e->cmda);
01539 e->_full_cmd = strdup(buf);
01540 if (!e->_full_cmd)
01541 ast_log(LOG_WARNING, "-- cannot allocate <%s>\n", buf);
01542 }
01543
01544 ast_cli_register_multiple(cli_cli, sizeof(cli_cli) / sizeof(struct ast_cli_entry));
01545 }
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556 struct cli_iterator {
01557 struct ast_cli_entry *builtins;
01558 struct ast_cli_entry *helpers;
01559 };
01560
01561 static struct ast_cli_entry *cli_next(struct cli_iterator *i)
01562 {
01563 struct ast_cli_entry *e;
01564
01565 if (i->builtins == NULL && i->helpers == NULL) {
01566
01567 i->builtins = builtins;
01568 i->helpers = AST_LIST_FIRST(&helpers);
01569 }
01570 e = i->builtins;
01571 if (!e->cmda[0] || (i->helpers &&
01572 strcmp(i->helpers->_full_cmd, e->_full_cmd) < 0)) {
01573
01574 e = i->helpers;
01575 if (e)
01576 i->helpers = AST_LIST_NEXT(e, list);
01577 } else {
01578 (i->builtins)++;
01579 }
01580 return e;
01581 }
01582
01583
01584
01585
01586
01587
01588
01589
01590 static struct ast_cli_entry *find_cli(char *const cmds[], int match_type)
01591 {
01592 int matchlen = -1;
01593 struct ast_cli_entry *cand = NULL, *e=NULL;
01594 struct cli_iterator i = { NULL, NULL};
01595
01596 while( (e = cli_next(&i)) ) {
01597 int y;
01598 for (y = 0 ; cmds[y] && e->cmda[y]; y++) {
01599 if (strcasecmp(e->cmda[y], cmds[y]))
01600 break;
01601 }
01602 if (e->cmda[y] == NULL) {
01603 if (cmds[y] == NULL)
01604 break;
01605
01606 if (match_type != 0)
01607 continue;
01608
01609 } else {
01610 if (cmds[y] == NULL)
01611 continue;
01612
01613 if (match_type == 0)
01614 continue;
01615 if (match_type == 1)
01616 continue;
01617 if (cmds[y+1] != NULL || e->cmda[y+1] != NULL)
01618 continue;
01619
01620 }
01621 if (y > matchlen) {
01622 matchlen = y;
01623 cand = e;
01624 }
01625 }
01626 return e ? e : cand;
01627 }
01628
01629 static char *find_best(char *argv[])
01630 {
01631 static char cmdline[80];
01632 int x;
01633
01634 char *myargv[AST_MAX_CMD_LEN];
01635 for (x=0;x<AST_MAX_CMD_LEN;x++)
01636 myargv[x]=NULL;
01637 AST_LIST_LOCK(&helpers);
01638 for (x=0;argv[x];x++) {
01639 myargv[x] = argv[x];
01640 if (!find_cli(myargv, -1))
01641 break;
01642 }
01643 AST_LIST_UNLOCK(&helpers);
01644 ast_join(cmdline, sizeof(cmdline), myargv);
01645 return cmdline;
01646 }
01647
01648 static int __ast_cli_unregister(struct ast_cli_entry *e, struct ast_cli_entry *ed)
01649 {
01650 if (e->deprecate_cmd) {
01651 __ast_cli_unregister(e->deprecate_cmd, e);
01652 }
01653 if (e->inuse) {
01654 ast_log(LOG_WARNING, "Can't remove command that is in use\n");
01655 } else {
01656 AST_LIST_LOCK(&helpers);
01657 AST_LIST_REMOVE(&helpers, e, list);
01658 AST_LIST_UNLOCK(&helpers);
01659 free(e->_full_cmd);
01660 }
01661 return 0;
01662 }
01663
01664 static int __ast_cli_register(struct ast_cli_entry *e, struct ast_cli_entry *ed)
01665 {
01666 struct ast_cli_entry *cur;
01667 char fulle[80] ="";
01668 int lf, ret = -1;
01669
01670 ast_join(fulle, sizeof(fulle), e->cmda);
01671 AST_LIST_LOCK(&helpers);
01672
01673 if (find_cli(e->cmda, 1)) {
01674 ast_log(LOG_WARNING, "Command '%s' already registered (or something close enough)\n", fulle);
01675 goto done;
01676 }
01677 e->_full_cmd = ast_strdup(fulle);
01678 if (!e->_full_cmd)
01679 goto done;
01680
01681 if (ed) {
01682 e->deprecated = 1;
01683 e->summary = ed->summary;
01684 e->usage = ed->usage;
01685
01686
01687
01688
01689
01690 e->_deprecated_by = S_OR(ed->_deprecated_by, ed->_full_cmd);
01691 } else {
01692 e->deprecated = 0;
01693 }
01694
01695 lf = strlen(fulle);
01696 AST_LIST_TRAVERSE_SAFE_BEGIN(&helpers, cur, list) {
01697 int len = strlen(cur->_full_cmd);
01698 if (lf < len)
01699 len = lf;
01700 if (strncasecmp(fulle, cur->_full_cmd, len) < 0) {
01701 AST_LIST_INSERT_BEFORE_CURRENT(&helpers, e, list);
01702 break;
01703 }
01704 }
01705 AST_LIST_TRAVERSE_SAFE_END;
01706
01707 if (!cur)
01708 AST_LIST_INSERT_TAIL(&helpers, e, list);
01709 ret = 0;
01710
01711 done:
01712 AST_LIST_UNLOCK(&helpers);
01713
01714 if (e->deprecate_cmd) {
01715
01716 __ast_cli_register(e->deprecate_cmd, e);
01717 }
01718
01719 return ret;
01720 }
01721
01722
01723 int ast_cli_unregister(struct ast_cli_entry *e)
01724 {
01725 return __ast_cli_unregister(e, NULL);
01726 }
01727
01728
01729 int ast_cli_register(struct ast_cli_entry *e)
01730 {
01731 return __ast_cli_register(e, NULL);
01732 }
01733
01734
01735
01736
01737 void ast_cli_register_multiple(struct ast_cli_entry *e, int len)
01738 {
01739 int i;
01740
01741 for (i = 0; i < len; i++)
01742 ast_cli_register(e + i);
01743 }
01744
01745 void ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
01746 {
01747 int i;
01748
01749 for (i = 0; i < len; i++)
01750 ast_cli_unregister(e + i);
01751 }
01752
01753
01754
01755
01756
01757
01758 static int help1(int fd, char *match[], int locked)
01759 {
01760 char matchstr[80] = "";
01761 struct ast_cli_entry *e;
01762 int len = 0;
01763 int found = 0;
01764 struct cli_iterator i = { NULL, NULL};
01765
01766 if (match) {
01767 ast_join(matchstr, sizeof(matchstr), match);
01768 len = strlen(matchstr);
01769 }
01770 if (!locked)
01771 AST_LIST_LOCK(&helpers);
01772 while ( (e = cli_next(&i)) ) {
01773
01774 if (e->_full_cmd[0] == '_')
01775 continue;
01776
01777 if (e->deprecated)
01778 continue;
01779 if (match && strncasecmp(matchstr, e->_full_cmd, len))
01780 continue;
01781 ast_cli(fd, "%25.25s %s\n", e->_full_cmd, S_OR(e->summary, ""));
01782 found++;
01783 }
01784 if (!locked)
01785 AST_LIST_UNLOCK(&helpers);
01786 if (!found && matchstr[0])
01787 ast_cli(fd, "No such command '%s'.\n", matchstr);
01788 return RESULT_SUCCESS;
01789 }
01790
01791 static int help_workhorse(int fd, char *match[])
01792 {
01793 return help1(fd, match, 0 );
01794 }
01795
01796 static int handle_help(int fd, int argc, char *argv[])
01797 {
01798 char fullcmd[80];
01799 struct ast_cli_entry *e;
01800 int res = RESULT_SUCCESS;
01801
01802 if (argc < 1)
01803 return RESULT_SHOWUSAGE;
01804 if (argc == 1)
01805 return help_workhorse(fd, NULL);
01806
01807 AST_LIST_LOCK(&helpers);
01808 e = find_cli(argv + 1, 1);
01809 if (!e) {
01810 res = help1(fd, argv + 1, 1 );
01811 AST_LIST_UNLOCK(&helpers);
01812 return res;
01813 }
01814 if (e->usage)
01815 ast_cli(fd, "%s", e->usage);
01816 else {
01817 ast_join(fullcmd, sizeof(fullcmd), argv+1);
01818 ast_cli(fd, "No help text available for '%s'.\n", fullcmd);
01819 }
01820 AST_LIST_UNLOCK(&helpers);
01821 return res;
01822 }
01823
01824 static char *parse_args(const char *s, int *argc, char *argv[], int max, int *trailingwhitespace)
01825 {
01826 char *dup, *cur;
01827 int x = 0;
01828 int quoted = 0;
01829 int escaped = 0;
01830 int whitespace = 1;
01831
01832 *trailingwhitespace = 0;
01833 if (s == NULL)
01834 return NULL;
01835
01836 if (!(dup = ast_strdup(s)))
01837 return NULL;
01838
01839 cur = dup;
01840
01841 for (; *s ; s++) {
01842 if (x >= max - 1) {
01843 ast_log(LOG_WARNING, "Too many arguments, truncating at %s\n", s);
01844 break;
01845 }
01846 if (*s == '"' && !escaped) {
01847 quoted = !quoted;
01848 if (quoted && whitespace) {
01849
01850 argv[x++] = cur;
01851 whitespace = 0;
01852 }
01853 } else if ((*s == ' ' || *s == '\t') && !(quoted || escaped)) {
01854
01855
01856
01857
01858 if (!whitespace) {
01859 *cur++ = '\0';
01860 whitespace = 1;
01861 }
01862 } else if (*s == '\\' && !escaped) {
01863 escaped = 1;
01864 } else {
01865 if (whitespace) {
01866
01867 argv[x++] = cur;
01868 whitespace = 0;
01869 }
01870 *cur++ = *s;
01871 escaped = 0;
01872 }
01873 }
01874
01875 *cur++ = '\0';
01876
01877
01878
01879
01880 argv[x] = NULL;
01881 *argc = x;
01882 *trailingwhitespace = whitespace;
01883 return dup;
01884 }
01885
01886
01887 int ast_cli_generatornummatches(const char *text, const char *word)
01888 {
01889 int matches = 0, i = 0;
01890 char *buf = NULL, *oldbuf = NULL;
01891
01892 while ((buf = ast_cli_generator(text, word, i++))) {
01893 if (!oldbuf || strcmp(buf,oldbuf))
01894 matches++;
01895 if (oldbuf)
01896 free(oldbuf);
01897 oldbuf = buf;
01898 }
01899 if (oldbuf)
01900 free(oldbuf);
01901 return matches;
01902 }
01903
01904 char **ast_cli_completion_matches(const char *text, const char *word)
01905 {
01906 char **match_list = NULL, *retstr, *prevstr;
01907 size_t match_list_len, max_equal, which, i;
01908 int matches = 0;
01909
01910
01911 match_list_len = 1;
01912 while ((retstr = ast_cli_generator(text, word, matches)) != NULL) {
01913 if (matches + 1 >= match_list_len) {
01914 match_list_len <<= 1;
01915 if (!(match_list = ast_realloc(match_list, match_list_len * sizeof(*match_list))))
01916 return NULL;
01917 }
01918 match_list[++matches] = retstr;
01919 }
01920
01921 if (!match_list)
01922 return match_list;
01923
01924
01925
01926
01927 prevstr = match_list[1];
01928 max_equal = strlen(prevstr);
01929 for (which = 2; which <= matches; which++) {
01930 for (i = 0; i < max_equal && toupper(prevstr[i]) == toupper(match_list[which][i]); i++)
01931 continue;
01932 max_equal = i;
01933 }
01934
01935 if (!(retstr = ast_malloc(max_equal + 1)))
01936 return NULL;
01937
01938 ast_copy_string(retstr, match_list[1], max_equal + 1);
01939 match_list[0] = retstr;
01940
01941
01942 if (matches + 1 >= match_list_len) {
01943 if (!(match_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(*match_list))))
01944 return NULL;
01945 }
01946 match_list[matches + 1] = NULL;
01947
01948 return match_list;
01949 }
01950
01951 static char *__ast_cli_generator(const char *text, const char *word, int state, int lock)
01952 {
01953 char *argv[AST_MAX_ARGS];
01954 struct ast_cli_entry *e;
01955 struct cli_iterator i = { NULL, NULL };
01956 int x = 0, argindex, matchlen;
01957 int matchnum=0;
01958 char *ret = NULL;
01959 char matchstr[80] = "";
01960 int tws = 0;
01961 char *dup = parse_args(text, &x, argv, sizeof(argv) / sizeof(argv[0]), &tws);
01962
01963 if (!dup)
01964 return NULL;
01965 argindex = (!ast_strlen_zero(word) && x>0) ? x-1 : x;
01966
01967 ast_join(matchstr, sizeof(matchstr)-1, argv);
01968 matchlen = strlen(matchstr);
01969 if (tws) {
01970 strcat(matchstr, " ");
01971 if (matchlen)
01972 matchlen++;
01973 }
01974 if (lock)
01975 AST_LIST_LOCK(&helpers);
01976 while( !ret && (e = cli_next(&i)) ) {
01977 int lc = strlen(e->_full_cmd);
01978 if (e->_full_cmd[0] != '_' && lc > 0 && matchlen <= lc &&
01979 !strncasecmp(matchstr, e->_full_cmd, matchlen)) {
01980
01981 if (e->cmda[argindex] && ++matchnum > state)
01982 ret = strdup(e->cmda[argindex]);
01983 } else if (e->generator && !strncasecmp(matchstr, e->_full_cmd, lc) && matchstr[lc] < 33) {
01984
01985
01986 ret = e->generator(matchstr, word, argindex, state);
01987 }
01988 }
01989 if (lock)
01990 AST_LIST_UNLOCK(&helpers);
01991 free(dup);
01992 return ret;
01993 }
01994
01995 char *ast_cli_generator(const char *text, const char *word, int state)
01996 {
01997 return __ast_cli_generator(text, word, state, 1);
01998 }
01999
02000 int ast_cli_command(int fd, const char *s)
02001 {
02002 char *argv[AST_MAX_ARGS];
02003 struct ast_cli_entry *e;
02004 int x;
02005 char *dup;
02006 int tws;
02007
02008 if (!(dup = parse_args(s, &x, argv, sizeof(argv) / sizeof(argv[0]), &tws)))
02009 return -1;
02010
02011
02012 if (x > 0) {
02013 AST_LIST_LOCK(&helpers);
02014 e = find_cli(argv, 0);
02015 if (e)
02016 e->inuse++;
02017 AST_LIST_UNLOCK(&helpers);
02018 if (e) {
02019 switch(e->handler(fd, x, argv)) {
02020 case RESULT_SHOWUSAGE:
02021 if (e->usage)
02022 ast_cli(fd, "%s", e->usage);
02023 else
02024 ast_cli(fd, "Invalid usage, but no usage information available.\n");
02025 AST_LIST_LOCK(&helpers);
02026 if (e->deprecated)
02027 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);
02028 AST_LIST_UNLOCK(&helpers);
02029 break;
02030 default:
02031 AST_LIST_LOCK(&helpers);
02032 if (e->deprecated == 1) {
02033 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);
02034 e->deprecated = 2;
02035 }
02036 AST_LIST_UNLOCK(&helpers);
02037 break;
02038 }
02039 } else
02040 ast_cli(fd, "No such command '%s' (type 'help %s' for other possible commands)\n", s, find_best(argv));
02041 if (e)
02042 ast_atomic_fetchadd_int(&e->inuse, -1);
02043 }
02044 free(dup);
02045
02046 return 0;
02047 }
02048
02049 int ast_cli_command_multiple(int fd, size_t size, const char *s)
02050 {
02051 char cmd[512];
02052 int x, y = 0, count = 0;
02053
02054 for (x = 0; x < size; x++) {
02055 cmd[y] = s[x];
02056 y++;
02057 if (s[x] == '\0') {
02058 ast_cli_command(fd, cmd);
02059 y = 0;
02060 count++;
02061 }
02062 }
02063 return count;
02064 }