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: 369001 $")
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 if (option_verbose)
01767 ast_verbose("Executing last minute cleanups\n");
01768 ast_run_atexits();
01769
01770 if (option_verbose && ast_opt_console)
01771 ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);
01772 ast_debug(1, "Asterisk ending (%d).\n", num);
01773 manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\nRestart: %s\r\n", ast_active_channels() ? "Uncleanly" : "Cleanly", restart ? "True" : "False");
01774 if (ast_socket > -1) {
01775 pthread_cancel(lthread);
01776 close(ast_socket);
01777 ast_socket = -1;
01778 unlink(ast_config_AST_SOCKET);
01779 }
01780 if (ast_consock > -1)
01781 close(ast_consock);
01782 if (!ast_opt_remote)
01783 unlink(ast_config_AST_PID);
01784 printf("%s", term_quit());
01785 if (restart) {
01786 int i;
01787 if (option_verbose || ast_opt_console)
01788 ast_verbose("Preparing for Asterisk restart...\n");
01789
01790 for (i = 3; i < 32768; i++) {
01791 fcntl(i, F_SETFD, FD_CLOEXEC);
01792 }
01793 if (option_verbose || ast_opt_console)
01794 ast_verbose("Asterisk is now restarting...\n");
01795 restartnow = 1;
01796
01797
01798 close_logger();
01799
01800
01801
01802 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
01803 pthread_kill(consolethread, SIGHUP);
01804
01805 sleep(2);
01806 } else
01807 execvp(_argv[0], _argv);
01808
01809 } else {
01810
01811 close_logger();
01812 }
01813
01814 exit(0);
01815 }
01816
01817 static void __quit_handler(int num)
01818 {
01819 int a = 0;
01820 sig_flags.need_quit = 1;
01821 if (sig_alert_pipe[1] != -1) {
01822 if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
01823 fprintf(stderr, "quit_handler: write() failed: %s\n", strerror(errno));
01824 }
01825 }
01826
01827
01828 }
01829
01830 static void __remote_quit_handler(int num)
01831 {
01832 sig_flags.need_quit = 1;
01833 }
01834
01835 static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp)
01836 {
01837 const char *c;
01838
01839
01840 if (*s == 127) {
01841 s++;
01842 }
01843
01844 if (!strncmp(s, cmp, strlen(cmp))) {
01845 c = s + strlen(cmp);
01846 term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
01847 return c;
01848 }
01849 return NULL;
01850 }
01851
01852 static void console_verboser(const char *s)
01853 {
01854 char tmp[80];
01855 const char *c = NULL;
01856
01857 if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
01858 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
01859 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
01860 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_1))) {
01861 fputs(tmp, stdout);
01862 fputs(c, stdout);
01863 } else {
01864 if (*s == 127) {
01865 s++;
01866 }
01867 fputs(s, stdout);
01868 }
01869
01870 fflush(stdout);
01871
01872
01873 if (ast_opt_console && consolethread != AST_PTHREADT_NULL)
01874 pthread_kill(consolethread, SIGURG);
01875 }
01876
01877 static int ast_all_zeros(char *s)
01878 {
01879 while (*s) {
01880 if (*s > 32)
01881 return 0;
01882 s++;
01883 }
01884 return 1;
01885 }
01886
01887 static void consolehandler(char *s)
01888 {
01889 printf("%s", term_end());
01890 fflush(stdout);
01891
01892
01893 if (!ast_all_zeros(s))
01894 ast_el_add_history(s);
01895
01896 if (s[0] == '!') {
01897 if (s[1])
01898 ast_safe_system(s+1);
01899 else
01900 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
01901 } else
01902 ast_cli_command(STDOUT_FILENO, s);
01903 }
01904
01905 static int remoteconsolehandler(char *s)
01906 {
01907 int ret = 0;
01908
01909
01910 if (!ast_all_zeros(s))
01911 ast_el_add_history(s);
01912
01913 if (s[0] == '!') {
01914 if (s[1])
01915 ast_safe_system(s+1);
01916 else
01917 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
01918 ret = 1;
01919 }
01920 if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
01921 (s[4] == '\0' || isspace(s[4]))) {
01922 quit_handler(0, SHUTDOWN_FAST, 0);
01923 ret = 1;
01924 }
01925
01926 return ret;
01927 }
01928
01929 static char *handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01930 {
01931 switch (cmd) {
01932 case CLI_INIT:
01933 e->command = "core show version";
01934 e->usage =
01935 "Usage: core show version\n"
01936 " Shows Asterisk version information.\n";
01937 return NULL;
01938 case CLI_GENERATE:
01939 return NULL;
01940 }
01941
01942 if (a->argc != 3)
01943 return CLI_SHOWUSAGE;
01944 ast_cli(a->fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
01945 ast_get_version(), ast_build_user, ast_build_hostname,
01946 ast_build_machine, ast_build_os, ast_build_date);
01947 return CLI_SUCCESS;
01948 }
01949
01950 #if 0
01951 static int handle_quit(int fd, int argc, char *argv[])
01952 {
01953 if (argc != 1)
01954 return RESULT_SHOWUSAGE;
01955 quit_handler(0, SHUTDOWN_NORMAL, 0);
01956 return RESULT_SUCCESS;
01957 }
01958 #endif
01959
01960 static char *handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01961 {
01962 switch (cmd) {
01963 case CLI_INIT:
01964 e->command = "core stop now";
01965 e->usage =
01966 "Usage: core stop now\n"
01967 " Shuts down a running Asterisk immediately, hanging up all active calls .\n";
01968 return NULL;
01969 case CLI_GENERATE:
01970 return NULL;
01971 }
01972
01973 if (a->argc != e->args)
01974 return CLI_SHOWUSAGE;
01975 quit_handler(0, SHUTDOWN_NORMAL, 0 );
01976 return CLI_SUCCESS;
01977 }
01978
01979 static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01980 {
01981 switch (cmd) {
01982 case CLI_INIT:
01983 e->command = "core stop gracefully";
01984 e->usage =
01985 "Usage: core stop gracefully\n"
01986 " Causes Asterisk to not accept new calls, and exit when all\n"
01987 " active calls have terminated normally.\n";
01988 return NULL;
01989 case CLI_GENERATE:
01990 return NULL;
01991 }
01992
01993 if (a->argc != e->args)
01994 return CLI_SHOWUSAGE;
01995 quit_handler(0, SHUTDOWN_NICE, 0 );
01996 return CLI_SUCCESS;
01997 }
01998
01999 static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02000 {
02001 switch (cmd) {
02002 case CLI_INIT:
02003 e->command = "core stop when convenient";
02004 e->usage =
02005 "Usage: core stop when convenient\n"
02006 " Causes Asterisk to perform a shutdown when all active calls have ended.\n";
02007 return NULL;
02008 case CLI_GENERATE:
02009 return NULL;
02010 }
02011
02012 if (a->argc != e->args)
02013 return CLI_SHOWUSAGE;
02014 ast_cli(a->fd, "Waiting for inactivity to perform halt\n");
02015 quit_handler(0, SHUTDOWN_REALLY_NICE, 0 );
02016 return CLI_SUCCESS;
02017 }
02018
02019 static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02020 {
02021 switch (cmd) {
02022 case CLI_INIT:
02023 e->command = "core restart now";
02024 e->usage =
02025 "Usage: core restart now\n"
02026 " Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
02027 " restart.\n";
02028 return NULL;
02029 case CLI_GENERATE:
02030 return NULL;
02031 }
02032
02033 if (a->argc != e->args)
02034 return CLI_SHOWUSAGE;
02035 quit_handler(0, SHUTDOWN_NORMAL, 1 );
02036 return CLI_SUCCESS;
02037 }
02038
02039 static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02040 {
02041 switch (cmd) {
02042 case CLI_INIT:
02043 e->command = "core restart gracefully";
02044 e->usage =
02045 "Usage: core restart gracefully\n"
02046 " Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
02047 " restart when all active calls have ended.\n";
02048 return NULL;
02049 case CLI_GENERATE:
02050 return NULL;
02051 }
02052
02053 if (a->argc != e->args)
02054 return CLI_SHOWUSAGE;
02055 quit_handler(0, SHUTDOWN_NICE, 1 );
02056 return CLI_SUCCESS;
02057 }
02058
02059 static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02060 {
02061 switch (cmd) {
02062 case CLI_INIT:
02063 e->command = "core restart when convenient";
02064 e->usage =
02065 "Usage: core restart when convenient\n"
02066 " Causes Asterisk to perform a cold restart when all active calls have ended.\n";
02067 return NULL;
02068 case CLI_GENERATE:
02069 return NULL;
02070 }
02071
02072 if (a->argc != e->args)
02073 return CLI_SHOWUSAGE;
02074 ast_cli(a->fd, "Waiting for inactivity to perform restart\n");
02075 quit_handler(0, SHUTDOWN_REALLY_NICE, 1 );
02076 return CLI_SUCCESS;
02077 }
02078
02079 static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02080 {
02081 int aborting_shutdown = 0;
02082
02083 switch (cmd) {
02084 case CLI_INIT:
02085 e->command = "core abort shutdown";
02086 e->usage =
02087 "Usage: core abort shutdown\n"
02088 " Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
02089 " call operations.\n";
02090 return NULL;
02091 case CLI_GENERATE:
02092 return NULL;
02093 }
02094
02095 if (a->argc != e->args)
02096 return CLI_SHOWUSAGE;
02097
02098 ast_mutex_lock(&safe_system_lock);
02099 if (shuttingdown >= SHUTDOWN_FAST) {
02100 aborting_shutdown = 1;
02101 shuttingdown = NOT_SHUTTING_DOWN;
02102 }
02103 ast_mutex_unlock(&safe_system_lock);
02104
02105 if (aborting_shutdown) {
02106 ast_cancel_shutdown();
02107 }
02108 return CLI_SUCCESS;
02109 }
02110
02111 static char *handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02112 {
02113 switch (cmd) {
02114 case CLI_INIT:
02115 e->command = "!";
02116 e->usage =
02117 "Usage: !<command>\n"
02118 " Executes a given shell command\n";
02119 return NULL;
02120 case CLI_GENERATE:
02121 return NULL;
02122 }
02123
02124 return CLI_SUCCESS;
02125 }
02126 static const char warranty_lines[] = {
02127 "\n"
02128 " NO WARRANTY\n"
02129 "\n"
02130 "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
02131 "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n"
02132 "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
02133 "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
02134 "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
02135 "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n"
02136 "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n"
02137 "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
02138 "REPAIR OR CORRECTION.\n"
02139 "\n"
02140 "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
02141 "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
02142 "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
02143 "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
02144 "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
02145 "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
02146 "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
02147 "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
02148 "POSSIBILITY OF SUCH DAMAGES.\n"
02149 };
02150
02151 static char *show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02152 {
02153 switch (cmd) {
02154 case CLI_INIT:
02155 e->command = "core show warranty";
02156 e->usage =
02157 "Usage: core show warranty\n"
02158 " Shows the warranty (if any) for this copy of Asterisk.\n";
02159 return NULL;
02160 case CLI_GENERATE:
02161 return NULL;
02162 }
02163
02164 ast_cli(a->fd, "%s", warranty_lines);
02165
02166 return CLI_SUCCESS;
02167 }
02168
02169 static const char license_lines[] = {
02170 "\n"
02171 "This program is free software; you can redistribute it and/or modify\n"
02172 "it under the terms of the GNU General Public License version 2 as\n"
02173 "published by the Free Software Foundation.\n"
02174 "\n"
02175 "This program also contains components licensed under other licenses.\n"
02176 "They include:\n"
02177 "\n"
02178 "This program is distributed in the hope that it will be useful,\n"
02179 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
02180 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
02181 "GNU General Public License for more details.\n"
02182 "\n"
02183 "You should have received a copy of the GNU General Public License\n"
02184 "along with this program; if not, write to the Free Software\n"
02185 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
02186 };
02187
02188 static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02189 {
02190 switch (cmd) {
02191 case CLI_INIT:
02192 e->command = "core show license";
02193 e->usage =
02194 "Usage: core show license\n"
02195 " Shows the license(s) for this copy of Asterisk.\n";
02196 return NULL;
02197 case CLI_GENERATE:
02198 return NULL;
02199 }
02200
02201 ast_cli(a->fd, "%s", license_lines);
02202
02203 return CLI_SUCCESS;
02204 }
02205
02206 #define ASTERISK_PROMPT "*CLI> "
02207
02208 #define ASTERISK_PROMPT2 "%s*CLI> "
02209
02210 static struct ast_cli_entry cli_asterisk[] = {
02211 AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
02212 AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"),
02213 AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"),
02214 AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
02215 AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"),
02216 AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"),
02217 AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
02218 AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
02219 AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"),
02220 AST_CLI_DEFINE(handle_version, "Display version info"),
02221 AST_CLI_DEFINE(handle_bang, "Execute a shell command"),
02222 #if !defined(LOW_MEMORY)
02223 AST_CLI_DEFINE(handle_show_version_files, "List versions of files used to build Asterisk"),
02224 AST_CLI_DEFINE(handle_show_threads, "Show running threads"),
02225 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
02226 AST_CLI_DEFINE(handle_show_sysinfo, "Show System Information"),
02227 #endif
02228 AST_CLI_DEFINE(handle_show_profile, "Display profiling info"),
02229 AST_CLI_DEFINE(handle_show_settings, "Show some core settings"),
02230 AST_CLI_DEFINE(handle_clear_profile, "Clear profiling info"),
02231 #endif
02232 };
02233
02234 static int ast_el_read_char(EditLine *editline, char *cp)
02235 {
02236 int num_read = 0;
02237 int lastpos = 0;
02238 struct pollfd fds[2];
02239 int res;
02240 int max;
02241 #define EL_BUF_SIZE 512
02242 char buf[EL_BUF_SIZE];
02243
02244 for (;;) {
02245 max = 1;
02246 fds[0].fd = ast_consock;
02247 fds[0].events = POLLIN;
02248 if (!ast_opt_exec) {
02249 fds[1].fd = STDIN_FILENO;
02250 fds[1].events = POLLIN;
02251 max++;
02252 }
02253 res = ast_poll(fds, max, -1);
02254 if (res < 0) {
02255 if (sig_flags.need_quit || sig_flags.need_quit_handler)
02256 break;
02257 if (errno == EINTR)
02258 continue;
02259 ast_log(LOG_ERROR, "poll failed: %s\n", strerror(errno));
02260 break;
02261 }
02262
02263 if (!ast_opt_exec && fds[1].revents) {
02264 num_read = read(STDIN_FILENO, cp, 1);
02265 if (num_read < 1) {
02266 break;
02267 } else
02268 return (num_read);
02269 }
02270 if (fds[0].revents) {
02271 char *tmp;
02272 res = read(ast_consock, buf, sizeof(buf) - 1);
02273
02274 if (res < 1) {
02275 fprintf(stderr, "\nDisconnected from Asterisk server\n");
02276 if (!ast_opt_reconnect) {
02277 quit_handler(0, SHUTDOWN_FAST, 0);
02278 } else {
02279 int tries;
02280 int reconnects_per_second = 20;
02281 fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
02282 for (tries = 0; tries < 30 * reconnects_per_second; tries++) {
02283 if (ast_tryconnect()) {
02284 fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
02285 printf("%s", term_quit());
02286 WELCOME_MESSAGE;
02287 if (!ast_opt_mute)
02288 fdsend(ast_consock, "logger mute silent");
02289 else
02290 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
02291 break;
02292 } else
02293 usleep(1000000 / reconnects_per_second);
02294 }
02295 if (tries >= 30 * reconnects_per_second) {
02296 fprintf(stderr, "Failed to reconnect for 30 seconds. Quitting.\n");
02297 quit_handler(0, SHUTDOWN_FAST, 0);
02298 }
02299 }
02300 continue;
02301 }
02302
02303 buf[res] = '\0';
02304
02305
02306 for (tmp = buf; *tmp; tmp++) {
02307 if (*tmp == 127) {
02308 memmove(tmp, tmp + 1, strlen(tmp));
02309 tmp--;
02310 res--;
02311 }
02312 }
02313
02314
02315 if (!ast_opt_exec && !lastpos) {
02316 if (write(STDOUT_FILENO, "\r[0K", 5) < 0) {
02317 }
02318 }
02319 if (write(STDOUT_FILENO, buf, res) < 0) {
02320 }
02321 if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (buf[res-2] == '\n'))) {
02322 *cp = CC_REFRESH;
02323 return(1);
02324 } else
02325 lastpos = 1;
02326 }
02327 }
02328
02329 *cp = '\0';
02330 return (0);
02331 }
02332
02333 static struct ast_str *prompt = NULL;
02334
02335 static char *cli_prompt(EditLine *editline)
02336 {
02337 char tmp[100];
02338 char *pfmt;
02339 int color_used = 0;
02340 static int cli_prompt_changes = 0;
02341 char term_code[20];
02342 struct passwd *pw;
02343 struct group *gr;
02344
02345 if (prompt == NULL) {
02346 prompt = ast_str_create(100);
02347 } else if (!cli_prompt_changes) {
02348 return ast_str_buffer(prompt);
02349 } else {
02350 ast_str_reset(prompt);
02351 }
02352
02353 if ((pfmt = getenv("ASTERISK_PROMPT"))) {
02354 char *t = pfmt;
02355 struct timeval ts = ast_tvnow();
02356 while (*t != '\0') {
02357 if (*t == '%') {
02358 char hostname[MAXHOSTNAMELEN] = "";
02359 int i, which;
02360 struct ast_tm tm = { 0, };
02361 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
02362
02363 t++;
02364 switch (*t) {
02365 case 'C':
02366 t++;
02367 if (sscanf(t, "%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
02368 ast_str_append(&prompt, 0, "%s", term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)));
02369 t += i - 1;
02370 } else if (sscanf(t, "%30d%n", &fgcolor, &i) == 1) {
02371 ast_str_append(&prompt, 0, "%s", term_color_code(term_code, fgcolor, 0, sizeof(term_code)));
02372 t += i - 1;
02373 }
02374
02375
02376 color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
02377 break;
02378 case 'd':
02379 if (ast_localtime(&ts, &tm, NULL)) {
02380 ast_strftime(tmp, sizeof(tmp), "%Y-%m-%d", &tm);
02381 ast_str_append(&prompt, 0, "%s", tmp);
02382 cli_prompt_changes++;
02383 }
02384 break;
02385 case 'g':
02386 if ((gr = getgrgid(getgid()))) {
02387 ast_str_append(&prompt, 0, "%s", gr->gr_name);
02388 }
02389 break;
02390 case 'h':
02391 if (!gethostname(hostname, sizeof(hostname) - 1)) {
02392 ast_str_append(&prompt, 0, "%s", hostname);
02393 } else {
02394 ast_str_append(&prompt, 0, "%s", "localhost");
02395 }
02396 break;
02397 case 'H':
02398 if (!gethostname(hostname, sizeof(hostname) - 1)) {
02399 char *dotptr;
02400 if ((dotptr = strchr(hostname, '.'))) {
02401 *dotptr = '\0';
02402 }
02403 ast_str_append(&prompt, 0, "%s", hostname);
02404 } else {
02405 ast_str_append(&prompt, 0, "%s", "localhost");
02406 }
02407 break;
02408 #ifdef HAVE_GETLOADAVG
02409 case 'l':
02410 t++;
02411 if (sscanf(t, "%30d", &which) == 1 && which > 0 && which <= 3) {
02412 double list[3];
02413 getloadavg(list, 3);
02414 ast_str_append(&prompt, 0, "%.2f", list[which - 1]);
02415 cli_prompt_changes++;
02416 }
02417 break;
02418 #endif
02419 case 's':
02420 ast_str_append(&prompt, 0, "%s", ast_config_AST_SYSTEM_NAME);
02421 break;
02422 case 't':
02423 if (ast_localtime(&ts, &tm, NULL)) {
02424 ast_strftime(tmp, sizeof(tmp), "%H:%M:%S", &tm);
02425 ast_str_append(&prompt, 0, "%s", tmp);
02426 cli_prompt_changes++;
02427 }
02428 break;
02429 case 'u':
02430 if ((pw = getpwuid(getuid()))) {
02431 ast_str_append(&prompt, 0, "%s", pw->pw_name);
02432 }
02433 break;
02434 case '#':
02435 ast_str_append(&prompt, 0, "%c", ast_opt_remote ? '>' : '#');
02436 break;
02437 case '%':
02438 ast_str_append(&prompt, 0, "%c", '%');
02439 break;
02440 case '\0':
02441 t--;
02442 break;
02443 }
02444 } else {
02445 ast_str_append(&prompt, 0, "%c", *t);
02446 }
02447 t++;
02448 }
02449 if (color_used) {
02450
02451 ast_str_append(&prompt, 0, "%s", term_color_code(term_code, 0, 0, sizeof(term_code)));
02452 }
02453 } else if (remotehostname) {
02454 ast_str_set(&prompt, 0, ASTERISK_PROMPT2, remotehostname);
02455 } else {
02456 ast_str_set(&prompt, 0, "%s", ASTERISK_PROMPT);
02457 }
02458
02459 return ast_str_buffer(prompt);
02460 }
02461
02462 static char **ast_el_strtoarr(char *buf)
02463 {
02464 char **match_list = NULL, **match_list_tmp, *retstr;
02465 size_t match_list_len;
02466 int matches = 0;
02467
02468 match_list_len = 1;
02469 while ( (retstr = strsep(&buf, " ")) != NULL) {
02470
02471 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
02472 break;
02473 if (matches + 1 >= match_list_len) {
02474 match_list_len <<= 1;
02475 if ((match_list_tmp = ast_realloc(match_list, match_list_len * sizeof(char *)))) {
02476 match_list = match_list_tmp;
02477 } else {
02478 if (match_list)
02479 ast_free(match_list);
02480 return (char **) NULL;
02481 }
02482 }
02483
02484 match_list[matches++] = ast_strdup(retstr);
02485 }
02486
02487 if (!match_list)
02488 return (char **) NULL;
02489
02490 if (matches >= match_list_len) {
02491 if ((match_list_tmp = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *)))) {
02492 match_list = match_list_tmp;
02493 } else {
02494 if (match_list)
02495 ast_free(match_list);
02496 return (char **) NULL;
02497 }
02498 }
02499
02500 match_list[matches] = (char *) NULL;
02501
02502 return match_list;
02503 }
02504
02505 static int ast_el_sort_compare(const void *i1, const void *i2)
02506 {
02507 char *s1, *s2;
02508
02509 s1 = ((char **)i1)[0];
02510 s2 = ((char **)i2)[0];
02511
02512 return strcasecmp(s1, s2);
02513 }
02514
02515 static int ast_cli_display_match_list(char **matches, int len, int max)
02516 {
02517 int i, idx, limit, count;
02518 int screenwidth = 0;
02519 int numoutput = 0, numoutputline = 0;
02520
02521 screenwidth = ast_get_termcols(STDOUT_FILENO);
02522
02523
02524 limit = screenwidth / (max + 2);
02525 if (limit == 0)
02526 limit = 1;
02527
02528
02529 count = len / limit;
02530 if (count * limit < len)
02531 count++;
02532
02533 idx = 1;
02534
02535 qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);
02536
02537 for (; count > 0; count--) {
02538 numoutputline = 0;
02539 for (i = 0; i < limit && matches[idx]; i++, idx++) {
02540
02541
02542 if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
02543 i--;
02544 ast_free(matches[idx]);
02545 matches[idx] = NULL;
02546 continue;
02547 }
02548
02549 numoutput++;
02550 numoutputline++;
02551 fprintf(stdout, "%-*s ", max, matches[idx]);
02552 ast_free(matches[idx]);
02553 matches[idx] = NULL;
02554 }
02555 if (numoutputline > 0)
02556 fprintf(stdout, "\n");
02557 }
02558
02559 return numoutput;
02560 }
02561
02562
02563 static char *cli_complete(EditLine *editline, int ch)
02564 {
02565 int len = 0;
02566 char *ptr;
02567 int nummatches = 0;
02568 char **matches;
02569 int retval = CC_ERROR;
02570 char buf[2048], savechr;
02571 int res;
02572
02573 LineInfo *lf = (LineInfo *)el_line(editline);
02574
02575 savechr = *(char *)lf->cursor;
02576 *(char *)lf->cursor = '\0';
02577 ptr = (char *)lf->cursor;
02578 if (ptr) {
02579 while (ptr > lf->buffer) {
02580 if (isspace(*ptr)) {
02581 ptr++;
02582 break;
02583 }
02584 ptr--;
02585 }
02586 }
02587
02588 len = lf->cursor - ptr;
02589
02590 if (ast_opt_remote) {
02591 snprintf(buf, sizeof(buf), "_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
02592 fdsend(ast_consock, buf);
02593 if ((res = read(ast_consock, buf, sizeof(buf) - 1)) < 0) {
02594 return (char*)(CC_ERROR);
02595 }
02596 buf[res] = '\0';
02597 nummatches = atoi(buf);
02598
02599 if (nummatches > 0) {
02600 char *mbuf;
02601 int mlen = 0, maxmbuf = 2048;
02602
02603 if (!(mbuf = ast_malloc(maxmbuf))) {
02604 lf->cursor[0] = savechr;
02605 return (char *)(CC_ERROR);
02606 }
02607 snprintf(buf, sizeof(buf), "_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
02608 fdsend(ast_consock, buf);
02609 res = 0;
02610 mbuf[0] = '\0';
02611 while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
02612 if (mlen + 1024 > maxmbuf) {
02613
02614 maxmbuf += 1024;
02615 if (!(mbuf = ast_realloc(mbuf, maxmbuf))) {
02616 lf->cursor[0] = savechr;
02617 return (char *)(CC_ERROR);
02618 }
02619 }
02620
02621 res = read(ast_consock, mbuf + mlen, 1024);
02622 if (res > 0)
02623 mlen += res;
02624 }
02625 mbuf[mlen] = '\0';
02626
02627 matches = ast_el_strtoarr(mbuf);
02628 ast_free(mbuf);
02629 } else
02630 matches = (char **) NULL;
02631 } else {
02632 char **p, *oldbuf=NULL;
02633 nummatches = 0;
02634 matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
02635 for (p = matches; p && *p; p++) {
02636 if (!oldbuf || strcmp(*p,oldbuf))
02637 nummatches++;
02638 oldbuf = *p;
02639 }
02640 }
02641
02642 if (matches) {
02643 int i;
02644 int matches_num, maxlen, match_len;
02645
02646 if (matches[0][0] != '\0') {
02647 el_deletestr(editline, (int) len);
02648 el_insertstr(editline, matches[0]);
02649 retval = CC_REFRESH;
02650 }
02651
02652 if (nummatches == 1) {
02653
02654 el_insertstr(editline, " ");
02655 retval = CC_REFRESH;
02656 } else {
02657
02658 for (i = 1, maxlen = 0; matches[i]; i++) {
02659 match_len = strlen(matches[i]);
02660 if (match_len > maxlen)
02661 maxlen = match_len;
02662 }
02663 matches_num = i - 1;
02664 if (matches_num >1) {
02665 fprintf(stdout, "\n");
02666 ast_cli_display_match_list(matches, nummatches, maxlen);
02667 retval = CC_REDISPLAY;
02668 } else {
02669 el_insertstr(editline," ");
02670 retval = CC_REFRESH;
02671 }
02672 }
02673 for (i = 0; matches[i]; i++)
02674 ast_free(matches[i]);
02675 ast_free(matches);
02676 }
02677
02678 lf->cursor[0] = savechr;
02679
02680 return (char *)(long)retval;
02681 }
02682
02683 static int ast_el_initialize(void)
02684 {
02685 HistEvent ev;
02686 char *editor = getenv("AST_EDITOR");
02687
02688 if (el != NULL)
02689 el_end(el);
02690 if (el_hist != NULL)
02691 history_end(el_hist);
02692
02693 el = el_init("asterisk", stdin, stdout, stderr);
02694 el_set(el, EL_PROMPT, cli_prompt);
02695
02696 el_set(el, EL_EDITMODE, 1);
02697 el_set(el, EL_EDITOR, editor ? editor : "emacs");
02698 el_hist = history_init();
02699 if (!el || !el_hist)
02700 return -1;
02701
02702
02703 history(el_hist, &ev, H_SETSIZE, 100);
02704
02705 el_set(el, EL_HIST, history, el_hist);
02706
02707 el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
02708
02709 el_set(el, EL_BIND, "^I", "ed-complete", NULL);
02710
02711 el_set(el, EL_BIND, "?", "ed-complete", NULL);
02712
02713 el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
02714
02715 return 0;
02716 }
02717
02718 #define MAX_HISTORY_COMMAND_LENGTH 256
02719
02720 static int ast_el_add_history(char *buf)
02721 {
02722 HistEvent ev;
02723
02724 if (el_hist == NULL || el == NULL)
02725 ast_el_initialize();
02726 if (strlen(buf) > (MAX_HISTORY_COMMAND_LENGTH - 1))
02727 return 0;
02728 return (history(el_hist, &ev, H_ENTER, ast_strip(ast_strdupa(buf))));
02729 }
02730
02731 static int ast_el_write_history(char *filename)
02732 {
02733 HistEvent ev;
02734
02735 if (el_hist == NULL || el == NULL)
02736 ast_el_initialize();
02737
02738 return (history(el_hist, &ev, H_SAVE, filename));
02739 }
02740
02741 static int ast_el_read_history(char *filename)
02742 {
02743 char buf[MAX_HISTORY_COMMAND_LENGTH];
02744 FILE *f;
02745 int ret = -1;
02746
02747 if (el_hist == NULL || el == NULL)
02748 ast_el_initialize();
02749
02750 if ((f = fopen(filename, "r")) == NULL)
02751 return ret;
02752
02753 while (!feof(f)) {
02754 if (!fgets(buf, sizeof(buf), f))
02755 break;
02756 if (!strcmp(buf, "_HiStOrY_V2_\n"))
02757 continue;
02758 if (ast_all_zeros(buf))
02759 continue;
02760 if ((ret = ast_el_add_history(buf)) == -1)
02761 break;
02762 }
02763 fclose(f);
02764
02765 return ret;
02766 }
02767
02768 static void ast_remotecontrol(char *data)
02769 {
02770 char buf[80];
02771 int res;
02772 char filename[80] = "";
02773 char *hostname;
02774 char *cpid;
02775 char *version;
02776 int pid;
02777 char *stringp = NULL;
02778
02779 char *ebuf;
02780 int num = 0;
02781
02782 memset(&sig_flags, 0, sizeof(sig_flags));
02783 signal(SIGINT, __remote_quit_handler);
02784 signal(SIGTERM, __remote_quit_handler);
02785 signal(SIGHUP, __remote_quit_handler);
02786
02787 if (read(ast_consock, buf, sizeof(buf)) < 0) {
02788 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
02789 return;
02790 }
02791 if (data) {
02792 char prefix[] = "cli quit after ";
02793 char *tmp = alloca(strlen(data) + strlen(prefix) + 1);
02794 sprintf(tmp, "%s%s", prefix, data);
02795 if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) {
02796 ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
02797 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
02798 return;
02799 }
02800 }
02801 }
02802 stringp = buf;
02803 hostname = strsep(&stringp, "/");
02804 cpid = strsep(&stringp, "/");
02805 version = strsep(&stringp, "\n");
02806 if (!version)
02807 version = "<Version Unknown>";
02808 stringp = hostname;
02809 strsep(&stringp, ".");
02810 if (cpid)
02811 pid = atoi(cpid);
02812 else
02813 pid = -1;
02814 if (!data) {
02815 char tmp[80];
02816 snprintf(tmp, sizeof(tmp), "core set verbose atleast %d", option_verbose);
02817 fdsend(ast_consock, tmp);
02818 snprintf(tmp, sizeof(tmp), "core set debug atleast %d", option_debug);
02819 fdsend(ast_consock, tmp);
02820 if (!ast_opt_mute)
02821 fdsend(ast_consock, "logger mute silent");
02822 else
02823 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
02824 }
02825
02826 if (ast_opt_exec && data) {
02827 struct pollfd fds;
02828 fds.fd = ast_consock;
02829 fds.events = POLLIN;
02830 fds.revents = 0;
02831 while (ast_poll(&fds, 1, 60000) > 0) {
02832 char buffer[512] = "", *curline = buffer, *nextline;
02833 int not_written = 1;
02834
02835 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
02836 break;
02837 }
02838
02839 if (read(ast_consock, buffer, sizeof(buffer) - 1) <= 0) {
02840 break;
02841 }
02842
02843 do {
02844 if ((nextline = strchr(curline, '\n'))) {
02845 nextline++;
02846 } else {
02847 nextline = strchr(curline, '\0');
02848 }
02849
02850
02851 if (*curline != 127) {
02852 not_written = 0;
02853 if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
02854 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
02855 }
02856 }
02857 curline = nextline;
02858 } while (!ast_strlen_zero(curline));
02859
02860
02861 if (not_written) {
02862 break;
02863 }
02864 }
02865 return;
02866 }
02867
02868 ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
02869 remotehostname = hostname;
02870 if (getenv("HOME"))
02871 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
02872 if (el_hist == NULL || el == NULL)
02873 ast_el_initialize();
02874
02875 el_set(el, EL_GETCFN, ast_el_read_char);
02876
02877 if (!ast_strlen_zero(filename))
02878 ast_el_read_history(filename);
02879
02880 for (;;) {
02881 ebuf = (char *)el_gets(el, &num);
02882
02883 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
02884 break;
02885 }
02886
02887 if (!ebuf && write(1, "", 1) < 0)
02888 break;
02889
02890 if (!ast_strlen_zero(ebuf)) {
02891 if (ebuf[strlen(ebuf)-1] == '\n')
02892 ebuf[strlen(ebuf)-1] = '\0';
02893 if (!remoteconsolehandler(ebuf)) {
02894
02895 char *temp;
02896 for (temp = ebuf; *temp; temp++) {
02897 if (*temp == 127) {
02898 memmove(temp, temp + 1, strlen(temp));
02899 temp--;
02900 }
02901 }
02902 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
02903 if (res < 1) {
02904 ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
02905 break;
02906 }
02907 }
02908 }
02909 }
02910 printf("\nDisconnected from Asterisk server\n");
02911 }
02912
02913 static int show_version(void)
02914 {
02915 printf("Asterisk %s\n", ast_get_version());
02916 return 0;
02917 }
02918
02919 static int show_cli_help(void)
02920 {
02921 printf("Asterisk %s, Copyright (C) 1999 - 2012, Digium, Inc. and others.\n", ast_get_version());
02922 printf("Usage: asterisk [OPTIONS]\n");
02923 printf("Valid Options:\n");
02924 printf(" -V Display version number and exit\n");
02925 printf(" -C <configfile> Use an alternate configuration file\n");
02926 printf(" -G <group> Run as a group other than the caller\n");
02927 printf(" -U <user> Run as a user other than the caller\n");
02928 printf(" -c Provide console CLI\n");
02929 printf(" -d Enable extra debugging\n");
02930 #if HAVE_WORKING_FORK
02931 printf(" -f Do not fork\n");
02932 printf(" -F Always fork\n");
02933 #endif
02934 printf(" -g Dump core in case of a crash\n");
02935 printf(" -h This help screen\n");
02936 printf(" -i Initialize crypto keys at startup\n");
02937 printf(" -I Enable internal timing if DAHDI timer is available\n");
02938 printf(" -L <load> Limit the maximum load average before rejecting new calls\n");
02939 printf(" -M <value> Limit the maximum number of calls to the specified value\n");
02940 printf(" -m Mute debugging and console output on the console\n");
02941 printf(" -n Disable console colorization\n");
02942 printf(" -p Run as pseudo-realtime thread\n");
02943 printf(" -q Quiet mode (suppress output)\n");
02944 printf(" -r Connect to Asterisk on this machine\n");
02945 printf(" -R Same as -r, except attempt to reconnect if disconnected\n");
02946 printf(" -s <socket> Connect to Asterisk via socket <socket> (only valid with -r)\n");
02947 printf(" -t Record soundfiles in /var/tmp and move them where they\n");
02948 printf(" belong after they are done\n");
02949 printf(" -T Display the time in [Mmm dd hh:mm:ss] format for each line\n");
02950 printf(" of output to the CLI\n");
02951 printf(" -v Increase verbosity (multiple v's = more verbose)\n");
02952 printf(" -x <cmd> Execute command <cmd> (implies -r)\n");
02953 printf(" -X Execute includes by default (allows #exec in asterisk.conf)\n");
02954 printf(" -W Adjust terminal colors to compensate for a light background\n");
02955 printf("\n");
02956 return 0;
02957 }
02958
02959 static void ast_readconfig(void)
02960 {
02961 struct ast_config *cfg;
02962 struct ast_variable *v;
02963 char *config = DEFAULT_CONFIG_FILE;
02964 char hostname[MAXHOSTNAMELEN] = "";
02965 struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
02966 struct {
02967 unsigned int dbdir:1;
02968 unsigned int keydir:1;
02969 } found = { 0, 0 };
02970
02971 if (ast_opt_override_config) {
02972 cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" , config_flags);
02973 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID)
02974 ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
02975 } else
02976 cfg = ast_config_load2(config, "" , config_flags);
02977
02978
02979 ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
02980 ast_copy_string(cfg_paths.spool_dir, DEFAULT_SPOOL_DIR, sizeof(cfg_paths.spool_dir));
02981 ast_copy_string(cfg_paths.module_dir, DEFAULT_MODULE_DIR, sizeof(cfg_paths.module_dir));
02982 snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", cfg_paths.spool_dir);
02983 ast_copy_string(cfg_paths.var_dir, DEFAULT_VAR_DIR, sizeof(cfg_paths.var_dir));
02984 ast_copy_string(cfg_paths.data_dir, DEFAULT_DATA_DIR, sizeof(cfg_paths.data_dir));
02985 ast_copy_string(cfg_paths.log_dir, DEFAULT_LOG_DIR, sizeof(cfg_paths.log_dir));
02986 ast_copy_string(cfg_paths.agi_dir, DEFAULT_AGI_DIR, sizeof(cfg_paths.agi_dir));
02987 ast_copy_string(cfg_paths.db_path, DEFAULT_DB, sizeof(cfg_paths.db_path));
02988 ast_copy_string(cfg_paths.key_dir, DEFAULT_KEY_DIR, sizeof(cfg_paths.key_dir));
02989 ast_copy_string(cfg_paths.pid_path, DEFAULT_PID, sizeof(cfg_paths.pid_path));
02990 ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path));
02991 ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir));
02992
02993 ast_set_default_eid(&ast_eid_default);
02994
02995
02996 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
02997 return;
02998 }
02999
03000 for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
03001 if (!strcasecmp(v->name, "astctlpermissions"))
03002 ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
03003 else if (!strcasecmp(v->name, "astctlowner"))
03004 ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
03005 else if (!strcasecmp(v->name, "astctlgroup"))
03006 ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
03007 else if (!strcasecmp(v->name, "astctl"))
03008 ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
03009 }
03010
03011 for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
03012 if (!strcasecmp(v->name, "astetcdir")) {
03013 ast_copy_string(cfg_paths.config_dir, v->value, sizeof(cfg_paths.config_dir));
03014 } else if (!strcasecmp(v->name, "astspooldir")) {
03015 ast_copy_string(cfg_paths.spool_dir, v->value, sizeof(cfg_paths.spool_dir));
03016 snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", v->value);
03017 } else if (!strcasecmp(v->name, "astvarlibdir")) {
03018 ast_copy_string(cfg_paths.var_dir, v->value, sizeof(cfg_paths.var_dir));
03019 if (!found.dbdir)
03020 snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
03021 } else if (!strcasecmp(v->name, "astdbdir")) {
03022 snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
03023 found.dbdir = 1;
03024 } else if (!strcasecmp(v->name, "astdatadir")) {
03025 ast_copy_string(cfg_paths.data_dir, v->value, sizeof(cfg_paths.data_dir));
03026 if (!found.keydir)
03027 snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
03028 } else if (!strcasecmp(v->name, "astkeydir")) {
03029 snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
03030 found.keydir = 1;
03031 } else if (!strcasecmp(v->name, "astlogdir")) {
03032 ast_copy_string(cfg_paths.log_dir, v->value, sizeof(cfg_paths.log_dir));
03033 } else if (!strcasecmp(v->name, "astagidir")) {
03034 ast_copy_string(cfg_paths.agi_dir, v->value, sizeof(cfg_paths.agi_dir));
03035 } else if (!strcasecmp(v->name, "astrundir")) {
03036 snprintf(cfg_paths.pid_path, sizeof(cfg_paths.pid_path), "%s/%s", v->value, "asterisk.pid");
03037 snprintf(cfg_paths.socket_path, sizeof(cfg_paths.socket_path), "%s/%s", v->value, ast_config_AST_CTL);
03038 ast_copy_string(cfg_paths.run_dir, v->value, sizeof(cfg_paths.run_dir));
03039 } else if (!strcasecmp(v->name, "astmoddir")) {
03040 ast_copy_string(cfg_paths.module_dir, v->value, sizeof(cfg_paths.module_dir));
03041 }
03042 }
03043
03044 for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
03045
03046 if (!strcasecmp(v->name, "verbose")) {
03047 option_verbose = atoi(v->value);
03048
03049 } else if (!strcasecmp(v->name, "timestamp")) {
03050 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
03051
03052 } else if (!strcasecmp(v->name, "execincludes")) {
03053 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
03054
03055 } else if (!strcasecmp(v->name, "debug")) {
03056 option_debug = 0;
03057 if (sscanf(v->value, "%30d", &option_debug) != 1) {
03058 option_debug = ast_true(v->value);
03059 }
03060 #if HAVE_WORKING_FORK
03061
03062 } else if (!strcasecmp(v->name, "nofork")) {
03063 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
03064
03065 } else if (!strcasecmp(v->name, "alwaysfork")) {
03066 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
03067 #endif
03068
03069 } else if (!strcasecmp(v->name, "quiet")) {
03070 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
03071
03072 } else if (!strcasecmp(v->name, "console")) {
03073 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
03074
03075 } else if (!strcasecmp(v->name, "highpriority")) {
03076 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
03077
03078 } else if (!strcasecmp(v->name, "initcrypto")) {
03079 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
03080
03081 } else if (!strcasecmp(v->name, "nocolor")) {
03082 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
03083
03084 } else if (!strcasecmp(v->name, "dontwarn")) {
03085 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
03086
03087 } else if (!strcasecmp(v->name, "dumpcore")) {
03088 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
03089
03090 } else if (!strcasecmp(v->name, "cache_record_files")) {
03091 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
03092
03093 } else if (!strcasecmp(v->name, "record_cache_dir")) {
03094 ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
03095
03096 } else if (!strcasecmp(v->name, "transcode_via_sln")) {
03097 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
03098
03099 } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
03100 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
03101
03102 } else if (!strcasecmp(v->name, "internal_timing")) {
03103 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INTERNAL_TIMING);
03104 } else if (!strcasecmp(v->name, "maxcalls")) {
03105 if ((sscanf(v->value, "%30d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
03106 option_maxcalls = 0;
03107 }
03108 } else if (!strcasecmp(v->name, "maxload")) {
03109 double test[1];
03110
03111 if (getloadavg(test, 1) == -1) {
03112 ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
03113 option_maxload = 0.0;
03114 } else if ((sscanf(v->value, "%30lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
03115 option_maxload = 0.0;
03116 }
03117
03118 } else if (!strcasecmp(v->name, "maxfiles")) {
03119 option_maxfiles = atoi(v->value);
03120 set_ulimit(option_maxfiles);
03121
03122 } else if (!strcasecmp(v->name, "runuser")) {
03123 ast_copy_string(cfg_paths.run_user, v->value, sizeof(cfg_paths.run_user));
03124
03125 } else if (!strcasecmp(v->name, "rungroup")) {
03126 ast_copy_string(cfg_paths.run_group, v->value, sizeof(cfg_paths.run_group));
03127 } else if (!strcasecmp(v->name, "systemname")) {
03128 ast_copy_string(cfg_paths.system_name, v->value, sizeof(cfg_paths.system_name));
03129 } else if (!strcasecmp(v->name, "autosystemname")) {
03130 if (ast_true(v->value)) {
03131 if (!gethostname(hostname, sizeof(hostname) - 1))
03132 ast_copy_string(cfg_paths.system_name, hostname, sizeof(cfg_paths.system_name));
03133 else {
03134 if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)){
03135 ast_copy_string(cfg_paths.system_name, "localhost", sizeof(cfg_paths.system_name));
03136 }
03137 ast_log(LOG_ERROR, "Cannot obtain hostname for this system. Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
03138 }
03139 }
03140 } else if (!strcasecmp(v->name, "languageprefix")) {
03141 ast_language_is_prefix = ast_true(v->value);
03142 } else if (!strcasecmp(v->name, "defaultlanguage")) {
03143 ast_copy_string(defaultlanguage, v->value, MAX_LANGUAGE);
03144 } else if (!strcasecmp(v->name, "lockmode")) {
03145 if (!strcasecmp(v->value, "lockfile")) {
03146 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
03147 } else if (!strcasecmp(v->value, "flock")) {
03148 ast_set_lock_type(AST_LOCK_TYPE_FLOCK);
03149 } else {
03150 ast_log(LOG_WARNING, "'%s' is not a valid setting for the lockmode option, "
03151 "defaulting to 'lockfile'\n", v->value);
03152 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
03153 }
03154 #if defined(HAVE_SYSINFO)
03155 } else if (!strcasecmp(v->name, "minmemfree")) {
03156
03157
03158 if ((sscanf(v->value, "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
03159 option_minmemfree = 0;
03160 }
03161 #endif
03162 } else if (!strcasecmp(v->name, "entityid")) {
03163 struct ast_eid tmp_eid;
03164 if (!ast_str_to_eid(&tmp_eid, v->value)) {
03165 ast_verbose("Successfully set global EID to '%s'\n", v->value);
03166 ast_eid_default = tmp_eid;
03167 } else
03168 ast_verbose("Invalid Entity ID '%s' provided\n", v->value);
03169 } else if (!strcasecmp(v->name, "lightbackground")) {
03170 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LIGHT_BACKGROUND);
03171 } else if (!strcasecmp(v->name, "forceblackbackground")) {
03172 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
03173 } else if (!strcasecmp(v->name, "hideconnect")) {
03174 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIDE_CONSOLE_CONNECT);
03175 } else if (!strcasecmp(v->name, "lockconfdir")) {
03176 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LOCK_CONFIG_DIR);
03177 }
03178 }
03179 for (v = ast_variable_browse(cfg, "compat"); v; v = v->next) {
03180 float version;
03181 if (sscanf(v->value, "%30f", &version) != 1) {
03182 ast_log(LOG_WARNING, "Compatibility version for option '%s' is not a number: '%s'\n", v->name, v->value);
03183 continue;
03184 }
03185 if (!strcasecmp(v->name, "app_set")) {
03186 ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_APP_SET);
03187 } else if (!strcasecmp(v->name, "res_agi")) {
03188 ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_DELIM_RES_AGI);
03189 } else if (!strcasecmp(v->name, "pbx_realtime")) {
03190 ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_DELIM_PBX_REALTIME);
03191 }
03192 }
03193 ast_config_destroy(cfg);
03194 }
03195
03196 static void *monitor_sig_flags(void *unused)
03197 {
03198 for (;;) {
03199 struct pollfd p = { sig_alert_pipe[0], POLLIN, 0 };
03200 int a;
03201 ast_poll(&p, 1, -1);
03202 if (sig_flags.need_reload) {
03203 sig_flags.need_reload = 0;
03204 ast_module_reload(NULL);
03205 }
03206 if (sig_flags.need_quit) {
03207 sig_flags.need_quit = 0;
03208 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
03209 sig_flags.need_quit_handler = 1;
03210 pthread_kill(consolethread, SIGURG);
03211 } else {
03212 quit_handler(0, SHUTDOWN_NORMAL, 0);
03213 }
03214 }
03215 if (read(sig_alert_pipe[0], &a, sizeof(a)) != sizeof(a)) {
03216 }
03217 }
03218
03219 return NULL;
03220 }
03221
03222 static void *canary_thread(void *unused)
03223 {
03224 struct stat canary_stat;
03225 struct timeval now;
03226
03227
03228 sleep(120);
03229
03230 for (;;) {
03231 now = ast_tvnow();
03232 if (stat(canary_filename, &canary_stat) || now.tv_sec > canary_stat.st_mtime + 60) {
03233 ast_log(LOG_WARNING,
03234 "The canary is no more. He has ceased to be! "
03235 "He's expired and gone to meet his maker! "
03236 "He's a stiff! Bereft of life, he rests in peace. "
03237 "His metabolic processes are now history! He's off the twig! "
03238 "He's kicked the bucket. He's shuffled off his mortal coil, "
03239 "run down the curtain, and joined the bleeding choir invisible!! "
03240 "THIS is an EX-CANARY. (Reducing priority)\n");
03241 ast_set_priority(0);
03242 pthread_exit(NULL);
03243 }
03244
03245
03246 sleep(60);
03247 }
03248 }
03249
03250
03251 static void canary_exit(void)
03252 {
03253 if (canary_pid > 0)
03254 kill(canary_pid, SIGKILL);
03255 }
03256
03257 static void run_startup_commands(void)
03258 {
03259 int fd;
03260 struct ast_config *cfg;
03261 struct ast_flags cfg_flags = { 0 };
03262 struct ast_variable *v;
03263
03264 if (!(cfg = ast_config_load2("cli.conf", "" , cfg_flags)))
03265 return;
03266 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
03267 return;
03268 }
03269
03270 fd = open("/dev/null", O_RDWR);
03271 if (fd < 0) {
03272 ast_config_destroy(cfg);
03273 return;
03274 }
03275
03276 for (v = ast_variable_browse(cfg, "startup_commands"); v; v = v->next) {
03277 if (ast_true(v->value))
03278 ast_cli_command(fd, v->name);
03279 }
03280
03281 close(fd);
03282 ast_config_destroy(cfg);
03283 }
03284
03285 static void env_init(void)
03286 {
03287 setenv("AST_SYSTEMNAME", ast_config_AST_SYSTEM_NAME, 1);
03288 setenv("AST_BUILD_HOST", ast_build_hostname, 1);
03289 setenv("AST_BUILD_DATE", ast_build_date, 1);
03290 setenv("AST_BUILD_KERNEL", ast_build_kernel, 1);
03291 setenv("AST_BUILD_MACHINE", ast_build_machine, 1);
03292 setenv("AST_BUILD_OS", ast_build_os, 1);
03293 setenv("AST_BUILD_USER", ast_build_user, 1);
03294 setenv("AST_VERSION", ast_get_version(), 1);
03295 }
03296
03297 int main(int argc, char *argv[])
03298 {
03299 int c;
03300 char filename[80] = "";
03301 char hostname[MAXHOSTNAMELEN] = "";
03302 char tmp[80];
03303 char * xarg = NULL;
03304 int x;
03305 FILE *f;
03306 sigset_t sigs;
03307 int num;
03308 int isroot = 1, rundir_exists = 0;
03309 char *buf;
03310 const char *runuser = NULL, *rungroup = NULL;
03311 char *remotesock = NULL;
03312 int moduleresult;
03313 struct rlimit l;
03314
03315
03316 if (argc > ARRAY_LEN(_argv) - 1) {
03317 fprintf(stderr, "Truncating argument size to %d\n", (int)ARRAY_LEN(_argv) - 1);
03318 argc = ARRAY_LEN(_argv) - 1;
03319 }
03320 for (x = 0; x < argc; x++)
03321 _argv[x] = argv[x];
03322 _argv[x] = NULL;
03323
03324 if (geteuid() != 0)
03325 isroot = 0;
03326
03327
03328 if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
03329 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
03330 }
03331 if (gethostname(hostname, sizeof(hostname)-1))
03332 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
03333 ast_mainpid = getpid();
03334 ast_ulaw_init();
03335 ast_alaw_init();
03336 callerid_init();
03337 ast_builtins_init();
03338 ast_utils_init();
03339 tdd_init();
03340 ast_tps_init();
03341 ast_fd_init();
03342 ast_pbx_init();
03343
03344 if (getenv("HOME"))
03345 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
03346
03347 while ((c = getopt(argc, argv, "BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx:")) != -1) {
03348
03349
03350
03351 switch (c) {
03352 case 'B':
03353 ast_set_flag(&ast_options, AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
03354 ast_clear_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND);
03355 break;
03356 case 'X':
03357 ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
03358 break;
03359 case 'C':
03360 ast_copy_string(cfg_paths.config_file, optarg, sizeof(cfg_paths.config_file));
03361 ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG);
03362 break;
03363 case 'c':
03364 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
03365 break;
03366 case 'd':
03367 option_debug++;
03368 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
03369 break;
03370 #if defined(HAVE_SYSINFO)
03371 case 'e':
03372 if ((sscanf(&optarg[1], "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
03373 option_minmemfree = 0;
03374 }
03375 break;
03376 #endif
03377 #if HAVE_WORKING_FORK
03378 case 'F':
03379 ast_set_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
03380 break;
03381 case 'f':
03382 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
03383 break;
03384 #endif
03385 case 'G':
03386 rungroup = ast_strdupa(optarg);
03387 break;
03388 case 'g':
03389 ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE);
03390 break;
03391 case 'h':
03392 show_cli_help();
03393 exit(0);
03394 case 'I':
03395 ast_set_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING);
03396 break;
03397 case 'i':
03398 ast_set_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS);
03399 break;
03400 case 'L':
03401 if ((sscanf(optarg, "%30lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
03402 option_maxload = 0.0;
03403 }
03404 break;
03405 case 'M':
03406 if ((sscanf(optarg, "%30d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
03407 option_maxcalls = 0;
03408 }
03409 break;
03410 case 'm':
03411 ast_set_flag(&ast_options, AST_OPT_FLAG_MUTE);
03412 break;
03413 case 'n':
03414 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_COLOR);
03415 break;
03416 case 'p':
03417 ast_set_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY);
03418 break;
03419 case 'q':
03420 ast_set_flag(&ast_options, AST_OPT_FLAG_QUIET);
03421 break;
03422 case 'R':
03423 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE | AST_OPT_FLAG_RECONNECT);
03424 break;
03425 case 'r':
03426 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
03427 break;
03428 case 's':
03429 remotesock = ast_strdupa(optarg);
03430 break;
03431 case 'T':
03432 ast_set_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP);
03433 break;
03434 case 't':
03435 ast_set_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES);
03436 break;
03437 case 'U':
03438 runuser = ast_strdupa(optarg);
03439 break;
03440 case 'V':
03441 show_version();
03442 exit(0);
03443 case 'v':
03444 option_verbose++;
03445 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
03446 break;
03447 case 'W':
03448 ast_set_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND);
03449 ast_clear_flag(&ast_options, AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
03450 break;
03451 case 'x':
03452
03453 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
03454
03455 ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC | AST_OPT_FLAG_NO_COLOR);
03456 xarg = ast_strdupa(optarg);
03457 break;
03458 case '?':
03459 exit(1);
03460 }
03461 }
03462
03463 if (ast_opt_console || option_verbose || (ast_opt_remote && !ast_opt_exec)) {
03464 if (ast_register_verbose(console_verboser)) {
03465 ast_log(LOG_WARNING, "Unable to register console verboser?\n");
03466 }
03467 WELCOME_MESSAGE;
03468 }
03469
03470 if (ast_opt_console && !option_verbose)
03471 ast_verbose("[ Booting...\n");
03472
03473
03474
03475
03476 if (ast_opt_remote) {
03477 strcpy(argv[0], "rasterisk");
03478 for (x = 1; x < argc; x++) {
03479 argv[x] = argv[0] + 10;
03480 }
03481 }
03482
03483 if (ast_opt_console && !option_verbose) {
03484 ast_verbose("[ Reading Master Configuration ]\n");
03485 }
03486
03487 ast_readconfig();
03488 env_init();
03489
03490 if (ast_opt_remote && remotesock != NULL)
03491 ast_copy_string((char *) cfg_paths.socket_path, remotesock, sizeof(cfg_paths.socket_path));
03492
03493 if (!ast_language_is_prefix && !ast_opt_remote)
03494 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");
03495
03496 if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
03497 ast_log(LOG_WARNING, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
03498 ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
03499 }
03500
03501 if (ast_opt_dump_core) {
03502 memset(&l, 0, sizeof(l));
03503 l.rlim_cur = RLIM_INFINITY;
03504 l.rlim_max = RLIM_INFINITY;
03505 if (setrlimit(RLIMIT_CORE, &l)) {
03506 ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
03507 }
03508 }
03509
03510 if (getrlimit(RLIMIT_NOFILE, &l)) {
03511 ast_log(LOG_WARNING, "Unable to check file descriptor limit: %s\n", strerror(errno));
03512 }
03513
03514 #if !defined(CONFIGURE_RAN_AS_ROOT)
03515
03516 do {
03517 int fd, fd2;
03518 ast_fdset readers;
03519 struct timeval tv = { 0, };
03520
03521 if (l.rlim_cur <= FD_SETSIZE) {
03522
03523
03524 break;
03525 }
03526
03527 if (!(fd = open("/dev/null", O_RDONLY))) {
03528 ast_log(LOG_ERROR, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
03529 break;
03530 }
03531
03532 fd2 = (l.rlim_cur > sizeof(readers) * 8 ? sizeof(readers) * 8 : l.rlim_cur) - 1;
03533 if (dup2(fd, fd2) < 0) {
03534 ast_log(LOG_WARNING, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
03535 close(fd);
03536 break;
03537 }
03538
03539 FD_ZERO(&readers);
03540 FD_SET(fd2, &readers);
03541 if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
03542 ast_log(LOG_WARNING, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
03543 }
03544 ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
03545 close(fd);
03546 close(fd2);
03547 } while (0);
03548 #elif defined(HAVE_VARIABLE_FDSET)
03549 ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
03550 #endif
03551
03552 if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
03553 rungroup = ast_config_AST_RUN_GROUP;
03554 if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
03555 runuser = ast_config_AST_RUN_USER;
03556
03557
03558
03559
03560 sigaction(SIGCHLD, &child_handler, NULL);
03561
03562
03563
03564 if (mkdir(ast_config_AST_RUN_DIR, 0755)) {
03565 if (errno == EEXIST) {
03566 rundir_exists = 1;
03567 } else {
03568 ast_log(LOG_WARNING, "Unable to create socket file directory. Remote consoles will not be able to connect! (%s)\n", strerror(x));
03569 }
03570 }
03571
03572 #ifndef __CYGWIN__
03573
03574 if (isroot) {
03575 ast_set_priority(ast_opt_high_priority);
03576 }
03577
03578 if (isroot && rungroup) {
03579 struct group *gr;
03580 gr = getgrnam(rungroup);
03581 if (!gr) {
03582 ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
03583 exit(1);
03584 }
03585 if (!rundir_exists && chown(ast_config_AST_RUN_DIR, -1, gr->gr_gid)) {
03586 ast_log(LOG_WARNING, "Unable to chgrp run directory to %d (%s)\n", (int) gr->gr_gid, rungroup);
03587 }
03588 if (setgid(gr->gr_gid)) {
03589 ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
03590 exit(1);
03591 }
03592 if (setgroups(0, NULL)) {
03593 ast_log(LOG_WARNING, "Unable to drop unneeded groups\n");
03594 exit(1);
03595 }
03596 if (option_verbose)
03597 ast_verbose("Running as group '%s'\n", rungroup);
03598 }
03599
03600 if (runuser && !ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)) {
03601 #ifdef HAVE_CAP
03602 int has_cap = 1;
03603 #endif
03604 struct passwd *pw;
03605 pw = getpwnam(runuser);
03606 if (!pw) {
03607 ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
03608 exit(1);
03609 }
03610 if (chown(ast_config_AST_RUN_DIR, pw->pw_uid, -1)) {
03611 ast_log(LOG_WARNING, "Unable to chown run directory to %d (%s)\n", (int) pw->pw_uid, runuser);
03612 }
03613 #ifdef HAVE_CAP
03614 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
03615 ast_log(LOG_WARNING, "Unable to keep capabilities.\n");
03616 has_cap = 0;
03617 }
03618 #endif
03619 if (!isroot && pw->pw_uid != geteuid()) {
03620 ast_log(LOG_ERROR, "Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
03621 exit(1);
03622 }
03623 if (!rungroup) {
03624 if (setgid(pw->pw_gid)) {
03625 ast_log(LOG_WARNING, "Unable to setgid to %d!\n", (int)pw->pw_gid);
03626 exit(1);
03627 }
03628 if (isroot && initgroups(pw->pw_name, pw->pw_gid)) {
03629 ast_log(LOG_WARNING, "Unable to init groups for '%s'\n", runuser);
03630 exit(1);
03631 }
03632 }
03633 if (setuid(pw->pw_uid)) {
03634 ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
03635 exit(1);
03636 }
03637 if (option_verbose)
03638 ast_verbose("Running as user '%s'\n", runuser);
03639 #ifdef HAVE_CAP
03640 if (has_cap) {
03641 cap_t cap;
03642
03643 cap = cap_from_text("cap_net_admin=eip");
03644
03645 if (cap_set_proc(cap))
03646 ast_log(LOG_WARNING, "Unable to install capabilities.\n");
03647
03648 if (cap_free(cap))
03649 ast_log(LOG_WARNING, "Unable to drop capabilities.\n");
03650 }
03651 #endif
03652 }
03653
03654 #endif
03655
03656 #ifdef linux
03657 if (geteuid() && ast_opt_dump_core) {
03658 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
03659 ast_log(LOG_WARNING, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
03660 }
03661 }
03662 #endif
03663
03664 {
03665 #if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
03666 #if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
03667 #define eaccess euidaccess
03668 #endif
03669 char dir[PATH_MAX];
03670 if (!getcwd(dir, sizeof(dir)) || eaccess(dir, R_OK | X_OK | F_OK)) {
03671 ast_log(LOG_ERROR, "Unable to access the running directory (%s). Changing to '/' for compatibility.\n", strerror(errno));
03672
03673
03674 if (chdir("/")) {
03675
03676 ast_log(LOG_ERROR, "chdir(\"/\") failed?!! %s\n", strerror(errno));
03677 }
03678 } else
03679 #endif
03680 if (!ast_opt_no_fork && !ast_opt_dump_core) {
03681
03682 if (chdir("/")) {
03683 ast_log(LOG_ERROR, "Unable to chdir(\"/\") ?!! %s\n", strerror(errno));
03684 }
03685 }
03686 }
03687
03688 ast_term_init();
03689 printf("%s", term_end());
03690 fflush(stdout);
03691
03692 if (ast_opt_console && !option_verbose)
03693 ast_verbose("[ Initializing Custom Configuration Options ]\n");
03694
03695 register_config_cli();
03696 read_config_maps();
03697
03698 if (ast_opt_console) {
03699 if (el_hist == NULL || el == NULL)
03700 ast_el_initialize();
03701
03702 if (!ast_strlen_zero(filename))
03703 ast_el_read_history(filename);
03704 }
03705
03706 if (ast_tryconnect()) {
03707
03708 if (ast_opt_remote) {
03709 if (ast_opt_exec) {
03710 ast_remotecontrol(xarg);
03711 quit_handler(0, SHUTDOWN_FAST, 0);
03712 exit(0);
03713 }
03714 printf("%s", term_quit());
03715 ast_remotecontrol(NULL);
03716 quit_handler(0, SHUTDOWN_FAST, 0);
03717 exit(0);
03718 } else {
03719 ast_log(LOG_ERROR, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
03720 printf("%s", term_quit());
03721 exit(1);
03722 }
03723 } else if (ast_opt_remote || ast_opt_exec) {
03724 ast_log(LOG_ERROR, "Unable to connect to remote asterisk (does %s exist?)\n", ast_config_AST_SOCKET);
03725 printf("%s", term_quit());
03726 exit(1);
03727 }
03728
03729 unlink(ast_config_AST_PID);
03730 f = fopen(ast_config_AST_PID, "w");
03731 if (f) {
03732 fprintf(f, "%ld\n", (long)getpid());
03733 fclose(f);
03734 } else
03735 ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
03736
03737 #if HAVE_WORKING_FORK
03738 if (ast_opt_always_fork || !ast_opt_no_fork) {
03739 #ifndef HAVE_SBIN_LAUNCHD
03740 if (daemon(1, 0) < 0) {
03741 ast_log(LOG_ERROR, "daemon() failed: %s\n", strerror(errno));
03742 }
03743 ast_mainpid = getpid();
03744
03745 unlink(ast_config_AST_PID);
03746 f = fopen(ast_config_AST_PID, "w");
03747 if (f) {
03748 fprintf(f, "%ld\n", (long)ast_mainpid);
03749 fclose(f);
03750 } else
03751 ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
03752 #else
03753 ast_log(LOG_WARNING, "Mac OS X detected. Use 'launchctl load /Library/LaunchDaemon/org.asterisk.asterisk.plist'.\n");
03754 #endif
03755 }
03756 #endif
03757
03758
03759 if (isroot && ast_opt_high_priority) {
03760 snprintf(canary_filename, sizeof(canary_filename), "%s/alt.asterisk.canary.tweet.tweet.tweet", ast_config_AST_RUN_DIR);
03761
03762
03763 sigaction(SIGPIPE, &ignore_sig_handler, NULL);
03764
03765 canary_pid = fork();
03766 if (canary_pid == 0) {
03767 char canary_binary[128], *lastslash, ppid[12];
03768
03769
03770 signal(SIGCHLD, SIG_DFL);
03771 signal(SIGPIPE, SIG_DFL);
03772
03773 ast_close_fds_above_n(0);
03774 ast_set_priority(0);
03775 snprintf(ppid, sizeof(ppid), "%d", (int) ast_mainpid);
03776
03777 execlp("astcanary", "astcanary", canary_filename, ppid, (char *)NULL);
03778
03779
03780 ast_copy_string(canary_binary, argv[0], sizeof(canary_binary));
03781 if ((lastslash = strrchr(canary_binary, '/'))) {
03782 ast_copy_string(lastslash + 1, "astcanary", sizeof(canary_binary) + canary_binary - (lastslash + 1));
03783 execl(canary_binary, "astcanary", canary_filename, ppid, (char *)NULL);
03784 }
03785
03786
03787 _exit(1);
03788 } else if (canary_pid > 0) {
03789 pthread_t dont_care;
03790 ast_pthread_create_detached(&dont_care, NULL, canary_thread, NULL);
03791 }
03792
03793
03794 ast_register_atexit(canary_exit);
03795 }
03796
03797 if (ast_event_init()) {
03798 printf("%s", term_quit());
03799 exit(1);
03800 }
03801
03802 #ifdef TEST_FRAMEWORK
03803 if (ast_test_init()) {
03804 printf("%s", term_quit());
03805 exit(1);
03806 }
03807 #endif
03808
03809 ast_aoc_cli_init();
03810
03811 ast_makesocket();
03812 sigemptyset(&sigs);
03813 sigaddset(&sigs, SIGHUP);
03814 sigaddset(&sigs, SIGTERM);
03815 sigaddset(&sigs, SIGINT);
03816 sigaddset(&sigs, SIGPIPE);
03817 sigaddset(&sigs, SIGWINCH);
03818 pthread_sigmask(SIG_BLOCK, &sigs, NULL);
03819 sigaction(SIGURG, &urg_handler, NULL);
03820 signal(SIGINT, __quit_handler);
03821 signal(SIGTERM, __quit_handler);
03822 sigaction(SIGHUP, &hup_handler, NULL);
03823 sigaction(SIGPIPE, &ignore_sig_handler, NULL);
03824
03825
03826
03827
03828 srand((unsigned int) getpid() + (unsigned int) time(NULL));
03829 initstate((unsigned int) getpid() * 65536 + (unsigned int) time(NULL), randompool, sizeof(randompool));
03830
03831 if (init_logger()) {
03832 printf("%s", term_quit());
03833 exit(1);
03834 }
03835
03836 threadstorage_init();
03837
03838 astobj2_init();
03839
03840 ast_autoservice_init();
03841
03842 if (ast_timing_init()) {
03843 printf("%s", term_quit());
03844 exit(1);
03845 }
03846
03847 if (ast_ssl_init()) {
03848 printf("%s", term_quit());
03849 exit(1);
03850 }
03851
03852 #ifdef AST_XML_DOCS
03853
03854 ast_xmldoc_load_documentation();
03855 #endif
03856
03857
03858 if (ast_data_init()) {
03859 printf ("%s", term_quit());
03860 exit(1);
03861 }
03862
03863 ast_channels_init();
03864
03865 if ((moduleresult = load_modules(1))) {
03866 printf("%s", term_quit());
03867 exit(moduleresult == -2 ? 2 : 1);
03868 }
03869
03870 if (dnsmgr_init()) {
03871 printf("%s", term_quit());
03872 exit(1);
03873 }
03874
03875 ast_http_init();
03876
03877 if (init_manager()) {
03878 printf("%s", term_quit());
03879 exit(1);
03880 }
03881
03882 if (ast_cdr_engine_init()) {
03883 printf("%s", term_quit());
03884 exit(1);
03885 }
03886
03887 if (ast_cel_engine_init()) {
03888 printf("%s", term_quit());
03889 exit(1);
03890 }
03891
03892 if (ast_device_state_engine_init()) {
03893 printf("%s", term_quit());
03894 exit(1);
03895 }
03896
03897 ast_dsp_init();
03898 ast_udptl_init();
03899
03900 if (ast_image_init()) {
03901 printf("%s", term_quit());
03902 exit(1);
03903 }
03904
03905 if (ast_file_init()) {
03906 printf("%s", term_quit());
03907 exit(1);
03908 }
03909
03910 if (load_pbx()) {
03911 printf("%s", term_quit());
03912 exit(1);
03913 }
03914
03915 if (ast_indications_init()) {
03916 printf("%s", term_quit());
03917 exit(1);
03918 }
03919
03920 if (ast_features_init()) {
03921 printf("%s", term_quit());
03922 exit(1);
03923 }
03924
03925 if (init_framer()) {
03926 printf("%s", term_quit());
03927 exit(1);
03928 }
03929
03930 if (astdb_init()) {
03931 printf("%s", term_quit());
03932 exit(1);
03933 }
03934
03935 if (ast_enum_init()) {
03936 printf("%s", term_quit());
03937 exit(1);
03938 }
03939
03940 if (ast_cc_init()) {
03941 printf("%s", term_quit());
03942 exit(1);
03943 }
03944
03945 if ((moduleresult = load_modules(0))) {
03946 printf("%s", term_quit());
03947 exit(moduleresult == -2 ? 2 : 1);
03948 }
03949
03950
03951 ast_cli_perms_init(0);
03952
03953 ast_stun_init();
03954
03955 dnsmgr_start_refresh();
03956
03957
03958
03959 if (ast_opt_console && !option_verbose)
03960 ast_verbose(" ]\n");
03961 if (option_verbose || ast_opt_console)
03962 ast_verbose("%s", term_color(tmp, "Asterisk Ready.\n", COLOR_BRWHITE, COLOR_BLACK, sizeof(tmp)));
03963 if (ast_opt_no_fork)
03964 consolethread = pthread_self();
03965
03966 if (pipe(sig_alert_pipe))
03967 sig_alert_pipe[0] = sig_alert_pipe[1] = -1;
03968
03969 ast_set_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED);
03970 manager_event(EVENT_FLAG_SYSTEM, "FullyBooted", "Status: Fully Booted\r\n");
03971
03972 ast_process_pending_reloads();
03973
03974 pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
03975
03976 #ifdef __AST_DEBUG_MALLOC
03977 __ast_mm_init();
03978 #endif
03979
03980 ast_lastreloadtime = ast_startuptime = ast_tvnow();
03981 ast_cli_register_multiple(cli_asterisk, ARRAY_LEN(cli_asterisk));
03982
03983 run_startup_commands();
03984
03985 if (ast_opt_console) {
03986
03987
03988 char title[256];
03989
03990 ast_pthread_create_detached(&mon_sig_flags, NULL, monitor_sig_flags, NULL);
03991
03992 set_icon("Asterisk");
03993 snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %ld)", hostname, (long)ast_mainpid);
03994 set_title(title);
03995
03996 el_set(el, EL_GETCFN, ast_el_read_char);
03997
03998 for (;;) {
03999 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
04000 quit_handler(0, SHUTDOWN_FAST, 0);
04001 break;
04002 }
04003 buf = (char *) el_gets(el, &num);
04004
04005 if (!buf && write(1, "", 1) < 0)
04006 goto lostterm;
04007
04008 if (buf) {
04009 if (buf[strlen(buf)-1] == '\n')
04010 buf[strlen(buf)-1] = '\0';
04011
04012 consolehandler((char *)buf);
04013 } else if (ast_opt_remote && (write(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n",
04014 strlen("\nUse EXIT or QUIT to exit the asterisk console\n")) < 0)) {
04015
04016 int fd;
04017 fd = open("/dev/null", O_RDWR);
04018 if (fd > -1) {
04019 dup2(fd, STDOUT_FILENO);
04020 dup2(fd, STDIN_FILENO);
04021 } else
04022 ast_log(LOG_WARNING, "Failed to open /dev/null to recover from dead console. Bad things will happen!\n");
04023 break;
04024 }
04025 }
04026 }
04027
04028 monitor_sig_flags(NULL);
04029
04030 lostterm:
04031 return 0;
04032 }