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