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