Skip to content
Snippets Groups Projects
asterisk.c 66.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • Mark Spencer's avatar
    Mark Spencer committed
    	/* Remember original args for restart */
    	if (argc > sizeof(_argv) / sizeof(_argv[0]) - 1) {
    
    		fprintf(stderr, "Truncating argument size to %d\n", (int)(sizeof(_argv) / sizeof(_argv[0])) - 1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		argc = sizeof(_argv) / sizeof(_argv[0]) - 1;
    	}
    	for (x=0;x<argc;x++)
    		_argv[x] = argv[x];
    	_argv[x] = NULL;
    
    
    	/* 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);
    
    	if (gethostname(hostname, sizeof(hostname)-1))
    
    		ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_ulaw_init();
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_alaw_init();
    
    Mark Spencer's avatar
    Mark Spencer committed
    	callerid_init();
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_utils_init();
    
    Mark Spencer's avatar
    Mark Spencer committed
    	tdd_init();
    
    	/* When Asterisk restarts after it has dropped the root privileges,
    	 * it can't issue setuid(), setgid(), setgroups() or set_priority() 
    	 * */
    	if (getenv("ASTERISK_ALREADY_NONROOT"))
    		is_child_of_nonroot=1;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (getenv("HOME")) 
    		snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Check if we're root */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/*
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (geteuid()) {
    		ast_log(LOG_ERROR, "Must be run as root\n");
    		exit(1);
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	*/
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Check for options */
    
    	while((c=getopt(argc, argv, "tThfdvVqprRgcinx:U:G:C:L:M:")) != -1) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		switch(c) {
    		case 'd':
    			option_debug++;
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'c':
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'f':
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'n':
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_COLOR);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'r':
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE | AST_OPT_FLAG_RECONNECT);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'p':
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    		case 'v':
    			option_verbose++;
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'M':
    			if ((sscanf(optarg, "%d", &option_maxcalls) != 1) || (option_maxcalls < 0))
    				option_maxcalls = 0;
    			break;
    
    		case 'L':
    			if ((sscanf(optarg, "%lf", &option_maxload) != 1) || (option_maxload < 0.0))
    				option_maxload = 0.0;
    			break;
    
    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;
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES);
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'x':
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			xarg = optarg;
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'C':
    
    			ast_copy_string(ast_config_AST_CONFIG_FILE, optarg, sizeof(ast_config_AST_CONFIG_FILE));
    			ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'i':
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case'g':
    
    			ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'h':
    			show_cli_help();
    			exit(0);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'V':
    			show_version();
    			exit(0);
    
    		case 'U':
    			runuser = optarg;
    			break;
    		case 'G':
    			rungroup = optarg;
    			break;
    
    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;
    		}
    	}
    
    
    	if (ast_opt_console && !option_verbose) 
    		ast_verbose("[ Reading Master Configuration ]");
    	ast_readconfig();
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    		struct rlimit l;
    		memset(&l, 0, sizeof(l));
    		l.rlim_cur = RLIM_INFINITY;
    		l.rlim_max = RLIM_INFINITY;
    		if (setrlimit(RLIMIT_CORE, &l)) {
    			ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
    		}
    	}
    
    
    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;
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    #ifndef __CYGWIN__
    
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    	if (!is_child_of_nonroot) 
    
    		ast_set_priority(ast_opt_high_priority);
    
    		struct group *gr;
    		gr = getgrnam(rungroup);
    		if (!gr) {
    			ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
    			exit(1);
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		if (setgid(gr->gr_gid)) {
    
    			ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", gr->gr_gid, rungroup);
    			exit(1);
    		}
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    		if (setgroups(0, NULL)) {
    			ast_log(LOG_WARNING, "Unable to drop unneeded groups\n");
    			exit(1);
    		}
    
    		if (option_verbose)
    			ast_verbose("Running as group '%s'\n", rungroup);
    	}
    
    
    		struct passwd *pw;
    		pw = getpwnam(runuser);
    		if (!pw) {
    			ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
    			exit(1);
    		}
    
    		if (!rungroup) {
    			if (setgid(pw->pw_gid)) {
    				ast_log(LOG_WARNING, "Unable to setgid to %d!\n", pw->pw_gid);
    				exit(1);
    			}
    
    			if (initgroups(pw->pw_name, pw->pw_gid)) {
    				ast_log(LOG_WARNING, "Unable to init groups for '%s'\n", runuser);
    				exit(1);
    			}
    
    		if (setuid(pw->pw_uid)) {
    			ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", pw->pw_uid, runuser);
    			exit(1);
    		}
    
    		setenv("ASTERISK_ALREADY_NONROOT","yes",1);
    
    		if (option_verbose)
    			ast_verbose("Running as user '%s'\n", runuser);
    	}
    
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    #endif /* __CYGWIN__ */
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    	term_init();
    	printf(term_end());
    	fflush(stdout);
    
    		ast_verbose("[ Initializing Custom Configuration Options ]");
    
    	/* custom config setup */
    	register_config_cli();
    
    	read_config_maps();
    
    		if (el_hist == NULL || el == NULL)
    			ast_el_initialize();
    
    		if (!ast_strlen_zero(filename))
    			ast_el_read_history(filename);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (ast_tryconnect()) {
    		/* One is already running */
    
    Mark Spencer's avatar
    Mark Spencer committed
    				ast_remotecontrol(xarg);
    
    Mark Spencer's avatar
    Mark Spencer committed
    				quit_handler(0, 0, 0, 0);
    
    Mark Spencer's avatar
    Mark Spencer committed
    				exit(0);
    			}
    
    Mark Spencer's avatar
    Mark Spencer committed
    			printf(term_quit());
    
    Mark Spencer's avatar
    Mark Spencer committed
    			ast_register_verbose(console_verboser);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			WELCOME_MESSAGE;
    
    Mark Spencer's avatar
    Mark Spencer committed
    			ast_remotecontrol(NULL);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			quit_handler(0, 0, 0, 0);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			exit(0);
    		} else {
    
    			ast_log(LOG_ERROR, "Asterisk already running on %s.  Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			printf(term_quit());
    
    Mark Spencer's avatar
    Mark Spencer committed
    			exit(1);
    		}
    
    	} else if (ast_opt_remote || ast_opt_exec) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_log(LOG_ERROR, "Unable to connect to remote asterisk (does %s exist?)\n",ast_config_AST_SOCKET);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		printf(term_quit());
    
    Mark Spencer's avatar
    Mark Spencer committed
    		exit(1);
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Blindly write pid file since we couldn't connect */
    
    	unlink(ast_config_AST_PID);
    	f = fopen(ast_config_AST_PID, "w");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (f) {
    		fprintf(f, "%d\n", getpid());
    		fclose(f);
    	} else
    
    		ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
    
    	if (!option_verbose && !option_debug && !ast_opt_no_fork && !ast_opt_console) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		daemon(0,0);
    
    		/* Blindly re-write pid file since we are forking */
    
    		unlink(ast_config_AST_PID);
    		f = fopen(ast_config_AST_PID, "w");
    
    		if (f) {
    			fprintf(f, "%d\n", getpid());
    			fclose(f);
    		} else
    
    			ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	/* Test recursive mutex locking. */
    	if (test_for_thread_safety())
    		ast_verbose("Warning! Asterisk is not thread safe.\n");
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_makesocket();
    	sigemptyset(&sigs);
    	sigaddset(&sigs, SIGHUP);
    	sigaddset(&sigs, SIGTERM);
    	sigaddset(&sigs, SIGINT);
    	sigaddset(&sigs, SIGPIPE);
    	sigaddset(&sigs, SIGWINCH);
    	pthread_sigmask(SIG_BLOCK, &sigs, NULL);
    
    	if (ast_opt_console || option_verbose || ast_opt_remote)
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_register_verbose(console_verboser);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Print a welcome message if desired */
    
    	if (option_verbose || ast_opt_console) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		WELCOME_MESSAGE;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_verbose("[ Booting...");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	signal(SIGURG, urg_handler);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	signal(SIGINT, __quit_handler);
    	signal(SIGTERM, __quit_handler);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	signal(SIGHUP, hup_handler);
    
    	signal(SIGCHLD, child_handler);
    	signal(SIGPIPE, SIG_IGN);
    
    
    	/* 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));
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (init_logger()) {
    		printf(term_quit());
    
    Mark Spencer's avatar
    Mark Spencer committed
    		exit(1);
    
    	if (dnsmgr_init()) {
    		printf(term_quit());
    		exit(1);
    	}
    
    	/* load 'preload' modules, required for access to Realtime-mapped configuration files */
    	if (load_modules(1)) {
    		printf(term_quit());
    		exit(1);
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (init_manager()) {
    		printf(term_quit());
    		exit(1);
    	}
    
    	if (ast_cdr_engine_init()) {
    		printf(term_quit());
    		exit(1);
    	}
    
    	if (ast_device_state_engine_init()) {
    		printf(term_quit());
    		exit(1);
    	}
    
    	ast_rtp_init();
    
    #if defined(T38_SUPPORT)
    	ast_udptl_init();
    #endif
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (ast_image_init()) {
    		printf(term_quit());
    
    Mark Spencer's avatar
    Mark Spencer committed
    		exit(1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (load_pbx()) {
    		printf(term_quit());
    
    Mark Spencer's avatar
    Mark Spencer committed
    		exit(1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		printf(term_quit());
    
    Mark Spencer's avatar
    Mark Spencer committed
    		exit(1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    	if (init_framer()) {
    		printf(term_quit());
    
    Mark Spencer's avatar
    Mark Spencer committed
    		exit(1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (astdb_init()) {
    		printf(term_quit());
    		exit(1);
    	}
    
    	if (ast_enum_init()) {
    		printf(term_quit());
    		exit(1);
    	}
    
    Kevin P. Fleming's avatar
    Kevin P. Fleming committed
    
    	dnsmgr_start_refresh();
    
    
    #if 0
    	/* This should no longer be necessary */
    
    	/* sync cust config and reload some internals in case a custom config handler binded to them */
    	read_ast_cust_config();
    
    	reload_logger(0);
    
    James Golovich's avatar
    James Golovich committed
    	reload_manager();
    	ast_enum_reload();
    	ast_rtp_reload();
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* We might have the option of showing a console, but for now just
    	   do nothing... */
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_verbose(" ]\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_verbose(term_color(tmp, "Asterisk Ready.\n", COLOR_BRWHITE, COLOR_BLACK, sizeof(tmp)));
    
    James Golovich's avatar
    James Golovich committed
    		consolethread = pthread_self();
    
    	ast_set_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	time(&ast_startuptime);
    
    	ast_cli_register_multiple(core_cli, sizeof(core_cli) / sizeof(core_cli[0]));
    
    Mark Spencer's avatar
    Mark Spencer committed
    		/* Console stuff now... */
    		/* Register our quit function */
    
    Mark Spencer's avatar
    Mark Spencer committed
    		char title[256];
    		set_icon("Asterisk");
    
    		snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %d)", hostname, ast_mainpid);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		set_title(title);
    
    		for (;;) {
    			buf = (char *)el_gets(el, &num);
    			if (buf) {
    				if (buf[strlen(buf)-1] == '\n')
    					buf[strlen(buf)-1] = '\0';
    
    				consolehandler((char *)buf);
    
    				if (write(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n",
    								  strlen("\nUse EXIT or QUIT to exit the asterisk console\n")) < 0) {
    					/* Whoa, stdout disappeared from under us... Make /dev/null's */
    					int fd;
    					fd = open("/dev/null", O_RDWR);
    					if (fd > -1) {
    						dup2(fd, STDOUT_FILENO);
    						dup2(fd, STDIN_FILENO);
    					} else
    						ast_log(LOG_WARNING, "Failed to open /dev/null to recover from dead console.  Bad things will happen!\n");
    					break;
    				}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	for(;;)  {	/* apparently needed for the MACos */
    		struct pollfd p = { -1 /* no descriptor */, 0, 0 };
    		poll(&p, 0, -1);
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return 0;
    }