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