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