00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
#include <unistd.h>
00015
#include <stdlib.h>
00016
#include <sys/poll.h>
00017
#include <asterisk/logger.h>
00018
#include <asterisk/options.h>
00019
#include <asterisk/cli.h>
00020
#include <asterisk/channel.h>
00021
#include <asterisk/ulaw.h>
00022
#include <asterisk/alaw.h>
00023
#include <asterisk/callerid.h>
00024
#include <asterisk/module.h>
00025
#include <asterisk/image.h>
00026
#include <asterisk/tdd.h>
00027
#include <asterisk/term.h>
00028
#include <asterisk/manager.h>
00029
#include <asterisk/pbx.h>
00030
#include <asterisk/enum.h>
00031
#include <asterisk/rtp.h>
00032
#include <asterisk/app.h>
00033
#include <asterisk/lock.h>
00034
#include <asterisk/utils.h>
00035
#include <sys/resource.h>
00036
#include <fcntl.h>
00037
#include <stdio.h>
00038
#include <signal.h>
00039
#include <sched.h>
00040
#include <asterisk/io.h>
00041
#include <asterisk/lock.h>
00042
#include <sys/socket.h>
00043
#include <sys/un.h>
00044
#include <sys/wait.h>
00045
#include <string.h>
00046
#include <errno.h>
00047
#include <ctype.h>
00048
#include "editline/histedit.h"
00049
#include "asterisk.h"
00050
#include <asterisk/config.h>
00051
00052
#if defined(__FreeBSD__)
00053
#include <netdb.h>
00054
#endif
00055
00056 #define AST_MAX_CONNECTS 128
00057 #define NUM_MSGS 64
00058
00059 int option_verbose=0;
00060 int option_debug=0;
00061 int option_nofork=0;
00062 int option_quiet=0;
00063 int option_console=0;
00064 int option_highpriority=0;
00065 int option_remote=0;
00066 int option_exec=0;
00067 int option_initcrypto=0;
00068 int option_nocolor;
00069 int option_dumpcore = 0;
00070 int option_overrideconfig = 0;
00071 int fully_booted = 0;
00072
00073
static int ast_socket = -1;
00074
static int ast_consock = -1;
00075 int ast_mainpid;
00076 struct console {
00077 int fd;
00078 int p[2];
00079 pthread_t
t;
00080 };
00081
00082
static struct ast_atexit {
00083 void (*func)(
void);
00084
struct ast_atexit *next;
00085 } *atexits = NULL;
00086
AST_MUTEX_DEFINE_STATIC(atexitslock);
00087
00088 time_t
ast_startuptime;
00089 time_t
ast_lastreloadtime;
00090
00091
static History *el_hist = NULL;
00092
static EditLine *el = NULL;
00093
static char *remotehostname;
00094
00095 struct console consoles[
AST_MAX_CONNECTS];
00096
00097 char defaultlanguage[
MAX_LANGUAGE] =
DEFAULT_LANGUAGE;
00098
00099
static int ast_el_add_history(
char *);
00100
static int ast_el_read_history(
char *);
00101
static int ast_el_write_history(
char *);
00102
00103 char ast_config_AST_CONFIG_DIR[
AST_CONFIG_MAX_PATH];
00104 char ast_config_AST_CONFIG_FILE[
AST_CONFIG_MAX_PATH];
00105 char ast_config_AST_MODULE_DIR[
AST_CONFIG_MAX_PATH];
00106 char ast_config_AST_SPOOL_DIR[
AST_CONFIG_MAX_PATH];
00107 char ast_config_AST_VAR_DIR[
AST_CONFIG_MAX_PATH];
00108 char ast_config_AST_LOG_DIR[
AST_CONFIG_MAX_PATH];
00109 char ast_config_AST_AGI_DIR[
AST_CONFIG_MAX_PATH];
00110 char ast_config_AST_DB[
AST_CONFIG_MAX_PATH];
00111 char ast_config_AST_KEY_DIR[
AST_CONFIG_MAX_PATH];
00112 char ast_config_AST_PID[
AST_CONFIG_MAX_PATH];
00113 char ast_config_AST_SOCKET[
AST_CONFIG_MAX_PATH];
00114 char ast_config_AST_RUN_DIR[
AST_CONFIG_MAX_PATH];
00115
00116
static char *_argv[256];
00117
static int shuttingdown = 0;
00118
static int restartnow = 0;
00119
static pthread_t consolethread =
AST_PTHREADT_NULL;
00120
00121 int ast_register_atexit(
void (*func)(
void))
00122 {
00123
int res = -1;
00124
struct ast_atexit *ae;
00125
ast_unregister_atexit(func);
00126 ae =
malloc(
sizeof(
struct ast_atexit));
00127
ast_mutex_lock(&atexitslock);
00128
if (ae) {
00129 memset(ae, 0,
sizeof(
struct ast_atexit));
00130 ae->next = atexits;
00131 ae->func = func;
00132 atexits = ae;
00133 res = 0;
00134 }
00135
ast_mutex_unlock(&atexitslock);
00136
return res;
00137 }
00138
00139 void ast_unregister_atexit(
void (*func)(
void))
00140 {
00141
struct ast_atexit *ae, *prev = NULL;
00142
ast_mutex_lock(&atexitslock);
00143 ae = atexits;
00144
while(ae) {
00145
if (ae->func == func) {
00146
if (prev)
00147 prev->next = ae->next;
00148
else
00149 atexits = ae->next;
00150
break;
00151 }
00152 prev = ae;
00153 ae = ae->next;
00154 }
00155
ast_mutex_unlock(&atexitslock);
00156 }
00157
00158
static int fdprint(
int fd,
const char *s)
00159 {
00160
return write(fd, s, strlen(s) + 1);
00161 }
00162
00163 int ast_safe_system(
const char *s)
00164 {
00165
00166 pid_t pid;
00167
int x;
00168
int res;
00169
struct rusage rusage;
00170
int status;
00171 pid = fork();
00172
if (pid == 0) {
00173
00174
for (x=STDERR_FILENO + 1; x<4096;x++) {
00175 close(x);
00176 }
00177 res = execl(
"/bin/sh",
"/bin/sh",
"-c",
s, NULL);
00178 exit(1);
00179 }
else if (pid > 0) {
00180
for(;;) {
00181 res = wait4(pid, &status, 0, &rusage);
00182
if (res > -1) {
00183
if (WIFEXITED(status))
00184 res = WEXITSTATUS(status);
00185
else
00186 res = -1;
00187 }
else {
00188
if (errno != EINTR)
00189
break;
00190 }
00191 }
00192 }
else {
00193
ast_log(
LOG_WARNING,
"Fork failed: %s\n", strerror(errno));
00194 res = -1;
00195 }
00196
return res;
00197 }
00198
00199
00200
00201
00202
static void ast_network_puts(
const char *string)
00203 {
00204
int x;
00205
for (x=0;x<
AST_MAX_CONNECTS; x++) {
00206
if (
consoles[x].
fd > -1)
00207 fdprint(consoles[x].p[1], string);
00208 }
00209 }
00210
00211
00212
00213
00214
00215
00216 void ast_console_puts(
const char *string)
00217 {
00218 fputs(
string, stdout);
00219 fflush(stdout);
00220 ast_network_puts(
string);
00221 }
00222
00223
static void network_verboser(
const char *s,
int pos,
int replace,
int complete)
00224
00225 {
00226 ast_network_puts(s);
00227 }
00228
00229
static pthread_t lthread;
00230
00231
static void *netconsole(
void *vconsole)
00232 {
00233
struct console *con = vconsole;
00234
char hostname[256];
00235
char tmp[512];
00236
int res;
00237
struct pollfd fds[2];
00238
00239
if (gethostname(hostname,
sizeof(hostname)))
00240 strncpy(hostname,
"<Unknown>",
sizeof(hostname)-1);
00241 snprintf(tmp,
sizeof(tmp),
"%s/%d/%s\n", hostname, ast_mainpid, ASTERISK_VERSION);
00242 fdprint(con->fd, tmp);
00243
for(;;) {
00244 fds[0].
fd = con->fd;
00245 fds[0].
events =
POLLIN;
00246 fds[1].
fd = con->p[0];
00247 fds[1].
events =
POLLIN;
00248
00249 res =
poll(fds, 2, -1);
00250
if (res < 0) {
00251
if (errno != EINTR)
00252
ast_log(LOG_WARNING,
"poll returned < 0: %s\n", strerror(errno));
00253
continue;
00254 }
00255
if (fds[0].
revents) {
00256 res = read(con->fd, tmp,
sizeof(tmp));
00257
if (res < 1) {
00258
break;
00259 }
00260 tmp[res] = 0;
00261
ast_cli_command(con->fd, tmp);
00262 }
00263
if (fds[1].
revents) {
00264 res = read(con->p[0], tmp,
sizeof(tmp));
00265
if (res < 1) {
00266
ast_log(LOG_ERROR,
"read returned %d\n", res);
00267
break;
00268 }
00269 res = write(con->fd, tmp, res);
00270
if (res < 1)
00271
break;
00272 }
00273 }
00274
if (
option_verbose > 2)
00275
ast_verbose(VERBOSE_PREFIX_3
"Remote UNIX connection disconnected\n");
00276 close(con->fd);
00277 close(con->p[0]);
00278 close(con->p[1]);
00279 con->fd = -1;
00280
00281
return NULL;
00282 }
00283
00284
static void *listener(
void *unused)
00285 {
00286
struct sockaddr_un sun;
00287
int s;
00288
int len;
00289
int x;
00290
int flags;
00291
struct pollfd fds[1];
00292 pthread_attr_t attr;
00293 pthread_attr_init(&attr);
00294 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00295
for(;;) {
00296
if (ast_socket < 0)
00297
return NULL;
00298 fds[0].
fd = ast_socket;
00299 fds[0].
events=
POLLIN;
00300
s =
poll(fds, 1, -1);
00301
if (
s < 0) {
00302
if (errno != EINTR)
00303
ast_log(LOG_WARNING,
"poll returned error: %s\n", strerror(errno));
00304
continue;
00305 }
00306 len =
sizeof(sun);
00307
s = accept(ast_socket, (
struct sockaddr *)&sun, &len);
00308
if (
s < 0) {
00309
if (errno != EINTR)
00310
ast_log(LOG_WARNING,
"Accept returned %d: %s\n", s, strerror(errno));
00311 }
else {
00312
for (x=0;x<
AST_MAX_CONNECTS;x++) {
00313
if (
consoles[x].
fd < 0) {
00314
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
00315
ast_log(LOG_ERROR,
"Unable to create pipe: %s\n", strerror(errno));
00316
consoles[x].
fd = -1;
00317 fdprint(s,
"Server failed to create pipe\n");
00318 close(s);
00319
break;
00320 }
00321 flags = fcntl(consoles[x].p[1], F_GETFL);
00322 fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
00323
consoles[x].
fd =
s;
00324
if (pthread_create(&consoles[x].t, &attr, netconsole, &consoles[x])) {
00325
ast_log(LOG_ERROR,
"Unable to spawn thread to handle connection: %s\n", strerror(errno));
00326
consoles[x].
fd = -1;
00327 fdprint(s,
"Server failed to spawn thread\n");
00328 close(s);
00329 }
00330
break;
00331 }
00332 }
00333
if (x >=
AST_MAX_CONNECTS) {
00334 fdprint(s,
"No more connections allowed\n");
00335
ast_log(LOG_WARNING,
"No more connections allowed\n");
00336 close(s);
00337 }
else if (
consoles[x].
fd > -1) {
00338
if (
option_verbose > 2)
00339
ast_verbose(VERBOSE_PREFIX_3
"Remote UNIX connection\n");
00340 }
00341 }
00342 }
00343
return NULL;
00344 }
00345
00346
static int ast_makesocket(
void)
00347 {
00348
struct sockaddr_un sun;
00349
int res;
00350
int x;
00351
for (x=0;x<
AST_MAX_CONNECTS;x++)
00352
consoles[x].
fd = -1;
00353 unlink((
char *)ast_config_AST_SOCKET);
00354 ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
00355
if (ast_socket < 0) {
00356
ast_log(LOG_WARNING,
"Unable to create control socket: %s\n", strerror(errno));
00357
return -1;
00358 }
00359 memset(&sun, 0,
sizeof(sun));
00360 sun.sun_family = AF_LOCAL;
00361 strncpy(sun.sun_path, (
char *)ast_config_AST_SOCKET,
sizeof(sun.sun_path)-1);
00362 res = bind(ast_socket, (
struct sockaddr *)&sun,
sizeof(sun));
00363
if (res) {
00364
ast_log(LOG_WARNING,
"Unable to bind socket to %s: %s\n", (
char *)ast_config_AST_SOCKET, strerror(errno));
00365 close(ast_socket);
00366 ast_socket = -1;
00367
return -1;
00368 }
00369 res = listen(ast_socket, 2);
00370
if (res < 0) {
00371
ast_log(LOG_WARNING,
"Unable to listen on socket %s: %s\n", (
char *)ast_config_AST_SOCKET, strerror(errno));
00372 close(ast_socket);
00373 ast_socket = -1;
00374
return -1;
00375 }
00376
ast_register_verbose(network_verboser);
00377 pthread_create(<hread, NULL, listener, NULL);
00378
return 0;
00379 }
00380
00381
static int ast_tryconnect(
void)
00382 {
00383
struct sockaddr_un sun;
00384
int res;
00385 ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
00386
if (ast_consock < 0) {
00387
ast_log(LOG_WARNING,
"Unable to create socket: %s\n", strerror(errno));
00388
return 0;
00389 }
00390 memset(&sun, 0,
sizeof(sun));
00391 sun.sun_family = AF_LOCAL;
00392 strncpy(sun.sun_path, (
char *)ast_config_AST_SOCKET,
sizeof(sun.sun_path)-1);
00393 res = connect(ast_consock, (
struct sockaddr *)&sun,
sizeof(sun));
00394
if (res) {
00395 close(ast_consock);
00396 ast_consock = -1;
00397
return 0;
00398 }
else
00399
return 1;
00400 }
00401
00402
static void urg_handler(
int num)
00403 {
00404
00405
00406
00407
if (
option_debug)
00408 printf(
"Urgent handler\n");
00409 signal(num, urg_handler);
00410
return;
00411 }
00412
00413
static void hup_handler(
int num)
00414 {
00415
if (
option_verbose > 1)
00416 printf(
"Received HUP signal -- Reloading configs\n");
00417
if (restartnow)
00418 execvp(_argv[0], _argv);
00419
00420
ast_module_reload();
00421 }
00422
00423
static void child_handler(
int sig)
00424 {
00425
00426
int n, status;
00427
00428
00429
00430
00431
for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++)
00432 ;
00433
if (n == 0 &&
option_debug)
00434 printf(
"Huh? Child handler, but nobody there?\n");
00435 }
00436
00437
static void set_title(
char *text)
00438 {
00439
00440
if (getenv(
"TERM") && strstr(getenv(
"TERM"),
"xterm"))
00441 fprintf(stdout,
"\033]2;%s\007", text);
00442 }
00443
00444
static void set_icon(
char *text)
00445 {
00446
if (getenv(
"TERM") && strstr(getenv(
"TERM"),
"xterm"))
00447 fprintf(stdout,
"\033]1;%s\007", text);
00448 }
00449
00450
static int set_priority(
int pri)
00451 {
00452
struct sched_param sched;
00453 memset(&sched, 0,
sizeof(sched));
00454
00455
00456
#ifdef __linux__
00457
if (pri) {
00458 sched.sched_priority = 10;
00459
if (sched_setscheduler(0, SCHED_RR, &sched)) {
00460
ast_log(LOG_WARNING,
"Unable to set high priority\n");
00461
return -1;
00462 }
else
00463
if (
option_verbose)
00464
ast_verbose(
"Set to realtime thread\n");
00465 }
else {
00466 sched.sched_priority = 0;
00467
if (sched_setscheduler(0, SCHED_OTHER, &sched)) {
00468
ast_log(LOG_WARNING,
"Unable to set normal priority\n");
00469
return -1;
00470 }
00471 }
00472
#else
00473
if (pri) {
00474
if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
00475
ast_log(LOG_WARNING,
"Unable to set high priority\n");
00476
return -1;
00477 }
else
00478
if (
option_verbose)
00479
ast_verbose(
"Set to high priority\n");
00480 }
else {
00481
if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
00482
ast_log(LOG_WARNING,
"Unable to set normal priority\n");
00483
return -1;
00484 }
00485 }
00486
#endif
00487
return 0;
00488 }
00489
00490
static void ast_run_atexits(
void)
00491 {
00492
struct ast_atexit *ae;
00493
ast_mutex_lock(&atexitslock);
00494 ae = atexits;
00495
while(ae) {
00496
if (ae->func)
00497 ae->func();
00498 ae = ae->next;
00499 }
00500
ast_mutex_unlock(&atexitslock);
00501 }
00502
00503
static void quit_handler(
int num,
int nice,
int safeshutdown,
int restart)
00504 {
00505
char filename[80] =
"";
00506 time_t
s,e;
00507
int x;
00508
if (safeshutdown) {
00509 shuttingdown = 1;
00510
if (!nice) {
00511
00512
ast_begin_shutdown(1);
00513
if (
option_verbose &&
option_console)
00514
ast_verbose(
"Beginning asterisk %s....\n", restart ?
"restart" :
"shutdown");
00515 time(&s);
00516
for(;;) {
00517 time(&e);
00518
00519
if ((e -
s) > 15)
00520
break;
00521
if (!
ast_active_channels())
00522
break;
00523
if (!shuttingdown)
00524
break;
00525
00526 usleep(100000);
00527 }
00528 }
else {
00529
if (nice < 2)
00530
ast_begin_shutdown(0);
00531
if (
option_verbose &&
option_console)
00532
ast_verbose(
"Waiting for inactivity to perform %s...\n", restart ?
"restart" :
"halt");
00533
for(;;) {
00534
if (!
ast_active_channels())
00535
break;
00536
if (!shuttingdown)
00537
break;
00538 sleep(1);
00539 }
00540 }
00541
00542
if (!shuttingdown) {
00543
if (
option_verbose &&
option_console)
00544
ast_verbose(
"Asterisk %s cancelled.\n", restart ?
"restart" :
"shutdown");
00545
return;
00546 }
00547 }
00548
if (
option_console ||
option_remote) {
00549
if (getenv(
"HOME"))
00550 snprintf(filename,
sizeof(filename),
"%s/.asterisk_history", getenv(
"HOME"));
00551
if (!ast_strlen_zero(filename))
00552 ast_el_write_history(filename);
00553
if (el != NULL)
00554 el_end(el);
00555
if (el_hist != NULL)
00556 history_end(el_hist);
00557 }
00558
if (
option_verbose)
00559
ast_verbose(
"Executing last minute cleanups\n");
00560 ast_run_atexits();
00561
00562
if (
option_verbose &&
option_console)
00563
ast_verbose(
"Asterisk %s ending (%d).\n",
ast_active_channels() ?
"uncleanly" :
"cleanly", num);
00564
else if (
option_debug)
00565
ast_log(LOG_DEBUG,
"Asterisk ending (%d).\n", num);
00566
manager_event(EVENT_FLAG_SYSTEM,
"Shutdown",
"Shutdown: %s\r\nRestart: %s\r\n",
ast_active_channels() ?
"Uncleanly" :
"Cleanly", restart ?
"True" :
"False");
00567
if (ast_socket > -1) {
00568 close(ast_socket);
00569 ast_socket = -1;
00570 }
00571
if (ast_consock > -1)
00572 close(ast_consock);
00573
if (ast_socket > -1)
00574 unlink((
char *)ast_config_AST_SOCKET);
00575
if (!
option_remote) unlink((
char *)ast_config_AST_PID);
00576 printf(
term_quit());
00577
if (restart) {
00578
if (
option_verbose ||
option_console)
00579
ast_verbose(
"Preparing for Asterisk restart...\n");
00580
00581
for (x=3;x<32768;x++) {
00582 fcntl(x, F_SETFD, FD_CLOEXEC);
00583 }
00584
if (
option_verbose ||
option_console)
00585
ast_verbose(
"Restarting Asterisk NOW...\n");
00586 restartnow = 1;
00587
00588
00589
if (consolethread !=
AST_PTHREADT_NULL) {
00590 pthread_kill(consolethread, SIGHUP);
00591
00592 sleep(2);
00593 }
else
00594 execvp(_argv[0], _argv);
00595
00596 }
00597 exit(0);
00598 }
00599
00600
static void __quit_handler(
int num)
00601 {
00602 quit_handler(num, 0, 1, 0);
00603 }
00604
00605
static const char *fix_header(
char *outbuf,
int maxout,
const char *s,
char *cmp)
00606 {
00607
const char *c;
00608
if (!strncmp(s, cmp, strlen(cmp))) {
00609 c =
s + strlen(cmp);
00610
term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
00611
return c;
00612 }
00613
return NULL;
00614 }
00615
00616
static void console_verboser(
const char *s,
int pos,
int replace,
int complete)
00617 {
00618
char tmp[80];
00619
const char *c=NULL;
00620
00621
if (!pos) {
00622 fprintf(stdout,
"\r");
00623
if ((c = fix_header(tmp,
sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
00624 (c = fix_header(tmp,
sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
00625 (c = fix_header(tmp,
sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
00626 (c = fix_header(tmp,
sizeof(tmp), s, VERBOSE_PREFIX_1)))
00627 fputs(tmp, stdout);
00628 }
00629
if (c)
00630 fputs(c + pos,stdout);
00631
else
00632 fputs(s + pos,stdout);
00633 fflush(stdout);
00634
if (complete)
00635
00636
if (
option_console && consolethread !=
AST_PTHREADT_NULL)
00637 pthread_kill(consolethread, SIGURG);
00638 }
00639
00640
static void consolehandler(
char *s)
00641 {
00642 printf(
term_end());
00643 fflush(stdout);
00644
00645
if (
s && !ast_strlen_zero(s))
00646 ast_el_add_history(s);
00647
00648
if (
s) {
00649
00650
if (
s[0] ==
'!') {
00651
if (
s[1])
00652
ast_safe_system(s+1);
00653
else
00654
ast_safe_system(getenv(
"SHELL") ? getenv(
"SHELL") :
"/bin/sh");
00655 }
else
00656
ast_cli_command(STDOUT_FILENO, s);
00657 }
else
00658 fprintf(stdout,
"\nUse \"quit\" to exit\n");
00659 }
00660
00661
static int remoteconsolehandler(
char *s)
00662 {
00663
int ret = 0;
00664
00665
if (
s && !ast_strlen_zero(s))
00666 ast_el_add_history(s);
00667
00668
if (
s) {
00669
00670
if (
s[0] ==
'!') {
00671
if (
s[1])
00672
ast_safe_system(s+1);
00673
else
00674
ast_safe_system(getenv(
"SHELL") ? getenv(
"SHELL") :
"/bin/sh");
00675 ret = 1;
00676 }
00677
if ((strncasecmp(s,
"quit", 4) == 0 || strncasecmp(s,
"exit", 4) == 0) &&
00678 (
s[4] ==
'\0' || isspace(s[4]))) {
00679 quit_handler(0, 0, 0, 0);
00680 ret = 1;
00681 }
00682 }
else
00683 fprintf(stdout,
"\nUse \"quit\" to exit\n");
00684
00685
return ret;
00686 }
00687
00688
static char quit_help[] =
00689
"Usage: quit\n"
00690
" Exits Asterisk.\n";
00691
00692
static char abort_halt_help[] =
00693
"Usage: abort shutdown\n"
00694
" Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
00695
" call operations.\n";
00696
00697
static char shutdown_now_help[] =
00698
"Usage: stop now\n"
00699
" Shuts down a running Asterisk immediately, hanging up all active calls .\n";
00700
00701
static char shutdown_gracefully_help[] =
00702
"Usage: stop gracefully\n"
00703
" Causes Asterisk to not accept new calls, and exit when all\n"
00704
" active calls have terminated normally.\n";
00705
00706
static char shutdown_when_convenient_help[] =
00707
"Usage: stop when convenient\n"
00708
" Causes Asterisk to perform a shutdown when all active calls have ended.\n";
00709
00710
static char restart_now_help[] =
00711
"Usage: restart now\n"
00712
" Causes Asterisk to hangup all calls and exec() itself performing a cold.\n"
00713
" restart.\n";
00714
00715
static char restart_gracefully_help[] =
00716
"Usage: restart gracefully\n"
00717
" Causes Asterisk to stop accepting new calls and exec() itself performing a cold.\n"
00718
" restart when all active calls have ended.\n";
00719
00720
static char restart_when_convenient_help[] =
00721
"Usage: restart when convenient\n"
00722
" Causes Asterisk to perform a cold restart when all active calls have ended.\n";
00723
00724
static char bang_help[] =
00725
"Usage: !<command>\n"
00726
" Executes a given shell command\n";
00727
00728
#if 0
00729
static int handle_quit(
int fd,
int argc,
char *argv[])
00730 {
00731
if (argc != 1)
00732
return RESULT_SHOWUSAGE;
00733 quit_handler(0, 0, 1, 0);
00734
return RESULT_SUCCESS;
00735 }
00736
#endif
00737
00738
static int no_more_quit(
int fd,
int argc,
char *argv[])
00739 {
00740
if (argc != 1)
00741
return RESULT_SHOWUSAGE;
00742
ast_cli(fd,
"The QUIT and EXIT commands may no longer be used to shutdown the PBX.\n"
00743
"Please use STOP NOW instead, if you wish to shutdown the PBX.\n");
00744
return RESULT_SUCCESS;
00745 }
00746
00747
static int handle_shutdown_now(
int fd,
int argc,
char *argv[])
00748 {
00749
if (argc != 2)
00750
return RESULT_SHOWUSAGE;
00751 quit_handler(0, 0 , 1 , 0 );
00752
return RESULT_SUCCESS;
00753 }
00754
00755
static int handle_shutdown_gracefully(
int fd,
int argc,
char *argv[])
00756 {
00757
if (argc != 2)
00758
return RESULT_SHOWUSAGE;
00759 quit_handler(0, 1 , 1 , 0 );
00760
return RESULT_SUCCESS;
00761 }
00762
00763
static int handle_shutdown_when_convenient(
int fd,
int argc,
char *argv[])
00764 {
00765
if (argc != 3)
00766
return RESULT_SHOWUSAGE;
00767 quit_handler(0, 2 , 1 , 0 );
00768
return RESULT_SUCCESS;
00769 }
00770
00771
static int handle_restart_now(
int fd,
int argc,
char *argv[])
00772 {
00773
if (argc != 2)
00774
return RESULT_SHOWUSAGE;
00775 quit_handler(0, 0 , 1 , 1 );
00776
return RESULT_SUCCESS;
00777 }
00778
00779
static int handle_restart_gracefully(
int fd,
int argc,
char *argv[])
00780 {
00781
if (argc != 2)
00782
return RESULT_SHOWUSAGE;
00783 quit_handler(0, 1 , 1 , 1 );
00784
return RESULT_SUCCESS;
00785 }
00786
00787
static int handle_restart_when_convenient(
int fd,
int argc,
char *argv[])
00788 {
00789
if (argc != 3)
00790
return RESULT_SHOWUSAGE;
00791 quit_handler(0, 2 , 1 , 1 );
00792
return RESULT_SUCCESS;
00793 }
00794
00795
static int handle_abort_halt(
int fd,
int argc,
char *argv[])
00796 {
00797
if (argc != 2)
00798
return RESULT_SHOWUSAGE;
00799
ast_cancel_shutdown();
00800 shuttingdown = 0;
00801
return RESULT_SUCCESS;
00802 }
00803
00804
static int handle_bang(
int fd,
int argc,
char *argv[])
00805 {
00806
return RESULT_SUCCESS;
00807 }
00808
00809 #define ASTERISK_PROMPT "*CLI> "
00810
00811 #define ASTERISK_PROMPT2 "%s*CLI> "
00812
00813
static struct ast_cli_entry aborthalt = { {
"abort",
"halt", NULL }, handle_abort_halt,
"Cancel a running halt", abort_halt_help };
00814
00815
static struct ast_cli_entry quit = { {
"quit", NULL }, no_more_quit,
"Exit Asterisk", quit_help };
00816
static struct ast_cli_entry astexit = { {
"exit", NULL }, no_more_quit,
"Exit Asterisk", quit_help };
00817
00818
static struct ast_cli_entry astshutdownnow = { {
"stop",
"now", NULL }, handle_shutdown_now,
"Shut down Asterisk immediately", shutdown_now_help };
00819
static struct ast_cli_entry astshutdowngracefully = { {
"stop",
"gracefully", NULL }, handle_shutdown_gracefully,
"Gracefully shut down Asterisk", shutdown_gracefully_help };
00820
static struct ast_cli_entry astshutdownwhenconvenient = { {
"stop",
"when",
"convenient", NULL }, handle_shutdown_when_convenient,
"Shut down Asterisk at empty call volume", shutdown_when_convenient_help };
00821
static struct ast_cli_entry astrestartnow = { {
"restart",
"now", NULL }, handle_restart_now,
"Restart Asterisk immediately", restart_now_help };
00822
static struct ast_cli_entry astrestartgracefully = { {
"restart",
"gracefully", NULL }, handle_restart_gracefully,
"Restart Asterisk gracefully", restart_gracefully_help };
00823
static struct ast_cli_entry astrestartwhenconvenient= { {
"restart",
"when",
"convenient", NULL }, handle_restart_when_convenient,
"Restart Asterisk at empty call volume", restart_when_convenient_help };
00824
static struct ast_cli_entry astbang = { {
"!", NULL }, handle_bang,
"Execute a shell command", bang_help };
00825
00826
static int ast_el_read_char(EditLine *el,
char *cp)
00827 {
00828
int num_read=0;
00829
int lastpos=0;
00830
struct pollfd fds[2];
00831
int res;
00832
int max;
00833
char buf[512];
00834
00835
for (;;) {
00836 max = 1;
00837 fds[0].
fd = ast_consock;
00838 fds[0].
events =
POLLIN;
00839
if (!
option_exec) {
00840 fds[1].
fd = STDIN_FILENO;
00841 fds[1].
events =
POLLIN;
00842 max++;
00843 }
00844 res =
poll(fds, max, -1);
00845
if (res < 0) {
00846
if (errno == EINTR)
00847
continue;
00848
ast_log(LOG_ERROR,
"poll failed: %s\n", strerror(errno));
00849
break;
00850 }
00851
00852
if (!
option_exec && fds[1].
revents) {
00853 num_read = read(STDIN_FILENO, cp, 1);
00854
if (num_read < 1) {
00855
break;
00856 }
else
00857
return (num_read);
00858 }
00859
if (fds[0].revents) {
00860 res = read(ast_consock, buf,
sizeof(buf) - 1);
00861
00862
if (res < 1) {
00863 fprintf(stderr,
"\nDisconnected from Asterisk server\n");
00864 quit_handler(0, 0, 0, 0);
00865 }
00866
00867 buf[res] =
'\0';
00868
00869
if (!
option_exec && !lastpos)
00870 write(STDOUT_FILENO,
"\r", 1);
00871 write(STDOUT_FILENO, buf, res);
00872
if ((buf[res-1] ==
'\n') || (buf[res-2] ==
'\n')) {
00873 *cp = CC_REFRESH;
00874
return(1);
00875 }
else {
00876 lastpos = 1;
00877 }
00878 }
00879 }
00880
00881 *cp =
'\0';
00882
return (0);
00883 }
00884
00885
static char *cli_prompt(EditLine *el)
00886 {
00887
static char prompt[200];
00888
char *pfmt;
00889
int color_used=0;
00890
char term_code[20];
00891
00892
if ((pfmt = getenv(
"ASTERISK_PROMPT"))) {
00893
char *t = pfmt, *p = prompt;
00894 memset(prompt, 0,
sizeof(prompt));
00895
while (*t !=
'\0' && *p <
sizeof(prompt)) {
00896
if (*t ==
'%') {
00897
char hostname[256];
00898
int i;
00899
struct timeval tv;
00900
struct tm tm;
00901
#ifdef linux
00902
FILE *LOADAVG;
00903
#endif
00904
int fgcolor =
COLOR_WHITE, bgcolor =
COLOR_BLACK;
00905
00906 t++;
00907
switch (*t) {
00908
case 'C':
00909 t++;
00910
if (sscanf(t,
"%d;%d%n", &fgcolor, &bgcolor, &i) == 2) {
00911 strncat(p,
term_color_code(term_code, fgcolor, bgcolor,
sizeof(term_code)),
sizeof(prompt) - strlen(prompt));
00912 t += i - 1;
00913 }
else if (sscanf(t,
"%d%n", &fgcolor, &i) == 1) {
00914 strncat(p,
term_color_code(term_code, fgcolor, 0,
sizeof(term_code)),
sizeof(prompt) - strlen(prompt));
00915 t += i - 1;
00916 }
00917
00918
00919
if ((fgcolor ==
COLOR_WHITE) && (bgcolor ==
COLOR_BLACK)) {
00920 color_used = 0;
00921 }
else {
00922 color_used = 1;
00923 }
00924
break;
00925
case 'd':
00926 memset(&tm, 0,
sizeof(
struct tm));
00927 gettimeofday(&tv, NULL);
00928
if (localtime_r(&(tv.tv_sec), &tm)) {
00929 strftime(p,
sizeof(prompt) - strlen(prompt),
"%Y-%m-%d", &tm);
00930 }
00931
break;
00932
case 'h':
00933
if (!gethostname(hostname,
sizeof(hostname) - 1)) {
00934 strncat(p, hostname,
sizeof(prompt) - strlen(prompt));
00935 }
else {
00936 strncat(p,
"localhost",
sizeof(prompt) - strlen(prompt));
00937 }
00938
break;
00939
case 'H':
00940
if (!gethostname(hostname,
sizeof(hostname) - 1)) {
00941
for (i=0;i<
sizeof(hostname);i++) {
00942
if (hostname[i] ==
'.') {
00943 hostname[i] =
'\0';
00944
break;
00945 }
00946 }
00947 strncat(p, hostname,
sizeof(prompt) - strlen(prompt));
00948 }
else {
00949 strncat(p,
"localhost",
sizeof(prompt) - strlen(prompt));
00950 }
00951
break;
00952
#ifdef linux
00953
case 'l':
00954 t++;
00955
if ((LOADAVG = fopen(
"/proc/loadavg",
"r"))) {
00956
float avg1, avg2, avg3;
00957
int actproc, totproc, npid, which;
00958 fscanf(LOADAVG,
"%f %f %f %d/%d %d",
00959 &avg1, &avg2, &avg3, &actproc, &totproc, &npid);
00960
if (sscanf(t,
"%d", &which) == 1) {
00961
switch (which) {
00962
case 1:
00963 snprintf(p,
sizeof(prompt) - strlen(prompt),
"%.2f", avg1);
00964
break;
00965
case 2:
00966 snprintf(p,
sizeof(prompt) - strlen(prompt),
"%.2f", avg2);
00967
break;
00968
case 3:
00969 snprintf(p,
sizeof(prompt) - strlen(prompt),
"%.2f", avg3);
00970
break;
00971
case 4:
00972 snprintf(p,
sizeof(prompt) - strlen(prompt),
"%d/%d", actproc, totproc);
00973
break;
00974
case 5:
00975 snprintf(p,
sizeof(prompt) - strlen(prompt),
"%d", npid);
00976
break;
00977 }
00978 }
00979 }
00980
break;
00981
#endif
00982
case 't':
00983 memset(&tm, 0,
sizeof(
struct tm));
00984 gettimeofday(&tv, NULL);
00985
if (localtime_r(&(tv.tv_sec), &tm)) {
00986 strftime(p,
sizeof(prompt) - strlen(prompt),
"%H:%M:%S", &tm);
00987 }
00988
break;
00989
case '#':
00990
if (!
option_remote) {
00991 strncat(p,
"#",
sizeof(prompt) - strlen(prompt));
00992 }
else {
00993 strncat(p,
">",
sizeof(prompt) - strlen(prompt));
00994 }
00995
break;
00996
case '%':
00997 strncat(p,
"%",
sizeof(prompt) - strlen(prompt));
00998
break;
00999
case '\0':
01000 t--;
01001
break;
01002 }
01003
while (*p !=
'\0') {
01004 p++;
01005 }
01006 t++;
01007 }
else {
01008 *p = *t;
01009 p++;
01010 t++;
01011 }
01012 }
01013
if (color_used) {
01014
01015
term_color_code(term_code, COLOR_WHITE, COLOR_BLACK,
sizeof(term_code));
01016
if (strlen(term_code) >
sizeof(prompt) - strlen(prompt)) {
01017 strncat(prompt +
sizeof(prompt) - strlen(term_code) - 1, term_code, strlen(term_code));
01018 }
else {
01019 strncat(p, term_code,
sizeof(term_code));
01020 }
01021 }
01022 }
else if (remotehostname)
01023 snprintf(prompt,
sizeof(prompt), ASTERISK_PROMPT2, remotehostname);
01024
else
01025 snprintf(prompt,
sizeof(prompt), ASTERISK_PROMPT);
01026
01027
return(prompt);
01028 }
01029
01030
static char **ast_el_strtoarr(
char *buf)
01031 {
01032
char **match_list = NULL, *retstr;
01033 size_t match_list_len;
01034
int matches = 0;
01035
01036 match_list_len = 1;
01037
while ( (retstr = strsep(&buf,
" ")) != NULL) {
01038
01039
if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
01040
break;
01041
if (matches + 1 >= match_list_len) {
01042 match_list_len <<= 1;
01043 match_list =
realloc(match_list, match_list_len *
sizeof(
char *));
01044 }
01045
01046 match_list[matches++] =
strdup(retstr);
01047 }
01048
01049
if (!match_list)
01050
return (
char **) NULL;
01051
01052
if (matches>= match_list_len)
01053 match_list =
realloc(match_list, (match_list_len + 1) *
sizeof(
char *));
01054
01055 match_list[matches] = (
char *) NULL;
01056
01057
return match_list;
01058 }
01059
01060
static int ast_el_sort_compare(
const void *i1,
const void *i2)
01061 {
01062
char *s1, *s2;
01063
01064 s1 = ((
char **)i1)[0];
01065 s2 = ((
char **)i2)[0];
01066
01067
return strcasecmp(s1, s2);
01068 }
01069
01070
static int ast_cli_display_match_list(
char **matches,
int len,
int max)
01071 {
01072
int i, idx, limit, count;
01073
int screenwidth = 0;
01074
int numoutput = 0, numoutputline = 0;
01075
01076 screenwidth =
ast_get_termcols(STDOUT_FILENO);
01077
01078
01079 limit = screenwidth / (max + 2);
01080
if (limit == 0)
01081 limit = 1;
01082
01083
01084 count = len / limit;
01085
if (count * limit < len)
01086 count++;
01087
01088 idx = 1;
01089
01090 qsort(&matches[0], (size_t)(len + 1),
sizeof(
char *), ast_el_sort_compare);
01091
01092
for (; count > 0; count--) {
01093 numoutputline = 0;
01094
for (i=0; i < limit && matches[idx]; i++, idx++) {
01095
01096
01097
if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
01098 i--;
01099
continue;
01100 }
01101
01102 numoutput++; numoutputline++;
01103 fprintf(stdout,
"%-*s ", max, matches[idx]);
01104 }
01105
if (numoutputline > 0)
01106 fprintf(stdout,
"\n");
01107 }
01108
01109
return numoutput;
01110 }
01111
01112
01113
static char *cli_complete(EditLine *el,
int ch)
01114 {
01115
int len=0;
01116
char *ptr;
01117
int nummatches = 0;
01118
char **matches;
01119
int retval = CC_ERROR;
01120
char buf[2048];
01121
int res;
01122
01123 LineInfo *lf = (LineInfo *)el_line(el);
01124
01125 *(
char *)lf->cursor =
'\0';
01126 ptr = (
char *)lf->cursor;
01127
if (ptr) {
01128
while (ptr > lf->buffer) {
01129
if (isspace(*ptr)) {
01130 ptr++;
01131
break;
01132 }
01133 ptr--;
01134 }
01135 }
01136
01137 len = lf->cursor - ptr;
01138
01139
if (
option_remote) {
01140 snprintf(buf,
sizeof(buf),
"_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
01141 fdprint(ast_consock, buf);
01142 res = read(ast_consock, buf,
sizeof(buf));
01143 buf[res] =
'\0';
01144 nummatches = atoi(buf);
01145
01146
if (nummatches > 0) {
01147
char *mbuf;
01148
int mlen = 0, maxmbuf = 2048;
01149
01150 mbuf =
malloc(maxmbuf);
01151
if (!mbuf)
01152
return (
char *)(CC_ERROR);
01153 snprintf(buf,
sizeof(buf),
"_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
01154 fdprint(ast_consock, buf);
01155 res = 0;
01156 mbuf[0] =
'\0';
01157
while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
01158
if (mlen + 1024 > maxmbuf) {
01159
01160 maxmbuf += 1024;
01161 mbuf =
realloc(mbuf, maxmbuf);
01162
if (!mbuf)
01163
return (
char *)(CC_ERROR);
01164 }
01165
01166 res = read(ast_consock, mbuf + mlen, 1024);
01167
if (res > 0)
01168 mlen += res;
01169 }
01170 mbuf[mlen] =
'\0';
01171
01172 matches = ast_el_strtoarr(mbuf);
01173
free(mbuf);
01174 }
else
01175 matches = (
char **) NULL;
01176
01177
01178 }
else {
01179
01180 nummatches =
ast_cli_generatornummatches((
char *)lf->buffer,ptr);
01181 matches =
ast_cli_completion_matches((
char *)lf->buffer,ptr);
01182 }
01183
01184
if (matches) {
01185
int i;
01186
int matches_num, maxlen, match_len;
01187
01188
if (matches[0][0] !=
'\0') {
01189 el_deletestr(el, (
int) len);
01190 el_insertstr(el, matches[0]);
01191 retval = CC_REFRESH;
01192 }
01193
01194
if (nummatches == 1) {
01195
01196 el_insertstr(el,
" ");
01197 retval = CC_REFRESH;
01198 }
else {
01199
01200
for (i=1, maxlen=0; matches[i]; i++) {
01201 match_len = strlen(matches[i]);
01202
if (match_len > maxlen)
01203 maxlen = match_len;
01204 }
01205 matches_num = i - 1;
01206
if (matches_num >1) {
01207 fprintf(stdout,
"\n");
01208 ast_cli_display_match_list(matches, nummatches, maxlen);
01209 retval = CC_REDISPLAY;
01210 }
else {
01211 el_insertstr(el,
" ");
01212 retval = CC_REFRESH;
01213 }
01214 }
01215
free(matches);
01216 }
01217
01218
return (
char *)retval;
01219 }
01220
01221
static int ast_el_initialize(
void)
01222 {
01223 HistEvent ev;
01224
01225
if (el != NULL)
01226 el_end(el);
01227
if (el_hist != NULL)
01228 history_end(el_hist);
01229
01230 el = el_init(
"asterisk", stdin, stdout, stderr);
01231 el_set(el, EL_PROMPT, cli_prompt);
01232
01233 el_set(el, EL_EDITMODE, 1);
01234 el_set(el, EL_EDITOR,
"emacs");
01235 el_hist = history_init();
01236
if (!el || !el_hist)
01237
return -1;
01238
01239
01240 history(el_hist, &ev, H_SETSIZE, 100);
01241
01242 el_set(el, EL_HIST, history, el_hist);
01243
01244 el_set(el, EL_ADDFN,
"ed-complete",
"Complete argument", cli_complete);
01245
01246 el_set(el, EL_BIND,
"^I",
"ed-complete", NULL);
01247
01248 el_set(el, EL_BIND,
"?",
"ed-complete", NULL);
01249
01250 el_set(el, EL_BIND,
"^D",
"ed-redisplay", NULL);
01251
01252
return 0;
01253 }
01254
01255
static int ast_el_add_history(
char *buf)
01256 {
01257 HistEvent ev;
01258
01259
if (el_hist == NULL || el == NULL)
01260 ast_el_initialize();
01261
if (strlen(buf) > 256)
01262
return 0;
01263
return (history(el_hist, &ev, H_ENTER, buf));
01264 }
01265
01266
static int ast_el_write_history(
char *filename)
01267 {
01268 HistEvent ev;
01269
01270
if (el_hist == NULL || el == NULL)
01271 ast_el_initialize();
01272
01273
return (history(el_hist, &ev, H_SAVE, filename));
01274 }
01275
01276
static int ast_el_read_history(
char *filename)
01277 {
01278
char buf[256];
01279 FILE *f;
01280
int ret = -1;
01281
01282
if (el_hist == NULL || el == NULL)
01283 ast_el_initialize();
01284
01285
if ((f = fopen(filename,
"r")) == NULL)
01286
return ret;
01287
01288
while (!feof(f)) {
01289 fgets(buf,
sizeof(buf), f);
01290
if (!strcmp(buf,
"_HiStOrY_V2_\n"))
01291
continue;
01292
if ((ret = ast_el_add_history(buf)) == -1)
01293
break;
01294 }
01295 fclose(f);
01296
01297
return ret;
01298 }
01299
01300
static void ast_remotecontrol(
char * data)
01301 {
01302
char buf[80];
01303
int res;
01304
char filename[80] =
"";
01305
char *hostname;
01306
char *cpid;
01307
char *version;
01308
int pid;
01309
char tmp[80];
01310
char *stringp=NULL;
01311
01312
char *ebuf;
01313
int num = 0;
01314
01315 read(ast_consock, buf,
sizeof(buf));
01316
if (data)
01317 write(ast_consock, data, strlen(data) + 1);
01318 stringp=buf;
01319 hostname = strsep(&stringp,
"/");
01320 cpid = strsep(&stringp,
"/");
01321 version = strsep(&stringp,
"\n");
01322
if (!version)
01323 version =
"<Version Unknown>";
01324 stringp=hostname;
01325 strsep(&stringp,
".");
01326
if (cpid)
01327 pid = atoi(cpid);
01328
else
01329 pid = -1;
01330 snprintf(tmp,
sizeof(tmp),
"set verbose atleast %d", option_verbose);
01331 fdprint(ast_consock, tmp);
01332
ast_verbose(
"Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
01333 remotehostname = hostname;
01334
if (getenv(
"HOME"))
01335 snprintf(filename,
sizeof(filename),
"%s/.asterisk_history", getenv(
"HOME"));
01336
if (el_hist == NULL || el == NULL)
01337 ast_el_initialize();
01338
01339 el_set(el, EL_GETCFN, ast_el_read_char);
01340
01341
if (!ast_strlen_zero(filename))
01342 ast_el_read_history(filename);
01343
01344
ast_cli_register(&quit);
01345
ast_cli_register(&astexit);
01346
#if 0
01347
ast_cli_register(&astshutdown);
01348
#endif
01349
if (
option_exec && data) {
01350
char tempchar;
01351 ast_el_read_char(el, &tempchar);
01352
return;
01353 }
01354
for(;;) {
01355 ebuf = (
char *)el_gets(el, &num);
01356
01357
if (ebuf && !ast_strlen_zero(ebuf)) {
01358
if (ebuf[strlen(ebuf)-1] ==
'\n')
01359 ebuf[strlen(ebuf)-1] =
'\0';
01360
if (!remoteconsolehandler(ebuf)) {
01361 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
01362
if (res < 1) {
01363
ast_log(LOG_WARNING,
"Unable to write: %s\n", strerror(errno));
01364
break;
01365 }
01366 }
01367 }
01368 }
01369 printf(
"\nDisconnected from Asterisk server\n");
01370 }
01371
01372
static int show_cli_help(
void) {
01373 printf(
"Asterisk " ASTERISK_VERSION
", Copyright (C) 2000-2004, Digium.\n");
01374 printf(
"Usage: asterisk [OPTIONS]\n");
01375 printf(
"Valid Options:\n");
01376 printf(
" -C <configfile> Use an alternate configuration file\n");
01377 printf(
" -c Provide console CLI\n");
01378 printf(
" -d Enable extra debugging\n");
01379 printf(
" -f Do not fork\n");
01380 printf(
" -g Dump core in case of a crash\n");
01381 printf(
" -h This help screen\n");
01382 printf(
" -i Initializie crypto keys at startup\n");
01383 printf(
" -n Disable console colorization\n");
01384 printf(
" -p Run as pseudo-realtime thread\n");
01385 printf(
" -q Quiet mode (supress output)\n");
01386 printf(
" -r Connect to Asterisk on this machine\n");
01387 printf(
" -v Increase verbosity (multiple v's = more verbose)\n");
01388 printf(
" -x <cmd> Execute command <cmd> (only valid with -r)\n");
01389 printf(
"\n");
01390
return 0;
01391 }
01392
01393
static void ast_readconfig(
void) {
01394
struct ast_config *cfg;
01395
struct ast_variable *v;
01396
char *config = ASTCONFPATH;
01397
01398
if (
option_overrideconfig == 1) {
01399 cfg =
ast_load((
char *)ast_config_AST_CONFIG_FILE);
01400 }
else {
01401 cfg =
ast_load(config);
01402 }
01403
01404
01405 strncpy((
char *)ast_config_AST_CONFIG_DIR,AST_CONFIG_DIR,
sizeof(ast_config_AST_CONFIG_DIR)-1);
01406 strncpy((
char *)ast_config_AST_SPOOL_DIR,AST_SPOOL_DIR,
sizeof(ast_config_AST_SPOOL_DIR)-1);
01407 strncpy((
char *)ast_config_AST_MODULE_DIR,AST_MODULE_DIR,
sizeof(ast_config_AST_VAR_DIR)-1);
01408 strncpy((
char *)ast_config_AST_VAR_DIR,AST_VAR_DIR,
sizeof(ast_config_AST_VAR_DIR)-1);
01409 strncpy((
char *)ast_config_AST_LOG_DIR,AST_LOG_DIR,
sizeof(ast_config_AST_LOG_DIR)-1);
01410 strncpy((
char *)ast_config_AST_AGI_DIR,AST_AGI_DIR,
sizeof(ast_config_AST_AGI_DIR)-1);
01411 strncpy((
char *)ast_config_AST_DB,AST_DB,
sizeof(ast_config_AST_DB)-1);
01412 strncpy((
char *)ast_config_AST_KEY_DIR,AST_KEY_DIR,
sizeof(ast_config_AST_KEY_DIR)-1);
01413 strncpy((
char *)ast_config_AST_PID,AST_PID,
sizeof(ast_config_AST_PID)-1);
01414 strncpy((
char *)ast_config_AST_SOCKET,AST_SOCKET,
sizeof(ast_config_AST_SOCKET)-1);
01415 strncpy((
char *)ast_config_AST_RUN_DIR,AST_RUN_DIR,
sizeof(ast_config_AST_RUN_DIR)-1);
01416
01417
01418
if (!cfg) {
01419
return;
01420 }
01421 v =
ast_variable_browse(cfg,
"directories");
01422
while(v) {
01423
if (!strcasecmp(v->name,
"astetcdir")) {
01424 strncpy((
char *)ast_config_AST_CONFIG_DIR,v->value,
sizeof(ast_config_AST_CONFIG_DIR)-1);
01425 }
else if (!strcasecmp(v->name,
"astspooldir")) {
01426 strncpy((
char *)ast_config_AST_SPOOL_DIR,v->value,
sizeof(ast_config_AST_SPOOL_DIR)-1);
01427 }
else if (!strcasecmp(v->name,
"astvarlibdir")) {
01428 strncpy((
char *)ast_config_AST_VAR_DIR,v->value,
sizeof(ast_config_AST_VAR_DIR)-1);
01429 snprintf((
char *)ast_config_AST_DB,
sizeof(ast_config_AST_DB)-1,
"%s/%s",v->value,
"astdb");
01430 }
else if (!strcasecmp(v->name,
"astlogdir")) {
01431 strncpy((
char *)ast_config_AST_LOG_DIR,v->value,
sizeof(ast_config_AST_LOG_DIR)-1);
01432 }
else if (!strcasecmp(v->name,
"astagidir")) {
01433 strncpy((
char *)ast_config_AST_AGI_DIR,v->value,
sizeof(ast_config_AST_AGI_DIR)-1);
01434 }
else if (!strcasecmp(v->name,
"astrundir")) {
01435 snprintf((
char *)ast_config_AST_PID,
sizeof(ast_config_AST_PID)-1,
"%s/%s",v->value,
"asterisk.pid");
01436 snprintf((
char *)ast_config_AST_SOCKET,
sizeof(ast_config_AST_SOCKET)-1,
"%s/%s",v->value,
"asterisk.ctl");
01437 strncpy((
char *)ast_config_AST_RUN_DIR,v->value,
sizeof(ast_config_AST_RUN_DIR)-1);
01438 }
else if (!strcasecmp(v->name,
"astmoddir")) {
01439 strncpy((
char *)ast_config_AST_MODULE_DIR,v->value,
sizeof(ast_config_AST_MODULE_DIR)-1);
01440 }
01441 v = v->next;
01442 }
01443
ast_destroy(cfg);
01444 }
01445
01446 int main(
int argc,
char *argv[])
01447 {
01448
int c;
01449
char filename[80] =
"";
01450
char hostname[256];
01451
char tmp[80];
01452
char * xarg = NULL;
01453
int x;
01454 FILE *f;
01455 sigset_t sigs;
01456
int num;
01457
char *buf;
01458
01459
01460
if (argc >
sizeof(_argv) /
sizeof(_argv[0]) - 1) {
01461 fprintf(stderr,
"Truncating argument size to %d\n",
sizeof(_argv) /
sizeof(_argv[0]) - 1);
01462 argc =
sizeof(_argv) /
sizeof(_argv[0]) - 1;
01463 }
01464
for (x=0;x<argc;x++)
01465 _argv[x] = argv[x];
01466 _argv[x] = NULL;
01467
01468
01469
if ( argv[0] && (strstr(argv[0],
"rasterisk")) != NULL) {
01470
option_remote++;
01471
option_nofork++;
01472 }
01473
if (gethostname(hostname,
sizeof(hostname)))
01474 strncpy(hostname,
"<Unknown>",
sizeof(hostname)-1);
01475
ast_mainpid = getpid();
01476
ast_ulaw_init();
01477
ast_alaw_init();
01478
callerid_init();
01479
tdd_init();
01480
if (getenv(
"HOME"))
01481 snprintf(filename,
sizeof(filename),
"%s/.asterisk_history", getenv(
"HOME"));
01482
01483
01484
01485
01486
01487
01488
01489
01490
while((c=getopt(argc, argv,
"hfdvqprgcinx:C:")) != -1) {
01491
switch(c) {
01492
case 'd':
01493
option_debug++;
01494
option_nofork++;
01495
break;
01496
case 'c':
01497
option_console++;
01498
option_nofork++;
01499
break;
01500
case 'f':
01501
option_nofork++;
01502
break;
01503
case 'n':
01504
option_nocolor++;
01505
break;
01506
case 'r':
01507
option_remote++;
01508
option_nofork++;
01509
break;
01510
case 'p':
01511
option_highpriority++;
01512
break;
01513
case 'v':
01514
option_verbose++;
01515
option_nofork++;
01516
break;
01517
case 'q':
01518
option_quiet++;
01519
break;
01520
case 'x':
01521
option_exec++;
01522 xarg = optarg;
01523
break;
01524
case 'C':
01525 strncpy((
char *)
ast_config_AST_CONFIG_FILE,optarg,
sizeof(
ast_config_AST_CONFIG_FILE));
01526
option_overrideconfig++;
01527
break;
01528
case 'i':
01529
option_initcrypto++;
01530
break;
01531
case'g':
01532
option_dumpcore++;
01533
break;
01534
case 'h':
01535 show_cli_help();
01536 exit(0);
01537
case '?':
01538 exit(1);
01539 }
01540 }
01541
01542
if (
option_dumpcore) {
01543
struct rlimit l;
01544 memset(&l, 0,
sizeof(l));
01545 l.rlim_cur = RLIM_INFINITY;
01546 l.rlim_max = RLIM_INFINITY;
01547
if (setrlimit(RLIMIT_CORE, &l)) {
01548
ast_log(
LOG_WARNING,
"Unable to disable core size resource limit: %s\n", strerror(errno));
01549 }
01550 }
01551
01552
term_init();
01553 printf(
term_end());
01554 fflush(stdout);
01555
if (
option_console && !
option_verbose)
01556
ast_verbose(
"[ Reading Master Configuration ]");
01557 ast_readconfig();
01558
01559
if (
option_console) {
01560
if (el_hist == NULL || el == NULL)
01561 ast_el_initialize();
01562
01563
if (!ast_strlen_zero(filename))
01564 ast_el_read_history(filename);
01565 }
01566
01567
if (ast_tryconnect()) {
01568
01569
if (
option_remote) {
01570
if (
option_exec) {
01571 ast_remotecontrol(xarg);
01572 quit_handler(0, 0, 0, 0);
01573 exit(0);
01574 }
01575 printf(
term_quit());
01576
ast_register_verbose(console_verboser);
01577
ast_verbose(
"Asterisk " ASTERISK_VERSION
", Copyright (C) 1999-2004 Digium.\n");
01578
ast_verbose(
"Written by Mark Spencer <markster@digium.com>\n");
01579
ast_verbose(
"=========================================================================\n");
01580 ast_remotecontrol(NULL);
01581 quit_handler(0, 0, 0, 0);
01582 exit(0);
01583 }
else {
01584
ast_log(
LOG_ERROR,
"Asterisk already running on %s. Use 'asterisk -r' to connect.\n", (
char *)
ast_config_AST_SOCKET);
01585 printf(
term_quit());
01586 exit(1);
01587 }
01588 }
else if (
option_remote ||
option_exec) {
01589
ast_log(
LOG_ERROR,
"Unable to connect to remote asterisk\n");
01590 printf(
term_quit());
01591 exit(1);
01592 }
01593
01594 unlink((
char *)
ast_config_AST_PID);
01595 f = fopen((
char *)
ast_config_AST_PID,
"w");
01596
if (f) {
01597 fprintf(f,
"%d\n", getpid());
01598 fclose(f);
01599 }
else
01600
ast_log(
LOG_WARNING,
"Unable to open pid file '%s': %s\n", (
char *)
ast_config_AST_PID, strerror(errno));
01601
01602
if (!
option_verbose && !
option_debug && !
option_nofork && !
option_console) {
01603 daemon(0,0);
01604
01605 unlink((
char *)
ast_config_AST_PID);
01606 f = fopen((
char *)
ast_config_AST_PID,
"w");
01607
if (f) {
01608 fprintf(f,
"%d\n", getpid());
01609 fclose(f);
01610 }
else
01611
ast_log(
LOG_WARNING,
"Unable to open pid file '%s': %s\n", (
char *)
ast_config_AST_PID, strerror(errno));
01612 }
01613
01614 ast_makesocket();
01615 sigemptyset(&sigs);
01616 sigaddset(&sigs, SIGHUP);
01617 sigaddset(&sigs, SIGTERM);
01618 sigaddset(&sigs, SIGINT);
01619 sigaddset(&sigs, SIGPIPE);
01620 sigaddset(&sigs, SIGWINCH);
01621 pthread_sigmask(SIG_BLOCK, &sigs, NULL);
01622
if (
option_console ||
option_verbose ||
option_remote)
01623
ast_register_verbose(console_verboser);
01624
01625
if (
option_verbose ||
option_console) {
01626
ast_verbose(
"Asterisk " ASTERISK_VERSION
", Copyright (C) 1999-2004 Digium.\n");
01627
ast_verbose(
"Written by Mark Spencer <markster@digium.com>\n");
01628
ast_verbose(
"=========================================================================\n");
01629 }
01630
if (
option_console && !
option_verbose)
01631
ast_verbose(
"[ Booting...");
01632
01633 signal(SIGURG, urg_handler);
01634 signal(SIGINT, __quit_handler);
01635 signal(SIGTERM, __quit_handler);
01636 signal(SIGHUP, hup_handler);
01637 signal(SIGCHLD, child_handler);
01638 signal(SIGPIPE, SIG_IGN);
01639
01640
if (set_priority(
option_highpriority)) {
01641 printf(
term_quit());
01642 exit(1);
01643 }
01644
if (
init_logger()) {
01645 printf(
term_quit());
01646 exit(1);
01647 }
01648
if (
init_manager()) {
01649 printf(
term_quit());
01650 exit(1);
01651 }
01652
ast_rtp_init();
01653
if (
ast_image_init()) {
01654 printf(
term_quit());
01655 exit(1);
01656 }
01657
if (
load_pbx()) {
01658 printf(
term_quit());
01659 exit(1);
01660 }
01661
if (
load_modules()) {
01662 printf(
term_quit());
01663 exit(1);
01664 }
01665
if (
init_framer()) {
01666 printf(
term_quit());
01667 exit(1);
01668 }
01669
if (
astdb_init()) {
01670 printf(
term_quit());
01671 exit(1);
01672 }
01673
if (
ast_enum_init()) {
01674 printf(
term_quit());
01675 exit(1);
01676 }
01677
01678
01679
if (
option_console && !
option_verbose)
01680
ast_verbose(
" ]\n");
01681
if (
option_verbose ||
option_console)
01682
ast_verbose(
term_color(tmp,
"Asterisk Ready.\n",
COLOR_BRWHITE,
COLOR_BLACK,
sizeof(tmp)));
01683
if (
option_nofork)
01684 consolethread = pthread_self();
01685
fully_booted = 1;
01686 pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
01687
#ifdef __AST_DEBUG_MALLOC
01688
__ast_mm_init();
01689
#endif
01690
time(&
ast_startuptime);
01691
ast_cli_register(&astshutdownnow);
01692
ast_cli_register(&astshutdowngracefully);
01693
ast_cli_register(&astrestartnow);
01694
ast_cli_register(&astrestartgracefully);
01695
ast_cli_register(&astrestartwhenconvenient);
01696
ast_cli_register(&astshutdownwhenconvenient);
01697
ast_cli_register(&aborthalt);
01698
ast_cli_register(&astbang);
01699
if (
option_console) {
01700
01701
01702
char title[256];
01703 set_icon(
"Asterisk");
01704 snprintf(title,
sizeof(title),
"Asterisk Console on '%s' (pid %d)", hostname,
ast_mainpid);
01705 set_title(title);
01706
ast_cli_register(&quit);
01707
ast_cli_register(&astexit);
01708
01709
for (;;) {
01710 buf = (
char *)el_gets(el, &num);
01711
if (buf) {
01712
if (buf[strlen(buf)-1] ==
'\n')
01713 buf[strlen(buf)-1] =
'\0';
01714
01715 consolehandler((
char *)buf);
01716 }
else {
01717
if (
option_remote)
01718
ast_cli(STDOUT_FILENO,
"\nUse EXIT or QUIT to exit the asterisk console\n");
01719 }
01720 }
01721
01722 }
else {
01723
01724
for(;;)
01725
poll(NULL,0, -1);
01726 }
01727
return 0;
01728 }