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