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