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