Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

asterisk.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- A telephony toolkit for Linux.
00003  *
00004  * Top level source file for asterisk
00005  * 
00006  * Copyright (C) 1999, Mark Spencer
00007  *
00008  * Mark Spencer <markster@linux-support.net>
00009  *
00010  * This program is free software, distributed under the terms of
00011  * the GNU General Public License
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;      /* UNIX Socket for allowing remote control */
00066 static int ast_consock = -1;     /* UNIX Socket for controlling another asterisk */
00067 static int mainpid;
00068 struct console {
00069    int fd;              /* File descriptor */
00070    int p[2];            /* Pipe */
00071    pthread_t t;         /* Thread of handler */
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(&lthread, 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    /* Called by soft_hangup to interrupt the select, read, or other
00327       system call.  We don't actually need to do anything though.  */
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    /* Ignore sigpipe */
00345 }
00346 static void set_title(char *text)
00347 {
00348    /* Set an X-term or screen title */
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    /* We set ourselves to a high priority, that we might pre-empt everything
00364       else.  If your PBX has heavy activity on it, this is a good thing.  */
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          /* Begin shutdown routine, hanging up active channels */
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             /* Wait up to 15 seconds for all channels to go away */
00432             if ((e - s) > 15)
00433                break;
00434             if (!ast_active_channels())
00435                break;
00436             if (!shuttingdown)
00437                break;
00438             /* Sleep 1/10 of a second */
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    /* Called on exit */
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       /* Mark all FD's for closing on exec */
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    /* Return to the beginning of the line */
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    /* Wake up a select()ing console */
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    /* Called when readline data is available */
00551    if (s && strlen(s))
00552       ast_el_add_history(s);
00553    /* Give the console access to the shell */
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    /* Called when readline data is available */
00572    if (s && strlen(s))
00573       ast_el_add_history(s);
00574    /* Give the console access to the shell */
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 /* Not nice */, 1 /* safely */, 0 /* not restart */);
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 /* nicely */, 1 /* safely */, 0 /* no restart */);
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 /* really nicely */, 1 /* safely */, 0 /* don't restart */);
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 /* not nicely */, 1 /* safely */, 1 /* restart */);
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 /* nicely */, 1 /* safely */, 1 /* restart */);
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 /* really nicely */, 1 /* safely */, 1 /* restart */);
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          /* if the remote side disappears exit */
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    /* find out how many entries can be put on one line, with two spaces between strings */
00844    limit = screenwidth / (max + 2);
00845    if (limit == 0)
00846       limit = 1;
00847 
00848    /* how many lines of output */
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          /* Don't print dupes */
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          /* Found an exact match */
00940          el_insertstr(el, " ");
00941          retval = CC_REFRESH;
00942       } else {
00943          /* Must be more than one match */
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    /* setup history with 100 entries */
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    /* Bind <tab> to command completion */
00990    el_set(el, EL_BIND, "^I", "ed-complete", NULL);
00991    /* Bind ? to command completion */
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) {  /* hack to print output then exit if asterisk -rx is used */
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    /* init with buildtime config */
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    /* no asterisk.conf? no problem, use buildtime config! */
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    /* Remember original args for restart */
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    /* Check for options */
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       /* One is already running */
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    /* Blindly write pid file since we couldn't connect */
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    /* Print a welcome message if desired */
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    /* We might have the option of showing a console, but for now just
01407       do nothing... */
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       /* Console stuff now... */
01427       /* Register our quit function */
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       /* Do nothing */
01453       ast_select(0,NULL,NULL,NULL,NULL);
01454    }
01455    return 0;
01456 }

Generated on Fri Oct 31 07:05:04 2003 for Asterisk by doxygen 1.3.4