Newer
Older
ast_term_color_code(&prompt, fgcolor, 0);
Olle Johansson
committed
t += i - 1;
}
Olle Johansson
committed
/* If the color has been reset correctly, then there's no need to reset it later */
color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
Olle Johansson
committed
break;
case 'd': /* date */
if (ast_localtime(&ts, &tm, NULL)) {
ast_strftime(tmp, sizeof(tmp), "%Y-%m-%d", &tm);
ast_str_append(&prompt, 0, "%s", tmp);
cli_prompt_changes++;
}
break;
case 'g': /* group */
if ((gr = getgrgid(getgid()))) {
ast_str_append(&prompt, 0, "%s", gr->gr_name);
}
Olle Johansson
committed
break;
case 'h': /* hostname */
if (!gethostname(hostname, sizeof(hostname) - 1)) {
ast_str_append(&prompt, 0, "%s", hostname);
} else {
ast_str_append(&prompt, 0, "%s", "localhost");
}
Olle Johansson
committed
break;
case 'H': /* short hostname */
if (!gethostname(hostname, sizeof(hostname) - 1)) {
char *dotptr;
if ((dotptr = strchr(hostname, '.'))) {
*dotptr = '\0';
ast_str_append(&prompt, 0, "%s", hostname);
} else {
ast_str_append(&prompt, 0, "%s", "localhost");
}
Olle Johansson
committed
break;
#ifdef HAVE_GETLOADAVG
Olle Johansson
committed
case 'l': /* load avg */
t++;
if (sscanf(t, "%30d", &which) == 1 && which > 0 && which <= 3) {
double list[3];
getloadavg(list, 3);
ast_str_append(&prompt, 0, "%.2f", list[which - 1]);
cli_prompt_changes++;
Olle Johansson
committed
}
break;
#endif
case 's': /* Asterisk system name (from asterisk.conf) */
ast_str_append(&prompt, 0, "%s", ast_config_AST_SYSTEM_NAME);
break;
Olle Johansson
committed
case 't': /* time */
if (ast_localtime(&ts, &tm, NULL)) {
ast_strftime(tmp, sizeof(tmp), "%H:%M:%S", &tm);
ast_str_append(&prompt, 0, "%s", tmp);
cli_prompt_changes++;
}
break;
case 'u': /* username */
if ((pw = getpwuid(getuid()))) {
ast_str_append(&prompt, 0, "%s", pw->pw_name);
}
Olle Johansson
committed
break;
case '#': /* process console or remote? */
ast_str_append(&prompt, 0, "%c", ast_opt_remote ? '>' : '#');
Olle Johansson
committed
break;
case '%': /* literal % */
ast_str_append(&prompt, 0, "%c", '%');
Olle Johansson
committed
break;
case '\0': /* % is last character - prevent bug */
t--;
break;
}
} else {
ast_str_append(&prompt, 0, "%c", *t);
Jeff Peeler
committed
t++;
if (color_used) {
/* Force colors back to normal at end */
} else {
ast_str_set(&prompt, 0, "%s%s",
remotehostname ? remotehostname : "",
ASTERISK_PROMPT);
}
static struct ast_vector_string *ast_el_strtoarr(char *buf)
struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec));
if (!vec) {
return NULL;
}
/* bestmatch must not be deduplicated */
bestmatch = strsep(&buf, " ");
if (!bestmatch || !strcmp(bestmatch, AST_CLI_COMPLETE_EOF)) {
goto vector_cleanup;
}
while ((retstr = strsep(&buf, " "))) {
if (!strcmp(retstr, AST_CLI_COMPLETE_EOF)) {
break;
/* Older daemons sent duplicates. */
if (AST_VECTOR_GET_CMP(vec, retstr, !strcasecmp)) {
continue;
}
/* Older daemons sent unsorted. */
if (!retstr || AST_VECTOR_ADD_SORTED(vec, retstr, strcasecmp)) {
ast_free(retstr);
goto vector_cleanup;
bestmatch = ast_strdup(bestmatch);
if (!bestmatch || AST_VECTOR_INSERT_AT(vec, 0, bestmatch)) {
ast_free(bestmatch);
goto vector_cleanup;
vector_cleanup:
AST_VECTOR_CALLBACK_VOID(vec, ast_free);
AST_VECTOR_PTR_FREE(vec);
return NULL;
static void ast_cli_display_match_list(struct ast_vector_string *matches, int max)
/* find out how many entries can be put on one line, with two spaces between strings */
int limit = ast_get_termcols(STDOUT_FILENO) / (max + 2);
if (limit == 0) {
limit = 1;
}
for (;;) {
int numoutputline;
for (numoutputline = 0; numoutputline < limit && idx < AST_VECTOR_SIZE(matches); idx++) {
fprintf(stdout, "%-*s ", max, AST_VECTOR_GET(matches, idx));
if (!numoutputline) {
break;
}
fprintf(stdout, "\n");
}
static char *cli_complete(EditLine *editline, int ch)
Olle Johansson
committed
int len = 0;
struct ast_vector_string *matches;
LineInfo *lf = (LineInfo *)el_line(editline);
savechr = *(char *)lf->cursor;
if (ptr) {
while (ptr > lf->buffer) {
if (isspace(*ptr)) {
ptr++;
break;
}
ptr--;
}
}
len = lf->cursor - ptr;
Russell Bryant
committed
if (ast_opt_remote) {
#define CMD_MATCHESARRAY "_COMMAND MATCHESARRAY \"%s\" \"%s\""
char *mbuf;
char *new_mbuf;
int mlen = 0, maxmbuf = 2048;
/* Start with a 2048 byte buffer */
mbuf = ast_malloc(maxmbuf);
/* This will run snprintf twice at most. */
while (mbuf && (mlen = snprintf(mbuf, maxmbuf, CMD_MATCHESARRAY, lf->buffer, ptr)) > maxmbuf) {
/* Return value does not include space for NULL terminator. */
maxmbuf = mlen + 1;
ast_free(mbuf);
mbuf = ast_malloc(maxmbuf);
}
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
if (!mbuf) {
*((char *) lf->cursor) = savechr;
return (char *)(CC_ERROR);
}
fdsend(ast_consock, mbuf);
res = 0;
mlen = 0;
mbuf[0] = '\0';
while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
if (mlen + 1024 > maxmbuf) {
/* Expand buffer to the next 1024 byte increment. */
maxmbuf = mlen + 1024;
new_mbuf = ast_realloc(mbuf, maxmbuf);
if (!new_mbuf) {
ast_free(mbuf);
*((char *) lf->cursor) = savechr;
return (char *)(CC_ERROR);
}
mbuf = new_mbuf;
}
/* Only read 1024 bytes at a time */
res = read(ast_consock, mbuf + mlen, 1024);
if (res > 0) {
mlen += res;
}
matches = ast_el_strtoarr(mbuf);
ast_free(mbuf);
matches = ast_cli_completion_vector((char *)lf->buffer, ptr);
const char *best_match = AST_VECTOR_GET(matches, 0);
if (!ast_strlen_zero(best_match)) {
el_deletestr(editline, (int) len);
el_insertstr(editline, best_match);
if (AST_VECTOR_SIZE(matches) == 2) {
el_insertstr(editline, " ");
retval = CC_REFRESH;
} else {
/* Must be more than one match */
for (i = 1, maxlen = 0; i < AST_VECTOR_SIZE(matches); i++) {
match_len = strlen(AST_VECTOR_GET(matches, i));
fprintf(stdout, "\n");
ast_cli_display_match_list(matches, maxlen);
retval = CC_REDISPLAY;
AST_VECTOR_CALLBACK_VOID(matches, ast_free);
AST_VECTOR_PTR_FREE(matches);
*((char *) lf->cursor) = savechr;
}
static int ast_el_initialize(void)
{
HistEvent ev;
Sean Bright
committed
char *editor, *editrc = getenv("EDITRC");
if (!(editor = getenv("AST_EDITMODE"))) {
if (!(editor = getenv("AST_EDITOR"))) {
editor = "emacs";
}
}
if (el != NULL)
el_end(el);
if (el_hist != NULL)
history_end(el_hist);
el = el_init("asterisk", stdin, stdout, stderr);
el_set(el, EL_PROMPT, cli_prompt);
Sean Bright
committed
el_set(el, EL_EDITOR, editor);
el_hist = history_init();
if (!el || !el_hist)
return -1;
/* setup history with 100 entries */
history(el_hist, &ev, H_SETSIZE, 100);
el_set(el, EL_HIST, history, el_hist);
el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
/* Bind <tab> to command completion */
el_set(el, EL_BIND, "^I", "ed-complete", NULL);
/* Bind ? to command completion */
el_set(el, EL_BIND, "?", "ed-complete", NULL);
/* Bind ^D to redisplay */
el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
Sean Bright
committed
/* Bind Delete to delete char left */
el_set(el, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
/* Bind Home and End to move to line start and end */
el_set(el, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
el_set(el, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
/* Bind C-left and C-right to move by word (not all terminals) */
el_set(el, EL_BIND, "\\eOC", "vi-next-word", NULL);
el_set(el, EL_BIND, "\\eOD", "vi-prev-word", NULL);
if (editrc) {
el_source(el, editrc);
}
#define MAX_HISTORY_COMMAND_LENGTH 256
static int ast_el_add_history(const char *buf)
char *stripped_buf;
if (el_hist == NULL || el == NULL) {
}
if (strlen(buf) > (MAX_HISTORY_COMMAND_LENGTH - 1)) {
return 0;
}
stripped_buf = ast_strip(ast_strdupa(buf));
/* HISTCONTROL=ignoredups */
if (!history(el_hist, &ev, H_FIRST) && strcmp(ev.str, stripped_buf) == 0) {
}
return history(el_hist, &ev, H_ENTER, stripped_buf);
static int ast_el_write_history(const char *filename)
{
HistEvent ev;
if (el_hist == NULL || el == NULL)
ast_el_initialize();
return (history(el_hist, &ev, H_SAVE, filename));
}
static int ast_el_read_history(const char *filename)
HistEvent ev;
if (el_hist == NULL || el == NULL) {
return history(el_hist, &ev, H_LOAD, filename);
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
static void ast_el_read_default_histfile(void)
{
char histfile[80] = "";
const char *home = getenv("HOME");
if (!ast_strlen_zero(home)) {
snprintf(histfile, sizeof(histfile), "%s/.asterisk_history", home);
ast_el_read_history(histfile);
}
}
static void ast_el_write_default_histfile(void)
{
char histfile[80] = "";
const char *home = getenv("HOME");
if (!ast_strlen_zero(home)) {
snprintf(histfile, sizeof(histfile), "%s/.asterisk_history", home);
ast_el_write_history(histfile);
}
}
Kevin P. Fleming
committed
static void ast_remotecontrol(char *data)
char buf[256] = "";
int res;
char *hostname;
char *cpid;
char *version;
int pid;
Olle Johansson
committed
char *stringp = NULL;
ast_term_init();
printf("%s", term_end());
fflush(stdout);
memset(&sig_flags, 0, sizeof(sig_flags));
signal(SIGINT, __remote_quit_handler);
signal(SIGTERM, __remote_quit_handler);
signal(SIGHUP, __remote_quit_handler);
if (read(ast_consock, buf, sizeof(buf) - 1) < 0) {
Kevin P. Fleming
committed
ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
return;
}
if (data) {
char prefix[] = "cli quit after ";
char *tmp = ast_alloca(strlen(data) + strlen(prefix) + 1);
sprintf(tmp, "%s%s", prefix, data);
Kevin P. Fleming
committed
if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) {
ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
if (sig_flags.need_quit || sig_flags.need_quit_handler) {
Kevin P. Fleming
committed
}
Olle Johansson
committed
stringp = buf;
hostname = strsep(&stringp, "/");
cpid = strsep(&stringp, "/");
if (!version)
version = "<Version Unknown>";
Olle Johansson
committed
stringp = hostname;
if (cpid)
pid = atoi(cpid);
else
pid = -1;
send_rasterisk_connect_commands();
Joshua Colp
committed
}
Russell Bryant
committed
if (ast_opt_exec && data) { /* hack to print output then exit if asterisk -rx is used */
int linefull = 1, prev_linefull = 1, prev_line_verbose = 0;
struct pollfd fds;
fds.fd = ast_consock;
fds.events = POLLIN;
fds.revents = 0;
while (ast_poll(&fds, 1, 60000) > 0) {
char buffer[512] = "", *curline = buffer, *nextline;
if (sig_flags.need_quit || sig_flags.need_quit_handler) {
if (read(ast_consock, buffer, sizeof(buffer) - 1) <= 0) {
break;
}
do {
if ((nextline = strchr(curline, '\n'))) {
nextline = strchr(curline, '\0');
}
/* Skip verbose lines */
/* Prev line full? | Line is verbose | Last line verbose? | Print
* TRUE | TRUE* | TRUE | FALSE
* TRUE | TRUE* | FALSE | FALSE
* TRUE | FALSE* | TRUE | TRUE
* TRUE | FALSE* | FALSE | TRUE
* FALSE | TRUE | TRUE* | FALSE
* FALSE | TRUE | FALSE* | TRUE
* FALSE | FALSE | TRUE* | FALSE
* FALSE | FALSE | FALSE* | TRUE
*/
if ((!prev_linefull && !prev_line_verbose) || (prev_linefull && *curline > 0)) {
prev_line_verbose = 0;
Kevin P. Fleming
committed
if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
}
}
curline = nextline;
} while (!ast_strlen_zero(curline));
/* No non-verbose output in 60 seconds. */
if (not_written) {
break;
}
}
ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
remotehostname = hostname;
if (el_hist == NULL || el == NULL)
ast_el_initialize();
ast_el_read_default_histfile();
el_set(el, EL_GETCFN, ast_el_read_char);
Olle Johansson
committed
for (;;) {
if (sig_flags.need_quit || sig_flags.need_quit_handler) {
if (!ebuf && write(1, "", 1) < 0)
break;
if (!ast_strlen_zero(ebuf)) {
if (ebuf[strlen(ebuf)-1] == '\n')
ebuf[strlen(ebuf)-1] = '\0';
if (!remoteconsolehandler(ebuf)) {
res = write(ast_consock, ebuf, strlen(ebuf) + 1);
if (res < 1) {
ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
break;
}
}
}
}
printf("\nDisconnected from Asterisk server\n");
}
Russell Bryant
committed
printf("Asterisk %s\n", ast_get_version());
static int show_cli_help(void)
{
printf("Asterisk %s, Copyright (C) 1999 - 2014, Digium, Inc. and others.\n", ast_get_version());
printf("Usage: asterisk [OPTIONS]\n");
printf("Valid Options:\n");
printf(" -C <configfile> Use an alternate configuration file\n");
printf(" -G <group> Run as a group other than the caller\n");
printf(" -U <user> Run as a user other than the caller\n");
printf(" -c Provide console CLI\n");
printf(" -d Enable extra debugging\n");
Kevin P. Fleming
committed
#if HAVE_WORKING_FORK
printf(" -f Do not fork\n");
Kevin P. Fleming
committed
printf(" -F Always fork\n");
#endif
printf(" -g Dump core in case of a crash\n");
printf(" -h This help screen\n");
printf(" -i Initialize crypto keys at startup\n");
Olle Johansson
committed
printf(" -L <load> Limit the maximum load average before rejecting new calls\n");
printf(" -M <value> Limit the maximum number of calls to the specified value\n");
printf(" -m Mute debugging and console output on the console\n");
printf(" -n Disable console colorization\n");
printf(" -p Run as pseudo-realtime thread\n");
printf(" -q Quiet mode (suppress output)\n");
printf(" -r Connect to Asterisk on this machine\n");
printf(" -R Same as -r, except attempt to reconnect if disconnected\n");
Tilghman Lesher
committed
printf(" -s <socket> Connect to Asterisk via socket <socket> (only valid with -r)\n");
printf(" -t Record soundfiles in /var/tmp and move them where they\n");
printf(" belong after they are done\n");
printf(" -T Display the time in [Mmm dd hh:mm:ss] format for each line\n");
printf(" of output to the CLI\n");
printf(" -v Increase verbosity (multiple v's = more verbose)\n");
printf(" -x <cmd> Execute command <cmd> (implies -r)\n");
Joshua Colp
committed
printf(" -X Execute includes by default (allows #exec in asterisk.conf)\n");
Tilghman Lesher
committed
printf(" -W Adjust terminal colors to compensate for a light background\n");
{
struct ast_config *cfg;
struct ast_variable *v;
char *config = DEFAULT_CONFIG_FILE;
char hostname[MAXHOSTNAMELEN] = "";
Tilghman Lesher
committed
struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
Tilghman Lesher
committed
struct {
unsigned int dbdir:1;
unsigned int keydir:1;
} found = { 0, 0 };
/* Default to false for security */
int live_dangerously = 0;
/* Set default value */
option_dtmfminduration = AST_MIN_DTMF_DURATION;
ast_option_rtpptdynamic = AST_RTP_PT_FIRST_DYNAMIC;
Russell Bryant
committed
if (ast_opt_override_config) {
Tilghman Lesher
committed
cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" /* core, can't reload */, config_flags);
Matthew Jordan
committed
if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
fprintf(stderr, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
}
} else {
Tilghman Lesher
committed
cfg = ast_config_load2(config, "" /* core, can't reload */, config_flags);
Matthew Jordan
committed
}
ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
ast_copy_string(cfg_paths.spool_dir, DEFAULT_SPOOL_DIR, sizeof(cfg_paths.spool_dir));
ast_copy_string(cfg_paths.module_dir, DEFAULT_MODULE_DIR, sizeof(cfg_paths.module_dir));
ast_copy_string(cfg_paths.monitor_dir, DEFAULT_MONITOR_DIR, sizeof(cfg_paths.monitor_dir));
ast_copy_string(cfg_paths.recording_dir, DEFAULT_RECORDING_DIR, sizeof(cfg_paths.recording_dir));
ast_copy_string(cfg_paths.var_dir, DEFAULT_VAR_DIR, sizeof(cfg_paths.var_dir));
ast_copy_string(cfg_paths.data_dir, DEFAULT_DATA_DIR, sizeof(cfg_paths.data_dir));
ast_copy_string(cfg_paths.log_dir, DEFAULT_LOG_DIR, sizeof(cfg_paths.log_dir));
ast_copy_string(cfg_paths.agi_dir, DEFAULT_AGI_DIR, sizeof(cfg_paths.agi_dir));
ast_copy_string(cfg_paths.db_path, DEFAULT_DB, sizeof(cfg_paths.db_path));
ast_copy_string(cfg_paths.sbin_dir, DEFAULT_SBIN_DIR, sizeof(cfg_paths.sbin_dir));
ast_copy_string(cfg_paths.key_dir, DEFAULT_KEY_DIR, sizeof(cfg_paths.key_dir));
ast_copy_string(cfg_paths.pid_path, DEFAULT_PID, sizeof(cfg_paths.pid_path));
ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path));
ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir));
ast_set_default_eid(&ast_eid_default);
/* no asterisk.conf? no problem, use buildtime config! */
Tilghman Lesher
committed
if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
Kevin P. Fleming
committed
for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
if (!strcasecmp(v->name, "astctlpermissions"))
ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
else if (!strcasecmp(v->name, "astctlowner"))
ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
else if (!strcasecmp(v->name, "astctlgroup"))
ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
Kevin P. Fleming
committed
for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
ast_copy_string(cfg_paths.config_dir, v->value, sizeof(cfg_paths.config_dir));
} else if (!strcasecmp(v->name, "astspooldir")) {
ast_copy_string(cfg_paths.spool_dir, v->value, sizeof(cfg_paths.spool_dir));
snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", v->value);
snprintf(cfg_paths.recording_dir, sizeof(cfg_paths.recording_dir), "%s/recording", v->value);
} else if (!strcasecmp(v->name, "astvarlibdir")) {
ast_copy_string(cfg_paths.var_dir, v->value, sizeof(cfg_paths.var_dir));
Tilghman Lesher
committed
if (!found.dbdir)
snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
Tilghman Lesher
committed
} else if (!strcasecmp(v->name, "astdbdir")) {
snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
Tilghman Lesher
committed
found.dbdir = 1;
Joshua Colp
committed
} else if (!strcasecmp(v->name, "astdatadir")) {
ast_copy_string(cfg_paths.data_dir, v->value, sizeof(cfg_paths.data_dir));
Tilghman Lesher
committed
if (!found.keydir)
snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
Tilghman Lesher
committed
} else if (!strcasecmp(v->name, "astkeydir")) {
snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
Tilghman Lesher
committed
found.keydir = 1;
ast_copy_string(cfg_paths.log_dir, v->value, sizeof(cfg_paths.log_dir));
ast_copy_string(cfg_paths.agi_dir, v->value, sizeof(cfg_paths.agi_dir));
snprintf(cfg_paths.pid_path, sizeof(cfg_paths.pid_path), "%s/%s", v->value, "asterisk.pid");
ast_copy_string(cfg_paths.run_dir, v->value, sizeof(cfg_paths.run_dir));
ast_copy_string(cfg_paths.module_dir, v->value, sizeof(cfg_paths.module_dir));
} else if (!strcasecmp(v->name, "astsbindir")) {
ast_copy_string(cfg_paths.sbin_dir, v->value, sizeof(cfg_paths.sbin_dir));
Kevin P. Fleming
committed
/* Combine astrundir and astctl settings. */
snprintf(cfg_paths.socket_path, sizeof(cfg_paths.socket_path), "%s/%s",
ast_config_AST_RUN_DIR, ast_config_AST_CTL);
Kevin P. Fleming
committed
for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
/* verbose level (-v at startup) */
if (!strcasecmp(v->name, "verbose")) {
option_verbose = atoi(v->value);
/* whether or not to force timestamping in CLI verbose output. (-T at startup) */
} else if (!strcasecmp(v->name, "timestamp")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
/* whether or not to support #exec in config files */
} else if (!strcasecmp(v->name, "execincludes")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
} else if (!strcasecmp(v->name, "debug")) {
option_debug = 0;
option_debug = ast_true(v->value) ? 1 : 0;
Kevin P. Fleming
committed
#if HAVE_WORKING_FORK
/* Disable forking (-f at startup) */
} else if (!strcasecmp(v->name, "nofork")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
/* Always fork, even if verbose or debug are enabled (-F at startup) */
} else if (!strcasecmp(v->name, "alwaysfork")) {
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
Kevin P. Fleming
committed
#endif
/* Run quietly (-q at startup ) */
} else if (!strcasecmp(v->name, "quiet")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
/* Run as console (-c at startup, implies nofork) */
} else if (!strcasecmp(v->name, "console")) {
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
/* Run with high priority if the O/S permits (-p at startup) */
} else if (!strcasecmp(v->name, "highpriority")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
/* Initialize RSA auth keys (IAX2) (-i at startup) */
} else if (!strcasecmp(v->name, "initcrypto")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
/* Disable ANSI colors for console (-c at startup) */
} else if (!strcasecmp(v->name, "nocolor")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
Russell Bryant
committed
/* Disable some usage warnings for picky people :p */
} else if (!strcasecmp(v->name, "dontwarn")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
/* Dump core in case of crash (-g) */
} else if (!strcasecmp(v->name, "dumpcore")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
/* Cache recorded sound files to another directory during recording */
} else if (!strcasecmp(v->name, "cache_record_files")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
#if !defined(LOW_MEMORY)
/* Cache media frames for performance */
} else if (!strcasecmp(v->name, "cache_media_frames")) {
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_MEDIA_FRAMES);
#endif
/* Specify cache directory */
} else if (!strcasecmp(v->name, "record_cache_dir")) {
ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
/* Build transcode paths via SLINEAR, instead of directly */
} else if (!strcasecmp(v->name, "transcode_via_sln")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
/* Transmit SLINEAR silence while a channel is being recorded or DTMF is being generated on a channel */
} else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
Richard Mudgett
committed
/* Enable internal timing */
} else if (!strcasecmp(v->name, "internal_timing")) {
if (!ast_opt_remote) {
fprintf(stderr,
"NOTICE: The internal_timing option is no longer needed.\n"
" It will always be enabled if you have a timing module loaded.\n");
}
} else if (!strcasecmp(v->name, "mindtmfduration")) {
if (sscanf(v->value, "%30u", &option_dtmfminduration) != 1) {
option_dtmfminduration = AST_MIN_DTMF_DURATION;
}
/* http://www.iana.org/assignments/rtp-parameters
* RTP dynamic payload types start at 96 normally; extend down to 0 */
} else if (!strcasecmp(v->name, "rtp_pt_dynamic")) {
ast_parse_arg(v->value, PARSE_UINT32|PARSE_IN_RANGE|PARSE_DEFAULT,
&ast_option_rtpptdynamic, AST_RTP_PT_FIRST_DYNAMIC,
0, AST_RTP_PT_LAST_REASSIGN);
if ((sscanf(v->value, "%30d", &ast_option_maxcalls) != 1) || (ast_option_maxcalls < 0)) {
ast_option_maxcalls = 0;
} else if (!strcasecmp(v->name, "maxload")) {
Kevin P. Fleming
committed
double test[1];
if (getloadavg(test, 1) == -1) {
ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
ast_option_maxload = 0.0;
} else if ((sscanf(v->value, "%30lf", &ast_option_maxload) != 1) || (ast_option_maxload < 0.0)) {
ast_option_maxload = 0.0;
}
Joshua Colp
committed
/* Set the maximum amount of open files */
} else if (!strcasecmp(v->name, "maxfiles")) {
if (!ast_opt_remote) {
set_ulimit(ast_option_maxfiles);
}
/* What user to run as */
} else if (!strcasecmp(v->name, "runuser")) {
ast_copy_string(cfg_paths.run_user, v->value, sizeof(cfg_paths.run_user));
/* What group to run as */
} else if (!strcasecmp(v->name, "rungroup")) {
ast_copy_string(cfg_paths.run_group, v->value, sizeof(cfg_paths.run_group));
} else if (!strcasecmp(v->name, "systemname")) {
ast_copy_string(cfg_paths.system_name, v->value, sizeof(cfg_paths.system_name));
} else if (!strcasecmp(v->name, "autosystemname")) {
if (ast_true(v->value)) {
if (!gethostname(hostname, sizeof(hostname) - 1))
ast_copy_string(cfg_paths.system_name, hostname, sizeof(cfg_paths.system_name));
if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)){
ast_copy_string(cfg_paths.system_name, "localhost", sizeof(cfg_paths.system_name));
}
ast_log(LOG_ERROR, "Cannot obtain hostname for this system. Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
Kevin P. Fleming
committed
} else if (!strcasecmp(v->name, "languageprefix")) {
ast_language_is_prefix = ast_true(v->value);
} else if (!strcasecmp(v->name, "defaultlanguage")) {
ast_copy_string(ast_defaultlanguage, v->value, MAX_LANGUAGE);
} else if (!strcasecmp(v->name, "lockmode")) {
if (!strcasecmp(v->value, "lockfile")) {
ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
} else if (!strcasecmp(v->value, "flock")) {
ast_set_lock_type(AST_LOCK_TYPE_FLOCK);
} else {
ast_log(LOG_WARNING, "'%s' is not a valid setting for the lockmode option, "
"defaulting to 'lockfile'\n", v->value);
ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
Joshua Colp
committed
#if defined(HAVE_SYSINFO)
Dwayne M. Hubbard
committed
} else if (!strcasecmp(v->name, "minmemfree")) {
/* specify the minimum amount of free memory to retain. Asterisk should stop accepting new calls
* if the amount of free memory falls below this watermark */
if ((sscanf(v->value, "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
Dwayne M. Hubbard
committed
option_minmemfree = 0;
}
Dwayne M. Hubbard
committed
#endif
} else if (!strcasecmp(v->name, "entityid")) {
struct ast_eid tmp_eid;
if (!ast_str_to_eid(&tmp_eid, v->value)) {
} else {
ast_log(LOG_WARNING, "Invalid Entity ID '%s' provided\n", v->value);
}
Tilghman Lesher
committed
} else if (!strcasecmp(v->name, "lightbackground")) {
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LIGHT_BACKGROUND);
} else if (!strcasecmp(v->name, "forceblackbackground")) {
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
} else if (!strcasecmp(v->name, "hideconnect")) {
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIDE_CONSOLE_CONNECT);
Jeff Peeler
committed
} else if (!strcasecmp(v->name, "lockconfdir")) {
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LOCK_CONFIG_DIR);
Richard Mudgett
committed
} else if (!strcasecmp(v->name, "stdexten")) {
/* Choose how to invoke the extensions.conf stdexten */
if (!strcasecmp(v->value, "gosub")) {
ast_clear_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
} else if (!strcasecmp(v->value, "macro")) {
ast_set_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
} else {
ast_log(LOG_WARNING,
"'%s' is not a valid setting for the stdexten option, defaulting to 'gosub'\n",
v->value);
ast_clear_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
}
} else if (!strcasecmp(v->name, "live_dangerously")) {
live_dangerously = ast_true(v->value);
if (!ast_opt_remote) {
pbx_live_dangerously(live_dangerously);
}
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
static void read_pjproject_startup_options(void)
{
struct ast_config *cfg;
struct ast_variable *v;
struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE | CONFIG_FLAG_NOREALTIME };
ast_option_pjproject_log_level = DEFAULT_PJ_LOG_MAX_LEVEL;
cfg = ast_config_load2("pjproject.conf", "" /* core, can't reload */, config_flags);
if (!cfg
|| cfg == CONFIG_STATUS_FILEUNCHANGED
|| cfg == CONFIG_STATUS_FILEINVALID) {
/* We'll have to use defaults */
return;
}
for (v = ast_variable_browse(cfg, "startup"); v; v = v->next) {
if (!strcasecmp(v->name, "log_level")) {
if (sscanf(v->value, "%30d", &ast_option_pjproject_log_level) != 1) {
ast_option_pjproject_log_level = DEFAULT_PJ_LOG_MAX_LEVEL;
} else if (ast_option_pjproject_log_level < 0) {
ast_option_pjproject_log_level = 0;
} else if (MAX_PJ_LOG_MAX_LEVEL < ast_option_pjproject_log_level) {
ast_option_pjproject_log_level = MAX_PJ_LOG_MAX_LEVEL;
}
}
}
ast_config_destroy(cfg);
}
static void *monitor_sig_flags(void *unused)
{
for (;;) {
struct pollfd p = { sig_alert_pipe[0], POLLIN, 0 };
int a;
if (sig_flags.need_reload) {
sig_flags.need_reload = 0;
ast_module_reload(NULL);
}
if (sig_flags.need_quit) {
sig_flags.need_quit = 0;
if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
sig_flags.need_quit_handler = 1;
pthread_kill(consolethread, SIGURG);
} else {
quit_handler(0, SHUTDOWN_NORMAL, 0);
Kevin P. Fleming
committed
if (read(sig_alert_pipe[0], &a, sizeof(a)) != sizeof(a)) {
}
}
return NULL;
}
Tilghman Lesher
committed
static void *canary_thread(void *unused)
{
struct stat canary_stat;
struct timeval now;
Tilghman Lesher
committed
/* Give the canary time to sing */
sleep(120);
for (;;) {
now = ast_tvnow();
if (stat(canary_filename, &canary_stat) || now.tv_sec > canary_stat.st_mtime + 60) {
ast_log(LOG_WARNING,
"The canary is no more. He has ceased to be! "
"He's expired and gone to meet his maker! "
"He's a stiff! Bereft of life, he rests in peace. "
"His metabolic processes are now history! He's off the twig! "
"He's kicked the bucket. He's shuffled off his mortal coil, "
"run down the curtain, and joined the bleeding choir invisible!! "
"THIS is an EX-CANARY. (Reducing priority)\n");
set_priority_all(0);
Tilghman Lesher
committed
pthread_exit(NULL);
}
/* Check the canary once a minute */
sleep(60);
}
}
/* Used by libc's atexit(3) function */
static void canary_exit(void)
{
if (canary_pid > 0) {
int status;
Tilghman Lesher
committed
kill(canary_pid, SIGKILL);
waitpid(canary_pid, &status, 0);
}
Tilghman Lesher
committed
}
/* Execute CLI commands on startup. Run by main() thread. */
Russell Bryant
committed
static void run_startup_commands(void)
{
int fd;
Russell Bryant
committed
struct ast_config *cfg;
struct ast_flags cfg_flags = { 0 };
struct ast_variable *v;
Russell Bryant
committed
Tilghman Lesher
committed
if (!(cfg = ast_config_load2("cli.conf", "" /* core, can't reload */, cfg_flags)))
Russell Bryant
committed
return;
Tilghman Lesher
committed
if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
return;
}
Russell Bryant
committed
Russell Bryant
committed
fd = open("/dev/null", O_RDWR);
if (fd < 0) {
ast_config_destroy(cfg);
Russell Bryant
committed
return;
Russell Bryant
committed
Russell Bryant
committed
for (v = ast_variable_browse(cfg, "startup_commands"); v; v = v->next) {
if (ast_true(v->value))
ast_cli_command(fd, v->name);
}
Russell Bryant
committed
close(fd);
Russell Bryant
committed
ast_config_destroy(cfg);
Russell Bryant
committed
}
Tilghman Lesher
committed
static void env_init(void)
{