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