Skip to content
Snippets Groups Projects
asterisk.c 136 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	setenv("AST_SYSTEMNAME", ast_config_AST_SYSTEM_NAME, 1);
    	setenv("AST_BUILD_HOST", ast_build_hostname, 1);
    	setenv("AST_BUILD_DATE", ast_build_date, 1);
    	setenv("AST_BUILD_KERNEL", ast_build_kernel, 1);
    	setenv("AST_BUILD_MACHINE", ast_build_machine, 1);
    	setenv("AST_BUILD_OS", ast_build_os, 1);
    	setenv("AST_BUILD_USER", ast_build_user, 1);
    	setenv("AST_VERSION", ast_get_version(), 1);
    }
    
    
    static void print_intro_message(const char *runuser, const char *rungroup)
    {
    
     	if (ast_opt_console || option_verbose || (ast_opt_remote && !ast_opt_exec)) {
    
    		if (ast_register_verbose(console_verboser)) {
    			fprintf(stderr, "Unable to register console verboser?\n");
    			return;
    		}
    		WELCOME_MESSAGE;
    		if (runuser) {
    			ast_verbose("Running as user '%s'\n", runuser);
    		}
    		if (rungroup) {
    			ast_verbose("Running under group '%s'\n", rungroup);
    		}
    	}
    }
    
    
    static void main_atexit(void)
    {
    	ast_cli_unregister_multiple(cli_asterisk, ARRAY_LEN(cli_asterisk));
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    int main(int argc, char *argv[])
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char * xarg = NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	int x;
    
    	int isroot = 1, rundir_exists = 0;
    
    	const char *runuser = NULL, *rungroup = NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Remember original args for restart */
    
    	if (argc > ARRAY_LEN(_argv) - 1) {
    		fprintf(stderr, "Truncating argument size to %d\n", (int)ARRAY_LEN(_argv) - 1);
    		argc = ARRAY_LEN(_argv) - 1;
    
    	for (x = 0; x < argc; x++)
    
    Mark Spencer's avatar
    Mark Spencer committed
    		_argv[x] = argv[x];
    	_argv[x] = NULL;
    
    
    	if (geteuid() != 0)
    		isroot = 0;
    
    
    	/* if the progname is rasterisk consider it a remote console */
    
    	if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
    
    		ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
    
    	/*! \brief Check for options
    	 *
    	 * \todo Document these options
    	 */
    
    	while ((c = getopt(argc, argv, "BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx:")) != -1) {
    
    		/*!\note Please keep the ordering here to alphabetical, capital letters
    		 * first.  This will make it easier in the future to select unused
    		 * option flags for new features. */
    
    		case 'B': /* Force black background */
    			ast_set_flag(&ast_options, AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
    			ast_clear_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND);
    			break;
    
    		case 'X':
    			ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
    			break;
    
    		case 'C':
    			ast_copy_string(cfg_paths.config_file, optarg, sizeof(cfg_paths.config_file));
    			ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG);
    			break;
    		case 'c':
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
    			break;
    		case 'd':
    			option_debug++;
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
    			break;
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    			if ((sscanf(&optarg[1], "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
    
    		case 'F':
    			ast_set_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
    			break;
    
    		case 'f':
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
    			break;
    #endif
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    		case 'g':
    			ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    		case 'I':
    			fprintf(stderr,
    				"NOTICE: The -I option is no longer needed.\n"
    				"  It will always be enabled if you have a timing module loaded.\n");
    			break;
    
    		case 'i':
    			ast_set_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS);
    
    			if ((sscanf(optarg, "%30lf", &ast_option_maxload) != 1) || (ast_option_maxload < 0.0)) {
    				ast_option_maxload = 0.0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    			if ((sscanf(optarg, "%30d", &ast_option_maxcalls) != 1) || (ast_option_maxcalls < 0)) {
    				ast_option_maxcalls = 0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_MUTE);
    
    		case 'n':
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_COLOR);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    		case 'p':
    			ast_set_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'q':
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_QUIET);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    		case 'R':
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE | AST_OPT_FLAG_RECONNECT);
    
    		case 'r':
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    		case 'T':
    			ast_set_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP);
    
    		case 't':
    			ast_set_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'V':
    			show_version();
    			exit(0);
    
    		case 'v':
    			option_verbose++;
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
    
    		case 'W': /* White background */
    			ast_set_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND);
    
    			ast_clear_flag(&ast_options, AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
    			break;
    
    			/* -r is implied by -x so set the flags -r sets as well. */
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
    
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC | AST_OPT_FLAG_NO_COLOR);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case '?':
    			exit(1);
    		}
    	}
    
    	/* For remote connections, change the name of the remote connection.
    	 * We do this for the benefit of init scripts (which need to know if/when
    	 * the main asterisk process has died yet). */
    
    		strcpy(argv[0], "rasterisk");
    		for (x = 1; x < argc; x++) {
    			argv[x] = argv[0] + 10;
    		}
    	}
    
    
    		ast_copy_string((char *) cfg_paths.socket_path, remotesock, sizeof(cfg_paths.socket_path));
    
    	if (!ast_language_is_prefix && !ast_opt_remote) {
    		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");
    	}
    
    	if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
    
    		fprintf(stderr, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
    
    		ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
    	}
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    		memset(&l, 0, sizeof(l));
    		l.rlim_cur = RLIM_INFINITY;
    		l.rlim_max = RLIM_INFINITY;
    		if (setrlimit(RLIMIT_CORE, &l)) {
    
    			fprintf(stderr, "Unable to disable core size resource limit: %s\n", strerror(errno));
    
    	if (getrlimit(RLIMIT_NOFILE, &l)) {
    
    		fprintf(stderr, "Unable to check file descriptor limit: %s\n", strerror(errno));
    
    	}
    
    #if !defined(CONFIGURE_RAN_AS_ROOT)
    	/* Check if select(2) will run with more file descriptors */
    	do {
    		int fd, fd2;
    		ast_fdset readers;
    		struct timeval tv = { 0, };
    
    		if (l.rlim_cur <= FD_SETSIZE) {
    			/* The limit of select()able FDs is irrelevant, because we'll never
    			 * open one that high. */
    			break;
    		}
    
    		if (!(fd = open("/dev/null", O_RDONLY))) {
    
    			fprintf(stderr, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
    
    			break; /* XXX Should we exit() here? XXX */
    		}
    
    
    		fd2 = ((l.rlim_cur > sizeof(readers) * 8) ? sizeof(readers) * 8 : l.rlim_cur) - 1;
    
    		if (dup2(fd, fd2) < 0) {
    
    			fprintf(stderr, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
    
    			break;
    		}
    
    		FD_ZERO(&readers);
    		FD_SET(fd2, &readers);
    		if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
    
    			fprintf(stderr, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
    
    		ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
    		close(fd);
    		close(fd2);
    
    	} while (0);
    #elif defined(HAVE_VARIABLE_FDSET)
    
    	ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
    
    #endif /* !defined(CONFIGURE_RAN_AS_ROOT) */
    
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    	if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
    		rungroup = ast_config_AST_RUN_GROUP;
    	if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
    		runuser = ast_config_AST_RUN_USER;
    
    	/* Must install this signal handler up here to ensure that if the canary
    	 * fails to execute that it doesn't kill the Asterisk process.
    	 */
    
    	sigaction(SIGCHLD, &child_handler, NULL);
    
    	/* It's common on some platforms to clear /var/run at boot.  Create the
    	 * socket file directory before we drop privileges. */
    
    	if (mkdir(ast_config_AST_RUN_DIR, 0755)) {
    		if (errno == EEXIST) {
    			rundir_exists = 1;
    		} else {
    
    			fprintf(stderr, "Unable to create socket file directory.  Remote consoles will not be able to connect! (%s)\n", strerror(x));
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    #ifndef __CYGWIN__
    
    
    		ast_set_priority(ast_opt_high_priority);
    
    	if (isroot && rungroup) {
    
    		struct group *gr;
    		gr = getgrnam(rungroup);
    		if (!gr) {
    
    			fprintf(stderr, "No such group '%s'!\n", rungroup);
    
    		if (!rundir_exists && chown(ast_config_AST_RUN_DIR, -1, gr->gr_gid)) {
    
    			fprintf(stderr, "Unable to chgrp run directory to %d (%s)\n", (int) gr->gr_gid, rungroup);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		if (setgid(gr->gr_gid)) {
    
    			fprintf(stderr, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    		if (setgroups(0, NULL)) {
    
    			fprintf(stderr, "Unable to drop unneeded groups\n");
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    			exit(1);
    		}
    
    	if (runuser && !ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)) {
    
    #ifdef HAVE_CAP
    		int has_cap = 1;
    #endif /* HAVE_CAP */
    
    		struct passwd *pw;
    		pw = getpwnam(runuser);
    		if (!pw) {
    
    			fprintf(stderr, "No such user '%s'!\n", runuser);
    
    		if (chown(ast_config_AST_RUN_DIR, pw->pw_uid, -1)) {
    
    			fprintf(stderr, "Unable to chown run directory to %d (%s)\n", (int) pw->pw_uid, runuser);
    
    #ifdef HAVE_CAP
    		if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
    			ast_log(LOG_WARNING, "Unable to keep capabilities.\n");
    
    		if (!isroot && pw->pw_uid != geteuid()) {
    
    			fprintf(stderr, "Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
    
    		if (!rungroup) {
    			if (setgid(pw->pw_gid)) {
    
    				fprintf(stderr, "Unable to setgid to %d!\n", (int)pw->pw_gid);
    
    			if (isroot && initgroups(pw->pw_name, pw->pw_gid)) {
    
    				fprintf(stderr, "Unable to init groups for '%s'\n", runuser);
    
    		if (setuid(pw->pw_uid)) {
    
    			fprintf(stderr, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
    
    			cap = cap_from_text("cap_net_admin=eip");
    
    			if (cap_set_proc(cap)) {
    				fprintf(stderr, "Unable to install capabilities.\n");
    			}
    			if (cap_free(cap)) {
    				fprintf(stderr, "Unable to drop capabilities.\n");
    			}
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    #endif /* __CYGWIN__ */
    
    
    	if (geteuid() && ast_opt_dump_core) {
    		if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
    
    			fprintf(stderr, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
    
    #if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
    #if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
    #define eaccess euidaccess
    #endif
    
    		char dir[PATH_MAX];
    		if (!getcwd(dir, sizeof(dir)) || eaccess(dir, R_OK | X_OK | F_OK)) {
    
    			fprintf(stderr, "Unable to access the running directory (%s).  Changing to '/' for compatibility.\n", strerror(errno));
    
    			/* If we cannot access the CWD, then we couldn't dump core anyway,
    			 * so chdir("/") won't break anything. */
    			if (chdir("/")) {
    
    				/* chdir(/) should never fail, so this ends up being a no-op */
    
    				fprintf(stderr, "chdir(\"/\") failed?!! %s\n", strerror(errno));
    
    		} else
    #endif /* defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS) */
    		if (!ast_opt_no_fork && !ast_opt_dump_core) {
    
    			/* Backgrounding, but no cores, so chdir won't break anything. */
    			if (chdir("/")) {
    
    				fprintf(stderr, "Unable to chdir(\"/\") ?!! %s\n", strerror(errno));
    
    	/* Initial value of the maximum active system verbosity level. */
    	ast_verb_sys_level = option_verbose;
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (ast_tryconnect()) {
    		/* One is already running */
    
    Mark Spencer's avatar
    Mark Spencer committed
    				ast_remotecontrol(xarg);
    
    				quit_handler(0, SHUTDOWN_FAST, 0);
    
    Mark Spencer's avatar
    Mark Spencer committed
    				exit(0);
    			}
    
    			ast_term_init();
    			printf("%s", term_end());
    			fflush(stdout);
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    			ast_remotecontrol(NULL);
    
    			quit_handler(0, SHUTDOWN_FAST, 0);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			exit(0);
    		} else {
    
    			fprintf(stderr, "Asterisk already running on %s.  Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			exit(1);
    		}
    
    	} else if (ast_opt_remote || ast_opt_exec) {
    
    		fprintf(stderr, "Unable to connect to remote asterisk (does %s exist?)\n", ast_config_AST_SOCKET);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		exit(1);
    	}
    
    	/* Not a remote console? Start the daemon. */
    	asterisk_daemon(isroot, runuser, rungroup);
    	return 0;
    }
    
    
    static inline void check_init(int init_result, const char *name)
    {
    	if (init_result) {
    
    		if (ast_is_logger_initialized()) {
    			ast_log(LOG_ERROR, "%s initialization failed.  ASTERISK EXITING!\n%s", name, term_quit());
    		} else {
    			fprintf(stderr, "%s initialization failed.  ASTERISK EXITING!\n%s", name, term_quit());
    		}
    
    		ast_run_atexits(0);
    		exit(init_result == -2 ? 2 : 1);
    	}
    }
    
    
    static void asterisk_daemon(int isroot, const char *runuser, const char *rungroup)
    {
    	FILE *f;
    	sigset_t sigs;
    	int num;
    	char *buf;
    
    	char pbx_uuid[AST_UUID_STR_LEN];
    
    	/* This needs to remain as high up in the initial start up as possible.
    	 * daemon causes a fork to occur, which has all sorts of unintended
    	 * consequences for things that interact with threads.  This call *must*
    	 * occur before anything in Asterisk spawns or manipulates thread related
    	 * primitives. */
    
    	if (ast_opt_always_fork || !ast_opt_no_fork) {
    
    #ifndef HAVE_SBIN_LAUNCHD
    
    			fprintf(stderr, "daemon() failed: %s\n", strerror(errno));
    
    		fprintf(stderr, "Mac OS X detected.  Use 'launchctl load /Library/LaunchDaemon/org.asterisk.asterisk.plist'.\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	/* At this point everything has been forked successfully,
    	 * we have determined that we aren't attempting to connect to
    	 * an Asterisk instance, and that there isn't one already running. */
    	multi_thread_safe = 1;
    
    
    #if defined(__AST_DEBUG_MALLOC)
    	__ast_mm_init_phase_1();
    #endif	/* defined(__AST_DEBUG_MALLOC) */
    
    
    	/* Check whether high prio was succesfully set by us or some
    	 * other incantation. */
    	if (has_priority()) {
    		ast_set_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY);
    	} else {
    		ast_clear_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY);
    	}
    
    
    	/* Spawning of astcanary must happen AFTER the call to daemon(3) */
    
    		snprintf(canary_filename, sizeof(canary_filename), "%s/alt.asterisk.canary.tweet.tweet.tweet", ast_config_AST_RUN_DIR);
    
    		/* Don't let the canary child kill Asterisk, if it dies immediately */
    
    		sigaction(SIGPIPE, &ignore_sig_handler, NULL);
    
    			char canary_binary[PATH_MAX], ppid[12];
    
    
    			/* Reset signal handler */
    			signal(SIGCHLD, SIG_DFL);
    			signal(SIGPIPE, SIG_DFL);
    
    			ast_close_fds_above_n(0);
    			ast_set_priority(0);
    
    			snprintf(ppid, sizeof(ppid), "%d", (int) ast_mainpid);
    
    			/* Use the astcanary binary that we installed */
    			snprintf(canary_binary, sizeof(canary_binary), "%s/astcanary", ast_config_AST_SBIN_DIR);
    			execl(canary_binary, "astcanary", canary_filename, ppid, (char *)NULL);
    
    
    			/* Should never happen */
    			_exit(1);
    		} else if (canary_pid > 0) {
    			pthread_t dont_care;
    			ast_pthread_create_detached(&dont_care, NULL, canary_thread, NULL);
    		}
    
    		/* Kill the canary when we exit */
    
    	/* Blindly write the PID file. */
    	unlink(ast_config_AST_PID);
    	f = fopen(ast_config_AST_PID, "w");
    	if (f) {
    
    		fprintf(f, "%ld\n", (long)ast_mainpid);
    
    		fclose(f);
    	} else {
    		fprintf(stderr, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
    	}
    
    	/* Initialize the terminal.  Since all processes have been forked,
    	 * we can now start using the standard log messages.
    	 */
    	ast_term_init();
    	printf("%s", term_end());
    	fflush(stdout);
    
    	print_intro_message(runuser, rungroup);
    
    
    	if (ast_opt_console) {
    		ast_verb(0, "[ Initializing Custom Configuration Options ]\n");
    
    	}
    	/* custom config setup */
    	register_config_cli();
    	read_config_maps();
    
    
    	check_init(astobj2_init(), "AO2");
    	check_init(ast_named_locks_init(), "Named Locks");
    
    	if (ast_opt_console) {
    		if (el_hist == NULL || el == NULL)
    			ast_el_initialize();
    
    		ast_el_read_default_histfile();
    
    #ifdef AST_XML_DOCS
    	/* Load XML documentation. */
    	ast_xmldoc_load_documentation();
    #endif
    
    
    	check_init(astdb_init(), "ASTdb");
    
    
    	ast_uuid_init();
    
    	if (ast_pbx_uuid_get(pbx_uuid, sizeof(pbx_uuid))) {
    		ast_uuid_generate_str(pbx_uuid, sizeof(pbx_uuid));
    		ast_db_put("pbx", "UUID", pbx_uuid);
    	}
    	ast_verb(0, "PBX UUID: %s\n", pbx_uuid);
    
    
    	ast_ulaw_init();
    	ast_alaw_init();
    	tdd_init();
    	callerid_init();
    	ast_builtins_init();
    
    
    	check_init(ast_utils_init(), "Utilities");
    	check_init(ast_tps_init(), "Task Processor Core");
    	check_init(ast_fd_init(), "File Descriptor Debugging");
    	check_init(ast_pbx_init(), "ast_pbx_init");
    
    David Vossel's avatar
    David Vossel committed
    #ifdef TEST_FRAMEWORK
    
    	check_init(ast_test_init(), "Test Framework");
    
    David Vossel's avatar
    David Vossel committed
    #endif
    
    	check_init(ast_translate_init(), "Translator Core");
    
    	ast_aoc_cli_init();
    
    
    	check_init(ast_sorcery_init(), "Sorcery");
    	check_init(ast_codec_init(), "Codecs");
    	check_init(ast_format_init(), "Formats");
    	check_init(ast_format_cache_init(), "Format Cache");
    	check_init(ast_codec_builtin_init(), "Built-in Codecs");
    	check_init(aco_init(), "Configuration Option Framework");
    	check_init(ast_bucket_init(), "Bucket API");
    	check_init(stasis_init(), "Stasis");
    	check_init(ast_stasis_system_init(), "Stasis system-level information");
    	check_init(ast_endpoint_stasis_init(), "Stasis Endpoint");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_makesocket();
    
    David M. Lee's avatar
    David M. Lee committed
    	/* GCC 4.9 gives a bogus "right-hand operand of comma expression has
    	 * no effect" warning */
    	(void) sigemptyset(&sigs);
    	(void) sigaddset(&sigs, SIGHUP);
    	(void) sigaddset(&sigs, SIGTERM);
    	(void) sigaddset(&sigs, SIGINT);
    	(void) sigaddset(&sigs, SIGPIPE);
    	(void) sigaddset(&sigs, SIGWINCH);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	pthread_sigmask(SIG_BLOCK, &sigs, NULL);
    
    	sigaction(SIGURG, &urg_handler, NULL);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	signal(SIGINT, __quit_handler);
    	signal(SIGTERM, __quit_handler);
    
    	sigaction(SIGHUP, &hup_handler, NULL);
    	sigaction(SIGPIPE, &ignore_sig_handler, NULL);
    
    	/* ensure that the random number generators are seeded with a different value every time
    	   Asterisk is started
    	*/
    	srand((unsigned int) getpid() + (unsigned int) time(NULL));
    
    	initstate((unsigned int) getpid() * 65536 + (unsigned int) time(NULL), randompool, sizeof(randompool));
    
    	check_init(init_logger(), "Logger");
    
    	check_init(ast_rtp_engine_init(), "RTP Engine");
    
    	check_init(ast_timing_init(), "Timing");
    	check_init(ast_ssl_init(), "SSL");
    
    	read_pjproject_startup_options();
    
    	check_init(ast_pj_init(), "Embedded PJProject");
    	check_init(app_init(), "App Core");
    	check_init(devstate_init(), "Device State Core");
    	check_init(ast_msg_init(), "Messaging API");
    	check_init(ast_data_init(), "Data Retrieval API");
    	check_init(ast_channels_init(), "Channel");
    	check_init(ast_endpoint_init(), "Endpoints");
    	check_init(ast_pickup_init(), "Call Pickup");
    	check_init(ast_bridging_init(), "Bridging");
    	check_init(ast_parking_stasis_init(), "Parking Core");
    	check_init(ast_device_state_engine_init(), "Device State Engine");
    	check_init(ast_presence_state_engine_init(), "Presence State Engine");
    	check_init(load_modules(1), "Module Preload");
    	check_init(ast_features_init(), "Call Features");
    	check_init(dnsmgr_init(), "DNS manager");
    	check_init(ast_security_stasis_init(), "Security Stasis Topic and Events");
    	check_init(ast_named_acl_init(), "Named ACL system");
    
    	ast_http_init();		/* Start the HTTP server, if needed */
    
    
    	check_init(ast_indications_init(), "Indication Tone Handling");
    	check_init(ast_cdr_engine_init(), "CDR Engine");
    
    	ast_dsp_init();
    	ast_udptl_init();
    
    
    	check_init(ast_image_init(), "Image");
    	check_init(ast_file_init(), "Generic File Format Support");
    	check_init(load_pbx(), "load_pbx");
    	check_init(load_pbx_builtins(), "Builtin PBX Applications");
    	check_init(load_pbx_functions_cli(), "PBX Functions Support");
    	check_init(load_pbx_variables(), "PBX Variables Support");
    	check_init(load_pbx_switch(), "PBX Switch Support");
    	check_init(load_pbx_app(), "PBX Application Support");
    	check_init(load_pbx_hangup_handler(), "PBX Hangup Handler Support");
    	check_init(ast_local_init(), "Local Proxy Channel Driver");
    	check_init(ast_cel_engine_init(), "CEL Engine");
    	check_init(init_manager(), "Asterisk Manager Interface");
    	check_init(ast_enum_init(), "ENUM Support");
    	check_init(ast_cc_init(), "Call Completion Supplementary Services");
    	check_init(load_modules(0), "Module");
    
    	/*
    	 * This is initialized after the dynamic modules load to avoid repeatedly
    	 * reindexing sounds for every format module load.
    	 */
    	check_init(ast_sounds_index_init(), "Sounds Indexer");
    
    
    	/* loads the cli_permissoins.conf file needed to implement cli restrictions. */
    	ast_cli_perms_init(0);
    
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    	dnsmgr_start_refresh();
    
    
    	if (ast_opt_no_fork) {
    
    James Golovich's avatar
    James Golovich committed
    		consolethread = pthread_self();
    
    	if (pipe(sig_alert_pipe)) {
    
    		sig_alert_pipe[0] = sig_alert_pipe[1] = -1;
    
    	ast_set_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
    
    #if defined(__AST_DEBUG_MALLOC)
    
    	__ast_mm_init_phase_2();
    
    #endif	/* defined(__AST_DEBUG_MALLOC) */
    
    	ast_lastreloadtime = ast_startuptime = ast_tvnow();
    
    	ast_cli_register_multiple(cli_asterisk_shutdown, ARRAY_LEN(cli_asterisk_shutdown));
    
    	ast_cli_register_multiple(cli_asterisk, ARRAY_LEN(cli_asterisk));
    
    	ast_register_cleanup(main_atexit);
    
    	ast_sd_notify("READY=1");
    
    	ast_verb(0, COLORIZE_FMT "\n", COLORIZE(COLOR_BRGREEN, 0, "Asterisk Ready."));
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    		/* Console stuff now... */
    		/* Register our quit function */
    
    Mark Spencer's avatar
    Mark Spencer committed
    		char title[256];
    
    		char hostname[MAXHOSTNAMELEN] = "";
    
    		if (gethostname(hostname, sizeof(hostname) - 1)) {
    			ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
    		}
    
    		ast_pthread_create_detached(&mon_sig_flags, NULL, monitor_sig_flags, NULL);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		set_icon("Asterisk");
    
    		snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %ld)", hostname, (long)ast_mainpid);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		set_title(title);
    
    		el_set(el, EL_GETCFN, ast_el_read_char);
    
    
    			if (sig_flags.need_quit || sig_flags.need_quit_handler) {
    
    				quit_handler(0, SHUTDOWN_FAST, 0);
    
    			buf = (char *) el_gets(el, &num);
    
    			if (!buf && write(1, "", 1) < 0)
    
    			if (buf) {
    				if (buf[strlen(buf)-1] == '\n')
    					buf[strlen(buf)-1] = '\0';
    
    Mark Spencer's avatar
    Mark Spencer committed
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	/* Stall until a quit signal is given */
    
    	monitor_sig_flags(NULL);
    
    Mark Spencer's avatar
    Mark Spencer committed
    }