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