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