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