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