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