Newer
Older
/* Give the console access to the shell */
if (s) {
Mark Spencer
committed
ast_safe_system(s+1);
Mark Spencer
committed
ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
(s[4] == '\0' || isspace(s[4]))) {
} else
fprintf(stdout, "\nUse \"quit\" to exit\n");
static char abort_halt_help[] =
"Usage: abort shutdown\n"
" Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
" call operations.\n";
static char shutdown_now_help[] =
" Shuts down a running Asterisk immediately, hanging up all active calls .\n";
static char shutdown_gracefully_help[] =
" Causes Asterisk to not accept new calls, and exit when all\n"
" active calls have terminated normally.\n";
static char shutdown_when_convenient_help[] =
"Usage: stop when convenient\n"
" Causes Asterisk to perform a shutdown when all active calls have ended.\n";
static char restart_now_help[] =
"Usage: restart now\n"
" Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
" restart.\n";
static char restart_gracefully_help[] =
"Usage: restart gracefully\n"
" Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
" restart when all active calls have ended.\n";
static char restart_when_convenient_help[] =
"Usage: restart when convenient\n"
" Causes Asterisk to perform a cold restart when all active calls have ended.\n";
static char bang_help[] =
"Usage: !<command>\n"
" Executes a given shell command\n";
static char show_warranty_help[] =
"Usage: show warranty\n"
" Shows the warranty (if any) for this copy of Asterisk.\n";
static char show_license_help[] =
"Usage: show license\n"
" Shows the license(s) for this copy of Asterisk.\n";
static int handle_quit(int fd, int argc, char *argv[])
{
if (argc != 1)
return RESULT_SHOWUSAGE;
quit_handler(0, 0, 1, 0);
return RESULT_SUCCESS;
}
static int handle_shutdown_now(int fd, int argc, char *argv[])
{
if (argc != 2)
return RESULT_SHOWUSAGE;
quit_handler(0, 0 /* Not nice */, 1 /* safely */, 0 /* not restart */);
return RESULT_SUCCESS;
}
static int handle_shutdown_gracefully(int fd, int argc, char *argv[])
{
if (argc != 2)
return RESULT_SHOWUSAGE;
quit_handler(0, 1 /* nicely */, 1 /* safely */, 0 /* no restart */);
return RESULT_SUCCESS;
}
static int handle_shutdown_when_convenient(int fd, int argc, char *argv[])
{
if (argc != 3)
return RESULT_SHOWUSAGE;
ast_cli(fd, "Waiting for inactivity to perform halt\n");
quit_handler(0, 2 /* really nicely */, 1 /* safely */, 0 /* don't restart */);
return RESULT_SUCCESS;
}
static int handle_restart_now(int fd, int argc, char *argv[])
{
if (argc != 2)
return RESULT_SHOWUSAGE;
quit_handler(0, 0 /* not nicely */, 1 /* safely */, 1 /* restart */);
return RESULT_SUCCESS;
}
static int handle_restart_gracefully(int fd, int argc, char *argv[])
{
if (argc != 2)
return RESULT_SHOWUSAGE;
quit_handler(0, 1 /* nicely */, 1 /* safely */, 1 /* restart */);
return RESULT_SUCCESS;
}
static int handle_restart_when_convenient(int fd, int argc, char *argv[])
{
if (argc != 3)
return RESULT_SHOWUSAGE;
ast_cli(fd, "Waiting for inactivity to perform restart\n");
quit_handler(0, 2 /* really nicely */, 1 /* safely */, 1 /* restart */);
return RESULT_SUCCESS;
}
static int handle_abort_halt(int fd, int argc, char *argv[])
{
if (argc != 2)
return RESULT_SHOWUSAGE;
ast_cancel_shutdown();
shuttingdown = 0;
static int handle_bang(int fd, int argc, char *argv[])
{
return RESULT_SUCCESS;
}
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
static const char *warranty_lines[] = {
"\n",
" NO WARRANTY\n",
"\n",
"BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n",
"FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n",
"OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n",
"PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n",
"OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n",
"MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n",
"TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n",
"PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n",
"REPAIR OR CORRECTION.\n",
"\n",
"IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n",
"WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n",
"REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n",
"INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n",
"OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n",
"TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n",
"YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n",
"PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n",
"POSSIBILITY OF SUCH DAMAGES.\n",
};
static int show_warranty(int fd, int argc, char *argv[])
{
int x;
for (x = 0; x < sizeof(warranty_lines) / sizeof(warranty_lines[0]); x++)
ast_cli(fd, (char *) warranty_lines[x]);
return RESULT_SUCCESS;
}
static const char *license_lines[] = {
"\n",
"This program is free software; you can redistribute it and/or modify\n",
"it under the terms of the GNU General Public License version 2 as\n",
"published by the Free Software Foundation.\n",
"\n",
"This program also contains components licensed under other licenses.\n",
"They include:\n",
"\n",
"This program is distributed in the hope that it will be useful,\n",
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n",
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n",
"GNU General Public License for more details.\n",
"\n",
"You should have received a copy of the GNU General Public License\n",
"along with this program; if not, write to the Free Software\n",
"Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n",
};
static int show_license(int fd, int argc, char *argv[])
{
int x;
for (x = 0; x < sizeof(license_lines) / sizeof(license_lines[0]); x++)
ast_cli(fd, (char *) license_lines[x]);
return RESULT_SUCCESS;
}
Kevin P. Fleming
committed
static struct ast_cli_entry core_cli[] = {
{ { "abort", "halt", NULL }, handle_abort_halt,
"Cancel a running halt", abort_halt_help },
{ { "stop", "now", NULL }, handle_shutdown_now,
"Shut down Asterisk immediately", shutdown_now_help },
{ { "stop", "gracefully", NULL }, handle_shutdown_gracefully,
"Gracefully shut down Asterisk", shutdown_gracefully_help },
{ { "stop", "when","convenient", NULL }, handle_shutdown_when_convenient,
"Shut down Asterisk at empty call volume", shutdown_when_convenient_help },
{ { "restart", "now", NULL }, handle_restart_now,
"Restart Asterisk immediately", restart_now_help },
{ { "restart", "gracefully", NULL }, handle_restart_gracefully,
"Restart Asterisk gracefully", restart_gracefully_help },
{ { "restart", "when", "convenient", NULL }, handle_restart_when_convenient,
"Restart Asterisk at empty call volume", restart_when_convenient_help },
{ { "show", "warranty", NULL }, show_warranty,
"Show the warranty (if any) for this copy of Asterisk", show_warranty_help },
{ { "show", "license", NULL }, show_license,
"Show the license(s) for this copy of Asterisk", show_license_help },
Kevin P. Fleming
committed
{ { "!", NULL }, handle_bang,
"Execute a shell command", bang_help },
#if !defined(LOW_MEMORY)
{ { "show", "version", "files", NULL }, handle_show_version_files,
"Show versions of files used to build Asterisk", show_version_files_help, complete_show_version_files },
#endif /* ! LOW_MEMORY */
Kevin P. Fleming
committed
};
static int ast_el_read_char(EditLine *el, char *cp)
{
Olle Johansson
committed
int num_read = 0;
int lastpos = 0;
struct pollfd fds[2];
int res;
int max;
char buf[512];
for (;;) {
max = 1;
fds[0].fd = ast_consock;
fds[0].events = POLLIN;
Russell Bryant
committed
if (!ast_opt_exec) {
fds[1].fd = STDIN_FILENO;
fds[1].events = POLLIN;
max++;
res = poll(fds, max, -1);
if (res < 0) {
if (errno == EINTR)
continue;
ast_log(LOG_ERROR, "poll failed: %s\n", strerror(errno));
Russell Bryant
committed
if (!ast_opt_exec && fds[1].revents) {
num_read = read(STDIN_FILENO, cp, 1);
if (num_read < 1) {
break;
} else
return (num_read);
}
if (fds[0].revents) {
res = read(ast_consock, buf, sizeof(buf) - 1);
/* if the remote side disappears exit */
if (res < 1) {
fprintf(stderr, "\nDisconnected from Asterisk server\n");
Russell Bryant
committed
if (!ast_opt_reconnect) {
quit_handler(0, 0, 0, 0);
} else {
int tries;
int reconnects_per_second = 20;
fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
Olle Johansson
committed
for (tries=0; tries < 30 * reconnects_per_second; tries++) {
if (ast_tryconnect()) {
fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
printf(term_quit());
break;
} else {
usleep(1000000 / reconnects_per_second);
}
}
fprintf(stderr, "Failed to reconnect for 30 seconds. Quitting.\n");
quit_handler(0, 0, 0, 0);
}
}
Russell Bryant
committed
if (!ast_opt_exec && !lastpos)
write(STDOUT_FILENO, "\r", 1);
write(STDOUT_FILENO, buf, res);
if ((buf[res-1] == '\n') || (buf[res-2] == '\n')) {
} else {
lastpos = 1;
}
}
}
*cp = '\0';
return (0);
}
static char *cli_prompt(EditLine *el)
static char prompt[200];
char *pfmt;
Olle Johansson
committed
int color_used = 0;
char term_code[20];
if ((pfmt = getenv("ASTERISK_PROMPT"))) {
char *t = pfmt, *p = prompt;
memset(prompt, 0, sizeof(prompt));
while (*t != '\0' && *p < sizeof(prompt)) {
if (*t == '%') {
char hostname[MAXHOSTNAMELEN]="";
int i;
struct tm tm;
#ifdef linux
FILE *LOADAVG;
int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
t++;
switch (*t) {
Olle Johansson
committed
case 'C': /* color */
t++;
if (sscanf(t, "%d;%d%n", &fgcolor, &bgcolor, &i) == 2) {
strncat(p, term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
t += i - 1;
} else if (sscanf(t, "%d%n", &fgcolor, &i) == 1) {
strncat(p, term_color_code(term_code, fgcolor, 0, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
t += i - 1;
}
Olle Johansson
committed
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
/* If the color has been reset correctly, then there's no need to reset it later */
if ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) {
color_used = 0;
} else {
color_used = 1;
}
break;
case 'd': /* date */
memset(&tm, 0, sizeof(tm));
time(&ts);
if (localtime_r(&ts, &tm)) {
strftime(p, sizeof(prompt) - strlen(prompt), "%Y-%m-%d", &tm);
}
break;
case 'h': /* hostname */
if (!gethostname(hostname, sizeof(hostname) - 1)) {
strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
} else {
strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
}
break;
case 'H': /* short hostname */
if (!gethostname(hostname, sizeof(hostname) - 1)) {
for (i = 0; i < sizeof(hostname); i++) {
if (hostname[i] == '.') {
hostname[i] = '\0';
break;
}
}
Olle Johansson
committed
strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
} else {
strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
}
break;
#ifdef linux
Olle Johansson
committed
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
case 'l': /* load avg */
t++;
if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
float avg1, avg2, avg3;
int actproc, totproc, npid, which;
fscanf(LOADAVG, "%f %f %f %d/%d %d",
&avg1, &avg2, &avg3, &actproc, &totproc, &npid);
if (sscanf(t, "%d", &which) == 1) {
switch (which) {
case 1:
snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg1);
break;
case 2:
snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg2);
break;
case 3:
snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg3);
break;
case 4:
snprintf(p, sizeof(prompt) - strlen(prompt), "%d/%d", actproc, totproc);
break;
case 5:
snprintf(p, sizeof(prompt) - strlen(prompt), "%d", npid);
break;
}
}
Olle Johansson
committed
}
break;
#endif
Olle Johansson
committed
case 't': /* time */
memset(&tm, 0, sizeof(tm));
time(&ts);
if (localtime_r(&ts, &tm)) {
strftime(p, sizeof(prompt) - strlen(prompt), "%H:%M:%S", &tm);
}
break;
case '#': /* process console or remote? */
if (!ast_opt_remote) {
strncat(p, "#", sizeof(prompt) - strlen(prompt) - 1);
} else {
strncat(p, ">", sizeof(prompt) - strlen(prompt) - 1);
}
break;
case '%': /* literal % */
strncat(p, "%", sizeof(prompt) - strlen(prompt) - 1);
break;
case '\0': /* % is last character - prevent bug */
t--;
break;
}
while (*p != '\0') {
p++;
}
t++;
} else {
*p = *t;
p++;
t++;
}
}
if (color_used) {
/* Force colors back to normal at end */
term_color_code(term_code, COLOR_WHITE, COLOR_BLACK, sizeof(term_code));
if (strlen(term_code) > sizeof(prompt) - strlen(prompt)) {
strncat(prompt + sizeof(prompt) - strlen(term_code) - 1, term_code, strlen(term_code));
} else {
strncat(p, term_code, sizeof(term_code));
}
}
} else if (remotehostname)
snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT2, remotehostname);
else
snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT);
}
static char **ast_el_strtoarr(char *buf)
{
char **match_list = NULL, *retstr;
while ( (retstr = strsep(&buf, " ")) != NULL) {
if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
break;
if (matches + 1 >= match_list_len) {
match_list_len <<= 1;
if (!(match_list = ast_realloc(match_list, match_list_len * sizeof(char *)))) {
/* TODO: Handle memory allocation failure */
}
match_list[matches++] = strdup(retstr);
if (!match_list)
return (char **) NULL;
if (matches >= match_list_len) {
if (!(match_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *)))) {
/* TODO: Handle memory allocation failure */
}
}
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
match_list[matches] = (char *) NULL;
return match_list;
}
static int ast_el_sort_compare(const void *i1, const void *i2)
{
char *s1, *s2;
s1 = ((char **)i1)[0];
s2 = ((char **)i2)[0];
return strcasecmp(s1, s2);
}
static int ast_cli_display_match_list(char **matches, int len, int max)
{
int i, idx, limit, count;
int screenwidth = 0;
int numoutput = 0, numoutputline = 0;
screenwidth = ast_get_termcols(STDOUT_FILENO);
/* find out how many entries can be put on one line, with two spaces between strings */
limit = screenwidth / (max + 2);
if (limit == 0)
limit = 1;
/* how many lines of output */
count = len / limit;
if (count * limit < len)
count++;
idx = 1;
qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);
for (; count > 0; count--) {
numoutputline = 0;
for (i=0; i < limit && matches[idx]; i++, idx++) {
/* Don't print dupes */
if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
i--;
free(matches[idx]);
matches[idx] = NULL;
free(matches[idx]);
matches[idx] = NULL;
}
if (numoutputline > 0)
fprintf(stdout, "\n");
}
return numoutput;
static char *cli_complete(EditLine *el, int ch)
Olle Johansson
committed
int len = 0;
char *ptr;
int nummatches = 0;
char **matches;
int retval = CC_ERROR;
James Golovich
committed
char buf[2048];
LineInfo *lf = (LineInfo *)el_line(el);
if (ptr) {
while (ptr > lf->buffer) {
if (isspace(*ptr)) {
ptr++;
break;
}
ptr--;
}
}
len = lf->cursor - ptr;
Russell Bryant
committed
if (ast_opt_remote) {
snprintf(buf, sizeof(buf),"_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
fdprint(ast_consock, buf);
res = read(ast_consock, buf, sizeof(buf));
buf[res] = '\0';
nummatches = atoi(buf);
if (nummatches > 0) {
char *mbuf;
int mlen = 0, maxmbuf = 2048;
/* Start with a 2048 byte buffer */
if (!(mbuf = ast_malloc(maxmbuf)))
return (char *)(CC_ERROR);
snprintf(buf, sizeof(buf),"_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
fdprint(ast_consock, buf);
res = 0;
while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
if (mlen + 1024 > maxmbuf) {
/* Every step increment buffer 1024 bytes */
maxmbuf += 1024;
if (!(mbuf = ast_realloc(mbuf, maxmbuf)))
return (char *)(CC_ERROR);
}
/* Only read 1024 bytes at a time */
res = read(ast_consock, mbuf + mlen, 1024);
if (res > 0)
mlen += res;
}
mbuf[mlen] = '\0';
matches = ast_el_strtoarr(mbuf);
free(mbuf);
matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
for (p = matches; p && *p; p++) {
if (!oldbuf || strcmp(*p,oldbuf))
nummatches++;
oldbuf = *p;
}
}
if (matches) {
int i;
int matches_num, maxlen, match_len;
if (matches[0][0] != '\0') {
el_deletestr(el, (int) len);
el_insertstr(el, matches[0]);
retval = CC_REFRESH;
}
if (nummatches == 1) {
/* Found an exact match */
retval = CC_REFRESH;
} else {
/* Must be more than one match */
for (i=1, maxlen=0; matches[i]; i++) {
match_len = strlen(matches[i]);
if (match_len > maxlen)
maxlen = match_len;
}
matches_num = i - 1;
if (matches_num >1) {
fprintf(stdout, "\n");
ast_cli_display_match_list(matches, nummatches, maxlen);
retval = CC_REDISPLAY;
} else {
Russell Bryant
committed
free(matches);
}
static int ast_el_initialize(void)
{
HistEvent ev;
char *editor = getenv("AST_EDITOR");
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);
el_set(el, EL_EDITMODE, 1);
el_set(el, EL_EDITOR, editor ? editor : "emacs");
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);
return 0;
}
static int ast_el_add_history(char *buf)
{
HistEvent ev;
if (el_hist == NULL || el == NULL)
ast_el_initialize();
if (strlen(buf) > 256)
return 0;
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
return (history(el_hist, &ev, H_ENTER, buf));
}
static int ast_el_write_history(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(char *filename)
{
char buf[256];
FILE *f;
int ret = -1;
if (el_hist == NULL || el == NULL)
ast_el_initialize();
if ((f = fopen(filename, "r")) == NULL)
return ret;
while (!feof(f)) {
fgets(buf, sizeof(buf), f);
if (!strcmp(buf, "_HiStOrY_V2_\n"))
continue;
Mark Spencer
committed
if (ast_all_zeros(buf))
continue;
if ((ret = ast_el_add_history(buf)) == -1)
break;
}
fclose(f);
return ret;
}
static void ast_remotecontrol(char * data)
{
char buf[80];
int res;
char filename[80] = "";
char *hostname;
char *cpid;
char *version;
int pid;
char tmp[80];
Olle Johansson
committed
char *stringp = NULL;
if (data)
write(ast_consock, data, strlen(data) + 1);
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;
snprintf(tmp, sizeof(tmp), "set verbose atleast %d", option_verbose);
snprintf(tmp, sizeof(tmp), "set debug atleast %d", option_debug);
fdprint(ast_consock, tmp);
ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
if (getenv("HOME"))
snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
if (el_hist == NULL || el == NULL)
ast_el_initialize();
el_set(el, EL_GETCFN, ast_el_read_char);
Russell Bryant
committed
if (ast_opt_exec && data) { /* hack to print output then exit if asterisk -rx is used */
struct pollfd fds[0];
fds[0].fd = ast_consock;
fds[0].events = POLLIN;
fds[0].revents = 0;
while(poll(fds, 1, 100) > 0) {
ast_el_read_char(el, &tempchar);
}
Olle Johansson
committed
for (;;) {
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");
}
static int show_version(void)
{
printf("Asterisk " ASTERISK_VERSION "\n");
return 0;
}
Olle Johansson
committed
printf("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2006, Digium, Inc. and others.\n");
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");
printf(" -f Do not fork\n");
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(" -I Enable internal timing if Zaptel timer is available\n");
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(" -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 Connect to Asterisk, and attempt to reconnect if disconnected\n");
printf(" -t Record soundfiles in /var/tmp and move them where they belong after they are done.\n");
printf(" -T Display the time in [Mmm dd hh:mm:ss] format for each line of output to the CLI.\n");
printf(" -v Increase verbosity (multiple v's = more verbose)\n");
printf(" -x <cmd> Execute command <cmd> (only valid with -r)\n");
static void ast_readconfig(void)
{
struct ast_config *cfg;
struct ast_variable *v;
Kevin P. Fleming
committed
char *config = AST_CONFIG_FILE;
Russell Bryant
committed
if (ast_opt_override_config) {
cfg = ast_config_load(ast_config_AST_CONFIG_FILE);
ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
ast_copy_string(ast_config_AST_CONFIG_DIR, AST_CONFIG_DIR, sizeof(ast_config_AST_CONFIG_DIR));
ast_copy_string(ast_config_AST_SPOOL_DIR, AST_SPOOL_DIR, sizeof(ast_config_AST_SPOOL_DIR));
ast_copy_string(ast_config_AST_MODULE_DIR, AST_MODULE_DIR, sizeof(ast_config_AST_MODULE_DIR));
snprintf(ast_config_AST_MONITOR_DIR, sizeof(ast_config_AST_MONITOR_DIR) - 1, "%s/monitor", ast_config_AST_SPOOL_DIR);
ast_copy_string(ast_config_AST_VAR_DIR, AST_VAR_DIR, sizeof(ast_config_AST_VAR_DIR));
ast_copy_string(ast_config_AST_LOG_DIR, AST_LOG_DIR, sizeof(ast_config_AST_LOG_DIR));
ast_copy_string(ast_config_AST_AGI_DIR, AST_AGI_DIR, sizeof(ast_config_AST_AGI_DIR));
ast_copy_string(ast_config_AST_DB, AST_DB, sizeof(ast_config_AST_DB));
ast_copy_string(ast_config_AST_KEY_DIR, AST_KEY_DIR, sizeof(ast_config_AST_KEY_DIR));
ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
/* no asterisk.conf? no problem, use buildtime config! */
if (!cfg) {
v = ast_variable_browse(cfg, "files");
while (v) {
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));
} else if (!strcasecmp(v->name, "astctl")) {
ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
}
v = v->next;
v = ast_variable_browse(cfg, "directories");
while(v) {
if (!strcasecmp(v->name, "astetcdir")) {
ast_copy_string(ast_config_AST_CONFIG_DIR, v->value, sizeof(ast_config_AST_CONFIG_DIR));
} else if (!strcasecmp(v->name, "astspooldir")) {
ast_copy_string(ast_config_AST_SPOOL_DIR, v->value, sizeof(ast_config_AST_SPOOL_DIR));
snprintf(ast_config_AST_MONITOR_DIR, sizeof(ast_config_AST_MONITOR_DIR) - 1, "%s/monitor", v->value);
} else if (!strcasecmp(v->name, "astvarlibdir")) {
ast_copy_string(ast_config_AST_VAR_DIR, v->value, sizeof(ast_config_AST_VAR_DIR));
snprintf(ast_config_AST_DB, sizeof(ast_config_AST_DB), "%s/astdb", v->value);
snprintf(ast_config_AST_KEY_DIR, sizeof(ast_config_AST_KEY_DIR), "%s/keys", v->value);
ast_copy_string(ast_config_AST_LOG_DIR, v->value, sizeof(ast_config_AST_LOG_DIR));
ast_copy_string(ast_config_AST_AGI_DIR, v->value, sizeof(ast_config_AST_AGI_DIR));
snprintf(ast_config_AST_PID, sizeof(ast_config_AST_PID), "%s/%s", v->value, "asterisk.pid");
snprintf(ast_config_AST_SOCKET, sizeof(ast_config_AST_SOCKET), "%s/%s", v->value, ast_config_AST_CTL);
ast_copy_string(ast_config_AST_RUN_DIR, v->value, sizeof(ast_config_AST_RUN_DIR));
ast_copy_string(ast_config_AST_MODULE_DIR, v->value, sizeof(ast_config_AST_MODULE_DIR));
v = ast_variable_browse(cfg, "options");
while(v) {
/* verbose level (-v at startup) */
if (!strcasecmp(v->name, "verbose")) {
option_verbose = atoi(v->value);
/* whether or not to force timestamping. (-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;
if (sscanf(v->value, "%d", &option_debug) != 1) {
option_debug = ast_true(v->value);
}
/* 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);
/* 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")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), 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);
/* 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 */
} else if (!strcasecmp(v->name, "transmit_silence_during_record")) {
Russell Bryant
committed
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
/* Enable internal timing */
} else if (!strcasecmp(v->name, "internal_timing")) {
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INTERNAL_TIMING);
if ((sscanf(v->value, "%d", &option_maxcalls) != 1) || (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");
option_maxload = 0.0;
} else if ((sscanf(v->value, "%lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
option_maxload = 0.0;
}
/* What user to run as */
} else if (!strcasecmp(v->name, "runuser")) {
ast_copy_string(ast_config_AST_RUN_USER, v->value, sizeof(ast_config_AST_RUN_USER));
/* What group to run as */
} else if (!strcasecmp(v->name, "rungroup")) {
ast_copy_string(ast_config_AST_RUN_GROUP, v->value, sizeof(ast_config_AST_RUN_GROUP));
} else if (!strcasecmp(v->name, "systemname")) {
ast_copy_string(ast_config_AST_SYSTEM_NAME, v->value, sizeof(ast_config_AST_SYSTEM_NAME));