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: 43708 $")
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 - 2006 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 #if !defined(LOW_MEMORY)
00238 struct file_version {
00239 AST_LIST_ENTRY(file_version) list;
00240 const char *file;
00241 char *version;
00242 };
00243
00244 static AST_LIST_HEAD_STATIC(file_versions, file_version);
00245
00246 void ast_register_file_version(const char *file, const char *version)
00247 {
00248 struct file_version *new;
00249 char *work;
00250 size_t version_length;
00251
00252 work = ast_strdupa(version);
00253 work = ast_strip(ast_strip_quoted(work, "$", "$"));
00254 version_length = strlen(work) + 1;
00255
00256 new = calloc(1, sizeof(*new) + version_length);
00257 if (!new)
00258 return;
00259
00260 new->file = file;
00261 new->version = (char *) new + sizeof(*new);
00262 memcpy(new->version, work, version_length);
00263 AST_LIST_LOCK(&file_versions);
00264 AST_LIST_INSERT_HEAD(&file_versions, new, list);
00265 AST_LIST_UNLOCK(&file_versions);
00266 }
00267
00268 void ast_unregister_file_version(const char *file)
00269 {
00270 struct file_version *find;
00271
00272 AST_LIST_LOCK(&file_versions);
00273 AST_LIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) {
00274 if (!strcasecmp(find->file, file)) {
00275 AST_LIST_REMOVE_CURRENT(&file_versions, list);
00276 break;
00277 }
00278 }
00279 AST_LIST_TRAVERSE_SAFE_END;
00280 AST_LIST_UNLOCK(&file_versions);
00281 if (find)
00282 free(find);
00283 }
00284
00285 static char show_version_files_help[] =
00286 "Usage: show version files [like <pattern>]\n"
00287 " Shows the revision numbers of the files used to build this copy of Asterisk.\n"
00288 " Optional regular expression pattern is used to filter the file list.\n";
00289
00290
00291 static int handle_show_version_files(int fd, int argc, char *argv[])
00292 {
00293 #define FORMAT "%-25.25s %-40.40s\n"
00294 struct file_version *iterator;
00295 regex_t regexbuf;
00296 int havepattern = 0;
00297 int havename = 0;
00298 int count_files = 0;
00299
00300 switch (argc) {
00301 case 5:
00302 if (!strcasecmp(argv[3], "like")) {
00303 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB))
00304 return RESULT_SHOWUSAGE;
00305 havepattern = 1;
00306 } else
00307 return RESULT_SHOWUSAGE;
00308 break;
00309 case 4:
00310 havename = 1;
00311 break;
00312 case 3:
00313 break;
00314 default:
00315 return RESULT_SHOWUSAGE;
00316 }
00317
00318 ast_cli(fd, FORMAT, "File", "Revision");
00319 ast_cli(fd, FORMAT, "----", "--------");
00320 AST_LIST_LOCK(&file_versions);
00321 AST_LIST_TRAVERSE(&file_versions, iterator, list) {
00322 if (havename && strcasecmp(iterator->file, argv[3]))
00323 continue;
00324
00325 if (havepattern && regexec(®exbuf, iterator->file, 0, NULL, 0))
00326 continue;
00327
00328 ast_cli(fd, FORMAT, iterator->file, iterator->version);
00329 count_files++;
00330 if (havename)
00331 break;
00332 }
00333 AST_LIST_UNLOCK(&file_versions);
00334 if (!havename) {
00335 ast_cli(fd, "%d files listed.\n", count_files);
00336 }
00337
00338 if (havepattern)
00339 regfree(®exbuf);
00340
00341 return RESULT_SUCCESS;
00342 #undef FORMAT
00343 }
00344
00345 static char *complete_show_version_files(char *line, char *word, int pos, int state)
00346 {
00347 struct file_version *find;
00348 int which = 0;
00349 char *ret = NULL;
00350 int matchlen = strlen(word);
00351
00352 if (pos != 3)
00353 return NULL;
00354
00355 AST_LIST_LOCK(&file_versions);
00356 AST_LIST_TRAVERSE(&file_versions, find, list) {
00357 if (!strncasecmp(word, find->file, matchlen)) {
00358 if (++which > state) {
00359 ret = strdup(find->file);
00360 break;
00361 }
00362 }
00363 }
00364 AST_LIST_UNLOCK(&file_versions);
00365
00366 return ret;
00367 }
00368 #endif
00369
00370 int ast_register_atexit(void (*func)(void))
00371 {
00372 int res = -1;
00373 struct ast_atexit *ae;
00374 ast_unregister_atexit(func);
00375 ae = malloc(sizeof(struct ast_atexit));
00376 ast_mutex_lock(&atexitslock);
00377 if (ae) {
00378 memset(ae, 0, sizeof(struct ast_atexit));
00379 ae->next = atexits;
00380 ae->func = func;
00381 atexits = ae;
00382 res = 0;
00383 }
00384 ast_mutex_unlock(&atexitslock);
00385 return res;
00386 }
00387
00388 void ast_unregister_atexit(void (*func)(void))
00389 {
00390 struct ast_atexit *ae, *prev = NULL;
00391 ast_mutex_lock(&atexitslock);
00392 ae = atexits;
00393 while(ae) {
00394 if (ae->func == func) {
00395 if (prev)
00396 prev->next = ae->next;
00397 else
00398 atexits = ae->next;
00399 break;
00400 }
00401 prev = ae;
00402 ae = ae->next;
00403 }
00404 ast_mutex_unlock(&atexitslock);
00405 }
00406
00407 static int fdprint(int fd, const char *s)
00408 {
00409 return write(fd, s, strlen(s) + 1);
00410 }
00411
00412
00413 static void null_sig_handler(int signal)
00414 {
00415
00416 }
00417
00418 AST_MUTEX_DEFINE_STATIC(safe_system_lock);
00419 static unsigned int safe_system_level = 0;
00420 static void *safe_system_prev_handler;
00421
00422 int ast_safe_system(const char *s)
00423 {
00424 pid_t pid;
00425 int x;
00426 int res;
00427 struct rusage rusage;
00428 int status;
00429 unsigned int level;
00430
00431
00432
00433
00434 ast_mutex_lock(&safe_system_lock);
00435 level = safe_system_level++;
00436
00437
00438 if (level == 0)
00439 safe_system_prev_handler = signal(SIGCHLD, null_sig_handler);
00440
00441 ast_mutex_unlock(&safe_system_lock);
00442
00443 pid = fork();
00444
00445 if (pid == 0) {
00446 if (option_highpriority)
00447 ast_set_priority(0);
00448
00449 for (x = STDERR_FILENO + 1; x < 4096; x++)
00450 close(x);
00451 execl("/bin/sh", "/bin/sh", "-c", s, NULL);
00452 exit(1);
00453 } else if (pid > 0) {
00454 for(;;) {
00455 res = wait4(pid, &status, 0, &rusage);
00456 if (res > -1) {
00457 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
00458 break;
00459 } else if (errno != EINTR)
00460 break;
00461 }
00462 } else {
00463 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
00464 res = -1;
00465 }
00466
00467 ast_mutex_lock(&safe_system_lock);
00468 level = --safe_system_level;
00469
00470
00471 if (level == 0)
00472 signal(SIGCHLD, safe_system_prev_handler);
00473
00474 ast_mutex_unlock(&safe_system_lock);
00475
00476 return res;
00477 }
00478
00479
00480
00481
00482 static void ast_network_puts(const char *string)
00483 {
00484 int x;
00485 for (x=0;x<AST_MAX_CONNECTS; x++) {
00486 if (consoles[x].fd > -1)
00487 fdprint(consoles[x].p[1], string);
00488 }
00489 }
00490
00491
00492
00493
00494
00495 void ast_console_puts(const char *string)
00496 {
00497 fputs(string, stdout);
00498 fflush(stdout);
00499 ast_network_puts(string);
00500 }
00501
00502 static void network_verboser(const char *s, int pos, int replace, int complete)
00503
00504 {
00505 if (replace) {
00506 char *t = alloca(strlen(s) + 2);
00507 if (t) {
00508 sprintf(t, "\r%s", s);
00509 if (complete)
00510 ast_network_puts(t);
00511 } else {
00512 ast_log(LOG_ERROR, "Out of memory\n");
00513 ast_network_puts(s);
00514 }
00515 } else {
00516 if (complete)
00517 ast_network_puts(s);
00518 }
00519 }
00520
00521 static pthread_t lthread;
00522
00523 static void *netconsole(void *vconsole)
00524 {
00525 struct console *con = vconsole;
00526 char hostname[MAXHOSTNAMELEN]="";
00527 char tmp[512];
00528 int res;
00529 struct pollfd fds[2];
00530
00531 if (gethostname(hostname, sizeof(hostname)-1))
00532 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
00533 snprintf(tmp, sizeof(tmp), "%s/%d/%s\n", hostname, ast_mainpid, ASTERISK_VERSION);
00534 fdprint(con->fd, tmp);
00535 for(;;) {
00536 fds[0].fd = con->fd;
00537 fds[0].events = POLLIN;
00538 fds[0].revents = 0;
00539 fds[1].fd = con->p[0];
00540 fds[1].events = POLLIN;
00541 fds[1].revents = 0;
00542
00543 res = poll(fds, 2, -1);
00544 if (res < 0) {
00545 if (errno != EINTR)
00546 ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
00547 continue;
00548 }
00549 if (fds[0].revents) {
00550 res = read(con->fd, tmp, sizeof(tmp));
00551 if (res < 1) {
00552 break;
00553 }
00554 tmp[res] = 0;
00555 ast_cli_command(con->fd, tmp);
00556 }
00557 if (fds[1].revents) {
00558 res = read(con->p[0], tmp, sizeof(tmp));
00559 if (res < 1) {
00560 ast_log(LOG_ERROR, "read returned %d\n", res);
00561 break;
00562 }
00563 res = write(con->fd, tmp, res);
00564 if (res < 1)
00565 break;
00566 }
00567 }
00568 if (option_verbose > 2)
00569 ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection disconnected\n");
00570 close(con->fd);
00571 close(con->p[0]);
00572 close(con->p[1]);
00573 con->fd = -1;
00574
00575 return NULL;
00576 }
00577
00578 static void *listener(void *unused)
00579 {
00580 struct sockaddr_un sunaddr;
00581 int s;
00582 socklen_t len;
00583 int x;
00584 int flags;
00585 struct pollfd fds[1];
00586 pthread_attr_t attr;
00587 pthread_attr_init(&attr);
00588 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00589 for(;;) {
00590 if (ast_socket < 0)
00591 return NULL;
00592 fds[0].fd = ast_socket;
00593 fds[0].events= POLLIN;
00594 s = poll(fds, 1, -1);
00595 pthread_testcancel();
00596 if (s < 0) {
00597 if (errno != EINTR)
00598 ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
00599 continue;
00600 }
00601 len = sizeof(sunaddr);
00602 s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
00603 if (s < 0) {
00604 if (errno != EINTR)
00605 ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
00606 } else {
00607 for (x=0;x<AST_MAX_CONNECTS;x++) {
00608 if (consoles[x].fd < 0) {
00609 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
00610 ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
00611 consoles[x].fd = -1;
00612 fdprint(s, "Server failed to create pipe\n");
00613 close(s);
00614 break;
00615 }
00616 flags = fcntl(consoles[x].p[1], F_GETFL);
00617 fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
00618 consoles[x].fd = s;
00619 if (ast_pthread_create(&consoles[x].t, &attr, netconsole, &consoles[x])) {
00620 ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
00621 close(consoles[x].p[0]);
00622 close(consoles[x].p[1]);
00623 consoles[x].fd = -1;
00624 fdprint(s, "Server failed to spawn thread\n");
00625 close(s);
00626 }
00627 break;
00628 }
00629 }
00630 if (x >= AST_MAX_CONNECTS) {
00631 fdprint(s, "No more connections allowed\n");
00632 ast_log(LOG_WARNING, "No more connections allowed\n");
00633 close(s);
00634 } else if (consoles[x].fd > -1) {
00635 if (option_verbose > 2)
00636 ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection\n");
00637 }
00638 }
00639 }
00640 return NULL;
00641 }
00642
00643 static int ast_makesocket(void)
00644 {
00645 struct sockaddr_un sunaddr;
00646 int res;
00647 int x;
00648 uid_t uid = -1;
00649 gid_t gid = -1;
00650
00651 for (x = 0; x < AST_MAX_CONNECTS; x++)
00652 consoles[x].fd = -1;
00653 unlink(ast_config_AST_SOCKET);
00654 ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
00655 if (ast_socket < 0) {
00656 ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
00657 return -1;
00658 }
00659 memset(&sunaddr, 0, sizeof(sunaddr));
00660 sunaddr.sun_family = AF_LOCAL;
00661 ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
00662 res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
00663 if (res) {
00664 ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
00665 close(ast_socket);
00666 ast_socket = -1;
00667 return -1;
00668 }
00669 res = listen(ast_socket, 2);
00670 if (res < 0) {
00671 ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
00672 close(ast_socket);
00673 ast_socket = -1;
00674 return -1;
00675 }
00676 ast_register_verbose(network_verboser);
00677 ast_pthread_create(<hread, NULL, listener, NULL);
00678
00679 if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {
00680 struct passwd *pw;
00681 if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL) {
00682 ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
00683 } else {
00684 uid = pw->pw_uid;
00685 }
00686 }
00687
00688 if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) {
00689 struct group *grp;
00690 if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL) {
00691 ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
00692 } else {
00693 gid = grp->gr_gid;
00694 }
00695 }
00696
00697 if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
00698 ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
00699
00700 if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) {
00701 int p1;
00702 mode_t p;
00703 sscanf(ast_config_AST_CTL_PERMISSIONS, "%o", &p1);
00704 p = p1;
00705 if ((chmod(ast_config_AST_SOCKET, p)) < 0)
00706 ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
00707 }
00708
00709 return 0;
00710 }
00711
00712 static int ast_tryconnect(void)
00713 {
00714 struct sockaddr_un sunaddr;
00715 int res;
00716 ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
00717 if (ast_consock < 0) {
00718 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
00719 return 0;
00720 }
00721 memset(&sunaddr, 0, sizeof(sunaddr));
00722 sunaddr.sun_family = AF_LOCAL;
00723 ast_copy_string(sunaddr.sun_path, (char *)ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
00724 res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
00725 if (res) {
00726 close(ast_consock);
00727 ast_consock = -1;
00728 return 0;
00729 } else
00730 return 1;
00731 }
00732
00733
00734
00735
00736
00737
00738 static void urg_handler(int num)
00739 {
00740 signal(num, urg_handler);
00741 return;
00742 }
00743
00744 static void hup_handler(int num)
00745 {
00746 if (option_verbose > 1)
00747 printf("Received HUP signal -- Reloading configs\n");
00748 if (restartnow)
00749 execvp(_argv[0], _argv);
00750
00751 ast_module_reload(NULL);
00752 signal(num, hup_handler);
00753 }
00754
00755 static void child_handler(int sig)
00756 {
00757
00758 int n, status;
00759
00760
00761
00762
00763 for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++)
00764 ;
00765 if (n == 0 && option_debug)
00766 printf("Huh? Child handler, but nobody there?\n");
00767 signal(sig, child_handler);
00768 }
00769
00770
00771 static void set_title(char *text)
00772 {
00773 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
00774 fprintf(stdout, "\033]2;%s\007", text);
00775 }
00776
00777 static void set_icon(char *text)
00778 {
00779 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
00780 fprintf(stdout, "\033]1;%s\007", text);
00781 }
00782
00783
00784
00785 int ast_set_priority(int pri)
00786 {
00787 struct sched_param sched;
00788 memset(&sched, 0, sizeof(sched));
00789 #ifdef __linux__
00790 if (pri) {
00791 sched.sched_priority = 10;
00792 if (sched_setscheduler(0, SCHED_RR, &sched)) {
00793 ast_log(LOG_WARNING, "Unable to set high priority\n");
00794 return -1;
00795 } else
00796 if (option_verbose)
00797 ast_verbose("Set to realtime thread\n");
00798 } else {
00799 sched.sched_priority = 0;
00800 if (sched_setscheduler(0, SCHED_OTHER, &sched)) {
00801 ast_log(LOG_WARNING, "Unable to set normal priority\n");
00802 return -1;
00803 }
00804 }
00805 #else
00806 if (pri) {
00807 if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
00808 ast_log(LOG_WARNING, "Unable to set high priority\n");
00809 return -1;
00810 } else
00811 if (option_verbose)
00812 ast_verbose("Set to high priority\n");
00813 } else {
00814 if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
00815 ast_log(LOG_WARNING, "Unable to set normal priority\n");
00816 return -1;
00817 }
00818 }
00819 #endif
00820 return 0;
00821 }
00822
00823 static void ast_run_atexits(void)
00824 {
00825 struct ast_atexit *ae;
00826 ast_mutex_lock(&atexitslock);
00827 ae = atexits;
00828 while(ae) {
00829 if (ae->func)
00830 ae->func();
00831 ae = ae->next;
00832 }
00833 ast_mutex_unlock(&atexitslock);
00834 }
00835
00836 static void quit_handler(int num, int nice, int safeshutdown, int restart)
00837 {
00838 char filename[80] = "";
00839 time_t s,e;
00840 int x;
00841
00842 ast_cdr_engine_term();
00843 if (safeshutdown) {
00844 shuttingdown = 1;
00845 if (!nice) {
00846
00847 ast_begin_shutdown(1);
00848 if (option_verbose && option_console)
00849 ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
00850 time(&s);
00851 for(;;) {
00852 time(&e);
00853
00854 if ((e - s) > 15)
00855 break;
00856 if (!ast_active_channels())
00857 break;
00858 if (!shuttingdown)
00859 break;
00860
00861 usleep(100000);
00862 }
00863 } else {
00864 if (nice < 2)
00865 ast_begin_shutdown(0);
00866 if (option_verbose && option_console)
00867 ast_verbose("Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
00868 for(;;) {
00869 if (!ast_active_channels())
00870 break;
00871 if (!shuttingdown)
00872 break;
00873 sleep(1);
00874 }
00875 }
00876
00877 if (!shuttingdown) {
00878 if (option_verbose && option_console)
00879 ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
00880 return;
00881 }
00882 }
00883 if (option_console || option_remote) {
00884 if (getenv("HOME"))
00885 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
00886 if (!ast_strlen_zero(filename))
00887 ast_el_write_history(filename);
00888 if (el != NULL)
00889 el_end(el);
00890 if (el_hist != NULL)
00891 history_end(el_hist);
00892 }
00893 if (option_verbose)
00894 ast_verbose("Executing last minute cleanups\n");
00895 ast_run_atexits();
00896
00897 if (option_verbose && option_console)
00898 ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);
00899 if (option_debug)
00900 ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num);
00901 manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\nRestart: %s\r\n", ast_active_channels() ? "Uncleanly" : "Cleanly", restart ? "True" : "False");
00902 if (ast_socket > -1) {
00903 pthread_cancel(lthread);
00904 close(ast_socket);
00905 ast_socket = -1;
00906 unlink(ast_config_AST_SOCKET);
00907 }
00908 if (ast_consock > -1)
00909 close(ast_consock);
00910 if (!option_remote) unlink((char *)ast_config_AST_PID);
00911 printf(term_quit());
00912 if (restart) {
00913 if (option_verbose || option_console)
00914 ast_verbose("Preparing for Asterisk restart...\n");
00915
00916 for (x=3;x<32768;x++) {
00917 fcntl(x, F_SETFD, FD_CLOEXEC);
00918 }
00919 if (option_verbose || option_console)
00920 ast_verbose("Restarting Asterisk NOW...\n");
00921 restartnow = 1;
00922
00923
00924 close_logger();
00925
00926
00927
00928 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
00929 pthread_kill(consolethread, SIGHUP);
00930
00931 sleep(2);
00932 } else
00933 execvp(_argv[0], _argv);
00934
00935 } else {
00936
00937 close_logger();
00938 }
00939 exit(0);
00940 }
00941
00942 static void __quit_handler(int num)
00943 {
00944 quit_handler(num, 0, 1, 0);
00945 }
00946
00947 static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp)
00948 {
00949 const char *c;
00950 if (!strncmp(s, cmp, strlen(cmp))) {
00951 c = s + strlen(cmp);
00952 term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
00953 return c;
00954 }
00955 return NULL;
00956 }
00957
00958 static void console_verboser(const char *s, int pos, int replace, int complete)
00959 {
00960 char tmp[80];
00961 const char *c=NULL;
00962
00963 if (!pos) {
00964 fprintf(stdout, "\r");
00965 if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
00966 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
00967 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
00968 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_1)))
00969 fputs(tmp, stdout);
00970 }
00971 if (c)
00972 fputs(c + pos,stdout);
00973 else
00974 fputs(s + pos,stdout);
00975 fflush(stdout);
00976 if (complete) {
00977
00978 if (option_console && consolethread != AST_PTHREADT_NULL)
00979 pthread_kill(consolethread, SIGURG);
00980 }
00981 }
00982
00983 static int ast_all_zeros(char *s)
00984 {
00985 while(*s) {
00986 if (*s > 32)
00987 return 0;
00988 s++;
00989 }
00990 return 1;
00991 }
00992
00993 static void consolehandler(char *s)
00994 {
00995 printf(term_end());
00996 fflush(stdout);
00997
00998
00999 if (!ast_all_zeros(s))
01000 ast_el_add_history(s);
01001
01002 if (s[0] == '!') {
01003 if (s[1])
01004 ast_safe_system(s+1);
01005 else
01006 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
01007 } else
01008 ast_cli_command(STDOUT_FILENO, s);
01009 }
01010
01011 static int remoteconsolehandler(char *s)
01012 {
01013 int ret = 0;
01014
01015
01016 if (!ast_all_zeros(s))
01017 ast_el_add_history(s);
01018
01019 if (s[0] == '!') {
01020 if (s[1])
01021 ast_safe_system(s+1);
01022 else
01023 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
01024 ret = 1;
01025 }
01026 if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
01027 (s[4] == '\0' || isspace(s[4]))) {
01028 quit_handler(0, 0, 0, 0);
01029 ret = 1;
01030 }
01031
01032 return ret;
01033 }
01034
01035 static char abort_halt_help[] =
01036 "Usage: abort shutdown\n"
01037 " Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
01038 " call operations.\n";
01039
01040 static char shutdown_now_help[] =
01041 "Usage: stop now\n"
01042 " Shuts down a running Asterisk immediately, hanging up all active calls .\n";
01043
01044 static char shutdown_gracefully_help[] =
01045 "Usage: stop gracefully\n"
01046 " Causes Asterisk to not accept new calls, and exit when all\n"
01047 " active calls have terminated normally.\n";
01048
01049 static char shutdown_when_convenient_help[] =
01050 "Usage: stop when convenient\n"
01051 " Causes Asterisk to perform a shutdown when all active calls have ended.\n";
01052
01053 static char restart_now_help[] =
01054 "Usage: restart now\n"
01055 " Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
01056 " restart.\n";
01057
01058 static char restart_gracefully_help[] =
01059 "Usage: restart gracefully\n"
01060 " Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
01061 " restart when all active calls have ended.\n";
01062
01063 static char restart_when_convenient_help[] =
01064 "Usage: restart when convenient\n"
01065 " Causes Asterisk to perform a cold restart when all active calls have ended.\n";
01066
01067 static char bang_help[] =
01068 "Usage: !<command>\n"
01069 " Executes a given shell command\n";
01070
01071 static char show_warranty_help[] =
01072 "Usage: show warranty\n"
01073 " Shows the warranty (if any) for this copy of Asterisk.\n";
01074
01075 static char show_license_help[] =
01076 "Usage: show license\n"
01077 " Shows the license(s) for this copy of Asterisk.\n";
01078
01079 #if 0
01080 static int handle_quit(int fd, int argc, char *argv[])
01081 {
01082 if (argc != 1)
01083 return RESULT_SHOWUSAGE;
01084 quit_handler(0, 0, 1, 0);
01085 return RESULT_SUCCESS;
01086 }
01087 #endif
01088
01089 static int handle_shutdown_now(int fd, int argc, char *argv[])
01090 {
01091 if (argc != 2)
01092 return RESULT_SHOWUSAGE;
01093 quit_handler(0, 0 , 1 , 0 );
01094 return RESULT_SUCCESS;
01095 }
01096
01097 static int handle_shutdown_gracefully(int fd, int argc, char *argv[])
01098 {
01099 if (argc != 2)
01100 return RESULT_SHOWUSAGE;
01101 quit_handler(0, 1 , 1 , 0 );
01102 return RESULT_SUCCESS;
01103 }
01104
01105 static int handle_shutdown_when_convenient(int fd, int argc, char *argv[])
01106 {
01107 if (argc != 3)
01108 return RESULT_SHOWUSAGE;
01109 quit_handler(0, 2 , 1 , 0 );
01110 return RESULT_SUCCESS;
01111 }
01112
01113 static int handle_restart_now(int fd, int argc, char *argv[])
01114 {
01115 if (argc != 2)
01116 return RESULT_SHOWUSAGE;
01117 quit_handler(0, 0 , 1 , 1 );
01118 return RESULT_SUCCESS;
01119 }
01120
01121 static int handle_restart_gracefully(int fd, int argc, char *argv[])
01122 {
01123 if (argc != 2)
01124 return RESULT_SHOWUSAGE;
01125 quit_handler(0, 1 , 1 , 1 );
01126 return RESULT_SUCCESS;
01127 }
01128
01129 static int handle_restart_when_convenient(int fd, int argc, char *argv[])
01130 {
01131 if (argc != 3)
01132 return RESULT_SHOWUSAGE;
01133 quit_handler(0, 2 , 1 , 1 );
01134 return RESULT_SUCCESS;
01135 }
01136
01137 static int handle_abort_halt(int fd, int argc, char *argv[])
01138 {
01139 if (argc != 2)
01140 return RESULT_SHOWUSAGE;
01141 ast_cancel_shutdown();
01142 shuttingdown = 0;
01143 return RESULT_SUCCESS;
01144 }
01145
01146 static int handle_bang(int fd, int argc, char *argv[])
01147 {
01148 return RESULT_SUCCESS;
01149 }
01150 static const char *warranty_lines[] = {
01151 "\n",
01152 " NO WARRANTY\n",
01153 "\n",
01154 "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n",
01155 "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n",
01156 "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n",
01157 "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n",
01158 "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n",
01159 "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n",
01160 "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n",
01161 "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n",
01162 "REPAIR OR CORRECTION.\n",
01163 "\n",
01164 "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n",
01165 "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n",
01166 "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n",
01167 "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n",
01168 "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n",
01169 "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n",
01170 "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n",
01171 "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n",
01172 "POSSIBILITY OF SUCH DAMAGES.\n",
01173 };
01174
01175 static int show_warranty(int fd, int argc, char *argv[])
01176 {
01177 int x;
01178
01179 for (x = 0; x < sizeof(warranty_lines) / sizeof(warranty_lines[0]); x++)
01180 ast_cli(fd, (char *) warranty_lines[x]);
01181
01182 return RESULT_SUCCESS;
01183 }
01184
01185 static const char *license_lines[] = {
01186 "\n",
01187 "This program is free software; you can redistribute it and/or modify\n",
01188 "it under the terms of the GNU General Public License version 2 as\n",
01189 "published by the Free Software Foundation.\n",
01190 "\n",
01191 "This program also contains components licensed under other licenses.\n",
01192 "They include:\n",
01193 "\n",
01194 "This program is distributed in the hope that it will be useful,\n",
01195 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n",
01196 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n",
01197 "GNU General Public License for more details.\n",
01198 "\n",
01199 "You should have received a copy of the GNU General Public License\n",
01200 "along with this program; if not, write to the Free Software\n",
01201 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n",
01202 };
01203
01204 static int show_license(int fd, int argc, char *argv[])
01205 {
01206 int x;
01207
01208 for (x = 0; x < sizeof(license_lines) / sizeof(license_lines[0]); x++)
01209 ast_cli(fd, (char *) license_lines[x]);
01210
01211 return RESULT_SUCCESS;
01212 }
01213
01214 #define ASTERISK_PROMPT "*CLI> "
01215
01216 #define ASTERISK_PROMPT2 "%s*CLI> "
01217
01218 static struct ast_cli_entry core_cli[] = {
01219 { { "abort", "halt", NULL }, handle_abort_halt,
01220 "Cancel a running halt", abort_halt_help },
01221 { { "stop", "now", NULL }, handle_shutdown_now,
01222 "Shut down Asterisk immediately", shutdown_now_help },
01223 { { "stop", "gracefully", NULL }, handle_shutdown_gracefully,
01224 "Gracefully shut down Asterisk", shutdown_gracefully_help },
01225 { { "stop", "when","convenient", NULL }, handle_shutdown_when_convenient,
01226 "Shut down Asterisk at empty call volume", shutdown_when_convenient_help },
01227 { { "restart", "now", NULL }, handle_restart_now,
01228 "Restart Asterisk immediately", restart_now_help },
01229 { { "restart", "gracefully", NULL }, handle_restart_gracefully,
01230 "Restart Asterisk gracefully", restart_gracefully_help },
01231 { { "restart", "when", "convenient", NULL }, handle_restart_when_convenient,
01232 "Restart Asterisk at empty call volume", restart_when_convenient_help },
01233 { { "show", "warranty", NULL }, show_warranty,
01234 "Show the warranty (if any) for this copy of Asterisk", show_warranty_help },
01235 { { "show", "license", NULL }, show_license,
01236 "Show the license(s) for this copy of Asterisk", show_license_help },
01237 { { "!", NULL }, handle_bang,
01238 "Execute a shell command", bang_help },
01239 #if !defined(LOW_MEMORY)
01240 { { "show", "version", "files", NULL }, handle_show_version_files,
01241 "Show versions of files used to build Asterisk", show_version_files_help, complete_show_version_files },
01242 #endif
01243 };
01244
01245 static int ast_el_read_char(EditLine *el, char *cp)
01246 {
01247 int num_read=0;
01248 int lastpos=0;
01249 struct pollfd fds[2];
01250 int res;
01251 int max;
01252 char buf[512];
01253
01254 for (;;) {
01255 max = 1;
01256 fds[0].fd = ast_consock;
01257 fds[0].events = POLLIN;
01258 if (!option_exec) {
01259 fds[1].fd = STDIN_FILENO;
01260 fds[1].events = POLLIN;
01261 max++;
01262 }
01263 res = poll(fds, max, -1);
01264 if (res < 0) {
01265 if (errno == EINTR)
01266 continue;
01267 ast_log(LOG_ERROR, "poll failed: %s\n", strerror(errno));
01268 break;
01269 }
01270
01271 if (!option_exec && fds[1].revents) {
01272 num_read = read(STDIN_FILENO, cp, 1);
01273 if (num_read < 1) {
01274 break;
01275 } else
01276 return (num_read);
01277 }
01278 if (fds[0].revents) {
01279 res = read(ast_consock, buf, sizeof(buf) - 1);
01280
01281 if (res < 1) {
01282 fprintf(stderr, "\nDisconnected from Asterisk server\n");
01283 if (!option_reconnect) {
01284 quit_handler(0, 0, 0, 0);
01285 } else {
01286 int tries;
01287 int reconnects_per_second = 20;
01288 fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
01289 for (tries=0;tries<30 * reconnects_per_second;tries++) {
01290 if (ast_tryconnect()) {
01291 fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
01292 printf(term_quit());
01293 WELCOME_MESSAGE;
01294 break;
01295 } else {
01296 usleep(1000000 / reconnects_per_second);
01297 }
01298 }
01299 if (tries >= 30 * reconnects_per_second) {
01300 fprintf(stderr, "Failed to reconnect for 30 seconds. Quitting.\n");
01301 quit_handler(0, 0, 0, 0);
01302 }
01303 }
01304 }
01305
01306 buf[res] = '\0';
01307
01308 if (!option_exec && !lastpos)
01309 write(STDOUT_FILENO, "\r", 1);
01310 write(STDOUT_FILENO, buf, res);
01311 if ((buf[res-1] == '\n') || (buf[res-2] == '\n')) {
01312 *cp = CC_REFRESH;
01313 return(1);
01314 } else {
01315 lastpos = 1;
01316 }
01317 }
01318 }
01319
01320 *cp = '\0';
01321 return (0);
01322 }
01323
01324 static char *cli_prompt(EditLine *el)
01325 {
01326 static char prompt[200];
01327 char *pfmt;
01328 int color_used=0;
01329 char term_code[20];
01330
01331 if ((pfmt = getenv("ASTERISK_PROMPT"))) {
01332 char *t = pfmt, *p = prompt;
01333 memset(prompt, 0, sizeof(prompt));
01334 while (*t != '\0' && *p < sizeof(prompt)) {
01335 if (*t == '%') {
01336 char hostname[MAXHOSTNAMELEN]="";
01337 int i;
01338 time_t ts;
01339 struct tm tm;
01340 #ifdef linux
01341 FILE *LOADAVG;
01342 #endif
01343 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
01344
01345 t++;
01346 switch (*t) {
01347 case 'C':
01348 t++;
01349 if (sscanf(t, "%d;%d%n", &fgcolor, &bgcolor, &i) == 2) {
01350 strncat(p, term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
01351 t += i - 1;
01352 } else if (sscanf(t, "%d%n", &fgcolor, &i) == 1) {
01353 strncat(p, term_color_code(term_code, fgcolor, 0, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
01354 t += i - 1;
01355 }
01356
01357
01358 if ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) {
01359 color_used = 0;
01360 } else {
01361 color_used = 1;
01362 }
01363 break;
01364 case 'd':
01365 memset(&tm, 0, sizeof(struct tm));
01366 time(&ts);
01367 if (localtime_r(&ts, &tm)) {
01368 strftime(p, sizeof(prompt) - strlen(prompt), "%Y-%m-%d", &tm);
01369 }
01370 break;
01371 case 'h':
01372 if (!gethostname(hostname, sizeof(hostname) - 1)) {
01373 strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
01374 } else {
01375 strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
01376 }
01377 break;
01378 case 'H':
01379 if (!gethostname(hostname, sizeof(hostname) - 1)) {
01380 for (i=0;i<sizeof(hostname);i++) {
01381 if (hostname[i] == '.') {
01382 hostname[i] = '\0';
01383 break;
01384 }
01385 }
01386 strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
01387 } else {
01388 strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
01389 }
01390 break;
01391 #ifdef linux
01392 case 'l':
01393 t++;
01394 if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
01395 float avg1, avg2, avg3;
01396 int actproc, totproc, npid, which;
01397 fscanf(LOADAVG, "%f %f %f %d/%d %d",
01398 &avg1, &avg2, &avg3, &actproc, &totproc, &npid);
01399 if (sscanf(t, "%d", &which) == 1) {
01400 switch (which) {
01401 case 1:
01402 snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg1);
01403 break;
01404 case 2:
01405 snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg2);
01406 break;
01407 case 3:
01408 snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg3);
01409 break;
01410 case 4:
01411 snprintf(p, sizeof(prompt) - strlen(prompt), "%d/%d", actproc, totproc);
01412 break;
01413 case 5:
01414 snprintf(p, sizeof(prompt) - strlen(prompt), "%d", npid);
01415 break;
01416 }
01417 }
01418 }
01419 break;
01420 #endif
01421 case 't':
01422 memset(&tm, 0, sizeof(struct tm));
01423 time(&ts);
01424 if (localtime_r(&ts, &tm)) {
01425 strftime(p, sizeof(prompt) - strlen(prompt), "%H:%M:%S", &tm);
01426 }
01427 break;
01428 case '#':
01429 if (! option_remote) {
01430 strncat(p, "#", sizeof(prompt) - strlen(prompt) - 1);
01431 } else {
01432 strncat(p, ">", sizeof(prompt) - strlen(prompt) - 1);
01433 }
01434 break;
01435 case '%':
01436 strncat(p, "%", sizeof(prompt) - strlen(prompt) - 1);
01437 break;
01438 case '\0':
01439 t--;
01440 break;
01441 }
01442 while (*p != '\0') {
01443 p++;
01444 }
01445 t++;
01446 } else {
01447 *p = *t;
01448 p++;
01449 t++;
01450 }
01451 }
01452 if (color_used) {
01453
01454 term_color_code(term_code, COLOR_WHITE, COLOR_BLACK, sizeof(term_code));
01455 if (strlen(term_code) > sizeof(prompt) - strlen(prompt)) {
01456 strncat(prompt + sizeof(prompt) - strlen(term_code) - 1, term_code, strlen(term_code));
01457 } else {
01458 strncat(p, term_code, sizeof(term_code));
01459 }
01460 }
01461 } else if (remotehostname)
01462 snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT2, remotehostname);
01463 else
01464 snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT);
01465
01466 return(prompt);
01467 }
01468
01469 static char **ast_el_strtoarr(char *buf)
01470 {
01471 char **match_list = NULL, *retstr;
01472 size_t match_list_len;
01473 int matches = 0;
01474
01475 match_list_len = 1;
01476 while ( (retstr = strsep(&buf, " ")) != NULL) {
01477
01478 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
01479 break;
01480 if (matches + 1 >= match_list_len) {
01481 match_list_len <<= 1;
01482 match_list = realloc(match_list, match_list_len * sizeof(char *));
01483 }
01484
01485 match_list[matches++] = strdup(retstr);
01486 }
01487
01488 if (!match_list)
01489 return (char **) NULL;
01490
01491 if (matches>= match_list_len)
01492 match_list = realloc(match_list, (match_list_len + 1) * sizeof(char *));
01493
01494 match_list[matches] = (char *) NULL;
01495
01496 return match_list;
01497 }
01498
01499 static int ast_el_sort_compare(const void *i1, const void *i2)
01500 {
01501 char *s1, *s2;
01502
01503 s1 = ((char **)i1)[0];
01504 s2 = ((char **)i2)[0];
01505
01506 return strcasecmp(s1, s2);
01507 }
01508
01509 static int ast_cli_display_match_list(char **matches, int len, int max)
01510 {
01511 int i, idx, limit, count;
01512 int screenwidth = 0;
01513 int numoutput = 0, numoutputline = 0;
01514
01515 screenwidth = ast_get_termcols(STDOUT_FILENO);
01516
01517
01518 limit = screenwidth / (max + 2);
01519 if (limit == 0)
01520 limit = 1;
01521
01522
01523 count = len / limit;
01524 if (count * limit < len)
01525 count++;
01526
01527 idx = 1;
01528
01529 qsort(&matches[0], (size_t)(len + 1), sizeof(char *), ast_el_sort_compare);
01530
01531 for (; count > 0; count--) {
01532 numoutputline = 0;
01533 for (i=0; i < limit && matches[idx]; i++, idx++) {
01534
01535
01536 if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
01537 i--;
01538 free(matches[idx]);
01539 matches[idx] = NULL;
01540 continue;
01541 }
01542
01543 numoutput++;
01544 numoutputline++;
01545 fprintf(stdout, "%-*s ", max, matches[idx]);
01546 free(matches[idx]);
01547 matches[idx] = NULL;
01548 }
01549 if (numoutputline > 0)
01550 fprintf(stdout, "\n");
01551 }
01552
01553 return numoutput;
01554 }
01555
01556
01557 static char *cli_complete(EditLine *el, int ch)
01558 {
01559 int len=0;
01560 char *ptr;
01561 int nummatches = 0;
01562 char **matches;
01563 int retval = CC_ERROR;
01564 char buf[2048];
01565 int res;
01566
01567 LineInfo *lf = (LineInfo *)el_line(el);
01568
01569 *(char *)lf->cursor = '\0';
01570 ptr = (char *)lf->cursor;
01571 if (ptr) {
01572 while (ptr > lf->buffer) {
01573 if (isspace(*ptr)) {
01574 ptr++;
01575 break;
01576 }
01577 ptr--;
01578 }
01579 }
01580
01581 len = lf->cursor - ptr;
01582
01583 if (option_remote) {
01584 snprintf(buf, sizeof(buf),"_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
01585 fdprint(ast_consock, buf);
01586 res = read(ast_consock, buf, sizeof(buf));
01587 buf[res] = '\0';
01588 nummatches = atoi(buf);
01589
01590 if (nummatches > 0) {
01591 char *mbuf;
01592 int mlen = 0, maxmbuf = 2048;
01593
01594 mbuf = malloc(maxmbuf);
01595 if (!mbuf)
01596 return (char *)(CC_ERROR);
01597 snprintf(buf, sizeof(buf),"_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
01598 fdprint(ast_consock, buf);
01599 res = 0;
01600 mbuf[0] = '\0';
01601 while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
01602 if (mlen + 1024 > maxmbuf) {
01603
01604 maxmbuf += 1024;
01605 mbuf = realloc(mbuf, maxmbuf);
01606 if (!mbuf)
01607 return (char *)(CC_ERROR);
01608 }
01609
01610 res = read(ast_consock, mbuf + mlen, 1024);
01611 if (res > 0)
01612 mlen += res;
01613 }
01614 mbuf[mlen] = '\0';
01615
01616 matches = ast_el_strtoarr(mbuf);
01617 free(mbuf);
01618 } else
01619 matches = (char **) NULL;
01620
01621
01622 } else {
01623
01624 nummatches = ast_cli_generatornummatches((char *)lf->buffer,ptr);
01625 matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
01626 }
01627
01628 if (matches) {
01629 int i;
01630 int matches_num, maxlen, match_len;
01631
01632 if (matches[0][0] != '\0') {
01633 el_deletestr(el, (int) len);
01634 el_insertstr(el, matches[0]);
01635 retval = CC_REFRESH;
01636 }
01637
01638 if (nummatches == 1) {
01639
01640 el_insertstr(el, " ");
01641 retval = CC_REFRESH;
01642 } else {
01643
01644 for (i=1, maxlen=0; matches[i]; i++) {
01645 match_len = strlen(matches[i]);
01646 if (match_len > maxlen)
01647 maxlen = match_len;
01648 }
01649 matches_num = i - 1;
01650 if (matches_num >1) {
01651 fprintf(stdout, "\n");
01652 ast_cli_display_match_list(matches, nummatches, maxlen);
01653 retval = CC_REDISPLAY;
01654 } else {
01655 el_insertstr(el," ");
01656 retval = CC_REFRESH;
01657 }
01658 }
01659 free(matches);
01660 }
01661
01662 return (char *)(long)retval;
01663 }
01664
01665 static int ast_el_initialize(void)
01666 {
01667 HistEvent ev;
01668 char *editor = getenv("AST_EDITOR");
01669
01670 if (el != NULL)
01671 el_end(el);
01672 if (el_hist != NULL)
01673 history_end(el_hist);
01674
01675 el = el_init("asterisk", stdin, stdout, stderr);
01676 el_set(el, EL_PROMPT, cli_prompt);
01677
01678 el_set(el, EL_EDITMODE, 1);
01679 el_set(el, EL_EDITOR, editor ? editor : "emacs");
01680 el_hist = history_init();
01681 if (!el || !el_hist)
01682 return -1;
01683
01684
01685 history(el_hist, &ev, H_SETSIZE, 100);
01686
01687 el_set(el, EL_HIST, history, el_hist);
01688
01689 el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
01690
01691 el_set(el, EL_BIND, "^I", "ed-complete", NULL);
01692
01693 el_set(el, EL_BIND, "?", "ed-complete", NULL);
01694
01695 el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
01696
01697 return 0;
01698 }
01699
01700 static int ast_el_add_history(char *buf)
01701 {
01702 HistEvent ev;
01703
01704 if (el_hist == NULL || el == NULL)
01705 ast_el_initialize();
01706 if (strlen(buf) > 256)
01707 return 0;
01708 return (history(el_hist, &ev, H_ENTER, buf));
01709 }
01710
01711 static int ast_el_write_history(char *filename)
01712 {
01713 HistEvent ev;
01714
01715 if (el_hist == NULL || el == NULL)
01716 ast_el_initialize();
01717
01718 return (history(el_hist, &ev, H_SAVE, filename));
01719 }
01720
01721 static int ast_el_read_history(char *filename)
01722 {
01723 char buf[256];
01724 FILE *f;
01725 int ret = -1;
01726
01727 if (el_hist == NULL || el == NULL)
01728 ast_el_initialize();
01729
01730 if ((f = fopen(filename, "r")) == NULL)
01731 return ret;
01732
01733 while (!feof(f)) {
01734 fgets(buf, sizeof(buf), f);
01735 if (!strcmp(buf, "_HiStOrY_V2_\n"))
01736 continue;
01737 if (ast_all_zeros(buf))
01738 continue;
01739 if ((ret = ast_el_add_history(buf)) == -1)
01740 break;
01741 }
01742 fclose(f);
01743
01744 return ret;
01745 }
01746
01747 static void ast_remotecontrol(char * data)
01748 {
01749 char buf[80];
01750 int res;
01751 char filename[80] = "";
01752 char *hostname;
01753 char *cpid;
01754 char *version;
01755 int pid;
01756 char tmp[80];
01757 char *stringp=NULL;
01758
01759 char *ebuf;
01760 int num = 0;
01761
01762 read(ast_consock, buf, sizeof(buf));
01763 if (data)
01764 write(ast_consock, data, strlen(data) + 1);
01765 stringp=buf;
01766 hostname = strsep(&stringp, "/");
01767 cpid = strsep(&stringp, "/");
01768 version = strsep(&stringp, "\n");
01769 if (!version)
01770 version = "<Version Unknown>";
01771 stringp=hostname;
01772 strsep(&stringp, ".");
01773 if (cpid)
01774 pid = atoi(cpid);
01775 else
01776 pid = -1;
01777 snprintf(tmp, sizeof(tmp), "set verbose atleast %d", option_verbose);
01778 fdprint(ast_consock, tmp);
01779 snprintf(tmp, sizeof(tmp), "set debug atleast %d", option_debug);
01780 fdprint(ast_consock, tmp);
01781 ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
01782 remotehostname = hostname;
01783 if (getenv("HOME"))
01784 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
01785 if (el_hist == NULL || el == NULL)
01786 ast_el_initialize();
01787
01788 el_set(el, EL_GETCFN, ast_el_read_char);
01789
01790 if (!ast_strlen_zero(filename))
01791 ast_el_read_history(filename);
01792
01793 if (option_exec && data) {
01794 char tempchar;
01795 struct pollfd fds;
01796 fds.fd = ast_consock;
01797 fds.events = POLLIN;
01798 fds.revents = 0;
01799 while (poll(&fds, 1, 100) > 0)
01800 ast_el_read_char(el, &tempchar);
01801 return;
01802 }
01803 for(;;) {
01804 ebuf = (char *)el_gets(el, &num);
01805
01806 if (!ast_strlen_zero(ebuf)) {
01807 if (ebuf[strlen(ebuf)-1] == '\n')
01808 ebuf[strlen(ebuf)-1] = '\0';
01809 if (!remoteconsolehandler(ebuf)) {
01810 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
01811 if (res < 1) {
01812 ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
01813 break;
01814 }
01815 }
01816 }
01817 }
01818 printf("\nDisconnected from Asterisk server\n");
01819 }
01820
01821 static int show_version(void)
01822 {
01823 printf("Asterisk " ASTERISK_VERSION "\n");
01824 return 0;
01825 }
01826
01827 static int show_cli_help(void) {
01828 printf("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2005, Digium, Inc. and others.\n");
01829 printf("Usage: asterisk [OPTIONS]\n");
01830 printf("Valid Options:\n");
01831 printf(" -V Display version number and exit\n");
01832 printf(" -C <configfile> Use an alternate configuration file\n");
01833 printf(" -G <group> Run as a group other than the caller\n");
01834 printf(" -U <user> Run as a user other than the caller\n");
01835 printf(" -c Provide console CLI\n");
01836 printf(" -d Enable extra debugging\n");
01837 printf(" -f Do not fork\n");
01838 printf(" -g Dump core in case of a crash\n");
01839 printf(" -h This help screen\n");
01840 printf(" -i Initialize crypto keys at startup\n");
01841 printf(" -n Disable console colorization\n");
01842 printf(" -p Run as pseudo-realtime thread\n");
01843 printf(" -q Quiet mode (suppress output)\n");
01844 printf(" -r Connect to Asterisk on this machine\n");
01845 printf(" -R Connect to Asterisk, and attempt to reconnect if disconnected\n");
01846 printf(" -t Record soundfiles in /var/tmp and move them where they belong after they are done.\n");
01847 printf(" -T Display the time in [Mmm dd hh:mm:ss] format for each line of output to the CLI.\n");
01848 printf(" -v Increase verbosity (multiple v's = more verbose)\n");
01849 printf(" -x <cmd> Execute command <cmd> (only valid with -r)\n");
01850 printf("\n");
01851 return 0;
01852 }
01853
01854 static void ast_readconfig(void) {
01855 struct ast_config *cfg;
01856 struct ast_variable *v;
01857 char *config = AST_CONFIG_FILE;
01858
01859 if (option_overrideconfig == 1) {
01860 cfg = ast_config_load(ast_config_AST_CONFIG_FILE);
01861 if (!cfg)
01862 ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
01863 } else {
01864 cfg = ast_config_load(config);
01865 }
01866
01867
01868 ast_copy_string(ast_config_AST_CONFIG_DIR, AST_CONFIG_DIR, sizeof(ast_config_AST_CONFIG_DIR));
01869 ast_copy_string(ast_config_AST_SPOOL_DIR, AST_SPOOL_DIR, sizeof(ast_config_AST_SPOOL_DIR));
01870 ast_copy_string(ast_config_AST_MODULE_DIR, AST_MODULE_DIR, sizeof(ast_config_AST_MODULE_DIR));
01871 snprintf(ast_config_AST_MONITOR_DIR, sizeof(ast_config_AST_MONITOR_DIR) - 1, "%s/monitor", ast_config_AST_SPOOL_DIR);
01872 ast_copy_string(ast_config_AST_VAR_DIR, AST_VAR_DIR, sizeof(ast_config_AST_VAR_DIR));
01873 ast_copy_string(ast_config_AST_LOG_DIR, AST_LOG_DIR, sizeof(ast_config_AST_LOG_DIR));
01874 ast_copy_string(ast_config_AST_AGI_DIR, AST_AGI_DIR, sizeof(ast_config_AST_AGI_DIR));
01875 ast_copy_string(ast_config_AST_DB, AST_DB, sizeof(ast_config_AST_DB));
01876 ast_copy_string(ast_config_AST_KEY_DIR, AST_KEY_DIR, sizeof(ast_config_AST_KEY_DIR));
01877 ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
01878 ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
01879 ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
01880
01881
01882 if (!cfg) {
01883 return;
01884 }
01885 v = ast_variable_browse(cfg, "files");
01886 while (v) {
01887 if (!strcasecmp(v->name, "astctlpermissions")) {
01888 ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
01889 } else if (!strcasecmp(v->name, "astctlowner")) {
01890 ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
01891 } else if (!strcasecmp(v->name, "astctlgroup")) {
01892 ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
01893 } else if (!strcasecmp(v->name, "astctl")) {
01894 ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
01895 }
01896 v = v->next;
01897 }
01898 v = ast_variable_browse(cfg, "directories");
01899 while(v) {
01900 if (!strcasecmp(v->name, "astetcdir")) {
01901 ast_copy_string(ast_config_AST_CONFIG_DIR, v->value, sizeof(ast_config_AST_CONFIG_DIR));
01902 } else if (!strcasecmp(v->name, "astspooldir")) {
01903 ast_copy_string(ast_config_AST_SPOOL_DIR, v->value, sizeof(ast_config_AST_SPOOL_DIR));
01904 snprintf(ast_config_AST_MONITOR_DIR, sizeof(ast_config_AST_MONITOR_DIR) - 1, "%s/monitor", v->value);
01905 } else if (!strcasecmp(v->name, "astvarlibdir")) {
01906 ast_copy_string(ast_config_AST_VAR_DIR, v->value, sizeof(ast_config_AST_VAR_DIR));
01907 snprintf(ast_config_AST_DB, sizeof(ast_config_AST_DB), "%s/astdb", v->value);
01908 snprintf(ast_config_AST_KEY_DIR, sizeof(ast_config_AST_KEY_DIR), "%s/keys", v->value);
01909 } else if (!strcasecmp(v->name, "astlogdir")) {
01910 ast_copy_string(ast_config_AST_LOG_DIR, v->value, sizeof(ast_config_AST_LOG_DIR));
01911 } else if (!strcasecmp(v->name, "astagidir")) {
01912 ast_copy_string(ast_config_AST_AGI_DIR, v->value, sizeof(ast_config_AST_AGI_DIR));
01913 } else if (!strcasecmp(v->name, "astrundir")) {
01914 snprintf(ast_config_AST_PID, sizeof(ast_config_AST_PID), "%s/%s", v->value, "asterisk.pid");
01915 snprintf(ast_config_AST_SOCKET, sizeof(ast_config_AST_SOCKET), "%s/%s", v->value, ast_config_AST_CTL);
01916 ast_copy_string(ast_config_AST_RUN_DIR, v->value, sizeof(ast_config_AST_RUN_DIR));
01917 } else if (!strcasecmp(v->name, "astmoddir")) {
01918 ast_copy_string(ast_config_AST_MODULE_DIR, v->value, sizeof(ast_config_AST_MODULE_DIR));
01919 }
01920 v = v->next;
01921 }
01922 v = ast_variable_browse(cfg, "options");
01923 while(v) {
01924
01925 if (!strcasecmp(v->name, "verbose")) {
01926 option_verbose = atoi(v->value);
01927
01928 } else if (!strcasecmp(v->name, "timestamp")) {
01929 option_timestamp = ast_true(v->value);
01930
01931 } else if (!strcasecmp(v->name, "execincludes")) {
01932 option_exec_includes = ast_true(v->value);
01933
01934 } else if (!strcasecmp(v->name, "debug")) {
01935 option_debug = 0;
01936 if (sscanf(v->value, "%d", &option_debug) != 1) {
01937 option_debug = ast_true(v->value);
01938 }
01939
01940 } else if (!strcasecmp(v->name, "nofork")) {
01941 option_nofork = ast_true(v->value);
01942
01943 } else if (!strcasecmp(v->name, "quiet")) {
01944 option_quiet = ast_true(v->value);
01945
01946 } else if (!strcasecmp(v->name, "console")) {
01947 option_console = ast_true(v->value);
01948
01949 } else if (!strcasecmp(v->name, "highpriority")) {
01950 option_highpriority = ast_true(v->value);
01951
01952 } else if (!strcasecmp(v->name, "initcrypto")) {
01953 option_initcrypto = ast_true(v->value);
01954
01955 } else if (!strcasecmp(v->name, "nocolor")) {
01956 option_nocolor = ast_true(v->value);
01957
01958 } else if (!strcasecmp(v->name, "dontwarn")) {
01959 option_dontwarn = ast_true(v->value);
01960
01961 } else if (!strcasecmp(v->name, "dumpcore")) {
01962 option_dumpcore = ast_true(v->value);
01963
01964 } else if (!strcasecmp(v->name, "cache_record_files")) {
01965 option_cache_record_files = ast_true(v->value);
01966
01967 } else if (!strcasecmp(v->name, "record_cache_dir")) {
01968 ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
01969
01970 } else if (!strcasecmp(v->name, "transcode_via_sln")) {
01971 option_transcode_slin = ast_true(v->value);
01972
01973 } else if (!strcasecmp(v->name, "transmit_silence_during_record")) {
01974 option_transmit_silence_during_record = ast_true(v->value);
01975 } else if (!strcasecmp(v->name, "maxcalls")) {
01976 if ((sscanf(v->value, "%d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
01977 option_maxcalls = 0;
01978 }
01979 } else if (!strcasecmp(v->name, "maxload")) {
01980 double test[1];
01981
01982 if (getloadavg(test, 1) == -1) {
01983 ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
01984 option_maxload = 0.0;
01985 } else if ((sscanf(v->value, "%lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
01986 option_maxload = 0.0;
01987 }
01988
01989 } else if (!strcasecmp(v->name, "runuser")) {
01990 ast_copy_string(ast_config_AST_RUN_USER, v->value, sizeof(ast_config_AST_RUN_USER));
01991
01992 } else if (!strcasecmp(v->name, "rungroup")) {
01993 ast_copy_string(ast_config_AST_RUN_GROUP, v->value, sizeof(ast_config_AST_RUN_GROUP));
01994 }
01995 v = v->next;
01996 }
01997 ast_config_destroy(cfg);
01998 }
01999
02000 int main(int argc, char *argv[])
02001 {
02002 int c;
02003 char filename[80] = "";
02004 char hostname[MAXHOSTNAMELEN]="";
02005 char tmp[80];
02006 char * xarg = NULL;
02007 int x;
02008 FILE *f;
02009 sigset_t sigs;
02010 int num;
02011 int is_child_of_nonroot=0;
02012 char *buf;
02013 char *runuser=NULL, *rungroup=NULL;
02014
02015
02016 if (argc > sizeof(_argv) / sizeof(_argv[0]) - 1) {
02017 fprintf(stderr, "Truncating argument size to %d\n", (int)(sizeof(_argv) / sizeof(_argv[0])) - 1);
02018 argc = sizeof(_argv) / sizeof(_argv[0]) - 1;
02019 }
02020 for (x=0;x<argc;x++)
02021 _argv[x] = argv[x];
02022 _argv[x] = NULL;
02023
02024
02025 if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
02026 option_remote++;
02027 option_nofork++;
02028 }
02029 if (gethostname(hostname, sizeof(hostname)-1))
02030 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
02031 ast_mainpid = getpid();
02032 ast_ulaw_init();
02033 ast_alaw_init();
02034 callerid_init();
02035 ast_utils_init();
02036 tdd_init();
02037
02038
02039
02040 if (getenv("ASTERISK_ALREADY_NONROOT"))
02041 is_child_of_nonroot=1;
02042 if (getenv("HOME"))
02043 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
02044
02045
02046
02047
02048
02049
02050
02051
02052 while((c=getopt(argc, argv, "tThfdvVqprRgcinx:U:G:C:L:M:")) != -1) {
02053 switch(c) {
02054 case 'd':
02055 option_debug++;
02056 option_nofork++;
02057 break;
02058 case 'c':
02059 option_console++;
02060 option_nofork++;
02061 break;
02062 case 'f':
02063 option_nofork++;
02064 break;
02065 case 'n':
02066 option_nocolor++;
02067 break;
02068 case 'r':
02069 option_remote++;
02070 option_nofork++;
02071 break;
02072 case 'R':
02073 option_remote++;
02074 option_nofork++;
02075 option_reconnect++;
02076 break;
02077 case 'p':
02078 option_highpriority++;
02079 break;
02080 case 'v':
02081 option_verbose++;
02082 option_nofork++;
02083 break;
02084 case 'M':
02085 if ((sscanf(optarg, "%d", &option_maxcalls) != 1) || (option_maxcalls < 0))
02086 option_maxcalls = 0;
02087 break;
02088 case 'L':
02089 if ((sscanf(optarg, "%lf", &option_maxload) != 1) || (option_maxload < 0.0))
02090 option_maxload = 0.0;
02091 break;
02092 case 'q':
02093 option_quiet++;
02094 break;
02095 case 't':
02096 option_cache_record_files++;
02097 break;
02098 case 'T':
02099 option_timestamp++;
02100 break;
02101 case 'x':
02102 option_exec++;
02103 xarg = optarg;
02104 break;
02105 case 'C':
02106 ast_copy_string((char *)ast_config_AST_CONFIG_FILE,optarg,sizeof(ast_config_AST_CONFIG_FILE));
02107 option_overrideconfig++;
02108 break;
02109 case 'i':
02110 option_initcrypto++;
02111 break;
02112 case'g':
02113 option_dumpcore++;
02114 break;
02115 case 'h':
02116 show_cli_help();
02117 exit(0);
02118 case 'V':
02119 show_version();
02120 exit(0);
02121 case 'U':
02122 runuser = optarg;
02123 break;
02124 case 'G':
02125 rungroup = optarg;
02126 break;
02127 case '?':
02128 exit(1);
02129 }
02130 }
02131
02132
02133
02134
02135 if (option_remote) {
02136 strcpy(argv[0], "rasterisk");
02137 for (x = 1; x < argc; x++) {
02138 argv[x] = argv[0] + 10;
02139 }
02140 }
02141
02142 if (option_console && !option_verbose)
02143 ast_verbose("[ Reading Master Configuration ]");
02144 ast_readconfig();
02145
02146 if (option_dumpcore) {
02147 struct rlimit l;
02148 memset(&l, 0, sizeof(l));
02149 l.rlim_cur = RLIM_INFINITY;
02150 l.rlim_max = RLIM_INFINITY;
02151 if (setrlimit(RLIMIT_CORE, &l)) {
02152 ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
02153 }
02154 }
02155
02156 if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
02157 rungroup = ast_config_AST_RUN_GROUP;
02158 if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
02159 runuser = ast_config_AST_RUN_USER;
02160 #ifndef __CYGWIN__
02161
02162 if (!is_child_of_nonroot)
02163 ast_set_priority(option_highpriority);
02164
02165 if (!is_child_of_nonroot && rungroup) {
02166 struct group *gr;
02167 gr = getgrnam(rungroup);
02168 if (!gr) {
02169 ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
02170 exit(1);
02171 }
02172 if (setgid(gr->gr_gid)) {
02173 ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
02174 exit(1);
02175 }
02176 if (setgroups(0, NULL)) {
02177 ast_log(LOG_WARNING, "Unable to drop unneeded groups\n");
02178 exit(1);
02179 }
02180 if (option_verbose)
02181 ast_verbose("Running as group '%s'\n", rungroup);
02182 }
02183
02184 if (!is_child_of_nonroot && runuser) {
02185 struct passwd *pw;
02186 pw = getpwnam(runuser);
02187 if (!pw) {
02188 ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
02189 exit(1);
02190 }
02191 if (!rungroup) {
02192 if (setgid(pw->pw_gid)) {
02193 ast_log(LOG_WARNING, "Unable to setgid to %d!\n", (int)pw->pw_gid);
02194 exit(1);
02195 }
02196 if (initgroups(pw->pw_name, pw->pw_gid)) {
02197 ast_log(LOG_WARNING, "Unable to init groups for '%s'\n", runuser);
02198 exit(1);
02199 }
02200 }
02201 if (setuid(pw->pw_uid)) {
02202 ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
02203 exit(1);
02204 }
02205 setenv("ASTERISK_ALREADY_NONROOT","yes",1);
02206 if (option_verbose)
02207 ast_verbose("Running as user '%s'\n", runuser);
02208 }
02209
02210 #endif
02211
02212 #ifdef linux
02213
02214 if (geteuid() && option_dumpcore) {
02215 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
02216 ast_log(LOG_WARNING, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
02217 }
02218 }
02219
02220 #endif
02221
02222 term_init();
02223 printf(term_end());
02224 fflush(stdout);
02225
02226 if (option_console && !option_verbose)
02227 ast_verbose("[ Initializing Custom Configuration Options ]");
02228
02229 register_config_cli();
02230 read_config_maps();
02231
02232
02233 if (option_console) {
02234 if (el_hist == NULL || el == NULL)
02235 ast_el_initialize();
02236
02237 if (!ast_strlen_zero(filename))
02238 ast_el_read_history(filename);
02239 }
02240
02241 if (ast_tryconnect()) {
02242
02243 if (option_remote) {
02244 if (option_exec) {
02245 ast_remotecontrol(xarg);
02246 quit_handler(0, 0, 0, 0);
02247 exit(0);
02248 }
02249 printf(term_quit());
02250 ast_register_verbose(console_verboser);
02251 WELCOME_MESSAGE;
02252 ast_remotecontrol(NULL);
02253 quit_handler(0, 0, 0, 0);
02254 exit(0);
02255 } else {
02256 ast_log(LOG_ERROR, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", (char *)ast_config_AST_SOCKET);
02257 printf(term_quit());
02258 exit(1);
02259 }
02260 } else if (option_remote || option_exec) {
02261 ast_log(LOG_ERROR, "Unable to connect to remote asterisk (does %s exist?)\n",ast_config_AST_SOCKET);
02262 printf(term_quit());
02263 exit(1);
02264 }
02265
02266 unlink((char *)ast_config_AST_PID);
02267 f = fopen((char *)ast_config_AST_PID, "w");
02268 if (f) {
02269 fprintf(f, "%d\n", (int)getpid());
02270 fclose(f);
02271 } else
02272 ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", (char *)ast_config_AST_PID, strerror(errno));
02273
02274 if (!option_verbose && !option_debug && !option_nofork && !option_console) {
02275 daemon(0,0);
02276
02277 unlink((char *)ast_config_AST_PID);
02278 f = fopen((char *)ast_config_AST_PID, "w");
02279 if (f) {
02280 fprintf(f, "%d\n", (int)getpid());
02281 fclose(f);
02282 } else
02283 ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", (char *)ast_config_AST_PID, strerror(errno));
02284 ast_mainpid = getpid();
02285 }
02286
02287
02288 if (test_for_thread_safety())
02289 ast_verbose("Warning! Asterisk is not thread safe.\n");
02290
02291 ast_makesocket();
02292 sigemptyset(&sigs);
02293 sigaddset(&sigs, SIGHUP);
02294 sigaddset(&sigs, SIGTERM);
02295 sigaddset(&sigs, SIGINT);
02296 sigaddset(&sigs, SIGPIPE);
02297 sigaddset(&sigs, SIGWINCH);
02298 pthread_sigmask(SIG_BLOCK, &sigs, NULL);
02299 if (option_console || option_verbose || option_remote)
02300 ast_register_verbose(console_verboser);
02301
02302 if (option_verbose || option_console) {
02303 WELCOME_MESSAGE;
02304 }
02305 if (option_console && !option_verbose)
02306 ast_verbose("[ Booting...");
02307
02308 signal(SIGURG, urg_handler);
02309 signal(SIGINT, __quit_handler);
02310 signal(SIGTERM, __quit_handler);
02311 signal(SIGHUP, hup_handler);
02312 signal(SIGCHLD, child_handler);
02313 signal(SIGPIPE, SIG_IGN);
02314
02315
02316
02317
02318 srand((unsigned int) getpid() + (unsigned int) time(NULL));
02319 srandom((unsigned int) getpid() + (unsigned int) time(NULL));
02320
02321 if (init_logger()) {
02322 printf(term_quit());
02323 exit(1);
02324 }
02325 if (dnsmgr_init()) {
02326 printf(term_quit());
02327 exit(1);
02328 }
02329
02330 if (load_modules(1)) {
02331 printf(term_quit());
02332 exit(1);
02333 }
02334 ast_channels_init();
02335 if (init_manager()) {
02336 printf(term_quit());
02337 exit(1);
02338 }
02339 if (ast_cdr_engine_init()) {
02340 printf(term_quit());
02341 exit(1);
02342 }
02343 if (ast_device_state_engine_init()) {
02344 printf(term_quit());
02345 exit(1);
02346 }
02347 ast_rtp_init();
02348 if (ast_image_init()) {
02349 printf(term_quit());
02350 exit(1);
02351 }
02352 if (ast_file_init()) {
02353 printf(term_quit());
02354 exit(1);
02355 }
02356 if (load_pbx()) {
02357 printf(term_quit());
02358 exit(1);
02359 }
02360 if (init_framer()) {
02361 printf(term_quit());
02362 exit(1);
02363 }
02364 if (astdb_init()) {
02365 printf(term_quit());
02366 exit(1);
02367 }
02368 if (ast_enum_init()) {
02369 printf(term_quit());
02370 exit(1);
02371 }
02372 if (load_modules(0)) {
02373 printf(term_quit());
02374 exit(1);
02375 }
02376
02377 dnsmgr_start_refresh();
02378
02379 #if 0
02380
02381
02382 read_ast_cust_config();
02383 reload_logger(0);
02384 reload_manager();
02385 ast_enum_reload();
02386 ast_rtp_reload();
02387 #endif
02388
02389
02390
02391
02392 if (option_console && !option_verbose)
02393 ast_verbose(" ]\n");
02394 if (option_verbose || option_console)
02395 ast_verbose(term_color(tmp, "Asterisk Ready.\n", COLOR_BRWHITE, COLOR_BLACK, sizeof(tmp)));
02396 if (option_nofork)
02397 consolethread = pthread_self();
02398 fully_booted = 1;
02399 pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
02400 #ifdef __AST_DEBUG_MALLOC
02401 __ast_mm_init();
02402 #endif
02403 time(&ast_startuptime);
02404 ast_cli_register_multiple(core_cli, sizeof(core_cli) / sizeof(core_cli[0]));
02405 if (option_console) {
02406
02407
02408 char title[256];
02409 set_icon("Asterisk");
02410 snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %d)", hostname, ast_mainpid);
02411 set_title(title);
02412
02413 for (;;) {
02414 buf = (char *)el_gets(el, &num);
02415 if (buf) {
02416 if (buf[strlen(buf)-1] == '\n')
02417 buf[strlen(buf)-1] = '\0';
02418
02419 consolehandler((char *)buf);
02420 } else if (option_remote) {
02421 if (write(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n",
02422 strlen("\nUse EXIT or QUIT to exit the asterisk console\n")) < 0) {
02423
02424 int fd;
02425 fd = open("/dev/null", O_RDWR);
02426 if (fd > -1) {
02427 dup2(fd, STDOUT_FILENO);
02428 dup2(fd, STDIN_FILENO);
02429 } else
02430 ast_log(LOG_WARNING, "Failed to open /dev/null to recover from dead console. Bad things will happen!\n");
02431 break;
02432 }
02433 }
02434 }
02435
02436 }
02437
02438 for(;;) {
02439 struct pollfd p = { -1 , 0, 0 };
02440 poll(&p, 0, -1);
02441 }
02442 return 0;
02443 }