00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 #include "asterisk.h"
00067
00068 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 415463 $")
00069
00070 #include "asterisk/_private.h"
00071
00072 #undef sched_setscheduler
00073 #undef setpriority
00074 #include <sys/time.h>
00075 #include <fcntl.h>
00076 #include <signal.h>
00077 #include <sched.h>
00078 #include <sys/un.h>
00079 #include <sys/wait.h>
00080 #include <ctype.h>
00081 #include <sys/resource.h>
00082 #include <grp.h>
00083 #include <pwd.h>
00084 #include <sys/stat.h>
00085 #if defined(HAVE_SYSINFO)
00086 #include <sys/sysinfo.h>
00087 #elif defined(HAVE_SYSCTL)
00088 #include <sys/param.h>
00089 #include <sys/sysctl.h>
00090 #if !defined(__OpenBSD__)
00091 #include <sys/vmmeter.h>
00092 #if defined(__FreeBSD__)
00093 #include <vm/vm_param.h>
00094 #endif
00095 #endif
00096 #if defined(HAVE_SWAPCTL)
00097 #include <sys/swap.h>
00098 #endif
00099 #endif
00100 #include <regex.h>
00101
00102 #if defined(SOLARIS)
00103 int daemon(int, int);
00104 #include <sys/loadavg.h>
00105 #endif
00106
00107 #ifdef linux
00108 #include <sys/prctl.h>
00109 #ifdef HAVE_CAP
00110 #include <sys/capability.h>
00111 #endif
00112 #endif
00113
00114 #include "asterisk/paths.h"
00115 #include "asterisk/network.h"
00116 #include "asterisk/cli.h"
00117 #include "asterisk/channel.h"
00118 #include "asterisk/features.h"
00119 #include "asterisk/ulaw.h"
00120 #include "asterisk/alaw.h"
00121 #include "asterisk/callerid.h"
00122 #include "asterisk/image.h"
00123 #include "asterisk/tdd.h"
00124 #include "asterisk/term.h"
00125 #include "asterisk/manager.h"
00126 #include "asterisk/cdr.h"
00127 #include "asterisk/cel.h"
00128 #include "asterisk/pbx.h"
00129 #include "asterisk/enum.h"
00130 #include "asterisk/http.h"
00131 #include "asterisk/udptl.h"
00132 #include "asterisk/app.h"
00133 #include "asterisk/lock.h"
00134 #include "asterisk/utils.h"
00135 #include "asterisk/file.h"
00136 #include "asterisk/io.h"
00137 #include "editline/histedit.h"
00138 #include "asterisk/config.h"
00139 #include "asterisk/ast_version.h"
00140 #include "asterisk/linkedlists.h"
00141 #include "asterisk/devicestate.h"
00142 #include "asterisk/module.h"
00143 #include "asterisk/dsp.h"
00144 #include "asterisk/buildinfo.h"
00145 #include "asterisk/xmldoc.h"
00146 #include "asterisk/poll-compat.h"
00147 #include "asterisk/ccss.h"
00148 #include "asterisk/test.h"
00149 #include "asterisk/aoc.h"
00150
00151 #include "../defaults.h"
00152
00153 #ifndef AF_LOCAL
00154 #define AF_LOCAL AF_UNIX
00155 #define PF_LOCAL PF_UNIX
00156 #endif
00157
00158 #define AST_MAX_CONNECTS 128
00159 #define NUM_MSGS 64
00160
00161
00162 #define WELCOME_MESSAGE \
00163 ast_verbose("Asterisk %s, Copyright (C) 1999 - 2013 Digium, Inc. and others.\n" \
00164 "Created by Mark Spencer <markster@digium.com>\n" \
00165 "Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n" \
00166 "This is free software, with components licensed under the GNU General Public\n" \
00167 "License version 2 and other licenses; you are welcome to redistribute it under\n" \
00168 "certain conditions. Type 'core show license' for details.\n" \
00169 "=========================================================================\n", ast_get_version()) \
00170
00171
00172
00173
00174
00175
00176
00177
00178 struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
00179 struct ast_flags ast_compat = { 0 };
00180
00181 int option_verbose;
00182 int option_debug;
00183 double option_maxload;
00184 int option_maxcalls;
00185 int option_maxfiles;
00186 #if defined(HAVE_SYSINFO)
00187 long option_minmemfree;
00188 #endif
00189
00190
00191
00192 struct ast_eid ast_eid_default;
00193
00194
00195 char record_cache_dir[AST_CACHE_DIR_LEN] = DEFAULT_TMP_DIR;
00196
00197 static int ast_socket = -1;
00198 static int ast_consock = -1;
00199 pid_t ast_mainpid;
00200 struct console {
00201 int fd;
00202 int p[2];
00203 pthread_t t;
00204 int mute;
00205 int uid;
00206 int gid;
00207 int levels[NUMLOGLEVELS];
00208 };
00209
00210 struct ast_atexit {
00211 void (*func)(void);
00212 int is_cleanup;
00213 AST_LIST_ENTRY(ast_atexit) list;
00214 };
00215
00216 static AST_LIST_HEAD_STATIC(atexits, ast_atexit);
00217
00218 struct timeval ast_startuptime;
00219 struct timeval ast_lastreloadtime;
00220
00221 static History *el_hist;
00222 static EditLine *el;
00223 static char *remotehostname;
00224
00225 struct console consoles[AST_MAX_CONNECTS];
00226
00227 char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
00228
00229 static int ast_el_add_history(char *);
00230 static int ast_el_read_history(char *);
00231 static int ast_el_write_history(char *);
00232
00233 struct _cfg_paths {
00234 char config_dir[PATH_MAX];
00235 char module_dir[PATH_MAX];
00236 char spool_dir[PATH_MAX];
00237 char monitor_dir[PATH_MAX];
00238 char var_dir[PATH_MAX];
00239 char data_dir[PATH_MAX];
00240 char log_dir[PATH_MAX];
00241 char agi_dir[PATH_MAX];
00242 char run_dir[PATH_MAX];
00243 char key_dir[PATH_MAX];
00244
00245 char config_file[PATH_MAX];
00246 char db_path[PATH_MAX];
00247 char pid_path[PATH_MAX];
00248 char socket_path[PATH_MAX];
00249 char run_user[PATH_MAX];
00250 char run_group[PATH_MAX];
00251 char system_name[128];
00252 };
00253
00254 static struct _cfg_paths cfg_paths;
00255
00256 const char *ast_config_AST_CONFIG_DIR = cfg_paths.config_dir;
00257 const char *ast_config_AST_CONFIG_FILE = cfg_paths.config_file;
00258 const char *ast_config_AST_MODULE_DIR = cfg_paths.module_dir;
00259 const char *ast_config_AST_SPOOL_DIR = cfg_paths.spool_dir;
00260 const char *ast_config_AST_MONITOR_DIR = cfg_paths.monitor_dir;
00261 const char *ast_config_AST_VAR_DIR = cfg_paths.var_dir;
00262 const char *ast_config_AST_DATA_DIR = cfg_paths.data_dir;
00263 const char *ast_config_AST_LOG_DIR = cfg_paths.log_dir;
00264 const char *ast_config_AST_AGI_DIR = cfg_paths.agi_dir;
00265 const char *ast_config_AST_KEY_DIR = cfg_paths.key_dir;
00266 const char *ast_config_AST_RUN_DIR = cfg_paths.run_dir;
00267
00268 const char *ast_config_AST_DB = cfg_paths.db_path;
00269 const char *ast_config_AST_PID = cfg_paths.pid_path;
00270 const char *ast_config_AST_SOCKET = cfg_paths.socket_path;
00271 const char *ast_config_AST_RUN_USER = cfg_paths.run_user;
00272 const char *ast_config_AST_RUN_GROUP = cfg_paths.run_group;
00273 const char *ast_config_AST_SYSTEM_NAME = cfg_paths.system_name;
00274
00275 static char ast_config_AST_CTL_PERMISSIONS[PATH_MAX];
00276 static char ast_config_AST_CTL_OWNER[PATH_MAX] = "\0";
00277 static char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0";
00278 static char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl";
00279
00280 extern unsigned int ast_FD_SETSIZE;
00281
00282 static char *_argv[256];
00283 typedef enum {
00284 NOT_SHUTTING_DOWN = -2,
00285 SHUTTING_DOWN = -1,
00286
00287 SHUTDOWN_FAST,
00288 SHUTDOWN_NORMAL,
00289 SHUTDOWN_NICE,
00290 SHUTDOWN_REALLY_NICE
00291 } shutdown_nice_t;
00292 static shutdown_nice_t shuttingdown = NOT_SHUTTING_DOWN;
00293 static int restartnow;
00294 static pthread_t consolethread = AST_PTHREADT_NULL;
00295 static pthread_t mon_sig_flags;
00296 static int canary_pid = 0;
00297 static char canary_filename[128];
00298 static int multi_thread_safe;
00299
00300 static char randompool[256];
00301
00302 static int sig_alert_pipe[2] = { -1, -1 };
00303 static struct {
00304 unsigned int need_reload:1;
00305 unsigned int need_quit:1;
00306 unsigned int need_quit_handler:1;
00307 } sig_flags;
00308
00309 #if !defined(LOW_MEMORY)
00310 struct file_version {
00311 AST_RWLIST_ENTRY(file_version) list;
00312 const char *file;
00313 char *version;
00314 };
00315
00316 static AST_RWLIST_HEAD_STATIC(file_versions, file_version);
00317
00318 void ast_register_file_version(const char *file, const char *version)
00319 {
00320 struct file_version *new;
00321 char *work;
00322 size_t version_length;
00323
00324 work = ast_strdupa(version);
00325 work = ast_strip(ast_strip_quoted(work, "$", "$"));
00326 version_length = strlen(work) + 1;
00327
00328 if (!(new = ast_calloc(1, sizeof(*new) + version_length)))
00329 return;
00330
00331 new->file = file;
00332 new->version = (char *) new + sizeof(*new);
00333 memcpy(new->version, work, version_length);
00334 AST_RWLIST_WRLOCK(&file_versions);
00335 AST_RWLIST_INSERT_HEAD(&file_versions, new, list);
00336 AST_RWLIST_UNLOCK(&file_versions);
00337 }
00338
00339 void ast_unregister_file_version(const char *file)
00340 {
00341 struct file_version *find;
00342
00343 AST_RWLIST_WRLOCK(&file_versions);
00344 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) {
00345 if (!strcasecmp(find->file, file)) {
00346 AST_RWLIST_REMOVE_CURRENT(list);
00347 break;
00348 }
00349 }
00350 AST_RWLIST_TRAVERSE_SAFE_END;
00351 AST_RWLIST_UNLOCK(&file_versions);
00352
00353 if (find)
00354 ast_free(find);
00355 }
00356
00357 char *ast_complete_source_filename(const char *partial, int n)
00358 {
00359 struct file_version *find;
00360 size_t len = strlen(partial);
00361 int count = 0;
00362 char *res = NULL;
00363
00364 AST_RWLIST_RDLOCK(&file_versions);
00365 AST_RWLIST_TRAVERSE(&file_versions, find, list) {
00366 if (!strncasecmp(find->file, partial, len) && ++count > n) {
00367 res = ast_strdup(find->file);
00368 break;
00369 }
00370 }
00371 AST_RWLIST_UNLOCK(&file_versions);
00372 return res;
00373 }
00374
00375
00376 const char *ast_file_version_find(const char *file)
00377 {
00378 struct file_version *iterator;
00379
00380 AST_RWLIST_WRLOCK(&file_versions);
00381 AST_RWLIST_TRAVERSE(&file_versions, iterator, list) {
00382 if (!strcasecmp(iterator->file, file))
00383 break;
00384 }
00385 AST_RWLIST_UNLOCK(&file_versions);
00386 if (iterator)
00387 return iterator->version;
00388 return NULL;
00389 }
00390
00391
00392
00393 struct thread_list_t {
00394 AST_RWLIST_ENTRY(thread_list_t) list;
00395 char *name;
00396 pthread_t id;
00397 };
00398
00399 static AST_RWLIST_HEAD_STATIC(thread_list, thread_list_t);
00400
00401 void ast_register_thread(char *name)
00402 {
00403 struct thread_list_t *new = ast_calloc(1, sizeof(*new));
00404
00405 if (!new)
00406 return;
00407
00408 ast_assert(multi_thread_safe);
00409 new->id = pthread_self();
00410 new->name = name;
00411 AST_RWLIST_WRLOCK(&thread_list);
00412 AST_RWLIST_INSERT_HEAD(&thread_list, new, list);
00413 AST_RWLIST_UNLOCK(&thread_list);
00414 }
00415
00416 void ast_unregister_thread(void *id)
00417 {
00418 struct thread_list_t *x;
00419
00420 AST_RWLIST_WRLOCK(&thread_list);
00421 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&thread_list, x, list) {
00422 if ((void *) x->id == id) {
00423 AST_RWLIST_REMOVE_CURRENT(list);
00424 break;
00425 }
00426 }
00427 AST_RWLIST_TRAVERSE_SAFE_END;
00428 AST_RWLIST_UNLOCK(&thread_list);
00429 if (x) {
00430 ast_free(x->name);
00431 ast_free(x);
00432 }
00433 }
00434
00435
00436 static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
00437 {
00438 char buf[BUFSIZ];
00439 struct ast_tm tm;
00440 char eid_str[128];
00441
00442 switch (cmd) {
00443 case CLI_INIT:
00444 e->command = "core show settings";
00445 e->usage = "Usage: core show settings\n"
00446 " Show core misc settings";
00447 return NULL;
00448 case CLI_GENERATE:
00449 return NULL;
00450 }
00451
00452 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
00453
00454 ast_cli(a->fd, "\nPBX Core settings\n");
00455 ast_cli(a->fd, "-----------------\n");
00456 ast_cli(a->fd, " Version: %s\n", ast_get_version());
00457 ast_cli(a->fd, " Build Options: %s\n", S_OR(AST_BUILDOPTS, "(none)"));
00458 if (option_maxcalls)
00459 ast_cli(a->fd, " Maximum calls: %d (Current %d)\n", option_maxcalls, ast_active_channels());
00460 else
00461 ast_cli(a->fd, " Maximum calls: Not set\n");
00462 if (option_maxfiles)
00463 ast_cli(a->fd, " Maximum open file handles: %d\n", option_maxfiles);
00464 else
00465 ast_cli(a->fd, " Maximum open file handles: Not set\n");
00466 ast_cli(a->fd, " Verbosity: %d\n", option_verbose);
00467 ast_cli(a->fd, " Debug level: %d\n", option_debug);
00468 ast_cli(a->fd, " Maximum load average: %lf\n", option_maxload);
00469 #if defined(HAVE_SYSINFO)
00470 ast_cli(a->fd, " Minimum free memory: %ld MB\n", option_minmemfree);
00471 #endif
00472 if (ast_localtime(&ast_startuptime, &tm, NULL)) {
00473 ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
00474 ast_cli(a->fd, " Startup time: %s\n", buf);
00475 }
00476 if (ast_localtime(&ast_lastreloadtime, &tm, NULL)) {
00477 ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
00478 ast_cli(a->fd, " Last reload time: %s\n", buf);
00479 }
00480 ast_cli(a->fd, " System: %s/%s built by %s on %s %s\n", ast_build_os, ast_build_kernel, ast_build_user, ast_build_machine, ast_build_date);
00481 ast_cli(a->fd, " System name: %s\n", ast_config_AST_SYSTEM_NAME);
00482 ast_cli(a->fd, " Entity ID: %s\n", eid_str);
00483 ast_cli(a->fd, " Default language: %s\n", defaultlanguage);
00484 ast_cli(a->fd, " Language prefix: %s\n", ast_language_is_prefix ? "Enabled" : "Disabled");
00485 ast_cli(a->fd, " User name and group: %s/%s\n", ast_config_AST_RUN_USER, ast_config_AST_RUN_GROUP);
00486 ast_cli(a->fd, " Executable includes: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) ? "Enabled" : "Disabled");
00487 ast_cli(a->fd, " Transcode via SLIN: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN) ? "Enabled" : "Disabled");
00488 ast_cli(a->fd, " Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) ? "Enabled" : "Disabled");
00489 ast_cli(a->fd, " Generic PLC: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled");
00490
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: %ld 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: %d 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(int run_cleanups)
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 && (!ae->is_cleanup || run_cleanups)) {
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 static int register_atexit(void (*func)(void), int is_cleanup)
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 ae->is_cleanup = is_cleanup;
00986
00987 AST_LIST_LOCK(&atexits);
00988 __ast_unregister_atexit(func);
00989 AST_LIST_INSERT_HEAD(&atexits, ae, list);
00990 AST_LIST_UNLOCK(&atexits);
00991
00992 return 0;
00993 }
00994
00995 int ast_register_atexit(void (*func)(void))
00996 {
00997 return register_atexit(func, 0);
00998 }
00999
01000 int ast_register_cleanup(void (*func)(void))
01001 {
01002 return register_atexit(func, 1);
01003 }
01004
01005 void ast_unregister_atexit(void (*func)(void))
01006 {
01007 AST_LIST_LOCK(&atexits);
01008 __ast_unregister_atexit(func);
01009 AST_LIST_UNLOCK(&atexits);
01010 }
01011
01012
01013 static int fdsend(int fd, const char *s)
01014 {
01015 return write(fd, s, strlen(s) + 1);
01016 }
01017
01018
01019 static int fdprint(int fd, const char *s)
01020 {
01021 return write(fd, s, strlen(s));
01022 }
01023
01024
01025 static void _null_sig_handler(int sig)
01026 {
01027 }
01028
01029 static struct sigaction null_sig_handler = {
01030 .sa_handler = _null_sig_handler,
01031 .sa_flags = SA_RESTART,
01032 };
01033
01034 static struct sigaction ignore_sig_handler = {
01035 .sa_handler = SIG_IGN,
01036 };
01037
01038 AST_MUTEX_DEFINE_STATIC(safe_system_lock);
01039
01040
01041 static unsigned int safe_system_level = 0;
01042 static struct sigaction safe_system_prev_handler;
01043
01044 void ast_replace_sigchld(void)
01045 {
01046 unsigned int level;
01047
01048 ast_mutex_lock(&safe_system_lock);
01049 level = safe_system_level++;
01050
01051
01052 if (level == 0) {
01053 sigaction(SIGCHLD, &null_sig_handler, &safe_system_prev_handler);
01054 }
01055
01056 ast_mutex_unlock(&safe_system_lock);
01057 }
01058
01059 void ast_unreplace_sigchld(void)
01060 {
01061 unsigned int level;
01062
01063 ast_mutex_lock(&safe_system_lock);
01064 level = --safe_system_level;
01065
01066
01067 if (level == 0) {
01068 sigaction(SIGCHLD, &safe_system_prev_handler, NULL);
01069 }
01070
01071 ast_mutex_unlock(&safe_system_lock);
01072 }
01073
01074 int ast_safe_system(const char *s)
01075 {
01076 pid_t pid;
01077 int res;
01078 struct rusage rusage;
01079 int status;
01080
01081 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
01082 ast_replace_sigchld();
01083
01084 #ifdef HAVE_WORKING_FORK
01085 pid = fork();
01086 #else
01087 pid = vfork();
01088 #endif
01089
01090 if (pid == 0) {
01091 #ifdef HAVE_CAP
01092 cap_t cap = cap_from_text("cap_net_admin-eip");
01093
01094 if (cap_set_proc(cap)) {
01095
01096 ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
01097 }
01098 cap_free(cap);
01099 #endif
01100 #ifdef HAVE_WORKING_FORK
01101 if (ast_opt_high_priority)
01102 ast_set_priority(0);
01103
01104 ast_close_fds_above_n(STDERR_FILENO);
01105 #endif
01106 execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
01107 _exit(1);
01108 } else if (pid > 0) {
01109 for (;;) {
01110 res = wait4(pid, &status, 0, &rusage);
01111 if (res > -1) {
01112 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
01113 break;
01114 } else if (errno != EINTR)
01115 break;
01116 }
01117 } else {
01118 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
01119 res = -1;
01120 }
01121
01122 ast_unreplace_sigchld();
01123 #else
01124 res = -1;
01125 #endif
01126
01127 return res;
01128 }
01129
01130
01131
01132
01133 void ast_console_toggle_loglevel(int fd, int level, int state)
01134 {
01135 int x;
01136
01137 if (level >= NUMLOGLEVELS) {
01138 level = NUMLOGLEVELS - 1;
01139 }
01140
01141 for (x = 0;x < AST_MAX_CONNECTS; x++) {
01142 if (fd == consoles[x].fd) {
01143
01144
01145
01146
01147 consoles[x].levels[level] = state ? 0 : 1;
01148 return;
01149 }
01150 }
01151 }
01152
01153
01154
01155
01156 void ast_console_toggle_mute(int fd, int silent)
01157 {
01158 int x;
01159 for (x = 0;x < AST_MAX_CONNECTS; x++) {
01160 if (fd == consoles[x].fd) {
01161 if (consoles[x].mute) {
01162 consoles[x].mute = 0;
01163 if (!silent)
01164 ast_cli(fd, "Console is not muted anymore.\n");
01165 } else {
01166 consoles[x].mute = 1;
01167 if (!silent)
01168 ast_cli(fd, "Console is muted.\n");
01169 }
01170 return;
01171 }
01172 }
01173 ast_cli(fd, "Couldn't find remote console.\n");
01174 }
01175
01176
01177
01178
01179 static void ast_network_puts_mutable(const char *string, int level)
01180 {
01181 int x;
01182 for (x = 0;x < AST_MAX_CONNECTS; x++) {
01183 if (consoles[x].mute)
01184 continue;
01185 if (consoles[x].fd > -1) {
01186 if (!consoles[x].levels[level])
01187 fdprint(consoles[x].p[1], string);
01188 }
01189 }
01190 }
01191
01192
01193
01194
01195
01196 void ast_console_puts_mutable(const char *string, int level)
01197 {
01198 fputs(string, stdout);
01199 fflush(stdout);
01200 ast_network_puts_mutable(string, level);
01201 }
01202
01203
01204
01205
01206 static void ast_network_puts(const char *string)
01207 {
01208 int x;
01209 for (x = 0; x < AST_MAX_CONNECTS; x++) {
01210 if (consoles[x].fd > -1)
01211 fdprint(consoles[x].p[1], string);
01212 }
01213 }
01214
01215
01216
01217
01218
01219 void ast_console_puts(const char *string)
01220 {
01221 fputs(string, stdout);
01222 fflush(stdout);
01223 ast_network_puts(string);
01224 }
01225
01226 static void network_verboser(const char *s)
01227 {
01228 ast_network_puts_mutable(s, __LOG_VERBOSE);
01229 }
01230
01231 static pthread_t lthread;
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243 static int read_credentials(int fd, char *buffer, size_t size, struct console *con)
01244 {
01245 #if defined(SO_PEERCRED)
01246 #ifdef HAVE_STRUCT_SOCKPEERCRED_UID
01247 #define HAVE_STRUCT_UCRED_UID
01248 struct sockpeercred cred;
01249 #else
01250 struct ucred cred;
01251 #endif
01252 socklen_t len = sizeof(cred);
01253 #endif
01254 #if defined(HAVE_GETPEEREID)
01255 uid_t uid;
01256 gid_t gid;
01257 #else
01258 int uid, gid;
01259 #endif
01260 int result;
01261
01262 result = read(fd, buffer, size);
01263 if (result < 0) {
01264 return result;
01265 }
01266
01267 #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID))
01268 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len)) {
01269 return result;
01270 }
01271 #if defined(HAVE_STRUCT_UCRED_UID)
01272 uid = cred.uid;
01273 gid = cred.gid;
01274 #else
01275 uid = cred.cr_uid;
01276 gid = cred.cr_gid;
01277 #endif
01278
01279 #elif defined(HAVE_GETPEEREID)
01280 if (getpeereid(fd, &uid, &gid)) {
01281 return result;
01282 }
01283 #else
01284 return result;
01285 #endif
01286 con->uid = uid;
01287 con->gid = gid;
01288
01289 return result;
01290 }
01291
01292 static void *netconsole(void *vconsole)
01293 {
01294 struct console *con = vconsole;
01295 char hostname[MAXHOSTNAMELEN] = "";
01296 char inbuf[512];
01297 char outbuf[512];
01298 const char * const end_buf = inbuf + sizeof(inbuf);
01299 char *start_read = inbuf;
01300 int res;
01301 struct pollfd fds[2];
01302
01303 if (gethostname(hostname, sizeof(hostname)-1))
01304 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
01305 snprintf(outbuf, sizeof(outbuf), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ast_get_version());
01306 fdprint(con->fd, outbuf);
01307 for (;;) {
01308 fds[0].fd = con->fd;
01309 fds[0].events = POLLIN;
01310 fds[0].revents = 0;
01311 fds[1].fd = con->p[0];
01312 fds[1].events = POLLIN;
01313 fds[1].revents = 0;
01314
01315 res = ast_poll(fds, 2, -1);
01316 if (res < 0) {
01317 if (errno != EINTR)
01318 ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
01319 continue;
01320 }
01321 if (fds[0].revents) {
01322 int cmds_read, bytes_read;
01323 if ((bytes_read = read_credentials(con->fd, start_read, end_buf - start_read, con)) < 1) {
01324 break;
01325 }
01326
01327 if (strncmp(inbuf, "cli quit after ", 15) == 0) {
01328 ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read - 15, inbuf + 15);
01329 break;
01330 }
01331
01332
01333 if (!(cmds_read = ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read + start_read - inbuf, inbuf))) {
01334
01335
01336 if (start_read + bytes_read < end_buf) {
01337 start_read += bytes_read;
01338 } else {
01339 ast_log(LOG_ERROR, "Command too long! Skipping\n");
01340 start_read = inbuf;
01341 }
01342 continue;
01343 }
01344 if (start_read[bytes_read - 1] == '\0') {
01345
01346 start_read = inbuf;
01347 continue;
01348 }
01349
01350
01351
01352 while (cmds_read-- && (start_read = strchr(start_read, '\0'))) {
01353 start_read++;
01354 }
01355 memmove(inbuf, start_read, end_buf - start_read);
01356 start_read = end_buf - start_read + inbuf;
01357 }
01358 if (fds[1].revents) {
01359 res = read_credentials(con->p[0], outbuf, sizeof(outbuf), con);
01360 if (res < 1) {
01361 ast_log(LOG_ERROR, "read returned %d\n", res);
01362 break;
01363 }
01364 res = write(con->fd, outbuf, res);
01365 if (res < 1)
01366 break;
01367 }
01368 }
01369 if (!ast_opt_hide_connect) {
01370 ast_verb(3, "Remote UNIX connection disconnected\n");
01371 }
01372 close(con->fd);
01373 close(con->p[0]);
01374 close(con->p[1]);
01375 con->fd = -1;
01376
01377 return NULL;
01378 }
01379
01380 static void *listener(void *unused)
01381 {
01382 struct sockaddr_un sunaddr;
01383 int s;
01384 socklen_t len;
01385 int x;
01386 int flags;
01387 struct pollfd fds[1];
01388 for (;;) {
01389 if (ast_socket < 0)
01390 return NULL;
01391 fds[0].fd = ast_socket;
01392 fds[0].events = POLLIN;
01393 s = ast_poll(fds, 1, -1);
01394 pthread_testcancel();
01395 if (s < 0) {
01396 if (errno != EINTR)
01397 ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
01398 continue;
01399 }
01400 len = sizeof(sunaddr);
01401 s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
01402 if (s < 0) {
01403 if (errno != EINTR)
01404 ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
01405 } else {
01406 #if !defined(SO_PASSCRED)
01407 {
01408 #else
01409 int sckopt = 1;
01410
01411 if (setsockopt(s, SOL_SOCKET, SO_PASSCRED, &sckopt, sizeof(sckopt)) < 0) {
01412 ast_log(LOG_WARNING, "Unable to turn on socket credentials passing\n");
01413 } else {
01414 #endif
01415 for (x = 0; x < AST_MAX_CONNECTS; x++) {
01416 if (consoles[x].fd >= 0) {
01417 continue;
01418 }
01419 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
01420 ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
01421 consoles[x].fd = -1;
01422 fdprint(s, "Server failed to create pipe\n");
01423 close(s);
01424 break;
01425 }
01426 flags = fcntl(consoles[x].p[1], F_GETFL);
01427 fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
01428 consoles[x].fd = s;
01429 consoles[x].mute = 1;
01430
01431
01432 consoles[x].uid = -2;
01433 consoles[x].gid = -2;
01434 if (ast_pthread_create_detached_background(&consoles[x].t, NULL, netconsole, &consoles[x])) {
01435 ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
01436 close(consoles[x].p[0]);
01437 close(consoles[x].p[1]);
01438 consoles[x].fd = -1;
01439 fdprint(s, "Server failed to spawn thread\n");
01440 close(s);
01441 }
01442 break;
01443 }
01444 if (x >= AST_MAX_CONNECTS) {
01445 fdprint(s, "No more connections allowed\n");
01446 ast_log(LOG_WARNING, "No more connections allowed\n");
01447 close(s);
01448 } else if ((consoles[x].fd > -1) && (!ast_opt_hide_connect)) {
01449 ast_verb(3, "Remote UNIX connection\n");
01450 }
01451 }
01452 }
01453 }
01454 return NULL;
01455 }
01456
01457 static int ast_makesocket(void)
01458 {
01459 struct sockaddr_un sunaddr;
01460 int res;
01461 int x;
01462 uid_t uid = -1;
01463 gid_t gid = -1;
01464
01465 for (x = 0; x < AST_MAX_CONNECTS; x++)
01466 consoles[x].fd = -1;
01467 unlink(ast_config_AST_SOCKET);
01468 ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
01469 if (ast_socket < 0) {
01470 ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
01471 return -1;
01472 }
01473 memset(&sunaddr, 0, sizeof(sunaddr));
01474 sunaddr.sun_family = AF_LOCAL;
01475 ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
01476 res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
01477 if (res) {
01478 ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
01479 close(ast_socket);
01480 ast_socket = -1;
01481 return -1;
01482 }
01483 res = listen(ast_socket, 2);
01484 if (res < 0) {
01485 ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
01486 close(ast_socket);
01487 ast_socket = -1;
01488 return -1;
01489 }
01490 if (ast_register_verbose(network_verboser)) {
01491 ast_log(LOG_WARNING, "Unable to register network verboser?\n");
01492 }
01493
01494 if (ast_pthread_create_background(<hread, NULL, listener, NULL)) {
01495 ast_log(LOG_WARNING, "Unable to create listener thread.\n");
01496 close(ast_socket);
01497 return -1;
01498 }
01499
01500 if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {
01501 struct passwd *pw;
01502 if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL)
01503 ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
01504 else
01505 uid = pw->pw_uid;
01506 }
01507
01508 if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) {
01509 struct group *grp;
01510 if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL)
01511 ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
01512 else
01513 gid = grp->gr_gid;
01514 }
01515
01516 if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
01517 ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
01518
01519 if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) {
01520 unsigned int p1;
01521 mode_t p;
01522 sscanf(ast_config_AST_CTL_PERMISSIONS, "%30o", &p1);
01523 p = p1;
01524 if ((chmod(ast_config_AST_SOCKET, p)) < 0)
01525 ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
01526 }
01527
01528 return 0;
01529 }
01530
01531 static int ast_tryconnect(void)
01532 {
01533 struct sockaddr_un sunaddr;
01534 int res;
01535 ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
01536 if (ast_consock < 0) {
01537 fprintf(stderr, "Unable to create socket: %s\n", strerror(errno));
01538 return 0;
01539 }
01540 memset(&sunaddr, 0, sizeof(sunaddr));
01541 sunaddr.sun_family = AF_LOCAL;
01542 ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
01543 res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
01544 if (res) {
01545 close(ast_consock);
01546 ast_consock = -1;
01547 return 0;
01548 } else
01549 return 1;
01550 }
01551
01552
01553
01554
01555
01556
01557
01558 static void _urg_handler(int num)
01559 {
01560 return;
01561 }
01562
01563 static struct sigaction urg_handler = {
01564 .sa_handler = _urg_handler,
01565 .sa_flags = SA_RESTART,
01566 };
01567
01568 static void _hup_handler(int num)
01569 {
01570 int a = 0, save_errno = errno;
01571 if (option_verbose > 1)
01572 printf("Received HUP signal -- Reloading configs\n");
01573 if (restartnow)
01574 execvp(_argv[0], _argv);
01575 sig_flags.need_reload = 1;
01576 if (sig_alert_pipe[1] != -1) {
01577 if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
01578 fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
01579 }
01580 }
01581 errno = save_errno;
01582 }
01583
01584 static struct sigaction hup_handler = {
01585 .sa_handler = _hup_handler,
01586 .sa_flags = SA_RESTART,
01587 };
01588
01589 static void _child_handler(int sig)
01590 {
01591
01592 int n, status, save_errno = errno;
01593
01594
01595
01596
01597 for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++)
01598 ;
01599 if (n == 0 && option_debug)
01600 printf("Huh? Child handler, but nobody there?\n");
01601 errno = save_errno;
01602 }
01603
01604 static struct sigaction child_handler = {
01605 .sa_handler = _child_handler,
01606 .sa_flags = SA_RESTART,
01607 };
01608
01609
01610 static void set_ulimit(int value)
01611 {
01612 struct rlimit l = {0, 0};
01613
01614 if (value <= 0) {
01615 ast_log(LOG_WARNING, "Unable to change max files open to invalid value %i\n",value);
01616 return;
01617 }
01618
01619 l.rlim_cur = value;
01620 l.rlim_max = value;
01621
01622 if (setrlimit(RLIMIT_NOFILE, &l)) {
01623 ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n",strerror(errno));
01624 return;
01625 }
01626
01627 ast_log(LOG_NOTICE, "Setting max files open to %d\n",value);
01628
01629 return;
01630 }
01631
01632
01633 static void set_title(char *text)
01634 {
01635 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
01636 fprintf(stdout, "\033]2;%s\007", text);
01637 }
01638
01639 static void set_icon(char *text)
01640 {
01641 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
01642 fprintf(stdout, "\033]1;%s\007", text);
01643 }
01644
01645
01646
01647 int ast_set_priority(int pri)
01648 {
01649 struct sched_param sched;
01650 memset(&sched, 0, sizeof(sched));
01651 #ifdef __linux__
01652 if (pri) {
01653 sched.sched_priority = 10;
01654 if (sched_setscheduler(0, SCHED_RR, &sched)) {
01655 ast_log(LOG_WARNING, "Unable to set high priority\n");
01656 return -1;
01657 } else
01658 if (option_verbose)
01659 ast_verbose("Set to realtime thread\n");
01660 } else {
01661 sched.sched_priority = 0;
01662
01663 sched_setscheduler(0, SCHED_OTHER, &sched);
01664 }
01665 #else
01666 if (pri) {
01667 if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
01668 ast_log(LOG_WARNING, "Unable to set high priority\n");
01669 return -1;
01670 } else
01671 if (option_verbose)
01672 ast_verbose("Set to high priority\n");
01673 } else {
01674
01675 setpriority(PRIO_PROCESS, 0, 0);
01676 }
01677 #endif
01678 return 0;
01679 }
01680
01681 static int can_safely_quit(shutdown_nice_t niceness, int restart);
01682 static void really_quit(int num, shutdown_nice_t niceness, int restart);
01683
01684 static void quit_handler(int num, shutdown_nice_t niceness, int restart)
01685 {
01686 if (can_safely_quit(niceness, restart)) {
01687 really_quit(num, niceness, restart);
01688
01689 }
01690
01691 }
01692
01693 static int can_safely_quit(shutdown_nice_t niceness, int restart)
01694 {
01695
01696 ast_mutex_lock(&safe_system_lock);
01697 if (shuttingdown != NOT_SHUTTING_DOWN && niceness >= shuttingdown) {
01698
01699 ast_mutex_unlock(&safe_system_lock);
01700 ast_verbose("Ignoring asterisk %s request, already in progress.\n", restart ? "restart" : "shutdown");
01701 return 0;
01702 }
01703 shuttingdown = niceness;
01704 ast_mutex_unlock(&safe_system_lock);
01705
01706
01707
01708
01709 ast_cdr_engine_term();
01710
01711 if (niceness == SHUTDOWN_NORMAL) {
01712 time_t s, e;
01713
01714 ast_begin_shutdown(1);
01715 if (option_verbose && ast_opt_console) {
01716 ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
01717 }
01718 time(&s);
01719 for (;;) {
01720 time(&e);
01721
01722 if ((e - s) > 15 || !ast_undestroyed_channels() || shuttingdown != niceness) {
01723 break;
01724 }
01725
01726 usleep(100000);
01727 }
01728 } else if (niceness >= SHUTDOWN_NICE) {
01729 if (niceness != SHUTDOWN_REALLY_NICE) {
01730 ast_begin_shutdown(0);
01731 }
01732 if (option_verbose && ast_opt_console) {
01733 ast_verbose("Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
01734 }
01735 for (;;) {
01736 if (!ast_undestroyed_channels() || shuttingdown != niceness) {
01737 break;
01738 }
01739 sleep(1);
01740 }
01741 }
01742
01743
01744
01745 ast_mutex_lock(&safe_system_lock);
01746 if (shuttingdown != niceness) {
01747 if (shuttingdown == NOT_SHUTTING_DOWN && option_verbose && ast_opt_console) {
01748 ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
01749 }
01750 ast_mutex_unlock(&safe_system_lock);
01751 return 0;
01752 }
01753 shuttingdown = SHUTTING_DOWN;
01754 ast_mutex_unlock(&safe_system_lock);
01755
01756 return 1;
01757 }
01758
01759
01760 static void really_quit(int num, shutdown_nice_t niceness, int restart)
01761 {
01762 int active_channels;
01763 int run_cleanups = niceness >= SHUTDOWN_NICE;
01764
01765 if (run_cleanups) {
01766 ast_module_shutdown();
01767 }
01768
01769 if (ast_opt_console || (ast_opt_remote && !ast_opt_exec)) {
01770 char filename[80] = "";
01771 if (getenv("HOME")) {
01772 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
01773 }
01774 if (!ast_strlen_zero(filename)) {
01775 ast_el_write_history(filename);
01776 }
01777 if (consolethread == AST_PTHREADT_NULL || consolethread == pthread_self()) {
01778
01779 if (el != NULL) {
01780 el_end(el);
01781 }
01782 if (el_hist != NULL) {
01783 history_end(el_hist);
01784 }
01785 } else if (mon_sig_flags == pthread_self()) {
01786 if (consolethread != AST_PTHREADT_NULL) {
01787 pthread_kill(consolethread, SIGURG);
01788 }
01789 }
01790 }
01791 active_channels = ast_active_channels();
01792
01793
01794
01795
01796 manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\n"
01797 "Restart: %s\r\n",
01798 active_channels ? "Uncleanly" : "Cleanly",
01799 restart ? "True" : "False");
01800 if (option_verbose && ast_opt_console) {
01801 ast_verbose("Asterisk %s ending (%d).\n",
01802 active_channels ? "uncleanly" : "cleanly", num);
01803 }
01804
01805 if (option_verbose)
01806 ast_verbose("Executing last minute cleanups\n");
01807 ast_run_atexits(run_cleanups);
01808
01809 ast_debug(1, "Asterisk ending (%d).\n", num);
01810 if (ast_socket > -1) {
01811 pthread_cancel(lthread);
01812 close(ast_socket);
01813 ast_socket = -1;
01814 unlink(ast_config_AST_SOCKET);
01815 pthread_kill(lthread, SIGURG);
01816 pthread_join(lthread, NULL);
01817 }
01818 if (ast_consock > -1)
01819 close(ast_consock);
01820 if (!ast_opt_remote)
01821 unlink(ast_config_AST_PID);
01822 if (sig_alert_pipe[0])
01823 close(sig_alert_pipe[0]);
01824 if (sig_alert_pipe[1])
01825 close(sig_alert_pipe[1]);
01826 printf("%s", term_quit());
01827 if (restart) {
01828 int i;
01829 if (option_verbose || ast_opt_console)
01830 ast_verbose("Preparing for Asterisk restart...\n");
01831
01832 for (i = 3; i < 32768; i++) {
01833 fcntl(i, F_SETFD, FD_CLOEXEC);
01834 }
01835 if (option_verbose || ast_opt_console)
01836 ast_verbose("Asterisk is now restarting...\n");
01837 restartnow = 1;
01838
01839
01840 close_logger();
01841 clean_time_zones();
01842
01843
01844
01845 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
01846 pthread_kill(consolethread, SIGHUP);
01847
01848 sleep(2);
01849 } else
01850 execvp(_argv[0], _argv);
01851
01852 } else {
01853
01854 close_logger();
01855 clean_time_zones();
01856 }
01857
01858 exit(0);
01859 }
01860
01861 static void __quit_handler(int num)
01862 {
01863 int a = 0;
01864 sig_flags.need_quit = 1;
01865 if (sig_alert_pipe[1] != -1) {
01866 if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
01867 fprintf(stderr, "quit_handler: write() failed: %s\n", strerror(errno));
01868 }
01869 }
01870
01871
01872 }
01873
01874 static void __remote_quit_handler(int num)
01875 {
01876 sig_flags.need_quit = 1;
01877 }
01878
01879 static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp)
01880 {
01881 const char *c;
01882
01883
01884 if (*s == 127) {
01885 s++;
01886 }
01887
01888 if (!strncmp(s, cmp, strlen(cmp))) {
01889 c = s + strlen(cmp);
01890 term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
01891 return c;
01892 }
01893 return NULL;
01894 }
01895
01896 static void console_verboser(const char *s)
01897 {
01898 char tmp[80];
01899 const char *c = NULL;
01900
01901 if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
01902 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
01903 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
01904 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_1))) {
01905 fputs(tmp, stdout);
01906 fputs(c, stdout);
01907 } else {
01908 if (*s == 127) {
01909 s++;
01910 }
01911 fputs(s, stdout);
01912 }
01913
01914 fflush(stdout);
01915
01916
01917 if (ast_opt_console && consolethread != AST_PTHREADT_NULL)
01918 pthread_kill(consolethread, SIGURG);
01919 }
01920
01921 static int ast_all_zeros(char *s)
01922 {
01923 while (*s) {
01924 if (*s > 32)
01925 return 0;
01926 s++;
01927 }
01928 return 1;
01929 }
01930
01931 static void consolehandler(char *s)
01932 {
01933 printf("%s", term_end());
01934 fflush(stdout);
01935
01936
01937 if (!ast_all_zeros(s))
01938 ast_el_add_history(s);
01939
01940 if (s[0] == '!') {
01941 if (s[1])
01942 ast_safe_system(s+1);
01943 else
01944 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
01945 } else
01946 ast_cli_command(STDOUT_FILENO, s);
01947 }
01948
01949 static int remoteconsolehandler(char *s)
01950 {
01951 int ret = 0;
01952
01953
01954 if (!ast_all_zeros(s))
01955 ast_el_add_history(s);
01956
01957 if (s[0] == '!') {
01958 if (s[1])
01959 ast_safe_system(s+1);
01960 else
01961 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
01962 ret = 1;
01963 }
01964 while (isspace(*s)) {
01965 s++;
01966 }
01967
01968 if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
01969 (s[4] == '\0' || isspace(s[4]))) {
01970 quit_handler(0, SHUTDOWN_FAST, 0);
01971 ret = 1;
01972 }
01973
01974 return ret;
01975 }
01976
01977 static char *handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01978 {
01979 switch (cmd) {
01980 case CLI_INIT:
01981 e->command = "core show version";
01982 e->usage =
01983 "Usage: core show version\n"
01984 " Shows Asterisk version information.\n";
01985 return NULL;
01986 case CLI_GENERATE:
01987 return NULL;
01988 }
01989
01990 if (a->argc != 3)
01991 return CLI_SHOWUSAGE;
01992 ast_cli(a->fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
01993 ast_get_version(), ast_build_user, ast_build_hostname,
01994 ast_build_machine, ast_build_os, ast_build_date);
01995 return CLI_SUCCESS;
01996 }
01997
01998 #if 0
01999 static int handle_quit(int fd, int argc, char *argv[])
02000 {
02001 if (argc != 1)
02002 return RESULT_SHOWUSAGE;
02003 quit_handler(0, SHUTDOWN_NORMAL, 0);
02004 return RESULT_SUCCESS;
02005 }
02006 #endif
02007
02008 static char *handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02009 {
02010 switch (cmd) {
02011 case CLI_INIT:
02012 e->command = "core stop now";
02013 e->usage =
02014 "Usage: core stop now\n"
02015 " Shuts down a running Asterisk immediately, hanging up all active calls .\n";
02016 return NULL;
02017 case CLI_GENERATE:
02018 return NULL;
02019 }
02020
02021 if (a->argc != e->args)
02022 return CLI_SHOWUSAGE;
02023 quit_handler(0, SHUTDOWN_NORMAL, 0 );
02024 return CLI_SUCCESS;
02025 }
02026
02027 static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02028 {
02029 switch (cmd) {
02030 case CLI_INIT:
02031 e->command = "core stop gracefully";
02032 e->usage =
02033 "Usage: core stop gracefully\n"
02034 " Causes Asterisk to not accept new calls, and exit when all\n"
02035 " active calls have terminated normally.\n";
02036 return NULL;
02037 case CLI_GENERATE:
02038 return NULL;
02039 }
02040
02041 if (a->argc != e->args)
02042 return CLI_SHOWUSAGE;
02043 quit_handler(0, SHUTDOWN_NICE, 0 );
02044 return CLI_SUCCESS;
02045 }
02046
02047 static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02048 {
02049 switch (cmd) {
02050 case CLI_INIT:
02051 e->command = "core stop when convenient";
02052 e->usage =
02053 "Usage: core stop when convenient\n"
02054 " Causes Asterisk to perform a shutdown when all active calls have ended.\n";
02055 return NULL;
02056 case CLI_GENERATE:
02057 return NULL;
02058 }
02059
02060 if (a->argc != e->args)
02061 return CLI_SHOWUSAGE;
02062 ast_cli(a->fd, "Waiting for inactivity to perform halt\n");
02063 quit_handler(0, SHUTDOWN_REALLY_NICE, 0 );
02064 return CLI_SUCCESS;
02065 }
02066
02067 static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02068 {
02069 switch (cmd) {
02070 case CLI_INIT:
02071 e->command = "core restart now";
02072 e->usage =
02073 "Usage: core restart now\n"
02074 " Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
02075 " restart.\n";
02076 return NULL;
02077 case CLI_GENERATE:
02078 return NULL;
02079 }
02080
02081 if (a->argc != e->args)
02082 return CLI_SHOWUSAGE;
02083 quit_handler(0, SHUTDOWN_NORMAL, 1 );
02084 return CLI_SUCCESS;
02085 }
02086
02087 static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02088 {
02089 switch (cmd) {
02090 case CLI_INIT:
02091 e->command = "core restart gracefully";
02092 e->usage =
02093 "Usage: core restart gracefully\n"
02094 " Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
02095 " restart when all active calls have ended.\n";
02096 return NULL;
02097 case CLI_GENERATE:
02098 return NULL;
02099 }
02100
02101 if (a->argc != e->args)
02102 return CLI_SHOWUSAGE;
02103 quit_handler(0, SHUTDOWN_NICE, 1 );
02104 return CLI_SUCCESS;
02105 }
02106
02107 static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02108 {
02109 switch (cmd) {
02110 case CLI_INIT:
02111 e->command = "core restart when convenient";
02112 e->usage =
02113 "Usage: core restart when convenient\n"
02114 " Causes Asterisk to perform a cold restart when all active calls have ended.\n";
02115 return NULL;
02116 case CLI_GENERATE:
02117 return NULL;
02118 }
02119
02120 if (a->argc != e->args)
02121 return CLI_SHOWUSAGE;
02122 ast_cli(a->fd, "Waiting for inactivity to perform restart\n");
02123 quit_handler(0, SHUTDOWN_REALLY_NICE, 1 );
02124 return CLI_SUCCESS;
02125 }
02126
02127 static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02128 {
02129 int aborting_shutdown = 0;
02130
02131 switch (cmd) {
02132 case CLI_INIT:
02133 e->command = "core abort shutdown";
02134 e->usage =
02135 "Usage: core abort shutdown\n"
02136 " Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
02137 " call operations.\n";
02138 return NULL;
02139 case CLI_GENERATE:
02140 return NULL;
02141 }
02142
02143 if (a->argc != e->args)
02144 return CLI_SHOWUSAGE;
02145
02146 ast_mutex_lock(&safe_system_lock);
02147 if (shuttingdown >= SHUTDOWN_FAST) {
02148 aborting_shutdown = 1;
02149 shuttingdown = NOT_SHUTTING_DOWN;
02150 }
02151 ast_mutex_unlock(&safe_system_lock);
02152
02153 if (aborting_shutdown) {
02154 ast_cancel_shutdown();
02155 }
02156 return CLI_SUCCESS;
02157 }
02158
02159 static char *handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02160 {
02161 switch (cmd) {
02162 case CLI_INIT:
02163 e->command = "!";
02164 e->usage =
02165 "Usage: !<command>\n"
02166 " Executes a given shell command\n";
02167 return NULL;
02168 case CLI_GENERATE:
02169 return NULL;
02170 }
02171
02172 return CLI_SUCCESS;
02173 }
02174 static const char warranty_lines[] = {
02175 "\n"
02176 " NO WARRANTY\n"
02177 "\n"
02178 "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
02179 "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n"
02180 "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
02181 "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
02182 "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
02183 "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n"
02184 "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n"
02185 "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
02186 "REPAIR OR CORRECTION.\n"
02187 "\n"
02188 "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
02189 "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
02190 "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
02191 "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
02192 "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
02193 "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
02194 "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
02195 "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
02196 "POSSIBILITY OF SUCH DAMAGES.\n"
02197 };
02198
02199 static char *show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02200 {
02201 switch (cmd) {
02202 case CLI_INIT:
02203 e->command = "core show warranty";
02204 e->usage =
02205 "Usage: core show warranty\n"
02206 " Shows the warranty (if any) for this copy of Asterisk.\n";
02207 return NULL;
02208 case CLI_GENERATE:
02209 return NULL;
02210 }
02211
02212 ast_cli(a->fd, "%s", warranty_lines);
02213
02214 return CLI_SUCCESS;
02215 }
02216
02217 static const char license_lines[] = {
02218 "\n"
02219 "This program is free software; you can redistribute it and/or modify\n"
02220 "it under the terms of the GNU General Public License version 2 as\n"
02221 "published by the Free Software Foundation.\n"
02222 "\n"
02223 "This program also contains components licensed under other licenses.\n"
02224 "They include:\n"
02225 "\n"
02226 "This program is distributed in the hope that it will be useful,\n"
02227 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
02228 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
02229 "GNU General Public License for more details.\n"
02230 "\n"
02231 "You should have received a copy of the GNU General Public License\n"
02232 "along with this program; if not, write to the Free Software\n"
02233 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
02234 };
02235
02236 static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02237 {
02238 switch (cmd) {
02239 case CLI_INIT:
02240 e->command = "core show license";
02241 e->usage =
02242 "Usage: core show license\n"
02243 " Shows the license(s) for this copy of Asterisk.\n";
02244 return NULL;
02245 case CLI_GENERATE:
02246 return NULL;
02247 }
02248
02249 ast_cli(a->fd, "%s", license_lines);
02250
02251 return CLI_SUCCESS;
02252 }
02253
02254 #define ASTERISK_PROMPT "*CLI> "
02255
02256 #define ASTERISK_PROMPT2 "%s*CLI> "
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266 static struct ast_cli_entry cli_asterisk_shutdown[] = {
02267 AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"),
02268 AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"),
02269 AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
02270 AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"),
02271 AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"),
02272 AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
02273 };
02274
02275 static struct ast_cli_entry cli_asterisk[] = {
02276 AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
02277 AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
02278 AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"),
02279 AST_CLI_DEFINE(handle_version, "Display version info"),
02280 AST_CLI_DEFINE(handle_bang, "Execute a shell command"),
02281 #if !defined(LOW_MEMORY)
02282 AST_CLI_DEFINE(handle_show_version_files, "List versions of files used to build Asterisk"),
02283 AST_CLI_DEFINE(handle_show_threads, "Show running threads"),
02284 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
02285 AST_CLI_DEFINE(handle_show_sysinfo, "Show System Information"),
02286 #endif
02287 AST_CLI_DEFINE(handle_show_profile, "Display profiling info"),
02288 AST_CLI_DEFINE(handle_show_settings, "Show some core settings"),
02289 AST_CLI_DEFINE(handle_clear_profile, "Clear profiling info"),
02290 #endif
02291 };
02292
02293 static int ast_el_read_char(EditLine *editline, char *cp)
02294 {
02295 int num_read = 0;
02296 int lastpos = 0;
02297 struct pollfd fds[2];
02298 int res;
02299 int max;
02300 #define EL_BUF_SIZE 512
02301 char buf[EL_BUF_SIZE];
02302
02303 for (;;) {
02304 max = 1;
02305 fds[0].fd = ast_consock;
02306 fds[0].events = POLLIN;
02307 if (!ast_opt_exec) {
02308 fds[1].fd = STDIN_FILENO;
02309 fds[1].events = POLLIN;
02310 max++;
02311 }
02312 res = ast_poll(fds, max, -1);
02313 if (res < 0) {
02314 if (sig_flags.need_quit || sig_flags.need_quit_handler)
02315 break;
02316 if (errno == EINTR)
02317 continue;
02318 fprintf(stderr, "poll failed: %s\n", strerror(errno));
02319 break;
02320 }
02321
02322 if (!ast_opt_exec && fds[1].revents) {
02323 num_read = read(STDIN_FILENO, cp, 1);
02324 if (num_read < 1) {
02325 break;
02326 } else
02327 return (num_read);
02328 }
02329 if (fds[0].revents) {
02330 char *tmp;
02331 res = read(ast_consock, buf, sizeof(buf) - 1);
02332
02333 if (res < 1) {
02334 fprintf(stderr, "\nDisconnected from Asterisk server\n");
02335 if (!ast_opt_reconnect) {
02336 quit_handler(0, SHUTDOWN_FAST, 0);
02337 } else {
02338 int tries;
02339 int reconnects_per_second = 20;
02340 fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
02341 for (tries = 0; tries < 30 * reconnects_per_second; tries++) {
02342 if (ast_tryconnect()) {
02343 fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
02344 printf("%s", term_quit());
02345 WELCOME_MESSAGE;
02346 if (!ast_opt_mute)
02347 fdsend(ast_consock, "logger mute silent");
02348 else
02349 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
02350 break;
02351 } else
02352 usleep(1000000 / reconnects_per_second);
02353 }
02354 if (tries >= 30 * reconnects_per_second) {
02355 fprintf(stderr, "Failed to reconnect for 30 seconds. Quitting.\n");
02356 quit_handler(0, SHUTDOWN_FAST, 0);
02357 }
02358 }
02359 continue;
02360 }
02361
02362 buf[res] = '\0';
02363
02364
02365 for (tmp = buf; *tmp; tmp++) {
02366 if (*tmp == 127) {
02367 memmove(tmp, tmp + 1, strlen(tmp));
02368 tmp--;
02369 res--;
02370 }
02371 }
02372
02373
02374 if (!ast_opt_exec && !lastpos) {
02375 if (write(STDOUT_FILENO, "\r[0K", 5) < 0) {
02376 }
02377 }
02378 if (write(STDOUT_FILENO, buf, res) < 0) {
02379 }
02380 if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (buf[res-2] == '\n'))) {
02381 *cp = CC_REFRESH;
02382 return(1);
02383 } else
02384 lastpos = 1;
02385 }
02386 }
02387
02388 *cp = '\0';
02389 return (0);
02390 }
02391
02392 static struct ast_str *prompt = NULL;
02393
02394 static char *cli_prompt(EditLine *editline)
02395 {
02396 char tmp[100];
02397 char *pfmt;
02398 int color_used = 0;
02399 static int cli_prompt_changes = 0;
02400 char term_code[20];
02401 struct passwd *pw;
02402 struct group *gr;
02403
02404 if (prompt == NULL) {
02405 prompt = ast_str_create(100);
02406 } else if (!cli_prompt_changes) {
02407 return ast_str_buffer(prompt);
02408 } else {
02409 ast_str_reset(prompt);
02410 }
02411
02412 if ((pfmt = getenv("ASTERISK_PROMPT"))) {
02413 char *t = pfmt;
02414 struct timeval ts = ast_tvnow();
02415 while (*t != '\0') {
02416 if (*t == '%') {
02417 char hostname[MAXHOSTNAMELEN] = "";
02418 int i, which;
02419 struct ast_tm tm = { 0, };
02420 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
02421
02422 t++;
02423 switch (*t) {
02424 case 'C':
02425 t++;
02426 if (sscanf(t, "%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
02427 ast_str_append(&prompt, 0, "%s", term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)));
02428 t += i - 1;
02429 } else if (sscanf(t, "%30d%n", &fgcolor, &i) == 1) {
02430 ast_str_append(&prompt, 0, "%s", term_color_code(term_code, fgcolor, 0, sizeof(term_code)));
02431 t += i - 1;
02432 }
02433
02434
02435 color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
02436 break;
02437 case 'd':
02438 if (ast_localtime(&ts, &tm, NULL)) {
02439 ast_strftime(tmp, sizeof(tmp), "%Y-%m-%d", &tm);
02440 ast_str_append(&prompt, 0, "%s", tmp);
02441 cli_prompt_changes++;
02442 }
02443 break;
02444 case 'g':
02445 if ((gr = getgrgid(getgid()))) {
02446 ast_str_append(&prompt, 0, "%s", gr->gr_name);
02447 }
02448 break;
02449 case 'h':
02450 if (!gethostname(hostname, sizeof(hostname) - 1)) {
02451 ast_str_append(&prompt, 0, "%s", hostname);
02452 } else {
02453 ast_str_append(&prompt, 0, "%s", "localhost");
02454 }
02455 break;
02456 case 'H':
02457 if (!gethostname(hostname, sizeof(hostname) - 1)) {
02458 char *dotptr;
02459 if ((dotptr = strchr(hostname, '.'))) {
02460 *dotptr = '\0';
02461 }
02462 ast_str_append(&prompt, 0, "%s", hostname);
02463 } else {
02464 ast_str_append(&prompt, 0, "%s", "localhost");
02465 }
02466 break;
02467 #ifdef HAVE_GETLOADAVG
02468 case 'l':
02469 t++;
02470 if (sscanf(t, "%30d", &which) == 1 && which > 0 && which <= 3) {
02471 double list[3];
02472 getloadavg(list, 3);
02473 ast_str_append(&prompt, 0, "%.2f", list[which - 1]);
02474 cli_prompt_changes++;
02475 }
02476 break;
02477 #endif
02478 case 's':
02479 ast_str_append(&prompt, 0, "%s", ast_config_AST_SYSTEM_NAME);
02480 break;
02481 case 't':
02482 if (ast_localtime(&ts, &tm, NULL)) {
02483 ast_strftime(tmp, sizeof(tmp), "%H:%M:%S", &tm);
02484 ast_str_append(&prompt, 0, "%s", tmp);
02485 cli_prompt_changes++;
02486 }
02487 break;
02488 case 'u':
02489 if ((pw = getpwuid(getuid()))) {
02490 ast_str_append(&prompt, 0, "%s", pw->pw_name);
02491 }
02492 break;
02493 case '#':
02494 ast_str_append(&prompt, 0, "%c", ast_opt_remote ? '>' : '#');
02495 break;
02496 case '%':
02497 ast_str_append(&prompt, 0, "%c", '%');
02498 break;
02499 case '\0':
02500 t--;
02501 break;
02502 }
02503 } else {
02504 ast_str_append(&prompt, 0, "%c", *t);
02505 }
02506 t++;
02507 }
02508 if (color_used) {
02509
02510 ast_str_append(&prompt, 0, "%s", term_color_code(term_code, 0, 0, sizeof(term_code)));
02511 }
02512 } else if (remotehostname) {
02513 ast_str_set(&prompt, 0, ASTERISK_PROMPT2, remotehostname);
02514 } else {
02515 ast_str_set(&prompt, 0, "%s", ASTERISK_PROMPT);
02516 }
02517
02518 return ast_str_buffer(prompt);
02519 }
02520
02521 static void destroy_match_list(char **match_list, int matches)
02522 {
02523 if (match_list) {
02524 int idx;
02525
02526 for (idx = 0; idx < matches; ++idx) {
02527 ast_free(match_list[idx]);
02528 }
02529 ast_free(match_list);
02530 }
02531 }
02532
02533 static char **ast_el_strtoarr(char *buf)
02534 {
02535 char *retstr;
02536 char **match_list = NULL;
02537 char **new_list;
02538 size_t match_list_len = 1;
02539 int matches = 0;
02540
02541 while ((retstr = strsep(&buf, " "))) {
02542 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF)) {
02543 break;
02544 }
02545 if (matches + 1 >= match_list_len) {
02546 match_list_len <<= 1;
02547 new_list = ast_realloc(match_list, match_list_len * sizeof(char *));
02548 if (!new_list) {
02549 destroy_match_list(match_list, matches);
02550 return NULL;
02551 }
02552 match_list = new_list;
02553 }
02554
02555 retstr = ast_strdup(retstr);
02556 if (!retstr) {
02557 destroy_match_list(match_list, matches);
02558 return NULL;
02559 }
02560 match_list[matches++] = retstr;
02561 }
02562
02563 if (!match_list) {
02564 return NULL;
02565 }
02566
02567 if (matches >= match_list_len) {
02568 new_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *));
02569 if (!new_list) {
02570 destroy_match_list(match_list, matches);
02571 return NULL;
02572 }
02573 match_list = new_list;
02574 }
02575
02576 match_list[matches] = NULL;
02577
02578 return match_list;
02579 }
02580
02581 static int ast_el_sort_compare(const void *i1, const void *i2)
02582 {
02583 char *s1, *s2;
02584
02585 s1 = ((char **)i1)[0];
02586 s2 = ((char **)i2)[0];
02587
02588 return strcasecmp(s1, s2);
02589 }
02590
02591 static int ast_cli_display_match_list(char **matches, int len, int max)
02592 {
02593 int i, idx, limit, count;
02594 int screenwidth = 0;
02595 int numoutput = 0, numoutputline = 0;
02596
02597 screenwidth = ast_get_termcols(STDOUT_FILENO);
02598
02599
02600 limit = screenwidth / (max + 2);
02601 if (limit == 0)
02602 limit = 1;
02603
02604
02605 count = len / limit;
02606 if (count * limit < len)
02607 count++;
02608
02609 idx = 1;
02610
02611 qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);
02612
02613 for (; count > 0; count--) {
02614 numoutputline = 0;
02615 for (i = 0; i < limit && matches[idx]; i++, idx++) {
02616
02617
02618 if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
02619 i--;
02620 ast_free(matches[idx]);
02621 matches[idx] = NULL;
02622 continue;
02623 }
02624
02625 numoutput++;
02626 numoutputline++;
02627 fprintf(stdout, "%-*s ", max, matches[idx]);
02628 ast_free(matches[idx]);
02629 matches[idx] = NULL;
02630 }
02631 if (numoutputline > 0)
02632 fprintf(stdout, "\n");
02633 }
02634
02635 return numoutput;
02636 }
02637
02638
02639 static char *cli_complete(EditLine *editline, int ch)
02640 {
02641 int len = 0;
02642 char *ptr;
02643 int nummatches = 0;
02644 char **matches;
02645 int retval = CC_ERROR;
02646 char buf[2048], savechr;
02647 int res;
02648
02649 LineInfo *lf = (LineInfo *)el_line(editline);
02650
02651 savechr = *(char *)lf->cursor;
02652 *(char *)lf->cursor = '\0';
02653 ptr = (char *)lf->cursor;
02654 if (ptr) {
02655 while (ptr > lf->buffer) {
02656 if (isspace(*ptr)) {
02657 ptr++;
02658 break;
02659 }
02660 ptr--;
02661 }
02662 }
02663
02664 len = lf->cursor - ptr;
02665
02666 if (ast_opt_remote) {
02667 snprintf(buf, sizeof(buf), "_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
02668 fdsend(ast_consock, buf);
02669 if ((res = read(ast_consock, buf, sizeof(buf) - 1)) < 0) {
02670 return (char*)(CC_ERROR);
02671 }
02672 buf[res] = '\0';
02673 nummatches = atoi(buf);
02674
02675 if (nummatches > 0) {
02676 char *mbuf;
02677 char *new_mbuf;
02678 int mlen = 0, maxmbuf = 2048;
02679
02680
02681 if (!(mbuf = ast_malloc(maxmbuf))) {
02682 lf->cursor[0] = savechr;
02683 return (char *)(CC_ERROR);
02684 }
02685 snprintf(buf, sizeof(buf), "_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
02686 fdsend(ast_consock, buf);
02687 res = 0;
02688 mbuf[0] = '\0';
02689 while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
02690 if (mlen + 1024 > maxmbuf) {
02691
02692 maxmbuf += 1024;
02693 new_mbuf = ast_realloc(mbuf, maxmbuf);
02694 if (!new_mbuf) {
02695 ast_free(mbuf);
02696 lf->cursor[0] = savechr;
02697 return (char *)(CC_ERROR);
02698 }
02699 mbuf = new_mbuf;
02700 }
02701
02702 res = read(ast_consock, mbuf + mlen, 1024);
02703 if (res > 0)
02704 mlen += res;
02705 }
02706 mbuf[mlen] = '\0';
02707
02708 matches = ast_el_strtoarr(mbuf);
02709 ast_free(mbuf);
02710 } else
02711 matches = (char **) NULL;
02712 } else {
02713 char **p, *oldbuf=NULL;
02714 nummatches = 0;
02715 matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
02716 for (p = matches; p && *p; p++) {
02717 if (!oldbuf || strcmp(*p,oldbuf))
02718 nummatches++;
02719 oldbuf = *p;
02720 }
02721 }
02722
02723 if (matches) {
02724 int i;
02725 int matches_num, maxlen, match_len;
02726
02727 if (matches[0][0] != '\0') {
02728 el_deletestr(editline, (int) len);
02729 el_insertstr(editline, matches[0]);
02730 retval = CC_REFRESH;
02731 }
02732
02733 if (nummatches == 1) {
02734
02735 el_insertstr(editline, " ");
02736 retval = CC_REFRESH;
02737 } else {
02738
02739 for (i = 1, maxlen = 0; matches[i]; i++) {
02740 match_len = strlen(matches[i]);
02741 if (match_len > maxlen)
02742 maxlen = match_len;
02743 }
02744 matches_num = i - 1;
02745 if (matches_num >1) {
02746 fprintf(stdout, "\n");
02747 ast_cli_display_match_list(matches, nummatches, maxlen);
02748 retval = CC_REDISPLAY;
02749 } else {
02750 el_insertstr(editline," ");
02751 retval = CC_REFRESH;
02752 }
02753 }
02754 for (i = 0; matches[i]; i++)
02755 ast_free(matches[i]);
02756 ast_free(matches);
02757 }
02758
02759 lf->cursor[0] = savechr;
02760
02761 return (char *)(long)retval;
02762 }
02763
02764 static int ast_el_initialize(void)
02765 {
02766 HistEvent ev;
02767 char *editor = getenv("AST_EDITOR");
02768
02769 if (el != NULL)
02770 el_end(el);
02771 if (el_hist != NULL)
02772 history_end(el_hist);
02773
02774 el = el_init("asterisk", stdin, stdout, stderr);
02775 el_set(el, EL_PROMPT, cli_prompt);
02776
02777 el_set(el, EL_EDITMODE, 1);
02778 el_set(el, EL_EDITOR, editor ? editor : "emacs");
02779 el_hist = history_init();
02780 if (!el || !el_hist)
02781 return -1;
02782
02783
02784 history(el_hist, &ev, H_SETSIZE, 100);
02785
02786 el_set(el, EL_HIST, history, el_hist);
02787
02788 el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
02789
02790 el_set(el, EL_BIND, "^I", "ed-complete", NULL);
02791
02792 el_set(el, EL_BIND, "?", "ed-complete", NULL);
02793
02794 el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
02795
02796 return 0;
02797 }
02798
02799 #define MAX_HISTORY_COMMAND_LENGTH 256
02800
02801 static int ast_el_add_history(char *buf)
02802 {
02803 HistEvent ev;
02804
02805 if (el_hist == NULL || el == NULL)
02806 ast_el_initialize();
02807 if (strlen(buf) > (MAX_HISTORY_COMMAND_LENGTH - 1))
02808 return 0;
02809 return (history(el_hist, &ev, H_ENTER, ast_strip(ast_strdupa(buf))));
02810 }
02811
02812 static int ast_el_write_history(char *filename)
02813 {
02814 HistEvent ev;
02815
02816 if (el_hist == NULL || el == NULL)
02817 ast_el_initialize();
02818
02819 return (history(el_hist, &ev, H_SAVE, filename));
02820 }
02821
02822 static int ast_el_read_history(char *filename)
02823 {
02824 HistEvent ev;
02825
02826 if (el_hist == NULL || el == NULL)
02827 ast_el_initialize();
02828
02829 return (history(el_hist, &ev, H_LOAD, filename));
02830 }
02831
02832 static void ast_remotecontrol(char *data)
02833 {
02834 char buf[80];
02835 int res;
02836 char filename[80] = "";
02837 char *hostname;
02838 char *cpid;
02839 char *version;
02840 int pid;
02841 char *stringp = NULL;
02842
02843 char *ebuf;
02844 int num = 0;
02845
02846 memset(&sig_flags, 0, sizeof(sig_flags));
02847 signal(SIGINT, __remote_quit_handler);
02848 signal(SIGTERM, __remote_quit_handler);
02849 signal(SIGHUP, __remote_quit_handler);
02850
02851 if (read(ast_consock, buf, sizeof(buf)) < 0) {
02852 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
02853 return;
02854 }
02855 if (data) {
02856 char prefix[] = "cli quit after ";
02857 char *tmp = ast_alloca(strlen(data) + strlen(prefix) + 1);
02858 sprintf(tmp, "%s%s", prefix, data);
02859 if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) {
02860 ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
02861 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
02862 return;
02863 }
02864 }
02865 }
02866 stringp = buf;
02867 hostname = strsep(&stringp, "/");
02868 cpid = strsep(&stringp, "/");
02869 version = strsep(&stringp, "\n");
02870 if (!version)
02871 version = "<Version Unknown>";
02872 stringp = hostname;
02873 strsep(&stringp, ".");
02874 if (cpid)
02875 pid = atoi(cpid);
02876 else
02877 pid = -1;
02878 if (!data) {
02879 char tmp[80];
02880 snprintf(tmp, sizeof(tmp), "core set verbose atleast %d", option_verbose);
02881 fdsend(ast_consock, tmp);
02882 snprintf(tmp, sizeof(tmp), "core set debug atleast %d", option_debug);
02883 fdsend(ast_consock, tmp);
02884 if (!ast_opt_mute)
02885 fdsend(ast_consock, "logger mute silent");
02886 else
02887 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
02888 }
02889
02890 if (ast_opt_exec && data) {
02891 struct pollfd fds;
02892 fds.fd = ast_consock;
02893 fds.events = POLLIN;
02894 fds.revents = 0;
02895 while (ast_poll(&fds, 1, 60000) > 0) {
02896 char buffer[512] = "", *curline = buffer, *nextline;
02897 int not_written = 1;
02898
02899 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
02900 break;
02901 }
02902
02903 if (read(ast_consock, buffer, sizeof(buffer) - 1) <= 0) {
02904 break;
02905 }
02906
02907 do {
02908 if ((nextline = strchr(curline, '\n'))) {
02909 nextline++;
02910 } else {
02911 nextline = strchr(curline, '\0');
02912 }
02913
02914
02915 if (*curline != 127) {
02916 not_written = 0;
02917 if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
02918 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
02919 }
02920 }
02921 curline = nextline;
02922 } while (!ast_strlen_zero(curline));
02923
02924
02925 if (not_written) {
02926 break;
02927 }
02928 }
02929 return;
02930 }
02931
02932 ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
02933 remotehostname = hostname;
02934 if (getenv("HOME"))
02935 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
02936 if (el_hist == NULL || el == NULL)
02937 ast_el_initialize();
02938
02939 el_set(el, EL_GETCFN, ast_el_read_char);
02940
02941 if (!ast_strlen_zero(filename))
02942 ast_el_read_history(filename);
02943
02944 for (;;) {
02945 ebuf = (char *)el_gets(el, &num);
02946
02947 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
02948 break;
02949 }
02950
02951 if (!ebuf && write(1, "", 1) < 0)
02952 break;
02953
02954 if (!ast_strlen_zero(ebuf)) {
02955 if (ebuf[strlen(ebuf)-1] == '\n')
02956 ebuf[strlen(ebuf)-1] = '\0';
02957 if (!remoteconsolehandler(ebuf)) {
02958
02959 char *temp;
02960 for (temp = ebuf; *temp; temp++) {
02961 if (*temp == 127) {
02962 memmove(temp, temp + 1, strlen(temp));
02963 temp--;
02964 }
02965 }
02966 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
02967 if (res < 1) {
02968 ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
02969 break;
02970 }
02971 }
02972 }
02973 }
02974 printf("\nDisconnected from Asterisk server\n");
02975 }
02976
02977 static int show_version(void)
02978 {
02979 printf("Asterisk %s\n", ast_get_version());
02980 return 0;
02981 }
02982
02983 static int show_cli_help(void)
02984 {
02985 printf("Asterisk %s, Copyright (C) 1999 - 2013, Digium, Inc. and others.\n", ast_get_version());
02986 printf("Usage: asterisk [OPTIONS]\n");
02987 printf("Valid Options:\n");
02988 printf(" -V Display version number and exit\n");
02989 printf(" -C <configfile> Use an alternate configuration file\n");
02990 printf(" -G <group> Run as a group other than the caller\n");
02991 printf(" -U <user> Run as a user other than the caller\n");
02992 printf(" -c Provide console CLI\n");
02993 printf(" -d Enable extra debugging\n");
02994 #if HAVE_WORKING_FORK
02995 printf(" -f Do not fork\n");
02996 printf(" -F Always fork\n");
02997 #endif
02998 printf(" -g Dump core in case of a crash\n");
02999 printf(" -h This help screen\n");
03000 printf(" -i Initialize crypto keys at startup\n");
03001 printf(" -L <load> Limit the maximum load average before rejecting new calls\n");
03002 printf(" -M <value> Limit the maximum number of calls to the specified value\n");
03003 printf(" -m Mute debugging and console output on the console\n");
03004 printf(" -n Disable console colorization\n");
03005 printf(" -p Run as pseudo-realtime thread\n");
03006 printf(" -q Quiet mode (suppress output)\n");
03007 printf(" -r Connect to Asterisk on this machine\n");
03008 printf(" -R Same as -r, except attempt to reconnect if disconnected\n");
03009 printf(" -s <socket> Connect to Asterisk via socket <socket> (only valid with -r)\n");
03010 printf(" -t Record soundfiles in /var/tmp and move them where they\n");
03011 printf(" belong after they are done\n");
03012 printf(" -T Display the time in [Mmm dd hh:mm:ss] format for each line\n");
03013 printf(" of output to the CLI\n");
03014 printf(" -v Increase verbosity (multiple v's = more verbose)\n");
03015 printf(" -x <cmd> Execute command <cmd> (implies -r)\n");
03016 printf(" -X Execute includes by default (allows #exec in asterisk.conf)\n");
03017 printf(" -W Adjust terminal colors to compensate for a light background\n");
03018 printf("\n");
03019 return 0;
03020 }
03021
03022 static void ast_readconfig(void)
03023 {
03024 struct ast_config *cfg;
03025 struct ast_variable *v;
03026 char *config = DEFAULT_CONFIG_FILE;
03027 char hostname[MAXHOSTNAMELEN] = "";
03028 struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
03029 struct {
03030 unsigned int dbdir:1;
03031 unsigned int keydir:1;
03032 } found = { 0, 0 };
03033
03034 int live_dangerously = 1;
03035
03036 if (ast_opt_override_config) {
03037 cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" , config_flags);
03038 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
03039 fprintf(stderr, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
03040 }
03041 } else {
03042 cfg = ast_config_load2(config, "" , config_flags);
03043 }
03044
03045
03046 ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
03047 ast_copy_string(cfg_paths.spool_dir, DEFAULT_SPOOL_DIR, sizeof(cfg_paths.spool_dir));
03048 ast_copy_string(cfg_paths.module_dir, DEFAULT_MODULE_DIR, sizeof(cfg_paths.module_dir));
03049 snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", cfg_paths.spool_dir);
03050 ast_copy_string(cfg_paths.var_dir, DEFAULT_VAR_DIR, sizeof(cfg_paths.var_dir));
03051 ast_copy_string(cfg_paths.data_dir, DEFAULT_DATA_DIR, sizeof(cfg_paths.data_dir));
03052 ast_copy_string(cfg_paths.log_dir, DEFAULT_LOG_DIR, sizeof(cfg_paths.log_dir));
03053 ast_copy_string(cfg_paths.agi_dir, DEFAULT_AGI_DIR, sizeof(cfg_paths.agi_dir));
03054 ast_copy_string(cfg_paths.db_path, DEFAULT_DB, sizeof(cfg_paths.db_path));
03055 ast_copy_string(cfg_paths.key_dir, DEFAULT_KEY_DIR, sizeof(cfg_paths.key_dir));
03056 ast_copy_string(cfg_paths.pid_path, DEFAULT_PID, sizeof(cfg_paths.pid_path));
03057 ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path));
03058 ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir));
03059
03060 ast_set_default_eid(&ast_eid_default);
03061
03062
03063 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
03064 return;
03065 }
03066
03067 for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
03068 if (!strcasecmp(v->name, "astctlpermissions"))
03069 ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
03070 else if (!strcasecmp(v->name, "astctlowner"))
03071 ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
03072 else if (!strcasecmp(v->name, "astctlgroup"))
03073 ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
03074 else if (!strcasecmp(v->name, "astctl"))
03075 ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
03076 }
03077
03078 for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
03079 if (!strcasecmp(v->name, "astetcdir")) {
03080 ast_copy_string(cfg_paths.config_dir, v->value, sizeof(cfg_paths.config_dir));
03081 } else if (!strcasecmp(v->name, "astspooldir")) {
03082 ast_copy_string(cfg_paths.spool_dir, v->value, sizeof(cfg_paths.spool_dir));
03083 snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", v->value);
03084 } else if (!strcasecmp(v->name, "astvarlibdir")) {
03085 ast_copy_string(cfg_paths.var_dir, v->value, sizeof(cfg_paths.var_dir));
03086 if (!found.dbdir)
03087 snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
03088 } else if (!strcasecmp(v->name, "astdbdir")) {
03089 snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
03090 found.dbdir = 1;
03091 } else if (!strcasecmp(v->name, "astdatadir")) {
03092 ast_copy_string(cfg_paths.data_dir, v->value, sizeof(cfg_paths.data_dir));
03093 if (!found.keydir)
03094 snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
03095 } else if (!strcasecmp(v->name, "astkeydir")) {
03096 snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
03097 found.keydir = 1;
03098 } else if (!strcasecmp(v->name, "astlogdir")) {
03099 ast_copy_string(cfg_paths.log_dir, v->value, sizeof(cfg_paths.log_dir));
03100 } else if (!strcasecmp(v->name, "astagidir")) {
03101 ast_copy_string(cfg_paths.agi_dir, v->value, sizeof(cfg_paths.agi_dir));
03102 } else if (!strcasecmp(v->name, "astrundir")) {
03103 snprintf(cfg_paths.pid_path, sizeof(cfg_paths.pid_path), "%s/%s", v->value, "asterisk.pid");
03104 snprintf(cfg_paths.socket_path, sizeof(cfg_paths.socket_path), "%s/%s", v->value, ast_config_AST_CTL);
03105 ast_copy_string(cfg_paths.run_dir, v->value, sizeof(cfg_paths.run_dir));
03106 } else if (!strcasecmp(v->name, "astmoddir")) {
03107 ast_copy_string(cfg_paths.module_dir, v->value, sizeof(cfg_paths.module_dir));
03108 }
03109 }
03110
03111 for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
03112
03113 if (!strcasecmp(v->name, "verbose")) {
03114 option_verbose = atoi(v->value);
03115
03116 } else if (!strcasecmp(v->name, "timestamp")) {
03117 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
03118
03119 } else if (!strcasecmp(v->name, "execincludes")) {
03120 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
03121
03122 } else if (!strcasecmp(v->name, "debug")) {
03123 option_debug = 0;
03124 if (sscanf(v->value, "%30d", &option_debug) != 1) {
03125 option_debug = ast_true(v->value);
03126 }
03127 #if HAVE_WORKING_FORK
03128
03129 } else if (!strcasecmp(v->name, "nofork")) {
03130 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
03131
03132 } else if (!strcasecmp(v->name, "alwaysfork")) {
03133 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
03134 #endif
03135
03136 } else if (!strcasecmp(v->name, "quiet")) {
03137 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
03138
03139 } else if (!strcasecmp(v->name, "console")) {
03140 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
03141
03142 } else if (!strcasecmp(v->name, "highpriority")) {
03143 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
03144
03145 } else if (!strcasecmp(v->name, "initcrypto")) {
03146 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
03147
03148 } else if (!strcasecmp(v->name, "nocolor")) {
03149 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
03150
03151 } else if (!strcasecmp(v->name, "dontwarn")) {
03152 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
03153
03154 } else if (!strcasecmp(v->name, "dumpcore")) {
03155 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
03156
03157 } else if (!strcasecmp(v->name, "cache_record_files")) {
03158 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
03159
03160 } else if (!strcasecmp(v->name, "record_cache_dir")) {
03161 ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
03162
03163 } else if (!strcasecmp(v->name, "transcode_via_sln")) {
03164 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
03165
03166 } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
03167 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
03168
03169 } else if (!strcasecmp(v->name, "internal_timing")) {
03170 if (!ast_opt_remote) {
03171 fprintf(stderr,
03172 "NOTICE: The internal_timing option is no longer needed.\n"
03173 " It will always be enabled if you have a timing module loaded.\n");
03174 }
03175 } else if (!strcasecmp(v->name, "maxcalls")) {
03176 if ((sscanf(v->value, "%30d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
03177 option_maxcalls = 0;
03178 }
03179 } else if (!strcasecmp(v->name, "maxload")) {
03180 double test[1];
03181
03182 if (getloadavg(test, 1) == -1) {
03183 ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
03184 option_maxload = 0.0;
03185 } else if ((sscanf(v->value, "%30lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
03186 option_maxload = 0.0;
03187 }
03188
03189 } else if (!strcasecmp(v->name, "maxfiles")) {
03190 option_maxfiles = atoi(v->value);
03191 set_ulimit(option_maxfiles);
03192
03193 } else if (!strcasecmp(v->name, "runuser")) {
03194 ast_copy_string(cfg_paths.run_user, v->value, sizeof(cfg_paths.run_user));
03195
03196 } else if (!strcasecmp(v->name, "rungroup")) {
03197 ast_copy_string(cfg_paths.run_group, v->value, sizeof(cfg_paths.run_group));
03198 } else if (!strcasecmp(v->name, "systemname")) {
03199 ast_copy_string(cfg_paths.system_name, v->value, sizeof(cfg_paths.system_name));
03200 } else if (!strcasecmp(v->name, "autosystemname")) {
03201 if (ast_true(v->value)) {
03202 if (!gethostname(hostname, sizeof(hostname) - 1))
03203 ast_copy_string(cfg_paths.system_name, hostname, sizeof(cfg_paths.system_name));
03204 else {
03205 if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)){
03206 ast_copy_string(cfg_paths.system_name, "localhost", sizeof(cfg_paths.system_name));
03207 }
03208 ast_log(LOG_ERROR, "Cannot obtain hostname for this system. Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
03209 }
03210 }
03211 } else if (!strcasecmp(v->name, "languageprefix")) {
03212 ast_language_is_prefix = ast_true(v->value);
03213 } else if (!strcasecmp(v->name, "defaultlanguage")) {
03214 ast_copy_string(defaultlanguage, v->value, MAX_LANGUAGE);
03215 } else if (!strcasecmp(v->name, "lockmode")) {
03216 if (!strcasecmp(v->value, "lockfile")) {
03217 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
03218 } else if (!strcasecmp(v->value, "flock")) {
03219 ast_set_lock_type(AST_LOCK_TYPE_FLOCK);
03220 } else {
03221 ast_log(LOG_WARNING, "'%s' is not a valid setting for the lockmode option, "
03222 "defaulting to 'lockfile'\n", v->value);
03223 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
03224 }
03225 #if defined(HAVE_SYSINFO)
03226 } else if (!strcasecmp(v->name, "minmemfree")) {
03227
03228
03229 if ((sscanf(v->value, "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
03230 option_minmemfree = 0;
03231 }
03232 #endif
03233 } else if (!strcasecmp(v->name, "entityid")) {
03234 struct ast_eid tmp_eid;
03235 if (!ast_str_to_eid(&tmp_eid, v->value)) {
03236 ast_verbose("Successfully set global EID to '%s'\n", v->value);
03237 ast_eid_default = tmp_eid;
03238 } else
03239 ast_verbose("Invalid Entity ID '%s' provided\n", v->value);
03240 } else if (!strcasecmp(v->name, "lightbackground")) {
03241 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LIGHT_BACKGROUND);
03242 } else if (!strcasecmp(v->name, "forceblackbackground")) {
03243 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
03244 } else if (!strcasecmp(v->name, "hideconnect")) {
03245 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIDE_CONSOLE_CONNECT);
03246 } else if (!strcasecmp(v->name, "lockconfdir")) {
03247 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LOCK_CONFIG_DIR);
03248 } else if (!strcasecmp(v->name, "live_dangerously")) {
03249 live_dangerously = ast_true(v->value);
03250 }
03251 }
03252 if (!ast_opt_remote) {
03253 pbx_live_dangerously(live_dangerously);
03254 }
03255 for (v = ast_variable_browse(cfg, "compat"); v; v = v->next) {
03256 float version;
03257 if (sscanf(v->value, "%30f", &version) != 1) {
03258 fprintf(stderr, "Compatibility version for option '%s' is not a number: '%s'\n", v->name, v->value);
03259 continue;
03260 }
03261 if (!strcasecmp(v->name, "app_set")) {
03262 ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_APP_SET);
03263 } else if (!strcasecmp(v->name, "res_agi")) {
03264 ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_DELIM_RES_AGI);
03265 } else if (!strcasecmp(v->name, "pbx_realtime")) {
03266 ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_DELIM_PBX_REALTIME);
03267 }
03268 }
03269 ast_config_destroy(cfg);
03270 }
03271
03272 static void *monitor_sig_flags(void *unused)
03273 {
03274 for (;;) {
03275 struct pollfd p = { sig_alert_pipe[0], POLLIN, 0 };
03276 int a;
03277 ast_poll(&p, 1, -1);
03278 if (sig_flags.need_reload) {
03279 sig_flags.need_reload = 0;
03280 ast_module_reload(NULL);
03281 }
03282 if (sig_flags.need_quit) {
03283 sig_flags.need_quit = 0;
03284 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
03285 sig_flags.need_quit_handler = 1;
03286 pthread_kill(consolethread, SIGURG);
03287 } else {
03288 quit_handler(0, SHUTDOWN_NORMAL, 0);
03289 }
03290 }
03291 if (read(sig_alert_pipe[0], &a, sizeof(a)) != sizeof(a)) {
03292 }
03293 }
03294
03295 return NULL;
03296 }
03297
03298 static void *canary_thread(void *unused)
03299 {
03300 struct stat canary_stat;
03301 struct timeval now;
03302
03303
03304 sleep(120);
03305
03306 for (;;) {
03307 now = ast_tvnow();
03308 if (stat(canary_filename, &canary_stat) || now.tv_sec > canary_stat.st_mtime + 60) {
03309 ast_log(LOG_WARNING,
03310 "The canary is no more. He has ceased to be! "
03311 "He's expired and gone to meet his maker! "
03312 "He's a stiff! Bereft of life, he rests in peace. "
03313 "His metabolic processes are now history! He's off the twig! "
03314 "He's kicked the bucket. He's shuffled off his mortal coil, "
03315 "run down the curtain, and joined the bleeding choir invisible!! "
03316 "THIS is an EX-CANARY. (Reducing priority)\n");
03317 ast_set_priority(0);
03318 pthread_exit(NULL);
03319 }
03320
03321
03322 sleep(60);
03323 }
03324 }
03325
03326
03327 static void canary_exit(void)
03328 {
03329 if (canary_pid > 0)
03330 kill(canary_pid, SIGKILL);
03331 }
03332
03333 static void run_startup_commands(void)
03334 {
03335 int fd;
03336 struct ast_config *cfg;
03337 struct ast_flags cfg_flags = { 0 };
03338 struct ast_variable *v;
03339
03340 if (!(cfg = ast_config_load2("cli.conf", "" , cfg_flags)))
03341 return;
03342 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
03343 return;
03344 }
03345
03346 fd = open("/dev/null", O_RDWR);
03347 if (fd < 0) {
03348 ast_config_destroy(cfg);
03349 return;
03350 }
03351
03352 for (v = ast_variable_browse(cfg, "startup_commands"); v; v = v->next) {
03353 if (ast_true(v->value))
03354 ast_cli_command(fd, v->name);
03355 }
03356
03357 close(fd);
03358 ast_config_destroy(cfg);
03359 }
03360
03361 static void env_init(void)
03362 {
03363 setenv("AST_SYSTEMNAME", ast_config_AST_SYSTEM_NAME, 1);
03364 setenv("AST_BUILD_HOST", ast_build_hostname, 1);
03365 setenv("AST_BUILD_DATE", ast_build_date, 1);
03366 setenv("AST_BUILD_KERNEL", ast_build_kernel, 1);
03367 setenv("AST_BUILD_MACHINE", ast_build_machine, 1);
03368 setenv("AST_BUILD_OS", ast_build_os, 1);
03369 setenv("AST_BUILD_USER", ast_build_user, 1);
03370 setenv("AST_VERSION", ast_get_version(), 1);
03371 }
03372
03373 static void print_intro_message(const char *runuser, const char *rungroup)
03374 {
03375 if (ast_opt_console || option_verbose || (ast_opt_remote && !ast_opt_exec)) {
03376 if (ast_register_verbose(console_verboser)) {
03377 fprintf(stderr, "Unable to register console verboser?\n");
03378 return;
03379 }
03380 WELCOME_MESSAGE;
03381 if (runuser) {
03382 ast_verbose("Running as user '%s'\n", runuser);
03383 }
03384 if (rungroup) {
03385 ast_verbose("Running under group '%s'\n", rungroup);
03386 }
03387 }
03388 }
03389
03390 static void main_atexit(void)
03391 {
03392 ast_cli_unregister_multiple(cli_asterisk, ARRAY_LEN(cli_asterisk));
03393 }
03394
03395 int main(int argc, char *argv[])
03396 {
03397 int c;
03398 char filename[80] = "";
03399 char hostname[MAXHOSTNAMELEN] = "";
03400 char tmp[80];
03401 char * xarg = NULL;
03402 int x;
03403 FILE *f;
03404 sigset_t sigs;
03405 int num;
03406 int isroot = 1, rundir_exists = 0;
03407 char *buf;
03408 const char *runuser = NULL, *rungroup = NULL;
03409 char *remotesock = NULL;
03410 int moduleresult;
03411 struct rlimit l;
03412
03413
03414 if (argc > ARRAY_LEN(_argv) - 1) {
03415 fprintf(stderr, "Truncating argument size to %d\n", (int)ARRAY_LEN(_argv) - 1);
03416 argc = ARRAY_LEN(_argv) - 1;
03417 }
03418 for (x = 0; x < argc; x++)
03419 _argv[x] = argv[x];
03420 _argv[x] = NULL;
03421
03422 if (geteuid() != 0)
03423 isroot = 0;
03424
03425
03426 if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
03427 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
03428 }
03429 if (gethostname(hostname, sizeof(hostname)-1))
03430 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
03431 ast_mainpid = getpid();
03432
03433 if (getenv("HOME"))
03434 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
03435
03436 while ((c = getopt(argc, argv, "BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx:")) != -1) {
03437
03438
03439
03440 switch (c) {
03441 case 'B':
03442 ast_set_flag(&ast_options, AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
03443 ast_clear_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND);
03444 break;
03445 case 'X':
03446 ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
03447 break;
03448 case 'C':
03449 ast_copy_string(cfg_paths.config_file, optarg, sizeof(cfg_paths.config_file));
03450 ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG);
03451 break;
03452 case 'c':
03453 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
03454 break;
03455 case 'd':
03456 option_debug++;
03457 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
03458 break;
03459 #if defined(HAVE_SYSINFO)
03460 case 'e':
03461 if ((sscanf(&optarg[1], "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
03462 option_minmemfree = 0;
03463 }
03464 break;
03465 #endif
03466 #if HAVE_WORKING_FORK
03467 case 'F':
03468 ast_set_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
03469 break;
03470 case 'f':
03471 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
03472 break;
03473 #endif
03474 case 'G':
03475 rungroup = ast_strdupa(optarg);
03476 break;
03477 case 'g':
03478 ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE);
03479 break;
03480 case 'h':
03481 show_cli_help();
03482 exit(0);
03483 case 'I':
03484 fprintf(stderr,
03485 "NOTICE: The -I option is no longer needed.\n"
03486 " It will always be enabled if you have a timing module loaded.\n");
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 astobj2_init();
03882
03883 if (ast_opt_console) {
03884 if (el_hist == NULL || el == NULL)
03885 ast_el_initialize();
03886
03887 if (!ast_strlen_zero(filename))
03888 ast_el_read_history(filename);
03889 }
03890
03891 ast_ulaw_init();
03892 ast_alaw_init();
03893 tdd_init();
03894 callerid_init();
03895 ast_builtins_init();
03896
03897 if (ast_utils_init()) {
03898 printf("%s", term_quit());
03899 exit(1);
03900 }
03901
03902 if (ast_tps_init()) {
03903 printf("%s", term_quit());
03904 exit(1);
03905 }
03906
03907 if (ast_fd_init()) {
03908 printf("%s", term_quit());
03909 exit(1);
03910 }
03911
03912 if (ast_pbx_init()) {
03913 printf("%s", term_quit());
03914 exit(1);
03915 }
03916
03917 if (ast_event_init()) {
03918 printf("%s", term_quit());
03919 exit(1);
03920 }
03921
03922 #ifdef TEST_FRAMEWORK
03923 if (ast_test_init()) {
03924 printf("%s", term_quit());
03925 exit(1);
03926 }
03927 #endif
03928
03929 ast_aoc_cli_init();
03930
03931 ast_makesocket();
03932 sigemptyset(&sigs);
03933 sigaddset(&sigs, SIGHUP);
03934 sigaddset(&sigs, SIGTERM);
03935 sigaddset(&sigs, SIGINT);
03936 sigaddset(&sigs, SIGPIPE);
03937 sigaddset(&sigs, SIGWINCH);
03938 pthread_sigmask(SIG_BLOCK, &sigs, NULL);
03939 sigaction(SIGURG, &urg_handler, NULL);
03940 signal(SIGINT, __quit_handler);
03941 signal(SIGTERM, __quit_handler);
03942 sigaction(SIGHUP, &hup_handler, NULL);
03943 sigaction(SIGPIPE, &ignore_sig_handler, NULL);
03944
03945
03946
03947
03948 srand((unsigned int) getpid() + (unsigned int) time(NULL));
03949 initstate((unsigned int) getpid() * 65536 + (unsigned int) time(NULL), randompool, sizeof(randompool));
03950
03951 if (init_logger()) {
03952 printf("%s", term_quit());
03953 exit(1);
03954 }
03955
03956 threadstorage_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 }