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