Пример #1
0
static int exec_exec(struct ast_channel *chan, void *data)
{
	int res=0;
	struct ast_module_user *u;
	char *s, *appname, *endargs, args[MAXRESULT] = "";
	struct ast_app *app;

	u = ast_module_user_add(chan);

	/* Check and parse arguments */
	if (data) {
		s = ast_strdupa(data);
		appname = strsep(&s, "(");
		if (s) {
			endargs = strrchr(s, ')');
			if (endargs)
				*endargs = '\0';
			pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
		}
		if (appname) {
			app = pbx_findapp(appname);
			if (app) {
				res = pbx_exec(chan, app, args);
			} else {
				ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
				res = -1;
			}
		}
	}

	ast_module_user_remove(u);
	return res;
}
Пример #2
0
static int echo_exec(struct ast_channel *chan, void *data)
{
	int res = -1;
	int format;
	struct ast_module_user *u;

	u = ast_module_user_add(chan);

	format = ast_best_codec(chan->nativeformats);
	ast_set_write_format(chan, format);
	ast_set_read_format(chan, format);

	while (ast_waitfor(chan, -1) > -1) {
		struct ast_frame *f = ast_read(chan);
		if (!f)
			break;
		f->delivery.tv_sec = 0;
		f->delivery.tv_usec = 0;
		if (ast_write(chan, f)) {
			ast_frfree(f);
			goto end;
		}
		if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
			res = 0;
			ast_frfree(f);
			goto end;
		}
		ast_frfree(f);
	}
end:
	ast_module_user_remove(u);
	return res;
}
Пример #3
0
/*! \brief SpeechCreate() Dialplan Application */
static int speech_create(struct ast_channel *chan, void *data)
{
	struct ast_module_user *u = NULL;
	struct ast_speech *speech = NULL;
	struct ast_datastore *datastore = NULL;

	u = ast_module_user_add(chan);

	/* Request a speech object */
	speech = ast_speech_new(data, AST_FORMAT_SLINEAR);
	if (speech == NULL) {
		/* Not available */
		pbx_builtin_setvar_helper(chan, "ERROR", "1");
		ast_module_user_remove(u);
		return 0;
	}

	datastore = ast_channel_datastore_alloc(&speech_datastore, NULL);
	if (datastore == NULL) {
		ast_speech_destroy(speech);
		pbx_builtin_setvar_helper(chan, "ERROR", "1");
		ast_module_user_remove(u);
		return 0;
	}
	datastore->data = speech;
	ast_channel_datastore_add(chan, datastore);

	pbx_builtin_setvar_helper(chan, "ERROR", NULL);

	ast_module_user_remove(u);

	return 0;
}
Пример #4
0
/* Main application entry point */
static int pickup_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct ast_module_user *u = NULL;
	char *tmp = ast_strdupa(data);
	char *exten = NULL, *context = NULL;

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "Pickup requires an argument (extension)!\n");
		return -1;	
	}

	u = ast_module_user_add(chan);
	
	/* Parse extension (and context if there) */
	while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
		if ((context = strchr(exten, '@')))
			*context++ = '\0';
		if (context && !strcasecmp(context, PICKUPMARK)) {
			if (!pickup_by_mark(chan, exten))
				break;
		} else {
			if (!pickup_by_exten(chan, exten, context ? context : chan->context))
				break;
		}
		ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten);
	}

	ast_module_user_remove(u);

	return res;
}
Пример #5
0
/*! \brief SpeechLoadGrammar(Grammar Name|Path) Dialplan Application */
static int speech_load(struct ast_channel *chan, void *data)
{
	int res = 0, argc = 0;
	struct ast_module_user *u = NULL;
	struct ast_speech *speech = find_speech(chan);
	char *argv[2], *args = NULL, *name = NULL, *path = NULL;

	args = ast_strdupa(data);

	u = ast_module_user_add(chan);

	if (speech == NULL) {
		ast_module_user_remove(u);
                return -1;
        }

	/* Parse out arguments */
	argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0]));
	if (argc != 2) {
		ast_module_user_remove(u);
		return -1;
	}
	name = argv[0];
	path = argv[1];

        /* Load the grammar locally on the object */
        res = ast_speech_grammar_load(speech, name, path);

        ast_module_user_remove(u);

        return res;
}
Пример #6
0
/*! \brief SpeechDestroy() Dialplan Application */
static int speech_destroy(struct ast_channel *chan, void *data)
{
	int res = 0;
        struct ast_module_user *u = NULL;
	struct ast_speech *speech = find_speech(chan);
	struct ast_datastore *datastore = NULL;

	u = ast_module_user_add(chan);

	if (speech == NULL) {
		ast_module_user_remove(u);
		return -1;
	}

	/* Destroy speech structure */
	ast_speech_destroy(speech);

	datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL);
	if (datastore != NULL) {
		ast_channel_datastore_remove(chan, datastore);
	}

	ast_module_user_remove(u);

	return res;
}
Пример #7
0
static int steal_channel(struct ast_channel *chan, void *pattern)
{
	int ret = 0;
	struct ast_module_user *u;
	struct ast_channel *cur;
	u = ast_module_user_add(chan);
	cur = find_matching_channel(chan, pattern, AST_STATE_UP);
	if (cur) {
		ast_verbose(VERBOSE_PREFIX_3 
			"Channel %s stole channel %s\n",
			chan->name, cur->name);
		pbx_builtin_setvar_helper(chan, "STEAL_CHANNEL", cur->name);
		if (chan->_state != AST_STATE_UP) {
			ast_answer(chan);
		}
		if (cur->_bridge) {
			if (!ast_mutex_lock(&cur->_bridge->lock)) {
				ast_moh_stop(cur->_bridge);
				ast_mutex_unlock(&cur->_bridge->lock);
			}
		}
			
		if (ast_channel_masquerade(cur, chan)) {
			ast_log(LOG_ERROR, "unable to masquerade\n");
			ret = -1;
		}
		ast_mutex_unlock(&cur->lock);
		ast_mutex_unlock(&chan->lock);
	} else {
		pbx_builtin_setvar_helper(chan, "STEAL_CHANNEL", "");
	}
	ast_module_user_remove(u);
	return(ret);
}
Пример #8
0
static int senddtmf_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct ast_module_user *u;
	char *digits = NULL, *to = NULL;
	int timeout = 250;

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "SendDTMF requires an argument (digits or *#aAbBcCdD)\n");
		return 0;
	}

	u = ast_module_user_add(chan);

	digits = ast_strdupa(data);

	if ((to = strchr(digits,'|'))) {
		*to = '\0';
		to++;
		timeout = atoi(to);
	}
		
	if (timeout <= 0)
		timeout = 250;

	res = ast_dtmf_stream(chan,NULL,digits,timeout);
		
	ast_module_user_remove(u);

	return res;
}
Пример #9
0
static int morsecode_exec(struct ast_channel *chan, void *data)
{
	int res=0, ditlen, tone;
	char *digit;
	const char *ditlenc, *tonec;
	struct ast_module_user *u;

	u = ast_module_user_add(chan);

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "Syntax: Morsecode(<string>) - no argument found\n");
		ast_module_user_remove(u);
		return 0;
	}

	/* Use variable MORESEDITLEN, if set (else 80) */
	ditlenc = pbx_builtin_getvar_helper(chan, "MORSEDITLEN");
	if (ast_strlen_zero(ditlenc) || (sscanf(ditlenc, "%30d", &ditlen) != 1)) {
		ditlen = 80;
	}

	/* Use variable MORSETONE, if set (else 800) */
	tonec = pbx_builtin_getvar_helper(chan, "MORSETONE");
	if (ast_strlen_zero(tonec) || (sscanf(tonec, "%30d", &tone) != 1)) {
		tone = 800;
	}

	for (digit = data; *digit; digit++) {
		int digit2 = *digit;
		char *dahdit;
		if (digit2 < 0) {
			continue;
		}
		for (dahdit = morsecode[digit2]; *dahdit; dahdit++) {
			if (*dahdit == '-') {
				playtone(chan, tone, 3 * ditlen);
			} else if (*dahdit == '.') {
				playtone(chan, tone, 1 * ditlen);
			} else {
				/* Account for ditlen of silence immediately following */
				playtone(chan, 0, 2 * ditlen);
			}

			/* Pause slightly between each dit and dah */
			playtone(chan, 0, 1 * ditlen);
		}
		/* Pause between characters */
		playtone(chan, 0, 2 * ditlen);
	}

	ast_module_user_remove(u);
	return res;
}
Пример #10
0
static int app_vonferencecount_main(struct ast_channel* chan, const char* data)
{
	int res ;
	struct ast_module_user *u ;

	u = ast_module_user_add(chan);

	// call count thread function
	res = count_exec( chan, data ) ;

	ast_module_user_remove(u);

	return res ;
}
Пример #11
0
static int app_konferencecount_main(struct ast_channel* chan, ast_application_parameter data)
{
	int res ;
	struct ast_module_user *u ;

	u = ast_module_user_add(chan);

	// call count thread function
	res = count_exec(chan, (const char *) data);

	ast_module_user_remove(u);

	return res ;
}
Пример #12
0
static int app_conference_main(struct ast_channel* chan, void* data)
{
	int res ;
	struct ast_module_user *u ;

	u = ast_module_user_add(chan);

	// call member thread function
	res = member_exec( chan, data ) ;

	ast_module_user_remove(u);

	return res ;
}
Пример #13
0
static int exec(struct ast_channel *chan, void *data, int dahdimode)
{
	int res=-1;
	struct ast_module_user *u;
	int retrycnt = 0;
	int confflags = 0;
	int confno = 0;
	char confstr[80] = "";

	u = ast_module_user_add(chan);
	
	if (!ast_strlen_zero(data)) {
		if (dahdimode) {
			if ((sscanf(data, "DAHDI/%30d", &confno) != 1) &&
			    (sscanf(data, "%30d", &confno) != 1)) {
				ast_log(LOG_WARNING, "Argument (if specified) must be a channel number, not '%s'\n", (char *) data);
				ast_module_user_remove(u);
				return 0;
			}
		} else {
			if ((sscanf(data, "Zap/%30d", &confno) != 1) &&
			    (sscanf(data, "%30d", &confno) != 1)) {
				ast_log(LOG_WARNING, "Argument (if specified) must be a channel number, not '%s'\n", (char *) data);
				ast_module_user_remove(u);
				return 0;
			}
		}
	}
	
	if (chan->_state != AST_STATE_UP)
		ast_answer(chan);

	while(!confno && (++retrycnt < 4)) {
		/* Prompt user for conference number */
		confstr[0] = '\0';
		res = ast_app_getdata(chan, "conf-getchannel",confstr, sizeof(confstr) - 1, 0);
		if (res <0) goto out;
		if (sscanf(confstr, "%30d", &confno) != 1)
			confno = 0;
	}
	if (confno) {
		/* XXX Should prompt user for pin if pin is required XXX */
		/* Run the conference */
		res = conf_run(chan, confno, confflags);
	}
out:
	/* Do the conference */
	ast_module_user_remove(u);
	return res;
}
Пример #14
0
static int
lookupblacklist_exec (struct ast_channel *chan, void *data)
{
	char blacklist[1];
	struct ast_module_user *u;
	int bl = 0;
	int priority_jump = 0;
	static int dep_warning = 0;

	u = ast_module_user_add(chan);

	if (!dep_warning) {
		dep_warning = 1;
		ast_log(LOG_WARNING, "LookupBlacklist is deprecated.  Please use ${BLACKLIST()} instead.\n");
	}

	if (!ast_strlen_zero(data)) {
		if (strchr(data, 'j'))
			priority_jump = 1;
	}

	if (chan->cid.cid_num) {
		if (!ast_db_get("blacklist", chan->cid.cid_num, blacklist, sizeof (blacklist))) {
			if (option_verbose > 2)
				ast_log(LOG_NOTICE, "Blacklisted number %s found\n",chan->cid.cid_num);
			bl = 1;
		}
	}
	if (chan->cid.cid_name) {
		if (!ast_db_get("blacklist", chan->cid.cid_name, blacklist, sizeof (blacklist))) {
			if (option_verbose > 2)
				ast_log (LOG_NOTICE,"Blacklisted name \"%s\" found\n",chan->cid.cid_name);
			bl = 1;
		}
	}

	if (bl) {
		if (priority_jump || ast_opt_priority_jumping) 
			ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
		pbx_builtin_setvar_helper(chan, "LOOKUPBLSTATUS", "FOUND");
	} else
		pbx_builtin_setvar_helper(chan, "LOOKUPBLSTATUS", "NOTFOUND");	

	ast_module_user_remove(u);

	return 0;
}
Пример #15
0
static int readfile_exec(struct ast_channel *chan, void *data)
{
	int res=0;
	struct ast_module_user *u;
	char *s, *varname=NULL, *file=NULL, *length=NULL, *returnvar=NULL;
	int len=0;

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "ReadFile require an argument!\n");
		return -1;
	}

	u = ast_module_user_add(chan);

	s = ast_strdupa(data);

	varname = strsep(&s, "=");
	file = strsep(&s, "|");
	length = s;

	if (!varname || !file) {
		ast_log(LOG_ERROR, "No file or variable specified!\n");
		ast_module_user_remove(u);
		return -1;
	}

	if (length) {
		if ((sscanf(length, "%30d", &len) != 1) || (len < 0)) {
			ast_log(LOG_WARNING, "%s is not a positive number, defaulting length to max\n", length);
			len = 0;
		}
	}

	if ((returnvar = ast_read_textfile(file))) {
		if (len > 0) {
			if (len < strlen(returnvar))
				returnvar[len]='\0';
			else
				ast_log(LOG_WARNING, "%s is longer than %d, and %d \n", file, len, (int)strlen(returnvar));
		}
		pbx_builtin_setvar_helper(chan, varname, returnvar);
		free(returnvar);
	}
	ast_module_user_remove(u);
	return res;
}
Пример #16
0
static int verbose_exec(struct ast_channel *chan, void *data)
{
	char *vtext;
	int vsize;
	struct ast_module_user *u;

	u = ast_module_user_add(chan);

	if (data) {
		char *tmp;
		vtext = ast_strdupa(data);
		tmp = strsep(&vtext, "|");
		if (vtext) {
			if (sscanf(tmp, "%30d", &vsize) != 1) {
				vsize = 0;
				ast_log(LOG_WARNING, "'%s' is not a verboser number\n", vtext);
			}
		} else {
			vtext = tmp;
			vsize = 0;
		}
		if (option_verbose >= vsize) {
			switch (vsize) {
			case 0:
				ast_verbose("%s\n", vtext);
				break;
			case 1:
				ast_verbose(VERBOSE_PREFIX_1 "%s\n", vtext);
				break;
			case 2:
				ast_verbose(VERBOSE_PREFIX_2 "%s\n", vtext);
				break;
			case 3:
				ast_verbose(VERBOSE_PREFIX_3 "%s\n", vtext);
				break;
			default:
				ast_verbose(VERBOSE_PREFIX_4 "%s\n", vtext);
			}
		}
	}

	ast_module_user_remove(u);

	return 0;
}
Пример #17
0
static int log_exec(struct ast_channel *chan, void *data)
{
	char *level, *ltext;
	struct ast_module_user *u;
	int lnum = -1;
	char extension[AST_MAX_EXTENSION + 5], context[AST_MAX_EXTENSION + 2];

	u = ast_module_user_add(chan);
	if (ast_strlen_zero(data)) {
		ast_module_user_remove(u);
		return 0;
	}

	ltext = ast_strdupa(data);

	level = strsep(&ltext, "|");

	if (!strcasecmp(level, "ERROR")) {
		lnum = __LOG_ERROR;
	} else if (!strcasecmp(level, "WARNING")) {
		lnum = __LOG_WARNING;
	} else if (!strcasecmp(level, "NOTICE")) {
		lnum = __LOG_NOTICE;
	} else if (!strcasecmp(level, "DEBUG")) {
		lnum = __LOG_DEBUG;
	} else if (!strcasecmp(level, "VERBOSE")) {
		lnum = __LOG_VERBOSE;
	} else if (!strcasecmp(level, "DTMF")) {
		lnum = __LOG_DTMF;
	} else if (!strcasecmp(level, "EVENT")) {
		lnum = __LOG_EVENT;
	} else {
		ast_log(LOG_ERROR, "Unknown log level: '%s'\n", level);
	}

	if (lnum > -1) {
		snprintf(context, sizeof(context), "@ %s", chan->context);
		snprintf(extension, sizeof(extension), "Ext. %s", chan->exten);

		ast_log(lnum, extension, chan->priority, context, "%s\n", ltext);
	}
	ast_module_user_remove(u);
	return 0;
}
Пример #18
0
/*! \brief SpeechStart() Dialplan Application */
static int speech_start(struct ast_channel *chan, void *data)
{
	int res = 0;
        struct ast_module_user *u = NULL;
	struct ast_speech *speech = find_speech(chan);

	u = ast_module_user_add(chan);

	if (speech == NULL) {
		ast_module_user_remove(u);
		return -1;
	}

	ast_speech_start(speech);

	ast_module_user_remove(u);

	return res;
}
Пример #19
0
static int pickdown_channel(struct ast_channel *chan, void *pattern)
{
	int ret = 0;
	struct ast_module_user *u;
	struct ast_channel *cur;
	u = ast_module_user_add(chan);
	cur = find_matching_channel(chan, pattern, AST_STATE_RINGING);
	if (cur) {
                ast_verbose(VERBOSE_PREFIX_3 
			"Channel %s hung up ringing channel %s\n",
			chan->name, cur->name);
		pbx_builtin_setvar_helper(chan, "PICKDOWN_CHANNEL", cur->name);
		ast_softhangup_nolock(cur, AST_SOFTHANGUP_DEV);
		ast_mutex_unlock(&cur->lock);
	} else {
		pbx_builtin_setvar_helper(chan, "PICKDOWN_CHANNEL", "");
	}
	ast_module_user_remove(u);
	return(ret);
}
Пример #20
0
/*! \brief SpeechActivateGrammar(Grammar Name) Dialplan Application */
static int speech_activate(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct ast_module_user *u = NULL;
	struct ast_speech *speech = find_speech(chan);

	u = ast_module_user_add(chan);

	if (speech == NULL) {
		ast_module_user_remove(u);
		return -1;
	}

	/* Activate the grammar on the speech object */
	res = ast_speech_grammar_activate(speech, data);

	ast_module_user_remove(u);

	return res;
}
Пример #21
0
/*! \brief SpeechUnloadGrammar(Grammar Name) Dialplan Application */
static int speech_unload(struct ast_channel *chan, void *data)
{
        int res = 0;
        struct ast_module_user *u = NULL;
        struct ast_speech *speech = find_speech(chan);

        u = ast_module_user_add(chan);

        if (speech == NULL) {
                ast_module_user_remove(u);
                return -1;
        }

        /* Unload the grammar */
        res = ast_speech_grammar_unload(speech, data);

        ast_module_user_remove(u);

        return res;
}
Пример #22
0
static int system_exec_helper(struct ast_channel *chan, void *data, int failmode)
{
	int res=0;
	struct ast_module_user *u;
	
	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "System requires an argument(command)\n");
		pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
		return failmode;
	}

	u = ast_module_user_add(chan);

	/* Do our thing here */
	res = ast_safe_system((char *)data);
	if ((res < 0) && (errno != ECHILD)) {
		ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
		pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
		res = failmode;
	} else if (res == 127) {
		ast_log(LOG_WARNING, "Unable to execute '%s'\n", (char *)data);
		pbx_builtin_setvar_helper(chan, chanvar, "FAILURE");
		res = failmode;
	} else {
		if (res < 0) 
			res = 0;
		if (ast_opt_priority_jumping && res)
			ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);

		if (res != 0)
			pbx_builtin_setvar_helper(chan, chanvar, "APPERROR");
		else
			pbx_builtin_setvar_helper(chan, chanvar, "SUCCESS");
		res = 0;
	} 

	ast_module_user_remove(u);

	return res;
}
Пример #23
0
static int deltree_exec(struct ast_channel *chan, void *data)
{
	char *argv, *family, *keytree;
	struct ast_module_user *u;

	u = ast_module_user_add(chan);

	argv = ast_strdupa(data);

	if (strchr(argv, '/')) {
		family = strsep(&argv, "/");
		keytree = strsep(&argv, "\0");
			if (!family || !keytree) {
				ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
				ast_module_user_remove(u);
				return 0;
			}
		if (ast_strlen_zero(keytree))
			keytree = 0;
	} else {
		family = argv;
		keytree = 0;
	}

	if (option_verbose > 2)	{
		if (keytree)
			ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: family=%s, keytree=%s\n", family, keytree);
		else
			ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: family=%s\n", family);
	}

	if (ast_db_deltree(family, keytree)) {
		if (option_verbose > 2)
			ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: Error deleting key from database.\n");
	}

	ast_module_user_remove(u);

	return 0;
}
Пример #24
0
static int execif_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct ast_module_user *u;
	char *myapp = NULL;
	char *mydata = NULL;
	char *expr = NULL;
	struct ast_app *app = NULL;

	u = ast_module_user_add(chan);

	expr = ast_strdupa(data);

	if ((myapp = strchr(expr,'|'))) {
		*myapp = '\0';
		myapp++;
		if ((mydata = strchr(myapp,'|'))) {
			*mydata = '\0';
			mydata++;
		} else
			mydata = "";

		if (pbx_checkcondition(expr)) { 
			if ((app = pbx_findapp(myapp))) {
				res = pbx_exec(chan, app, mydata);
			} else {
				ast_log(LOG_WARNING, "Could not find application! (%s)\n", myapp);
				res = -1;
			}
		}
	} else {
		ast_log(LOG_ERROR,"Invalid Syntax.\n");
		res = -1;
	}
		
	ast_module_user_remove(u);

	return res;
}
Пример #25
0
static int matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
{
	int res;
	lua_State *L;
	struct ast_module_user *u = ast_module_user_add(chan);
	if (!u) {
		ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
		return 0;
	}

	L = lua_get_state(chan);
	if (!L) {
		ast_module_user_remove(u);
		return 0;
	}
	
	res = lua_find_extension(L, context, exten, priority, &matchmore, 0);

	if (!chan) lua_close(L);
	ast_module_user_remove(u);
	return res;
}
Пример #26
0
static int del_exec(struct ast_channel *chan, void *data)
{
	char *argv, *family, *key;
	struct ast_module_user *u;
	static int deprecation_warning = 0;

	u = ast_module_user_add(chan);

	if (!deprecation_warning) {
		deprecation_warning = 1;
		ast_log(LOG_WARNING, "The DBdel application has been deprecated in favor of the DB_DELETE dialplan function!\n");
	}

	argv = ast_strdupa(data);

	if (strchr(argv, '/')) {
		family = strsep(&argv, "/");
		key = strsep(&argv, "\0");
		if (!family || !key) {
			ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
			ast_module_user_remove(u);
			return 0;
		}
		if (option_verbose > 2)
			ast_verbose(VERBOSE_PREFIX_3 "DBdel: family=%s, key=%s\n", family, key);
		if (ast_db_del(family, key)) {
			if (option_verbose > 2)
				ast_verbose(VERBOSE_PREFIX_3 "DBdel: Error deleting key from database.\n");
		}
	} else {
		ast_log(LOG_DEBUG, "Ignoring, no parameters\n");
	}

	ast_module_user_remove(u);
	
	return 0;
}
Пример #27
0
/*! \brief SpeechProcessingSound(Sound File) Dialplan Application */
static int speech_processing_sound(struct ast_channel *chan, void *data)
{
        int res = 0;
        struct ast_module_user *u = NULL;
        struct ast_speech *speech = find_speech(chan);

        u = ast_module_user_add(chan);

        if (speech == NULL) {
                ast_module_user_remove(u);
                return -1;
        }

	if (speech->processing_sound != NULL) {
		free(speech->processing_sound);
		speech->processing_sound = NULL;
	}

	speech->processing_sound = strdup(data);

        ast_module_user_remove(u);

        return res;
}
Пример #28
0
static int app_exec(struct ast_channel *chan, void *data)
{
	struct ast_module_user *lu;
	struct playlist_entry *entry;
	const char *args = data;
	int child_stdin[2] = { 0,0 };
	int child_stdout[2] = { 0,0 };
	int child_stderr[2] = { 0,0 };
	int res = -1;
	int test_available_fd = -1;
	int gen_active = 0;
	int pid;
	char *argv[32];
	int argc = 1;
	char *buf, *command;
	FILE *child_commands = NULL;
	FILE *child_errors = NULL;
	FILE *child_events = NULL;
	struct ivr_localuser foo = {
		.playlist = AST_LIST_HEAD_INIT_VALUE,
		.finishlist = AST_LIST_HEAD_INIT_VALUE,
	};
	struct ivr_localuser *u = &foo;
	sigset_t fullset, oldset;

	lu = ast_module_user_add(chan);

	sigfillset(&fullset);
	pthread_sigmask(SIG_BLOCK, &fullset, &oldset);

	u->abort_current_sound = 0;
	u->chan = chan;
	
	if (ast_strlen_zero(args)) {
		ast_log(LOG_WARNING, "ExternalIVR requires a command to execute\n");
		ast_module_user_remove(lu);
		return -1;	
	}

	buf = ast_strdupa(data);

	argc = ast_app_separate_args(buf, '|', argv, sizeof(argv) / sizeof(argv[0]));

	if (pipe(child_stdin)) {
		ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child input: %s\n", strerror(errno));
		goto exit;
	}

	if (pipe(child_stdout)) {
		ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child output: %s\n", strerror(errno));
		goto exit;
	}

	if (pipe(child_stderr)) {
		ast_chan_log(LOG_WARNING, chan, "Could not create pipe for child errors: %s\n", strerror(errno));
		goto exit;
	}

	if (chan->_state != AST_STATE_UP) {
		ast_answer(chan);
	}

	if (ast_activate_generator(chan, &gen, u) < 0) {
		ast_chan_log(LOG_WARNING, chan, "Failed to activate generator\n");
		goto exit;
	} else
		gen_active = 1;

	pid = fork();
	if (pid < 0) {
		ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
		goto exit;
	}

	if (!pid) {
		/* child process */
		int i;

		signal(SIGPIPE, SIG_DFL);
		pthread_sigmask(SIG_UNBLOCK, &fullset, NULL);

		if (ast_opt_high_priority)
			ast_set_priority(0);

		dup2(child_stdin[0], STDIN_FILENO);
		dup2(child_stdout[1], STDOUT_FILENO);
		dup2(child_stderr[1], STDERR_FILENO);
		for (i = STDERR_FILENO + 1; i < 1024; i++)
			close(i);
		execv(argv[0], argv);
		fprintf(stderr, "Failed to execute '%s': %s\n", argv[0], strerror(errno));
		_exit(1);
	} else {
		/* parent process */
		int child_events_fd = child_stdin[1];
		int child_commands_fd = child_stdout[0];
		int child_errors_fd = child_stderr[0];
		struct ast_frame *f;
		int ms;
		int exception;
		int ready_fd;
		int waitfds[2] = { child_errors_fd, child_commands_fd };
		struct ast_channel *rchan;

		pthread_sigmask(SIG_SETMASK, &oldset, NULL);

		close(child_stdin[0]);
		child_stdin[0] = 0;
		close(child_stdout[1]);
		child_stdout[1] = 0;
		close(child_stderr[1]);
		child_stderr[1] = 0;

		if (!(child_events = fdopen(child_events_fd, "w"))) {
			ast_chan_log(LOG_WARNING, chan, "Could not open stream for child events\n");
			goto exit;
		}

		if (!(child_commands = fdopen(child_commands_fd, "r"))) {
			ast_chan_log(LOG_WARNING, chan, "Could not open stream for child commands\n");
			goto exit;
		}

		if (!(child_errors = fdopen(child_errors_fd, "r"))) {
			ast_chan_log(LOG_WARNING, chan, "Could not open stream for child errors\n");
			goto exit;
		}

		test_available_fd = open("/dev/null", O_RDONLY);

		setvbuf(child_events, NULL, _IONBF, 0);
		setvbuf(child_commands, NULL, _IONBF, 0);
		setvbuf(child_errors, NULL, _IONBF, 0);

		res = 0;

		while (1) {
			if (ast_test_flag(chan, AST_FLAG_ZOMBIE)) {
				ast_chan_log(LOG_NOTICE, chan, "Is a zombie\n");
				res = -1;
				break;
			}

			if (ast_check_hangup(chan)) {
				ast_chan_log(LOG_NOTICE, chan, "Got check_hangup\n");
				send_child_event(child_events, 'H', NULL, chan);
				res = -1;
				break;
			}

			ready_fd = 0;
			ms = 100;
			errno = 0;
			exception = 0;

			rchan = ast_waitfor_nandfds(&chan, 1, waitfds, 2, &exception, &ready_fd, &ms);

			if (!AST_LIST_EMPTY(&u->finishlist)) {
				AST_LIST_LOCK(&u->finishlist);
				while ((entry = AST_LIST_REMOVE_HEAD(&u->finishlist, list))) {
					send_child_event(child_events, 'F', entry->filename, chan);
					free(entry);
				}
				AST_LIST_UNLOCK(&u->finishlist);
			}

			if (rchan) {
				/* the channel has something */
				f = ast_read(chan);
				if (!f) {
					ast_chan_log(LOG_NOTICE, chan, "Returned no frame\n");
					send_child_event(child_events, 'H', NULL, chan);
					res = -1;
					break;
				}

				if (f->frametype == AST_FRAME_DTMF) {
					send_child_event(child_events, f->subclass, NULL, chan);
					if (u->option_autoclear) {
						if (!u->abort_current_sound && !u->playing_silence)
							send_child_event(child_events, 'T', NULL, chan);
						AST_LIST_LOCK(&u->playlist);
						while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
							send_child_event(child_events, 'D', entry->filename, chan);
							free(entry);
						}
						if (!u->playing_silence)
							u->abort_current_sound = 1;
						AST_LIST_UNLOCK(&u->playlist);
					}
				} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP)) {
					ast_chan_log(LOG_NOTICE, chan, "Got AST_CONTROL_HANGUP\n");
					send_child_event(child_events, 'H', NULL, chan);
					ast_frfree(f);
					res = -1;
					break;
				}
				ast_frfree(f);
			} else if (ready_fd == child_commands_fd) {
				char input[1024];

				if (exception || feof(child_commands)) {
					ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
					res = -1;
					break;
				}

				if (!fgets(input, sizeof(input), child_commands))
					continue;

				command = ast_strip(input);

				ast_chan_log(LOG_DEBUG, chan, "got command '%s'\n", input);

				if (strlen(input) < 4)
					continue;

				if (input[0] == 'S') {
					if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
						ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
						send_child_event(child_events, 'Z', NULL, chan);
						strcpy(&input[2], "exception");
					}
					if (!u->abort_current_sound && !u->playing_silence)
						send_child_event(child_events, 'T', NULL, chan);
					AST_LIST_LOCK(&u->playlist);
					while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list))) {
						send_child_event(child_events, 'D', entry->filename, chan);
						free(entry);
					}
					if (!u->playing_silence)
						u->abort_current_sound = 1;
					entry = make_entry(&input[2]);
					if (entry)
						AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
					AST_LIST_UNLOCK(&u->playlist);
				} else if (input[0] == 'A') {
					if (ast_fileexists(&input[2], NULL, u->chan->language) == -1) {
						ast_chan_log(LOG_WARNING, chan, "Unknown file requested '%s'\n", &input[2]);
						send_child_event(child_events, 'Z', NULL, chan);
						strcpy(&input[2], "exception");
					}
					entry = make_entry(&input[2]);
					if (entry) {
						AST_LIST_LOCK(&u->playlist);
						AST_LIST_INSERT_TAIL(&u->playlist, entry, list);
						AST_LIST_UNLOCK(&u->playlist);
					}
				} else if (input[0] == 'H') {
					ast_chan_log(LOG_NOTICE, chan, "Hanging up: %s\n", &input[2]);
					send_child_event(child_events, 'H', NULL, chan);
					break;
				} else if (input[0] == 'O') {
					if (!strcasecmp(&input[2], "autoclear"))
						u->option_autoclear = 1;
					else if (!strcasecmp(&input[2], "noautoclear"))
						u->option_autoclear = 0;
					else
						ast_chan_log(LOG_WARNING, chan, "Unknown option requested '%s'\n", &input[2]);
				}
			} else if (ready_fd == child_errors_fd) {
				char input[1024];

				if (exception || (dup2(child_commands_fd, test_available_fd) == -1) || feof(child_errors)) {
					ast_chan_log(LOG_WARNING, chan, "Child process went away\n");
					res = -1;
					break;
				}

				if (fgets(input, sizeof(input), child_errors)) {
					command = ast_strip(input);
					ast_chan_log(LOG_NOTICE, chan, "stderr: %s\n", command);
				}
			} else if ((ready_fd < 0) && ms) { 
				if (errno == 0 || errno == EINTR)
					continue;

				ast_chan_log(LOG_WARNING, chan, "Wait failed (%s)\n", strerror(errno));
				break;
			}
		}
	}

 exit:
	if (gen_active)
		ast_deactivate_generator(chan);

	if (child_events)
		fclose(child_events);

	if (child_commands)
		fclose(child_commands);

	if (child_errors)
		fclose(child_errors);

	if (test_available_fd > -1) {
		close(test_available_fd);
	}

	if (child_stdin[0])
		close(child_stdin[0]);

	if (child_stdin[1])
		close(child_stdin[1]);

	if (child_stdout[0])
		close(child_stdout[0]);

	if (child_stdout[1])
		close(child_stdout[1]);

	if (child_stderr[0])
		close(child_stderr[0]);

	if (child_stderr[1])
		close(child_stderr[1]);

	while ((entry = AST_LIST_REMOVE_HEAD(&u->playlist, list)))
		free(entry);

	ast_module_user_remove(lu);

	return res;
}
Пример #29
0
/*! \brief SpeechBackground(Sound File|Timeout) Dialplan Application */
static int speech_background(struct ast_channel *chan, void *data)
{
        unsigned int timeout = 0;
        int res = 0, done = 0, argc = 0, started = 0, quieted = 0, max_dtmf_len = 0;
        struct ast_module_user *u = NULL;
        struct ast_speech *speech = find_speech(chan);
        struct ast_frame *f = NULL;
        int oldreadformat = AST_FORMAT_SLINEAR;
        char dtmf[AST_MAX_EXTENSION] = "";
        time_t start, current;
        struct ast_datastore *datastore = NULL;
        char *argv[2], *args = NULL, *filename_tmp = NULL, *filename = NULL, tmp[2] = "", dtmf_terminator = '#';
	const char *tmp2 = NULL;

        args = ast_strdupa(data);

        u = ast_module_user_add(chan);

        if (speech == NULL) {
                ast_module_user_remove(u);
                return -1;
        }

	/* If channel is not already answered, then answer it */
	if (chan->_state != AST_STATE_UP && ast_answer(chan)) {
		ast_module_user_remove(u);
		return -1;
	}

        /* Record old read format */
        oldreadformat = chan->readformat;

        /* Change read format to be signed linear */
        if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
                ast_module_user_remove(u);
                return -1;
        }

        /* Parse out options */
        argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0]));
        if (argc > 0) {
                /* Yay sound file */
                filename_tmp = ast_strdupa(argv[0]);
		if (!ast_strlen_zero(argv[1])) {
			if ((timeout = atoi(argv[1])) == 0)
				timeout = -1;
		} else
			timeout = 0;
        }

	/* See if the maximum DTMF length variable is set... we use a variable in case they want to carry it through their entire dialplan */
	if ((tmp2 = pbx_builtin_getvar_helper(chan, "SPEECH_DTMF_MAXLEN")) && !ast_strlen_zero(tmp2))
		max_dtmf_len = atoi(tmp2);

	/* See if a terminator is specified */
	if ((tmp2 = pbx_builtin_getvar_helper(chan, "SPEECH_DTMF_TERMINATOR"))) {
		if (ast_strlen_zero(tmp2))
			dtmf_terminator = '\0';
		else
			dtmf_terminator = tmp2[0];
	}

        /* Before we go into waiting for stuff... make sure the structure is ready, if not - start it again */
        if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
		ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
                ast_speech_start(speech);
        }

	/* Ensure no streams are currently running */
	ast_stopstream(chan);

        /* Okay it's streaming so go into a loop grabbing frames! */
        while (done == 0) {
		/* If the filename is null and stream is not running, start up a new sound file */
		if (!quieted && (chan->streamid == -1 && chan->timingfunc == NULL) && (filename = strsep(&filename_tmp, "&"))) {
			/* Discard old stream information */
			ast_stopstream(chan);
			/* Start new stream */
			speech_streamfile(chan, filename, chan->language);
		}

                /* Run scheduled stuff */
                ast_sched_runq(chan->sched);

                /* Yay scheduling */
                res = ast_sched_wait(chan->sched);
                if (res < 0) {
                        res = 1000;
                }

                /* If there is a frame waiting, get it - if not - oh well */
                if (ast_waitfor(chan, res) > 0) {
                        f = ast_read(chan);
                        if (f == NULL) {
                                /* The channel has hung up most likely */
                                done = 3;
                                break;
                        }
                }

		/* Do timeout check (shared between audio/dtmf) */
		if ((!quieted || strlen(dtmf)) && started == 1) {
			time(&current);
			if ((current-start) >= timeout) {
				done = 1;
				if (f)
					ast_frfree(f);
				break;
			}
		}

                /* Do checks on speech structure to see if it's changed */
                ast_mutex_lock(&speech->lock);
                if (ast_test_flag(speech, AST_SPEECH_QUIET)) {
			if (chan->stream)
				ast_stopstream(chan);
			ast_clear_flag(speech, AST_SPEECH_QUIET);
			quieted = 1;
                }
                /* Check state so we can see what to do */
                switch (speech->state) {
                case AST_SPEECH_STATE_READY:
                        /* If audio playback has stopped do a check for timeout purposes */
                        if (chan->streamid == -1 && chan->timingfunc == NULL)
                                ast_stopstream(chan);
                        if (!quieted && chan->stream == NULL && timeout && started == 0 && !filename_tmp) {
				if (timeout == -1) {
					done = 1;
					if (f)
						ast_frfree(f);
					break;
				}
				time(&start);
				started = 1;
                        }
                        /* Write audio frame out to speech engine if no DTMF has been received */
                        if (!strlen(dtmf) && f != NULL && f->frametype == AST_FRAME_VOICE) {
                                ast_speech_write(speech, f->data, f->datalen);
                        }
                        break;
                case AST_SPEECH_STATE_WAIT:
                        /* Cue up waiting sound if not already playing */
			if (!strlen(dtmf)) {
				if (chan->stream == NULL) {
					if (speech->processing_sound != NULL) {
						if (strlen(speech->processing_sound) > 0 && strcasecmp(speech->processing_sound,"none")) {
							speech_streamfile(chan, speech->processing_sound, chan->language);
						}
					}
				} else if (chan->streamid == -1 && chan->timingfunc == NULL) {
					ast_stopstream(chan);
					if (speech->processing_sound != NULL) {
						if (strlen(speech->processing_sound) > 0 && strcasecmp(speech->processing_sound,"none")) {
							speech_streamfile(chan, speech->processing_sound, chan->language);
						}
					}
				}
			}
                        break;
                case AST_SPEECH_STATE_DONE:
			/* Now that we are done... let's switch back to not ready state */
			ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
			if (!strlen(dtmf)) {
				/* Copy to speech structure the results, if available */
				speech->results = ast_speech_results_get(speech);
				/* Break out of our background too */
				done = 1;
				/* Stop audio playback */
				if (chan->stream != NULL) {
					ast_stopstream(chan);
				}
			}
                        break;
                default:
                        break;
                }
                ast_mutex_unlock(&speech->lock);

                /* Deal with other frame types */
                if (f != NULL) {
                        /* Free the frame we received */
                        switch (f->frametype) {
                        case AST_FRAME_DTMF:
				if (dtmf_terminator != '\0' && f->subclass == dtmf_terminator) {
					done = 1;
				} else {
					if (chan->stream != NULL) {
						ast_stopstream(chan);
					}
					if (!started) {
						/* Change timeout to be 5 seconds for DTMF input */
						timeout = (chan->pbx && chan->pbx->dtimeout) ? chan->pbx->dtimeout : 5;
						started = 1;
					}
					time(&start);
					snprintf(tmp, sizeof(tmp), "%c", f->subclass);
					strncat(dtmf, tmp, sizeof(dtmf) - strlen(dtmf) - 1);
					/* If the maximum length of the DTMF has been reached, stop now */
					if (max_dtmf_len && strlen(dtmf) == max_dtmf_len)
						done = 1;
				}
                                break;
                        case AST_FRAME_CONTROL:
                                switch (f->subclass) {
                                case AST_CONTROL_HANGUP:
                                        /* Since they hung up we should destroy the speech structure */
                                        done = 3;
                                default:
                                        break;
                                }
                        default:
                                break;
                        }
                        ast_frfree(f);
                        f = NULL;
                }
        }

	if (strlen(dtmf)) {
		/* We sort of make a results entry */
		speech->results = ast_calloc(1, sizeof(*speech->results));
		if (speech->results != NULL) {
			ast_speech_dtmf(speech, dtmf);
			speech->results->score = 1000;
			speech->results->text = strdup(dtmf);
			speech->results->grammar = strdup("dtmf");
		}
		ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
	}

        /* See if it was because they hung up */
        if (done == 3) {
                /* Destroy speech structure */
                ast_speech_destroy(speech);
                datastore = ast_channel_datastore_find(chan, &speech_datastore, NULL);
                if (datastore != NULL) {
                        ast_channel_datastore_remove(chan, datastore);
                }
        } else {
                /* Channel is okay so restore read format */
                ast_set_read_format(chan, oldreadformat);
        }

        ast_module_user_remove(u);

        return 0;
}
Пример #30
0
static int exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
{
	int res, error_func;
	lua_State *L;
	struct ast_module_user *u = ast_module_user_add(chan);
	if (!u) {
		ast_log(LOG_ERROR, "Error adjusting use count, probably could not allocate memory\n");
		return -1;
	}
	
	L = lua_get_state(chan);
	if (!L) {
		ast_module_user_remove(u);
		return -1;
	}

	lua_pushcfunction(L, &lua_error_function);
	error_func = lua_gettop(L);

	/* push the extension function onto the stack */
	if (!lua_find_extension(L, context, exten, priority, &exists, 1)) {
		lua_pop(L, 1); /* pop the debug function */
		ast_log(LOG_ERROR, "Could not find extension %s in context %s\n", exten, context);
		if (!chan) lua_close(L);
		ast_module_user_remove(u);
		return -1;
	}

	lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
	if (lua_toboolean(L, -1)) {
		ast_autoservice_start(chan);
	}
	lua_pop(L, 1);

	lua_update_registry(L, context, exten, priority);
	
	lua_pushstring(L, context);
	lua_pushstring(L, exten);
	
	res = lua_pcall(L, 2, 0, error_func);
	if (res) {
		if (res == LUA_ERRRUN) {
			res = -1;
			if (lua_isnumber(L, -1)) {
				res = lua_tointeger(L, -1);

				if (res == LUA_GOTO_DETECTED) {
					res = 0;
				}
			} else if (lua_isstring(L, -1)) {
				const char *error = lua_tostring(L, -1);
				ast_log(LOG_ERROR, "Error executing lua extension: %s\n", error);
			}
		} else if (res == LUA_ERRERR) {
			res = -1;
			ast_log(LOG_ERROR, "Error in the lua error handler (this is probably a bug in pbx_lua)\n");
		} else if (res == LUA_ERRMEM) {
			res = -1;
			ast_log(LOG_ERROR, "Memory allocation error\n");
		}
		lua_pop(L, 1);
	}
	lua_remove(L, error_func);

	lua_getfield(L, LUA_REGISTRYINDEX, "autoservice");
	if (lua_toboolean(L, -1)) {
		ast_autoservice_stop(chan);
	}
	lua_pop(L, 1);

	if (!chan) lua_close(L);
	ast_module_user_remove(u);
	return res;
}