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