Skip to content
Snippets Groups Projects
asterisk.c 53.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • Mark Spencer's avatar
    Mark Spencer committed
    			if (!option_exec && !lastpos)
    
    Mark Spencer's avatar
    Mark Spencer committed
    				write(STDOUT_FILENO, "\r", 1);
    			write(STDOUT_FILENO, buf, res);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			if ((buf[res-1] == '\n') || (buf[res-2] == '\n')) {
    
    				*cp = CC_REFRESH;
    				return(1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			} else {
    				lastpos = 1;
    			}
    		}
    	}
    
    	*cp = '\0';
    	return (0);
    }
    
    static char *cli_prompt(EditLine *el)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    	int color_used=0;
    	char term_code[20];
    
    
    	if ((pfmt = getenv("ASTERISK_PROMPT"))) {
    		char *t = pfmt, *p = prompt;
    		memset(prompt, 0, sizeof(prompt));
    		while (*t != '\0' && *p < sizeof(prompt)) {
    			if (*t == '%') {
    
    				char hostname[256];
    				int i;
    				struct timeval tv;
    				struct tm tm;
    
    				int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
    
    
    					case 'C': /* color */
    						t++;
    						if (sscanf(t, "%d;%d%n", &fgcolor, &bgcolor, &i) == 2) {
    
    							strncat(p, term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
    
    							t += i - 1;
    						} else if (sscanf(t, "%d%n", &fgcolor, &i) == 1) {
    
    							strncat(p, term_color_code(term_code, fgcolor, 0, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
    
    							t += i - 1;
    						}
    
    						/* If the color has been reset correctly, then there's no need to reset it later */
    						if ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) {
    							color_used = 0;
    						} else {
    							color_used = 1;
    						}
    						break;
    
    					case 'd': /* date */
    						memset(&tm, 0, sizeof(struct tm));
    						gettimeofday(&tv, NULL);
    						if (localtime_r(&(tv.tv_sec), &tm)) {
    							strftime(p, sizeof(prompt) - strlen(prompt), "%Y-%m-%d", &tm);
    						}
    						break;
    					case 'h': /* hostname */
    						if (!gethostname(hostname, sizeof(hostname) - 1)) {
    
    							strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
    
    							strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
    
    					case 'H': /* short hostname */
    						if (!gethostname(hostname, sizeof(hostname) - 1)) {
    							for (i=0;i<sizeof(hostname);i++) {
    								if (hostname[i] == '.') {
    									hostname[i] = '\0';
    									break;
    								}
    							}
    
    							strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
    
    							strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
    
    #ifdef linux
    					case 'l': /* load avg */
    						t++;
    						if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
    							float avg1, avg2, avg3;
    							int actproc, totproc, npid, which;
    							fscanf(LOADAVG, "%f %f %f %d/%d %d",
    								&avg1, &avg2, &avg3, &actproc, &totproc, &npid);
    							if (sscanf(t, "%d", &which) == 1) {
    								switch (which) {
    									case 1:
    										snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg1);
    										break;
    									case 2:
    										snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg2);
    										break;
    									case 3:
    										snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg3);
    										break;
    									case 4:
    										snprintf(p, sizeof(prompt) - strlen(prompt), "%d/%d", actproc, totproc);
    										break;
    									case 5:
    										snprintf(p, sizeof(prompt) - strlen(prompt), "%d", npid);
    										break;
    								}
    							}
    						}
    						break;
    #endif
    					case 't': /* time */
    						memset(&tm, 0, sizeof(struct tm));
    						gettimeofday(&tv, NULL);
    						if (localtime_r(&(tv.tv_sec), &tm)) {
    							strftime(p, sizeof(prompt) - strlen(prompt), "%H:%M:%S", &tm);
    						}
    						break;
    					case '#': /* process console or remote? */
    						if (! option_remote) {
    
    							strncat(p, "#", sizeof(prompt) - strlen(prompt) - 1);
    
    							strncat(p, ">", sizeof(prompt) - strlen(prompt) - 1);
    
    						strncat(p, "%", sizeof(prompt) - strlen(prompt) - 1);
    
    						break;
    					case '\0': /* % is last character - prevent bug */
    						t--;
    						break;
    				}
    				while (*p != '\0') {
    					p++;
    				}
    				t++;
    			} else {
    				*p = *t;
    				p++;
    				t++;
    			}
    		}
    
    		if (color_used) {
    			/* Force colors back to normal at end */
    			term_color_code(term_code, COLOR_WHITE, COLOR_BLACK, sizeof(term_code));
    			if (strlen(term_code) > sizeof(prompt) - strlen(prompt)) {
    				strncat(prompt + sizeof(prompt) - strlen(term_code) - 1, term_code, strlen(term_code));
    			} else {
    				strncat(p, term_code, sizeof(term_code));
    			}
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT2, remotehostname);
    	else
    		snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT);
    
    
    	return(prompt);	
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    static char **ast_el_strtoarr(char *buf)
    {
    	char **match_list = NULL, *retstr;
    
    	size_t match_list_len;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	int matches = 0;
    
    
    	match_list_len = 1;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	while ( (retstr = strsep(&buf, " ")) != NULL) {
    
    
    		if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
    			break;
    
    		if (matches + 1 >= match_list_len) {
    			match_list_len <<= 1;
    			match_list = realloc(match_list, match_list_len * sizeof(char *));
    
    		match_list[matches++] = strdup(retstr);
    
    	if (!match_list)
    		return (char **) NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	if (matches>= match_list_len)
    		match_list = realloc(match_list, (match_list_len + 1) * sizeof(char *));
    
    	match_list[matches] = (char *) NULL;
    
    	return match_list;
    }
    
    static int ast_el_sort_compare(const void *i1, const void *i2)
    {
    	char *s1, *s2;
    
    	s1 = ((char **)i1)[0];
    	s2 = ((char **)i2)[0];
    
    	return strcasecmp(s1, s2);
    }
    
    static int ast_cli_display_match_list(char **matches, int len, int max)
    {
    	int i, idx, limit, count;
    	int screenwidth = 0;
    	int numoutput = 0, numoutputline = 0;
    
    	screenwidth = ast_get_termcols(STDOUT_FILENO);
    
    	/* find out how many entries can be put on one line, with two spaces between strings */
    	limit = screenwidth / (max + 2);
    	if (limit == 0)
    		limit = 1;
    
    	/* how many lines of output */
    	count = len / limit;
    	if (count * limit < len)
    		count++;
    
    	idx = 1;
    
    	qsort(&matches[0], (size_t)(len + 1), sizeof(char *), ast_el_sort_compare);
    
    	for (; count > 0; count--) {
    		numoutputline = 0;
    		for (i=0; i < limit && matches[idx]; i++, idx++) {
    
    			/* Don't print dupes */
    			if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
    				i--;
    
    				free(matches[idx]);
    				matches[idx] = NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    				continue;
    			}
    
    
    			numoutput++;
    			numoutputline++;
    
    Mark Spencer's avatar
    Mark Spencer committed
    			fprintf(stdout, "%-*s  ", max, matches[idx]);
    
    			free(matches[idx]);
    			matches[idx] = NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		}
    		if (numoutputline > 0)
    			fprintf(stdout, "\n");
    	}
    
    	return numoutput;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    static char *cli_complete(EditLine *el, int ch)
    
    Mark Spencer's avatar
    Mark Spencer committed
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	int len=0;
    	char *ptr;
    	int nummatches = 0;
    	char **matches;
    	int retval = CC_ERROR;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	int res;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	LineInfo *lf = (LineInfo *)el_line(el);
    
    
    	*(char *)lf->cursor = '\0';
    
    	ptr = (char *)lf->cursor;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (ptr) {
    		while (ptr > lf->buffer) {
    			if (isspace(*ptr)) {
    				ptr++;
    				break;
    			}
    			ptr--;
    		}
    	}
    
    	len = lf->cursor - ptr;
    
    	if (option_remote) {
    		snprintf(buf, sizeof(buf),"_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr); 
    		fdprint(ast_consock, buf);
    		res = read(ast_consock, buf, sizeof(buf));
    		buf[res] = '\0';
    		nummatches = atoi(buf);
    
    		if (nummatches > 0) {
    
    			char *mbuf;
    			int mlen = 0, maxmbuf = 2048;
    			/* Start with a 2048 byte buffer */
    			mbuf = malloc(maxmbuf);
    			if (!mbuf)
    
    				return (char *)(CC_ERROR);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			snprintf(buf, sizeof(buf),"_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr); 
    			fdprint(ast_consock, buf);
    
    			while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
    				if (mlen + 1024 > maxmbuf) {
    					/* Every step increment buffer 1024 bytes */
    					maxmbuf += 1024;
    					mbuf = realloc(mbuf, maxmbuf);
    					if (!mbuf)
    
    						return (char *)(CC_ERROR);
    
    				}
    				/* Only read 1024 bytes at a time */
    				res = read(ast_consock, mbuf + mlen, 1024);
    				if (res > 0)
    					mlen += res;
    			}
    			mbuf[mlen] = '\0';
    
    			matches = ast_el_strtoarr(mbuf);
    			free(mbuf);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		} else
    			matches = (char **) NULL;
    
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    		nummatches = ast_cli_generatornummatches((char *)lf->buffer,ptr);
    		matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
    	}
    
    	if (matches) {
    		int i;
    		int matches_num, maxlen, match_len;
    
    		if (matches[0][0] != '\0') {
    			el_deletestr(el, (int) len);
    			el_insertstr(el, matches[0]);
    			retval = CC_REFRESH;
    		}
    
    		if (nummatches == 1) {
    			/* Found an exact match */
    
    			el_insertstr(el, " ");
    
    Mark Spencer's avatar
    Mark Spencer committed
    			retval = CC_REFRESH;
    		} else {
    			/* Must be more than one match */
    			for (i=1, maxlen=0; matches[i]; i++) {
    				match_len = strlen(matches[i]);
    				if (match_len > maxlen)
    					maxlen = match_len;
    			}
    			matches_num = i - 1;
    			if (matches_num >1) {
    				fprintf(stdout, "\n");
    				ast_cli_display_match_list(matches, nummatches, maxlen);
    				retval = CC_REDISPLAY;
    			} else { 
    
    				el_insertstr(el," ");
    
    Mark Spencer's avatar
    Mark Spencer committed
    				retval = CC_REFRESH;
    			}
    		}
    
    	free(matches);
    
    	return (char *)(long)retval;
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    static int ast_el_initialize(void)
    {
    	HistEvent ev;
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	if (el != NULL)
    		el_end(el);
    	if (el_hist != NULL)
    		history_end(el_hist);
    
    	el = el_init("asterisk", stdin, stdout, stderr);
    	el_set(el, EL_PROMPT, cli_prompt);
    
    	el_set(el, EL_EDITMODE, 1);		
    
    	el_set(el, EL_EDITOR, editor ? editor : "emacs");		
    
    Mark Spencer's avatar
    Mark Spencer committed
    	el_hist = history_init();
    	if (!el || !el_hist)
    		return -1;
    
    	/* setup history with 100 entries */
    	history(el_hist, &ev, H_SETSIZE, 100);
    
    	el_set(el, EL_HIST, history, el_hist);
    
    	el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
    	/* Bind <tab> to command completion */
    	el_set(el, EL_BIND, "^I", "ed-complete", NULL);
    	/* Bind ? to command completion */
    	el_set(el, EL_BIND, "?", "ed-complete", NULL);
    
    	/* Bind ^D to redisplay */
    	el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	return 0;
    }
    
    static int ast_el_add_history(char *buf)
    {
    	HistEvent ev;
    
    	if (el_hist == NULL || el == NULL)
    		ast_el_initialize();
    
    	if (strlen(buf) > 256)
    		return 0;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	return (history(el_hist, &ev, H_ENTER, buf));
    }
    
    static int ast_el_write_history(char *filename)
    {
    	HistEvent ev;
    
    	if (el_hist == NULL || el == NULL)
    		ast_el_initialize();
    
    	return (history(el_hist, &ev, H_SAVE, filename));
    }
    
    static int ast_el_read_history(char *filename)
    {
    	char buf[256];
    	FILE *f;
    	int ret = -1;
    
    	if (el_hist == NULL || el == NULL)
    		ast_el_initialize();
    
    	if ((f = fopen(filename, "r")) == NULL)
    		return ret;
    
    	while (!feof(f)) {
    		fgets(buf, sizeof(buf), f);
    		if (!strcmp(buf, "_HiStOrY_V2_\n"))
    			continue;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		if ((ret = ast_el_add_history(buf)) == -1)
    			break;
    	}
    	fclose(f);
    
    	return ret;
    
    Mark Spencer's avatar
    Mark Spencer committed
    }
    
    static void ast_remotecontrol(char * data)
    {
    	char buf[80];
    	int res;
    	char filename[80] = "";
    	char *hostname;
    	char *cpid;
    	char *version;
    	int pid;
    	char tmp[80];
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char *stringp=NULL;
    
    	char *ebuf;
    	int num = 0;
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    	read(ast_consock, buf, sizeof(buf));
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (data)
    		write(ast_consock, data, strlen(data) + 1);
    	stringp=buf;
    	hostname = strsep(&stringp, "/");
    	cpid = strsep(&stringp, "/");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	version = strsep(&stringp, "\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (!version)
    		version = "<Version Unknown>";
    
    Mark Spencer's avatar
    Mark Spencer committed
    	stringp=hostname;
    	strsep(&stringp, ".");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (cpid)
    		pid = atoi(cpid);
    	else
    		pid = -1;
    
    	snprintf(tmp, sizeof(tmp), "set verbose atleast %d", option_verbose);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	fdprint(ast_consock, tmp);
    
    	snprintf(tmp, sizeof(tmp), "set debug atleast %d", option_debug);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	remotehostname = hostname;
    
    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
    	if (el_hist == NULL || el == NULL)
    		ast_el_initialize();
    
    	el_set(el, EL_GETCFN, ast_el_read_char);
    
    
    	if (!ast_strlen_zero(filename))
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_el_read_history(filename);
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_cli_register(&quit);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_cli_register(&astexit);
    
    Mark Spencer's avatar
    Mark Spencer committed
    #if 0
    	ast_cli_register(&astshutdown);
    #endif	
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (option_exec && data) {  /* hack to print output then exit if asterisk -rx is used */
    		char tempchar;
    
    		struct pollfd fds[0];
    		fds[0].fd = ast_consock;
    		fds[0].events = POLLIN;
    		fds[0].revents = 0;
    		while(poll(fds, 1, 100) > 0) {
    			ast_el_read_char(el, &tempchar);
    		}
    
    Mark Spencer's avatar
    Mark Spencer committed
    		return;
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	for(;;) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ebuf = (char *)el_gets(el, &num);
    
    
    		if (ebuf && !ast_strlen_zero(ebuf)) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    			if (ebuf[strlen(ebuf)-1] == '\n')
    				ebuf[strlen(ebuf)-1] = '\0';
    			if (!remoteconsolehandler(ebuf)) {
    				res = write(ast_consock, ebuf, strlen(ebuf) + 1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    				if (res < 1) {
    					ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
    					break;
    				}
    			}
    		}
    	}
    	printf("\nDisconnected from Asterisk server\n");
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    static int show_version(void)
    {
    	printf("Asterisk " ASTERISK_VERSION "\n");
    	return 0;
    }
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    static int show_cli_help(void) {
    
    	printf("Asterisk " ASTERISK_VERSION ", Copyright (C) 2000 - 2005, Digium.\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	printf("Usage: asterisk [OPTIONS]\n");
    	printf("Valid Options:\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	printf("   -V              Display version number and exit\n");
    
    	printf("   -C <configfile> Use an alternate configuration file\n");
    
    	printf("   -G <group>      Run as a group other than the caller\n");
    	printf("   -U <user>       Run as a user other than the caller\n");
    
    	printf("   -c              Provide console CLI\n");
    	printf("   -d              Enable extra debugging\n");
    	printf("   -f              Do not fork\n");
    	printf("   -g              Dump core in case of a crash\n");
    	printf("   -h              This help screen\n");
    
    	printf("   -i              Initialize crypto keys at startup\n");
    
    	printf("   -n              Disable console colorization\n");
    	printf("   -p              Run as pseudo-realtime thread\n");
    
    	printf("   -q              Quiet mode (suppress output)\n");
    
    	printf("   -r              Connect to Asterisk on this machine\n");
    
    	printf("   -R              Connect to Asterisk, and attempt to reconnect if disconnected\n");
    
    	printf("   -t              Record soundfiles in /var/tmp and move them where they belong after they are done.\n");
    
    	printf("   -T              Display the time in [Mmm dd hh:mm:ss] format for each line of output to the CLI.\n");
    
    	printf("   -v              Increase verbosity (multiple v's = more verbose)\n");
    	printf("   -x <cmd>        Execute command <cmd> (only valid with -r)\n");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	printf("\n");
    	return 0;
    }
    
    
    static void ast_readconfig(void) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	struct ast_config *cfg;
    	struct ast_variable *v;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	struct ast_variable *v_ctlfile;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char *config = ASTCONFPATH;
    
    	if (option_overrideconfig == 1) {
    
    		cfg = ast_config_load((char *)ast_config_AST_CONFIG_FILE);
    
    		if (!cfg)
    			ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using builtin defaults\n", ast_config_AST_CONFIG_FILE);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	} else {
    
    		cfg = ast_config_load(config);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    	/* init with buildtime config */
    	strncpy((char *)ast_config_AST_CONFIG_DIR,AST_CONFIG_DIR,sizeof(ast_config_AST_CONFIG_DIR)-1);
    	strncpy((char *)ast_config_AST_SPOOL_DIR,AST_SPOOL_DIR,sizeof(ast_config_AST_SPOOL_DIR)-1);
    	strncpy((char *)ast_config_AST_MODULE_DIR,AST_MODULE_DIR,sizeof(ast_config_AST_VAR_DIR)-1);
    	strncpy((char *)ast_config_AST_VAR_DIR,AST_VAR_DIR,sizeof(ast_config_AST_VAR_DIR)-1);
    	strncpy((char *)ast_config_AST_LOG_DIR,AST_LOG_DIR,sizeof(ast_config_AST_LOG_DIR)-1);
    	strncpy((char *)ast_config_AST_AGI_DIR,AST_AGI_DIR,sizeof(ast_config_AST_AGI_DIR)-1);
    	strncpy((char *)ast_config_AST_DB,AST_DB,sizeof(ast_config_AST_DB)-1);
    	strncpy((char *)ast_config_AST_KEY_DIR,AST_KEY_DIR,sizeof(ast_config_AST_KEY_DIR)-1);
    	strncpy((char *)ast_config_AST_PID,AST_PID,sizeof(ast_config_AST_PID)-1);
    	strncpy((char *)ast_config_AST_SOCKET,AST_SOCKET,sizeof(ast_config_AST_SOCKET)-1);
    	strncpy((char *)ast_config_AST_RUN_DIR,AST_RUN_DIR,sizeof(ast_config_AST_RUN_DIR)-1);
    	
    	/* no asterisk.conf? no problem, use buildtime config! */
    	if (!cfg) {
    
    James Golovich's avatar
    James Golovich committed
    		return;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	v_ctlfile = ast_variable_browse(cfg, "files");
    	while (v_ctlfile!=NULL) {
    		if (strcmp(v_ctlfile->name,"astctl")==0)
    			break;
    		v_ctlfile=v_ctlfile->next;
    	}
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    	v = ast_variable_browse(cfg, "directories");
    	while(v) {
    		if (!strcasecmp(v->name, "astetcdir")) {
    
    James Golovich's avatar
    James Golovich committed
    			strncpy((char *)ast_config_AST_CONFIG_DIR,v->value,sizeof(ast_config_AST_CONFIG_DIR)-1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		} else if (!strcasecmp(v->name, "astspooldir")) {
    
    James Golovich's avatar
    James Golovich committed
    			strncpy((char *)ast_config_AST_SPOOL_DIR,v->value,sizeof(ast_config_AST_SPOOL_DIR)-1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		} else if (!strcasecmp(v->name, "astvarlibdir")) {
    
    James Golovich's avatar
    James Golovich committed
    			strncpy((char *)ast_config_AST_VAR_DIR,v->value,sizeof(ast_config_AST_VAR_DIR)-1);
    			snprintf((char *)ast_config_AST_DB,sizeof(ast_config_AST_DB),"%s/%s",v->value,"astdb");    
    
    Mark Spencer's avatar
    Mark Spencer committed
    		} else if (!strcasecmp(v->name, "astlogdir")) {
    
    James Golovich's avatar
    James Golovich committed
    			strncpy((char *)ast_config_AST_LOG_DIR,v->value,sizeof(ast_config_AST_LOG_DIR)-1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		} else if (!strcasecmp(v->name, "astagidir")) {
    
    James Golovich's avatar
    James Golovich committed
    			strncpy((char *)ast_config_AST_AGI_DIR,v->value,sizeof(ast_config_AST_AGI_DIR)-1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		} else if (!strcasecmp(v->name, "astrundir")) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    			snprintf((char *)ast_config_AST_PID,sizeof(ast_config_AST_PID),"%s/%s",v->value,"asterisk.pid");
    			snprintf((char *)ast_config_AST_SOCKET,sizeof(ast_config_AST_SOCKET),"%s/%s",v->value,v_ctlfile==NULL?"asterisk.ctl":v_ctlfile->value);
    
    James Golovich's avatar
    James Golovich committed
    			strncpy((char *)ast_config_AST_RUN_DIR,v->value,sizeof(ast_config_AST_RUN_DIR)-1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		} else if (!strcasecmp(v->name, "astmoddir")) {
    
    James Golovich's avatar
    James Golovich committed
    			strncpy((char *)ast_config_AST_MODULE_DIR,v->value,sizeof(ast_config_AST_MODULE_DIR)-1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		}
    		v = v->next;
    	}
    
    	v = ast_variable_browse(cfg, "options");
    	while(v) {
    
    		/* verbose level (-v at startup) */
    
    		if (!strcasecmp(v->name, "verbose")) {
    
    			option_verbose= atoi(v->value);
    
    		/* whether or not to force timestamping. (-T at startup) */
    		} else if (!strcasecmp(v->name, "timestamp")) {
    			option_timestamp = ast_true(v->value);
    
    		/* whether or not to support #exec in config files */
    
    		} else if (!strcasecmp(v->name, "execincludes")) {
    			option_exec_includes = ast_true(v->value);
    
    Mark Spencer's avatar
    Mark Spencer committed
    		/* debug level (-d at startup) */
    
    		} else if (!strcasecmp(v->name, "debug")) {
    
    			option_debug = 0;
    			if (sscanf(v->value, "%d", &option_debug) != 1) {
    				option_debug = ast_true(v->value);
    			}
    		/* Disable forking (-f at startup) */
    
    		} else if (!strcasecmp(v->name, "nofork")) {
    
    James Golovich's avatar
    James Golovich committed
    			option_nofork = ast_true(v->value);
    
    		/* Run quietly (-q at startup ) */
    
    		} else if (!strcasecmp(v->name, "quiet")) {
    
    James Golovich's avatar
    James Golovich committed
    			option_quiet = ast_true(v->value);
    
    		/* Run as console (-c at startup, implies nofork) */
    
    		} else if (!strcasecmp(v->name, "console")) {
    
    James Golovich's avatar
    James Golovich committed
    			option_console = ast_true(v->value);
    
    		/* Run with highg priority if the O/S permits (-p at startup) */
    
    		} else if (!strcasecmp(v->name, "highpriority")) {
    
    James Golovich's avatar
    James Golovich committed
    			option_highpriority = ast_true(v->value);
    
    		/* Initialize RSA auth keys (IAX2) (-i at startup) */
    
    		} else if (!strcasecmp(v->name, "initcrypto")) {
    
    James Golovich's avatar
    James Golovich committed
    			option_initcrypto = ast_true(v->value);
    
    		/* Disable ANSI colors for console (-c at startup) */
    
    		} else if (!strcasecmp(v->name, "nocolor")) {
    
    James Golovich's avatar
    James Golovich committed
    			option_nocolor = ast_true(v->value);
    
    		/* Dump core in case of crash (-g) */
    
    		} else if (!strcasecmp(v->name, "dumpcore")) {
    
    James Golovich's avatar
    James Golovich committed
    			option_dumpcore = ast_true(v->value);
    
    		/* Cache recorded sound files to another directory during recording */
    
    		} else if (!strcasecmp(v->name, "cache_record_files")) {
    
    James Golovich's avatar
    James Golovich committed
    			option_cache_record_files = ast_true(v->value);
    
    		/* Specify cache directory */
    
    		}  else if (!strcasecmp(v->name, "record_cache_dir")) {
    			strncpy(record_cache_dir,v->value,AST_CACHE_DIR_LEN);
    
    		/* Build transcode paths via SLINEAR, instead of directly */
    		} else if (!strcasecmp(v->name, "transcode_via_sln")) {
    			option_transcode_slin = ast_true(v->value);
    
    	ast_config_destroy(cfg);
    
    Mark Spencer's avatar
    Mark Spencer committed
    int main(int argc, char *argv[])
    {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char filename[80] = "";
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char hostname[256];
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char tmp[80];
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char * xarg = NULL;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	int x;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	FILE *f;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	sigset_t sigs;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	int num;
    	char *buf;
    
    	char *runuser=NULL, *rungroup=NULL;
    
    	struct pollfd silly_macos[1];	
    
    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) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (gethostname(hostname, sizeof(hostname)))
    
    Mark Spencer's avatar
    Mark Spencer committed
    		strncpy(hostname, "<Unknown>", sizeof(hostname)-1);
    
    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();
    
    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:")) != -1) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		switch(c) {
    		case 'd':
    			option_debug++;
    			option_nofork++;
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'c':
    			option_console++;
    			option_nofork++;
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'f':
    			option_nofork++;
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'n':
    			option_nocolor++;
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'r':
    			option_remote++;
    			option_nofork++;
    			break;
    
    		case 'R':
    			option_remote++;
    			option_nofork++;
    			option_reconnect++;
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'p':
    			option_highpriority++;
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    		case 'v':
    			option_verbose++;
    
    Mark Spencer's avatar
    Mark Spencer committed
    			option_nofork++;
    
    Mark Spencer's avatar
    Mark Spencer committed
    			break;
    		case 'q':
    			option_quiet++;
    			break;
    
    		case 't':
    			option_cache_record_files++;
    			break;
    
    		case 'T':
    			option_timestamp++;
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'x':
    			option_exec++;
    			xarg = optarg;
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'C':
    
    			strncpy((char *)ast_config_AST_CONFIG_FILE,optarg,sizeof(ast_config_AST_CONFIG_FILE) - 1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    			option_overrideconfig++;
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case 'i':
    			option_initcrypto++;
    			break;
    
    Mark Spencer's avatar
    Mark Spencer committed
    		case'g':
    			option_dumpcore++;
    			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);
    		}
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (option_dumpcore) {
    		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));
    		}
    	}
    
    
    	if (option_console && !option_verbose) 
    		ast_verbose("[ Reading Master Configuration ]");
    	ast_readconfig();
    
    	if (set_priority(option_highpriority)) {
    		exit(1);
    	}
    
    
    	if (rungroup) {
    		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);
    		}
    		if (option_verbose)
    			ast_verbose("Running as group '%s'\n", rungroup);
    	}
    
    	if (runuser) {
    		struct passwd *pw;
    		pw = getpwnam(runuser);
    		if (!pw) {
    			ast_log(LOG_WARNING, "No such user '%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);
    		}
    		if (option_verbose)
    			ast_verbose("Running as user '%s'\n", runuser);
    	}
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    	term_init();
    	printf(term_end());
    	fflush(stdout);
    
    	if (option_console && !option_verbose) 
    
    		ast_verbose("[ Initializing Custom Configuration Options ]");
    
    	/* custom config setup */
    	register_config_cli();
    
    	read_config_maps();
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (option_console) {
    
    		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 */
    		if (option_remote) {
    			if (option_exec) {
    				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 {
    
    Mark Spencer's avatar
    Mark Spencer committed
    			ast_log(LOG_ERROR, "Asterisk already running on %s.  Use 'asterisk -r' to connect.\n", (char *)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 (option_remote || option_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 */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	unlink((char *)ast_config_AST_PID);
    	f = fopen((char *)ast_config_AST_PID, "w");
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (f) {
    		fprintf(f, "%d\n", getpid());
    		fclose(f);
    	} else
    
    Mark Spencer's avatar
    Mark Spencer committed
    		ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", (char *)ast_config_AST_PID, strerror(errno));
    
    Mark Spencer's avatar
    Mark Spencer committed
    
    	if (!option_verbose && !option_debug && !option_nofork && !option_console) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		daemon(0,0);
    
    		/* Blindly re-write pid file since we are forking */
    		unlink((char *)ast_config_AST_PID);
    		f = fopen((char *)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", (char *)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 (option_console || option_verbose || option_remote)
    		ast_register_verbose(console_verboser);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	/* Print a welcome message if desired */
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (option_verbose || option_console) {
    
    Mark Spencer's avatar
    Mark Spencer committed
    		WELCOME_MESSAGE;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	}
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (option_console && !option_verbose) 
    		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));
    	srandom((unsigned int) getpid() + (unsigned int) time(NULL));
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (init_logger()) {
    		printf(term_quit());
    
    Mark Spencer's avatar
    Mark Spencer committed
    		exit(1);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	if (init_manager()) {
    		printf(term_quit());
    		exit(1);
    	}
    
    	ast_rtp_init();
    
    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
    	}
    	if (load_modules()) {
    		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);
    	}
    
    	if (dnsmgr_init()) {
    		printf(term_quit());
    		exit(1);
    	}
    
    #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
    	if (option_console && !option_verbose)
    		ast_verbose(" ]\n");
    	if (option_verbose || option_console)
    
    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
    	if (option_nofork)
    		consolethread = pthread_self();
    
    Mark Spencer's avatar
    Mark Spencer committed
    	fully_booted = 1;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	time(&ast_startuptime);
    
    Mark Spencer's avatar
    Mark Spencer committed
    	ast_cli_register(&astshutdownnow);
    	ast_cli_register(&astshutdowngracefully);