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