00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 #include <unistd.h>
00062 #include <stdlib.h>
00063 #include <sys/time.h>
00064 #include <fcntl.h>
00065 #include <stdio.h>
00066 #include <signal.h>
00067 #include <sched.h>
00068 #include <sys/socket.h>
00069 #include <sys/un.h>
00070 #include <sys/wait.h>
00071 #include <string.h>
00072 #include <errno.h>
00073 #include <ctype.h>
00074 #include <sys/resource.h>
00075 #include <grp.h>
00076 #include <pwd.h>
00077 #include <sys/stat.h>
00078 #include <regex.h>
00079
00080 #ifdef linux
00081 #include <sys/prctl.h>
00082 #endif
00083
00084 #if defined(__FreeBSD__) || defined( __NetBSD__ ) || defined(SOLARIS)
00085 #include <netdb.h>
00086 #if defined(SOLARIS)
00087 extern int daemon(int, int);
00088 #endif
00089 #endif
00090
00091 #include "asterisk.h"
00092
00093 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 72373 $")
00094
00095 #include "asterisk/logger.h"
00096 #include "asterisk/options.h"
00097 #include "asterisk/cli.h"
00098 #include "asterisk/channel.h"
00099 #include "asterisk/ulaw.h"
00100 #include "asterisk/alaw.h"
00101 #include "asterisk/callerid.h"
00102 #include "asterisk/module.h"
00103 #include "asterisk/image.h"
00104 #include "asterisk/tdd.h"
00105 #include "asterisk/term.h"
00106 #include "asterisk/manager.h"
00107 #include "asterisk/cdr.h"
00108 #include "asterisk/pbx.h"
00109 #include "asterisk/enum.h"
00110 #include "asterisk/rtp.h"
00111 #include "asterisk/app.h"
00112 #include "asterisk/lock.h"
00113 #include "asterisk/utils.h"
00114 #include "asterisk/file.h"
00115 #include "asterisk/io.h"
00116 #include "asterisk/lock.h"
00117 #include "editline/histedit.h"
00118 #include "asterisk/config.h"
00119 #include "asterisk/version.h"
00120 #include "asterisk/linkedlists.h"
00121 #include "asterisk/devicestate.h"
00122 #include "asterisk/compat.h"
00123
00124 #include "asterisk/doxyref.h"
00125
00126 #include "defaults.h"
00127
00128 #ifndef AF_LOCAL
00129 #define AF_LOCAL AF_UNIX
00130 #define PF_LOCAL PF_UNIX
00131 #endif
00132
00133 #define AST_MAX_CONNECTS 128
00134 #define NUM_MSGS 64
00135
00136
00137 #define WELCOME_MESSAGE \
00138 ast_verbose("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2007 Digium, Inc. and others.\n"); \
00139 ast_verbose("Created by Mark Spencer <markster@digium.com>\n"); \
00140 ast_verbose("Asterisk comes with ABSOLUTELY NO WARRANTY; type 'show warranty' for details.\n"); \
00141 ast_verbose("This is free software, with components licensed under the GNU General Public\n"); \
00142 ast_verbose("License version 2 and other licenses; you are welcome to redistribute it under\n"); \
00143 ast_verbose("certain conditions. Type 'show license' for details.\n"); \
00144 ast_verbose("=========================================================================\n")
00145
00146
00147
00148
00149
00150
00151
00152 int option_verbose=0;
00153 int option_debug=0;
00154 int option_exec_includes=0;
00155 int option_nofork=0;
00156 int option_quiet=0;
00157 int option_console=0;
00158 int option_highpriority=0;
00159 int option_remote=0;
00160 int option_exec=0;
00161 int option_initcrypto=0;
00162 int option_nocolor;
00163 int option_dumpcore = 0;
00164 int option_cache_record_files = 0;
00165 int option_timestamp = 0;
00166 int option_overrideconfig = 0;
00167 int option_reconnect = 0;
00168 int option_transcode_slin = 1;
00169 int option_maxcalls = 0;
00170 double option_maxload = 0.0;
00171 int option_dontwarn = 0;
00172 int option_priority_jumping = 1;
00173 int option_transmit_silence_during_record = 0;
00174
00175
00176
00177 int fully_booted = 0;
00178 char record_cache_dir[AST_CACHE_DIR_LEN] = AST_TMP_DIR;
00179 char debug_filename[AST_FILENAME_MAX] = "";
00180
00181 static int ast_socket = -1;
00182 static int ast_consock = -1;
00183 int ast_mainpid;
00184 struct console {
00185 int fd;
00186 int p[2];
00187 pthread_t t;
00188 };
00189
00190 static struct ast_atexit {
00191 void (*func)(void);
00192 struct ast_atexit *next;
00193 } *atexits = NULL;
00194
00195 AST_MUTEX_DEFINE_STATIC(atexitslock);
00196
00197 time_t ast_startuptime;
00198 time_t ast_lastreloadtime;
00199
00200 static History *el_hist = NULL;
00201 static EditLine *el = NULL;
00202 static char *remotehostname;
00203
00204 struct console consoles[AST_MAX_CONNECTS];
00205
00206 char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
00207
00208 static int ast_el_add_history(char *);
00209 static int ast_el_read_history(char *);
00210 static int ast_el_write_history(char *);
00211
00212 char ast_config_AST_CONFIG_DIR[AST_CONFIG_MAX_PATH];
00213 char ast_config_AST_CONFIG_FILE[AST_CONFIG_MAX_PATH];
00214 char ast_config_AST_MODULE_DIR[AST_CONFIG_MAX_PATH];
00215 char ast_config_AST_SPOOL_DIR[AST_CONFIG_MAX_PATH];
00216 char ast_config_AST_MONITOR_DIR[AST_CONFIG_MAX_PATH];
00217 char ast_config_AST_VAR_DIR[AST_CONFIG_MAX_PATH];
00218 char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH];
00219 char ast_config_AST_AGI_DIR[AST_CONFIG_MAX_PATH];
00220 char ast_config_AST_DB[AST_CONFIG_MAX_PATH];
00221 char ast_config_AST_KEY_DIR[AST_CONFIG_MAX_PATH];
00222 char ast_config_AST_PID[AST_CONFIG_MAX_PATH];
00223 char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH];
00224 char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH];
00225 char ast_config_AST_RUN_USER[AST_CONFIG_MAX_PATH];
00226 char ast_config_AST_RUN_GROUP[AST_CONFIG_MAX_PATH];
00227 char ast_config_AST_CTL_PERMISSIONS[AST_CONFIG_MAX_PATH];
00228 char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH] = "\0";
00229 char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH] = "\0";
00230 char ast_config_AST_CTL[AST_CONFIG_MAX_PATH] = "asterisk.ctl";
00231
00232 static char *_argv[256];
00233 static int shuttingdown = 0;
00234 static int restartnow = 0;
00235 static pthread_t consolethread = AST_PTHREADT_NULL;
00236
00237 static int sig_alert_pipe[2] = { -1, -1 };
00238 static struct {
00239 unsigned int need_reload:1;
00240 unsigned int need_quit:1;
00241 } sig_flags;
00242
00243 #if !defined(LOW_MEMORY)
00244 struct file_version {
00245 AST_LIST_ENTRY(file_version) list;
00246 const char *file;
00247 char *version;
00248 };
00249
00250 static AST_LIST_HEAD_STATIC(file_versions, file_version);
00251
00252 void ast_register_file_version(const char *file, const char *version)
00253 {
00254 struct file_version *new;
00255 char *work;
00256 size_t version_length;
00257
00258 work = ast_strdupa(version);
00259 work = ast_strip(ast_strip_quoted(work, "$", "$"));
00260 version_length = strlen(work) + 1;
00261
00262 new = calloc(1, sizeof(*new) + version_length);
00263 if (!new)
00264 return;
00265
00266 new->file = file;
00267 new->version = (char *) new + sizeof(*new);
00268 memcpy(new->version, work, version_length);
00269 AST_LIST_LOCK(&file_versions);
00270 AST_LIST_INSERT_HEAD(&file_versions, new, list);
00271 AST_LIST_UNLOCK(&file_versions);
00272 }
00273
00274 void ast_unregister_file_version(const char *file)
00275 {
00276 struct file_version *find;
00277
00278 AST_LIST_LOCK(&file_versions);
00279 AST_LIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) {
00280 if (!strcasecmp(find->file, file)) {
00281 AST_LIST_REMOVE_CURRENT(&file_versions, list);
00282 break;
00283 }
00284 }
00285 AST_LIST_TRAVERSE_SAFE_END;
00286 AST_LIST_UNLOCK(&file_versions);
00287 if (find)
00288 free(find);
00289 }
00290
00291 static char show_version_files_help[] =
00292 "Usage: show version files [like <pattern>]\n"
00293 " Shows the revision numbers of the files used to build this copy of Asterisk.\n"
00294 " Optional regular expression pattern is used to filter the file list.\n";
00295
00296
00297 static int handle_show_version_files(int fd, int argc, char *argv[])
00298 {
00299 #define FORMAT "%-25.25s %-40.40s\n"
00300 struct file_version *iterator;
00301 regex_t regexbuf;
00302 int havepattern = 0;
00303 int havename = 0;
00304 int count_files = 0;
00305
00306 switch (argc) {
00307 case 5:
00308 if (!strcasecmp(argv[3], "like")) {
00309 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB))
00310 return RESULT_SHOWUSAGE;
00311 havepattern = 1;
00312 } else
00313 return RESULT_SHOWUSAGE;
00314 break;
00315 case 4:
00316 havename = 1;
00317 break;
00318 case 3:
00319 break;
00320 default:
00321 return RESULT_SHOWUSAGE;
00322 }
00323
00324 ast_cli(fd, FORMAT, "File", "Revision");
00325 ast_cli(fd, FORMAT, "----", "--------");
00326 AST_LIST_LOCK(&file_versions);
00327 AST_LIST_TRAVERSE(&file_versions, iterator, list) {
00328 if (havename && strcasecmp(iterator->file, argv[3]))
00329 continue;
00330
00331 if (havepattern && regexec(®exbuf, iterator->file, 0, NULL, 0))
00332 continue;
00333
00334 ast_cli(fd, FORMAT, iterator->file, iterator->version);
00335 count_files++;
00336 if (havename)
00337 break;
00338 }
00339 AST_LIST_UNLOCK(&file_versions);
00340 if (!havename) {
00341 ast_cli(fd, "%d files listed.\n", count_files);
00342 }
00343
00344 if (havepattern)
00345 regfree(®exbuf);
00346
00347 return RESULT_SUCCESS;
00348 #undef FORMAT
00349 }
00350
00351 static char *complete_show_version_files(char *line, char *word, int pos, int state)
00352 {
00353 struct file_version *find;
00354 int which = 0;
00355 char *ret = NULL;
00356 int matchlen = strlen(word);
00357
00358 if (pos != 3)
00359 return NULL;
00360
00361 AST_LIST_LOCK(&file_versions);
00362 AST_LIST_TRAVERSE(&file_versions, find, list) {
00363 if (!strncasecmp(word, find->file, matchlen)) {
00364 if (++which > state) {
00365 ret = strdup(find->file);
00366 break;
00367 }
00368 }
00369 }
00370 AST_LIST_UNLOCK(&file_versions);
00371
00372 return ret;
00373 }
00374 #endif
00375
00376 int ast_register_atexit(void (*func)(void))
00377 {
00378 int res = -1;
00379 struct ast_atexit *ae;
00380 ast_unregister_atexit(func);
00381 ae = malloc(sizeof(struct ast_atexit));
00382 ast_mutex_lock(&atexitslock);
00383 if (ae) {
00384 memset(ae, 0, sizeof(struct ast_atexit));
00385 ae->next = atexits;
00386 ae->func = func;
00387 atexits = ae;
00388 res = 0;
00389 }
00390 ast_mutex_unlock(&atexitslock);
00391 return res;
00392 }
00393
00394 void ast_unregister_atexit(void (*func)(void))
00395 {
00396 struct ast_atexit *ae, *prev = NULL;
00397 ast_mutex_lock(&atexitslock);
00398 ae = atexits;
00399 while(ae) {
00400 if (ae->func == func) {
00401 if (prev)
00402 prev->next = ae->next;
00403 else
00404 atexits = ae->next;
00405 break;
00406 }
00407 prev = ae;
00408 ae = ae->next;
00409 }
00410 ast_mutex_unlock(&atexitslock);
00411 }
00412
00413 static int fdprint(int fd, const char *s)
00414 {
00415 return write(fd, s, strlen(s) + 1);
00416 }
00417
00418
00419 static void null_sig_handler(int signal)
00420 {
00421
00422 }
00423
00424 AST_MUTEX_DEFINE_STATIC(safe_system_lock);
00425 static unsigned int safe_system_level = 0;
00426 static void *safe_system_prev_handler;
00427
00428 int ast_safe_system(const char *s)
00429 {
00430 pid_t pid;
00431 int x;
00432 int res;
00433 struct rusage rusage;
00434 int status;
00435 unsigned int level;
00436
00437
00438
00439
00440 ast_mutex_lock(&safe_system_lock);
00441 level = safe_system_level++;
00442
00443
00444 if (level == 0)
00445 safe_system_prev_handler = signal(SIGCHLD, null_sig_handler);
00446
00447 ast_mutex_unlock(&safe_system_lock);
00448
00449 pid = fork();
00450
00451 if (pid == 0) {
00452 if (option_highpriority)
00453 ast_set_priority(0);
00454
00455 for (x = STDERR_FILENO + 1; x < 4096; x++)
00456 close(x);
00457 execl("/bin/sh", "/bin/sh", "-c", s, NULL);
00458 _exit(1);
00459 } else if (pid > 0) {
00460 for(;;) {
00461 res = wait4(pid, &status, 0, &rusage);
00462 if (res > -1) {
00463 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
00464 break;
00465 } else if (errno != EINTR)
00466 break;
00467 }
00468 } else {
00469 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
00470 res = -1;
00471 }
00472
00473 ast_mutex_lock(&safe_system_lock);
00474 level = --safe_system_level;
00475
00476
00477 if (level == 0)
00478 signal(SIGCHLD, safe_system_prev_handler);
00479
00480 ast_mutex_unlock(&safe_system_lock);
00481
00482 return res;
00483 }
00484
00485
00486
00487
00488 static void ast_network_puts(const char *string)
00489 {
00490 int x;
00491 for (x=0;x<AST_MAX_CONNECTS; x++) {
00492 if (consoles[x].fd > -1)
00493 fdprint(consoles[x].p[1], string);
00494 }
00495 }
00496
00497
00498
00499
00500
00501 void ast_console_puts(const char *string)
00502 {
00503 fputs(string, stdout);
00504 fflush(stdout);
00505 ast_network_puts(string);
00506 }
00507
00508 static void network_verboser(const char *s, int pos, int replace, int complete)
00509
00510 {
00511 if (replace) {
00512 char *t = alloca(strlen(s) + 2);
00513 if (t) {
00514 sprintf(t, "\r%s", s);
00515 if (complete)
00516 ast_network_puts(t);
00517 } else {
00518 ast_log(LOG_ERROR, "Out of memory\n");
00519 ast_network_puts(s);
00520 }
00521 } else {
00522 if (complete)
00523 ast_network_puts(s);
00524 }
00525 }
00526
00527 static pthread_t lthread;
00528
00529 static void *netconsole(void *vconsole)
00530 {
00531 struct console *con = vconsole;
00532 char hostname[MAXHOSTNAMELEN]="";
00533 char tmp[512];
00534 int res;
00535 struct pollfd fds[2];
00536
00537 if (gethostname(hostname, sizeof(hostname)-1))
00538 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
00539 snprintf(tmp, sizeof(tmp), "%s/%d/%s\n", hostname, ast_mainpid, ASTERISK_VERSION);
00540 fdprint(con->fd, tmp);
00541 for(;;) {
00542 fds[0].fd = con->fd;
00543 fds[0].events = POLLIN;
00544 fds[0].revents = 0;
00545 fds[1].fd = con->p[0];
00546 fds[1].events = POLLIN;
00547 fds[1].revents = 0;
00548
00549 res = poll(fds, 2, -1);
00550 if (res < 0) {
00551 if (errno != EINTR)
00552 ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
00553 continue;
00554 }
00555 if (fds[0].revents) {
00556 res = read(con->fd, tmp, sizeof(tmp));
00557 if (res < 1) {
00558 break;
00559 }
00560 tmp[res] = 0;
00561 ast_cli_command(con->fd, tmp);
00562 }
00563 if (fds[1].revents) {
00564 res = read(con->p[0], tmp, sizeof(tmp));
00565 if (res < 1) {
00566 ast_log(LOG_ERROR, "read returned %d\n", res);
00567 break;
00568 }
00569 res = write(con->fd, tmp, res);
00570 if (res < 1)
00571 break;
00572 }
00573 }
00574 if (option_verbose > 2)
00575 ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection disconnected\n");
00576 close(con->fd);
00577 close(con->p[0]);
00578 close(con->p[1]);
00579 con->fd = -1;
00580
00581 return NULL;
00582 }
00583
00584 static void *listener(void *unused)
00585 {
00586 struct sockaddr_un sunaddr;
00587 int s;
00588 socklen_t len;
00589 int x;
00590 int flags;
00591 struct pollfd fds[1];
00592 pthread_attr_t attr;
00593 pthread_attr_init(&attr);
00594 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00595 for(;;) {
00596 if (ast_socket < 0)
00597 return NULL;
00598 fds[0].fd = ast_socket;
00599 fds[0].events= POLLIN;
00600 s = poll(fds, 1, -1);
00601 pthread_testcancel();
00602 if (s < 0) {
00603 if (errno != EINTR)
00604 ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
00605 continue;
00606 }
00607 len = sizeof(sunaddr);
00608 s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
00609 if (s < 0) {
00610 if (errno != EINTR)
00611 ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
00612 } else {
00613 for (x=0;x<AST_MAX_CONNECTS;x++) {
00614 if (consoles[x].fd < 0) {
00615 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
00616 ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
00617 consoles[x].fd = -1;
00618 fdprint(s, "Server failed to create pipe\n");
00619 close(s);
00620 break;
00621 }
00622 flags = fcntl(consoles[x].p[1], F_GETFL);
00623 fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
00624 consoles[x].fd = s;
00625 if (ast_pthread_create(&consoles[x].t, &attr, netconsole, &consoles[x])) {
00626 ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
00627 close(consoles[x].p[0]);
00628 close(consoles[x].p[1]);
00629 consoles[x].fd = -1;
00630 fdprint(s, "Server failed to spawn thread\n");
00631 close(s);
00632 }
00633 break;
00634 }
00635 }
00636 if (x >= AST_MAX_CONNECTS) {
00637 fdprint(s, "No more connections allowed\n");
00638 ast_log(LOG_WARNING, "No more connections allowed\n");
00639 close(s);
00640 } else if (consoles[x].fd > -1) {
00641 if (option_verbose > 2)
00642 ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection\n");
00643 }
00644 }
00645 }
00646 return NULL;
00647 }
00648
00649 static int ast_makesocket(void)
00650 {
00651 struct sockaddr_un sunaddr;
00652 int res;
00653 int x;
00654 uid_t uid = -1;
00655 gid_t gid = -1;
00656
00657 for (x = 0; x < AST_MAX_CONNECTS; x++)
00658 consoles[x].fd = -1;
00659 unlink(ast_config_AST_SOCKET);
00660 ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
00661 if (ast_socket < 0) {
00662 ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
00663 return -1;
00664 }
00665 memset(&sunaddr, 0, sizeof(sunaddr));
00666 sunaddr.sun_family = AF_LOCAL;
00667 ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
00668 res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
00669 if (res) {
00670 ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
00671 close(ast_socket);
00672 ast_socket = -1;
00673 return -1;
00674 }
00675 res = listen(ast_socket, 2);
00676 if (res < 0) {
00677 ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
00678 close(ast_socket);
00679 ast_socket = -1;
00680 return -1;
00681 }
00682 ast_register_verbose(network_verboser);
00683 ast_pthread_create(<hread, NULL, listener, NULL);
00684
00685 if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {
00686 struct passwd *pw;
00687 if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL) {
00688 ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
00689 } else {
00690 uid = pw->pw_uid;
00691 }
00692 }
00693
00694 if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) {
00695 struct group *grp;
00696 if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL) {
00697 ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
00698 } else {
00699 gid = grp->gr_gid;
00700 }
00701 }
00702
00703 if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
00704 ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
00705
00706 if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) {
00707 int p1;
00708 mode_t p;
00709 sscanf(ast_config_AST_CTL_PERMISSIONS, "%o", &p1);
00710 p = p1;
00711 if ((chmod(ast_config_AST_SOCKET, p)) < 0)
00712 ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
00713 }
00714
00715 return 0;
00716 }
00717
00718 static int ast_tryconnect(void)
00719 {
00720 struct sockaddr_un sunaddr;
00721 int res;
00722 ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
00723 if (ast_consock < 0) {
00724 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
00725 return 0;
00726 }
00727 memset(&sunaddr, 0, sizeof(sunaddr));
00728 sunaddr.sun_family = AF_LOCAL;
00729 ast_copy_string(sunaddr.sun_path, (char *)ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
00730 res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
00731 if (res) {
00732 close(ast_consock);
00733 ast_consock = -1;
00734 return 0;
00735 } else
00736 return 1;
00737 }
00738
00739
00740
00741
00742
00743
00744 static void urg_handler(int num)
00745 {
00746 signal(num, urg_handler);
00747 return;
00748 }
00749
00750 static void hup_handler(int num)
00751 {
00752 int a = 0;
00753 if (option_verbose > 1)
00754 printf("Received HUP signal -- Reloading configs\n");
00755 if (restartnow)
00756 execvp(_argv[0], _argv);
00757 sig_flags.need_reload = 1;
00758 if (sig_alert_pipe[1] != -1)
00759 write(sig_alert_pipe[1], &a, sizeof(a));
00760 signal(num, hup_handler);
00761 }
00762
00763 static void child_handler(int sig)
00764 {
00765
00766 int n, status;
00767
00768
00769
00770
00771 for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++)
00772 ;
00773 if (n == 0 && option_debug)
00774 printf("Huh? Child handler, but nobody there?\n");
00775 signal(sig, child_handler);
00776 }
00777
00778
00779 static void set_title(char *text)
00780 {
00781 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
00782 fprintf(stdout, "\033]2;%s\007", text);
00783 }
00784
00785 static void set_icon(char *text)
00786 {
00787 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
00788 fprintf(stdout, "\033]1;%s\007", text);
00789 }
00790
00791
00792
00793 int ast_set_priority(int pri)
00794 {
00795 struct sched_param sched;
00796 memset(&sched, 0, sizeof(sched));
00797 #ifdef __linux__
00798 #undef sched_setscheduler
00799 if (pri) {
00800 sched.sched_priority = 10;
00801 if (sched_setscheduler(0, SCHED_RR, &sched)) {
00802 ast_log(LOG_WARNING, "Unable to set high priority\n");
00803 return -1;
00804 } else
00805 if (option_verbose)
00806 ast_verbose("Set to realtime thread\n");
00807 } else {
00808 sched.sched_priority = 0;
00809
00810 sched_setscheduler(0, SCHED_OTHER, &sched);
00811 }
00812 #else
00813 #undef setpriority
00814 if (pri) {
00815 if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
00816 ast_log(LOG_WARNING, "Unable to set high priority\n");
00817 return -1;
00818 } else
00819 if (option_verbose)
00820 ast_verbose("Set to high priority\n");
00821 } else {
00822
00823 setpriority(PRIO_PROCESS, 0, 0);
00824 }
00825 #endif
00826 return 0;
00827 }
00828
00829 static void ast_run_atexits(void)
00830 {
00831 struct ast_atexit *ae;
00832 ast_mutex_lock(&atexitslock);
00833 ae = atexits;
00834 while(ae) {
00835 if (ae->func)
00836 ae->func();
00837 ae = ae->next;
00838 }
00839 ast_mutex_unlock(&atexitslock);
00840 }
00841
00842 static void quit_handler(int num, int nice, int safeshutdown, int restart)
00843 {
00844 char filename[80] = "";
00845 time_t s,e;
00846 int x;
00847
00848 ast_cdr_engine_term();
00849 if (safeshutdown) {
00850 shuttingdown = 1;
00851 if (!nice) {
00852
00853 ast_begin_shutdown(1);
00854 if (option_verbose && option_console)
00855 ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
00856 time(&s);
00857 for(;;) {
00858 time(&e);
00859
00860 if ((e - s) > 15)
00861 break;
00862 if (!ast_active_channels())
00863 break;
00864 if (!shuttingdown)
00865 break;
00866
00867 usleep(100000);
00868 }
00869 } else {
00870 if (nice < 2)
00871 ast_begin_shutdown(0);
00872 if (option_verbose && option_console)
00873 ast_verbose("Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
00874 for(;;) {
00875 if (!ast_active_channels())
00876 break;
00877 if (!shuttingdown)
00878 break;
00879 sleep(1);
00880 }
00881 }
00882
00883 if (!shuttingdown) {
00884 if (option_verbose && option_console)
00885 ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
00886 return;
00887 }
00888 }
00889 if (option_console || option_remote) {
00890 if (getenv("HOME"))
00891 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
00892 if (!ast_strlen_zero(filename))
00893 ast_el_write_history(filename);
00894 if (el != NULL)
00895 el_end(el);
00896 if (el_hist != NULL)
00897 history_end(el_hist);
00898 }
00899 if (option_verbose)
00900 ast_verbose("Executing last minute cleanups\n");
00901 ast_run_atexits();
00902
00903 if (option_verbose && option_console)
00904 ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);
00905 if (option_debug)
00906 ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num);
00907 manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\nRestart: %s\r\n", ast_active_channels() ? "Uncleanly" : "Cleanly", restart ? "True" : "False");
00908 if (ast_socket > -1) {
00909 pthread_cancel(lthread);
00910 close(ast_socket);
00911 ast_socket = -1;
00912 unlink(ast_config_AST_SOCKET);
00913 }
00914 if (ast_consock > -1)
00915 close(ast_consock);
00916 if (!option_remote) unlink((char *)ast_config_AST_PID);
00917 printf(term_quit());
00918 if (restart) {
00919 if (option_verbose || option_console)
00920 ast_verbose("Preparing for Asterisk restart...\n");
00921
00922 for (x=3;x<32768;x++) {
00923 fcntl(x, F_SETFD, FD_CLOEXEC);
00924 }
00925 if (option_verbose || option_console)
00926 ast_verbose("Restarting Asterisk NOW...\n");
00927 restartnow = 1;
00928
00929
00930 close_logger();
00931
00932
00933
00934 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
00935 pthread_kill(consolethread, SIGHUP);
00936
00937 sleep(2);
00938 } else
00939 execvp(_argv[0], _argv);
00940
00941 } else {
00942
00943 close_logger();
00944 }
00945 exit(0);
00946 }
00947
00948 static void __quit_handler(int num)
00949 {
00950 int a = 0;
00951 sig_flags.need_quit = 1;
00952 if (sig_alert_pipe[1] != -1)
00953 write(sig_alert_pipe[1], &a, sizeof(a));
00954
00955
00956 }
00957
00958 static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp)
00959 {
00960 const char *c;
00961 if (!strncmp(s, cmp, strlen(cmp))) {
00962 c = s + strlen(cmp);
00963 term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
00964 return c;
00965 }
00966 return NULL;
00967 }
00968
00969 static void console_verboser(const char *s, int pos, int replace, int complete)
00970 {
00971 char tmp[80];
00972 const char *c=NULL;
00973
00974 if (!pos) {
00975 fprintf(stdout, "\r");
00976 if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
00977 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
00978 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
00979 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_1)))
00980 fputs(tmp, stdout);
00981 }
00982 if (c)
00983 fputs(c + pos,stdout);
00984 else
00985 fputs(s + pos,stdout);
00986 fflush(stdout);
00987 if (complete) {
00988
00989 if (option_console && consolethread != AST_PTHREADT_NULL)
00990 pthread_kill(consolethread, SIGURG);
00991 }
00992 }
00993
00994 static int ast_all_zeros(char *s)
00995 {
00996 while(*s) {
00997 if (*s > 32)
00998 return 0;
00999 s++;
01000 }
01001 return 1;
01002 }
01003
01004 static void consolehandler(char *s)
01005 {
01006 printf(term_end());
01007 fflush(stdout);
01008
01009
01010 if (!ast_all_zeros(s))
01011 ast_el_add_history(s);
01012
01013 if (s[0] == '!') {
01014 if (s[1])
01015 ast_safe_system(s+1);
01016 else
01017 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
01018 } else
01019 ast_cli_command(STDOUT_FILENO, s);
01020 }
01021
01022 static int remoteconsolehandler(char *s)
01023 {
01024 int ret = 0;
01025
01026
01027 if (!ast_all_zeros(s))
01028 ast_el_add_history(s);
01029
01030 if (s[0] == '!') {
01031 if (s[1])
01032 ast_safe_system(s+1);
01033 else
01034 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
01035 ret = 1;
01036 }
01037 if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
01038 (s[4] == '\0' || isspace(s[4]))) {
01039 quit_handler(0, 0, 0, 0);
01040 ret = 1;
01041 }
01042
01043 return ret;
01044 }
01045
01046 static char abort_halt_help[] =
01047 "Usage: abort shutdown\n"
01048 " Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
01049 " call operations.\n";
01050
01051 static char shutdown_now_help[] =
01052 "Usage: stop now\n"
01053 " Shuts down a running Asterisk immediately, hanging up all active calls .\n";
01054
01055 static char shutdown_gracefully_help[] =
01056 "Usage: stop gracefully\n"
01057 " Causes Asterisk to not accept new calls, and exit when all\n"
01058 " active calls have terminated normally.\n";
01059
01060 static char shutdown_when_convenient_help[] =
01061 "Usage: stop when convenient\n"
01062 " Causes Asterisk to perform