asterisk.c

来自「在asterisk平台写注册命令的程序」· C语言 代码 · 共 2,332 行 · 第 1/5 页

C
2,332
字号
	ast_mutex_lock(&safe_system_lock);	level = --safe_system_level;	/* only restore the handler if we are the last one */	if (level == 0)		signal(SIGCHLD, safe_system_prev_handler);	ast_mutex_unlock(&safe_system_lock);	return res;}/*! * write the string to all attached console clients */static void ast_network_puts(const char *string){	int x;	for (x=0;x<AST_MAX_CONNECTS; x++) {		if (consoles[x].fd > -1) 			fdprint(consoles[x].p[1], string);	}}/*! * write the string to the console, and all attached * console clients */void ast_console_puts(const char *string){	fputs(string, stdout);	fflush(stdout);	ast_network_puts(string);}static void network_verboser(const char *s, int pos, int replace, int complete)	/* ARGUSED */{	if (replace) {		char *t = alloca(strlen(s) + 2);		if (t) {			sprintf(t, "\r%s", s);			if (complete)				ast_network_puts(t);		} else {			ast_log(LOG_ERROR, "Out of memory\n");			ast_network_puts(s);		}	} else {		if (complete)			ast_network_puts(s);	}}static pthread_t lthread;static void *netconsole(void *vconsole){	struct console *con = vconsole;	char hostname[MAXHOSTNAMELEN]="";	char tmp[512];	int res;	struct pollfd fds[2];		if (gethostname(hostname, sizeof(hostname)-1))		ast_copy_string(hostname, "<Unknown>", sizeof(hostname));	snprintf(tmp, sizeof(tmp), "%s/%d/%s\n", hostname, ast_mainpid, ASTERISK_VERSION);	fdprint(con->fd, tmp);	for(;;) {		fds[0].fd = con->fd;		fds[0].events = POLLIN;		fds[0].revents = 0;		fds[1].fd = con->p[0];		fds[1].events = POLLIN;		fds[1].revents = 0;		res = poll(fds, 2, -1);		if (res < 0) {			if (errno != EINTR)				ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));			continue;		}		if (fds[0].revents) {			res = read(con->fd, tmp, sizeof(tmp));			if (res < 1) {				break;			}			tmp[res] = 0;			ast_cli_command(con->fd, tmp);		}		if (fds[1].revents) {			res = read(con->p[0], tmp, sizeof(tmp));			if (res < 1) {				ast_log(LOG_ERROR, "read returned %d\n", res);				break;			}			res = write(con->fd, tmp, res);			if (res < 1)				break;		}	}	if (option_verbose > 2) 		ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection disconnected\n");	close(con->fd);	close(con->p[0]);	close(con->p[1]);	con->fd = -1;		return NULL;}static void *listener(void *unused){	struct sockaddr_un sunaddr;	int s;	socklen_t len;	int x;	int flags;	struct pollfd fds[1];	pthread_attr_t attr;	pthread_attr_init(&attr);	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);	for(;;) {		if (ast_socket < 0)			return NULL;		fds[0].fd = ast_socket;		fds[0].events= POLLIN;		s = poll(fds, 1, -1);		pthread_testcancel();		if (s < 0) {			if (errno != EINTR)				ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));			continue;		}		len = sizeof(sunaddr);		s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);		if (s < 0) {			if (errno != EINTR)				ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));		} else {			for (x=0;x<AST_MAX_CONNECTS;x++) {				if (consoles[x].fd < 0) {					if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {						ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));						consoles[x].fd = -1;						fdprint(s, "Server failed to create pipe\n");						close(s);						break;					}					flags = fcntl(consoles[x].p[1], F_GETFL);					fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);					consoles[x].fd = s;					if (ast_pthread_create(&consoles[x].t, &attr, netconsole, &consoles[x])) {						ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));						close(consoles[x].p[0]);						close(consoles[x].p[1]);						consoles[x].fd = -1;						fdprint(s, "Server failed to spawn thread\n");						close(s);					}					break;				}			}			if (x >= AST_MAX_CONNECTS) {				fdprint(s, "No more connections allowed\n");				ast_log(LOG_WARNING, "No more connections allowed\n");				close(s);			} else if (consoles[x].fd > -1) {				if (option_verbose > 2) 					ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection\n");			}		}	}	return NULL;}static int ast_makesocket(void){	struct sockaddr_un sunaddr;	int res;	int x;	uid_t uid = -1;	gid_t gid = -1;	for (x = 0; x < AST_MAX_CONNECTS; x++)			consoles[x].fd = -1;	unlink(ast_config_AST_SOCKET);	ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);	if (ast_socket < 0) {		ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));		return -1;	}			memset(&sunaddr, 0, sizeof(sunaddr));	sunaddr.sun_family = AF_LOCAL;	ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));	res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));	if (res) {		ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));		close(ast_socket);		ast_socket = -1;		return -1;	}	res = listen(ast_socket, 2);	if (res < 0) {		ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));		close(ast_socket);		ast_socket = -1;		return -1;	}	ast_register_verbose(network_verboser);	ast_pthread_create(&lthread, NULL, listener, NULL);	if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {		struct passwd *pw;		if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL) {			ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);		} else {			uid = pw->pw_uid;		}	}			if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) {		struct group *grp;		if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL) {			ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);		} else {			gid = grp->gr_gid;		}	}	if (chown(ast_config_AST_SOCKET, uid, gid) < 0)		ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));	if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) {		int p1;		mode_t p;		sscanf(ast_config_AST_CTL_PERMISSIONS, "%o", &p1);		p = p1;		if ((chmod(ast_config_AST_SOCKET, p)) < 0)			ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));	}	return 0;}static int ast_tryconnect(void){	struct sockaddr_un sunaddr;	int res;	ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);	if (ast_consock < 0) {		ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));		return 0;	}	memset(&sunaddr, 0, sizeof(sunaddr));	sunaddr.sun_family = AF_LOCAL;	ast_copy_string(sunaddr.sun_path, (char *)ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));	res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));	if (res) {		close(ast_consock);		ast_consock = -1;		return 0;	} else		return 1;}/*! Urgent handler Called by soft_hangup to interrupt the poll, read, or other system call.  We don't actually need to do anything though.   Remember: Cannot EVER ast_log from within a signal handler  */static void urg_handler(int num){	signal(num, urg_handler);	return;}static void hup_handler(int num){	if (option_verbose > 1) 		printf("Received HUP signal -- Reloading configs\n");	if (restartnow)		execvp(_argv[0], _argv);	/* XXX This could deadlock XXX */	ast_module_reload(NULL);	signal(num, hup_handler);}static void child_handler(int sig){	/* Must not ever ast_log or ast_verbose within signal handler */	int n, status;	/*	 * Reap all dead children -- not just one	 */	for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++)		;	if (n == 0 && option_debug)			printf("Huh?  Child handler, but nobody there?\n");	signal(sig, child_handler);}/*! Set an X-term or screen title */static void set_title(char *text){	if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))		fprintf(stdout, "\033]2;%s\007", text);}static void set_icon(char *text){	if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))		fprintf(stdout, "\033]1;%s\007", text);}/*! We set ourselves to a high priority, that we might pre-empt everything   else.  If your PBX has heavy activity on it, this is a good thing.  */int ast_set_priority(int pri){	struct sched_param sched;	memset(&sched, 0, sizeof(sched));#ifdef __linux__	if (pri) {  		sched.sched_priority = 10;		if (sched_setscheduler(0, SCHED_RR, &sched)) {			ast_log(LOG_WARNING, "Unable to set high priority\n");			return -1;		} else			if (option_verbose)				ast_verbose("Set to realtime thread\n");	} else {		sched.sched_priority = 0;		if (sched_setscheduler(0, SCHED_OTHER, &sched)) {			ast_log(LOG_WARNING, "Unable to set normal priority\n");			return -1;		}	}#else	if (pri) {		if (setpriority(PRIO_PROCESS, 0, -10) == -1) {			ast_log(LOG_WARNING, "Unable to set high priority\n");			return -1;		} else			if (option_verbose)				ast_verbose("Set to high priority\n");	} else {		if (setpriority(PRIO_PROCESS, 0, 0) == -1) {			ast_log(LOG_WARNING, "Unable to set normal priority\n");			return -1;		}	}#endif	return 0;}static void ast_run_atexits(void){	struct ast_atexit *ae;	ast_mutex_lock(&atexitslock);	ae = atexits;	while(ae) {		if (ae->func) 			ae->func();		ae = ae->next;	}	ast_mutex_unlock(&atexitslock);}static void quit_handler(int num, int nice, int safeshutdown, int restart){	char filename[80] = "";	time_t s,e;	int x;	/* Try to get as many CDRs as possible submitted to the backend engines (if in batch mode) */	ast_cdr_engine_term();	if (safeshutdown) {		shuttingdown = 1;		if (!nice) {			/* Begin shutdown routine, hanging up active channels */			ast_begin_shutdown(1);			if (option_verbose && option_console)				ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");			time(&s);			for(;;) {				time(&e);				/* Wait up to 15 seconds for all channels to go away */				if ((e - s) > 15)					break;				if (!ast_active_channels())					break;				if (!shuttingdown)					break;				/* Sleep 1/10 of a second */				usleep(100000);			}		} else {			if (nice < 2)				ast_begin_shutdown(0);			if (option_verbose && option_console)				ast_verbose("Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");			for(;;) {				if (!ast_active_channels())					break;				if (!shuttingdown)					break;				sleep(1);			}		}		if (!shuttingdown) {			if (option_verbose && option_console)				ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");			return;		}	}	if (option_console || option_remote) {		if (getenv("HOME")) 			snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));		if (!ast_strlen_zero(filename))			ast_el_write_history(filename);		if (el != NULL)			el_end(el);		if (el_hist != NULL)			history_end(el_hist);	}	if (option_verbose)		ast_verbose("Executing last minute cleanups\n");	ast_run_atexits();	/* Called on exit */	if (option_verbose && option_console)		ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);	else if (option_debug)		ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num);	manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\nRestart: %s\r\n", ast_active_channels() ? "Uncleanly" : "Cleanly", restart ? "True" : "False");	if (ast_socket > -1) {		pthread_cancel(lthread);		close(ast_socket);		ast_socket = -1;		unlink(ast_config_AST_SOCKET);	}	if (ast_consock > -1)		close(ast_consock);	if (!option_remote) unlink((char *)ast_config_AST_PID);	printf(term_quit());	if (restart) {		if (option_verbose || option_console)			ast_verbose("Preparing for Asterisk restart...\n");		/* Mark all FD's for closing on exec */		for (x=3;x<32768;x++) {			fcntl(x, F_SETFD, FD_CLOEXEC);		}		if (option_verbose || option_console)			ast_verbose("Restarting Asterisk NOW...\n");		restartnow = 1;		/* close logger */		close_logger();		/* If there is a consolethread running send it a SIGHUP 		   so it can execvp, otherwise we can do it ourselves */		if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {			pthread_kill(consolethread, SIGHUP);			/* Give the signal handler some time to complete */			sleep(2);		} else			execvp(_argv[0], _argv);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?