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