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