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