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 #include "asterisk.h"
00054
00055 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 312285 $")
00056
00057 #undef sched_setscheduler
00058 #undef setpriority
00059 #include <unistd.h>
00060 #include <stdlib.h>
00061 #include <sys/time.h>
00062 #include <fcntl.h>
00063 #include <stdio.h>
00064 #include <signal.h>
00065 #include <sched.h>
00066 #include <sys/socket.h>
00067 #include <sys/un.h>
00068 #include <sys/wait.h>
00069 #include <string.h>
00070 #include <errno.h>
00071 #include <ctype.h>
00072 #include <sys/resource.h>
00073 #include <grp.h>
00074 #include <pwd.h>
00075 #include <sys/stat.h>
00076
00077 #if defined(HAVE_ZAPTEL) || defined (HAVE_DAHDI)
00078 #include <sys/ioctl.h>
00079 #include "asterisk/dahdi_compat.h"
00080 #endif
00081
00082 #if defined(HAVE_SYSINFO)
00083 #include <sys/sysinfo.h>
00084 #endif
00085
00086 #ifdef linux
00087 #include <sys/prctl.h>
00088 #ifdef HAVE_CAP
00089 #include <sys/capability.h>
00090 #endif
00091 #endif
00092 #include <regex.h>
00093
00094 #if defined(__FreeBSD__) || defined( __NetBSD__ ) || defined(SOLARIS)
00095 #include <netdb.h>
00096 #if defined(SOLARIS)
00097 int daemon(int, int);
00098 #endif
00099 #endif
00100
00101 #include "asterisk/logger.h"
00102 #include "asterisk/options.h"
00103 #include "asterisk/cli.h"
00104 #include "asterisk/channel.h"
00105 #include "asterisk/ulaw.h"
00106 #include "asterisk/alaw.h"
00107 #include "asterisk/callerid.h"
00108 #include "asterisk/image.h"
00109 #include "asterisk/tdd.h"
00110 #include "asterisk/term.h"
00111 #include "asterisk/manager.h"
00112 #include "asterisk/cdr.h"
00113 #include "asterisk/pbx.h"
00114 #include "asterisk/enum.h"
00115 #include "asterisk/rtp.h"
00116 #include "asterisk/http.h"
00117 #include "asterisk/udptl.h"
00118 #include "asterisk/app.h"
00119 #include "asterisk/lock.h"
00120 #include "asterisk/utils.h"
00121 #include "asterisk/file.h"
00122 #include "asterisk/io.h"
00123 #include "asterisk/lock.h"
00124 #include "editline/histedit.h"
00125 #include "asterisk/config.h"
00126 #include "asterisk/version.h"
00127 #include "asterisk/linkedlists.h"
00128 #include "asterisk/devicestate.h"
00129 #include "asterisk/module.h"
00130 #include "asterisk/poll-compat.h"
00131
00132 #include "asterisk/doxyref.h"
00133
00134 #include "../defaults.h"
00135
00136 #ifndef AF_LOCAL
00137 #define AF_LOCAL AF_UNIX
00138 #define PF_LOCAL PF_UNIX
00139 #endif
00140
00141 #define AST_MAX_CONNECTS 128
00142 #define NUM_MSGS 64
00143
00144
00145 #define WELCOME_MESSAGE \
00146 ast_verbose("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2010 Digium, Inc. and others.\n"); \
00147 ast_verbose("Created by Mark Spencer <markster@digium.com>\n"); \
00148 ast_verbose("Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n"); \
00149 ast_verbose("This is free software, with components licensed under the GNU General Public\n"); \
00150 ast_verbose("License version 2 and other licenses; you are welcome to redistribute it under\n"); \
00151 ast_verbose("certain conditions. Type 'core show license' for details.\n"); \
00152 ast_verbose("=========================================================================\n")
00153
00154
00155
00156
00157
00158
00159
00160
00161 struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
00162
00163 int option_verbose;
00164 int option_debug;
00165
00166 double option_maxload;
00167 int option_maxcalls;
00168 int option_maxfiles = 0;
00169 #if defined(HAVE_SYSINFO)
00170 long option_minmemfree = 0;
00171 #endif
00172
00173
00174 char record_cache_dir[AST_CACHE_DIR_LEN] = AST_TMP_DIR;
00175 char debug_filename[AST_FILENAME_MAX] = "";
00176 #ifdef HAVE_ZAPTEL
00177 static char _dahdi_chan_name[AST_CHANNEL_NAME] = "Zap";
00178 static size_t _dahdi_chan_name_len = 3;
00179 static enum dahdi_chan_modes _dahdi_chan_mode = CHAN_ZAP_MODE;
00180 #else
00181 static char _dahdi_chan_name[AST_CHANNEL_NAME] = "DAHDI";
00182 static size_t _dahdi_chan_name_len = 5;
00183 static enum dahdi_chan_modes _dahdi_chan_mode = CHAN_DAHDI_PLUS_ZAP_MODE;
00184 #endif
00185 const char *dahdi_chan_name;
00186 const size_t *dahdi_chan_name_len;
00187 const enum dahdi_chan_modes *dahdi_chan_mode;
00188
00189 static int ast_socket = -1;
00190 static int ast_consock = -1;
00191 pid_t ast_mainpid;
00192 struct console {
00193 int fd;
00194 int p[2];
00195 pthread_t t;
00196 int mute;
00197 };
00198
00199 struct ast_atexit {
00200 void (*func)(void);
00201 AST_LIST_ENTRY(ast_atexit) list;
00202 };
00203
00204 static AST_LIST_HEAD_STATIC(atexits, ast_atexit);
00205
00206 time_t ast_startuptime;
00207 time_t ast_lastreloadtime;
00208
00209 static History *el_hist;
00210 static EditLine *el;
00211 static char *remotehostname;
00212
00213 struct console consoles[AST_MAX_CONNECTS];
00214
00215 char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
00216
00217 static int ast_el_add_history(char *);
00218 static int ast_el_read_history(char *);
00219 static int ast_el_write_history(char *);
00220
00221 char ast_config_AST_CONFIG_DIR[PATH_MAX];
00222 char ast_config_AST_CONFIG_FILE[PATH_MAX];
00223 char ast_config_AST_MODULE_DIR[PATH_MAX];
00224 char ast_config_AST_SPOOL_DIR[PATH_MAX];
00225 char ast_config_AST_MONITOR_DIR[PATH_MAX];
00226 char ast_config_AST_VAR_DIR[PATH_MAX];
00227 char ast_config_AST_DATA_DIR[PATH_MAX];
00228 char ast_config_AST_LOG_DIR[PATH_MAX];
00229 char ast_config_AST_AGI_DIR[PATH_MAX];
00230 char ast_config_AST_DB[PATH_MAX];
00231 char ast_config_AST_KEY_DIR[PATH_MAX];
00232 char ast_config_AST_PID[PATH_MAX];
00233 char ast_config_AST_SOCKET[PATH_MAX];
00234 char ast_config_AST_RUN_DIR[PATH_MAX];
00235 char ast_config_AST_RUN_USER[PATH_MAX];
00236 char ast_config_AST_RUN_GROUP[PATH_MAX];
00237 char ast_config_AST_CTL_PERMISSIONS[PATH_MAX];
00238 char ast_config_AST_CTL_OWNER[PATH_MAX] = "\0";
00239 char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0";
00240 char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl";
00241 char ast_config_AST_SYSTEM_NAME[20] = "";
00242
00243 extern const char *ast_build_hostname;
00244 extern const char *ast_build_kernel;
00245 extern const char *ast_build_machine;
00246 extern const char *ast_build_os;
00247 extern const char *ast_build_date;
00248 extern const char *ast_build_user;
00249
00250 unsigned int ast_FD_SETSIZE = FD_SETSIZE;
00251
00252 static char *_argv[256];
00253 static int shuttingdown;
00254 static int restartnow;
00255 static pthread_t consolethread = AST_PTHREADT_NULL;
00256 static pthread_t mon_sig_flags;
00257
00258 static char randompool[256];
00259
00260 static int sig_alert_pipe[2] = { -1, -1 };
00261 static struct {
00262 unsigned int need_reload:1;
00263 unsigned int need_quit:1;
00264 } sig_flags;
00265
00266 #if !defined(LOW_MEMORY)
00267 struct file_version {
00268 AST_LIST_ENTRY(file_version) list;
00269 const char *file;
00270 char *version;
00271 };
00272
00273 #ifndef AST_MUTEX_INIT_W_CONSTRUCTORS
00274 static AST_LIST_HEAD_STATIC(file_versions, file_version);
00275 #else
00276 static AST_LIST_HEAD(file_versions, file_version) file_versions;
00277 static pthread_once_t file_versions_once = PTHREAD_ONCE_INIT;
00278 static void file_versions_init(void)
00279 {
00280 AST_LIST_HEAD_INIT(&file_versions);
00281 }
00282 #endif
00283
00284 void ast_register_file_version(const char *file, const char *version)
00285 {
00286 struct file_version *new;
00287 char *work;
00288 size_t version_length;
00289
00290 work = ast_strdupa(version);
00291 work = ast_strip(ast_strip_quoted(work, "$", "$"));
00292 version_length = strlen(work) + 1;
00293
00294 if (!(new = ast_calloc(1, sizeof(*new) + version_length)))
00295 return;
00296
00297 new->file = file;
00298 new->version = (char *) new + sizeof(*new);
00299 memcpy(new->version, work, version_length);
00300 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00301 pthread_once(&file_versions_once, file_versions_init);
00302 #endif
00303 AST_LIST_LOCK(&file_versions);
00304 AST_LIST_INSERT_HEAD(&file_versions, new, list);
00305 AST_LIST_UNLOCK(&file_versions);
00306 }
00307
00308 void ast_unregister_file_version(const char *file)
00309 {
00310 struct file_version *find;
00311
00312 AST_LIST_LOCK(&file_versions);
00313 AST_LIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) {
00314 if (!strcasecmp(find->file, file)) {
00315 AST_LIST_REMOVE_CURRENT(&file_versions, list);
00316 break;
00317 }
00318 }
00319 AST_LIST_TRAVERSE_SAFE_END;
00320 AST_LIST_UNLOCK(&file_versions);
00321 if (find)
00322 ast_free(find);
00323 }
00324
00325 struct thread_list_t {
00326 AST_LIST_ENTRY(thread_list_t) list;
00327 char *name;
00328 pthread_t id;
00329 };
00330
00331 static AST_LIST_HEAD_STATIC(thread_list, thread_list_t);
00332
00333 static char show_threads_help[] =
00334 "Usage: core show threads\n"
00335 " List threads currently active in the system.\n";
00336
00337 static char show_settings_help[] =
00338 "Usage: core show settings\n"
00339 " Show core misc settings.\n";
00340
00341 static char show_sysinfo_help[] =
00342 "Usage: core show sysinfo\n"
00343 " List current system information.\n";
00344
00345 void ast_register_thread(char *name)
00346 {
00347 struct thread_list_t *new = ast_calloc(1, sizeof(*new));
00348
00349 if (!new)
00350 return;
00351 new->id = pthread_self();
00352 new->name = name;
00353 AST_LIST_LOCK(&thread_list);
00354 AST_LIST_INSERT_HEAD(&thread_list, new, list);
00355 AST_LIST_UNLOCK(&thread_list);
00356 }
00357
00358 void ast_unregister_thread(void *id)
00359 {
00360 struct thread_list_t *x;
00361
00362 AST_LIST_LOCK(&thread_list);
00363 AST_LIST_TRAVERSE_SAFE_BEGIN(&thread_list, x, list) {
00364 if ((void *) x->id == id) {
00365 AST_LIST_REMOVE_CURRENT(&thread_list, list);
00366 break;
00367 }
00368 }
00369 AST_LIST_TRAVERSE_SAFE_END;
00370 AST_LIST_UNLOCK(&thread_list);
00371 if (x) {
00372 ast_free(x->name);
00373 ast_free(x);
00374 }
00375 }
00376
00377
00378 static int handle_show_settings(int fd, int argc, char *argv[])
00379 {
00380 char buf[BUFSIZ];
00381 struct tm tm;
00382
00383 ast_cli(fd, "\nPBX Core settings\n");
00384 ast_cli(fd, "-----------------\n");
00385 ast_cli(fd, " Version: %s\n", "" ASTERISK_VERSION "" );
00386 if (option_maxcalls)
00387 ast_cli(fd, " Max. calls: %d (Current %d)\n", option_maxcalls, ast_active_channels());
00388 else
00389 ast_cli(fd, " Max. calls: Not set\n");
00390 if (option_maxfiles)
00391 ast_cli(fd, " Max. open file handles: %d\n", option_maxfiles);
00392 else
00393 ast_cli(fd, " Max. open file handles: Not set\n");
00394 ast_cli(fd, " Verbosity: %d\n", option_verbose);
00395 ast_cli(fd, " Debug level: %d\n", option_debug);
00396 ast_cli(fd, " Max load avg: %lf\n", option_maxload);
00397 #if defined(HAVE_SYSINFO)
00398 ast_cli(fd, " Min Free Memory: %ld MB\n", option_minmemfree);
00399 #endif
00400 if (ast_localtime(&ast_startuptime, &tm, NULL)) {
00401 strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
00402 ast_cli(fd, " Startup time: %s\n", buf);
00403 }
00404 if (ast_localtime(&ast_lastreloadtime, &tm, NULL)) {
00405 strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
00406 ast_cli(fd, " Last reload time: %s\n", buf);
00407 }
00408 ast_cli(fd, " System: %s/%s built by %s on %s %s\n", ast_build_os, ast_build_kernel, ast_build_user, ast_build_machine, ast_build_date);
00409 ast_cli(fd, " System name: %s\n", ast_config_AST_SYSTEM_NAME);
00410 ast_cli(fd, " Default language: %s\n", defaultlanguage);
00411 ast_cli(fd, " Language prefix: %s\n", ast_language_is_prefix ? "Enabled" : "Disabled");
00412 ast_cli(fd, " User name and group: %s/%s\n", ast_config_AST_RUN_USER, ast_config_AST_RUN_GROUP);
00413 ast_cli(fd, " Executable includes: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) ? "Enabled" : "Disabled");
00414 ast_cli(fd, " Transcode via SLIN: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN) ? "Enabled" : "Disabled");
00415 ast_cli(fd, " Internal timing: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING) ? "Enabled" : "Disabled");
00416 ast_cli(fd, " Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING) ? "Enabled" : "Disabled");
00417
00418 struct rlimit rlim;
00419 if (!getrlimit(RLIMIT_NOFILE, &rlim))
00420 ast_cli(fd, " Current fd limits: current: %i max: %i\n", rlim.rlim_cur, rlim.rlim_max);
00421 ast_cli(fd, "\n* Subsystems\n");
00422 ast_cli(fd, " -------------\n");
00423 ast_cli(fd, " Manager (AMI): %s\n", check_manager_enabled() ? "Enabled" : "Disabled");
00424 ast_cli(fd, " Web Manager (AMI/HTTP): %s\n", check_webmanager_enabled() ? "Enabled" : "Disabled");
00425 ast_cli(fd, " Call data records: %s\n", check_cdr_enabled() ? "Enabled" : "Disabled");
00426 ast_cli(fd, " Realtime Architecture (ARA): %s\n", ast_realtime_enabled() ? "Enabled" : "Disabled");
00427
00428
00429
00430 ast_cli(fd, "\n* Directories\n");
00431 ast_cli(fd, " -------------\n");
00432 ast_cli(fd, " Configuration file: %s\n", ast_config_AST_CONFIG_FILE);
00433 ast_cli(fd, " Configuration directory: %s\n", ast_config_AST_CONFIG_DIR);
00434 ast_cli(fd, " Module directory: %s\n", ast_config_AST_MODULE_DIR);
00435 ast_cli(fd, " Spool directory: %s\n", ast_config_AST_SPOOL_DIR);
00436 ast_cli(fd, " Log directory: %s\n", ast_config_AST_LOG_DIR);
00437 ast_cli(fd, "\n\n");
00438 return RESULT_SUCCESS;
00439 }
00440
00441 static int handle_show_threads(int fd, int argc, char *argv[])
00442 {
00443 int count = 0;
00444 struct thread_list_t *cur;
00445
00446 AST_LIST_LOCK(&thread_list);
00447 AST_LIST_TRAVERSE(&thread_list, cur, list) {
00448 ast_cli(fd, "%p %s\n", (void *)cur->id, cur->name);
00449 count++;
00450 }
00451 AST_LIST_UNLOCK(&thread_list);
00452 ast_cli(fd, "%d threads listed.\n", count);
00453 return RESULT_SUCCESS;
00454 }
00455
00456 #if defined(HAVE_SYSINFO)
00457
00458 static int handle_show_sysinfo(int fd, int argc, char *argv[])
00459 {
00460 struct sysinfo sys_info;
00461
00462 if (sysinfo(&sys_info)) {
00463 ast_cli(fd, "FAILED to retrieve system information\n\n");
00464 return RESULT_FAILURE;
00465 }
00466 ast_cli(fd, "\nSystem Statistics\n");
00467 ast_cli(fd, "-----------------\n");
00468 ast_cli(fd, " System Uptime: %ld hours\n", sys_info.uptime/3600);
00469 ast_cli(fd, " Total RAM: %ld KiB\n", (sys_info.totalram / sys_info.mem_unit)/1024);
00470 ast_cli(fd, " Free RAM: %ld KiB\n", (sys_info.freeram / sys_info.mem_unit)/1024);
00471 ast_cli(fd, " Buffer RAM: %ld KiB\n", (sys_info.bufferram / sys_info.mem_unit)/1024);
00472 ast_cli(fd, " Total Swap Space: %ld KiB\n", (sys_info.totalswap / sys_info.mem_unit)/1024);
00473 ast_cli(fd, " Free Swap Space: %ld KiB\n\n", (sys_info.freeswap / sys_info.mem_unit)/1024);
00474 ast_cli(fd, " Number of Processes: %d \n\n", sys_info.procs);
00475 return RESULT_SUCCESS;
00476 }
00477 #endif
00478
00479 struct profile_entry {
00480 const char *name;
00481 uint64_t scale;
00482 int64_t mark;
00483 int64_t value;
00484 int64_t events;
00485 };
00486
00487 struct profile_data {
00488 int entries;
00489 int max_size;
00490 struct profile_entry e[0];
00491 };
00492
00493 static struct profile_data *prof_data;
00494
00495
00496
00497
00498 int ast_add_profile(const char *name, uint64_t scale)
00499 {
00500 int l = sizeof(struct profile_data);
00501 int n = 10;
00502
00503 if (prof_data == NULL) {
00504 prof_data = ast_calloc(1, l + n*sizeof(struct profile_entry));
00505 if (prof_data == NULL)
00506 return -1;
00507 prof_data->entries = 0;
00508 prof_data->max_size = n;
00509 }
00510 if (prof_data->entries >= prof_data->max_size) {
00511 void *p;
00512 n = prof_data->max_size + 20;
00513 p = ast_realloc(prof_data, l + n*sizeof(struct profile_entry));
00514 if (p == NULL)
00515 return -1;
00516 prof_data = p;
00517 prof_data->max_size = n;
00518 }
00519 n = prof_data->entries++;
00520 prof_data->e[n].name = ast_strdup(name);
00521 prof_data->e[n].value = 0;
00522 prof_data->e[n].events = 0;
00523 prof_data->e[n].mark = 0;
00524 prof_data->e[n].scale = scale;
00525 return n;
00526 }
00527
00528 int64_t ast_profile(int i, int64_t delta)
00529 {
00530 if (!prof_data || i < 0 || i > prof_data->entries)
00531 return 0;
00532 if (prof_data->e[i].scale > 1)
00533 delta /= prof_data->e[i].scale;
00534 prof_data->e[i].value += delta;
00535 prof_data->e[i].events++;
00536 return prof_data->e[i].value;
00537 }
00538
00539
00540
00541
00542 #if defined ( __i686__) && (defined(__FreeBSD__) || defined(linux))
00543 #if defined(__FreeBSD__)
00544 #include <machine/cpufunc.h>
00545 #elif defined(linux)
00546 static __inline uint64_t
00547 rdtsc(void)
00548 {
00549 uint64_t rv;
00550
00551 __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
00552 return (rv);
00553 }
00554 #endif
00555 #else
00556 static __inline uint64_t
00557 rdtsc(void)
00558 {
00559 return 0;
00560 }
00561 #endif
00562
00563 int64_t ast_mark(int i, int startstop)
00564 {
00565 if (!prof_data || i < 0 || i > prof_data->entries)
00566 return 0;
00567 if (startstop == 1)
00568 prof_data->e[i].mark = rdtsc();
00569 else {
00570 prof_data->e[i].mark = (rdtsc() - prof_data->e[i].mark);
00571 if (prof_data->e[i].scale > 1)
00572 prof_data->e[i].mark /= prof_data->e[i].scale;
00573 prof_data->e[i].value += prof_data->e[i].mark;
00574 prof_data->e[i].events++;
00575 }
00576 return prof_data->e[i].mark;
00577 }
00578
00579 static int handle_show_profile_deprecated(int fd, int argc, char *argv[])
00580 {
00581 int i, min, max;
00582 char *search = NULL;
00583
00584 if (prof_data == NULL)
00585 return 0;
00586
00587 min = 0;
00588 max = prof_data->entries;
00589 if (argc >= 3) {
00590 if (isdigit(argv[2][0])) {
00591 min = atoi(argv[2]);
00592 if (argc == 4 && strcmp(argv[3], "-"))
00593 max = atoi(argv[3]);
00594 } else
00595 search = argv[2];
00596 }
00597 if (max > prof_data->entries)
00598 max = prof_data->entries;
00599 if (!strcmp(argv[0], "clear")) {
00600 for (i= min; i < max; i++) {
00601 if (!search || strstr(prof_data->e[i].name, search)) {
00602 prof_data->e[i].value = 0;
00603 prof_data->e[i].events = 0;
00604 }
00605 }
00606 return 0;
00607 }
00608 ast_cli(fd, "profile values (%d, allocated %d)\n-------------------\n",
00609 prof_data->entries, prof_data->max_size);
00610 ast_cli(fd, "%6s %8s %10s %12s %12s %s\n", "ID", "Scale", "Events",
00611 "Value", "Average", "Name");
00612 for (i = min; i < max; i++) {
00613 struct profile_entry *e = &prof_data->e[i];
00614 if (!search || strstr(prof_data->e[i].name, search))
00615 ast_cli(fd, "%6d: [%8ld] %10ld %12lld %12lld %s\n",
00616 i,
00617 (long)e->scale,
00618 (long)e->events, (long long)e->value,
00619 (long long)(e->events ? e->value / e->events : e->value),
00620 e->name);
00621 }
00622 return 0;
00623 }
00624
00625 static int handle_show_profile(int fd, int argc, char *argv[])
00626 {
00627 int i, min, max;
00628 char *search = NULL;
00629
00630 if (prof_data == NULL)
00631 return 0;
00632
00633 min = 0;
00634 max = prof_data->entries;
00635 if (argc > 3) {
00636 if (isdigit(argv[3][0])) {
00637 min = atoi(argv[3]);
00638 if (argc == 5 && strcmp(argv[4], "-"))
00639 max = atoi(argv[4]);
00640 } else
00641 search = argv[3];
00642 }
00643 if (max > prof_data->entries)
00644 max = prof_data->entries;
00645 if (!strcmp(argv[1], "clear")) {
00646 for (i= min; i < max; i++) {
00647 if (!search || strstr(prof_data->e[i].name, search)) {
00648 prof_data->e[i].value = 0;
00649 prof_data->e[i].events = 0;
00650 }
00651 }
00652 return 0;
00653 }
00654 ast_cli(fd, "profile values (%d, allocated %d)\n-------------------\n",
00655 prof_data->entries, prof_data->max_size);
00656 ast_cli(fd, "%6s %8s %10s %12s %12s %s\n", "ID", "Scale", "Events",
00657 "Value", "Average", "Name");
00658 for (i = min; i < max; i++) {
00659 struct profile_entry *e = &prof_data->e[i];
00660 if (!search || strstr(prof_data->e[i].name, search))
00661 ast_cli(fd, "%6d: [%8ld] %10ld %12lld %12lld %s\n",
00662 i,
00663 (long)e->scale,
00664 (long)e->events, (long long)e->value,
00665 (long long)(e->events ? e->value / e->events : e->value),
00666 e->name);
00667 }
00668 return 0;
00669 }
00670
00671 static char show_version_files_help[] =
00672 "Usage: core show file version [like <pattern>]\n"
00673 " Lists the revision numbers of the files used to build this copy of Asterisk.\n"
00674 " Optional regular expression pattern is used to filter the file list.\n";
00675
00676
00677 static int handle_show_version_files_deprecated(int fd, int argc, char *argv[])
00678 {
00679 #define FORMAT "%-25.25s %-40.40s\n"
00680 struct file_version *iterator;
00681 regex_t regexbuf;
00682 int havepattern = 0;
00683 int havename = 0;
00684 int count_files = 0;
00685
00686 switch (argc) {
00687 case 5:
00688 if (!strcasecmp(argv[3], "like")) {
00689 if (regcomp(®exbuf, argv[4], REG_EXTENDED | REG_NOSUB))
00690 return RESULT_SHOWUSAGE;
00691 havepattern = 1;
00692 } else
00693 return RESULT_SHOWUSAGE;
00694 break;
00695 case 4:
00696 havename = 1;
00697 break;
00698 case 3:
00699 break;
00700 default:
00701 return RESULT_SHOWUSAGE;
00702 }
00703
00704 ast_cli(fd, FORMAT, "File", "Revision");
00705 ast_cli(fd, FORMAT, "----", "--------");
00706 AST_LIST_LOCK(&file_versions);
00707 AST_LIST_TRAVERSE(&file_versions, iterator, list) {
00708 if (havename && strcasecmp(iterator->file, argv[3]))
00709 continue;
00710
00711 if (havepattern && regexec(®exbuf, iterator->file, 0, NULL, 0))
00712 continue;
00713
00714 ast_cli(fd, FORMAT, iterator->file, iterator->version);
00715 count_files++;
00716 if (havename)
00717 break;
00718 }
00719 AST_LIST_UNLOCK(&file_versions);
00720 if (!havename) {
00721 ast_cli(fd, "%d files listed.\n", count_files);
00722 }
00723
00724 if (havepattern)
00725 regfree(®exbuf);
00726
00727 return RESULT_SUCCESS;
00728 #undef FORMAT
00729 }
00730
00731 static int handle_show_version_files(int fd, int argc, char *argv[])
00732 {
00733 #define FORMAT "%-25.25s %-40.40s\n"
00734 struct file_version *iterator;
00735 regex_t regexbuf;
00736 int havepattern = 0;
00737 int havename = 0;
00738 int count_files = 0;
00739
00740 switch (argc) {
00741 case 6:
00742 if (!strcasecmp(argv[4], "like")) {
00743 if (regcomp(®exbuf, argv[5], REG_EXTENDED | REG_NOSUB))
00744 return RESULT_SHOWUSAGE;
00745 havepattern = 1;
00746 } else
00747 return RESULT_SHOWUSAGE;
00748 break;
00749 case 5:
00750 havename = 1;
00751 break;
00752 case 4:
00753 break;
00754 default:
00755 return RESULT_SHOWUSAGE;
00756 }
00757
00758 ast_cli(fd, FORMAT, "File", "Revision");
00759 ast_cli(fd, FORMAT, "----", "--------");
00760 AST_LIST_LOCK(&file_versions);
00761 AST_LIST_TRAVERSE(&file_versions, iterator, list) {
00762 if (havename && strcasecmp(iterator->file, argv[4]))
00763 continue;
00764
00765 if (havepattern && regexec(®exbuf, iterator->file, 0, NULL, 0))
00766 continue;
00767
00768 ast_cli(fd, FORMAT, iterator->file, iterator->version);
00769 count_files++;
00770 if (havename)
00771 break;
00772 }
00773 AST_LIST_UNLOCK(&file_versions);
00774 if (!havename) {
00775 ast_cli(fd, "%d files listed.\n", count_files);
00776 }
00777
00778 if (havepattern)
00779 regfree(®exbuf);
00780
00781 return RESULT_SUCCESS;
00782 #undef FORMAT
00783 }
00784
00785 static char *complete_show_version_files_deprecated(const char *line, const char *word, int pos, int state)
00786 {
00787 struct file_version *find;
00788 int which = 0;
00789 char *ret = NULL;
00790 int matchlen = strlen(word);
00791
00792 if (pos != 3)
00793 return NULL;
00794
00795 AST_LIST_LOCK(&file_versions);
00796 AST_LIST_TRAVERSE(&file_versions, find, list) {
00797 if (!strncasecmp(word, find->file, matchlen) && ++which > state) {
00798 ret = ast_strdup(find->file);
00799 break;
00800 }
00801 }
00802 AST_LIST_UNLOCK(&file_versions);
00803
00804 return ret;
00805 }
00806
00807 static char *complete_show_version_files(const char *line, const char *word, int pos, int state)
00808 {
00809 struct file_version *find;
00810 int which = 0;
00811 char *ret = NULL;
00812 int matchlen = strlen(word);
00813
00814 if (pos != 4)
00815 return NULL;
00816
00817 AST_LIST_LOCK(&file_versions);
00818 AST_LIST_TRAVERSE(&file_versions, find, list) {
00819 if (!strncasecmp(word, find->file, matchlen) && ++which > state) {
00820 ret = ast_strdup(find->file);
00821 break;
00822 }
00823 }
00824 AST_LIST_UNLOCK(&file_versions);
00825
00826 return ret;
00827 }
00828
00829 #endif
00830
00831 int ast_register_atexit(void (*func)(void))
00832 {
00833 struct ast_atexit *ae;
00834
00835 if (!(ae = ast_calloc(1, sizeof(*ae))))
00836 return -1;
00837
00838 ae->func = func;
00839
00840 ast_unregister_atexit(func);
00841
00842 AST_LIST_LOCK(&atexits);
00843 AST_LIST_INSERT_HEAD(&atexits, ae, list);
00844 AST_LIST_UNLOCK(&atexits);
00845
00846 return 0;
00847 }
00848
00849 void ast_unregister_atexit(void (*func)(void))
00850 {
00851 struct ast_atexit *ae = NULL;
00852
00853 AST_LIST_LOCK(&atexits);
00854 AST_LIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) {
00855 if (ae->func == func) {
00856 AST_LIST_REMOVE_CURRENT(&atexits, list);
00857 break;
00858 }
00859 }
00860 AST_LIST_TRAVERSE_SAFE_END
00861 AST_LIST_UNLOCK(&atexits);
00862
00863 if (ae)
00864 free(ae);
00865 }
00866
00867
00868 static int fdsend(int fd, const char *s)
00869 {
00870 return write(fd, s, strlen(s) + 1);
00871 }
00872
00873
00874 static int fdprint(int fd, const char *s)
00875 {
00876 return write(fd, s, strlen(s));
00877 }
00878
00879
00880 static void _null_sig_handler(int signal)
00881 {
00882
00883 }
00884
00885 static struct sigaction null_sig_handler = {
00886 .sa_handler = _null_sig_handler,
00887 .sa_flags = SA_RESTART,
00888 };
00889
00890 AST_MUTEX_DEFINE_STATIC(safe_system_lock);
00891
00892
00893 static unsigned int safe_system_level = 0;
00894 static struct sigaction safe_system_prev_handler;
00895
00896 void ast_replace_sigchld(void)
00897 {
00898 unsigned int level;
00899
00900 ast_mutex_lock(&safe_system_lock);
00901 level = safe_system_level++;
00902
00903
00904 if (level == 0) {
00905 sigaction(SIGCHLD, &null_sig_handler, &safe_system_prev_handler);
00906 }
00907
00908 ast_mutex_unlock(&safe_system_lock);
00909 }
00910
00911 void ast_unreplace_sigchld(void)
00912 {
00913 unsigned int level;
00914
00915 ast_mutex_lock(&safe_system_lock);
00916 level = --safe_system_level;
00917
00918
00919 if (level == 0) {
00920 sigaction(SIGCHLD, &safe_system_prev_handler, NULL);
00921 }
00922
00923 ast_mutex_unlock(&safe_system_lock);
00924 }
00925
00926 int ast_safe_system(const char *s)
00927 {
00928 pid_t pid;
00929 #ifdef HAVE_WORKING_FORK
00930 int x;
00931 #endif
00932 int res;
00933 struct rusage rusage;
00934 int status;
00935
00936 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
00937 ast_replace_sigchld();
00938
00939 #ifdef HAVE_WORKING_FORK
00940 pid = fork();
00941 #else
00942 pid = vfork();
00943 #endif
00944
00945 if (pid == 0) {
00946 #ifdef HAVE_CAP
00947 cap_t cap = cap_from_text("cap_net_admin-eip");
00948
00949 if (cap_set_proc(cap)) {
00950
00951 ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
00952 }
00953 cap_free(cap);
00954 #endif
00955 #ifdef HAVE_WORKING_FORK
00956 if (ast_opt_high_priority)
00957 ast_set_priority(0);
00958
00959 for (x = STDERR_FILENO + 1; x < 4096; x++)
00960 close(x);
00961 #endif
00962 execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
00963 _exit(1);
00964 } else if (pid > 0) {
00965 for(;;) {
00966 res = wait4(pid, &status, 0, &rusage);
00967 if (res > -1) {
00968 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
00969 break;
00970 } else if (errno != EINTR)
00971 break;
00972 }
00973 } else {
00974 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
00975 res = -1;
00976 }
00977
00978 ast_unreplace_sigchld();
00979 #else
00980 res = -1;
00981 #endif
00982
00983 return res;
00984 }
00985
00986
00987
00988
00989 void ast_console_toggle_mute(int fd, int silent) {
00990 int x;
00991 for (x = 0;x < AST_MAX_CONNECTS; x++) {
00992 if (fd == consoles[x].fd) {
00993 if (consoles[x].mute) {
00994 consoles[x].mute = 0;
00995 if (!silent)
00996 ast_cli(fd, "Console is not muted anymore.\n");
00997 } else {
00998 consoles[x].mute = 1;
00999 if (!silent)
01000 ast_cli(fd, "Console is muted.\n");
01001 }
01002 return;
01003 }
01004 }
01005 ast_cli(fd, "Couldn't find remote console.\n");
01006 }
01007
01008
01009
01010
01011 static void ast_network_puts_mutable(const char *string)
01012 {
01013 int x;
01014 for (x = 0;x < AST_MAX_CONNECTS; x++) {
01015 if (consoles[x].mute)
01016 continue;
01017 if (consoles[x].fd > -1)
01018 fdprint(consoles[x].p[1], string);
01019 }
01020 }
01021
01022
01023
01024
01025
01026 void ast_console_puts_mutable(const char *string)
01027 {
01028 fputs(string, stdout);
01029 fflush(stdout);
01030 ast_network_puts_mutable(string);
01031 }
01032
01033
01034
01035
01036 static void ast_network_puts(const char *string)
01037 {
01038 int x;
01039 for (x=0; x < AST_MAX_CONNECTS; x++) {
01040 if (consoles[x].fd > -1)
01041 fdprint(consoles[x].p[1], string);
01042 }
01043 }
01044
01045
01046
01047
01048
01049 void ast_console_puts(const char *string)
01050 {
01051 fputs(string, stdout);
01052 fflush(stdout);
01053 ast_network_puts(string);
01054 }
01055
01056 static void network_verboser(const char *s)
01057 {
01058 ast_network_puts_mutable(s);
01059 }
01060
01061 static pthread_t lthread;
01062
01063 static void *netconsole(void *vconsole)
01064 {
01065 struct console *con = vconsole;
01066 char hostname[MAXHOSTNAMELEN] = "";
01067 char tmp[512];
01068 int res;
01069 struct pollfd fds[2];
01070
01071 if (gethostname(hostname, sizeof(hostname)-1))
01072 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
01073 snprintf(tmp, sizeof(tmp), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ASTERISK_VERSION);
01074 fdprint(con->fd, tmp);
01075 for(;;) {
01076 fds[0].fd = con->fd;
01077 fds[0].events = POLLIN;
01078 fds[0].revents = 0;
01079 fds[1].fd = con->p[0];
01080 fds[1].events = POLLIN;
01081 fds[1].revents = 0;
01082
01083 res = ast_poll(fds, 2, -1);
01084 if (res < 0) {
01085 if (errno != EINTR)
01086 ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
01087 continue;
01088 }
01089 if (fds[0].revents) {
01090 res = read(con->fd, tmp, sizeof(tmp) - 1);
01091 if (res < 1) {
01092 break;
01093 }
01094 tmp[res] = 0;
01095 ast_cli_command_multiple(con->fd, res, tmp);
01096 }
01097 if (fds[1].revents) {
01098 res = read(con->p[0], tmp, sizeof(tmp));
01099 if (res < 1) {
01100 ast_log(LOG_ERROR, "read returned %d\n", res);
01101 break;
01102 }
01103 res = write(con->fd, tmp, res);
01104 if (res < 1)
01105 break;
01106 }
01107 }
01108 if (option_verbose > 2)
01109 ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection disconnected\n");
01110 close(con->fd);
01111 close(con->p[0]);
01112 close(con->p[1]);
01113 con->fd = -1;
01114
01115 return NULL;
01116 }
01117
01118 static void *listener(void *unused)
01119 {
01120 struct sockaddr_un sunaddr;
01121 int s;
01122 socklen_t len;
01123 int x;
01124 int flags;
01125 struct pollfd fds[1];
01126 pthread_attr_t attr;
01127 pthread_attr_init(&attr);
01128 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
01129 for (;;) {
01130 if (ast_socket < 0)
01131 return NULL;
01132 fds[0].fd = ast_socket;
01133 fds[0].events = POLLIN;
01134 s = ast_poll(fds, 1, -1);
01135 pthread_testcancel();
01136 if (s < 0) {
01137 if (errno != EINTR)
01138 ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
01139 continue;
01140 }
01141 len = sizeof(sunaddr);
01142 s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
01143 if (s < 0) {
01144 if (errno != EINTR)
01145 ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
01146 } else {
01147 for (x = 0; x < AST_MAX_CONNECTS; x++) {
01148 if (consoles[x].fd < 0) {
01149 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
01150 ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
01151 consoles[x].fd = -1;
01152 fdprint(s, "Server failed to create pipe\n");
01153 close(s);
01154 break;
01155 }
01156 flags = fcntl(consoles[x].p[1], F_GETFL);
01157 fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
01158 consoles[x].fd = s;
01159 consoles[x].mute = 1;
01160 if (ast_pthread_create_background(&consoles[x].t, &attr, netconsole, &consoles[x])) {
01161 ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
01162 close(consoles[x].p[0]);
01163 close(consoles[x].p[1]);
01164 consoles[x].fd = -1;
01165 fdprint(s, "Server failed to spawn thread\n");
01166 close(s);
01167 }
01168 break;
01169 }
01170 }
01171 if (x >= AST_MAX_CONNECTS) {
01172 fdprint(s, "No more connections allowed\n");
01173 ast_log(LOG_WARNING, "No more connections allowed\n");
01174 close(s);
01175 } else if (consoles[x].fd > -1) {
01176 if (option_verbose > 2)
01177 ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection\n");
01178 }
01179 }
01180 }
01181 return NULL;
01182 }
01183
01184 static int ast_makesocket(void)
01185 {
01186 struct sockaddr_un sunaddr;
01187 int res;
01188 int x;
01189 uid_t uid = -1;
01190 gid_t gid = -1;
01191
01192 for (x = 0; x < AST_MAX_CONNECTS; x++)
01193 consoles[x].fd = -1;
01194 unlink(ast_config_AST_SOCKET);
01195 ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
01196 if (ast_socket < 0) {
01197 ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
01198 return -1;
01199 }
01200 memset(&sunaddr, 0, sizeof(sunaddr));
01201 sunaddr.sun_family = AF_LOCAL;
01202 ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
01203 res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
01204 if (res) {
01205 ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
01206 close(ast_socket);
01207 ast_socket = -1;
01208 return -1;
01209 }
01210 res = listen(ast_socket, 2);
01211 if (res < 0) {
01212 ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
01213 close(ast_socket);
01214 ast_socket = -1;
01215 return -1;
01216 }
01217 ast_register_verbose(network_verboser);
01218 ast_pthread_create_background(<hread, NULL, listener, NULL);
01219
01220 if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {
01221 struct passwd *pw;
01222 if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL) {
01223 ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
01224 } else {
01225 uid = pw->pw_uid;
01226 }
01227 }
01228
01229 if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) {
01230 struct group *grp;
01231 if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL) {
01232 ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
01233 } else {
01234 gid = grp->gr_gid;
01235 }
01236 }
01237
01238 if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
01239 ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
01240
01241 if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) {
01242 int p1;
01243 mode_t p;
01244 sscanf(ast_config_AST_CTL_PERMISSIONS, "%30o", &p1);
01245 p = p1;
01246 if ((chmod(ast_config_AST_SOCKET, p)) < 0)
01247 ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
01248 }
01249
01250 return 0;
01251 }
01252
01253 static int ast_tryconnect(void)
01254 {
01255 struct sockaddr_un sunaddr;
01256 int res;
01257 ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
01258 if (ast_consock < 0) {
01259 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
01260 return 0;
01261 }
01262 memset(&sunaddr, 0, sizeof(sunaddr));
01263 sunaddr.sun_family = AF_LOCAL;
01264 ast_copy_string(sunaddr.sun_path, (char *)ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
01265 res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
01266 if (res) {
01267 close(ast_consock);
01268 ast_consock = -1;
01269 return 0;
01270 } else
01271 return 1;
01272 }
01273
01274
01275
01276
01277
01278
01279
01280 static void _urg_handler(int num)
01281 {
01282 return;
01283 }
01284
01285 static struct sigaction urg_handler = {
01286 .sa_handler = _urg_handler,
01287 .sa_flags = SA_RESTART,
01288 };
01289
01290 static void _hup_handler(int num)
01291 {
01292 int a = 0;
01293 if (option_verbose > 1)
01294 printf("Received HUP signal -- Reloading configs\n");
01295 if (restartnow)
01296 execvp(_argv[0], _argv);
01297 sig_flags.need_reload = 1;
01298 if (sig_alert_pipe[1] != -1) {
01299 if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
01300 fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
01301 }
01302 }
01303 }
01304
01305 static struct sigaction hup_handler = {
01306 .sa_handler = _hup_handler,
01307 .sa_flags = SA_RESTART,
01308 };
01309
01310 static void _child_handler(int sig)
01311 {
01312
01313 int n, status;
01314
01315
01316
01317
01318 for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++)
01319 ;
01320 if (n == 0 && option_debug)
01321 printf("Huh? Child handler, but nobody there?\n");
01322 }
01323
01324 static struct sigaction child_handler = {
01325 .sa_handler = _child_handler,
01326 .sa_flags = SA_RESTART,
01327 };
01328
01329
01330 static void set_ulimit(int value)
01331 {
01332 struct rlimit l = {0, 0};
01333
01334 if (value <= 0) {
01335 ast_log(LOG_WARNING, "Unable to change max files open to invalid value %i\n",value);
01336 return;
01337 }
01338
01339 l.rlim_cur = value;
01340 l.rlim_max = value;
01341
01342 if (setrlimit(RLIMIT_NOFILE, &l)) {
01343 ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n",strerror(errno));
01344 return;
01345 }
01346 ast_log(LOG_NOTICE, "Setting max files open to %d\n",value);
01347 return;
01348 }
01349
01350
01351 static void set_title(char *text)
01352 {
01353 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
01354 fprintf(stdout, "\033]2;%s\007", text);
01355 }
01356
01357 static void set_icon(char *text)
01358 {
01359 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
01360 fprintf(stdout, "\033]1;%s\007", text);
01361 }
01362
01363
01364
01365 int ast_set_priority(int pri)
01366 {
01367 struct sched_param sched;
01368 memset(&sched, 0, sizeof(sched));
01369 #ifdef __linux__
01370 if (pri) {
01371 sched.sched_priority = 10;
01372 if (sched_setscheduler(0, SCHED_RR, &sched)) {
01373 ast_log(LOG_WARNING, "Unable to set high priority\n");
01374 return -1;
01375 } else
01376 if (option_verbose)
01377 ast_verbose("Set to realtime thread\n");
01378 } else {
01379 sched.sched_priority = 0;
01380
01381 sched_setscheduler(0, SCHED_OTHER, &sched);
01382 }
01383 #else
01384 if (pri) {
01385 if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
01386 ast_log(LOG_WARNING, "Unable to set high priority\n");
01387 return -1;
01388 } else
01389 if (option_verbose)
01390 ast_verbose("Set to high priority\n");
01391 } else {
01392
01393 setpriority(PRIO_PROCESS, 0, 0);
01394 }
01395 #endif
01396 return 0;
01397 }
01398
01399 static void ast_run_atexits(void)
01400 {
01401 struct ast_atexit *ae;
01402 AST_LIST_LOCK(&atexits);
01403 AST_LIST_TRAVERSE(&atexits, ae, list) {
01404 if (ae->func)
01405 ae->func();
01406 }
01407 AST_LIST_UNLOCK(&atexits);
01408 }
01409
01410 static void quit_handler(int num, int nice, int safeshutdown, int restart)
01411 {
01412 char filename[80] = "";
01413 time_t s,e;
01414 int x;
01415
01416 ast_cdr_engine_term();
01417 if (safeshutdown) {
01418 shuttingdown = 1;
01419 if (!nice) {
01420
01421 ast_begin_shutdown(1);
01422 if (option_verbose && ast_opt_console)
01423 ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
01424 time(&s);
01425 for (;;) {
01426 time(&e);
01427
01428 if ((e - s) > 15)
01429 break;
01430 if (!ast_active_channels())
01431 break;
01432 if (!shuttingdown)
01433 break;
01434
01435 usleep(100000);
01436 }
01437 } else {
01438 if (nice < 2)
01439 ast_begin_shutdown(0);
01440 if (option_verbose && ast_opt_console)
01441 ast_verbose("Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
01442 for (;;) {
01443 if (!ast_active_channels())
01444 break;
01445 if (!shuttingdown)
01446 break;
01447 sleep(1);
01448 }
01449 }
01450
01451 if (!shuttingdown) {
01452 if (option_verbose && ast_opt_console)
01453 ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
01454 return;
01455 }
01456
01457 if (nice)
01458 ast_module_shutdown();
01459 }
01460 if (ast_opt_console || ast_opt_remote) {
01461 pthread_t thisthread = pthread_self();
01462 if (getenv("HOME")) {
01463 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
01464 }
01465 if (!ast_strlen_zero(filename)) {
01466 ast_el_write_history(filename);
01467 }
01468 if (consolethread == AST_PTHREADT_NULL || consolethread == thisthread || mon_sig_flags == thisthread) {
01469
01470 if (el != NULL) {
01471 el_end(el);
01472 }
01473 if (el_hist != NULL) {
01474 history_end(el_hist);
01475 }
01476 }
01477 }
01478 if (option_verbose)
01479 ast_verbose("Executing last minute cleanups\n");
01480 ast_run_atexits();
01481
01482 if (option_verbose && ast_opt_console)
01483 ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);
01484 if (option_debug)
01485 ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num);
01486 manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\nRestart: %s\r\n", ast_active_channels() ? "Uncleanly" : "Cleanly", restart ? "True" : "False");
01487 if (ast_socket > -1) {
01488 pthread_cancel(lthread);
01489 close(ast_socket);
01490 ast_socket = -1;
01491 unlink(ast_config_AST_SOCKET);
01492 }
01493 if (ast_consock > -1)
01494 close(ast_consock);
01495 if (!ast_opt_remote)
01496 unlink(ast_config_AST_PID);
01497 printf("%s", term_quit());
01498 if (restart) {
01499 if (option_verbose || ast_opt_console)
01500 ast_verbose("Preparing for Asterisk restart...\n");
01501
01502 for (x=3; x < 32768; x++) {
01503 fcntl(x, F_SETFD, FD_CLOEXEC);
01504 }
01505 if (option_verbose || ast_opt_console)
01506 ast_verbose("Asterisk is now restarting...\n");
01507 restartnow = 1;
01508
01509
01510 close_logger();
01511
01512
01513
01514 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
01515 pthread_kill(consolethread, SIGHUP);
01516
01517 sleep(2);
01518 } else
01519 execvp(_argv[0], _argv);
01520
01521 } else {
01522
01523 close_logger();
01524 }
01525 exit(0);
01526 }
01527
01528 static void __quit_handler(int num)
01529 {
01530 int a = 0;
01531 sig_flags.need_quit = 1;
01532 if (sig_alert_pipe[1] != -1) {
01533 if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
01534 fprintf(stderr, "quit_handler: write() failed: %s\n", strerror(errno));
01535 }
01536 }
01537
01538
01539 }
01540
01541 static void __remote_quit_handler(int num)
01542 {
01543 sig_flags.need_quit = 1;
01544 }
01545
01546 static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp)
01547 {
01548 const char *c;
01549
01550
01551 if (*s == 127) {
01552 s++;
01553 }
01554
01555 if (!strncmp(s, cmp, strlen(cmp))) {
01556 c = s + strlen(cmp);
01557 term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
01558 return c;
01559 }
01560 return NULL;
01561 }
01562
01563 static void console_verboser(const char *s)
01564 {
01565 char tmp[80];
01566 const char *c = NULL;
01567
01568 if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
01569 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
01570 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
01571 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_1))) {
01572 fputs(tmp, stdout);
01573 fputs(c, stdout);
01574 } else {
01575 if (*s == 127) {
01576 s++;
01577 }
01578 fputs(s, stdout);
01579 }
01580
01581 fflush(stdout);
01582
01583
01584 if (ast_opt_console && consolethread != AST_PTHREADT_NULL)
01585 pthread_kill(consolethread, SIGURG);
01586 }
01587
01588 static int ast_all_zeros(char *s)
01589 {
01590 while (*s) {
01591 if (*s > 32)
01592 return 0;
01593 s++;
01594 }
01595 return 1;
01596 }
01597
01598 static void consolehandler(char *s)
01599 {
01600 printf("%s", term_end());
01601 fflush(stdout);
01602
01603
01604 if (!ast_all_zeros(s))
01605 ast_el_add_history(s);
01606
01607 if (s[0] == '!') {
01608 if (s[1])
01609 ast_safe_system(s+1);
01610 else
01611 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
01612 } else
01613 ast_cli_command(STDOUT_FILENO, s);
01614 }
01615
01616 static int remoteconsolehandler(char *s)
01617 {
01618 int ret = 0;
01619
01620
01621 if (!ast_all_zeros(s))
01622 ast_el_add_history(s);
01623
01624 if (s[0] == '!') {
01625 if (s[1])
01626 ast_safe_system(s+1);
01627 else
01628 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
01629 ret = 1;
01630 }
01631 if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
01632 (s[4] == '\0' || isspace(s[4]))) {
01633 quit_handler(0, 0, 0, 0);
01634 ret = 1;
01635 }
01636
01637 return ret;
01638 }
01639
01640 static char abort_halt_help[] =
01641 "Usage: abort shutdown\n"
01642 " Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
01643 " call operations.\n";
01644
01645 static char shutdown_now_help[] =
01646 "Usage: stop now\n"
01647 " Shuts down a running Asterisk immediately, hanging up all active calls .\n";
01648
01649 static char shutdown_gracefully_help[] =
01650 "Usage: stop gracefully\n"
01651 " Causes Asterisk to not accept new calls, and exit when all\n"
01652 " active calls have terminated normally.\n";
01653
01654 static char shutdown_when_convenient_help[] =
01655 "Usage: stop when convenient\n"
01656 " Causes Asterisk to perform a shutdown when all active calls have ended.\n";
01657
01658 static char restart_now_help[] =
01659 "Usage: restart now\n"
01660 " Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
01661 " restart.\n";
01662
01663 static char restart_gracefully_help[] =
01664 "Usage: restart gracefully\n"
01665 " Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
01666 " restart when all active calls have ended.\n";
01667
01668 static char restart_when_convenient_help[] =
01669 "Usage: restart when convenient\n"
01670 " Causes Asterisk to perform a cold restart when all active calls have ended.\n";
01671
01672 static char bang_help[] =
01673 "Usage: !<command>\n"
01674 " Executes a given shell command\n";
01675
01676 static char show_warranty_help[] =
01677 "Usage: core show warranty\n"
01678 " Shows the warranty (if any) for this copy of Asterisk.\n";
01679
01680 static char show_license_help[] =
01681 "Usage: core show license\n"
01682 " Shows the license(s) for this copy of Asterisk.\n";
01683
01684 static char version_help[] =
01685 "Usage: core show version\n"
01686 " Shows Asterisk version information.\n";
01687
01688 static int handle_version_deprecated(int fd, int argc, char *argv[])
01689 {
01690 if (argc != 2)
01691 return RESULT_SHOWUSAGE;
01692 ast_cli(fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
01693 ASTERISK_VERSION, ast_build_user, ast_build_hostname,
01694 ast_build_machine, ast_build_os, ast_build_date);
01695 return RESULT_SUCCESS;
01696 }
01697
01698 static int handle_version(int fd, int argc, char *argv[])
01699 {
01700 if (argc != 3)
01701 return RESULT_SHOWUSAGE;
01702 ast_cli(fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
01703 ASTERISK_VERSION, ast_build_user, ast_build_hostname,
01704 ast_build_machine, ast_build_os, ast_build_date);
01705 return RESULT_SUCCESS;
01706 }
01707
01708 #if 0
01709 static int handle_quit(int fd, int argc, char *argv[])
01710 {
01711 if (argc != 1)
01712 return RESULT_SHOWUSAGE;
01713 quit_handler(0, 0, 1, 0);
01714 return RESULT_SUCCESS;
01715 }
01716 #endif
01717
01718 static int handle_shutdown_now(int fd, int argc, char *argv[])
01719 {
01720 if (argc != 2)
01721 return RESULT_SHOWUSAGE;
01722 quit_handler(0, 0 , 1 , 0 );
01723 return RESULT_SUCCESS;
01724 }
01725
01726 static int handle_shutdown_gracefully(int fd, int argc, char *argv[])
01727 {
01728 if (argc != 2)
01729 return RESULT_SHOWUSAGE;
01730 quit_handler(0, 1 , 1 , 0 );
01731 return RESULT_SUCCESS;
01732 }
01733
01734 static int handle_shutdown_when_convenient(int fd, int argc, char *argv[])
01735 {
01736 if (argc != 3)
01737 return RESULT_SHOWUSAGE;
01738 ast_cli(fd, "Waiting for inactivity to perform halt\n");
01739 quit_handler(0, 2 , 1 , 0 );
01740 return RESULT_SUCCESS;
01741 }
01742
01743 static int handle_restart_now(int fd, int argc, char *argv[])
01744 {
01745 if (argc != 2)
01746 return RESULT_SHOWUSAGE;
01747 quit_handler(0, 0 , 1 , 1 );
01748 return RESULT_SUCCESS;
01749 }
01750
01751 static int handle_restart_gracefully(int fd, int argc, char *argv[])
01752 {
01753 if (argc != 2)
01754 return RESULT_SHOWUSAGE;
01755 quit_handler(0, 1 , 1 , 1 );
01756 return RESULT_SUCCESS;
01757 }
01758
01759 static int handle_restart_when_convenient(int fd, int argc, char *argv[])
01760 {
01761 if (argc != 3)
01762 return RESULT_SHOWUSAGE;
01763 ast_cli(fd, "Waiting for inactivity to perform restart\n");
01764 quit_handler(0, 2 , 1 , 1 );
01765 return RESULT_SUCCESS;
01766 }
01767
01768 static int handle_abort_halt(int fd, int argc, char *argv[])
01769 {
01770 if (argc != 2)
01771 return RESULT_SHOWUSAGE;
01772 ast_cancel_shutdown();
01773 shuttingdown = 0;
01774 return RESULT_SUCCESS;
01775 }
01776
01777 static int handle_bang(int fd, int argc, char *argv[])
01778 {
01779 return RESULT_SUCCESS;
01780 }
01781 static const char *warranty_lines[] = {
01782 "\n",
01783 " NO WARRANTY\n",
01784 "\n",
01785 "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n",
01786 "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n",
01787 "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n",
01788 "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n",
01789 "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n",
01790 "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n",
01791 "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n",
01792 "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n",
01793 "REPAIR OR CORRECTION.\n",
01794 "\n",
01795 "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n",
01796 "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n",
01797 "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n",
01798 "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n",
01799 "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n",
01800 "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n",
01801 "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n",
01802 "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n",
01803 "POSSIBILITY OF SUCH DAMAGES.\n",
01804 };
01805
01806 static int show_warranty(int fd, int argc, char *argv[])
01807 {
01808 int x;
01809
01810 for (x = 0; x < ARRAY_LEN(warranty_lines); x++)
01811 ast_cli(fd, "%s", (char *) warranty_lines[x]);
01812
01813 return RESULT_SUCCESS;
01814 }
01815
01816 static const char *license_lines[] = {
01817 "\n",
01818 "This program is free software; you can redistribute it and/or modify\n",
01819 "it under the terms of the GNU General Public License version 2 as\n",
01820 "published by the Free Software Foundation.\n",
01821 "\n",
01822 "This program also contains components licensed under other licenses.\n",
01823 "They include:\n",
01824 "\n",
01825 "This program is distributed in the hope that it will be useful,\n",
01826 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n",
01827 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n",
01828 "GNU General Public License for more details.\n",
01829 "\n",
01830 "You should have received a copy of the GNU General Public License\n",
01831 "along with this program; if not, write to the Free Software\n",
01832 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n",
01833 };
01834
01835 static int show_license(int fd, int argc, char *argv[])
01836 {
01837 int x;
01838
01839 for (x = 0; x < ARRAY_LEN(license_lines); x++)
01840 ast_cli(fd, "%s", (char *) license_lines[x]);
01841
01842 return RESULT_SUCCESS;
01843 }
01844
01845 #define ASTERISK_PROMPT "*CLI> "
01846
01847 #define ASTERISK_PROMPT2 "%s*CLI> "
01848
01849 static struct ast_cli_entry cli_show_version_deprecated = {
01850 { "show", "version", NULL },
01851 handle_version_deprecated, "Display version info",
01852 version_help };
01853
01854 #if !defined(LOW_MEMORY)
01855 static struct ast_cli_entry cli_show_version_files_deprecated = {
01856 { "show", "version", "files", NULL },
01857 handle_show_version_files_deprecated, NULL,
01858 NULL, complete_show_version_files_deprecated };
01859
01860 static struct ast_cli_entry cli_show_profile_deprecated = {
01861 { "show", "profile", NULL },
01862 handle_show_profile_deprecated, NULL,
01863 NULL };
01864
01865 static struct ast_cli_entry cli_clear_profile_deprecated = {
01866 { "clear", "profile", NULL },
01867 handle_show_profile_deprecated, NULL,
01868 NULL };
01869 #endif
01870
01871 static struct ast_cli_entry cli_asterisk[] = {
01872 { { "abort", "halt", NULL },
01873 handle_abort_halt, "Cancel a running halt",
01874 abort_halt_help },
01875
01876 { { "stop", "now", NULL },
01877 handle_shutdown_now, "Shut down Asterisk immediately",
01878 shutdown_now_help },
01879
01880 { { "stop", "gracefully", NULL },
01881 handle_shutdown_gracefully, "Gracefully shut down Asterisk",
01882 shutdown_gracefully_help },
01883
01884 { { "stop", "when", "convenient", NULL },
01885 handle_shutdown_when_convenient, "Shut down Asterisk at empty call volume",
01886 shutdown_when_convenient_help },
01887
01888 { { "restart", "now", NULL },
01889 handle_restart_now, "Restart Asterisk immediately",
01890 restart_now_help },
01891
01892 { { "restart", "gracefully", NULL },
01893 handle_restart_gracefully, "Restart Asterisk gracefully",
01894 restart_gracefully_help },
01895
01896 { { "restart", "when", "convenient", NULL },
01897 handle_restart_when_convenient, "Restart Asterisk at empty call volume",
01898 restart_when_convenient_help },
01899
01900 { { "core", "show", "warranty", NULL },
01901 show_warranty, "Show the warranty (if any) for this copy of Asterisk",
01902 show_warranty_help },
01903
01904 { { "core", "show", "license", NULL },
01905 show_license, "Show the license(s) for this copy of Asterisk",
01906 show_license_help },
01907
01908 { { "core", "show", "version", NULL },
01909 handle_version, "Display version info",
01910 version_help, NULL, &cli_show_version_deprecated },
01911
01912 { { "!", NULL },
01913 handle_bang, "Execute a shell command",
01914 bang_help },
01915
01916 #if !defined(LOW_MEMORY)
01917 { { "core", "show", "file", "version", NULL },
01918 handle_show_version_files, "List versions of files used to build Asterisk",
01919 show_version_files_help, complete_show_version_files, &cli_show_version_files_deprecated },
01920
01921 { { "core", "show", "settings", NULL },
01922 handle_show_settings, "Show some core settings",
01923 show_settings_help },
01924
01925 { { "core", "show", "threads", NULL },
01926 handle_show_threads, "Show running threads",
01927 show_threads_help },
01928
01929 { { "core", "show", "sysinfo", NULL },
01930 handle_show_sysinfo, "Show System Information",
01931 show_sysinfo_help },
01932
01933 { { "core", "show", "profile", NULL },
01934 handle_show_profile, "Display profiling info",
01935 NULL, NULL, &cli_show_profile_deprecated },
01936
01937 { { "core", "clear", "profile", NULL },
01938 handle_show_profile, "Clear profiling info",
01939 NULL, NULL, &cli_clear_profile_deprecated },
01940 #endif
01941 };
01942
01943 static int ast_el_read_char(EditLine *el, char *cp)
01944 {
01945 int num_read = 0;
01946 int lastpos = 0;
01947 struct pollfd fds[2];
01948 int res;
01949 int max;
01950 #define EL_BUF_SIZE 512
01951 char buf[EL_BUF_SIZE];
01952
01953 for (;;) {
01954 max = 1;
01955 fds[0].fd = ast_consock;
01956 fds[0].events = POLLIN;
01957 if (!ast_opt_exec) {
01958 fds[1].fd = STDIN_FILENO;
01959 fds[1].events = POLLIN;
01960 max++;
01961 }
01962 res = ast_poll(fds, max, -1);
01963 if (res < 0) {
01964 if (sig_flags.need_quit)
01965 break;
01966 if (errno == EINTR)
01967 continue;
01968 ast_log(LOG_ERROR, "poll failed: %s\n", strerror(errno));
01969 break;
01970 }
01971
01972 if (!ast_opt_exec && fds[1].revents) {
01973 num_read = read(STDIN_FILENO, cp, 1);
01974 if (num_read < 1) {
01975 break;
01976 } else
01977 return (num_read);
01978 }
01979 if (fds[0].revents) {
01980 char *tmp;
01981 res = read(ast_consock, buf, sizeof(buf) - 1);
01982
01983 if (res < 1) {
01984 fprintf(stderr, "\nDisconnected from Asterisk server\n");
01985 if (!ast_opt_reconnect) {
01986 quit_handler(0, 0, 0, 0);
01987 } else {
01988 int tries;
01989 int reconnects_per_second = 20;
01990 fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
01991 for (tries=0; tries < 30 * reconnects_per_second; tries++) {
01992 if (ast_tryconnect()) {
01993 fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
01994 printf("%s", term_quit());
01995 WELCOME_MESSAGE;
01996 if (!ast_opt_mute)
01997 fdsend(ast_consock, "logger mute silent");
01998 else {
01999 snprintf(tmp, sizeof(tmp), "log and verbose output currently muted ('logger unmute' to unmute)");
02000 fdprint(ast_consock, tmp);
02001 }
02002
02003 break;
02004 } else {
02005 usleep(1000000 / reconnects_per_second);
02006 }
02007 }
02008 if (tries >= 30 * reconnects_per_second) {
02009 fprintf(stderr, "Failed to reconnect for 30 seconds. Quitting.\n");
02010 quit_handler(0, 0, 0, 0);
02011 }
02012 }
02013 }
02014
02015 buf[res] = '\0';
02016
02017
02018 for (tmp = buf; *tmp; tmp++) {
02019 if (*tmp == 127) {
02020 memmove(tmp, tmp + 1, strlen(tmp));
02021 tmp--;
02022 res--;
02023 }
02024 }
02025
02026
02027 if (!ast_opt_exec && !lastpos) {
02028 if (write(STDOUT_FILENO, "\r[0K", 5) < 0) {
02029 }
02030 }
02031 if (write(STDOUT_FILENO, buf, res) < 0) {
02032 }
02033 if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (buf[res-2] == '\n'))) {
02034 *cp = CC_REFRESH;
02035 return(1);
02036 } else {
02037 lastpos = 1;
02038 }
02039 }
02040 }
02041
02042 *cp = '\0';
02043 return (0);
02044 }
02045
02046 static char *cli_prompt(EditLine *el)
02047 {
02048 static char prompt[200];
02049 char *pfmt;
02050 int color_used = 0;
02051 char term_code[20];
02052
02053 if ((pfmt = getenv("ASTERISK_PROMPT"))) {
02054 char *t = pfmt, *p = prompt;
02055 memset(prompt, 0, sizeof(prompt));
02056 while (*t != '\0' && *p < sizeof(prompt)) {
02057 if (*t == '%') {
02058 char hostname[MAXHOSTNAMELEN]="";
02059 int i;
02060 time_t ts;
02061 struct tm tm;
02062 #ifdef linux
02063 FILE *LOADAVG;
02064 #endif
02065 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
02066
02067 t++;
02068 switch (*t) {
02069 case 'C':
02070 t++;
02071 if (sscanf(t, "%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
02072 strncat(p, term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
02073 t += i - 1;
02074 } else if (sscanf(t, "%30d%n", &fgcolor, &i) == 1) {
02075 strncat(p, term_color_code(term_code, fgcolor, 0, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
02076 t += i - 1;
02077 }
02078
02079
02080 if ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) {
02081 color_used = 0;
02082 } else {
02083 color_used = 1;
02084 }
02085 break;
02086 case 'd':
02087 memset(&tm, 0, sizeof(tm));
02088 time(&ts);
02089 if (ast_localtime(&ts, &tm, NULL)) {
02090 strftime(p, sizeof(prompt) - strlen(prompt), "%Y-%m-%d", &tm);
02091 }
02092 break;
02093 case 'h':
02094 if (!gethostname(hostname, sizeof(hostname) - 1)) {
02095 strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
02096 } else {
02097 strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
02098 }
02099 break;
02100 case 'H':
02101 if (!gethostname(hostname, sizeof(hostname) - 1)) {
02102 for (i = 0; i < sizeof(hostname); i++) {
02103 if (hostname[i] == '.') {
02104 hostname[i] = '\0';
02105 break;
02106 }
02107 }
02108 strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
02109 } else {
02110 strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
02111 }
02112 break;
02113 #ifdef linux
02114 case 'l':
02115 t++;
02116 if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
02117 float avg1, avg2, avg3;
02118 int actproc, totproc, npid, which;
02119
02120 if (fscanf(LOADAVG, "%30f %30f %30f %30d/%30d %30d",
02121 &avg1, &avg2, &avg3, &actproc, &totproc, &npid) != 6) {
02122 ast_log(LOG_WARNING, "parsing /proc/loadavg failed\n");
02123 fclose(LOADAVG);
02124 break;
02125 }
02126 if (sscanf(t, "%30d", &which) == 1) {
02127 switch (which) {
02128 case 1:
02129 snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg1);
02130 break;
02131 case 2:
02132 snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg2);
02133 break;
02134 case 3:
02135 snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg3);
02136 break;
02137 case 4:
02138 snprintf(p, sizeof(prompt) - strlen(prompt), "%d/%d", actproc, totproc);
02139 break;
02140 case 5:
02141 snprintf(p, sizeof(prompt) - strlen(prompt), "%d", npid);
02142 break;
02143 }
02144 }
02145 fclose(LOADAVG);
02146 }
02147 break;
02148 #endif
02149 case 's':
02150 strncat(p, ast_config_AST_SYSTEM_NAME, sizeof(prompt) - strlen(prompt) - 1);
02151 break;
02152 case 't':
02153 memset(&tm, 0, sizeof(tm));
02154 time(&ts);
02155 if (ast_localtime(&ts, &tm, NULL)) {
02156 strftime(p, sizeof(prompt) - strlen(prompt), "%H:%M:%S", &tm);
02157 }
02158 break;
02159 case '#':
02160 if (!ast_opt_remote) {
02161 strncat(p, "#", sizeof(prompt) - strlen(prompt) - 1);
02162 } else {
02163 strncat(p, ">", sizeof(prompt) - strlen(prompt) - 1);
02164 }
02165 break;
02166 case '%':
02167 strncat(p, "%", sizeof(prompt) - strlen(prompt) - 1);
02168 break;
02169 case '\0':
02170 t--;
02171 break;
02172 }
02173 while (*p != '\0') {
02174 p++;
02175 }
02176 t++;
02177 } else {
02178 *p = *t;
02179 p++;
02180 t++;
02181 }
02182 }
02183 if (color_used) {
02184
02185 term_color_code(term_code, COLOR_WHITE, COLOR_BLACK, sizeof(term_code));
02186 if (strlen(term_code) > sizeof(prompt) - strlen(prompt) - 1) {
02187 ast_copy_string(prompt + sizeof(prompt) - strlen(term_code) - 1, term_code, strlen(term_code) + 1);
02188 } else {
02189
02190 strncat(p, term_code, sizeof(term_code));
02191 }
02192 }
02193 } else if (remotehostname)
02194 snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT2, remotehostname);
02195 else
02196 ast_copy_string(prompt, ASTERISK_PROMPT, sizeof(prompt));
02197
02198 return(prompt);
02199 }
02200
02201 static char **ast_el_strtoarr(char *buf)
02202 {
02203 char **match_list = NULL, *retstr;
02204 size_t match_list_len;
02205 int matches = 0;
02206
02207 match_list_len = 1;
02208 while ( (retstr = strsep(&buf, " ")) != NULL) {
02209
02210 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
02211 break;
02212 if (matches + 1 >= match_list_len) {
02213 match_list_len <<= 1;
02214 if (!(match_list = ast_realloc(match_list, match_list_len * sizeof(char *)))) {
02215
02216 }
02217 }
02218
02219 match_list[matches++] = ast_strdup(retstr);
02220 }
02221
02222 if (!match_list)
02223 return (char **) NULL;
02224
02225 if (matches >= match_list_len) {
02226 if (!(match_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *)))) {
02227
02228 }
02229 }
02230
02231 match_list[matches] = (char *) NULL;
02232
02233 return match_list;
02234 }
02235
02236 static int ast_el_sort_compare(const void *i1, const void *i2)
02237 {
02238 char *s1, *s2;
02239
02240 s1 = ((char **)i1)[0];
02241 s2 = ((char **)i2)[0];
02242
02243 return strcasecmp(s1, s2);
02244 }
02245
02246 static int ast_cli_display_match_list(char **matches, int len, int max)
02247 {
02248 int i, idx, limit, count;
02249 int screenwidth = 0;
02250 int numoutput = 0, numoutputline = 0;
02251
02252 screenwidth = ast_get_termcols(STDOUT_FILENO);
02253
02254
02255 limit = screenwidth / (max + 2);
02256 if (limit == 0)
02257 limit = 1;
02258
02259
02260 count = len / limit;
02261 if (count * limit < len)
02262 count++;
02263
02264 idx = 1;
02265
02266 qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);
02267
02268 for (; count > 0; count--) {
02269 numoutputline = 0;
02270 for (i=0; i < limit && matches[idx]; i++, idx++) {
02271
02272
02273 if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
02274 i--;
02275 ast_free(matches[idx]);
02276 matches[idx] = NULL;
02277 continue;
02278 }
02279
02280 numoutput++;
02281 numoutputline++;
02282 fprintf(stdout, "%-*s ", max, matches[idx]);
02283 ast_free(matches[idx]);
02284 matches[idx] = NULL;
02285 }
02286 if (numoutputline > 0)
02287 fprintf(stdout, "\n");
02288 }
02289
02290 return numoutput;
02291 }
02292
02293
02294 static char *cli_complete(EditLine *el, int ch)
02295 {
02296 int len = 0;
02297 char *ptr;
02298 int nummatches = 0;
02299 char **matches;
02300 int retval = CC_ERROR;
02301 char buf[2048], savechr;
02302 int res;
02303
02304 LineInfo *lf = (LineInfo *)el_line(el);
02305
02306 savechr = *(char *)lf->cursor;
02307 *(char *)lf->cursor = '\0';
02308 ptr = (char *)lf->cursor;
02309 if (ptr) {
02310 while (ptr > lf->buffer) {
02311 if (isspace(*ptr)) {
02312 ptr++;
02313 break;
02314 }
02315 ptr--;
02316 }
02317 }
02318
02319 len = lf->cursor - ptr;
02320
02321 if (ast_opt_remote) {
02322 snprintf(buf, sizeof(buf),"_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
02323 fdsend(ast_consock, buf);
02324 res = read(ast_consock, buf, sizeof(buf) - 1);
02325 buf[res] = '\0';
02326 nummatches = atoi(buf);
02327
02328 if (nummatches > 0) {
02329 char *mbuf;
02330 int mlen = 0, maxmbuf = 2048;
02331
02332 if (!(mbuf = ast_malloc(maxmbuf))) {
02333 lf->cursor[0] = savechr;
02334 return (char *)(CC_ERROR);
02335 }
02336 snprintf(buf, sizeof(buf),"_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
02337 fdsend(ast_consock, buf);
02338 res = 0;
02339 mbuf[0] = '\0';
02340 while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
02341 if (mlen + 1024 > maxmbuf) {
02342
02343 maxmbuf += 1024;
02344 if (!(mbuf = ast_realloc(mbuf, maxmbuf))) {
02345 lf->cursor[0] = savechr;
02346 return (char *)(CC_ERROR);
02347 }
02348 }
02349
02350 res = read(ast_consock, mbuf + mlen, 1024);
02351 if (res > 0)
02352 mlen += res;
02353 }
02354 mbuf[mlen] = '\0';
02355
02356 matches = ast_el_strtoarr(mbuf);
02357 ast_free(mbuf);
02358 } else
02359 matches = (char **) NULL;
02360 } else {
02361 char **p, *oldbuf=NULL;
02362 nummatches = 0;
02363 matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
02364 for (p = matches; p && *p; p++) {
02365 if (!oldbuf || strcmp(*p,oldbuf))
02366 nummatches++;
02367 oldbuf = *p;
02368 }
02369 }
02370
02371 if (matches) {
02372 int i;
02373 int matches_num, maxlen, match_len;
02374
02375 if (matches[0][0] != '\0') {
02376 el_deletestr(el, (int) len);
02377 el_insertstr(el, matches[0]);
02378 retval = CC_REFRESH;
02379 }
02380
02381 if (nummatches == 1) {
02382
02383 el_insertstr(el, " ");
02384 retval = CC_REFRESH;
02385 } else {
02386
02387 for (i=1, maxlen=0; matches[i]; i++) {
02388 match_len = strlen(matches[i]);
02389 if (match_len > maxlen)
02390 maxlen = match_len;
02391 }
02392 matches_num = i - 1;
02393 if (matches_num >1) {
02394 fprintf(stdout, "\n");
02395 ast_cli_display_match_list(matches, nummatches, maxlen);
02396 retval = CC_REDISPLAY;
02397 } else {
02398 el_insertstr(el," ");
02399 retval = CC_REFRESH;
02400 }
02401 }
02402 for (i = 0; matches[i]; i++)
02403 ast_free(matches[i]);
02404 ast_free(matches);
02405 }
02406
02407 lf->cursor[0] = savechr;
02408
02409 return (char *)(long)retval;
02410 }
02411
02412 static int ast_el_initialize(void)
02413 {
02414 HistEvent ev;
02415 char *editor = getenv("AST_EDITOR");
02416
02417 if (el != NULL)
02418 el_end(el);
02419 if (el_hist != NULL)
02420 history_end(el_hist);
02421
02422 el = el_init("asterisk", stdin, stdout, stderr);
02423 el_set(el, EL_PROMPT, cli_prompt);
02424
02425 el_set(el, EL_EDITMODE, 1);
02426 el_set(el, EL_EDITOR, editor ? editor : "emacs");
02427 el_hist = history_init();
02428 if (!el || !el_hist)
02429 return -1;
02430
02431
02432 history(el_hist, &ev, H_SETSIZE, 100);
02433
02434 el_set(el, EL_HIST, history, el_hist);
02435
02436 el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
02437
02438 el_set(el, EL_BIND, "^I", "ed-complete", NULL);
02439
02440 el_set(el, EL_BIND, "?", "ed-complete", NULL);
02441
02442 el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
02443
02444 return 0;
02445 }
02446
02447 static int ast_el_add_history(char *buf)
02448 {
02449 HistEvent ev;
02450
02451 if (el_hist == NULL || el == NULL)
02452 ast_el_initialize();
02453 if (strlen(buf) > 256)
02454 return 0;
02455 return (history(el_hist, &ev, H_ENTER, buf));
02456 }
02457
02458 static int ast_el_write_history(char *filename)
02459 {
02460 HistEvent ev;
02461
02462 if (el_hist == NULL || el == NULL)
02463 ast_el_initialize();
02464
02465 return (history(el_hist, &ev, H_SAVE, filename));
02466 }
02467
02468 static int ast_el_read_history(char *filename)
02469 {
02470 char buf[256];
02471 FILE *f;
02472 int ret = -1;
02473
02474 if (el_hist == NULL || el == NULL)
02475 ast_el_initialize();
02476
02477 if ((f = fopen(filename, "r")) == NULL)
02478 return ret;
02479
02480 while (!feof(f)) {
02481 if (!fgets(buf, sizeof(buf), f)) {
02482 continue;
02483 }
02484 if (!strcmp(buf, "_HiStOrY_V2_\n"))
02485 continue;
02486 if (ast_all_zeros(buf))
02487 continue;
02488 if ((ret = ast_el_add_history(buf)) == -1)
02489 break;
02490 }
02491 fclose(f);
02492
02493 return ret;
02494 }
02495
02496 static void ast_remotecontrol(char *data)
02497 {
02498 char buf[80];
02499 int res;
02500 char filename[80] = "";
02501 char *hostname;
02502 char *cpid;
02503 char *version;
02504 int pid;
02505 char tmp[80];
02506 char *stringp = NULL;
02507
02508 char *ebuf;
02509 int num = 0;
02510
02511 memset(&sig_flags, 0, sizeof(sig_flags));
02512 signal(SIGINT, __remote_quit_handler);
02513 signal(SIGTERM, __remote_quit_handler);
02514 signal(SIGHUP, __remote_quit_handler);
02515
02516 if (read(ast_consock, buf, sizeof(buf)) < 0) {
02517 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
02518 return;
02519 }
02520 if (data) {
02521 if (write(ast_consock, data, strlen(data) + 1) < 0) {
02522 ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
02523 if (sig_flags.need_quit == 1) {
02524 return;
02525 }
02526 }
02527 }
02528 stringp = buf;
02529 hostname = strsep(&stringp, "/");
02530 cpid = strsep(&stringp, "/");
02531 version = strsep(&stringp, "\n");
02532 if (!version)
02533 version = "<Version Unknown>";
02534 stringp = hostname;
02535 strsep(&stringp, ".");
02536 if (cpid)
02537 pid = atoi(cpid);
02538 else
02539 pid = -1;
02540 if (!data) {
02541 snprintf(tmp, sizeof(tmp), "core set verbose atleast %d", option_verbose);
02542 fdsend(ast_consock, tmp);
02543 snprintf(tmp, sizeof(tmp), "core set debug atleast %d", option_debug);
02544 fdsend(ast_consock, tmp);
02545 if (!ast_opt_mute)
02546 fdsend(ast_consock, "logger mute silent");
02547 else
02548 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
02549 }
02550 ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
02551 remotehostname = hostname;
02552 if (getenv("HOME"))
02553 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
02554 if (el_hist == NULL || el == NULL)
02555 ast_el_initialize();
02556
02557 el_set(el, EL_GETCFN, ast_el_read_char);
02558
02559 if (!ast_strlen_zero(filename))
02560 ast_el_read_history(filename);
02561
02562 if (ast_opt_exec && data) {
02563 struct pollfd fds;
02564 fds.fd = ast_consock;
02565 fds.events = POLLIN;
02566 fds.revents = 0;
02567 while (ast_poll(&fds, 1, 500) > 0) {
02568 char buf[512] = "", *curline = buf, *nextline;
02569 int not_written = 1;
02570
02571 if (sig_flags.need_quit == 1) {
02572 break;
02573 }
02574
02575 if (read(ast_consock, buf, sizeof(buf) - 1) <= 0) {
02576 break;
02577 }
02578
02579 do {
02580 if ((nextline = strchr(curline, '\n'))) {
02581 nextline++;
02582 } else {
02583 nextline = strchr(curline, '\0');
02584 }
02585
02586
02587 if (*curline != 127) {
02588 not_written = 0;
02589 if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
02590 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
02591 }
02592 }
02593 curline = nextline;
02594 } while (!ast_strlen_zero(curline));
02595
02596
02597 if (not_written) {
02598 break;
02599 }
02600 }
02601 return;
02602 }
02603 for (;;) {
02604 ebuf = (char *)el_gets(el, &num);
02605
02606 if (sig_flags.need_quit == 1) {
02607 break;
02608 }
02609
02610 if (!ebuf && write(1, "", 1) < 0)
02611 break;
02612
02613 if (!ast_strlen_zero(ebuf)) {
02614 if (ebuf[strlen(ebuf)-1] == '\n')
02615 ebuf[strlen(ebuf)-1] = '\0';
02616 if (!remoteconsolehandler(ebuf)) {
02617
02618 char *tmp;
02619 for (tmp = ebuf; *tmp; tmp++) {
02620 if (*tmp == 127) {
02621 memmove(tmp, tmp + 1, strlen(tmp));
02622 tmp--;
02623 }
02624 }
02625 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
02626 if (res < 1) {
02627 ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
02628 break;
02629 }
02630 }
02631 }
02632 }
02633 printf("\nDisconnected from Asterisk server\n");
02634 }
02635
02636 static int show_version(void)
02637 {
02638 printf("Asterisk " ASTERISK_VERSION "\n");
02639 return 0;
02640 }
02641
02642 static int show_cli_help(void) {
02643 printf("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2010, Digium, Inc. and others.\n");
02644 printf("Usage: asterisk [OPTIONS]\n");
02645 printf("Valid Options:\n");
02646 printf(" -V Display version number and exit\n");
02647 printf(" -C <configfile> Use an alternate configuration file\n");
02648 printf(" -G <group> Run as a group other than the caller\n");
02649 printf(" -U <user> Run as a user other than the caller\n");
02650 printf(" -c Provide console CLI\n");
02651 printf(" -d Enable extra debugging\n");
02652 #if HAVE_WORKING_FORK
02653 printf(" -f Do not fork\n");
02654 printf(" -F Always fork\n");
02655 #endif
02656 printf(" -g Dump core in case of a crash\n");
02657 printf(" -h This help screen\n");
02658 printf(" -i Initialize crypto keys at startup\n");
02659 printf(" -I Enable internal timing if %s timer is available\n", dahdi_chan_name);
02660 printf(" -L <load> Limit the maximum load average before rejecting new calls\n");
02661 printf(" -M <value> Limit the maximum number of calls to the specified value\n");
02662 printf(" -m Mute debugging and console output on the console\n");
02663 printf(" -n Disable console colorization\n");
02664 printf(" -p Run as pseudo-realtime thread\n");
02665 printf(" -q Quiet mode (suppress output)\n");
02666 printf(" -r Connect to Asterisk on this machine\n");
02667 printf(" -R Same as -r, except attempt to reconnect if disconnected\n");
02668 printf(" -t Record soundfiles in /var/tmp and move them where they\n");
02669 printf(" belong after they are done\n");
02670 printf(" -T Display the time in [Mmm dd hh:mm:ss] format for each line\n");
02671 printf(" of output to the CLI\n");
02672 printf(" -v Increase verbosity (multiple v's = more verbose)\n");
02673 printf(" -x <cmd> Execute command <cmd> (only valid with -r)\n");
02674 printf("\n");
02675 return 0;
02676 }
02677
02678 static void ast_readconfig(void)
02679 {
02680 struct ast_config *cfg;
02681 struct ast_variable *v;
02682 char *config = AST_CONFIG_FILE;
02683
02684 if (ast_opt_override_config) {
02685 cfg = ast_config_load(ast_config_AST_CONFIG_FILE);
02686 if (!cfg)
02687 ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
02688 } else {
02689 cfg = ast_config_load(config);
02690 }
02691
02692
02693 ast_copy_string(ast_config_AST_CONFIG_DIR, AST_CONFIG_DIR, sizeof(ast_config_AST_CONFIG_DIR));
02694 ast_copy_string(ast_config_AST_SPOOL_DIR, AST_SPOOL_DIR, sizeof(ast_config_AST_SPOOL_DIR));
02695 ast_copy_string(ast_config_AST_MODULE_DIR, AST_MODULE_DIR, sizeof(ast_config_AST_MODULE_DIR));
02696 snprintf(ast_config_AST_MONITOR_DIR, sizeof(ast_config_AST_MONITOR_DIR) - 1, "%s/monitor", ast_config_AST_SPOOL_DIR);
02697 ast_copy_string(ast_config_AST_VAR_DIR, AST_VAR_DIR, sizeof(ast_config_AST_VAR_DIR));
02698 ast_copy_string(ast_config_AST_DATA_DIR, AST_DATA_DIR, sizeof(ast_config_AST_DATA_DIR));
02699 ast_copy_string(ast_config_AST_LOG_DIR, AST_LOG_DIR, sizeof(ast_config_AST_LOG_DIR));
02700 ast_copy_string(ast_config_AST_AGI_DIR, AST_AGI_DIR, sizeof(ast_config_AST_AGI_DIR));
02701 ast_copy_string(ast_config_AST_DB, AST_DB, sizeof(ast_config_AST_DB));
02702 ast_copy_string(ast_config_AST_KEY_DIR, AST_KEY_DIR, sizeof(ast_config_AST_KEY_DIR));
02703 ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
02704 ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
02705 ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
02706
02707
02708 if (!cfg) {
02709 return;
02710 }
02711
02712 for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
02713 if (!strcasecmp(v->name, "astctlpermissions")) {
02714 ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
02715 } else if (!strcasecmp(v->name, "astctlowner")) {
02716 ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
02717 } else if (!strcasecmp(v->name, "astctlgroup")) {
02718 ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
02719 } else if (!strcasecmp(v->name, "astctl")) {
02720 ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
02721 }
02722 }
02723
02724 for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
02725 if (!strcasecmp(v->name, "astetcdir")) {
02726 ast_copy_string(ast_config_AST_CONFIG_DIR, v->value, sizeof(ast_config_AST_CONFIG_DIR));
02727 } else if (!strcasecmp(v->name, "astspooldir")) {
02728 ast_copy_string(ast_config_AST_SPOOL_DIR, v->value, sizeof(ast_config_AST_SPOOL_DIR));
02729 snprintf(ast_config_AST_MONITOR_DIR, sizeof(ast_config_AST_MONITOR_DIR) - 1, "%s/monitor", v->value);
02730 } else if (!strcasecmp(v->name, "astvarlibdir")) {
02731 ast_copy_string(ast_config_AST_VAR_DIR, v->value, sizeof(ast_config_AST_VAR_DIR));
02732 snprintf(ast_config_AST_DB, sizeof(ast_config_AST_DB), "%s/astdb", v->value);
02733 } else if (!strcasecmp(v->name, "astdatadir")) {
02734 ast_copy_string(ast_config_AST_DATA_DIR, v->value, sizeof(ast_config_AST_DATA_DIR));
02735 snprintf(ast_config_AST_KEY_DIR, sizeof(ast_config_AST_KEY_DIR), "%s/keys", v->value);
02736 } else if (!strcasecmp(v->name, "astlogdir")) {
02737 ast_copy_string(ast_config_AST_LOG_DIR, v->value, sizeof(ast_config_AST_LOG_DIR));
02738 } else if (!strcasecmp(v->name, "astagidir")) {
02739 ast_copy_string(ast_config_AST_AGI_DIR, v->value, sizeof(ast_config_AST_AGI_DIR));
02740 } else if (!strcasecmp(v->name, "astrundir")) {
02741 snprintf(ast_config_AST_PID, sizeof(ast_config_AST_PID), "%s/%s", v->value, "asterisk.pid");
02742 snprintf(ast_config_AST_SOCKET, sizeof(ast_config_AST_SOCKET), "%s/%s", v->value, ast_config_AST_CTL);
02743 ast_copy_string(ast_config_AST_RUN_DIR, v->value, sizeof(ast_config_AST_RUN_DIR));
02744 } else if (!strcasecmp(v->name, "astmoddir")) {
02745 ast_copy_string(ast_config_AST_MODULE_DIR, v->value, sizeof(ast_config_AST_MODULE_DIR));
02746 }
02747 }
02748
02749 for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
02750
02751 if (!strcasecmp(v->name, "verbose")) {
02752 option_verbose = atoi(v->value);
02753
02754 } else if (!strcasecmp(v->name, "timestamp")) {
02755 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
02756
02757 } else if (!strcasecmp(v->name, "execincludes")) {
02758 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
02759
02760 } else if (!strcasecmp(v->name, "debug")) {
02761 option_debug = 0;
02762 if (sscanf(v->value, "%30d", &option_debug) != 1) {
02763 option_debug = ast_true(v->value);
02764 }
02765 #if HAVE_WORKING_FORK
02766
02767 } else if (!strcasecmp(v->name, "nofork")) {
02768 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
02769
02770 } else if (!strcasecmp(v->name, "alwaysfork")) {
02771 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
02772 #endif
02773
02774 } else if (!strcasecmp(v->name, "quiet")) {
02775 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
02776
02777 } else if (!strcasecmp(v->name, "console")) {
02778 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
02779
02780 } else if (!strcasecmp(v->name, "highpriority")) {
02781 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
02782
02783 } else if (!strcasecmp(v->name, "initcrypto")) {
02784 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
02785
02786 } else if (!strcasecmp(v->name, "nocolor")) {
02787 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
02788
02789 } else if (!strcasecmp(v->name, "dontwarn")) {
02790 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
02791
02792 } else if (!strcasecmp(v->name, "dumpcore")) {
02793 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
02794
02795 } else if (!strcasecmp(v->name, "cache_record_files")) {
02796 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
02797
02798 } else if (!strcasecmp(v->name, "record_cache_dir")) {
02799 ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
02800
02801 } else if (!strcasecmp(v->name, "transcode_via_sln")) {
02802 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
02803
02804 } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
02805 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
02806
02807 } else if (!strcasecmp(v->name, "internal_timing")) {
02808 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INTERNAL_TIMING);
02809 } else if (!strcasecmp(v->name, "maxcalls")) {
02810 if ((sscanf(v->value, "%30d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
02811 option_maxcalls = 0;
02812 }
02813 } else if (!strcasecmp(v->name, "maxload")) {
02814 double test[1];
02815 if (getloadavg(test, 1) == -1) {
02816 ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
02817 option_maxload = 0.0;
02818 } else if ((sscanf(v->value, "%30lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
02819 option_maxload = 0.0;
02820 }
02821
02822 } else if (!strcasecmp(v->name, "maxfiles")) {
02823 option_maxfiles = atoi(v->value);
02824 set_ulimit(option_maxfiles);
02825
02826 } else if (!strcasecmp(v->name, "runuser")) {
02827 ast_copy_string(ast_config_AST_RUN_USER, v->value, sizeof(ast_config_AST_RUN_USER));
02828
02829 } else if (!strcasecmp(v->name, "rungroup")) {
02830 ast_copy_string(ast_config_AST_RUN_GROUP, v->value, sizeof(ast_config_AST_RUN_GROUP));
02831 } else if (!strcasecmp(v->name, "systemname")) {
02832 ast_copy_string(ast_config_AST_SYSTEM_NAME, v->value, sizeof(ast_config_AST_SYSTEM_NAME));
02833 } else if (!strcasecmp(v->name, "languageprefix")) {
02834 ast_language_is_prefix = ast_true(v->value);
02835 } else if (!strcasecmp(v->name, "dahdichanname")) {
02836 #ifdef HAVE_ZAPTEL
02837 if (ast_true(v->value)) {
02838 strcpy(_dahdi_chan_name, "DAHDI");
02839 _dahdi_chan_name_len = 5;
02840 _dahdi_chan_mode = CHAN_DAHDI_PLUS_ZAP_MODE;
02841 }
02842 #else
02843 if (ast_false(v->value)) {
02844 strcpy(_dahdi_chan_name, "Zap");
02845 _dahdi_chan_name_len = 3;
02846 _dahdi_chan_mode = CHAN_ZAP_MODE;
02847 }
02848 #endif
02849 #if defined(HAVE_SYSINFO)
02850 } else if (!strcasecmp(v->name, "minmemfree")) {
02851
02852
02853 if ((sscanf(v->value, "%ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
02854 option_minmemfree = 0;
02855 }
02856 #endif
02857 } else if (!strcasecmp(v->name, "sendfullybooted")) {
02858 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_SEND_FULLYBOOTED);
02859 }
02860 }
02861 ast_config_destroy(cfg);
02862 }
02863
02864 static void *monitor_sig_flags(void *unused)
02865 {
02866 for (;;) {
02867 struct pollfd p = { sig_alert_pipe[0], POLLIN, 0 };
02868 int a;
02869 ast_poll(&p, 1, -1);
02870 if (sig_flags.need_reload) {
02871 sig_flags.need_reload = 0;
02872 ast_module_reload(NULL);
02873 }
02874 if (sig_flags.need_quit) {
02875 sig_flags.need_quit = 0;
02876 quit_handler(0, 0, 1, 0);
02877 }
02878 if (read(sig_alert_pipe[0], &a, sizeof(a)) != sizeof(a)) {
02879 }
02880 }
02881
02882 return NULL;
02883 }
02884
02885 int main(int argc, char *argv[])
02886 {
02887 int c;
02888 char filename[80] = "";
02889 char hostname[MAXHOSTNAMELEN] = "";
02890 char tmp[80];
02891 char * xarg = NULL;
02892 int x;
02893 FILE *f;
02894 sigset_t sigs;
02895 int num;
02896 int isroot = 1, rundir_exists = 0;
02897 char *buf;
02898 char *runuser = NULL, *rungroup = NULL;
02899 struct rlimit l;
02900
02901
02902 if (argc > sizeof(_argv) / sizeof(_argv[0]) - 1) {
02903 fprintf(stderr, "Truncating argument size to %d\n", (int)(sizeof(_argv) / sizeof(_argv[0])) - 1);
02904 argc = sizeof(_argv) / sizeof(_argv[0]) - 1;
02905 }
02906 for (x=0; x<argc; x++)
02907 _argv[x] = argv[x];
02908 _argv[x] = NULL;
02909
02910 if (geteuid() != 0)
02911 isroot = 0;
02912
02913
02914 if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
02915 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
02916 }
02917 if (gethostname(hostname, sizeof(hostname)-1))
02918 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
02919 ast_mainpid = getpid();
02920 ast_ulaw_init();
02921 ast_alaw_init();
02922 callerid_init();
02923 ast_builtins_init();
02924 ast_utils_init();
02925 tdd_init();
02926 ast_fd_init();
02927 ast_pbx_init();
02928
02929 if (getenv("HOME"))
02930 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
02931
02932 while ((c = getopt(argc, argv, "mtThfFdvVqprRgciInx:U:G:C:L:M:e:")) != -1) {
02933 switch (c) {
02934 #if defined(HAVE_SYSINFO)
02935 case 'e':
02936 if ((sscanf(&optarg[1], "%ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
02937 option_minmemfree = 0;
02938 }
02939 break;
02940 #endif
02941 #if HAVE_WORKING_FORK
02942 case 'F':
02943 ast_set_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
02944 break;
02945 case 'f':
02946 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
02947 break;
02948 #endif
02949 case 'd':
02950 option_debug++;
02951 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
02952 break;
02953 case 'c':
02954 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
02955 break;
02956 case 'n':
02957 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_COLOR);
02958 break;
02959 case 'r':
02960 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
02961 break;
02962 case 'R':
02963 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE | AST_OPT_FLAG_RECONNECT);
02964 break;
02965 case 'p':
02966 ast_set_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY);
02967 break;
02968 case 'v':
02969 option_verbose++;
02970 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
02971 break;
02972 case 'm':
02973 ast_set_flag(&ast_options, AST_OPT_FLAG_MUTE);
02974 break;
02975 case 'M':
02976 if ((sscanf(optarg, "%30d", &option_maxcalls) != 1) || (option_maxcalls < 0))
02977 option_maxcalls = 0;
02978 break;
02979 case 'L':
02980 if ((sscanf(optarg, "%30lf", &option_maxload) != 1) || (option_maxload < 0.0))
02981 option_maxload = 0.0;
02982 break;
02983 case 'q':
02984 ast_set_flag(&ast_options, AST_OPT_FLAG_QUIET);
02985 break;
02986 case 't':
02987 ast_set_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES);
02988 break;
02989 case 'T':
02990 ast_set_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP);
02991 break;
02992 case 'x':
02993 ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC | AST_OPT_FLAG_NO_COLOR);
02994 xarg = ast_strdupa(optarg);
02995 break;
02996 case 'C':
02997 ast_copy_string(ast_config_AST_CONFIG_FILE, optarg, sizeof(ast_config_AST_CONFIG_FILE));
02998 ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG);
02999 break;
03000 case 'I':
03001 ast_set_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING);
03002 break;
03003 case 'i':
03004 ast_set_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS);
03005 break;
03006 case 'g':
03007 ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE);
03008 break;
03009 case 'h':
03010 show_cli_help();
03011 exit(0);
03012 case 'V':
03013 show_version();
03014 exit(0);
03015 case 'U':
03016 runuser = ast_strdupa(optarg);
03017 break;
03018 case 'G':
03019 rungroup = ast_strdupa(optarg);
03020 break;
03021 case '?':
03022 exit(1);
03023 }
03024 }
03025
03026 if (ast_opt_console || option_verbose || (ast_opt_remote && !ast_opt_exec)) {
03027 ast_register_verbose(console_verboser);
03028 WELCOME_MESSAGE;
03029 }
03030
03031 if (ast_opt_console && !option_verbose)
03032 ast_verbose("[ Booting...\n");
03033
03034
03035
03036
03037 if (ast_opt_remote) {
03038 strcpy(argv[0], "rasterisk");
03039 for (x = 1; x < argc; x++) {
03040 argv[x] = argv[0] + 10;
03041 }
03042 }
03043
03044 if (ast_opt_console && !option_verbose) {
03045 ast_verbose("[ Reading Master Configuration ]\n");
03046 }
03047
03048 ast_readconfig();
03049
03050 if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
03051 ast_log(LOG_WARNING, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
03052 ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
03053 }
03054
03055 if (ast_opt_dump_core) {
03056 memset(&l, 0, sizeof(l));
03057 l.rlim_cur = RLIM_INFINITY;
03058 l.rlim_max = RLIM_INFINITY;
03059 if (setrlimit(RLIMIT_CORE, &l)) {
03060 ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
03061 }
03062 }
03063
03064 if (getrlimit(RLIMIT_NOFILE, &l)) {
03065 ast_log(LOG_WARNING, "Unable to check file descriptor limit: %s\n", strerror(errno));
03066 }
03067
03068 #if !defined(CONFIGURE_RAN_AS_ROOT)
03069
03070 do {
03071 int fd, fd2;
03072 ast_fdset readers;
03073 struct timeval tv = { 0, };
03074
03075 if (l.rlim_cur <= FD_SETSIZE) {
03076
03077
03078 break;
03079 }
03080
03081 if (!(fd = open("/dev/null", O_RDONLY))) {
03082 ast_log(LOG_ERROR, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
03083 break;
03084 }
03085
03086 fd2 = (l.rlim_cur > sizeof(readers) * 8 ? sizeof(readers) * 8 : l.rlim_cur) - 1;
03087 if (dup2(fd, fd2) < 0) {
03088 ast_log(LOG_WARNING, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
03089 close(fd);
03090 break;
03091 }
03092
03093 FD_ZERO(&readers);
03094 FD_SET(fd2, &readers);
03095 if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
03096 ast_log(LOG_WARNING, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
03097 }
03098 ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
03099 close(fd);
03100 close(fd2);
03101 } while (0);
03102 #elif defined(HAVE_VARIABLE_FDSET)
03103 ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
03104 #endif
03105
03106 if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
03107 rungroup = ast_config_AST_RUN_GROUP;
03108 if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
03109 runuser = ast_config_AST_RUN_USER;
03110
03111
03112
03113 if (mkdir(ast_config_AST_RUN_DIR, 0755)) {
03114 if (errno == EEXIST) {
03115 rundir_exists = 1;
03116 } else {
03117 ast_log(LOG_WARNING, "Unable to create socket file directory. Remote consoles will not be able to connect! (%s)\n", strerror(x));
03118 }
03119 }
03120
03121 #ifndef __CYGWIN__
03122
03123 if (isroot)
03124 ast_set_priority(ast_opt_high_priority);
03125
03126 if (isroot && rungroup) {
03127 struct group *gr;
03128 gr = getgrnam(rungroup);
03129 if (!gr) {
03130 ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
03131 exit(1);
03132 }
03133 if (!rundir_exists && chown(ast_config_AST_RUN_DIR, -1, gr->gr_gid)) {
03134 ast_log(LOG_WARNING, "Unable to chgrp run directory to %d (%s)\n", (int) gr->gr_gid, rungroup);
03135 }
03136 if (setgid(gr->gr_gid)) {
03137 ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
03138 exit(1);
03139 }
03140 if (setgroups(0, NULL)) {
03141 ast_log(LOG_WARNING, "Unable to drop unneeded groups\n");
03142 exit(1);
03143 }
03144 if (option_verbose)
03145 ast_verbose("Running as group '%s'\n", rungroup);
03146 }
03147
03148 if (runuser && !ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)) {
03149 #ifdef HAVE_CAP
03150 int has_cap = 1;
03151 #endif
03152 struct passwd *pw;
03153 pw = getpwnam(runuser);
03154 if (!pw) {
03155 ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
03156 exit(1);
03157 }
03158 if (chown(ast_config_AST_RUN_DIR, pw->pw_uid, -1)) {
03159 ast_log(LOG_WARNING, "Unable to chown run directory to %d (%s)\n", (int) pw->pw_uid, runuser);
03160 }
03161 #ifdef HAVE_CAP
03162 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
03163 ast_log(LOG_WARNING, "Unable to keep capabilities.\n");
03164 has_cap = 0;
03165 }
03166 #endif
03167 if (!isroot && pw->pw_uid != geteuid()) {
03168 ast_log(LOG_ERROR, "Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
03169 exit(1);
03170 }
03171 if (!rungroup) {
03172 if (setgid(pw->pw_gid)) {
03173 ast_log(LOG_WARNING, "Unable to setgid to %d!\n", (int)pw->pw_gid);
03174 exit(1);
03175 }
03176 if (isroot && initgroups(pw->pw_name, pw->pw_gid)) {
03177 ast_log(LOG_WARNING, "Unable to init groups for '%s'\n", runuser);
03178 exit(1);
03179 }
03180 }
03181 if (setuid(pw->pw_uid)) {
03182 ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
03183 exit(1);
03184 }
03185 if (option_verbose)
03186 ast_verbose("Running as user '%s'\n", runuser);
03187 #ifdef HAVE_CAP
03188 if (has_cap) {
03189 cap_t cap = cap_from_text("cap_net_admin=eip");
03190
03191 if (cap_set_proc(cap))
03192 ast_log(LOG_WARNING, "Unable to install capabilities.\n");
03193
03194 if (cap_free(cap))
03195 ast_log(LOG_WARNING, "Unable to drop capabilities.\n");
03196 }
03197 #endif
03198 }
03199
03200 #endif
03201
03202 #ifdef linux
03203 if (geteuid() && ast_opt_dump_core) {
03204 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
03205 ast_log(LOG_WARNING, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
03206 }
03207 }
03208 #endif
03209
03210 ast_term_init();
03211 printf("%s", term_end());
03212 fflush(stdout);
03213
03214 if (ast_opt_console && !option_verbose)
03215 ast_verbose("[ Initializing Custom Configuration Options ]\n");
03216
03217 register_config_cli();
03218 read_config_maps();
03219
03220 if (ast_opt_console) {
03221 if (el_hist == NULL || el == NULL)
03222 ast_el_initialize();
03223
03224 if (!ast_strlen_zero(filename))
03225 ast_el_read_history(filename);
03226 }
03227
03228 if (ast_tryconnect()) {
03229
03230 if (ast_opt_remote) {
03231 if (ast_opt_exec) {
03232 ast_remotecontrol(xarg);
03233 quit_handler(0, 0, 0, 0);
03234 exit(0);
03235 }
03236 printf("%s", term_quit());
03237 ast_remotecontrol(NULL);
03238 quit_handler(0, 0, 0, 0);
03239 exit(0);
03240 } else {
03241 ast_log(LOG_ERROR, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
03242 printf("%s", term_quit());
03243 exit(1);
03244 }
03245 } else if (ast_opt_remote || ast_opt_exec) {
03246 ast_log(LOG_ERROR, "Unable to connect to remote asterisk (does %s exist?)\n", ast_config_AST_SOCKET);
03247 printf("%s", term_quit());
03248 exit(1);
03249 }
03250
03251 unlink(ast_config_AST_PID);
03252 f = fopen(ast_config_AST_PID, "w");
03253 if (f) {
03254 fprintf(f, "%ld\n", (long)getpid());
03255 fclose(f);
03256 } else
03257 ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
03258
03259 #if HAVE_WORKING_FORK
03260 if (ast_opt_always_fork || !ast_opt_no_fork) {
03261 #ifndef HAVE_SBIN_LAUNCHD
03262 if (daemon(1, 0) < 0) {
03263 ast_log(LOG_ERROR, "daemon() failed: %s\n", strerror(errno));
03264 }
03265 ast_mainpid = getpid();
03266
03267 unlink(ast_config_AST_PID);
03268 f = fopen(ast_config_AST_PID, "w");
03269 if (f) {
03270 fprintf(f, "%ld\n", (long)ast_mainpid);
03271 fclose(f);
03272 } else
03273 ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
03274 #else
03275 ast_log(LOG_WARNING, "Mac OS X detected. Use 'launchctl load /Library/LaunchDaemon/org.asterisk.asterisk.plist'.\n");
03276 #endif
03277 }
03278 #endif
03279
03280 #ifdef TEST_FRAMEWORK
03281 if (ast_test_init()) {
03282 printf("%s", term_quit());
03283 exit(1);
03284 }
03285 #endif
03286
03287 ast_makesocket();
03288 sigemptyset(&sigs);
03289 sigaddset(&sigs, SIGHUP);
03290 sigaddset(&sigs, SIGTERM);
03291 sigaddset(&sigs, SIGINT);
03292 sigaddset(&sigs, SIGPIPE);
03293 sigaddset(&sigs, SIGWINCH);
03294 pthread_sigmask(SIG_BLOCK, &sigs, NULL);
03295 sigaction(SIGURG, &urg_handler, NULL);
03296 signal(SIGINT, __quit_handler);
03297 signal(SIGTERM, __quit_handler);
03298 sigaction(SIGHUP, &hup_handler, NULL);
03299 sigaction(SIGCHLD, &child_handler, NULL);
03300 signal(SIGPIPE, SIG_IGN);
03301
03302
03303
03304
03305 srand((unsigned int) getpid() + (unsigned int) time(NULL));
03306 initstate((unsigned int) getpid() * 65536 + (unsigned int) time(NULL), randompool, sizeof(randompool));
03307
03308 if (init_logger()) {
03309 printf("%s", term_quit());
03310 exit(1);
03311 }
03312
03313 dahdi_chan_name = _dahdi_chan_name;
03314 dahdi_chan_name_len = &_dahdi_chan_name_len;
03315 dahdi_chan_mode = &_dahdi_chan_mode;
03316
03317 #ifdef HAVE_DAHDI
03318 {
03319 int fd;
03320 int x = 160;
03321 fd = open(DAHDI_FILE_TIMER, O_RDWR);
03322 if (fd >= 0) {
03323 if (ioctl(fd, DAHDI_TIMERCONFIG, &x)) {
03324 ast_log(LOG_ERROR, "You have " DAHDI_NAME
03325 " built and drivers loaded, but the "
03326 DAHDI_NAME " timer test failed to set DAHDI_TIMERCONFIG to %d.\n", x);
03327 exit(1);
03328 }
03329 if ((x = ast_wait_for_input(fd, 300)) < 0) {
03330 ast_log(LOG_ERROR, "You have " DAHDI_NAME
03331 "built and drivers loaded, but the "
03332 DAHDI_NAME " timer could not be polled during the "
03333 DAHDI_NAME " timer test.\n");
03334 exit(1);
03335 }
03336 if (!x) {
03337 const char dahdi_timer_error[] = {
03338 "Asterisk has detected a problem with your " DAHDI_NAME
03339 " configuration and will shutdown for your protection. You have options:"
03340 "\n\t1. You only have to compile " DAHDI_NAME
03341 " support into Asterisk if you need it. One option is to recompile without "
03342 DAHDI_NAME " support."
03343 "\n\t2. You only have to load " DAHDI_NAME " drivers if you want to take advantage of "
03344 DAHDI_NAME " services. One option is to unload "
03345 DAHDI_NAME " modules if you don't need them."
03346 "\n\t3. If you need Zaptel services, you must correctly configure " DAHDI_NAME "."
03347 };
03348 ast_log(LOG_ERROR, "%s\n", dahdi_timer_error);
03349 exit(1);
03350 }
03351 close(fd);
03352 }
03353 }
03354 #endif
03355 threadstorage_init();
03356
03357 astobj2_init();
03358
03359 ast_autoservice_init();
03360
03361 if (load_modules(1)) {
03362 printf("%s", term_quit());
03363 exit(1);
03364 }
03365
03366 if (dnsmgr_init()) {
03367 printf("%s", term_quit());
03368 exit(1);
03369 }
03370
03371 ast_http_init();
03372
03373 ast_channels_init();
03374
03375 if (init_manager()) {
03376 printf("%s", term_quit());
03377 exit(1);
03378 }
03379
03380 if (ast_cdr_engine_init()) {
03381 printf("%s", term_quit());
03382 exit(1);
03383 }
03384
03385 if (ast_device_state_engine_init()) {
03386 printf("%s", term_quit());
03387 exit(1);
03388 }
03389
03390 ast_rtp_init();
03391
03392 ast_udptl_init();
03393
03394 if (ast_image_init()) {
03395 printf("%s", term_quit());
03396 exit(1);
03397 }
03398
03399 if (ast_file_init()) {
03400 printf("%s", term_quit());
03401 exit(1);
03402 }
03403
03404 if (load_pbx()) {
03405 printf("%s", term_quit());
03406 exit(1);
03407 }
03408
03409 if (init_framer()) {
03410 printf("%s", term_quit());
03411 exit(1);
03412 }
03413
03414 if (astdb_init()) {
03415 printf("%s", term_quit());
03416 exit(1);
03417 }
03418
03419 if (ast_enum_init()) {
03420 printf("%s", term_quit());
03421 exit(1);
03422 }
03423
03424 if (load_modules(0)) {
03425 printf("%s", term_quit());
03426 exit(1);
03427 }
03428
03429 dnsmgr_start_refresh();
03430
03431
03432
03433 if (ast_opt_console && !option_verbose)
03434 ast_verbose(" ]\n");
03435 if (option_verbose || ast_opt_console)
03436 ast_verbose("%s", term_color(tmp, "Asterisk Ready.\n", COLOR_BRWHITE, COLOR_BLACK, sizeof(tmp)));
03437 if (ast_opt_no_fork)
03438 consolethread = pthread_self();
03439
03440 if (pipe(sig_alert_pipe))
03441 sig_alert_pipe[0] = sig_alert_pipe[1] = -1;
03442
03443 ast_set_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED);
03444 if (ast_opt_send_fullybooted) {
03445 manager_event(EVENT_FLAG_SYSTEM, "FullyBooted", "Status: Fully Booted\r\n");
03446 }
03447
03448 ast_process_pending_reloads();
03449
03450 pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
03451
03452 #ifdef __AST_DEBUG_MALLOC
03453 __ast_mm_init();
03454 #endif
03455
03456 time(&ast_startuptime);
03457 ast_cli_register_multiple(cli_asterisk, sizeof(cli_asterisk) / sizeof(struct ast_cli_entry));
03458
03459 if (ast_opt_console) {
03460
03461
03462 char title[256];
03463 pthread_attr_t attr;
03464
03465 pthread_attr_init(&attr);
03466 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
03467 ast_pthread_create(&mon_sig_flags, &attr, monitor_sig_flags, NULL);
03468 pthread_attr_destroy(&attr);
03469
03470 set_icon("Asterisk");
03471 snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %ld)", hostname, (long)ast_mainpid);
03472 set_title(title);
03473
03474 for (;;) {
03475 buf = (char *)el_gets(el, &num);
03476
03477 if (!buf && write(1, "", 1) < 0)
03478 goto lostterm;
03479
03480 if (buf) {
03481 if (buf[strlen(buf)-1] == '\n')
03482 buf[strlen(buf)-1] = '\0';
03483
03484 consolehandler((char *)buf);
03485 } else if (ast_opt_remote && (write(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n",
03486 strlen("\nUse EXIT or QUIT to exit the asterisk console\n")) < 0)) {
03487
03488 int fd;
03489 fd = open("/dev/null", O_RDWR);
03490 if (fd > -1) {
03491 dup2(fd, STDOUT_FILENO);
03492 dup2(fd, STDIN_FILENO);
03493 } else
03494 ast_log(LOG_WARNING, "Failed to open /dev/null to recover from dead console. Bad things will happen!\n");
03495 break;
03496 }
03497 }
03498 }
03499
03500 monitor_sig_flags(NULL);
03501
03502 lostterm:
03503 return 0;
03504 }