154 #undef sched_setscheduler
156 #include <sys/time.h>
161 #include <sys/wait.h>
163 #include <sys/resource.h>
166 #include <sys/stat.h>
167 #if defined(HAVE_SYSINFO)
168 #include <sys/sysinfo.h>
169 #elif defined(HAVE_SYSCTL)
170 #include <sys/param.h>
171 #include <sys/sysctl.h>
172 #include <sys/vmmeter.h>
173 #if defined(__FreeBSD__) || defined(__DragonFly__)
174 #include <vm/vm_param.h>
176 #if defined(HAVE_SWAPCTL)
177 #include <sys/swap.h>
181 #include <histedit.h>
184 int daemon(
int,
int);
185 #include <sys/loadavg.h>
189 #include <sys/prctl.h>
191 #include <sys/capability.h>
224 #include "asterisk/buildinfo.h"
226 #include "asterisk/poll-compat.h"
237 #include "asterisk/stasis_system.h"
247 #include "../defaults.h"
292 #define AF_LOCAL AF_UNIX
293 #define PF_LOCAL PF_UNIX
296 #define AST_MAX_CONNECTS 128
300 #define COPYRIGHT_TAG "Copyright (C) 1999 - 2022, Sangoma Technologies Corporation and others."
303 #define WELCOME_MESSAGE \
304 ast_verbose("Asterisk %s, " COPYRIGHT_TAG "\n" \
305 "Created by Mark Spencer <markster@digium.com>\n" \
306 "Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n" \
307 "This is free software, with components licensed under the GNU General Public\n" \
308 "License version 2 and other licenses; you are welcome to redistribute it under\n" \
309 "certain conditions. Type 'core show license' for details.\n" \
310 "=========================================================================\n" \
311 "This package has been modified for the PLD Linux distribution\n" \
312 "Please report all bugs to http://bugs.pld-linux.org/\n" \
313 "=========================================================================\n", ast_get_version()) \
339 struct timeval ast_startuptime;
340 struct timeval ast_lastreloadtime;
342 static History *el_hist;
344 static char *remotehostname;
346 struct console consoles[AST_MAX_CONNECTS];
348 static int ast_el_add_history(
const char *);
349 static int ast_el_read_history(
const char *);
350 static int ast_el_write_history(
const char *);
352 static void ast_el_read_default_histfile(
void);
353 static void ast_el_write_default_histfile(
void);
355 static void asterisk_daemon(
int isroot,
const char *runuser,
const char *rungroup);
357 static char *_argv[256];
386 static int restartnow;
387 static pthread_t consolethread = AST_PTHREADT_NULL;
388 static pthread_t mon_sig_flags;
389 static int canary_pid = 0;
390 static char canary_filename[128];
391 static int multi_thread_safe;
393 static char randompool[256];
396 static cap_t child_cap;
399 static int sig_alert_pipe[2] = { -1, -1 };
401 unsigned int need_reload:1;
402 unsigned int need_quit:1;
403 unsigned int need_quit_handler:1;
404 unsigned int need_el_end:1;
407 #if !defined(LOW_MEMORY)
417 void ast_register_thread(
char *name)
424 ast_assert(multi_thread_safe);
425 new->id = pthread_self();
433 void ast_unregister_thread(
void *
id)
438 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&
thread_list, x, list) {
439 if ((
void *) x->id ==
id) {
440 AST_RWLIST_REMOVE_CURRENT(list);
444 AST_RWLIST_TRAVERSE_SAFE_END;
453 static int print_file(
int fd,
char *desc,
const char *filename)
457 if (!(f = fopen(filename,
"r"))) {
460 ast_cli(fd,
"%s", desc);
461 while ((c = fgetc(f)) != EOF) {
462 ast_cli(fd,
"%c", c);
475 struct rlimit limits;
476 char pbx_uuid[AST_UUID_STR_LEN];
477 #if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
483 e->
command =
"core show settings";
484 e->
usage =
"Usage: core show settings\n"
485 " Show core misc settings";
494 ast_cli(a->fd,
"\nPBX Core settings\n");
495 ast_cli(a->fd,
"-----------------\n");
502 ast_cli(a->fd,
" Maximum calls: Not set\n");
504 if (getrlimit(RLIMIT_NOFILE, &limits)) {
505 ast_cli(a->fd,
" Maximum open file handles: Error because of %s\n", strerror(errno));
506 }
else if (limits.rlim_cur == RLIM_INFINITY) {
507 ast_cli(a->fd,
" Maximum open file handles: Unlimited\n");
509 ast_cli(a->fd,
" Maximum open file handles: %d (is) %d (requested)\n", (
int) limits.rlim_cur,
ast_option_maxfiles);
511 ast_cli(a->fd,
" Maximum open file handles: %d\n", (
int) limits.rlim_cur);
518 ast_cli(a->fd,
" Dump core on crash: %s\n", ast_opt_dump_core ?
"Yes" :
"No");
519 print_file(a->fd,
" Core dump file: ",
"/proc/sys/kernel/core_pattern");
521 #if defined(HAVE_SYSINFO)
526 ast_cli(a->fd,
" Startup time: %s\n", buf);
530 ast_cli(a->fd,
" Last reload time: %s\n", buf);
532 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);
533 ast_cli(a->fd,
" System name: %s\n", ast_config_AST_SYSTEM_NAME);
534 ast_cli(a->fd,
" Entity ID: %s\n", eid_str);
535 ast_cli(a->fd,
" PBX UUID: %s\n", pbx_uuid);
536 ast_cli(a->fd,
" Default language: %s\n", ast_defaultlanguage);
538 ast_cli(a->fd,
" User name and group: %s/%s\n", ast_config_AST_RUN_USER, ast_config_AST_RUN_GROUP);
539 #if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
540 #if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
541 #define eaccess euidaccess
543 if (!getcwd(dir,
sizeof(dir))) {
544 if (eaccess(dir, R_OK | X_OK | F_OK)) {
545 ast_cli(a->fd,
" Running directory: %s\n",
"Unable to access");
547 ast_cli(a->fd,
" Running directory: %s (%s)\n", dir,
"Unable to access");
550 ast_cli(a->fd,
" Running directory: %s\n", dir);
553 ast_cli(a->fd,
" Executable includes: %s\n", ast_test_flag(&ast_options,
AST_OPT_FLAG_EXEC_INCLUDES) ?
"Enabled" :
"Disabled");
556 ast_cli(a->fd,
" Generic PLC: %s\n", ast_test_flag(&ast_options,
AST_OPT_FLAG_GENERIC_PLC) ?
"Enabled" :
"Disabled");
558 ast_cli(a->fd,
" Hide Msg Chan AMI events: %s\n", ast_opt_hide_messaging_ami_events ?
"Enabled" :
"Disabled");
559 ast_cli(a->fd,
" Sounds search custom dir: %s\n", ast_opt_sounds_search_custom ?
"Enabled" :
"Disabled");
561 #if !defined(LOW_MEMORY)
562 ast_cli(a->fd,
" Cache media frames: %s\n", ast_opt_cache_media_frames ?
"Enabled" :
"Disabled");
564 ast_cli(a->fd,
" RTP use dynamic payloads: %u\n", ast_option_rtpusedynamic);
567 ast_cli(a->fd,
" RTP dynamic payload types: %u,%u-%u\n",
568 ast_option_rtpptdynamic,
571 ast_cli(a->fd,
" RTP dynamic payload types: %u-%u,%u-%u\n",
575 ast_cli(a->fd,
" RTP dynamic payload types: %u-%u\n",
579 ast_cli(a->fd,
"\n* Subsystems\n");
580 ast_cli(a->fd,
" -------------\n");
583 ast_cli(a->fd,
" Call data records: %s\n",
ast_cdr_is_enabled() ?
"Enabled" :
"Disabled");
584 ast_cli(a->fd,
" Realtime Architecture (ARA): %s\n",
ast_realtime_enabled() ?
"Enabled" :
"Disabled");
588 ast_cli(a->fd,
"\n* Directories\n");
589 ast_cli(a->fd,
" -------------\n");
590 ast_cli(a->fd,
" Configuration file: %s\n", ast_config_AST_CONFIG_FILE);
591 ast_cli(a->fd,
" Configuration directory: %s\n", ast_config_AST_CONFIG_DIR);
592 ast_cli(a->fd,
" Module directory: %s\n", ast_config_AST_MODULE_DIR);
593 ast_cli(a->fd,
" Spool directory: %s\n", ast_config_AST_SPOOL_DIR);
594 ast_cli(a->fd,
" Log directory: %s\n", ast_config_AST_LOG_DIR);
595 ast_cli(a->fd,
" Run/Sockets directory: %s\n", ast_config_AST_RUN_DIR);
596 ast_cli(a->fd,
" PID file: %s\n", ast_config_AST_PID);
597 ast_cli(a->fd,
" VarLib directory: %s\n", ast_config_AST_VAR_DIR);
598 ast_cli(a->fd,
" Data directory: %s\n", ast_config_AST_DATA_DIR);
599 ast_cli(a->fd,
" ASTDB: %s\n", ast_config_AST_DB);
600 ast_cli(a->fd,
" IAX2 Keys directory: %s\n", ast_config_AST_KEY_DIR);
601 ast_cli(a->fd,
" AGI Scripts directory: %s\n", ast_config_AST_AGI_DIR);
602 ast_cli(a->fd,
" Cache directory: %s\n", ast_config_AST_CACHE_DIR);
603 ast_cli(a->fd,
"\n\n");
613 e->
command =
"core show threads";
615 "Usage: core show threads\n"
616 " List threads currently active in the system.\n";
624 ast_cli(a->fd,
"%p %d %s\n", (
void *)cur->id, cur->lwp, cur->name);
628 ast_cli(a->fd,
"%d threads listed.\n", count);
632 #if defined (HAVE_SYSCTL) && defined(HAVE_SWAPCTL)
637 static int swapmode(
int *used,
int *total)
639 struct swapent *swdev;
640 int nswap, rnswap, i;
642 nswap = swapctl(SWAP_NSWAP, 0, 0);
650 rnswap = swapctl(SWAP_STATS, swdev, nswap);
660 for (i = 0; i < nswap; i++) {
661 if (swdev[i].se_flags & SWF_ENABLE) {
662 *used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
663 *total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
671 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
675 uint64_t physmem, freeram;
676 #if defined(HAVE_SYSINFO) || defined(HAVE_SWAPCTL)
678 uint64_t freeswap = 0;
682 #if defined(HAVE_SYSINFO)
683 struct sysinfo sys_info;
684 #elif defined(HAVE_SYSCTL)
685 static int pageshift;
686 struct vmtotal vmtotal;
687 struct timeval boottime;
689 int mib[2], pagesize;
690 #if defined(HAVE_SWAPCTL)
698 e->
command =
"core show sysinfo";
700 "Usage: core show sysinfo\n"
701 " List current system information.\n";
707 #if defined(HAVE_SYSINFO)
709 uptime = sys_info.uptime / 3600;
710 physmem = sys_info.totalram * sys_info.mem_unit;
711 freeram = (sys_info.freeram * sys_info.mem_unit) / 1024;
712 totalswap = (sys_info.totalswap * sys_info.mem_unit) / 1024;
713 freeswap = (sys_info.freeswap * sys_info.mem_unit) / 1024;
714 nprocs = sys_info.procs;
715 #elif defined(HAVE_SYSCTL)
719 mib[1] = KERN_BOOTTIME;
720 len =
sizeof(boottime);
721 if (sysctl(mib, 2, &boottime, &len, NULL, 0) != -1) {
722 uptime = now - boottime.tv_sec;
724 uptime = uptime/3600;
727 #if defined(HW_PHYSMEM64)
728 mib[1] = HW_PHYSMEM64;
732 len =
sizeof(physmem);
733 sysctl(mib, 2, &physmem, &len, NULL, 0);
735 pagesize = getpagesize();
737 while (pagesize > 1) {
748 len =
sizeof(vmtotal);
749 sysctl(mib, 2, &vmtotal, &len, NULL, 0);
750 freeram = (vmtotal.t_free << pageshift);
752 #if defined(HAVE_SWAPCTL)
753 swapmode(&usedswap, &totalswap);
754 freeswap = (totalswap - usedswap);
757 #if defined(__OpenBSD__)
759 mib[1] = KERN_NPROCS;
760 len =
sizeof(nprocs);
761 sysctl(mib, 2, &nprocs, &len, NULL, 0);
765 ast_cli(a->fd,
"\nSystem Statistics\n");
766 ast_cli(a->fd,
"-----------------\n");
767 ast_cli(a->fd,
" System Uptime: %ld hours\n", uptime);
768 ast_cli(a->fd,
" Total RAM: %" PRIu64
" KiB\n", physmem / 1024);
769 ast_cli(a->fd,
" Free RAM: %" PRIu64
" KiB\n", freeram);
770 #if defined(HAVE_SYSINFO)
771 ast_cli(a->fd,
" Buffer RAM: %" PRIu64
" KiB\n", ((uint64_t) sys_info.bufferram * sys_info.mem_unit) / 1024);
773 #if defined(HAVE_SYSINFO) || defined(HAVE_SWAPCTL)
774 ast_cli(a->fd,
" Total Swap Space: %d KiB\n", totalswap);
775 ast_cli(a->fd,
" Free Swap Space: %" PRIu64
" KiB\n\n", freeswap);
777 ast_cli(a->fd,
" Number of Processes: %d \n\n", nprocs);
804 #if !defined(LOW_MEMORY)
808 if (prof_data == NULL) {
810 if (prof_data == NULL)
812 prof_data->entries = 0;
813 prof_data->max_size = n;
815 if (prof_data->entries >= prof_data->max_size) {
817 n = prof_data->max_size + 20;
822 prof_data->max_size = n;
824 n = prof_data->entries++;
826 prof_data->e[n].value = 0;
827 prof_data->e[n].events = 0;
828 prof_data->e[n].mark = 0;
829 prof_data->e[n].scale = scale;
836 int64_t ast_profile(
int i, int64_t delta)
838 #if !defined(LOW_MEMORY)
839 if (!prof_data || i < 0 || i > prof_data->entries)
841 if (prof_data->e[i].scale > 1)
842 delta /= prof_data->e[i].scale;
843 prof_data->e[i].value += delta;
844 prof_data->e[i].events++;
845 return prof_data->e[i].value;
851 #if !defined(LOW_MEMORY)
855 #if defined ( __i686__) && (defined(__FreeBSD__) || defined(__NetBSD__) || defined(linux))
856 #if defined(__FreeBSD__)
857 #include <machine/cpufunc.h>
858 #elif defined(__NetBSD__) || defined(linux)
859 static __inline uint64_t
864 __asm __volatile(
".byte 0x0f, 0x31" :
"=A" (rv));
869 static __inline uint64_t
877 int64_t ast_mark(
int i,
int startstop)
879 #if !defined(LOW_MEMORY)
880 if (!prof_data || i < 0 || i > prof_data->entries)
883 prof_data->e[i].mark = rdtsc();
885 prof_data->e[i].mark = (rdtsc() - prof_data->e[i].mark);
886 if (prof_data->e[i].scale > 1)
887 prof_data->e[i].mark /= prof_data->e[i].scale;
888 prof_data->e[i].value += prof_data->e[i].mark;
889 prof_data->e[i].events++;
891 return prof_data->e[i].mark;
897 #if !defined(LOW_MEMORY)
898 #define DEFINE_PROFILE_MIN_MAX_VALUES min = 0; \
899 max = prof_data->entries;\
901 if (isdigit(a->argv[3][0])) { \
902 min = atoi(a->argv[3]); \
903 if (a->argc == 5 && strcmp(a->argv[4], "-")) \
904 max = atoi(a->argv[4]); \
906 search = a->argv[3]; \
908 if (max > prof_data->entries) \
909 max = prof_data->entries;
914 const char *search = NULL;
917 e->
command =
"core show profile";
918 e->
usage =
"Usage: core show profile\n"
919 " show profile information";
925 if (prof_data == NULL)
928 DEFINE_PROFILE_MIN_MAX_VALUES;
929 ast_cli(a->fd,
"profile values (%d, allocated %d)\n-------------------\n",
930 prof_data->entries, prof_data->max_size);
931 ast_cli(a->fd,
"%6s %8s %10s %12s %12s %s\n",
"ID",
"Scale",
"Events",
932 "Value",
"Average",
"Name");
933 for (i = min; i < max; i++) {
935 if (!search || strstr(entry->name, search))
936 ast_cli(a->fd,
"%6d: [%8ld] %10ld %12lld %12lld %s\n",
939 (
long)entry->events, (
long long)entry->value,
940 (
long long)(entry->events ? entry->value / entry->events : entry->value),
949 const char *search = NULL;
952 e->
command =
"core clear profile";
953 e->
usage =
"Usage: core clear profile\n"
954 " clear profile information";
960 if (prof_data == NULL)
963 DEFINE_PROFILE_MIN_MAX_VALUES;
964 for (i= min; i < max; i++) {
965 if (!search || strstr(prof_data->e[i].name, search)) {
966 prof_data->e[i].value = 0;
967 prof_data->e[i].events = 0;
972 #undef DEFINE_PROFILE_MIN_MAX_VALUES
978 return ast_db_get(
"pbx",
"UUID", pbx_uuid, length);
981 static void publish_fully_booted(
void)
985 int lastreloaded = 0;
989 if (ast_startuptime.tv_sec) {
990 tmp =
ast_tvsub(curtime, ast_startuptime);
991 uptime = (int) tmp.tv_sec;
994 if (ast_lastreloadtime.tv_sec) {
995 tmp =
ast_tvsub(curtime, ast_lastreloadtime);
996 lastreloaded = (int) tmp.tv_sec;
1000 "Status",
"Fully Booted",
1002 "LastReload", lastreloaded);
1007 static void ast_run_atexits(
int run_cleanups)
1013 if (ae->func && (!ae->is_cleanup || run_cleanups)) {
1021 static void __ast_unregister_atexit(
void (*func)(
void))
1026 if (ae->func == func) {
1035 static int register_atexit(
void (*func)(
void),
int is_cleanup)
1044 ae->is_cleanup = is_cleanup;
1047 __ast_unregister_atexit(func);
1056 return register_atexit(func, 0);
1061 return register_atexit(func, 1);
1067 __ast_unregister_atexit(func);
1072 static int fdsend(
int fd,
const char *s)
1074 return write(fd, s, strlen(s) + 1);
1078 static int fdprint(
int fd,
const char *s)
1080 return write(fd, s, strlen(s));
1088 static struct sigaction null_sig_handler = {
1090 .sa_flags = SA_RESTART,
1093 static struct sigaction ignore_sig_handler = {
1094 .sa_handler = SIG_IGN,
1097 AST_MUTEX_DEFINE_STATIC(safe_system_lock);
1102 static struct sigaction safe_system_prev_handler;
1108 ast_mutex_lock(&safe_system_lock);
1109 level = safe_system_level++;
1113 sigaction(SIGCHLD, &null_sig_handler, &safe_system_prev_handler);
1116 ast_mutex_unlock(&safe_system_lock);
1123 ast_mutex_lock(&safe_system_lock);
1128 sigaction(SIGCHLD, &safe_system_prev_handler, NULL);
1131 ast_mutex_unlock(&safe_system_lock);
1139 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
1142 #ifdef HAVE_WORKING_FORK
1150 cap_set_proc(child_cap);
1152 #ifdef HAVE_WORKING_FORK
1153 if (ast_opt_high_priority) {
1160 #ifdef HAVE_WORKING_FORK
1185 ast_log(LOG_WARNING,
"Fork failed: %s\n", strerror(errno));
1188 ast_log(LOG_WARNING,
"Fork failed: %s\n", strerror(ENOTSUP));
1200 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
1205 res = waitpid(pid, &status, 0);
1207 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
1210 if (errno != EINTR) {
1240 execl(
"/bin/sh",
"/bin/sh",
"-c", s, (
char *) NULL);
1255 if (level >= NUMLOGLEVELS) {
1256 level = NUMLOGLEVELS - 1;
1259 for (x = 0;x < AST_MAX_CONNECTS; x++) {
1260 if (fd == consoles[x].fd) {
1265 consoles[x].
levels[level] = state ? 0 : 1;
1277 for (x = 0;x < AST_MAX_CONNECTS; x++) {
1278 if (fd == consoles[x].fd) {
1279 if (consoles[x].mute) {
1280 consoles[x].
mute = 0;
1282 ast_cli(fd,
"Console is not muted anymore.\n");
1284 consoles[x].
mute = 1;
1286 ast_cli(fd,
"Console is muted.\n");
1291 ast_cli(fd,
"Couldn't find remote console.\n");
1301 for (x = 0; x < AST_MAX_CONNECTS; ++x) {
1302 if (consoles[x].fd < 0
1304 || consoles[x].
levels[level]
1305 || (level == __LOG_VERBOSE && consoles[x].
option_verbose < sublevel)) {
1308 fdprint(consoles[x].p[1],
string);
1321 static int console_print(
const char *s);
1326 console_print(message);
1329 if (ast_opt_console && consolethread != AST_PTHREADT_NULL) {
1330 pthread_kill(consolethread, SIGURG);
1344 for (x = 0; x < AST_MAX_CONNECTS; ++x) {
1345 if (consoles[x].fd < 0) {
1348 fdprint(consoles[x].p[1],
string);
1359 fputs(
string, stdout);
1366 static pthread_t lthread;
1380 #if defined(SO_PEERCRED)
1381 #ifdef HAVE_STRUCT_SOCKPEERCRED_UID
1382 #define HAVE_STRUCT_UCRED_UID
1383 struct sockpeercred cred;
1387 socklen_t len =
sizeof(cred);
1389 #if defined(HAVE_GETPEEREID)
1397 result = read(fd, buffer, size);
1402 #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID))
1403 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len)) {
1406 #if defined(HAVE_STRUCT_UCRED_UID)
1414 #elif defined(HAVE_GETPEEREID)
1415 if (getpeereid(fd, &uid, &gid)) {
1428 static void *netconsole(
void *vconsole)
1430 struct console *con = vconsole;
1431 char hostname[MAXHOSTNAMELEN] =
"";
1434 const char *
const end_buf = inbuf +
sizeof(
inbuf);
1435 char *start_read =
inbuf;
1437 struct pollfd fds[2];
1439 if (gethostname(hostname,
sizeof(hostname)-1))
1441 snprintf(outbuf,
sizeof(outbuf),
"%s/%ld/%s\n", hostname, (
long)ast_mainpid,
ast_get_version());
1442 fdprint(con->
fd, outbuf);
1445 fds[0].fd = con->
fd;
1446 fds[0].events = POLLIN;
1448 fds[1].fd = con->
p[0];
1449 fds[1].events = POLLIN;
1452 res = ast_poll(fds, 2, -1);
1455 ast_log(LOG_WARNING,
"poll returned < 0: %s\n", strerror(errno));
1458 if (fds[0].revents) {
1459 int cmds_read, bytes_read;
1460 if ((bytes_read =
read_credentials(con->
fd, start_read, end_buf - start_read, con)) < 1) {
1464 if (strncmp(inbuf,
"cli quit after ", 15) == 0) {
1473 if (start_read + bytes_read < end_buf) {
1474 start_read += bytes_read;
1476 ast_log(LOG_ERROR,
"Command too long! Skipping\n");
1481 if (start_read[bytes_read - 1] ==
'\0') {
1489 while (cmds_read-- && (start_read = strchr(start_read,
'\0'))) {
1492 memmove(inbuf, start_read, end_buf - start_read);
1493 start_read = end_buf - start_read +
inbuf;
1495 if (fds[1].revents) {
1498 ast_log(LOG_ERROR,
"read returned %d\n", res);
1501 res = write(con->
fd, outbuf, res);
1507 if (!ast_opt_hide_connect) {
1508 ast_verb(3,
"Remote UNIX connection disconnected\n");
1518 static void *listener(
void *unused)
1520 struct sockaddr_un sunaddr;
1525 struct pollfd fds[1];
1532 fds[0].events = POLLIN;
1533 poll_result = ast_poll(fds, 1, -1);
1534 pthread_testcancel();
1535 if (poll_result < 0) {
1536 if (errno != EINTR) {
1537 ast_log(LOG_WARNING,
"poll returned error: %s\n", strerror(errno));
1541 len =
sizeof(sunaddr);
1542 s = accept(
ast_socket, (
struct sockaddr *)&sunaddr, &len);
1545 ast_log(LOG_WARNING,
"Accept returned %d: %s\n", s, strerror(errno));
1547 #if defined(SO_PASSCRED)
1550 if (setsockopt(s, SOL_SOCKET, SO_PASSCRED, &sckopt,
sizeof(sckopt)) < 0) {
1551 ast_log(LOG_WARNING,
"Unable to turn on socket credentials passing\n");
1556 for (x = 0; x < AST_MAX_CONNECTS; x++) {
1557 if (consoles[x].fd >= 0) {
1560 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
1561 ast_log(LOG_ERROR,
"Unable to create pipe: %s\n", strerror(errno));
1562 fdprint(s,
"Server failed to create pipe\n");
1567 consoles[x].
mute = 1;
1570 consoles[x].
uid = -2;
1571 consoles[x].
gid = -2;
1575 if (ast_pthread_create_detached_background(&consoles[x].t, NULL, netconsole, &consoles[x])) {
1576 consoles[x].
fd = -1;
1577 ast_log(LOG_ERROR,
"Unable to spawn thread to handle connection: %s\n", strerror(errno));
1578 close(consoles[x].p[0]);
1579 close(consoles[x].p[1]);
1580 fdprint(s,
"Server failed to spawn thread\n");
1585 if (x >= AST_MAX_CONNECTS) {
1586 fdprint(s,
"No more connections allowed\n");
1587 ast_log(LOG_WARNING,
"No more connections allowed\n");
1589 }
else if ((consoles[x].fd > -1) && (!ast_opt_hide_connect)) {
1590 ast_verb(3,
"Remote UNIX connection\n");
1598 static int ast_makesocket(
void)
1600 struct sockaddr_un sunaddr;
1606 for (x = 0; x < AST_MAX_CONNECTS; x++) {
1607 consoles[x].
fd = -1;
1616 unlink(ast_config_AST_SOCKET);
1617 ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
1619 ast_log(LOG_WARNING,
"Unable to create control socket: %s\n", strerror(errno));
1622 memset(&sunaddr, 0,
sizeof(sunaddr));
1623 sunaddr.sun_family = AF_LOCAL;
1624 ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET,
sizeof(sunaddr.sun_path));
1625 res = bind(
ast_socket, (
struct sockaddr *)&sunaddr,
sizeof(sunaddr));
1627 ast_log(LOG_WARNING,
"Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1634 ast_log(LOG_WARNING,
"Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1641 if (ast_pthread_create_background(<hread, NULL, listener, NULL)) {
1642 ast_log(LOG_WARNING,
"Unable to create listener thread.\n");
1653 if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {
1655 if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL)
1656 ast_log(LOG_WARNING,
"Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
1661 if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) {
1663 if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL)
1664 ast_log(LOG_WARNING,
"Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
1669 if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
1670 ast_log(LOG_WARNING,
"Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1672 if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) {
1675 sscanf(ast_config_AST_CTL_PERMISSIONS,
"%30o", &p1);
1677 if ((chmod(ast_config_AST_SOCKET, p)) < 0)
1678 ast_log(LOG_WARNING,
"Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1684 static int ast_tryconnect(
void)
1686 struct sockaddr_un sunaddr;
1690 fprintf(stderr,
"Unable to create socket: %s\n", strerror(errno));
1693 memset(&sunaddr, 0,
sizeof(sunaddr));
1694 sunaddr.sun_family = AF_LOCAL;
1695 ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET,
sizeof(sunaddr.sun_path));
1696 res = connect(
ast_consock, (
struct sockaddr *)&sunaddr,
sizeof(sunaddr));
1716 static struct sigaction urg_handler = {
1720 static void _hup_handler(
int num)
1722 int save_errno = errno;
1728 execvp(_argv[0], _argv);
1731 printf(
"Received HUP signal -- Reloading configs\n");
1732 sig_flags.need_reload = 1;
1734 fprintf(stderr,
"hup_handler: write() failed: %s\n", strerror(errno));
1739 static struct sigaction hup_handler = {
1740 .sa_handler = _hup_handler,
1741 .sa_flags = SA_RESTART,
1744 static void _child_handler(
int sig)
1747 int n, status, save_errno = errno;
1752 for (n = 0; waitpid(-1, &status, WNOHANG) > 0; n++)
1755 printf(
"Huh? Child handler, but nobody there?\n");
1759 static struct sigaction child_handler = {
1760 .sa_handler = _child_handler,
1761 .sa_flags = SA_RESTART,
1767 if (getenv(
"TERM") && strstr(getenv(
"TERM"),
"xterm"))
1768 fprintf(stdout,
"\033]2;%s\007", text);
1771 static void set_icon(
char *text)
1773 if (getenv(
"TERM") && strstr(getenv(
"TERM"),
"xterm"))
1774 fprintf(stdout,
"\033]1;%s\007", text);
1785 return sched_getscheduler(0);
1793 return (getpriority(PRIO_PROCESS, 0) < 0);
1800 #if !defined(__linux__)
1803 #elif defined(LOW_MEMORY)
1804 ast_log(LOG_WARNING,
"Unable to enumerate all threads to update priority\n");
1808 struct sched_param sched;
1809 char const *policy_str;
1812 memset(&sched, 0,
sizeof(sched));
1815 policy_str =
"realtime";
1816 sched.sched_priority = 10;
1818 policy = SCHED_OTHER;
1819 policy_str =
"regular";
1820 sched.sched_priority = 0;
1822 if (sched_setscheduler(getpid(), policy, &sched)) {
1823 ast_log(LOG_WARNING,
"Unable to set %s thread priority on main thread\n", policy_str);
1826 ast_verb(1,
"Setting %s thread priority on all threads\n", policy_str);
1830 sched_setscheduler(cur->lwp, policy, &sched);
1843 struct sched_param sched;
1844 memset(&sched, 0,
sizeof(sched));
1847 sched.sched_priority = 10;
1848 if (sched_setscheduler(0, SCHED_RR, &sched)) {
1852 sched.sched_priority = 0;
1854 sched_setscheduler(0, SCHED_OTHER, &sched);
1858 if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
1859 ast_log(LOG_WARNING,
"Unable to set high priority\n");
1862 ast_verb(1,
"Set to high priority\n");
1865 setpriority(PRIO_PROCESS, 0, 0);
1883 int shutdown_aborted = 0;
1885 ast_mutex_lock(&safe_system_lock);
1889 shutdown_aborted = 1;
1891 ast_mutex_unlock(&safe_system_lock);
1892 return shutdown_aborted;
1899 static void ast_begin_shutdown(
void)
1901 ast_mutex_lock(&safe_system_lock);
1905 ast_mutex_unlock(&safe_system_lock);
1911 static void quit_handler(
int num,
shutdown_nice_t niceness,
int restart)
1913 if (can_safely_quit(niceness, restart)) {
1920 #define SHUTDOWN_TIMEOUT 15
1933 static int wait_for_channels_to_die(
shutdown_nice_t niceness,
int seconds)
1951 if (seconds < (now - start)) {
1968 ast_mutex_lock(&safe_system_lock);
1971 ast_mutex_unlock(&safe_system_lock);
1972 ast_verbose(
"Ignoring asterisk %s request, already in progress.\n", restart ?
"restart" :
"shutdown");
1975 shuttingdown = niceness;
1976 ast_mutex_unlock(&safe_system_lock);
1993 ast_begin_shutdown();
1994 if (ast_opt_console) {
1995 ast_verb(0,
"Beginning asterisk %s....\n", restart ?
"restart" :
"shutdown");
1998 waited |= wait_for_channels_to_die(niceness, SHUTDOWN_TIMEOUT);
2001 ast_begin_shutdown();
2003 if (ast_opt_console) {
2004 ast_verb(0,
"Waiting for inactivity to perform %s...\n", restart ?
"restart" :
"halt");
2006 waited |= wait_for_channels_to_die(niceness, -1);
2012 ast_mutex_lock(&safe_system_lock);
2013 if (shuttingdown != niceness) {
2015 ast_verb(0,
"Asterisk %s cancelled.\n", restart ?
"restart" :
"shutdown");
2017 ast_mutex_unlock(&safe_system_lock);
2023 ast_mutex_unlock(&safe_system_lock);
2026 ast_begin_shutdown();
2028 waited |= wait_for_channels_to_die(
SHUTTING_DOWN, SHUTDOWN_TIMEOUT);
2030 ast_mutex_lock(&safe_system_lock);
2033 ast_mutex_unlock(&safe_system_lock);
2048 int active_channels;
2049 struct ast_json *json_object = NULL;
2053 ast_verb(0,
"Some modules could not be unloaded, switching to fast shutdown\n");
2057 if (!restart && !ast_opt_remote) {
2060 if (ast_opt_console || (ast_opt_remote && !ast_opt_exec)) {
2061 ast_el_write_default_histfile();
2062 if (consolethread == AST_PTHREADT_NULL || consolethread == pthread_self()) {
2067 if (el_hist != NULL) {
2068 history_end(el_hist);
2070 }
else if (!restart) {
2071 sig_flags.need_el_end = 1;
2072 pthread_kill(consolethread, SIGURG);
2079 if (!ast_opt_remote) {
2081 "Shutdown", active_channels ?
"Uncleanly" :
"Cleanly",
2082 "Restart", restart ?
"True" :
"False");
2087 ast_verb(0,
"Asterisk %s ending (%d).\n",
2088 active_channels ?
"uncleanly" :
"cleanly", num);
2090 ast_verb(0,
"Executing last minute cleanups\n");
2091 ast_run_atexits(run_cleanups);
2093 ast_debug(1,
"Asterisk ending (%d).\n", num);
2095 pthread_cancel(lthread);
2099 unlink(ast_config_AST_SOCKET);
2101 pthread_kill(lthread, SIGURG);
2102 pthread_join(lthread, NULL);
2106 if (!ast_opt_remote)
2107 unlink(ast_config_AST_PID);
2109 printf(
"%s", term_quit());
2112 ast_verb(0,
"Preparing for Asterisk restart...\n");
2114 for (i = 3; i < 32768; i++) {
2115 fcntl(i, F_SETFD, FD_CLOEXEC);
2117 ast_verb(0,
"Asterisk is now restarting...\n");
2126 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
2127 pthread_kill(consolethread, SIGHUP);
2131 execvp(_argv[0], _argv);
2142 static void __quit_handler(
int num)
2144 sig_flags.need_quit = 1;
2146 fprintf(stderr,
"quit_handler: write() failed: %s\n", strerror(errno));
2152 static void __remote_quit_handler(
int num)
2154 sig_flags.need_quit = 1;
2157 static void set_header(
char *outbuf,
int maxout,
char level)
2165 case 1: cmp = VERBOSE_PREFIX_1;
2167 case 2: cmp = VERBOSE_PREFIX_2;
2169 case 3: cmp = VERBOSE_PREFIX_3;
2171 case 4: cmp = VERBOSE_PREFIX_4;
2173 case 5: cmp = VERBOSE_PREFIX_5;
2175 case 6: cmp = VERBOSE_PREFIX_6;
2177 case 7: cmp = VERBOSE_PREFIX_7;
2179 case 8: cmp = VERBOSE_PREFIX_8;
2181 case 9: cmp = VERBOSE_PREFIX_9;
2183 default: cmp = VERBOSE_PREFIX_10;
2187 if (ast_opt_timestamp) {
2194 snprintf(outbuf, maxout,
"%s%s%s%s%s%s",
2195 ast_opt_timestamp ?
"[" :
"",
2196 ast_opt_timestamp ? date :
"",
2197 ast_opt_timestamp ?
"] " :
"",
2204 char verbose_line_level;
2207 static int console_state_init(
void *ptr)
2210 state->verbose_line_level = 0;
2216 static int console_print(
const char *s)
2224 unsigned int newline;
2227 if (VERBOSE_HASMAGIC(s)) {
2231 state->verbose_line_level = VERBOSE_MAGIC2LEVEL(s);
2236 set_header(prefix,
sizeof(prefix), state->verbose_line_level);
2243 if ((s = strchr(c,
'\n'))) {
2247 s = strchr(c,
'\0');
2258 if (!ast_strlen_zero(prefix)) {
2259 fputs(prefix, stdout);
2263 if (fwrite(c,
sizeof(
char), num, stdout) < num) {
2277 state->verbose_line_level = 0;
2287 static int ast_all_zeros(
const char *s)
2298 static void consolehandler(
const char *s)
2300 printf(
"%s", term_end());
2304 if (!ast_all_zeros(s))
2305 ast_el_add_history(s);
2316 static int remoteconsolehandler(
const char *s)
2321 if (!ast_all_zeros(s))
2322 ast_el_add_history(s);
2324 while (isspace(*s)) {
2335 }
else if ((strncasecmp(s,
"quit", 4) == 0 || strncasecmp(s,
"exit", 4) == 0) &&
2336 (s[4] ==
'\0' || isspace(s[4]))) {
2348 e->
command =
"core show version";
2350 "Usage: core show version\n"
2351 " Shows Asterisk version information.\n";
2358 return CLI_SHOWUSAGE;
2359 ast_cli(a->fd,
"Asterisk %s built by %s @ %s on a %s running %s on %s\n",
2361 ast_build_machine, ast_build_os, ast_build_date);
2371 "Usage: core stop now\n"
2372 " Shuts down a running Asterisk immediately, hanging up all active calls .\n";
2379 if (a->argc != e->
args)
2380 return CLI_SHOWUSAGE;
2389 e->
command =
"core stop gracefully";
2391 "Usage: core stop gracefully\n"
2392 " Causes Asterisk to not accept new calls, and exit when all\n"
2393 " active calls have terminated normally.\n";
2400 if (a->argc != e->
args)
2401 return CLI_SHOWUSAGE;
2410 e->
command =
"core stop when convenient";
2412 "Usage: core stop when convenient\n"
2413 " Causes Asterisk to perform a shutdown when all active calls have ended.\n";
2420 if (a->argc != e->
args)
2421 return CLI_SHOWUSAGE;
2422 ast_cli(a->fd,
"Waiting for inactivity to perform halt\n");
2431 e->
command =
"core restart now";
2433 "Usage: core restart now\n"
2434 " Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
2442 if (a->argc != e->
args)
2443 return CLI_SHOWUSAGE;
2452 e->
command =
"core restart gracefully";
2454 "Usage: core restart gracefully\n"
2455 " Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
2456 " restart when all active calls have ended.\n";
2463 if (a->argc != e->
args)
2464 return CLI_SHOWUSAGE;
2473 e->
command =
"core restart when convenient";
2475 "Usage: core restart when convenient\n"
2476 " Causes Asterisk to perform a cold restart when all active calls have ended.\n";
2483 if (a->argc != e->
args)
2484 return CLI_SHOWUSAGE;
2485 ast_cli(a->fd,
"Waiting for inactivity to perform restart\n");
2494 e->
command =
"core abort shutdown";
2496 "Usage: core abort shutdown\n"
2497 " Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
2498 " call operations.\n";
2505 if (a->argc != e->
args)
2506 return CLI_SHOWUSAGE;
2519 "Usage: !<command>\n"
2520 " Executes a given shell command\n";
2528 static const char warranty_lines[] = {
2532 "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
2533 "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n"
2534 "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
2535 "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
2536 "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
2537 "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n"
2538 "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n"
2539 "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
2540 "REPAIR OR CORRECTION.\n"
2542 "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
2543 "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
2544 "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
2545 "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
2546 "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
2547 "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
2548 "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
2549 "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
2550 "POSSIBILITY OF SUCH DAMAGES.\n"
2557 e->
command =
"core show warranty";
2559 "Usage: core show warranty\n"
2560 " Shows the warranty (if any) for this copy of Asterisk.\n";
2566 ast_cli(a->fd,
"%s", warranty_lines);
2571 static const char license_lines[] = {
2573 "This program is free software; you can redistribute it and/or modify\n"
2574 "it under the terms of the GNU General Public License version 2 as\n"
2575 "published by the Free Software Foundation.\n"
2577 "This program also contains components licensed under other licenses.\n"
2580 "This program is distributed in the hope that it will be useful,\n"
2581 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2582 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
2583 "GNU General Public License for more details.\n"
2585 "You should have received a copy of the GNU General Public License\n"
2586 "along with this program; if not, write to the Free Software\n"
2587 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
2594 e->
command =
"core show license";
2596 "Usage: core show license\n"
2597 " Shows the license(s) for this copy of Asterisk.\n";
2603 ast_cli(a->fd,
"%s", license_lines);
2608 #define ASTERISK_PROMPT "*CLI> "
2619 AST_CLI_DEFINE(handle_stop_now,
"Shut down Asterisk immediately"),
2620 AST_CLI_DEFINE(handle_stop_gracefully,
"Gracefully shut down Asterisk"),
2621 AST_CLI_DEFINE(handle_stop_when_convenient,
"Shut down Asterisk at empty call volume"),
2622 AST_CLI_DEFINE(handle_restart_now,
"Restart Asterisk immediately"),
2623 AST_CLI_DEFINE(handle_restart_gracefully,
"Restart Asterisk gracefully"),
2624 AST_CLI_DEFINE(handle_restart_when_convenient,
"Restart Asterisk at empty call volume"),
2628 AST_CLI_DEFINE(handle_abort_shutdown,
"Cancel a running shutdown"),
2629 AST_CLI_DEFINE(show_warranty,
"Show the warranty (if any) for this copy of Asterisk"),
2630 AST_CLI_DEFINE(show_license,
"Show the license(s) for this copy of Asterisk"),
2631 AST_CLI_DEFINE(handle_version,
"Display version info"),
2632 AST_CLI_DEFINE(handle_bang,
"Execute a shell command"),
2633 #if !defined(LOW_MEMORY)
2634 AST_CLI_DEFINE(handle_show_threads,
"Show running threads"),
2635 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2638 AST_CLI_DEFINE(handle_show_profile,
"Display profiling info"),
2640 AST_CLI_DEFINE(handle_clear_profile,
"Clear profiling info"),
2644 static void send_rasterisk_connect_commands(
void)
2653 snprintf(buf,
sizeof(buf),
"core set verbose atleast %d silent",
option_verbose);
2658 snprintf(buf,
sizeof(buf),
"core set debug atleast %d",
option_debug);
2665 if (!ast_opt_mute) {
2668 printf(
"log and verbose output currently muted ('logger mute' to unmute)\n");
2672 #ifdef HAVE_LIBEDIT_IS_UNICODE
2673 #define CHAR_T_LIBEDIT wchar_t
2674 #define CHAR_TO_LIBEDIT(c) btowc(c)
2676 #define CHAR_T_LIBEDIT char
2677 #define CHAR_TO_LIBEDIT(c) c
2680 static int ast_el_read_char(EditLine *editline, CHAR_T_LIBEDIT *cp)
2684 struct pollfd fds[2];
2687 #define EL_BUF_SIZE 512
2688 char buf[EL_BUF_SIZE];
2693 fds[0].events = POLLIN;
2694 if (!ast_opt_exec) {
2695 fds[1].fd = STDIN_FILENO;
2696 fds[1].events = POLLIN;
2699 res = ast_poll(fds, max, -1);
2701 if (sig_flags.need_quit || sig_flags.need_quit_handler || sig_flags.need_el_end) {
2704 if (errno == EINTR) {
2707 fprintf(stderr,
"poll failed: %s\n", strerror(errno));
2711 if (!ast_opt_exec && fds[1].revents) {
2714 num_read = read(STDIN_FILENO, &c, 1);
2719 *cp = CHAR_TO_LIBEDIT(c);
2724 if (fds[0].revents) {
2728 fprintf(stderr,
"\nDisconnected from Asterisk server\n");
2729 if (!ast_opt_reconnect) {
2733 int reconnects_per_second = 20;
2735 fprintf(stderr,
"Attempting to reconnect for 30 seconds\n");
2736 for (tries = 0; tries < 30 * reconnects_per_second; tries++) {
2737 if (ast_tryconnect()) {
2738 fprintf(stderr,
"Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
2739 printf(
"%s", term_quit());
2741 send_rasterisk_connect_commands();
2745 usleep(1000000 / reconnects_per_second);
2747 if (tries >= 30 * reconnects_per_second) {
2748 fprintf(stderr,
"Failed to reconnect for 30 seconds. Quitting.\n");
2758 if (!ast_opt_exec && !lastpos) {
2759 if (write(STDOUT_FILENO,
"\r[0K", 5) < 0) {
2765 if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] ==
'\n') || (res >= 2 && buf[res-2] ==
'\n'))) {
2766 *cp = CHAR_TO_LIBEDIT(CC_REFRESH);
2774 *cp = CHAR_TO_LIBEDIT(
'\0');
2779 static struct ast_str *prompt = NULL;
2781 static char *cli_prompt(EditLine *editline)
2786 static int cli_prompt_changes = 0;
2790 if (prompt == NULL) {
2792 }
else if (!cli_prompt_changes) {
2798 if ((pfmt = getenv(
"ASTERISK_PROMPT"))) {
2801 while (*t !=
'\0') {
2803 char hostname[MAXHOSTNAMELEN] =
"";
2805 struct ast_tm tm = { 0, };
2806 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
2812 if (sscanf(t,
"%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
2815 }
else if (sscanf(t,
"%30d%n", &fgcolor, &i) == 1) {
2821 color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
2827 cli_prompt_changes++;
2831 if ((gr = getgrgid(getgid()))) {
2836 if (!gethostname(hostname,
sizeof(hostname) - 1)) {
2843 if (!gethostname(hostname,
sizeof(hostname) - 1)) {
2845 if ((dotptr = strchr(hostname,
'.'))) {
2853 #ifdef HAVE_GETLOADAVG
2856 if (sscanf(t,
"%30d", &which) == 1 && which > 0 && which <= 3) {
2858 getloadavg(list, 3);
2860 cli_prompt_changes++;
2871 cli_prompt_changes++;
2875 if ((pw = getpwuid(getuid()))) {
2900 remotehostname ? remotehostname :
"",
2916 while ((retstr = strsep(&buf,
" "))) {
2917 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF)) {
2924 goto vector_cleanup;
2929 goto vector_cleanup;
2941 static void ast_cli_display_match_list(
struct ast_vector_string *matches,
int max)
2954 for (numoutputline = 0; numoutputline < limit && idx <
AST_VECTOR_SIZE(matches); idx++) {
2959 if (!numoutputline) {
2963 fprintf(stdout,
"\n");
2968 static char *cli_complete(EditLine *editline,
int ch)
2973 int retval = CC_ERROR;
2977 LineInfo *lf = (LineInfo *)el_line(editline);
2979 savechr = *(
char *)lf->cursor;
2980 *(
char *)lf->cursor =
'\0';
2981 ptr = (
char *)lf->cursor;
2983 while (ptr > lf->buffer) {
2984 if (isspace(*ptr)) {
2992 len = lf->cursor - ptr;
2994 if (ast_opt_remote) {
2995 #define CMD_MATCHESARRAY "_COMMAND MATCHESARRAY \"%s\" \"%s\""
2999 int maxmbuf =
ast_asprintf(&mbuf, CMD_MATCHESARRAY, lf->buffer, ptr);
3001 if (maxmbuf == -1) {
3002 *((
char *) lf->cursor) = savechr;
3004 return (
char *)(CC_ERROR);
3012 while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
3013 if (mlen + 1024 > maxmbuf) {
3015 maxmbuf = mlen + 1024;
3019 *((
char *) lf->cursor) = savechr;
3021 return (
char *)(CC_ERROR);
3028 if (!strncmp(mbuf,
"Usage:", 6)) {
3051 matches = ast_el_strtoarr(mbuf);
3059 int maxlen, match_len;
3062 if (!ast_strlen_zero(best_match)) {
3063 el_deletestr(editline, (
int) len);
3064 el_insertstr(editline, best_match);
3065 retval = CC_REFRESH;
3070 el_insertstr(editline,
" ");
3071 retval = CC_REFRESH;
3076 if (match_len > maxlen) {
3081 fprintf(stdout,
"\n");
3082 ast_cli_display_match_list(matches, maxlen);
3083 retval = CC_REDISPLAY;
3089 *((
char *) lf->cursor) = savechr;
3091 return (
char *)(long)retval;
3094 static int ast_el_initialize(
void)
3097 char *editor, *editrc = getenv(
"EDITRC");
3099 if (!(editor = getenv(
"AST_EDITMODE"))) {
3100 if (!(editor = getenv(
"AST_EDITOR"))) {
3107 if (el_hist != NULL)
3108 history_end(el_hist);
3110 el = el_init(
"asterisk", stdin, stdout, stderr);
3111 el_set(el, EL_PROMPT, cli_prompt);
3113 el_set(el, EL_EDITMODE, 1);
3114 el_set(el, EL_EDITOR, editor);
3115 el_hist = history_init();
3116 if (!el || !el_hist)
3120 history(el_hist, &ev, H_SETSIZE, 100);
3122 el_set(el, EL_HIST, history, el_hist);
3124 el_set(el, EL_ADDFN,
"ed-complete",
"Complete argument", cli_complete);
3126 el_set(el, EL_BIND,
"^I",
"ed-complete", NULL);
3128 el_set(el, EL_BIND,
"?",
"ed-complete", NULL);
3130 el_set(el, EL_BIND,
"^D",
"ed-redisplay", NULL);
3132 el_set(el, EL_BIND,
"\\e[3~",
"ed-delete-next-char", NULL);
3134 el_set(el, EL_BIND,
"\\e[1~",
"ed-move-to-beg", NULL);
3135 el_set(el, EL_BIND,
"\\e[4~",
"ed-move-to-end", NULL);
3137 el_set(el, EL_BIND,
"\\eOC",
"vi-next-word", NULL);
3138 el_set(el, EL_BIND,
"\\eOD",
"vi-prev-word", NULL);
3141 el_source(el, editrc);
3147 #define MAX_HISTORY_COMMAND_LENGTH 256
3149 static int ast_el_add_history(
const char *buf)
3154 if (el_hist == NULL || el == NULL) {
3155 ast_el_initialize();
3157 if (strlen(buf) > (MAX_HISTORY_COMMAND_LENGTH - 1)) {
3164 if (!history(el_hist, &ev, H_FIRST) && strcmp(ev.str, stripped_buf) == 0) {
3168 return history(el_hist, &ev, H_ENTER, stripped_buf);
3171 static int ast_el_write_history(
const char *filename)
3175 if (el_hist == NULL || el == NULL)
3176 ast_el_initialize();
3178 return (history(el_hist, &ev, H_SAVE, filename));
3181 static int ast_el_read_history(
const char *filename)
3185 if (el_hist == NULL || el == NULL) {
3186 ast_el_initialize();
3189 if (access(filename, F_OK) == 0) {
3190 return history(el_hist, &ev, H_LOAD, filename);
3197 static void process_histfile(
int (*readwrite)(
const char *filename))
3199 struct passwd *pw = getpwuid(geteuid());
3203 if (!pw || ast_strlen_zero(pw->pw_dir)) {
3204 ast_log(LOG_ERROR,
"Unable to determine home directory. History read/write disabled.\n");
3208 ret =
ast_asprintf(&name,
"%s/.asterisk_history", pw->pw_dir);
3210 ast_log(LOG_ERROR,
"Unable to create history file name. History read/write disabled.\n");
3214 ret = readwrite(name);
3216 ast_log(LOG_ERROR,
"Unable to read or write history file '%s'\n", name);
3224 static void ast_el_read_default_histfile(
void)
3226 process_histfile(ast_el_read_history);
3229 static void ast_el_write_default_histfile(
void)
3231 process_histfile(ast_el_write_history);
3234 static void ast_remotecontrol(
char *data)
3242 char *stringp = NULL;
3248 printf(
"%s", term_end());
3251 memset(&sig_flags, 0,
sizeof(sig_flags));
3252 signal(SIGINT, __remote_quit_handler);
3253 signal(SIGTERM, __remote_quit_handler);
3254 signal(SIGHUP, __remote_quit_handler);
3256 if (read(
ast_consock, buf,
sizeof(buf) - 1) < 0) {
3257 ast_log(LOG_ERROR,
"read() failed: %s\n", strerror(errno));
3261 char prefix[] =
"cli quit after ";
3262 char *tmp =
ast_alloca(strlen(data) + strlen(prefix) + 1);
3263 sprintf(tmp,
"%s%s", prefix, data);
3264 if (write(
ast_consock, tmp, strlen(tmp) + 1) < 0) {
3265 ast_log(LOG_ERROR,
"write() failed: %s\n", strerror(errno));
3266 if (sig_flags.need_quit || sig_flags.need_quit_handler || sig_flags.need_el_end) {
3272 hostname = strsep(&stringp,
"/");
3273 cpid = strsep(&stringp,
"/");
3274 version = strsep(&stringp,
"\n");
3276 version =
"<Version Unknown>";
3278 strsep(&stringp,
".");
3284 send_rasterisk_connect_commands();
3287 if (ast_opt_exec && data) {
3288 int linefull = 1, prev_linefull = 1, prev_line_verbose = 0;
3291 fds.events = POLLIN;
3294 while (ast_poll(&fds, 1, 60000) > 0) {
3295 char buffer[512] =
"", *curline = buffer, *nextline;
3296 int not_written = 1;
3298 if (sig_flags.need_quit || sig_flags.need_quit_handler || sig_flags.need_el_end) {
3302 if (read(
ast_consock, buffer,
sizeof(buffer) - 1) <= 0) {
3307 prev_linefull = linefull;
3308 if ((nextline = strchr(curline,
'\n'))) {
3313 nextline = strchr(curline,
'\0');
3327 if ((!prev_linefull && !prev_line_verbose) || (prev_linefull && *curline > 0)) {
3328 prev_line_verbose = 0;
3330 if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
3331 ast_log(LOG_WARNING,
"write() failed: %s\n", strerror(errno));
3334 prev_line_verbose = 1;
3337 }
while (!ast_strlen_zero(curline));
3347 ast_verbose(
"Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
3350 remotehostname = hostname;
3351 if (el_hist == NULL || el == NULL)
3352 ast_el_initialize();
3353 ast_el_read_default_histfile();
3355 el_set(el, EL_GETCFN, ast_el_read_char);
3358 ebuf = (
char *)el_gets(el, &num);
3360 if (sig_flags.need_quit || sig_flags.need_quit_handler || sig_flags.need_el_end) {
3364 if (!ebuf && write(1,
"", 1) < 0)
3367 if (!ast_strlen_zero(ebuf)) {
3368 if (ebuf[strlen(ebuf)-1] ==
'\n')
3369 ebuf[strlen(ebuf)-1] =
'\0';
3370 if (!remoteconsolehandler(ebuf)) {
3373 ast_log(LOG_WARNING,
"Unable to write: %s\n", strerror(errno));
3379 printf(
"\nDisconnected from Asterisk server\n");
3382 static int show_version(
void)
3388 static int show_cli_help(
void)
3391 printf(
"Usage: asterisk [OPTIONS]\n");
3392 printf(
"Valid Options:\n");
3393 printf(
" -V Display version number and exit\n");
3394 printf(
" -C <configfile> Use an alternate configuration file\n");
3395 printf(
" -G <group> Run as a group other than the caller\n");
3396 printf(
" -U <user> Run as a user other than the caller\n");
3397 printf(
" -c Provide console CLI\n");
3398 printf(
" -d Increase debugging (multiple d's = more debugging)\n");
3399 #if HAVE_WORKING_FORK
3400 printf(
" -f Do not fork\n");
3401 printf(
" -F Always fork\n");
3403 printf(
" -g Dump core in case of a crash\n");
3404 printf(
" -h This help screen\n");
3405 printf(
" -i Initialize crypto keys at startup\n");
3406 printf(
" -L <load> Limit the maximum load average before rejecting new calls\n");
3407 printf(
" -M <value> Limit the maximum number of calls to the specified value\n");
3408 printf(
" -m Mute debugging and console output on the console\n");
3409 printf(
" -n Disable console colorization. Can be used only at startup.\n");
3410 printf(
" -p Run as pseudo-realtime thread\n");
3411 printf(
" -q Quiet mode (suppress output)\n");
3412 printf(
" -r Connect to Asterisk on this machine\n");
3413 printf(
" -R Same as -r, except attempt to reconnect if disconnected\n");
3414 printf(
" -s <socket> Connect to Asterisk via socket <socket> (only valid with -r)\n");
3415 printf(
" -t Record soundfiles in /var/tmp and move them where they\n");
3416 printf(
" belong after they are done\n");
3417 printf(
" -T Display the time in [Mmm dd hh:mm:ss] format for each line\n");
3418 printf(
" of output to the CLI. Cannot be used with remote console mode.\n\n");
3419 printf(
" -v Increase verbosity (multiple v's = more verbose)\n");
3420 printf(
" -x <cmd> Execute command <cmd> (implies -r)\n");
3421 printf(
" -X Enable use of #exec in asterisk.conf\n");
3422 printf(
" -W Adjust terminal colors to compensate for a light background\n");
3427 static void read_pjproject_startup_options(
void)
3438 || cfg == CONFIG_STATUS_FILEUNCHANGED
3439 || cfg == CONFIG_STATUS_FILEINVALID) {
3444 for (v = ast_variable_browse(cfg,
"startup"); v; v = v->
next) {
3445 if (!strcasecmp(v->
name,
"log_level")) {
3453 }
else if (!strcasecmp(v->
name,
"cache_pools")) {
3461 static void *monitor_sig_flags(
void *unused)
3464 struct pollfd p = { sig_alert_pipe[0], POLLIN, 0 };
3466 ast_poll(&p, 1, -1);
3467 if (sig_flags.need_reload) {
3468 sig_flags.need_reload = 0;
3471 if (sig_flags.need_quit) {
3472 sig_flags.need_quit = 0;
3473 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
3474 sig_flags.need_quit_handler = 1;
3475 pthread_kill(consolethread, SIGURG);
3486 static void *canary_thread(
void *unused)
3488 struct stat canary_stat;
3496 if (stat(canary_filename, &canary_stat) || now.tv_sec > canary_stat.st_mtime + 60) {
3497 ast_log(LOG_WARNING,
3498 "The canary is no more. He has ceased to be! "
3499 "He's expired and gone to meet his maker! "
3500 "He's a stiff! Bereft of life, he rests in peace. "
3501 "His metabolic processes are now history! He's off the twig! "
3502 "He's kicked the bucket. He's shuffled off his mortal coil, "
3503 "run down the curtain, and joined the bleeding choir invisible!! "
3504 "THIS is an EX-CANARY. (Reducing priority)\n");
3515 static void canary_exit(
void)
3517 if (canary_pid > 0) {
3519 kill(canary_pid, SIGKILL);
3520 waitpid(canary_pid, &status, 0);
3525 static void run_startup_commands(
void)
3534 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
3538 fd = open(
"/dev/null", O_RDWR);
3544 for (v = ast_variable_browse(cfg,
"startup_commands"); v; v = v->
next) {
3553 static void env_init(
void)
3555 setenv(
"AST_SYSTEMNAME", ast_config_AST_SYSTEM_NAME, 1);
3556 setenv(
"AST_BUILD_HOST", ast_build_hostname, 1);
3557 setenv(
"AST_BUILD_DATE", ast_build_date, 1);
3558 setenv(
"AST_BUILD_KERNEL", ast_build_kernel, 1);
3559 setenv(
"AST_BUILD_MACHINE", ast_build_machine, 1);
3560 setenv(
"AST_BUILD_OS", ast_build_os, 1);
3561 setenv(
"AST_BUILD_USER", ast_build_user, 1);
3565 static void print_intro_message(
const char *runuser,
const char *rungroup)
3567 if (ast_opt_console ||
option_verbose || (ast_opt_remote && !ast_opt_exec)) {
3570 ast_verbose(
"Running as user '%s'\n", runuser);
3573 ast_verbose(
"Running under group '%s'\n", rungroup);
3578 static void main_atexit(
void)
3587 int isroot = 1, rundir_exists = 0;
3588 RAII_VAR(
char *, runuser, NULL, ast_free);
3589 RAII_VAR(
char *, rungroup, NULL, ast_free);
3590 RAII_VAR(
char *, xarg, NULL, ast_free);
3592 static const char *getopt_settings =
"BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx:";
3595 if (argc > ARRAY_LEN(_argv) - 1) {
3596 fprintf(stderr,
"Truncating argument size to %d\n", (
int)ARRAY_LEN(_argv) - 1);
3597 argc = ARRAY_LEN(_argv) - 1;
3599 for (x = 0; x < argc; x++)
3607 if (argv[0] && (strstr(argv[0],
"rasterisk")) != NULL) {
3610 ast_mainpid = getpid();
3613 while ((c = getopt(argc, argv, getopt_settings)) != -1) {
3619 set_asterisk_conf_path(optarg);
3648 load_asterisk_conf();
3658 while ((c = getopt(argc, argv, getopt_settings)) != -1) {
3679 #if defined(HAVE_SYSINFO)
3686 #if HAVE_WORKING_FORK
3705 "NOTICE: The -I option is no longer needed.\n"
3706 " It will always be enabled if you have a timing module loaded.\n");
3740 if (ast_opt_remote) {
3741 set_socket_path(optarg);
3774 if (ast_opt_remote) {
3779 while ((c = getopt(argc, argv, getopt_settings)) != -1) {
3816 fprintf(stderr,
"'%c' option is not compatible with remote console mode and has no effect.\n", c);
3821 fprintf(stderr,
"\n");
3828 if (ast_opt_remote) {
3829 strcpy(argv[0],
"rasterisk");
3830 for (x = 1; x < argc; x++) {
3831 argv[x] = argv[0] + 10;
3836 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");
3839 if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
3840 fprintf(stderr,
"'alwaysfork' is not compatible with console or remote console mode; ignored\n");
3844 if (ast_opt_dump_core) {
3845 memset(&l, 0,
sizeof(l));
3846 l.rlim_cur = RLIM_INFINITY;
3847 l.rlim_max = RLIM_INFINITY;
3848 if (setrlimit(RLIMIT_CORE, &l)) {
3849 fprintf(stderr,
"Unable to disable core size resource limit: %s\n", strerror(errno));
3853 if (getrlimit(RLIMIT_NOFILE, &l)) {
3854 fprintf(stderr,
"Unable to check file descriptor limit: %s\n", strerror(errno));
3857 #if !defined(CONFIGURE_RAN_AS_ROOT)
3862 struct timeval tv = { 0, };
3864 if (l.rlim_cur <= FD_SETSIZE) {
3870 if (!(fd = open(
"/dev/null", O_RDONLY))) {
3871 fprintf(stderr,
"Cannot open a file descriptor at boot? %s\n", strerror(errno));
3875 fd2 = ((l.rlim_cur >
sizeof(readers) * 8) ?
sizeof(readers) * 8 : l.rlim_cur) - 1;
3876 if (dup2(fd, fd2) < 0) {
3877 fprintf(stderr,
"Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
3883 FD_SET(fd2, &readers);
3884 if (
ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
3885 fprintf(stderr,
"Maximum select()able file descriptor is %d\n", FD_SETSIZE);
3887 ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
3891 #elif defined(HAVE_VARIABLE_FDSET)
3892 ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
3895 if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
3896 rungroup =
ast_strdup(ast_config_AST_RUN_GROUP);
3897 if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
3898 runuser =
ast_strdup(ast_config_AST_RUN_USER);
3903 sigaction(SIGCHLD, &child_handler, NULL);
3907 if (mkdir(ast_config_AST_RUN_DIR, 0755)) {
3908 if (errno == EEXIST) {
3911 fprintf(stderr,
"Unable to create socket file directory. Remote consoles will not be able to connect! (%s)\n", strerror(x));
3921 if (isroot && rungroup) {
3923 gr = getgrnam(rungroup);
3925 fprintf(stderr,
"No such group '%s'!\n", rungroup);
3928 if (!rundir_exists && chown(ast_config_AST_RUN_DIR, -1, gr->gr_gid)) {
3929 fprintf(stderr,
"Unable to chgrp run directory to %d (%s)\n", (
int) gr->gr_gid, rungroup);
3931 if (setgid(gr->gr_gid)) {
3932 fprintf(stderr,
"Unable to setgid to %d (%s)\n", (
int)gr->gr_gid, rungroup);
3935 if (setgroups(0, NULL)) {
3936 fprintf(stderr,
"Unable to drop unneeded groups\n");
3946 pw = getpwnam(runuser);
3948 fprintf(stderr,
"No such user '%s'!\n", runuser);
3951 if (chown(ast_config_AST_RUN_DIR, pw->pw_uid, -1)) {
3952 fprintf(stderr,
"Unable to chown run directory to %d (%s)\n", (
int) pw->pw_uid, runuser);
3955 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
3956 ast_log(LOG_WARNING,
"Unable to keep capabilities.\n");
3960 if (!isroot && pw->pw_uid != geteuid()) {
3961 fprintf(stderr,
"Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
3965 if (setgid(pw->pw_gid)) {
3966 fprintf(stderr,
"Unable to setgid to %d!\n", (
int)pw->pw_gid);
3969 if (isroot && initgroups(pw->pw_name, pw->pw_gid)) {
3970 fprintf(stderr,
"Unable to init groups for '%s'\n", runuser);
3974 if (setuid(pw->pw_uid)) {
3975 fprintf(stderr,
"Unable to setuid to %d (%s)\n", (
int)pw->pw_uid, runuser);
3982 cap = cap_from_text(
"cap_net_admin=eip");
3984 if (cap_set_proc(cap)) {
3985 fprintf(stderr,
"Unable to install capabilities.\n");
3987 if (cap_free(cap)) {
3988 fprintf(stderr,
"Unable to drop capabilities.\n");
3997 if (geteuid() && ast_opt_dump_core) {
3998 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
3999 fprintf(stderr,
"Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
4005 #if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
4007 if (!getcwd(dir,
sizeof(dir)) || eaccess(dir, R_OK | X_OK | F_OK)) {
4008 fprintf(stderr,
"Unable to access the running directory (%s). Changing to '/' for compatibility.\n", strerror(errno));
4013 fprintf(stderr,
"chdir(\"/\") failed?!! %s\n", strerror(errno));
4017 if (!ast_opt_no_fork && !ast_opt_dump_core) {
4020 fprintf(stderr,
"Unable to chdir(\"/\") ?!! %s\n", strerror(errno));
4035 if (ast_opt_remote) {
4036 multi_thread_safe = 1;
4038 ast_remotecontrol(xarg);
4043 printf(
"%s", term_end());
4046 print_intro_message(runuser, rungroup);
4047 printf(
"%s", term_quit());
4048 ast_remotecontrol(NULL);
4052 fprintf(stderr,
"Asterisk already running on %s. Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
4053 printf(
"%s", term_quit());
4056 }
else if (ast_opt_remote || ast_opt_exec) {
4057 fprintf(stderr,
"Unable to connect to remote asterisk (does %s exist?)\n", ast_config_AST_SOCKET);
4058 printf(
"%s", term_quit());
4063 child_cap = cap_from_text(
"cap_net_admin-eip");
4066 asterisk_daemon(isroot, runuser, rungroup);
4068 cap_free(child_cap);
4073 static inline void check_init(
int init_result,
const char *name)
4077 ast_log(LOG_ERROR,
"%s initialization failed. ASTERISK EXITING!\n%s", name, term_quit());
4079 fprintf(stderr,
"%s initialization failed. ASTERISK EXITING!\n%s", name, term_quit());
4082 exit(init_result == -2 ? 2 : 1);
4086 static void asterisk_daemon(
int isroot,
const char *runuser,
const char *rungroup)
4092 char pbx_uuid[AST_UUID_STR_LEN];
4095 ast_lastreloadtime = ast_startuptime =
ast_tvnow();
4102 #if HAVE_WORKING_FORK
4103 if (ast_opt_always_fork || !ast_opt_no_fork) {
4104 #ifndef HAVE_SBIN_LAUNCHD
4105 if (daemon(1, 0) < 0) {
4106 fprintf(stderr,
"daemon() failed: %s\n", strerror(errno));
4108 ast_mainpid = getpid();
4111 fprintf(stderr,
"Mac OS X detected. Use 'launchctl load /Library/LaunchDaemon/org.asterisk.asterisk.plist'.\n");
4119 multi_thread_safe = 1;
4132 if (ast_opt_high_priority) {
4133 snprintf(canary_filename,
sizeof(canary_filename),
"%s/alt.asterisk.canary.tweet.tweet.tweet", ast_config_AST_RUN_DIR);
4136 sigaction(SIGPIPE, &ignore_sig_handler, NULL);
4138 canary_pid = fork();
4139 if (canary_pid == 0) {
4140 char canary_binary[PATH_MAX], ppid[12];
4143 signal(SIGCHLD, SIG_DFL);
4144 signal(SIGPIPE, SIG_DFL);
4148 snprintf(ppid,
sizeof(ppid),
"%d", (
int) ast_mainpid);
4151 snprintf(canary_binary,
sizeof(canary_binary),
"%s/astcanary", ast_config_AST_SBIN_DIR);
4152 execl(canary_binary,
"astcanary", canary_filename, ppid, (
char *)NULL);
4156 }
else if (canary_pid > 0) {
4157 pthread_t dont_care;
4158 ast_pthread_create_detached(&dont_care, NULL, canary_thread, NULL);
4166 unlink(ast_config_AST_PID);
4167 f = fopen(ast_config_AST_PID,
"w");
4169 fprintf(f,
"%ld\n", (
long)ast_mainpid);
4172 fprintf(stderr,
"Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
4179 printf(
"%s", term_end());
4182 print_intro_message(runuser, rungroup);
4189 if (ast_opt_console) {
4190 if (el_hist == NULL || el == NULL)
4191 ast_el_initialize();
4192 ast_el_read_default_histfile();
4208 ast_verb(0,
"PBX UUID: %s\n", pbx_uuid);
4218 check_init(ast_utils_init(),
"Utilities");
4220 check_init(
ast_fd_init(),
"File Descriptor Debugging");
4222 check_init(
aco_init(),
"Configuration Option Framework");
4224 #ifdef TEST_FRAMEWORK
4243 (void) sigemptyset(&sigs);
4244 (void) sigaddset(&sigs, SIGHUP);
4245 (void) sigaddset(&sigs, SIGTERM);
4246 (void) sigaddset(&sigs, SIGINT);
4247 (void) sigaddset(&sigs, SIGPIPE);
4248 (void) sigaddset(&sigs, SIGWINCH);
4249 pthread_sigmask(SIG_BLOCK, &sigs, NULL);
4250 sigaction(SIGURG, &urg_handler, NULL);
4251 signal(SIGINT, __quit_handler);
4252 signal(SIGTERM, __quit_handler);
4253 sigaction(SIGHUP, &hup_handler, NULL);
4254 sigaction(SIGPIPE, &ignore_sig_handler, NULL);
4259 srand((
unsigned int) getpid() + (
unsigned int) time(NULL));
4260 initstate((
unsigned int) getpid() * 65536 + (
unsigned int) time(NULL), randompool,
sizeof(randompool));
4271 read_pjproject_startup_options();
4273 check_init(
app_init(),
"App Core");
4274 check_init(
mwi_init(),
"MWI Core");
4283 check_init(ast_presence_state_engine_init(),
"Presence State Engine");
4289 check_init(
load_pbx(),
"load_pbx");
4317 if (ast_opt_no_fork) {
4318 consolethread = pthread_self();
4326 publish_fully_booted();
4328 pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
4336 run_startup_commands();
4339 ast_verb(0,
COLORIZE_FMT "\n", COLORIZE(COLOR_BRGREEN, 0,
"Asterisk Ready."));
4343 if (ast_opt_console) {
4347 char hostname[MAXHOSTNAMELEN] =
"";
4349 if (gethostname(hostname,
sizeof(hostname) - 1)) {
4353 ast_pthread_create_detached(&mon_sig_flags, NULL, monitor_sig_flags, NULL);
4355 set_icon(
"Asterisk");
4356 snprintf(title,
sizeof(title),
"Asterisk Console on '%s' (pid %ld)", hostname, (
long)ast_mainpid);
4359 el_set(el, EL_GETCFN, ast_el_read_char);
4362 if (sig_flags.need_el_end) {
4368 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
4372 buf = (
char *) el_gets(el, &num);
4374 if (!buf && write(1,
"", 1) < 0)
4378 if (buf[strlen(buf)-1] ==
'\n')
4379 buf[strlen(buf)-1] =
'\0';
4381 consolehandler(buf);
4387 monitor_sig_flags(NULL);
int load_pbx_variables(void)
A-Law to Signed linear conversion.
struct ast_variable * next
int ast_codec_builtin_init(void)
Initialize built-in codecs within the core.
int stasis_init(void)
Initialize the Stasis subsystem.
Security Event Reporting API.
#define AST_LIST_LOCK(head)
Locks a list.
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
int ast_named_locks_init(void)
#define ast_realloc(p, len)
A wrapper for realloc()
void ast_verb_console_unregister(void)
Unregister this thread's console verbosity level.
int ast_pickup_init(void)
Initialize pickup.
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
void ast_autoservice_init(void)
int ast_image_init(void)
Initialize image stuff Initializes all the various image stuff. Basically just registers the cli stuf...
unsigned int option_dtmfminduration
int ast_translate_init(void)
Initialize the translation matrix and index to format conversion table.
void ast_builtins_init(void)
initialize the _full_cmd string in * each of the builtins.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
Asterisk version information.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
int ast_sd_get_fd_un(int type, const char *path)
Find a listening AF_LOCAL file descriptor provided by socket activation.
Support for translation of data formats. translate.c.
int ast_manager_check_enabled(void)
Check if AMI is enabled.
int register_config_cli(void)
Exposed initialization method for core process.
static char * handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Give an overview of system statistics.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
const char * ast_get_version(void)
Retrieve the Asterisk version string.
#define DEFAULT_PJ_LOG_MAX_LEVEL
enum ast_module_reload_result ast_module_reload(const char *name)
Reload asterisk modules.
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
descriptor for a cli entry.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
int ast_endpoint_init(void)
Endpoint support initialization.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
void load_astmm_phase_1(void)
Initialize malloc debug phase 1.
int load_pbx_switch(void)
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define WELCOME_MESSAGE
Welcome message when starting a CLI interface.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
const char * ast_get_build_opts(void)
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Structure for variables, used for configurations and for channel variables.
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Universally unique identifier support.
int ast_bucket_init(void)
Initialize bucket support.
int ast_term_color_code(struct ast_str **str, int fgcolor, int bgcolor)
Append a color sequence to an ast_str.
void ast_alertpipe_close(int alert_pipe[2])
Close an alert pipe.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
void ast_verb_console_register(int *level)
Register this thread's console verbosity level pointer.
int ast_bridging_init(void)
Initialize the bridging system.
int ast_xmldoc_load_documentation(void)
Load XML documentation. Provided by xmldoc.c.
static char * levels[NUMLOGLEVELS]
Logging channels used in the Asterisk logging system.
int ast_endpoint_stasis_init(void)
Initialization function for endpoint stasis support.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
int ast_verb_console_get(void)
Get this thread's console verbosity level.
static void _null_sig_handler(int sig)
NULL handler so we can collect the child exit status.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
int ast_dns_system_resolver_init(void)
Initializes the resolver.
void ast_alaw_init(void)
To init the alaw to slinear conversion stuff, this needs to be run.
double ast_option_maxload
#define ast_strdup(str)
A wrapper for strdup()
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
int ast_add_profile(const char *name, uint64_t scale)
allocates a counter with a given name and scale.
#define AST_RTP_PT_FIRST_DYNAMIC
int ast_cancel_shutdown(void)
Cancel an existing shutdown and return to normal operation.
I/O Management (derived from Cheops-NG)
void ast_console_puts_mutable(const char *string, int level)
log the string to the root console, and all attached network console clients
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
UTF-8 information and validation functions.
void ast_free_ptr(void *ptr)
free() wrapper
int modules_shutdown(void)
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
int ast_sorcery_init(void)
Initialize the sorcery API.
int ast_get_termcols(int fd)
Columns of Terminal.
int ast_codec_init(void)
Initialize codec support within the core.
const char * ast_get_build_opts_all(void)
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
int args
This gets set in ast_cli_register()
int ast_realtime_enabled(void)
Check if there's any realtime engines loaded.
int ast_webmanager_check_enabled(void)
Check if AMI/HTTP is enabled.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
static void _urg_handler(int num)
Urgent handler.
int ast_cdr_is_enabled(void)
Return TRUE if CDR subsystem is enabled.
void ast_console_toggle_loglevel(int fd, int level, int state)
enable or disable a logging level to a specified console
void ast_replace_sigchld(void)
Replace the SIGCHLD handler.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Configuration File Parser.
int load_pbx_hangup_handler(void)
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
static int shutdown_pending
General Asterisk channel definitions for image handling.
u-Law to Signed linear conversion
Generic Advice of Charge encode and decode routines.
void ast_console_puts_mutable_full(const char *message, int level, int sublevel)
log the string to the console, and all attached console clients
struct ast_vector_string * ast_cli_completion_vector(const char *text, const char *word)
Generates a vector of strings for CLI completion.
void callerid_init(void)
CallerID Initialization.
General Asterisk PBX channel definitions.
Asterisk JSON abstraction layer.
Asterisk file paths, configured in asterisk.conf.
int ast_sd_notify(const char *state)
a wrapper for sd_notify(): notify systemd of any state changes.
int ast_get_tid(void)
Get current thread ID.
#define ast_strdupa(s)
duplicate a string in memory from the stack
ast_alert_status_t ast_alertpipe_read(int alert_pipe[2])
Read an event from an alert pipe.
int ast_set_priority(int pri)
We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy ac...
static void set_title(char *text)
Set an X-term or screen title.
Access Control of various sorts.
void ast_softhangup_all(void)
Soft hangup all active channels.
int ast_language_is_prefix
The following variable controls the layout of localized sound files. If 0, use the historical layout ...
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Scheduler Routines (derived from cheops)
int ast_utf8_init(void)
Register UTF-8 tests.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
static int ast_select(int nfds, ast_fdset *rfds, ast_fdset *wfds, ast_fdset *efds, struct timeval *tvp)
Waits for activity on a group of channels.
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
int devstate_init(void)
Initialize the device state core.
int ast_option_pjproject_log_level
A set of macros to manage forward-linked lists.
ast_cli_command
calling arguments for new-style handlers.
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
int ast_aoc_cli_init(void)
enable aoc cli options
int ast_cli_allow_at_shutdown(struct ast_cli_entry *e)
Allow a CLI command to be executed while Asterisk is shutting down.
Core PBX routines and definitions.
Wrapper for network related headers, masking differences between various operating systems...
int ast_alertpipe_init(int alert_pipe[2])
Initialize an alert pipe.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
void ast_cdr_engine_term(void)
int ast_device_state_engine_init(void)
Initialize the device state engine in separate thread.
static int set_priority_all(int pri)
Set priority on all known threads.
Presence state management.
void ast_unreplace_sigchld(void)
Restore the SIGCHLD handler.
void ast_ulaw_init(void)
Set up mu-law conversion table.
void ast_uuid_init(void)
Initialize the UUID system.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
void ast_stun_init(void)
Initialize the STUN system in Asterisk.
Support for dynamic strings.
int ast_option_pjproject_cache_pools
static char * handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Give an overview of core settings.
TTY/TDD Generation support.
int ast_pbx_uuid_get(char *pbx_uuid, int length)
Retrieve the PBX UUID.
int ast_parking_stasis_init(void)
initializes the rtp engine arrays
int ast_local_init(void)
Initialize the local proxy channel.
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
int mwi_init(void)
Initialize the mwi core.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
static int print_file(int fd, char *desc, const char *filename)
Print the contents of a file.
void ast_console_puts(const char *string)
write the string to the root console, and all attached network console clients
static pid_t safe_exec_prep(int dualfork)
fork and perform other preparations for spawning applications
#define ast_calloc(num, len)
A wrapper for calloc()
static int read_credentials(int fd, char *buffer, size_t size, struct console *con)
read() function supporting the reception of user credentials.
const char * ast_term_reset(void)
Returns the terminal reset code.
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
int ast_shutdown_final(void)
Asterisk XML Documentation API.
int ast_rtp_engine_init(void)
initializes the rtp engine arrays
Prototypes for public functions only of internal interest,.
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
const char * ast_term_color(int fgcolor, int bgcolor)
Return a color sequence string.
void logger_queue_start(void)
Start the ast_queue_log() logger.
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
#define AST_VECTOR_PTR_FREE(vec)
Deallocates this vector pointer.
Structure used to handle boolean flags.
static unsigned int safe_system_level
Keep track of how many threads are currently trying to wait*() on a child process.
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
struct ast_eid ast_eid_default
Global EID.
void ast_init_logger_for_socket_console(void)
load logger.conf configuration for console socket connections
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
void load_astmm_phase_2(void)
Initialize malloc debug phase 2.
void clean_time_zones(void)
int ast_cli_command_multiple_full(int uid, int gid, int fd, size_t size, const char *s)
Executes multiple CLI commands Interpret strings separated by NULL and execute each one...
#define MAX_PJ_LOG_MAX_LEVEL
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
const char * ast_logger_get_dateformat(void)
Get the logger configured date format.
void ast_console_toggle_mute(int fd, int silent)
mute or unmute a console from logging
ssize_t ast_alertpipe_write(int alert_pipe[2])
Write an event to an alert pipe.
int ast_security_stasis_init(void)
initializes stasis topic/event types for ast_security_topic and ast_security_event_type ...
void threadstorage_init(void)
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
int ast_json_init(void)
Initialize the JSON library.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
int ast_is_logger_initialized(void)
Test if logger is initialized.
int ast_stasis_system_init(void)
Initialize the system level items for Stasis Message Bus API.
int ast_safe_execvp(int dualfork, const char *file, char *const argv[])
Safely spawn an external program while closing file descriptors.
void dnsmgr_start_refresh(void)
int ast_shutting_down(void)
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
#define AST_RTP_PT_LAST_REASSIGN
void ast_cli_channels_init(void)
static int ast_socket_is_sd
Abstract JSON element (object, array, string, int, ...).
Options provided by main asterisk program.
void ast_unregister_atexit(void(*func)(void))
Unregister a function registered with ast_register_atexit().
static int has_priority(void)
Check whether we were set to high(er) priority.
Handy terminal functions for vt* terms.
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
int ast_timing_init(void)
int ast_undestroyed_channels(void)
int load_pbx_functions_cli(void)
String vector definitions.
void ast_msg_shutdown(void)
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
int main(int argc, char *argv[])
static int safe_exec_wait(pid_t pid)
wait for spawned application to complete and unreplace sigchld
static void ast_network_puts(const char *string)
write the string to all attached console clients
Pluggable RTP Architecture.
Asterisk module definitions.
int ast_channels_init(void)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
static struct ast_cli_entry cli_asterisk_shutdown[]
Shutdown Asterisk CLI commands.
int load_pbx_builtins(void)
int ast_active_channels(void)
returns number of active/allocated channels
Persistent data storage (akin to *doze registry)
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
static void ast_network_puts_mutable(const char *string, int level, int sublevel)
log the string to all attached network console clients
void ast_process_pending_reloads(void)
Process reload requests received during startup.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
static void really_quit(int num, shutdown_nice_t niceness, int restart)
int ast_cli_perms_init(int reload)
int app_init(void)
Initialize the application core.
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Sorcery Data Access Layer API.