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 char buf[MAX_HISTORY_COMMAND_LENGTH];
02700 FILE *f;
02701 int ret = -1;
02702
02703 if (el_hist == NULL || el == NULL)
02704 ast_el_initialize();
02705
02706 if ((f = fopen(filename, "r")) == NULL)
02707 return ret;
02708
02709 while (!feof(f)) {
02710 if (!fgets(buf, sizeof(buf), f))
02711 break;
02712 if (!strcmp(buf, "_HiStOrY_V2_\n"))
02713 continue;
02714 if (ast_all_zeros(buf))
02715 continue;
02716 if ((ret = ast_el_add_history(buf)) == -1)
02717 break;
02718 }
02719 fclose(f);
02720
02721 return ret;
02722 }
02723
02724 static void ast_remotecontrol(char *data)
02725 {
02726 char buf[80];
02727 int res;
02728 char filename[80] = "";
02729 char *hostname;
02730 char *cpid;
02731 char *version;
02732 int pid;
02733 char *stringp = NULL;
02734
02735 char *ebuf;
02736 int num = 0;
02737
02738 memset(&sig_flags, 0, sizeof(sig_flags));
02739 signal(SIGINT, __remote_quit_handler);
02740 signal(SIGTERM, __remote_quit_handler);
02741 signal(SIGHUP, __remote_quit_handler);
02742
02743 if (read(ast_consock, buf, sizeof(buf)) < 0) {
02744 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
02745 return;
02746 }
02747 if (data) {
02748 char prefix[] = "cli quit after ";
02749 char *tmp = alloca(strlen(data) + strlen(prefix) + 1);
02750 sprintf(tmp, "%s%s", prefix, data);
02751 if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) {
02752 ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
02753 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
02754 return;
02755 }
02756 }
02757 }
02758 stringp = buf;
02759 hostname = strsep(&stringp, "/");
02760 cpid = strsep(&stringp, "/");
02761 version = strsep(&stringp, "\n");
02762 if (!version)
02763 version = "<Version Unknown>";
02764 stringp = hostname;
02765 strsep(&stringp, ".");
02766 if (cpid)
02767 pid = atoi(cpid);
02768 else
02769 pid = -1;
02770 if (!data) {
02771 char tmp[80];
02772 snprintf(tmp, sizeof(tmp), "core set verbose atleast %d", option_verbose);
02773 fdsend(ast_consock, tmp);
02774 snprintf(tmp, sizeof(tmp), "core set debug atleast %d", option_debug);
02775 fdsend(ast_consock, tmp);
02776 if (!ast_opt_mute)
02777 fdsend(ast_consock, "logger mute silent");
02778 else
02779 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
02780 }
02781
02782 if (ast_opt_exec && data) {
02783 struct pollfd fds;
02784 fds.fd = ast_consock;
02785 fds.events = POLLIN;
02786 fds.revents = 0;
02787 while (ast_poll(&fds, 1, 60000) > 0) {
02788 char buffer[512] = "", *curline = buffer, *nextline;
02789 int not_written = 1;
02790
02791 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
02792 break;
02793 }
02794
02795 if (read(ast_consock, buffer, sizeof(buffer) - 1) <= 0) {
02796 break;
02797 }
02798
02799 do {
02800 if ((nextline = strchr(curline, '\n'))) {
02801 nextline++;
02802 } else {
02803 nextline = strchr(curline, '\0');
02804 }
02805
02806
02807 if (*curline != 127) {
02808 not_written = 0;
02809 if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
02810 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
02811 }
02812 }
02813 curline = nextline;
02814 } while (!ast_strlen_zero(curline));
02815
02816
02817 if (not_written) {
02818 break;
02819 }
02820 }
02821 return;
02822 }
02823
02824 ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
02825 remotehostname = hostname;
02826 if (getenv("HOME"))
02827 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
02828 if (el_hist == NULL || el == NULL)
02829 ast_el_initialize();
02830
02831 el_set(el, EL_GETCFN, ast_el_read_char);
02832
02833 if (!ast_strlen_zero(filename))
02834 ast_el_read_history(filename);
02835
02836 for (;;) {
02837 ebuf = (char *)el_gets(el, &num);
02838
02839 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
02840 break;
02841 }
02842
02843 if (!ebuf && write(1, "", 1) < 0)
02844 break;
02845
02846 if (!ast_strlen_zero(ebuf)) {
02847 if (ebuf[strlen(ebuf)-1] == '\n')
02848 ebuf[strlen(ebuf)-1] = '\0';
02849 if (!remoteconsolehandler(ebuf)) {
02850
02851 char *temp;
02852 for (temp = ebuf; *temp; temp++) {
02853 if (*temp == 127) {
02854 memmove(temp, temp + 1, strlen(temp));
02855 temp--;
02856 }
02857 }
02858 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
02859 if (res < 1) {
02860 ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
02861 break;
02862 }
02863 }
02864 }
02865 }
02866 printf("\nDisconnected from Asterisk server\n");
02867 }
02868
02869 static int show_version(void)
02870 {
02871 printf("Asterisk %s\n", ast_get_version());
02872 return 0;
02873 }
02874
02875 static int show_cli_help(void)
02876 {
02877 printf("Asterisk %s, Copyright (C) 1999 - 2012, Digium, Inc. and others.\n", ast_get_version());
02878 printf("Usage: asterisk [OPTIONS]\n");
02879 printf("Valid Options:\n");
02880 printf(" -V Display version number and exit\n");
02881 printf(" -C <configfile> Use an alternate configuration file\n");
02882 printf(" -G <group> Run as a group other than the caller\n");
02883 printf(" -U <user> Run as a user other than the caller\n");
02884 printf(" -c Provide console CLI\n");
02885 printf(" -d Enable extra debugging\n");
02886 #if HAVE_WORKING_FORK
02887 printf(" -f Do not fork\n");
02888 printf(" -F Always fork\n");
02889 #endif
02890 printf(" -g Dump core in case of a crash\n");
02891 printf(" -h This help screen\n");
02892 printf(" -i Initialize crypto keys at startup\n");
02893 printf(" -I Enable internal timing if DAHDI timer is available\n");
02894 printf(" -L <load> Limit the maximum load average before rejecting new calls\n");
02895 printf(" -M <value> Limit the maximum number of calls to the specified value\n");
02896 printf(" -m Mute debugging and console output on the console\n");
02897 printf(" -n Disable console colorization\n");
02898 printf(" -p Run as pseudo-realtime thread\n");
02899 printf(" -q Quiet mode (suppress output)\n");
02900 printf(" -r Connect to Asterisk on this machine\n");
02901 printf(" -R Same as -r, except attempt to reconnect if disconnected\n");
02902 printf(" -s <socket> Connect to Asterisk via socket <socket> (only valid with -r)\n");
02903 printf(" -t Record soundfiles in /var/tmp and move them where they\n");
02904 printf(" belong after they are done\n");
02905 printf(" -T Display the time in [Mmm dd hh:mm:ss] format for each line\n");
02906 printf(" of output to the CLI\n");
02907 printf(" -v Increase verbosity (multiple v's = more verbose)\n");
02908 printf(" -x <cmd> Execute command <cmd> (implies -r)\n");
02909 printf(" -X Execute includes by default (allows #exec in asterisk.conf)\n");
02910 printf(" -W Adjust terminal colors to compensate for a light background\n");
02911 printf("\n");
02912 return 0;
02913 }
02914
02915 static void ast_readconfig(void)
02916 {
02917 struct ast_config *cfg;
02918 struct ast_variable *v;
02919 char *config = DEFAULT_CONFIG_FILE;
02920 char hostname[MAXHOSTNAMELEN] = "";
02921 struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
02922 struct {
02923 unsigned int dbdir:1;
02924 unsigned int keydir:1;
02925 } found = { 0, 0 };
02926
02927 if (ast_opt_override_config) {
02928 cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" , config_flags);
02929 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID)
02930 ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
02931 } else
02932 cfg = ast_config_load2(config, "" , config_flags);
02933
02934
02935 ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
02936 ast_copy_string(cfg_paths.spool_dir, DEFAULT_SPOOL_DIR, sizeof(cfg_paths.spool_dir));
02937 ast_copy_string(cfg_paths.module_dir, DEFAULT_MODULE_DIR, sizeof(cfg_paths.module_dir));
02938 snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", cfg_paths.spool_dir);
02939 ast_copy_string(cfg_paths.var_dir, DEFAULT_VAR_DIR, sizeof(cfg_paths.var_dir));
02940 ast_copy_string(cfg_paths.data_dir, DEFAULT_DATA_DIR, sizeof(cfg_paths.data_dir));
02941 ast_copy_string(cfg_paths.log_dir, DEFAULT_LOG_DIR, sizeof(cfg_paths.log_dir));
02942 ast_copy_string(cfg_paths.agi_dir, DEFAULT_AGI_DIR, sizeof(cfg_paths.agi_dir));
02943 ast_copy_string(cfg_paths.db_path, DEFAULT_DB, sizeof(cfg_paths.db_path));
02944 ast_copy_string(cfg_paths.key_dir, DEFAULT_KEY_DIR, sizeof(cfg_paths.key_dir));
02945 ast_copy_string(cfg_paths.pid_path, DEFAULT_PID, sizeof(cfg_paths.pid_path));
02946 ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path));
02947 ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir));
02948
02949 ast_set_default_eid(&ast_eid_default);
02950
02951
02952 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
02953 return;
02954 }
02955
02956 for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
02957 if (!strcasecmp(v->name, "astctlpermissions"))
02958 ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
02959 else if (!strcasecmp(v->name, "astctlowner"))
02960 ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
02961 else if (!strcasecmp(v->name, "astctlgroup"))
02962 ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
02963 else if (!strcasecmp(v->name, "astctl"))
02964 ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
02965 }
02966
02967 for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
02968 if (!strcasecmp(v->name, "astetcdir")) {
02969 ast_copy_string(cfg_paths.config_dir, v->value, sizeof(cfg_paths.config_dir));
02970 } else if (!strcasecmp(v->name, "astspooldir")) {
02971 ast_copy_string(cfg_paths.spool_dir, v->value, sizeof(cfg_paths.spool_dir));
02972 snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", v->value);
02973 } else if (!strcasecmp(v->name, "astvarlibdir")) {
02974 ast_copy_string(cfg_paths.var_dir, v->value, sizeof(cfg_paths.var_dir));
02975 if (!found.dbdir)
02976 snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
02977 } else if (!strcasecmp(v->name, "astdbdir")) {
02978 snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
02979 found.dbdir = 1;
02980 } else if (!strcasecmp(v->name, "astdatadir")) {
02981 ast_copy_string(cfg_paths.data_dir, v->value, sizeof(cfg_paths.data_dir));
02982 if (!found.keydir)
02983 snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
02984 } else if (!strcasecmp(v->name, "astkeydir")) {
02985 snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
02986 found.keydir = 1;
02987 } else if (!strcasecmp(v->name, "astlogdir")) {
02988 ast_copy_string(cfg_paths.log_dir, v->value, sizeof(cfg_paths.log_dir));
02989 } else if (!strcasecmp(v->name, "astagidir")) {
02990 ast_copy_string(cfg_paths.agi_dir, v->value, sizeof(cfg_paths.agi_dir));
02991 } else if (!strcasecmp(v->name, "astrundir")) {
02992 snprintf(cfg_paths.pid_path, sizeof(cfg_paths.pid_path), "%s/%s", v->value, "asterisk.pid");
02993 snprintf(cfg_paths.socket_path, sizeof(cfg_paths.socket_path), "%s/%s", v->value, ast_config_AST_CTL);
02994 ast_copy_string(cfg_paths.run_dir, v->value, sizeof(cfg_paths.run_dir));
02995 } else if (!strcasecmp(v->name, "astmoddir")) {
02996 ast_copy_string(cfg_paths.module_dir, v->value, sizeof(cfg_paths.module_dir));
02997 }
02998 }
02999
03000 for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
03001
03002 if (!strcasecmp(v->name, "verbose")) {
03003 option_verbose = atoi(v->value);
03004
03005 } else if (!strcasecmp(v->name, "timestamp")) {
03006 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
03007
03008 } else if (!strcasecmp(v->name, "execincludes")) {
03009 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
03010
03011 } else if (!strcasecmp(v->name, "debug")) {
03012 option_debug = 0;
03013 if (sscanf(v->value, "%30d", &option_debug) != 1) {
03014 option_debug = ast_true(v->value);
03015 }
03016 #if HAVE_WORKING_FORK
03017
03018 } else if (!strcasecmp(v->name, "nofork")) {
03019 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
03020
03021 } else if (!strcasecmp(v->name, "alwaysfork")) {
03022 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
03023 #endif
03024
03025 } else if (!strcasecmp(v->name, "quiet")) {
03026 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
03027
03028 } else if (!strcasecmp(v->name, "console")) {
03029 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
03030
03031 } else if (!strcasecmp(v->name, "highpriority")) {
03032 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
03033
03034 } else if (!strcasecmp(v->name, "initcrypto")) {
03035 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
03036
03037 } else if (!strcasecmp(v->name, "nocolor")) {
03038 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
03039
03040 } else if (!strcasecmp(v->name, "dontwarn")) {
03041 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
03042
03043 } else if (!strcasecmp(v->name, "dumpcore")) {
03044 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
03045
03046 } else if (!strcasecmp(v->name, "cache_record_files")) {
03047 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
03048
03049 } else if (!strcasecmp(v->name, "record_cache_dir")) {
03050 ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
03051
03052 } else if (!strcasecmp(v->name, "transcode_via_sln")) {
03053 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
03054
03055 } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
03056 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
03057
03058 } else if (!strcasecmp(v->name, "internal_timing")) {
03059 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INTERNAL_TIMING);
03060 } else if (!strcasecmp(v->name, "maxcalls")) {
03061 if ((sscanf(v->value, "%30d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
03062 option_maxcalls = 0;
03063 }
03064 } else if (!strcasecmp(v->name, "maxload")) {
03065 double test[1];
03066
03067 if (getloadavg(test, 1) == -1) {
03068 ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
03069 option_maxload = 0.0;
03070 } else if ((sscanf(v->value, "%30lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
03071 option_maxload = 0.0;
03072 }
03073
03074 } else if (!strcasecmp(v->name, "maxfiles")) {
03075 option_maxfiles = atoi(v->value);
03076 set_ulimit(option_maxfiles);
03077
03078 } else if (!strcasecmp(v->name, "runuser")) {
03079 ast_copy_string(cfg_paths.run_user, v->value, sizeof(cfg_paths.run_user));
03080
03081 } else if (!strcasecmp(v->name, "rungroup")) {
03082 ast_copy_string(cfg_paths.run_group, v->value, sizeof(cfg_paths.run_group));
03083 } else if (!strcasecmp(v->name, "systemname")) {
03084 ast_copy_string(cfg_paths.system_name, v->value, sizeof(cfg_paths.system_name));
03085 } else if (!strcasecmp(v->name, "autosystemname")) {
03086 if (ast_true(v->value)) {
03087 if (!gethostname(hostname, sizeof(hostname) - 1))
03088 ast_copy_string(cfg_paths.system_name, hostname, sizeof(cfg_paths.system_name));
03089 else {
03090 if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)){
03091 ast_copy_string(cfg_paths.system_name, "localhost", sizeof(cfg_paths.system_name));
03092 }
03093 ast_log(LOG_ERROR, "Cannot obtain hostname for this system. Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
03094 }
03095 }
03096 } else if (!strcasecmp(v->name, "languageprefix")) {
03097 ast_language_is_prefix = ast_true(v->value);
03098 } else if (!strcasecmp(v->name, "defaultlanguage")) {
03099 ast_copy_string(defaultlanguage, v->value, MAX_LANGUAGE);
03100 } else if (!strcasecmp(v->name, "lockmode")) {
03101 if (!strcasecmp(v->value, "lockfile")) {
03102 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
03103 } else if (!strcasecmp(v->value, "flock")) {
03104 ast_set_lock_type(AST_LOCK_TYPE_FLOCK);
03105 } else {
03106 ast_log(LOG_WARNING, "'%s' is not a valid setting for the lockmode option, "
03107 "defaulting to 'lockfile'\n", v->value);
03108 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
03109 }
03110 #if defined(HAVE_SYSINFO)
03111 } else if (!strcasecmp(v->name, "minmemfree")) {
03112
03113
03114 if ((sscanf(v->value, "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
03115 option_minmemfree = 0;
03116 }
03117 #endif
03118 } else if (!strcasecmp(v->name, "entityid")) {
03119 struct ast_eid tmp_eid;
03120 if (!ast_str_to_eid(&tmp_eid, v->value)) {
03121 ast_verbose("Successfully set global EID to '%s'\n", v->value);
03122 ast_eid_default = tmp_eid;
03123 } else
03124 ast_verbose("Invalid Entity ID '%s' provided\n", v->value);
03125 } else if (!strcasecmp(v->name, "lightbackground")) {
03126 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LIGHT_BACKGROUND);
03127 } else if (!strcasecmp(v->name, "forceblackbackground")) {
03128 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
03129 } else if (!strcasecmp(v->name, "hideconnect")) {
03130 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIDE_CONSOLE_CONNECT);
03131 } else if (!strcasecmp(v->name, "lockconfdir")) {
03132 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LOCK_CONFIG_DIR);
03133 }
03134 }
03135 for (v = ast_variable_browse(cfg, "compat"); v; v = v->next) {
03136 float version;
03137 if (sscanf(v->value, "%30f", &version) != 1) {
03138 ast_log(LOG_WARNING, "Compatibility version for option '%s' is not a number: '%s'\n", v->name, v->value);
03139 continue;
03140 }
03141 if (!strcasecmp(v->name, "app_set")) {
03142 ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_APP_SET);
03143 } else if (!strcasecmp(v->name, "res_agi")) {
03144 ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_DELIM_RES_AGI);
03145 } else if (!strcasecmp(v->name, "pbx_realtime")) {
03146 ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_DELIM_PBX_REALTIME);
03147 }
03148 }
03149 ast_config_destroy(cfg);
03150 }
03151
03152 static void *monitor_sig_flags(void *unused)
03153 {
03154 for (;;) {
03155 struct pollfd p = { sig_alert_pipe[0], POLLIN, 0 };
03156 int a;
03157 ast_poll(&p, 1, -1);
03158 if (sig_flags.need_reload) {
03159 sig_flags.need_reload = 0;
03160 ast_module_reload(NULL);
03161 }
03162 if (sig_flags.need_quit) {
03163 sig_flags.need_quit = 0;
03164 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
03165 sig_flags.need_quit_handler = 1;
03166 pthread_kill(consolethread, SIGURG);
03167 } else {
03168 quit_handler(0, SHUTDOWN_NORMAL, 0);
03169 }
03170 }
03171 if (read(sig_alert_pipe[0], &a, sizeof(a)) != sizeof(a)) {
03172 }
03173 }
03174
03175 return NULL;
03176 }
03177
03178 static void *canary_thread(void *unused)
03179 {
03180 struct stat canary_stat;
03181 struct timeval now;
03182
03183
03184 sleep(120);
03185
03186 for (;;) {
03187 stat(canary_filename, &canary_stat);
03188 now = ast_tvnow();
03189 if (now.tv_sec > canary_stat.st_mtime + 60) {
03190 ast_log(LOG_WARNING,
03191 "The canary is no more. He has ceased to be! "
03192 "He's expired and gone to meet his maker! "
03193 "He's a stiff! Bereft of life, he rests in peace. "
03194 "His metabolic processes are now history! He's off the twig! "
03195 "He's kicked the bucket. He's shuffled off his mortal coil, "
03196 "run down the curtain, and joined the bleeding choir invisible!! "
03197 "THIS is an EX-CANARY. (Reducing priority)\n");
03198 ast_set_priority(0);
03199 pthread_exit(NULL);
03200 }
03201
03202
03203 sleep(60);
03204 }
03205 }
03206
03207
03208 static void canary_exit(void)
03209 {
03210 if (canary_pid > 0)
03211 kill(canary_pid, SIGKILL);
03212 }
03213
03214 static void run_startup_commands(void)
03215 {
03216 int fd;
03217 struct ast_config *cfg;
03218 struct ast_flags cfg_flags = { 0 };
03219 struct ast_variable *v;
03220
03221 if (!(cfg = ast_config_load2("cli.conf", "" , cfg_flags)))
03222 return;
03223 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
03224 return;
03225 }
03226
03227 fd = open("/dev/null", O_RDWR);
03228 if (fd < 0) {
03229 ast_config_destroy(cfg);
03230 return;
03231 }
03232
03233 for (v = ast_variable_browse(cfg, "startup_commands"); v; v = v->next) {
03234 if (ast_true(v->value))
03235 ast_cli_command(fd, v->name);
03236 }
03237
03238 close(fd);
03239 ast_config_destroy(cfg);
03240 }
03241
03242 static void env_init(void)
03243 {
03244 setenv("AST_SYSTEMNAME", ast_config_AST_SYSTEM_NAME, 1);
03245 setenv("AST_BUILD_HOST", ast_build_hostname, 1);
03246 setenv("AST_BUILD_DATE", ast_build_date, 1);
03247 setenv("AST_BUILD_KERNEL", ast_build_kernel, 1);
03248 setenv("AST_BUILD_MACHINE", ast_build_machine, 1);
03249 setenv("AST_BUILD_OS", ast_build_os, 1);
03250 setenv("AST_BUILD_USER", ast_build_user, 1);
03251 setenv("AST_VERSION", ast_get_version(), 1);
03252 }
03253
03254 int main(int argc, char *argv[])
03255 {
03256 int c;
03257 char filename[80] = "";
03258 char hostname[MAXHOSTNAMELEN] = "";
03259 char tmp[80];
03260 char * xarg = NULL;
03261 int x;
03262 FILE *f;
03263 sigset_t sigs;
03264 int num;
03265 int isroot = 1, rundir_exists = 0;
03266 char *buf;
03267 const char *runuser = NULL, *rungroup = NULL;
03268 char *remotesock = NULL;
03269 int moduleresult;
03270 struct rlimit l;
03271
03272
03273 if (argc > ARRAY_LEN(_argv) - 1) {
03274 fprintf(stderr, "Truncating argument size to %d\n", (int)ARRAY_LEN(_argv) - 1);
03275 argc = ARRAY_LEN(_argv) - 1;
03276 }
03277 for (x = 0; x < argc; x++)
03278 _argv[x] = argv[x];
03279 _argv[x] = NULL;
03280
03281 if (geteuid() != 0)
03282 isroot = 0;
03283
03284
03285 if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
03286 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
03287 }
03288 if (gethostname(hostname, sizeof(hostname)-1))
03289 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
03290 ast_mainpid = getpid();
03291 ast_ulaw_init();
03292 ast_alaw_init();
03293 callerid_init();
03294 ast_builtins_init();
03295 ast_utils_init();
03296 tdd_init();
03297 ast_tps_init();
03298 ast_fd_init();
03299 ast_pbx_init();
03300
03301 if (getenv("HOME"))
03302 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
03303
03304 while ((c = getopt(argc, argv, "BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx:")) != -1) {
03305
03306
03307
03308 switch (c) {
03309 case 'B':
03310 ast_set_flag(&ast_options, AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
03311 ast_clear_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND);
03312 break;
03313 case 'X':
03314 ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
03315 break;
03316 case 'C':
03317 ast_copy_string(cfg_paths.config_file, optarg, sizeof(cfg_paths.config_file));
03318 ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG);
03319 break;
03320 case 'c':
03321 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
03322 break;
03323 case 'd':
03324 option_debug++;
03325 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
03326 break;
03327 #if defined(HAVE_SYSINFO)
03328 case 'e':
03329 if ((sscanf(&optarg[1], "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
03330 option_minmemfree = 0;
03331 }
03332 break;
03333 #endif
03334 #if HAVE_WORKING_FORK
03335 case 'F':
03336 ast_set_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
03337 break;
03338 case 'f':
03339 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
03340 break;
03341 #endif
03342 case 'G':
03343 rungroup = ast_strdupa(optarg);
03344 break;
03345 case 'g':
03346 ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE);
03347 break;
03348 case 'h':
03349 show_cli_help();
03350 exit(0);
03351 case 'I':
03352 ast_set_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING);
03353 break;
03354 case 'i':
03355 ast_set_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS);
03356 break;
03357 case 'L':
03358 if ((sscanf(optarg, "%30lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
03359 option_maxload = 0.0;
03360 }
03361 break;
03362 case 'M':
03363 if ((sscanf(optarg, "%30d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
03364 option_maxcalls = 0;
03365 }
03366 break;
03367 case 'm':
03368 ast_set_flag(&ast_options, AST_OPT_FLAG_MUTE);
03369 break;
03370 case 'n':
03371 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_COLOR);
03372 break;
03373 case 'p':
03374 ast_set_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY);
03375 break;
03376 case 'q':
03377 ast_set_flag(&ast_options, AST_OPT_FLAG_QUIET);
03378 break;
03379 case 'R':
03380 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE | AST_OPT_FLAG_RECONNECT);
03381 break;
03382 case 'r':
03383 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
03384 break;
03385 case 's':
03386 remotesock = ast_strdupa(optarg);
03387 break;
03388 case 'T':
03389 ast_set_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP);
03390 break;
03391 case 't':
03392 ast_set_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES);
03393 break;
03394 case 'U':
03395 runuser = ast_strdupa(optarg);
03396 break;
03397 case 'V':
03398 show_version();
03399 exit(0);
03400 case 'v':
03401 option_verbose++;
03402 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
03403 break;
03404 case 'W':
03405 ast_set_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND);
03406 ast_clear_flag(&ast_options, AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
03407 break;
03408 case 'x':
03409
03410 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
03411
03412 ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC | AST_OPT_FLAG_NO_COLOR);
03413 xarg = ast_strdupa(optarg);
03414 break;
03415 case '?':
03416 exit(1);
03417 }
03418 }
03419
03420 if (ast_opt_console || option_verbose || (ast_opt_remote && !ast_opt_exec)) {
03421 if (ast_register_verbose(console_verboser)) {
03422 ast_log(LOG_WARNING, "Unable to register console verboser?\n");
03423 }
03424 WELCOME_MESSAGE;
03425 }
03426
03427 if (ast_opt_console && !option_verbose)
03428 ast_verbose("[ Booting...\n");
03429
03430
03431
03432
03433 if (ast_opt_remote) {
03434 strcpy(argv[0], "rasterisk");
03435 for (x = 1; x < argc; x++) {
03436 argv[x] = argv[0] + 10;
03437 }
03438 }
03439
03440 if (ast_opt_console && !option_verbose) {
03441 ast_verbose("[ Reading Master Configuration ]\n");
03442 }
03443
03444 ast_readconfig();
03445 env_init();
03446
03447 if (ast_opt_remote && remotesock != NULL)
03448 ast_copy_string((char *) cfg_paths.socket_path, remotesock, sizeof(cfg_paths.socket_path));
03449
03450 if (!ast_language_is_prefix && !ast_opt_remote)
03451 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");
03452
03453 if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
03454 ast_log(LOG_WARNING, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
03455 ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
03456 }
03457
03458 if (ast_opt_dump_core) {
03459 memset(&l, 0, sizeof(l));
03460 l.rlim_cur = RLIM_INFINITY;
03461 l.rlim_max = RLIM_INFINITY;
03462 if (setrlimit(RLIMIT_CORE, &l)) {
03463 ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
03464 }
03465 }
03466
03467 if (getrlimit(RLIMIT_NOFILE, &l)) {
03468 ast_log(LOG_WARNING, "Unable to check file descriptor limit: %s\n", strerror(errno));
03469 }
03470
03471 #if !defined(CONFIGURE_RAN_AS_ROOT)
03472
03473 do {
03474 int fd, fd2;
03475 ast_fdset readers;
03476 struct timeval tv = { 0, };
03477
03478 if (l.rlim_cur <= FD_SETSIZE) {
03479
03480
03481 break;
03482 }
03483
03484 if (!(fd = open("/dev/null", O_RDONLY))) {
03485 ast_log(LOG_ERROR, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
03486 break;
03487 }
03488
03489 fd2 = (l.rlim_cur > sizeof(readers) * 8 ? sizeof(readers) * 8 : l.rlim_cur) - 1;
03490 if (dup2(fd, fd2) < 0) {
03491 ast_log(LOG_WARNING, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
03492 close(fd);
03493 break;
03494 }
03495
03496 FD_ZERO(&readers);
03497 FD_SET(fd2, &readers);
03498 if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
03499 ast_log(LOG_WARNING, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
03500 }
03501 ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
03502 close(fd);
03503 close(fd2);
03504 } while (0);
03505 #elif defined(HAVE_VARIABLE_FDSET)
03506 ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
03507 #endif
03508
03509 if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
03510 rungroup = ast_config_AST_RUN_GROUP;
03511 if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
03512 runuser = ast_config_AST_RUN_USER;
03513
03514
03515
03516
03517 sigaction(SIGCHLD, &child_handler, NULL);
03518
03519
03520
03521 if (mkdir(ast_config_AST_RUN_DIR, 0755)) {
03522 if (errno == EEXIST) {
03523 rundir_exists = 1;
03524 } else {
03525 ast_log(LOG_WARNING, "Unable to create socket file directory. Remote consoles will not be able to connect! (%s)\n", strerror(x));
03526 }
03527 }
03528
03529 #ifndef __CYGWIN__
03530
03531 if (isroot) {
03532 ast_set_priority(ast_opt_high_priority);
03533 }
03534
03535 if (isroot && rungroup) {
03536 struct group *gr;
03537 gr = getgrnam(rungroup);
03538 if (!gr) {
03539 ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
03540 exit(1);
03541 }
03542 if (!rundir_exists && chown(ast_config_AST_RUN_DIR, -1, gr->gr_gid)) {
03543 ast_log(LOG_WARNING, "Unable to chgrp run directory to %d (%s)\n", (int) gr->gr_gid, rungroup);
03544 }
03545 if (setgid(gr->gr_gid)) {
03546 ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
03547 exit(1);
03548 }
03549 if (setgroups(0, NULL)) {
03550 ast_log(LOG_WARNING, "Unable to drop unneeded groups\n");
03551 exit(1);
03552 }
03553 if (option_verbose)
03554 ast_verbose("Running as group '%s'\n", rungroup);
03555 }
03556
03557 if (runuser && !ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)) {
03558 #ifdef HAVE_CAP
03559 int has_cap = 1;
03560 #endif
03561 struct passwd *pw;
03562 pw = getpwnam(runuser);
03563 if (!pw) {
03564 ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
03565 exit(1);
03566 }
03567 if (chown(ast_config_AST_RUN_DIR, pw->pw_uid, -1)) {
03568 ast_log(LOG_WARNING, "Unable to chown run directory to %d (%s)\n", (int) pw->pw_uid, runuser);
03569 }
03570 #ifdef HAVE_CAP
03571 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
03572 ast_log(LOG_WARNING, "Unable to keep capabilities.\n");
03573 has_cap = 0;
03574 }
03575 #endif
03576 if (!isroot && pw->pw_uid != geteuid()) {
03577 ast_log(LOG_ERROR, "Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
03578 exit(1);
03579 }
03580 if (!rungroup) {
03581 if (setgid(pw->pw_gid)) {
03582 ast_log(LOG_WARNING, "Unable to setgid to %d!\n", (int)pw->pw_gid);
03583 exit(1);
03584 }
03585 if (isroot && initgroups(pw->pw_name, pw->pw_gid)) {
03586 ast_log(LOG_WARNING, "Unable to init groups for '%s'\n", runuser);
03587 exit(1);
03588 }
03589 }
03590 if (setuid(pw->pw_uid)) {
03591 ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
03592 exit(1);
03593 }
03594 if (option_verbose)
03595 ast_verbose("Running as user '%s'\n", runuser);
03596 #ifdef HAVE_CAP
03597 if (has_cap) {
03598 cap_t cap;
03599
03600 cap = cap_from_text("cap_net_admin=eip");
03601
03602 if (cap_set_proc(cap))
03603 ast_log(LOG_WARNING, "Unable to install capabilities.\n");
03604
03605 if (cap_free(cap))
03606 ast_log(LOG_WARNING, "Unable to drop capabilities.\n");
03607 }
03608 #endif
03609 }
03610
03611 #endif
03612
03613 #ifdef linux
03614 if (geteuid() && ast_opt_dump_core) {
03615 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
03616 ast_log(LOG_WARNING, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
03617 }
03618 }
03619 #endif
03620
03621 {
03622 #if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
03623 #if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
03624 #define eaccess euidaccess
03625 #endif
03626 char dir[PATH_MAX];
03627 if (!getcwd(dir, sizeof(dir)) || eaccess(dir, R_OK | X_OK | F_OK)) {
03628 ast_log(LOG_ERROR, "Unable to access the running directory (%s). Changing to '/' for compatibility.\n", strerror(errno));
03629
03630
03631 if (chdir("/")) {
03632
03633 ast_log(LOG_ERROR, "chdir(\"/\") failed?!! %s\n", strerror(errno));
03634 }
03635 } else
03636 #endif
03637 if (!ast_opt_no_fork && !ast_opt_dump_core) {
03638
03639 if (chdir("/")) {
03640 ast_log(LOG_ERROR, "Unable to chdir(\"/\") ?!! %s\n", strerror(errno));
03641 }
03642 }
03643 }
03644
03645 ast_term_init();
03646 printf("%s", term_end());
03647 fflush(stdout);
03648
03649 if (ast_opt_console && !option_verbose)
03650 ast_verbose("[ Initializing Custom Configuration Options ]\n");
03651
03652 register_config_cli();
03653 read_config_maps();
03654
03655 if (ast_opt_console) {
03656 if (el_hist == NULL || el == NULL)
03657 ast_el_initialize();
03658
03659 if (!ast_strlen_zero(filename))
03660 ast_el_read_history(filename);
03661 }
03662
03663 if (ast_tryconnect()) {
03664
03665 if (ast_opt_remote) {
03666 if (ast_opt_exec) {
03667 ast_remotecontrol(xarg);
03668 quit_handler(0, SHUTDOWN_FAST, 0);
03669 exit(0);
03670 }
03671 printf("%s", term_quit());
03672 ast_remotecontrol(NULL);
03673 quit_handler(0, SHUTDOWN_FAST, 0);
03674 exit(0);
03675 } else {
03676 ast_log(LOG_ERROR, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
03677 printf("%s", term_quit());
03678 exit(1);
03679 }
03680 } else if (ast_opt_remote || ast_opt_exec) {
03681 ast_log(LOG_ERROR, "Unable to connect to remote asterisk (does %s exist?)\n", ast_config_AST_SOCKET);
03682 printf("%s", term_quit());
03683 exit(1);
03684 }
03685
03686 unlink(ast_config_AST_PID);
03687 f = fopen(ast_config_AST_PID, "w");
03688 if (f) {
03689 fprintf(f, "%ld\n", (long)getpid());
03690 fclose(f);
03691 } else
03692 ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
03693
03694 #if HAVE_WORKING_FORK
03695 if (ast_opt_always_fork || !ast_opt_no_fork) {
03696 #ifndef HAVE_SBIN_LAUNCHD
03697 if (daemon(1, 0) < 0) {
03698 ast_log(LOG_ERROR, "daemon() failed: %s\n", strerror(errno));
03699 }
03700 ast_mainpid = getpid();
03701
03702 unlink(ast_config_AST_PID);
03703 f = fopen(ast_config_AST_PID, "w");
03704 if (f) {
03705 fprintf(f, "%ld\n", (long)ast_mainpid);
03706 fclose(f);
03707 } else
03708 ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
03709 #else
03710 ast_log(LOG_WARNING, "Mac OS X detected. Use 'launchctl load /Library/LaunchDaemon/org.asterisk.asterisk.plist'.\n");
03711 #endif
03712 }
03713 #endif
03714
03715
03716 if (isroot && ast_opt_high_priority) {
03717 snprintf(canary_filename, sizeof(canary_filename), "%s/alt.asterisk.canary.tweet.tweet.tweet", ast_config_AST_RUN_DIR);
03718
03719
03720 sigaction(SIGPIPE, &ignore_sig_handler, NULL);
03721
03722 canary_pid = fork();
03723 if (canary_pid == 0) {
03724 char canary_binary[128], *lastslash, ppid[12];
03725
03726
03727 signal(SIGCHLD, SIG_DFL);
03728 signal(SIGPIPE, SIG_DFL);
03729
03730 ast_close_fds_above_n(0);
03731 ast_set_priority(0);
03732 snprintf(ppid, sizeof(ppid), "%d", (int) ast_mainpid);
03733
03734 execlp("astcanary", "astcanary", canary_filename, ppid, (char *)NULL);
03735
03736
03737 ast_copy_string(canary_binary, argv[0], sizeof(canary_binary));
03738 if ((lastslash = strrchr(canary_binary, '/'))) {
03739 ast_copy_string(lastslash + 1, "astcanary", sizeof(canary_binary) + canary_binary - (lastslash + 1));
03740 execl(canary_binary, "astcanary", canary_filename, ppid, (char *)NULL);
03741 }
03742
03743
03744 _exit(1);
03745 } else if (canary_pid > 0) {
03746 pthread_t dont_care;
03747 ast_pthread_create_detached(&dont_care, NULL, canary_thread, NULL);
03748 }
03749
03750
03751 ast_register_atexit(canary_exit);
03752 }
03753
03754 if (ast_event_init()) {
03755 printf("%s", term_quit());
03756 exit(1);
03757 }
03758
03759 #ifdef TEST_FRAMEWORK
03760 if (ast_test_init()) {
03761 printf("%s", term_quit());
03762 exit(1);
03763 }
03764 #endif
03765
03766 ast_aoc_cli_init();
03767
03768 ast_makesocket();
03769 sigemptyset(&sigs);
03770 sigaddset(&sigs, SIGHUP);
03771 sigaddset(&sigs, SIGTERM);
03772 sigaddset(&sigs, SIGINT);
03773 sigaddset(&sigs, SIGPIPE);
03774 sigaddset(&sigs, SIGWINCH);
03775 pthread_sigmask(SIG_BLOCK, &sigs, NULL);
03776 sigaction(SIGURG, &urg_handler, NULL);
03777 signal(SIGINT, __quit_handler);
03778 signal(SIGTERM, __quit_handler);
03779 sigaction(SIGHUP, &hup_handler, NULL);
03780 sigaction(SIGPIPE, &ignore_sig_handler, NULL);
03781
03782
03783
03784
03785 srand((unsigned int) getpid() + (unsigned int) time(NULL));
03786 initstate((unsigned int) getpid() * 65536 + (unsigned int) time(NULL), randompool, sizeof(randompool));
03787
03788 if (init_logger()) {
03789 printf("%s", term_quit());
03790 exit(1);
03791 }
03792
03793 threadstorage_init();
03794
03795 astobj2_init();
03796
03797 ast_autoservice_init();
03798
03799 if (ast_timing_init()) {
03800 printf("%s", term_quit());
03801 exit(1);
03802 }
03803
03804 if (ast_ssl_init()) {
03805 printf("%s", term_quit());
03806 exit(1);
03807 }
03808
03809 #ifdef AST_XML_DOCS
03810
03811 ast_xmldoc_load_documentation();
03812 #endif
03813
03814
03815 if (ast_data_init()) {
03816 printf ("%s", term_quit());
03817 exit(1);
03818 }
03819
03820 ast_channels_init();
03821
03822 if ((moduleresult = load_modules(1))) {
03823 printf("%s", term_quit());
03824 exit(moduleresult == -2 ? 2 : 1);
03825 }
03826
03827 if (dnsmgr_init()) {
03828 printf("%s", term_quit());
03829 exit(1);
03830 }
03831
03832 ast_http_init();
03833
03834 if (init_manager()) {
03835 printf("%s", term_quit());
03836 exit(1);
03837 }
03838
03839 if (ast_cdr_engine_init()) {
03840 printf("%s", term_quit());
03841 exit(1);
03842 }
03843
03844 if (ast_cel_engine_init()) {
03845 printf("%s", term_quit());
03846 exit(1);
03847 }
03848
03849 if (ast_device_state_engine_init()) {
03850 printf("%s", term_quit());
03851 exit(1);
03852 }
03853
03854 ast_dsp_init();
03855 ast_udptl_init();
03856
03857 if (ast_image_init()) {
03858 printf("%s", term_quit());
03859 exit(1);
03860 }
03861
03862 if (ast_file_init()) {
03863 printf("%s", term_quit());
03864 exit(1);
03865 }
03866
03867 if (load_pbx()) {
03868 printf("%s", term_quit());
03869 exit(1);
03870 }
03871
03872 if (ast_indications_init()) {
03873 printf("%s", term_quit());
03874 exit(1);
03875 }
03876
03877 if (ast_features_init()) {
03878 printf("%s", term_quit());
03879 exit(1);
03880 }
03881
03882 if (init_framer()) {
03883 printf("%s", term_quit());
03884 exit(1);
03885 }
03886
03887 if (astdb_init()) {
03888 printf("%s", term_quit());
03889 exit(1);
03890 }
03891
03892 if (ast_enum_init()) {
03893 printf("%s", term_quit());
03894 exit(1);
03895 }
03896
03897 if (ast_cc_init()) {
03898 printf("%s", term_quit());
03899 exit(1);
03900 }
03901
03902 if ((moduleresult = load_modules(0))) {
03903 printf("%s", term_quit());
03904 exit(moduleresult == -2 ? 2 : 1);
03905 }
03906
03907
03908 ast_cli_perms_init(0);
03909
03910 ast_stun_init();
03911
03912 dnsmgr_start_refresh();
03913
03914
03915
03916 if (ast_opt_console && !option_verbose)
03917 ast_verbose(" ]\n");
03918 if (option_verbose || ast_opt_console)
03919 ast_verbose("%s", term_color(tmp, "Asterisk Ready.\n", COLOR_BRWHITE, COLOR_BLACK, sizeof(tmp)));
03920 if (ast_opt_no_fork)
03921 consolethread = pthread_self();
03922
03923 if (pipe(sig_alert_pipe))
03924 sig_alert_pipe[0] = sig_alert_pipe[1] = -1;
03925
03926 ast_set_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED);
03927 manager_event(EVENT_FLAG_SYSTEM, "FullyBooted", "Status: Fully Booted\r\n");
03928
03929 ast_process_pending_reloads();
03930
03931 pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
03932
03933 #ifdef __AST_DEBUG_MALLOC
03934 __ast_mm_init();
03935 #endif
03936
03937 ast_lastreloadtime = ast_startuptime = ast_tvnow();
03938 ast_cli_register_multiple(cli_asterisk, ARRAY_LEN(cli_asterisk));
03939
03940 run_startup_commands();
03941
03942 if (ast_opt_console) {
03943
03944
03945 char title[256];
03946
03947 ast_pthread_create_detached(&mon_sig_flags, NULL, monitor_sig_flags, NULL);
03948
03949 set_icon("Asterisk");
03950 snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %ld)", hostname, (long)ast_mainpid);
03951 set_title(title);
03952
03953 el_set(el, EL_GETCFN, ast_el_read_char);
03954
03955 for (;;) {
03956 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
03957 quit_handler(0, SHUTDOWN_FAST, 0);
03958 break;
03959 }
03960 buf = (char *) el_gets(el, &num);
03961
03962 if (!buf && write(1, "", 1) < 0)
03963 goto lostterm;
03964
03965 if (buf) {
03966 if (buf[strlen(buf)-1] == '\n')
03967 buf[strlen(buf)-1] = '\0';
03968
03969 consolehandler((char *)buf);
03970 } else if (ast_opt_remote && (write(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n",
03971 strlen("\nUse EXIT or QUIT to exit the asterisk console\n")) < 0)) {
03972
03973 int fd;
03974 fd = open("/dev/null", O_RDWR);
03975 if (fd > -1) {
03976 dup2(fd, STDOUT_FILENO);
03977 dup2(fd, STDIN_FILENO);
03978 } else
03979 ast_log(LOG_WARNING, "Failed to open /dev/null to recover from dead console. Bad things will happen!\n");
03980 break;
03981 }
03982 }
03983 }
03984
03985 monitor_sig_flags(NULL);
03986
03987 lostterm:
03988 return 0;
03989 }