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