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