static int pickup_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct localuser *u = NULL;
	struct ast_channel *origin = NULL, *target = NULL;
	char *tmp = NULL, *exten = NULL, *context = NULL;
	char workspace[256] = "";

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

	LOCAL_USER_ADD(u);
	
	/* Get the extension and context if present */
	exten = data;
	context = strchr(data, '@');
	if (context) {
		*context = '\0';
		context++;
	}

	/* Find a channel to pickup */
	origin = ast_get_channel_by_exten_locked(exten, context);
	if (origin && origin->cdr) {
		ast_cdr_getvar(origin->cdr, "dstchannel", &tmp, workspace,
			       sizeof(workspace), 0);
		if (tmp) {
			/* We have a possible channel... now we need to find it! */
			target = ast_get_channel_by_name_locked(tmp);
		} else {
			ast_log(LOG_DEBUG, "No target channel found.\n");
			res = -1;
		}
		ast_mutex_unlock(&origin->lock);
	} else {
		if (origin)
			ast_mutex_unlock(&origin->lock);
		ast_log(LOG_DEBUG, "No originating channel found.\n");
	}
	
	if (res)
		goto out;

	if (target && (!target->pbx) && ((target->_state == AST_STATE_RINGING) || (target->_state == AST_STATE_RING))) {
		ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n", target->name,
			chan->name);
		res = ast_answer(chan);
		if (res) {
			ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
			res = -1;
			goto out;
		}
		res = ast_queue_control(chan, AST_CONTROL_ANSWER);
		if (res) {
			ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n",
				chan->name);
			res = -1;
			goto out;
		}
		res = ast_channel_masquerade(target, chan);
		if (res) {
			ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
			res = -1;
			goto out;
		}
	} else {
		ast_log(LOG_DEBUG, "No call pickup possible...\n");
		res = -1;
	}
	/* Done */
 out:
	if (target) 
		ast_mutex_unlock(&target->lock);
	
	LOCAL_USER_REMOVE(u);

	return res;
}
Example #2
0
static int read_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct localuser *u;
	char tmp[256];
	char *timeout = NULL;
	char *varname = NULL;
	char *filename = NULL;
	char *loops;
	char *maxdigitstr=NULL;
	char *options=NULL;
	int option_skip = 0;
	int option_noanswer = 0;
	int maxdigits=255;
	int tries = 1;
	int to = 0;
	int x = 0;
	char *argcopy = NULL;
	char *args[8];

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

	LOCAL_USER_ADD(u);
	
	argcopy = ast_strdupa(data);
	if (!argcopy) {
		ast_log(LOG_ERROR, "Out of memory\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	if (ast_app_separate_args(argcopy, '|', args, sizeof(args) / sizeof(args[0])) < 1) {
		ast_log(LOG_WARNING, "Cannot Parse Arguments.\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	varname = args[x++];
	filename = args[x++];
	maxdigitstr = args[x++];
	options = args[x++];
	loops = args[x++];
	timeout = args[x++];
	
	if (options) { 
		if (!strcasecmp(options, "skip"))
			option_skip = 1;
		else if (!strcasecmp(options, "noanswer"))
			option_noanswer = 1;
		else {
			if (strchr(options, 's'))
				option_skip = 1;
			if (strchr(options, 'n'))
				option_noanswer = 1;
		}
	}

	if(loops) {
		tries = atoi(loops);
		if(tries <= 0)
			tries = 1;
	}

	if(timeout) {
		to = atoi(timeout);
		if (to <= 0)
			to = 0;
		else
			to *= 1000;
	}

	if (ast_strlen_zero(filename)) 
		filename = NULL;
	if (maxdigitstr) {
		maxdigits = atoi(maxdigitstr);
		if ((maxdigits<1) || (maxdigits>255)) {
    			maxdigits = 255;
		} else if (option_verbose > 2)
			ast_verbose(VERBOSE_PREFIX_3 "Accepting a maximum of %d digits.\n", maxdigits);
	}
	if (ast_strlen_zero(varname)) {
		ast_log(LOG_WARNING, "Invalid! Usage: Read(variable[|filename][|maxdigits][|option][|attempts][|timeout])\n\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}
	
	if (chan->_state != AST_STATE_UP) {
		if (option_skip) {
			/* At the user's option, skip if the line is not up */
			pbx_builtin_setvar_helper(chan, varname, "\0");
			LOCAL_USER_REMOVE(u);
			return 0;
		} else if (!option_noanswer) {
			/* Otherwise answer unless we're supposed to read while on-hook */
			res = ast_answer(chan);
		}
	}
	if (!res) {
		while(tries && !res) {
			ast_stopstream(chan);
			res = ast_app_getdata(chan, filename, tmp, maxdigits, to);
			if (res > -1) {
				pbx_builtin_setvar_helper(chan, varname, tmp);
				if (!ast_strlen_zero(tmp)) {
					if (option_verbose > 2)
						ast_verbose(VERBOSE_PREFIX_3 "User entered '%s'\n", tmp);
					tries = 0;
				} else {
					tries--;
					if (option_verbose > 2) {
						if (tries)
							ast_verbose(VERBOSE_PREFIX_3 "User entered nothing, %d chance%s left\n", tries, (tries != 1) ? "s" : "");
						else
							ast_verbose(VERBOSE_PREFIX_3 "User entered nothing.\n");
					}
				}
				res = 0;
			} else {
				if (option_verbose > 2)
					ast_verbose(VERBOSE_PREFIX_3 "User disconnected\n");
			}
		}
	}
	LOCAL_USER_REMOVE(u);
	return res;
}
static int cpeid_exec(struct ast_channel *chan, void *idata)
{
	int res=0;
	struct localuser *u;
	unsigned char cpeid[4];
	int gotgeometry = 0;
	int gotcpeid = 0;
	int width, height, buttons;
	char data[4][80];
	char *stuff[4];

	LOCAL_USER_ADD(u);
	stuff[0] = data[0];
	stuff[1] = data[1];
	stuff[2] = data[2];
	stuff[3] = data[3];
	memset(data, 0, sizeof(data));
	strncpy(stuff[0], "** CPE Info **", sizeof(data[0]) - 1);
	strncpy(stuff[1], "Identifying CPE...", sizeof(data[1]) - 1);
	strncpy(stuff[2], "Please wait...", sizeof(data[2]) - 1);
	res = adsi_load_session(chan, NULL, 0, 1);
	if (res > 0) {
		cpeid_setstatus(chan, stuff, 0);
		res = adsi_get_cpeid(chan, cpeid, 0);
		if (res > 0) {
			gotcpeid = 1;
			if (option_verbose > 2)
				ast_verbose(VERBOSE_PREFIX_3 "Got CPEID of '%02x:%02x:%02x:%02x' on '%s'\n", cpeid[0], cpeid[1], cpeid[2], cpeid[3], chan->name);
		}
		if (res > -1) {
			strncpy(stuff[1], "Measuring CPE...", sizeof(data[1]) - 1);
			strncpy(stuff[2], "Please wait...", sizeof(data[2]) - 1);
			cpeid_setstatus(chan, stuff, 0);
			res = adsi_get_cpeinfo(chan, &width, &height, &buttons, 0);
			if (res > -1) {
				if (option_verbose > 2)
					ast_verbose(VERBOSE_PREFIX_3 "CPE has %d lines, %d columns, and %d buttons on '%s'\n", height, width, buttons, chan->name);
				gotgeometry = 1;
			}
		}
		if (res > -1) {
			if (gotcpeid)
				snprintf(stuff[1], sizeof(data[1]), "CPEID: %02x:%02x:%02x:%02x", cpeid[0], cpeid[1], cpeid[2], cpeid[3]);
			else
				strncpy(stuff[1], "CPEID Unknown", sizeof(data[1]) - 1);
			if (gotgeometry) 
				snprintf(stuff[2], sizeof(data[2]), "Geom: %dx%d, %d buttons", width, height, buttons);
			else
				strncpy(stuff[2], "Geometry unknown", sizeof(data[2]) - 1);
			strncpy(stuff[3], "Press # to exit", sizeof(data[3]) - 1);
			cpeid_setstatus(chan, stuff, 1);
			for(;;) {
				res = ast_waitfordigit(chan, 1000);
				if (res < 0)
					break;
				if (res == '#') {
					res = 0;
					break;
				}
			}
			adsi_unload_session(chan);
		}
	}
	LOCAL_USER_REMOVE(u);
	return res;
}
Example #4
0
/*--- conf_exec: The meetme() application */
static int conf_exec(struct ast_channel *chan, void *data)
{
	int res=-1;
	struct localuser *u;
	char confno[AST_MAX_EXTENSION] = "";
	int allowretry = 0;
	int retrycnt = 0;
	struct ast_conference *cnf;
	int confflags = 0;
	int dynamic = 0;
	int empty = 0, empty_no_pin = 0;
	char *notdata, *info, *inflags = NULL, *inpin = NULL, the_pin[AST_MAX_EXTENSION] = "";

	if (!data || ast_strlen_zero(data)) {
		allowretry = 1;
		notdata = "";
	} else {
		notdata = data;
	}
	LOCAL_USER_ADD(u);
	if (chan->_state != AST_STATE_UP)
		ast_answer(chan);

	info = ast_strdupa((char *)notdata);

	if (info) {
		char *tmp = strsep(&info, "|");
		strncpy(confno, tmp, sizeof(confno) - 1);
		if (ast_strlen_zero(confno)) {
			allowretry = 1;
		}
	}
	if (info)
		inflags = strsep(&info, "|");
	if (info)
		inpin = strsep(&info, "|");
	if (inpin)
		strncpy(the_pin, inpin, sizeof(the_pin) - 1);

	if (inflags) {
		if (strchr(inflags, 'a'))
			confflags |= CONFFLAG_ADMIN;
		if (strchr(inflags, 'm'))
			confflags |= CONFFLAG_MONITOR;
		if (strchr(inflags, 'p'))
			confflags |= CONFFLAG_POUNDEXIT;
		if (strchr(inflags, 's'))
			confflags |= CONFFLAG_STARMENU;
		if (strchr(inflags, 't'))
			confflags |= CONFFLAG_TALKER;
		if (strchr(inflags, 'q'))
			confflags |= CONFFLAG_QUIET;
		if (strchr(inflags, 'M'))
			confflags |= CONFFLAG_MOH;
		if (strchr(inflags, 'x'))
			confflags |= CONFFLAG_MARKEDEXIT;
		if (strchr(inflags, 'X'))
			confflags |= CONFFLAG_EXIT_CONTEXT;
		if (strchr(inflags, 'A'))
			confflags |= CONFFLAG_MARKEDUSER;
		if (strchr(inflags, 'b'))
			confflags |= CONFFLAG_AGI;
		if (strchr(inflags, 'w'))
			confflags |= CONFFLAG_WAITMARKED;
		if (strchr(inflags, 'd'))
			dynamic = 1;
		if (strchr(inflags, 'D')) {
			dynamic = 1;
			if (! inpin) {
				strncpy(the_pin, "q", sizeof(the_pin) - 1);
			}
		}
		if (strchr(inflags, 'e'))
			empty = 1;
		if (strchr(inflags, 'E')) {
			empty = 1;
			empty_no_pin = 1;
		}
	}

	do {
		if (retrycnt > 3)
			allowretry = 0;
		if (empty) {
			int i, map[1024];
			struct ast_config *cfg;
			struct ast_variable *var;
			int confno_int;

			memset(map, 0, sizeof(map));

			ast_mutex_lock(&conflock);
			cnf = confs;
			while (cnf) {
				if (sscanf(cnf->confno, "%d", &confno_int) == 1) {
					/* Disqualify in use conference */
					if (confno_int >= 0 && confno_int < 1024)
						map[confno_int]++;
				}
				cnf = cnf->next;
			}
			ast_mutex_unlock(&conflock);

			/* We only need to load the config file for static and empty_no_pin (otherwise we don't care) */
			if ((empty_no_pin) || (!dynamic)) {
				cfg = ast_load("meetme.conf");
				if (cfg) {
					var = ast_variable_browse(cfg, "rooms");
					while(var) {
						if (!strcasecmp(var->name, "conf")) {
							char *stringp = ast_strdupa(var->value);
							if (stringp) {
								char *confno_tmp = strsep(&stringp, "|,");
								int found = 0;
								if (sscanf(confno_tmp, "%d", &confno_int) == 1) {
									if ((confno_int >= 0) && (confno_int < 1024)) {
										if (stringp && empty_no_pin) {
											map[confno_int]++;
										}
									}
								}
								if (! dynamic) {
									/* For static:  run through the list and see if this conference is empty */
									ast_mutex_lock(&conflock);
									cnf = confs;
									while (cnf) {
										if (!strcmp(confno_tmp, cnf->confno)) {
											/* The conference exists, therefore it's not empty */
											found = 1;
											break;
										}
										cnf = cnf->next;
									}
									ast_mutex_unlock(&conflock);
									if (!found) {
										/* At this point, we have a confno_tmp (static conference) that is empty */
										if ((empty_no_pin && ((!stringp) || (stringp && (stringp[0] == '\0')))) || (!empty_no_pin)) {
										/* Case 1:  empty_no_pin and pin is nonexistant (NULL)
										 * Case 2:  empty_no_pin and pin is blank (but not NULL)
										 * Case 3:  not empty_no_pin
										 */
											strncpy(confno, confno_tmp, sizeof(confno) - 1);
											break;
											/* XXX the map is not complete (but we do have a confno) */
										}
									}
								}
							} else {
								ast_log(LOG_ERROR, "Out of memory\n");
							}
						}
						var = var->next;
					}
					ast_destroy(cfg);
				}
			}
			/* Select first conference number not in use */
			if (ast_strlen_zero(confno) && dynamic) {
				for (i=0;i<1024;i++) {
					if (!map[i]) {
						snprintf(confno, sizeof(confno), "%d", i);
						break;
					}
				}
			}

			/* Not found? */
			if (ast_strlen_zero(confno)) {
				res = ast_streamfile(chan, "conf-noempty", chan->language);
				if (!res)
					ast_waitstream(chan, "");
			} else {
				if (sscanf(confno, "%d", &confno_int) == 1) {
					res = ast_streamfile(chan, "conf-enteringno", chan->language);
					if (!res) {
						ast_waitstream(chan, "");
						res = ast_say_digits(chan, confno_int, "", chan->language);
					}
				} else {
					ast_log(LOG_ERROR, "Could not scan confno '%s'\n", confno);
				}
			}
		}
		while (allowretry && (ast_strlen_zero(confno)) && (++retrycnt < 4)) {
			/* Prompt user for conference number */
			res = ast_app_getdata(chan, "conf-getconfno", confno, sizeof(confno) - 1, 0);
			if (res < 0) {
				/* Don't try to validate when we catch an error */
				confno[0] = '\0';
				allowretry = 0;
				break;
			}
		}
		if (!ast_strlen_zero(confno)) {
			/* Check the validity of the conference */
			cnf = find_conf(chan, confno, 1, dynamic, the_pin);
			if (!cnf) {
				res = ast_streamfile(chan, "conf-invalid", chan->language);
				if (!res)
					ast_waitstream(chan, "");
				res = -1;
				if (allowretry)
					confno[0] = '\0';
			} else {
				if (!ast_strlen_zero(cnf->pin)) {
					char pin[AST_MAX_EXTENSION]="";
					int j;

					/* Allow the pin to be retried up to 3 times */
					for (j=0; j<3; j++) {
						if (*the_pin) {
							strncpy(pin, the_pin, sizeof(pin) - 1);
							res = 0;
						} else {
							/* Prompt user for pin if pin is required */
							res = ast_app_getdata(chan, "conf-getpin", pin + strlen(pin), sizeof(pin) - 1 - strlen(pin), 0);
						}
						if (res >= 0) {
							if (!strcasecmp(pin, cnf->pin)) {
								/* Pin correct */
								allowretry = 0;
								/* Run the conference */
								res = conf_run(chan, cnf, confflags);
								break;
							} else {
								/* Pin invalid */
								res = ast_streamfile(chan, "conf-invalidpin", chan->language);
								if (!res)
									ast_waitstream(chan, AST_DIGIT_ANY);
								if (res < 0)
									break;
								pin[0] = res;
								pin[1] = '\0';
								res = -1;
								if (allowretry)
									confno[0] = '\0';
							}
						} else {
							res = -1;
							allowretry = 0;
							break;
						}

						/* Don't retry pin with a static pin */
						if (*the_pin) {
							break;
						}
					}
				} else {
					/* No pin required */
					allowretry = 0;

					/* Run the conference */
					res = conf_run(chan, cnf, confflags);
				}
			}
		}
	} while (allowretry);
	/* Do the conference */
	LOCAL_USER_REMOVE(u);
	return res;
}
Example #5
0
static int privacy_exec (struct cw_channel *chan, int argc, char **argv)
{
	char phone[30];
	struct localuser *u;
	struct cw_config *cfg;
	char *s;
	int res=0;
	int retries;
	int maxretries = 3;
	int minlength = 10;
	int x;

	LOCAL_USER_ADD (u);

	if (!cw_strlen_zero(chan->cid.cid_num)) {
		if (option_verbose > 2)
			cw_verbose (VERBOSE_PREFIX_3 "CallerID Present: Skipping\n");
		pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
	} else {
		/*Answer the channel if it is not already*/
		if (chan->_state != CW_STATE_UP) {
			res = cw_answer(chan);
			if (res) {
				pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAIL");
				LOCAL_USER_REMOVE(u);
				return 0;
			}
		}
		/*Read in the config file*/
		cfg = cw_config_load(PRIV_CONFIG);
		
		
		/*Play unidentified call*/
		res = cw_safe_sleep(chan, 1000);
		if (!res)
			res = cw_streamfile(chan, "privacy-unident", chan->language);
		if (!res)
			res = cw_waitstream(chan, "");

        if (cfg && (s = cw_variable_retrieve(cfg, "general", "maxretries"))) {
                if (sscanf(s, "%d", &x) == 1) {
                        maxretries = x;
                } else {
                        cw_log(LOG_WARNING, "Invalid max retries argument\n");
                }
        }
        if (cfg && (s = cw_variable_retrieve(cfg, "general", "minlength"))) {
                if (sscanf(s, "%d", &x) == 1) {
                        minlength = x;
                } else {
                        cw_log(LOG_WARNING, "Invalid min length argument\n");
                }
        }
			
		/*Ask for 10 digit number, give 3 attempts*/
		for (retries = 0; retries < maxretries; retries++) {
			if (!res ) 
				res = cw_app_getdata(chan, "privacy-prompt", phone, sizeof(phone), 0);

			if (res < 0)
				break;

			/*Make sure we get at least our minimum of digits*/
			if (strlen(phone) >= minlength ) 
				break;
			else {
				res = cw_streamfile(chan, "privacy-incorrect", chan->language);
				if (!res)
					res = cw_waitstream(chan, "");
			}
		}
		
		/*Got a number, play sounds and send them on their way*/
		if ((retries < maxretries) && res == 1 ) {
			res = cw_streamfile(chan, "privacy-thankyou", chan->language);
			if (!res)
				res = cw_waitstream(chan, "");
			cw_set_callerid (chan, phone, "Privacy Manager", NULL);
			if (option_verbose > 2)
				cw_verbose (VERBOSE_PREFIX_3 "Changed Caller*ID to %s\n",phone);
			pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "SUCCESS");
		} else {
			/* Flag Failure  */
			pbx_builtin_setvar_helper(chan, "PRIVACYMGRSTATUS", "FAIL");
		}
		if (cfg) 
			cw_config_destroy(cfg);
	}

  LOCAL_USER_REMOVE (u);
  return 0;
}
Example #6
0
static int pipe_exec(struct cw_channel *chan, int argc, char **argv)
{
	int res=0;
	struct localuser *u;
	int fds[2];
	int ms = -1;
	int pid = -1;
	int owriteformat;
	int oreadformat;
	int timeout = 2000;
	struct timeval last;
	struct cw_frame *f;
	struct myframe {
		struct cw_frame f;
		char offset[CW_FRIENDLY_OFFSET];
		short frdata[160];
	} myf;

	last.tv_usec = 0;
	last.tv_sec = 0;

	if (argc < 2 || argc > 3) {
		cw_log(LOG_ERROR, "Syntax: %s\n", pipe_syntax);
		return -1;
	}

	LOCAL_USER_ADD(u);

	if (pipe(fds)) {
		cw_log(LOG_WARNING, "Unable to create pipe\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

// MOC: Setting non blocking doesn't seem to change anything
//	flags = fcntl(fds[1], F_GETFL);
//	fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);

//	flags = fcntl(fds[0], F_GETFL);
//	fcntl(fds[0], F_SETFL, flags | O_NONBLOCK);

	cw_stopstream(chan);

	if (chan->_state != CW_STATE_UP)
		res = cw_answer(chan);
		
	if (res) {
		close(fds[0]);
		close(fds[1]);
		cw_log(LOG_WARNING, "Answer failed!\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	oreadformat = chan->readformat;
	res = cw_set_read_format(chan, CW_FORMAT_SLINEAR);

	owriteformat = chan->writeformat;
	res += cw_set_write_format(chan, CW_FORMAT_SLINEAR);

	if (res < 0) {
		close(fds[0]);
		close(fds[1]);
		cw_log(LOG_WARNING, "Unable to set write format to signed linear\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	res = pipeencode(argv[1], argv[2], fds[0], fds[1]);

	if (res >= 0) {
	   last = cw_tvnow();
	   last.tv_sec += 1;

		pid = res;
		for (;;) {
			/* Wait for audio, and stream */
			if (argv[0][0] == '0') {
				/* START WRITE TO FD */
				ms = cw_waitfor(chan, 10);
				if (ms < 0) {
					cw_log(LOG_DEBUG, "Hangup detected\n");
					res = -1;
					break;
				} else if (ms > 0) {
					f = cw_read(chan);
					if (!f) {
						cw_log(LOG_DEBUG, "Null frame == hangup() detected\n");
						res = -1;
						break;
					}
					if (f->frametype == CW_FRAME_DTMF) {
						cw_log(LOG_DEBUG, "User pressed a key\n");
						cw_fr_free(f);
						res = 0;
						break;
					}
					if (f->frametype == CW_FRAME_VOICE) {
						res = write(fds[1], f->data, f->datalen);
						if (res < 0) {
							if (errno != EAGAIN) {
								cw_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
                                cw_fr_free(f);
								res = -1;
								break;
							}
						}
					}
					cw_fr_free(f);
				} /* END WRITE TO FD */
			} else {
				/* START WRITE CHANNEL */
				ms = cw_tvdiff_ms(last, cw_tvnow());
				if (ms <= 0) {
					res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
					if (res > 0) {
                        cw_fr_init_ex(&myf.f, CW_FRAME_VOICE, CW_FORMAT_SLINEAR, __PRETTY_FUNCTION__);
						myf.f.datalen = res;
						myf.f.samples = res/sizeof(int16_t);
						myf.f.offset = CW_FRIENDLY_OFFSET;
						myf.f.data = myf.frdata;
						if (cw_write(chan, &myf.f) < 0)
                        {
							res = -1;
							break;
						}
					} else {
						cw_log(LOG_DEBUG, "No more stream\n");
						res = 0;
						break;
					}
					last = cw_tvadd(last, cw_samp2tv(myf.f.samples, 8000));
				} else {
					ms = cw_waitfor(chan, ms);
					if (ms < 0) {
						cw_log(LOG_DEBUG, "Hangup detected\n");
						res = -1;
						break;
					}
					if (ms) {
						f = cw_read(chan);
						if (!f) {
							cw_log(LOG_DEBUG, "Null frame == hangup() detected\n");
							res = -1;
							break;
						}
						if (f->frametype == CW_FRAME_DTMF) {
							cw_log(LOG_DEBUG, "User pressed a key\n");
							cw_fr_free(f);
							res = 0;
							break;
						}
						cw_fr_free(f);
					}
				}
				/* END WRITE CHANNEL */
			}
		}
	}
	close(fds[0]);
	close(fds[1]);

	LOCAL_USER_REMOVE(u);
	if (pid > -1)
		kill(pid, SIGKILL);
	if (!res && oreadformat)
		cw_set_read_format(chan, oreadformat);
	if (!res && owriteformat)
		cw_set_write_format(chan, owriteformat);

	return res;
}
static int festival_exec(struct ast_channel *chan, void *vdata)
{
    int usecache;
    int res=0;
    struct localuser *u;
    struct sockaddr_in serv_addr;
    struct hostent *serverhost;
    struct ast_hostent ahp;
    int fd;
    FILE *fs;
    char *host;
    char *cachedir;
    char *temp;
    char *festivalcommand;
    int port=1314;
    int n;
    char ack[4];
    char *waveform;
    int filesize;
    int wave;
    char bigstring[MAXFESTLEN];
    int i;
    struct MD5Context md5ctx;
    unsigned char MD5Res[16];
    char MD5Hex[33] = "";
    char koko[4] = "";
    char cachefile[MAXFESTLEN]="";
    int readcache=0;
    int writecache=0;
    int strln;
    int fdesc = -1;
    char buffer[16384];
    int seekpos = 0;
    char *data;
    char *intstr;
    struct ast_config *cfg;
    char *newfestivalcommand;

    if (ast_strlen_zero(vdata)) {
        ast_log(LOG_WARNING, "festival requires an argument (text)\n");
        return -1;
    }

    LOCAL_USER_ADD(u);

    cfg = ast_config_load(FESTIVAL_CONFIG);
    if (!cfg) {
        ast_log(LOG_WARNING, "No such configuration file %s\n", FESTIVAL_CONFIG);
        LOCAL_USER_REMOVE(u);
        return -1;
    }
    if (!(host = ast_variable_retrieve(cfg, "general", "host"))) {
        host = "localhost";
    }
    if (!(temp = ast_variable_retrieve(cfg, "general", "port"))) {
        port = 1314;
    } else {
        port = atoi(temp);
    }
    if (!(temp = ast_variable_retrieve(cfg, "general", "usecache"))) {
        usecache=0;
    } else {
        usecache = ast_true(temp);
    }
    if (!(cachedir = ast_variable_retrieve(cfg, "general", "cachedir"))) {
        cachedir = "/tmp/";
    }
    if (!(festivalcommand = ast_variable_retrieve(cfg, "general", "festivalcommand"))) {
        festivalcommand = "(tts_textasterisk \"%s\" 'file)(quit)\n";
    } else { /* This else parses the festivalcommand that we're sent from the config file for \n's, etc */
        int i, j;
        newfestivalcommand = alloca(strlen(festivalcommand) + 1);

        for (i = 0, j = 0; i < strlen(festivalcommand); i++) {
            if (festivalcommand[i] == '\\' && festivalcommand[i + 1] == 'n') {
                newfestivalcommand[j++] = '\n';
                i++;
            } else if (festivalcommand[i] == '\\') {
                newfestivalcommand[j++] = festivalcommand[i + 1];
                i++;
            } else
                newfestivalcommand[j++] = festivalcommand[i];
        }
        newfestivalcommand[j] = '\0';
        festivalcommand = newfestivalcommand;
    }

    data = ast_strdupa(vdata);

    intstr = strchr(data, '|');
    if (intstr) {
        *intstr = '\0';
        intstr++;
        if (!strcasecmp(intstr, "any"))
            intstr = AST_DIGIT_ANY;
    }

    ast_log(LOG_DEBUG, "Text passed to festival server : %s\n",(char *)data);
    /* Connect to local festival server */

    fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (fd < 0) {
        ast_log(LOG_WARNING,"festival_client: can't get socket\n");
        ast_config_destroy(cfg);
        LOCAL_USER_REMOVE(u);
        return -1;
    }
    memset(&serv_addr, 0, sizeof(serv_addr));
    if ((serv_addr.sin_addr.s_addr = inet_addr(host)) == -1) {
        /* its a name rather than an ipnum */
        serverhost = ast_gethostbyname(host, &ahp);
        if (serverhost == (struct hostent *)0) {
            ast_log(LOG_WARNING,"festival_client: gethostbyname failed\n");
            ast_config_destroy(cfg);
            LOCAL_USER_REMOVE(u);
            return -1;
        }
        memmove(&serv_addr.sin_addr,serverhost->h_addr, serverhost->h_length);
    }
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(port);

    if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0) {
        ast_log(LOG_WARNING,"festival_client: connect to server failed\n");
        ast_config_destroy(cfg);
        LOCAL_USER_REMOVE(u);
        return -1;
    }

    /* Compute MD5 sum of string */
    MD5Init(&md5ctx);
    MD5Update(&md5ctx,(unsigned char const *)data,strlen(data));
    MD5Final(MD5Res,&md5ctx);
    MD5Hex[0] = '\0';

    /* Convert to HEX and look if there is any matching file in the cache
    	directory */
    for (i=0; i<16; i++) {
        snprintf(koko, sizeof(koko), "%X",MD5Res[i]);
        strncat(MD5Hex, koko, sizeof(MD5Hex) - strlen(MD5Hex) - 1);
    }
    readcache=0;
    writecache=0;
    if (strlen(cachedir)+strlen(MD5Hex)+1<=MAXFESTLEN && (usecache==-1)) {
        snprintf(cachefile, sizeof(cachefile), "%s/%s", cachedir, MD5Hex);
        fdesc=open(cachefile,O_RDWR);
        if (fdesc==-1) {
            fdesc=open(cachefile,O_CREAT|O_RDWR,0777);
            if (fdesc!=-1) {
                writecache=1;
                strln=strlen((char *)data);
                ast_log(LOG_DEBUG,"line length : %d\n",strln);
                write(fdesc,&strln,sizeof(int));
                write(fdesc,data,strln);
                seekpos=lseek(fdesc,0,SEEK_CUR);
                ast_log(LOG_DEBUG,"Seek position : %d\n",seekpos);
            }
        } else {
            read(fdesc,&strln,sizeof(int));
            ast_log(LOG_DEBUG,"Cache file exists, strln=%d, strlen=%d\n",strln,(int)strlen((char *)data));
            if (strlen((char *)data)==strln) {
                ast_log(LOG_DEBUG,"Size OK\n");
                read(fdesc,&bigstring,strln);
                bigstring[strln] = 0;
                if (strcmp(bigstring,data)==0) {
                    readcache=1;
                } else {
                    ast_log(LOG_WARNING,"Strings do not match\n");
                }
            } else {
                ast_log(LOG_WARNING,"Size mismatch\n");
            }
        }
    }

    if (readcache==1) {
        close(fd);
        fd=fdesc;
        ast_log(LOG_DEBUG,"Reading from cache...\n");
    } else {
        ast_log(LOG_DEBUG,"Passing text to festival...\n");
        fs=fdopen(dup(fd),"wb");
        fprintf(fs,festivalcommand,(char *)data);
        fflush(fs);
        fclose(fs);
    }

    /* Write to cache and then pass it down */
    if (writecache==1) {
        ast_log(LOG_DEBUG,"Writing result to cache...\n");
        while ((strln=read(fd,buffer,16384))!=0) {
            write(fdesc,buffer,strln);
        }
        close(fd);
        close(fdesc);
        fd=open(cachefile,O_RDWR);
        lseek(fd,seekpos,SEEK_SET);
    }

    ast_log(LOG_DEBUG,"Passing data to channel...\n");

    /* Read back info from server */
    /* This assumes only one waveform will come back, also LP is unlikely */
    wave = 0;
    do {
        int read_data;
        for (n=0; n < 3; )
        {
            read_data = read(fd,ack+n,3-n);
            /* this avoids falling in infinite loop
             * in case that festival server goes down
             * */
            if ( read_data == -1 )
            {
                ast_log(LOG_WARNING,"Unable to read from cache/festival fd");
                close(fd);
                ast_config_destroy(cfg);
                LOCAL_USER_REMOVE(u);
                return -1;
            }
            n += read_data;
        }
        ack[3] = '\0';
        if (strcmp(ack,"WV\n") == 0) {         /* receive a waveform */
            ast_log(LOG_DEBUG,"Festival WV command\n");
            waveform = socket_receive_file_to_buff(fd,&filesize);
            res = send_waveform_to_channel(chan,waveform,filesize, intstr);
            free(waveform);
            break;
        }
        else if (strcmp(ack,"LP\n") == 0) {   /* receive an s-expr */
            ast_log(LOG_DEBUG,"Festival LP command\n");
            waveform = socket_receive_file_to_buff(fd,&filesize);
            waveform[filesize]='\0';
            ast_log(LOG_WARNING,"Festival returned LP : %s\n",waveform);
            free(waveform);
        } else if (strcmp(ack,"ER\n") == 0) {    /* server got an error */
            ast_log(LOG_WARNING,"Festival returned ER\n");
            res=-1;
            break;
        }
    } while (strcmp(ack,"OK\n") != 0);
    close(fd);
    ast_config_destroy(cfg);
    LOCAL_USER_REMOVE(u);
    return res;

}
static int directory_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct localuser *u;
	struct ast_config *cfg;
	int last = 1;
	int fromappvm = 0;
	char *context, *dialcontext, *dirintro, *options;

	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "Directory requires an argument (context[,dialcontext])\n");
		return -1;
	}

	LOCAL_USER_ADD(u);

	context = ast_strdupa(data);
	dialcontext = strchr(context, '|');
	if (dialcontext) {
		*dialcontext = '\0';
		dialcontext++;
		options = strchr(dialcontext, '|');
		if (options) {
			*options = '\0';
			options++; 
			if (strchr(options, 'f'))
				last = 0;
			if (strchr(options, 'v'))
				fromappvm = 1;
		}
	} else	
		dialcontext = context;

	cfg = realtime_directory(context);
	if (!cfg) {
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	dirintro = ast_variable_retrieve(cfg, context, "directoryintro");
	if (ast_strlen_zero(dirintro))
		dirintro = ast_variable_retrieve(cfg, "general", "directoryintro");
	if (ast_strlen_zero(dirintro)) {
		if (last)
			dirintro = "dir-intro";	
		else
			dirintro = "dir-intro-fn";
	}

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

	for (;;) {
		if (!res)
			res = ast_streamfile(chan, dirintro, chan->language);
		if (!res)
			res = ast_waitstream(chan, AST_DIGIT_ANY);
		ast_stopstream(chan);
		if (!res)
			res = ast_waitfordigit(chan, 5000);
		if (res > 0) {
			res = do_directory(chan, cfg, context, dialcontext, res, last, fromappvm);
			if (res > 0) {
				res = ast_waitstream(chan, AST_DIGIT_ANY);
				ast_stopstream(chan);
				if (res >= 0) {
					continue;
				}
			}
		}
		break;
	}
	ast_config_destroy(cfg);
	LOCAL_USER_REMOVE(u);
	return res;
}
static int alarmreceiver_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct localuser *u;
	event_node_t *elp, *efree;
	char signalling_type[64] = "";

	event_node_t *event_head = NULL;

	LOCAL_USER_ADD(u);

	/* Set write and read formats to ULAW */

	if(option_verbose >= 4)
		ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Setting read and write formats to ULAW\n");

	if (ast_set_write_format(chan,AST_FORMAT_ULAW)){
		ast_log(LOG_WARNING, "AlarmReceiver: Unable to set write format to Mu-law on %s\n",chan->name);
		LOCAL_USER_REMOVE(u);
		return -1;
	}
	
	if (ast_set_read_format(chan,AST_FORMAT_ULAW)){
		ast_log(LOG_WARNING, "AlarmReceiver: Unable to set read format to Mu-law on %s\n",chan->name);
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	/* Set default values for this invokation of the application */
	
	ast_copy_string(signalling_type, ADEMCO_CONTACT_ID, sizeof(signalling_type));


	/* Answer the channel if it is not already */

	if(option_verbose >= 4)
		ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Answering channel\n");

	if (chan->_state != AST_STATE_UP) {
	
		res = ast_answer(chan);
		
		if (res) {
			LOCAL_USER_REMOVE(u);
			return -1;
		}
	}

	/* Wait for the connection to settle post-answer */

	if(option_verbose >= 4)
		ast_verbose(VERBOSE_PREFIX_4 "AlarmReceiver: Waiting for connection to stabilize\n");

	res = ast_safe_sleep(chan, 1250);

	/* Attempt to receive the events */

	if(!res){
	
		/* Determine the protocol to receive in advance */
		/* Note: Ademco contact is the only one supported at this time */
		/* Others may be added later */
		
		if(!strcmp(signalling_type, ADEMCO_CONTACT_ID))
			receive_ademco_contact_id(chan, data, fdtimeout, sdtimeout, toneloudness, &event_head);
		else
			res = -1;
	}
	
		
	
	/* Events queued by receiver, write them all out here if so configured */

	if((!res) && (log_individual_events == 0)){
		res = log_events(chan, signalling_type, event_head);

	}

	/*
	* Do we exec a command line at the end?
	*/
	
	if((!res) && (!ast_strlen_zero(event_app)) && (event_head)){
		ast_log(LOG_DEBUG,"Alarmreceiver: executing: %s\n", event_app);
		ast_safe_system(event_app);
	}

	/*
	* Free up the data allocated in our linked list
	*/
		
	for(elp = event_head; (elp != NULL);){
		efree = elp;
		elp = elp->next;
		free(efree);
	}


	LOCAL_USER_REMOVE(u);

	return 0;
}
Example #10
0
static int testclient_exec(struct ast_channel *chan, void *data)
{
	struct localuser *u;
	int res = 0;
	char *testid=data;
	char fn[80];
	char serverver[80];
	FILE *f;
	LOCAL_USER_ADD(u);
	
	/* Check for test id */
	if (!testid || ast_strlen_zero(testid)) {
		ast_log(LOG_WARNING, "TestClient requires an argument - the test id\n");
		return -1;
	}
	
	if (chan->_state != AST_STATE_UP)
		res = ast_answer(chan);
	
	/* Wait a few just to be sure things get started */
	res = ast_safe_sleep(chan, 3000);
	/* Transmit client version */
	if (!res)
		res = ast_dtmf_stream(chan, NULL, "8378*1#", 0);
	ast_log(LOG_DEBUG, "Transmit client version\n");
	
	/* Read server version */
	ast_log(LOG_DEBUG, "Read server version\n");
	if (!res) 
		res = ast_app_getdata(chan, NULL, serverver, sizeof(serverver) - 1, 0);
	if (res > 0)
		res = 0;
	ast_log(LOG_DEBUG, "server version: %s\n", serverver);
		
	if (res > 0)
		res = 0;

	if (!res)
		res = ast_safe_sleep(chan, 1000);
	/* Send test id */
	if (!res) 
		res = ast_dtmf_stream(chan, NULL, testid, 0);		
	if (!res) 
		res = ast_dtmf_stream(chan, NULL, "#", 0);		
	ast_log(LOG_DEBUG, "send test identifier: %s\n", testid);

	if ((res >=0) && (!ast_strlen_zero(testid))) {
		/* Make the directory to hold the test results in case it's not there */
		snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR);
		mkdir(fn, 0777);
		snprintf(fn, sizeof(fn), "%s/testresults/%s-client.txt", ast_config_AST_LOG_DIR, testid);
		if ((f = fopen(fn, "w+"))) {
			setlinebuf(f);
			fprintf(f, "CLIENTCHAN:    %s\n", chan->name);
			fprintf(f, "CLIENTTEST ID: %s\n", testid);
			fprintf(f, "ANSWER:        PASS\n");
			res = 0;
			
			if (!res) {
				/* Step 1: Wait for "1" */
				ast_log(LOG_DEBUG, "TestClient: 2.  Wait DTMF 1\n");
				res = ast_waitfordigit(chan, 3000);
				fprintf(f, "WAIT DTMF 1:   %s\n", (res != '1') ? "FAIL" : "PASS");
				if (res == '1')
					res = 0;
				else
					res = -1;
			}
			if (!res)
				res = ast_safe_sleep(chan, 1000);
			if (!res) {
				/* Step 2: Send "2" */
				ast_log(LOG_DEBUG, "TestClient: 2.  Send DTMF 2\n");
				res = ast_dtmf_stream(chan, NULL, "2", 0);
				fprintf(f, "SEND DTMF 2:   %s\n", (res < 0) ? "FAIL" : "PASS");
				if (res > 0)
					res = 0;
			}
			if (!res) {
				/* Step 3: Wait one second */
				ast_log(LOG_DEBUG, "TestClient: 3.  Wait one second\n");
				res = ast_safe_sleep(chan, 1000);
				fprintf(f, "WAIT 1 SEC:    %s\n", (res < 0) ? "FAIL" : "PASS");
				if (res > 0)
					res = 0;
			}			
			if (!res) {
				/* Step 4: Measure noise */
				ast_log(LOG_DEBUG, "TestClient: 4.  Measure noise\n");
				res = measurenoise(chan, 5000, "TestClient");
				fprintf(f, "MEASURENOISE:  %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
				if (res > 0)
					res = 0;
			}
			if (!res) {
				/* Step 5: Wait for "4" */
				ast_log(LOG_DEBUG, "TestClient: 5.  Wait DTMF 4\n");
				res = ast_waitfordigit(chan, 3000);
				fprintf(f, "WAIT DTMF 4:   %s\n", (res != '4') ? "FAIL" : "PASS");
				if (res == '4')
					res = 0;
				else
					res = -1;
			}
			if (!res) {
				/* Step 6: Transmit tone noise */
				ast_log(LOG_DEBUG, "TestClient: 6.  Transmit tone\n");
				res = sendnoise(chan, 6000);
				fprintf(f, "SENDTONE:      %s\n", (res < 0) ? "FAIL" : "PASS");
			}
			if (!res || (res == '5')) {
				/* Step 7: Wait for "5" */
				ast_log(LOG_DEBUG, "TestClient: 7.  Wait DTMF 5\n");
				if (!res)
					res = ast_waitfordigit(chan, 3000);
				fprintf(f, "WAIT DTMF 5:   %s\n", (res != '5') ? "FAIL" : "PASS");
				if (res == '5')
					res = 0;
				else
					res = -1;
			}
			if (!res) {
				/* Step 8: Wait one second */
				ast_log(LOG_DEBUG, "TestClient: 8.  Wait one second\n");
				res = ast_safe_sleep(chan, 1000);
				fprintf(f, "WAIT 1 SEC:    %s\n", (res < 0) ? "FAIL" : "PASS");
				if (res > 0)
					res = 0;
			}
			if (!res) {
				/* Step 9: Measure noise */
				ast_log(LOG_DEBUG, "TestClient: 6.  Measure tone\n");
				res = measurenoise(chan, 4000, "TestClient");
				fprintf(f, "MEASURETONE:   %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
				if (res > 0)
					res = 0;
			}
			if (!res) {
				/* Step 10: Send "7" */
				ast_log(LOG_DEBUG, "TestClient: 7.  Send DTMF 7\n");
				res = ast_dtmf_stream(chan, NULL, "7", 0);
				fprintf(f, "SEND DTMF 7:   %s\n", (res < 0) ? "FAIL" : "PASS");
				if (res > 0)
					res =0;
			}
			if (!res) {
				/* Step 11: Wait for "8" */
				ast_log(LOG_DEBUG, "TestClient: 11.  Wait DTMF 8\n");
				res = ast_waitfordigit(chan, 3000);
				fprintf(f, "WAIT DTMF 8:   %s\n", (res != '8') ? "FAIL" : "PASS");
				if (res == '8')
					res = 0;
				else
					res = -1;
			}
			if (!res) {
				/* Step 12: Hangup! */
				ast_log(LOG_DEBUG, "TestClient: 12.  Hangup\n");
			}

			ast_log(LOG_DEBUG, "-- TEST COMPLETE--\n");
			fprintf(f, "-- END TEST--\n");
			fclose(f);
			res = -1;
		} else
			res = -1;
	} else {
		ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", chan->name);
		res = -1;
	}
	LOCAL_USER_REMOVE(u);
	return res;
}
Example #11
0
static int testserver_exec(struct ast_channel *chan, void *data)
{
	struct localuser *u;
	int res = 0;
	char testid[80]="";
	char fn[80];
	FILE *f;
	LOCAL_USER_ADD(u);
	if (chan->_state != AST_STATE_UP)
		res = ast_answer(chan);
	/* Read version */
	ast_log(LOG_DEBUG, "Read client version\n");
	if (!res) 
		res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);
	if (res > 0)
		res = 0;
	ast_log(LOG_DEBUG, "client version: %s\n", testid);
	ast_log(LOG_DEBUG, "Transmit server version\n");
	res = ast_safe_sleep(chan, 1000);
	if (!res)
		res = ast_dtmf_stream(chan, NULL, "8378*1#", 0);
	if (res > 0)
		res = 0;

	if (!res) 
		res = ast_app_getdata(chan, NULL, testid, sizeof(testid) - 1, 0);		
	ast_log(LOG_DEBUG, "read test identifier: %s\n", testid);
	/* Check for sneakyness */
	if (strchr(testid, '/'))
		res = -1;
	if ((res >=0) && (!ast_strlen_zero(testid))) {
		/* Got a Test ID!  Whoo hoo! */
		/* Make the directory to hold the test results in case it's not there */
		snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR);
		mkdir(fn, 0777);
		snprintf(fn, sizeof(fn), "%s/testresults/%s-server.txt", ast_config_AST_LOG_DIR, testid);
		if ((f = fopen(fn, "w+"))) {
			setlinebuf(f);
			fprintf(f, "SERVERCHAN:    %s\n", chan->name);
			fprintf(f, "SERVERTEST ID: %s\n", testid);
			fprintf(f, "ANSWER:        PASS\n");
			ast_log(LOG_DEBUG, "Processing Test ID '%s'\n", testid);
			res = ast_safe_sleep(chan, 1000);
			if (!res) {
				/* Step 1: Send "1" */
				ast_log(LOG_DEBUG, "TestServer: 1.  Send DTMF 1\n");
				res = ast_dtmf_stream(chan, NULL, "1", 0);
				fprintf(f, "SEND DTMF 1:   %s\n", (res < 0) ? "FAIL" : "PASS");
				if (res > 0)
					res = 0;
			}
			if (!res) {
				/* Step 2: Wait for "2" */
				ast_log(LOG_DEBUG, "TestServer: 2.  Wait DTMF 2\n");
				res = ast_waitfordigit(chan, 3000);
				fprintf(f, "WAIT DTMF 2:   %s\n", (res != '2') ? "FAIL" : "PASS");
				if (res == '2')
					res = 0;
				else
					res = -1;
			}
			if (!res) {
				/* Step 3: Measure noise */
				ast_log(LOG_DEBUG, "TestServer: 3.  Measure noise\n");
				res = measurenoise(chan, 6000, "TestServer");
				fprintf(f, "MEASURENOISE:  %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
				if (res > 0)
					res = 0;
			}
			if (!res) {
				/* Step 4: Send "4" */
				ast_log(LOG_DEBUG, "TestServer: 4.  Send DTMF 4\n");
				res = ast_dtmf_stream(chan, NULL, "4", 0);
				fprintf(f, "SEND DTMF 4:   %s\n", (res < 0) ? "FAIL" : "PASS");
				if (res > 0)
					res = 0;
			}
		
			if (!res) {
				/* Step 5: Wait one second */
				ast_log(LOG_DEBUG, "TestServer: 5.  Wait one second\n");
				res = ast_safe_sleep(chan, 1000);
				fprintf(f, "WAIT 1 SEC:    %s\n", (res < 0) ? "FAIL" : "PASS");
				if (res > 0)
					res = 0;
			}
		
			if (!res) {
				/* Step 6: Measure noise */
				ast_log(LOG_DEBUG, "TestServer: 6.  Measure tone\n");
				res = measurenoise(chan, 4000, "TestServer");
				fprintf(f, "MEASURETONE:   %s (%d)\n", (res < 0) ? "FAIL" : "PASS", res);
				if (res > 0)
					res = 0;
			}

			if (!res) {
				/* Step 7: Send "5" */
				ast_log(LOG_DEBUG, "TestServer: 7.  Send DTMF 5\n");
				res = ast_dtmf_stream(chan, NULL, "5", 0);
				fprintf(f, "SEND DTMF 5:   %s\n", (res < 0) ? "FAIL" : "PASS");
				if (res > 0)
					res = 0;
			}

			if (!res) {
				/* Step 8: Transmit tone noise */
				ast_log(LOG_DEBUG, "TestServer: 8.  Transmit tone\n");
				res = sendnoise(chan, 6000);
				fprintf(f, "SENDTONE:      %s\n", (res < 0) ? "FAIL" : "PASS");
			}
		
			if (!res || (res == '7')) {
				/* Step 9: Wait for "7" */
				ast_log(LOG_DEBUG, "TestServer: 9.  Wait DTMF 7\n");
				if (!res)
					res = ast_waitfordigit(chan, 3000);
				fprintf(f, "WAIT DTMF 7:   %s\n", (res != '7') ? "FAIL" : "PASS");
				if (res == '7')
					res = 0;
				else
					res = -1;
			}
			if (!res)
				res = ast_safe_sleep(chan, 1000);
			if (!res) {
				/* Step 10: Send "8" */
				ast_log(LOG_DEBUG, "TestServer: 10.  Send DTMF 8\n");
				res = ast_dtmf_stream(chan, NULL, "8", 0);
				fprintf(f, "SEND DTMF 8:   %s\n", (res < 0) ? "FAIL" : "PASS");
				if (res > 0)
					res = 0;
			}
			if (!res) {
				/* Step 11: Wait for hangup to arrive! */
				ast_log(LOG_DEBUG, "TestServer: 11.  Waiting for hangup\n");
				res = ast_safe_sleep(chan, 10000);
				fprintf(f, "WAIT HANGUP:   %s\n", (res < 0) ? "PASS" : "FAIL");
			}

			ast_log(LOG_DEBUG, "-- TEST COMPLETE--\n");
			fprintf(f, "-- END TEST--\n");
			fclose(f);
			res = -1;
		} else
			res = -1;
	} else {
		ast_log(LOG_NOTICE, "Did not read a test ID on '%s'\n", chan->name);
		res = -1;
	}
	LOCAL_USER_REMOVE(u);
	return res;
}
static int controlplayback_exec(struct ast_channel *chan, void *data)
{
	int res = 0, priority_jump = 0;
	int skipms = 0;
	struct localuser *u;
	char *tmp;
	int argc;
	char *argv[8];
	enum arg_ids {
		arg_file = 0,
		arg_skip = 1,
		arg_fwd = 2,
		arg_rev = 3,
		arg_stop = 4,
		arg_pause = 5,
		arg_restart = 6,
		options = 7,
	};
	
	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
		return -1;
	}

	LOCAL_USER_ADD(u);
	
	tmp = ast_strdupa(data);
	memset(argv, 0, sizeof(argv));

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

	if (argc < 1) {
		ast_log(LOG_WARNING, "ControlPlayback requires an argument (filename)\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	skipms = argv[arg_skip] ? atoi(argv[arg_skip]) : 3000;
	if (!skipms)
		skipms = 3000;

	if (!argv[arg_fwd] || !is_on_phonepad(*argv[arg_fwd]))
		argv[arg_fwd] = "#";
	if (!argv[arg_rev] || !is_on_phonepad(*argv[arg_rev]))
		argv[arg_rev] = "*";
	if (argv[arg_stop] && !is_on_phonepad(*argv[arg_stop]))
		argv[arg_stop] = NULL;
	if (argv[arg_pause] && !is_on_phonepad(*argv[arg_pause]))
		argv[arg_pause] = NULL;
	if (argv[arg_restart] && !is_on_phonepad(*argv[arg_restart]))
		argv[arg_restart] = NULL;

	if (argv[options]) {
		if (strchr(argv[options], 'j'))
			priority_jump = 1;
	}

	res = ast_control_streamfile(chan, argv[arg_file], argv[arg_fwd], argv[arg_rev], argv[arg_stop], argv[arg_pause], argv[arg_restart], skipms);

	/* If we stopped on one of our stop keys, return 0  */
	if (argv[arg_stop] && strchr(argv[arg_stop], res)) {
		res = 0;
		pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "USERSTOPPED");
	} else {
		if (res < 0) {
			if (priority_jump || ast_opt_priority_jumping) {
				if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101)) {
					ast_log(LOG_WARNING, "ControlPlayback tried to jump to priority n+101 as requested, but priority didn't exist\n");
				}
			}
			res = 0;
			pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "ERROR");
		} else
			pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "SUCCESS");
	}

	LOCAL_USER_REMOVE(u);

	return res;
}
static int chanspy_exec(struct ast_channel *chan, void *data)
{
	struct localuser *u;
	struct ast_channel *peer=NULL, *prev=NULL;
	char name[AST_NAME_STRLEN],
		peer_name[AST_NAME_STRLEN + 5],
		*args,
		*ptr = NULL,
		*options = NULL,
		*spec = NULL,
		*argv[5],
		*mygroup = NULL,
		*recbase = NULL;
	int res = -1,
		volfactor = 0,
		silent = 0,
		argc = 0,
		bronly = 0,
		chosen = 0,
		count=0,
		waitms = 100,
		num = 0,
		oldrf = 0,
		oldwf = 0,
		fd = 0;
	struct ast_flags flags;
	signed char zero_volume = 0;

	if (!(args = ast_strdupa((char *)data))) {
		ast_log(LOG_ERROR, "Out of memory!\n");
		return -1;
	}

	LOCAL_USER_ADD(u);

	oldrf = chan->readformat;
	oldwf = chan->writeformat;
	if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) {
		ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}
	
	if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) {
		ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	ast_answer(chan);

	ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */

	if ((argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])))) {
		spec = argv[0];
		if ( argc > 1) {
			options = argv[1];
		}
		if (ast_strlen_zero(spec) || !strcmp(spec, "all")) {
			spec = NULL;
		}
	}
	
	if (options) {
		char *opts[OPT_ARG_ARRAY_SIZE];
		ast_app_parse_options(chanspy_opts, &flags, opts, options);
		if (ast_test_flag(&flags, OPTION_GROUP)) {
			mygroup = opts[OPT_ARG_GROUP];
		}
		if (ast_test_flag(&flags, OPTION_RECORD)) {
			if (!(recbase = opts[OPT_ARG_RECORD])) {
				recbase = "chanspy";
			}
		}
		silent = ast_test_flag(&flags, OPTION_QUIET);
		bronly = ast_test_flag(&flags, OPTION_BRIDGED);
		if (ast_test_flag(&flags, OPTION_VOLUME) && opts[OPT_ARG_VOLUME]) {
			int vol;

			if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &vol) != 1) || (vol > 4) || (vol < -4))
				ast_log(LOG_NOTICE, "Volume factor must be a number between -4 and 4\n");
			else
				volfactor = vol;
			}
	}
	else 
		ast_clear_flag(&flags, AST_FLAGS_ALL);

	if (recbase) {
		char filename[512];
		snprintf(filename,sizeof(filename),"%s/%s.%d.raw",ast_config_AST_MONITOR_DIR, recbase, (int)time(NULL));
		if ((fd = open(filename, O_CREAT | O_WRONLY, O_TRUNC, 0644)) <= 0) {
			ast_log(LOG_WARNING, "Cannot open %s for recording\n", filename);
			fd = 0;
		}
	}

	for(;;) {
		if (!silent) {
			res = ast_streamfile(chan, "beep", chan->language);
			if (!res)
				res = ast_waitstream(chan, "");
			if (res < 0) {
				ast_clear_flag(chan, AST_FLAG_SPYING);
				break;
			}
		}

		count = 0;
		res = ast_waitfordigit(chan, waitms);
		if (res < 0) {
			ast_clear_flag(chan, AST_FLAG_SPYING);
			break;
		}
				
		peer = local_channel_walk(NULL);
		prev=NULL;
		while(peer) {
			if (peer != chan) {
				char *group = NULL;
				int igrp = 1;

				if (peer == prev && !chosen) {
					break;
				}
				chosen = 0;
				group = pbx_builtin_getvar_helper(peer, "SPYGROUP");
				if (mygroup) {
					if (!group || strcmp(mygroup, group)) {
						igrp = 0;
					}
				}
				
				if (igrp && (!spec || ((strlen(spec) <= strlen(peer->name) &&
							!strncasecmp(peer->name, spec, strlen(spec)))))) {
					if (peer && (!bronly || ast_bridged_channel(peer)) &&
					    !ast_check_hangup(peer) && !ast_test_flag(peer, AST_FLAG_SPYING)) {
						int x = 0;
						strncpy(peer_name, "spy-", 5);
						strncpy(peer_name + strlen(peer_name), peer->name, AST_NAME_STRLEN);
						ptr = strchr(peer_name, '/');
						*ptr = '\0';
						ptr++;
						for (x = 0 ; x < strlen(peer_name) ; x++) {
							if (peer_name[x] == '/') {
								break;
							}
							peer_name[x] = tolower(peer_name[x]);
						}

						if (!silent) {
							if (ast_fileexists(peer_name, NULL, NULL) != -1) {
								res = ast_streamfile(chan, peer_name, chan->language);
								if (!res)
									res = ast_waitstream(chan, "");
								if (res)
									break;
							} else
								res = ast_say_character_str(chan, peer_name, "", chan->language);
							if ((num=atoi(ptr))) 
								ast_say_digits(chan, atoi(ptr), "", chan->language);
						}
						count++;
						prev = peer;
						res = channel_spy(chan, peer, &volfactor, fd);
						if (res == -1) {
							break;
						} else if (res > 1 && spec) {
							snprintf(name, AST_NAME_STRLEN, "%s/%d", spec, res);
							if ((peer = local_get_channel_begin_name(name))) {
								chosen = 1;
							}
							continue;
						}
					}
				}
			}
			if ((peer = local_channel_walk(peer)) == NULL) {
				break;
			}
		}
		waitms = count ? 100 : 5000;
	}
	

	if (fd > 0) {
		close(fd);
	}

	if (oldrf && ast_set_read_format(chan, oldrf) < 0) {
		ast_log(LOG_ERROR, "Could Not Set Read Format.\n");
	}
	
	if (oldwf && ast_set_write_format(chan, oldwf) < 0) {
		ast_log(LOG_ERROR, "Could Not Set Write Format.\n");
	}

	ast_clear_flag(chan, AST_FLAG_SPYING);

	ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0);

	ALL_DONE(u, res);
}
Example #14
0
static int ldap_exec(struct cw_channel *chan, int argc, char **argv)
{
	char result[2048];
	struct localuser *u;
	char *varname, *config, *keys = NULL, *key = NULL, *tail = NULL;
	char *result_conv;
	struct cw_config *cfg;

	int port = LDAP_PORT, version = LDAP_VERSION2, timeout = 10;
	char *temp, *host, *user, *pass, *base, *scope, *filter, *_filter, *attribute,
		 *convert_from = NULL, *convert_to = NULL;

	if (argc != 1) {
		cw_log(LOG_ERROR, "Syntax: %s\n", g_syntax);
		pbx_builtin_setvar_helper(chan, "LDAPSTATUS", "FAILURE");
		return 0;
	}

	LOCAL_USER_ADD(u);

	if (strchr(argv[0], '=')) {
		varname = strsep (&argv[0], "=");
		if (strchr(argv[0], '/')) {
			config = strsep(&argv[0], "/");
			keys = strsep(&argv[0], "\0");
			if (option_verbose > 2)
				cw_verbose(VERBOSE_PREFIX_3 "LDAPget: varname=%s, config-section=%s, keys=%s\n", varname, config, keys);
		} else {
			config = strsep(&argv[0], "\0");
			if (option_verbose > 2)
				cw_verbose(VERBOSE_PREFIX_3 "LDAPget: varname=%s, config-section=%s\n", varname, config);
		}
		if (!varname || !config) {
			cw_log(LOG_WARNING, "Ignoring; Syntax error in argument\n");
			pbx_builtin_setvar_helper(chan, "LDAPSTATUS", "FAILURE");
			return 0;
		}
	} else {
		cw_log(LOG_WARNING, "Ignoring, no parameters\n");
		pbx_builtin_setvar_helper(chan, "LDAPSTATUS", "FAILURE");
		return 0;
	}

	cfg = cw_config_load(LDAP_CONFIG);

	if (!cfg) {
		cw_log(LOG_WARNING, "No such configuration file %s\n", LDAP_CONFIG);
		return -1;
	}
	if (!(host = cw_variable_retrieve(cfg, config, "host"))) {
		host = "localhost";
	}
	if ((temp = cw_variable_retrieve(cfg, config, "port"))) {
		port = atoi(temp);
	}
	if ((temp = cw_variable_retrieve(cfg, config, "timeout"))) {
		timeout = atoi(temp);
	}
	if ((temp = cw_variable_retrieve(cfg, config, "version"))) {
		version = atoi(temp);
	}
	user = cw_variable_retrieve(cfg, config, "user");
	pass = cw_variable_retrieve(cfg, config, "pass");
	base = cw_variable_retrieve(cfg, config, "base");
	if (!base) base = "";
	base = replace_cw_vars(chan, base);
	if (!(scope = cw_variable_retrieve(cfg, config, "scope"))) {
		scope = "sub";
	}
	if (!(_filter = cw_variable_retrieve(cfg, config, "filter"))) {
		_filter = "(&(objectClass=person)(telephoneNumber=${CALLERIDNUM}))";
	}
	if (!(attribute = cw_variable_retrieve(cfg, config, "attribute"))) {
		attribute = "cn";
	}
	if ((temp = cw_variable_retrieve(cfg, config, "convert"))) {
		if (strchr(temp, ',')) {
			convert_from = strtrim(strsep(&temp, ","));
			convert_to = strtrim(strsep(&temp, "\0"));
		} else {
			cw_log(LOG_WARNING, "syntax error: convert = <source-charset>,<destination charset>\n");
		}
	}

	if (option_verbose > 3)
		cw_verbose (VERBOSE_PREFIX_4 "LDAPget: ldap://%s/%s?%s?%s?%s\n", host, base, attribute, scope, _filter);

	filter = replace_cw_vars(chan, _filter);
	if (option_verbose > 3)
		cw_verbose (VERBOSE_PREFIX_4 "LDAPget: %s\n", filter);

	if (keys && strstr(filter, "%s") != NULL) {
		filter = (char *)realloc(filter, (strlen(filter)+strlen(keys)+1)*sizeof(char));
		while((key = strsep(&keys, "|")) != NULL) {
			if ((tail = strstr(filter, "%s")) != NULL) {
				memmove(tail+strlen(key), tail+2, strlen(tail+2)+1);
				memcpy(tail, key, strlen(key));
			}
		}
	}

	if (option_verbose > 2)
		cw_verbose (VERBOSE_PREFIX_3 "LDAPget: ldap://%s/%s?%s?%s?%s\n", host, base, attribute, scope, filter);

	if (ldap_lookup(host, port, version, timeout, user, pass, base, scope, filter, attribute, result)) {

		if (convert_from) {
			if (option_verbose > 2)
				cw_verbose(VERBOSE_PREFIX_3 "LDAPget: convert: %s -> %s\n", convert_from, convert_to);
			result_conv = malloc(strlen(result) * 2);
			strconvert(convert_from, convert_to, result, result_conv);
			strcpy(result, result_conv);
			free(result_conv);
		}
		
		if (strcmp("CALLERIDNAME", varname)==0) {
			cw_set_callerid(chan, NULL, result, NULL);
			if (option_verbose > 2)
				cw_verbose (VERBOSE_PREFIX_3 "LDAPget: set CIDNAME to \"%s\"\n", result);
		} else {
			if (option_verbose > 2)
				cw_verbose (VERBOSE_PREFIX_3 "LDAPget: set %s='%s'\n", varname, result);
			pbx_builtin_setvar_helper(chan, varname, result);
		}
		
	} else {
		pbx_builtin_setvar_helper(chan, "LDAPSTATUS", "FAILURE");
		return 0;
	}
	cw_config_destroy(cfg);
	free(filter);
	free(base);
	pbx_builtin_setvar_helper(chan, "LDAPSTATUS", "SUCCESS");

	LOCAL_USER_REMOVE(u);
	return 0;
}
Example #15
0
static int mp3_exec(struct ast_channel *chan, void *data)
{
	int res=0;
	struct localuser *u;
	int fds[2];
	int ms = -1;
	int pid = -1;
	int owriteformat;
	int timeout = 2000;
	struct timeval next;
	struct ast_frame *f;
	struct myframe {
		struct ast_frame f;
		char offset[AST_FRIENDLY_OFFSET];
		short frdata[160];
	} myf;
	
	if (ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "MP3 Playback requires an argument (filename)\n");
		return -1;
	}

	LOCAL_USER_ADD(u);

	if (pipe(fds)) {
		ast_log(LOG_WARNING, "Unable to create pipe\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}
	
	ast_stopstream(chan);

	owriteformat = chan->writeformat;
	res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
	if (res < 0) {
		ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}
	
	res = mp3play((char *)data, fds[1]);
	if (!strncasecmp((char *)data, "http://", 7)) {
		timeout = 10000;
	}
	/* Wait 1000 ms first */
	next = ast_tvnow();
	next.tv_sec += 1;
	if (res >= 0) {
		pid = res;
		/* Order is important -- there's almost always going to be mp3...  we want to prioritize the
		   user */
		for (;;) {
			ms = ast_tvdiff_ms(next, ast_tvnow());
			if (ms <= 0) {
				res = timed_read(fds[0], myf.frdata, sizeof(myf.frdata), timeout);
				if (res > 0) {
					myf.f.frametype = AST_FRAME_VOICE;
					myf.f.subclass = AST_FORMAT_SLINEAR;
					myf.f.datalen = res;
					myf.f.samples = res / 2;
					myf.f.mallocd = 0;
					myf.f.offset = AST_FRIENDLY_OFFSET;
					myf.f.src = __PRETTY_FUNCTION__;
					myf.f.delivery.tv_sec = 0;
					myf.f.delivery.tv_usec = 0;
					myf.f.data = myf.frdata;
					if (ast_write(chan, &myf.f) < 0) {
						res = -1;
						break;
					}
				} else {
					ast_log(LOG_DEBUG, "No more mp3\n");
					res = 0;
					break;
				}
				next = ast_tvadd(next, ast_samp2tv(myf.f.samples, 8000));
			} else {
				ms = ast_waitfor(chan, ms);
				if (ms < 0) {
					ast_log(LOG_DEBUG, "Hangup detected\n");
					res = -1;
					break;
				}
				if (ms) {
					f = ast_read(chan);
					if (!f) {
						ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
						res = -1;
						break;
					}
					if (f->frametype == AST_FRAME_DTMF) {
						ast_log(LOG_DEBUG, "User pressed a key\n");
						ast_frfree(f);
						res = 0;
						break;
					}
					ast_frfree(f);
				} 
			}
		}
	}
	close(fds[0]);
	close(fds[1]);
	
	if (pid > -1)
		kill(pid, SIGKILL);
	if (!res && owriteformat)
		ast_set_write_format(chan, owriteformat);

	LOCAL_USER_REMOVE(u);
	
	return res;
}
static int conf_exec(struct ast_channel *chan, void *data)
{
	int res=-1;
	struct localuser *u;
	int confflags = 0;
	int confno = 0;
	char confstr[80] = "", *tmp = NULL;
	struct ast_channel *tempchan = NULL, *lastchan = NULL,*ichan = NULL;
	struct ast_frame *f;
	char *mygroup;
	char *desired_group;
	int input=0,search_group=0;
	
	LOCAL_USER_ADD(u);
	
	if (chan->_state != AST_STATE_UP)
		ast_answer(chan);
	
	desired_group = ast_strdupa((char *) data);
	if(!ast_strlen_zero(desired_group)) {
		ast_verbose(VERBOSE_PREFIX_3 "Scanning for group %s\n", desired_group);
		search_group = 1;
	}

	for (;;) {
		if (ast_waitfor(chan, 100) < 0)
			break;
		
		f = ast_read(chan);
		if (!f)
			break;
		if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) {
			ast_frfree(f);
			break;
		}
		ast_frfree(f);
		ichan = NULL;
		if(input) {
			ichan = get_zap_channel_locked(input);
			input = 0;
		}
		
		tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan);
		
		if ( !tempchan && !lastchan )
			break;
		
		if (tempchan && search_group) {
			if((mygroup = pbx_builtin_getvar_helper(tempchan, "GROUP")) && (!strcmp(mygroup, desired_group))) {
				ast_verbose(VERBOSE_PREFIX_3 "Found Matching Channel %s in group %s\n", tempchan->name, desired_group);
			} else {
				ast_mutex_unlock(&tempchan->lock);
				lastchan = tempchan;
				continue;
			}
		}
		if ( tempchan && tempchan->type && (!strcmp(tempchan->type, "Zap")) && (tempchan != chan) ) {
			ast_verbose(VERBOSE_PREFIX_3 "Zap channel %s is in-use, monitoring...\n", tempchan->name);
			ast_copy_string(confstr, tempchan->name, sizeof(confstr));
			ast_mutex_unlock(&tempchan->lock);
			if ((tmp = strchr(confstr,'-'))) {
				*tmp = '\0';
			}
			confno = atoi(strchr(confstr,'/') + 1);
			ast_stopstream(chan);
			ast_say_number(chan, confno, AST_DIGIT_ANY, chan->language, (char *) NULL);
			res = conf_run(chan, confno, confflags);
			if (res<0) break;
			input = res;
		} else if (tempchan)
			ast_mutex_unlock(&tempchan->lock);
		lastchan = tempchan;
	}
	LOCAL_USER_REMOVE(u);
	return res;
}
Example #17
0
static int record_exec(struct cw_channel *chan, int argc, char **argv)
{
	int res = 0;
	int count = 0;
	int percentflag = 0;
	char *ext = NULL;
	int i = 0;
	char tmp[256];

	struct cw_filestream *s = '\0';
	struct localuser *u;
	struct cw_frame *f = NULL;
	
	struct cw_dsp *sildet = NULL;   	/* silence detector dsp */
	int totalsilence = 0;
	int dspsilence = 0;
	int silence = 0;		/* amount of silence to allow */
	int gotsilence = 0;		/* did we timeout for silence? */
	int maxduration = 0;		/* max duration of recording in milliseconds */
	int gottimeout = 0;		/* did we timeout for maxduration exceeded? */
	int option_skip = 0;
	int option_noanswer = 0;
	int option_append = 0;
	int terminator = '#';
	int option_quiet = 0;
	int rfmt = 0;
	int flags;
	
	if (argc < 1 || argc > 4 || !argv[0][0]) {
		cw_log(LOG_ERROR, "Syntax: %s\n", record_syntax);
		return -1;
	}

	LOCAL_USER_ADD(u);

	if (strstr(argv[0], "%d"))
		percentflag = 1;
	ext = strrchr(argv[0], '.'); /* to support filename with a . in the filename, not format */
	if (!ext)
		ext = strchr(argv[0], ':');
	if (ext) {
		*ext = '\0';
		ext++;
	}

	if (!ext) {
		cw_log(LOG_WARNING, "No extension specified to filename!\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	if (argc > 1) {
		silence = atoi(argv[1]);
		if (silence > 0)
			silence *= 1000;
		else if (silence < 0)
			silence = 0;
	}
	
	if (argc > 2) {
		maxduration = atoi(argv[2]);
		if (maxduration > 0)
			maxduration *= 1000;
		else if (maxduration < 0)
			maxduration = 0;
	}

	if (argc > 3) {
		/* Retain backwards compatibility with old style options */
		if (!strcasecmp(argv[3], "skip"))
			option_skip = 1;
		else if (!strcasecmp(argv[3], "noanswer"))
			option_noanswer = 1;
		else {
			if (strchr(argv[3], 's'))
				option_skip = 1;
			if (strchr(argv[3], 'n'))
				option_noanswer = 1;
			if (strchr(argv[3], 'a'))
				option_append = 1;
			if (strchr(argv[3], 't'))
				terminator = '*';
			if (strchr(argv[3], 'q'))
				option_quiet = 1;
		}
	}
	
	/* done parsing */
	
	/* these are to allow the use of the %d in the config file for a wild card of sort to
	  create a new file with the inputed name scheme */
	if (percentflag) {
		char *piece[100];
		int pieces;

		/* Separate each piece out by the format specifier */
		pieces = cw_separate_app_args(argv[0], '%', arraysize(piece), piece);

		do {
			int tmplen;
			/* First piece has no leading percent, so it's copied verbatim */
			cw_copy_string(tmp, piece[0], sizeof(tmp));
			tmplen = strlen(tmp);
			for (i = 1; i < pieces; i++) {
				if (piece[i][0] == 'd') {
					/* Substitute the count */
					snprintf(tmp + tmplen, sizeof(tmp) - tmplen, "%d", count);
					tmplen += strlen(tmp + tmplen);
				} else if (tmplen + 2 < sizeof(tmp)) {
					/* Unknown format specifier - just copy it verbatim */
					tmp[tmplen++] = '%';
					tmp[tmplen++] = piece[i][0];
				}
				/* Copy the remaining portion of the piece */
				cw_copy_string(tmp + tmplen, &(piece[i][1]), sizeof(tmp) - tmplen);
			}
			count++;
		} while ( cw_fileexists(tmp, ext, chan->language) != -1 );
		pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
	} else
		strncpy(tmp, argv[0], sizeof(tmp)-1);
	/* end of routine mentioned */
	
	
	
	if (chan->_state != CW_STATE_UP) {
		if (option_skip) {
			/* At the user's option, skip if the line is not up */
			LOCAL_USER_REMOVE(u);
			return 0;
		} else if (!option_noanswer) {
			/* Otherwise answer unless we're supposed to record while on-hook */
			res = cw_answer(chan);
		}
	}
	
	if (!res) {
	
		if (!option_quiet) {
			/* Some code to play a nice little beep to signify the start of the record operation */
			res = cw_streamfile(chan, "beep", chan->language);
			if (!res) {
				res = cw_waitstream(chan, "");
			} else {
				cw_log(LOG_WARNING, "cw_streamfile failed on %s\n", chan->name);
			}
			cw_stopstream(chan);
		}
		
		/* The end of beep code.  Now the recording starts */
		
		if (silence > 0) {
			rfmt = chan->readformat;
			res = cw_set_read_format(chan, CW_FORMAT_SLINEAR);
			if (res < 0) {
				cw_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
				LOCAL_USER_REMOVE(u);
				return -1;
			}
			sildet = cw_dsp_new();
			if (!sildet) {
				cw_log(LOG_WARNING, "Unable to create silence detector :(\n");
				LOCAL_USER_REMOVE(u);
				return -1;
			}
			cw_dsp_set_threshold(sildet, 256);
		} 
		
		
		flags = option_append ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
		s = cw_writefile( tmp, ext, NULL, flags , 0, 0644);
		
		if (s) {
			int waitres;

			/* Request a video update */
			cw_indicate(chan, CW_CONTROL_VIDUPDATE);

			if (maxduration <= 0)
				maxduration = -1;
			
			while ((waitres = cw_waitfor(chan, maxduration)) > -1) {
				if (maxduration > 0) {
					if (waitres == 0) {
						gottimeout = 1;
						break;
					}
					maxduration = waitres;
  				}
				
				f = cw_read(chan);
				if (!f) {
					res = -1;
					break;
				}
				if (f->frametype == CW_FRAME_VOICE) {
					res = cw_writestream(s, f);
					if (res) {
						cw_log(LOG_WARNING, "Problem writing frame\n");
						cw_fr_free(f);
						break;
					}
					
					if (silence > 0) {
						dspsilence = 0;
						cw_dsp_silence(sildet, f, &dspsilence);
						if (dspsilence) {
							totalsilence = dspsilence;
						} else {
							totalsilence = 0;
						}
						if (totalsilence > silence) {
							/* Ended happily with silence */
							cw_fr_free(f);
							gotsilence = 1;
							break;
						}
					}
				}
				if (f->frametype == CW_FRAME_VIDEO) {
					res = cw_writestream(s, f);
					if (res) {
						cw_log(LOG_WARNING, "Problem writing frame\n");
						cw_fr_free(f);
						break;
					}
				}
				if ((f->frametype == CW_FRAME_DTMF) &&
					(f->subclass == terminator)) {
					cw_fr_free(f);
					break;
				}
				cw_fr_free(f);
			}
			if (!f) {
				cw_log(LOG_DEBUG, "Got hangup\n");
				res = -1;
			}
			
			if (gotsilence) {
				cw_stream_rewind(s, silence-1000);
				cw_truncstream(s);
			} else if (!gottimeout) {
				/* Strip off the last 1/4 second of it */
				cw_stream_rewind(s, 250);
				cw_truncstream(s);
			}
			cw_closestream(s);
		} else
			cw_log(LOG_WARNING, "Could not create file %s\n", tmp);
	} else
		cw_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
	
	if ((silence > 0) && rfmt) {
		res = cw_set_read_format(chan, rfmt);
		if (res)
			cw_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
		if (sildet)
			cw_dsp_free(sildet);
	}

	LOCAL_USER_REMOVE(u);

	return res;
}
Example #18
0
static int visdn_ppp_exec(struct cw_channel *chan, int argc, char **argv)
{
	struct visdn_chan *visdn_chan;
	const char **nargv;
	struct localuser *u;
	struct cw_frame *f;
	int res=-1;

	LOCAL_USER_ADD(u);

	if (chan->_state != CW_STATE_UP)
		cw_answer(chan);

	cw_mutex_lock(&chan->lock);

	if (strcmp(chan->type, "VISDN")) {
		cw_log(LOG_WARNING,
			"Only VISDN channels may be connected to"
			" this application\n");

		cw_mutex_unlock(&chan->lock);
		return -1;
	}

	visdn_chan = chan->tech_pvt;

	if (!strlen(visdn_chan->visdn_chanid)) {
		cw_log(LOG_WARNING,
			"vISDN crossconnector channel ID not present\n");
		cw_mutex_unlock(&chan->lock);
		return -1;
	}

	nargv = alloca((2 + argc + 3 + 1) * sizeof(nargv[0]));
	nargv[0] = PPP_EXEC;
	nargv[1] = "nodetach";
	memcpy(nargv + 2, argc, argv * sizeof(argv[0]));
	nargv[2 + argc + 0] = "plugin";
	nargv[2 + argc + 1] = "visdn.so";
	nargv[2 + argc + 2] = visdn_chan->visdn_chanid;
	nargv[2 + argc + 3] = NULL;

	cw_mutex_unlock(&chan->lock);

#if 0
	int i;
	for (i=0;i<argc;i++) {
		cw_log(LOG_NOTICE, "Arg %d: %s\n", i, argv[i]);
	}
#endif

	signal(SIGCHLD, SIG_DFL);

	pid_t pid = spawn_ppp(chan, nargv);
	if (pid < 0) {
		cw_log(LOG_WARNING, "Failed to spawn pppd\n");
		return -1;
	}

	while(cw_waitfor(chan, -1) > -1) {

		f = cw_read(chan);
		if (!f) {
			cw_log(LOG_NOTICE,
				"Channel '%s' hungup."
				" Signalling PPP at %d to die...\n",
				chan->name, pid);

			kill(pid, SIGTERM);

			break;
		}

		cw_fr_free(f);

		int status;
		res = wait4(pid, &status, WNOHANG, NULL);
		if (res < 0) {
			cw_log(LOG_WARNING,
				"wait4 returned %d: %s\n",
				res, strerror(errno));

			break;
		} else if (res > 0) {
			if (option_verbose > 2) {
				if (WIFEXITED(status)) {
					cw_verbose(VERBOSE_PREFIX_3
						"PPP on %s terminated with status %d\n",
						chan->name, WEXITSTATUS(status));
				} else if (WIFSIGNALED(status)) {
					cw_verbose(VERBOSE_PREFIX_3
						"PPP on %s terminated with signal %d\n", 
						chan->name, WTERMSIG(status));
				} else {
					cw_verbose(VERBOSE_PREFIX_3
						"PPP on %s terminated weirdly.\n", chan->name);
				}
			}

			break;
		}
	}

	LOCAL_USER_REMOVE(u);
	return res;
}
Example #19
0
static int ices_exec(struct ast_channel *chan, void *data)
{
	int res=0;
	struct localuser *u;
	int fds[2];
	int ms = -1;
	int pid = -1;
	int flags;
	int oreadformat;
	struct timeval last;
	struct ast_frame *f;
	char filename[256]="";
	char *c;
	last.tv_usec = 0;
	last.tv_sec = 0;
	if (!data || !strlen(data)) {
		ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
		return -1;
	}
	if (pipe(fds)) {
		ast_log(LOG_WARNING, "Unable to create pipe\n");
		return -1;
	}
	flags = fcntl(fds[1], F_GETFL);
	fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
	
	LOCAL_USER_ADD(u);
	ast_stopstream(chan);

	if (chan->_state != AST_STATE_UP)
		res = ast_answer(chan);
		
	if (res) {
		close(fds[0]);
		close(fds[1]);
		ast_log(LOG_WARNING, "Answer failed!\n");
		return -1;
	}

	oreadformat = chan->readformat;
	res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
	if (res < 0) {
		close(fds[0]);
		close(fds[1]);
		ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
		return -1;
	}
	if (((char *)data)[0] == '/')
		strncpy(filename, (char *)data, sizeof(filename) - 1);
	else
		snprintf(filename, sizeof(filename), "%s/%s", (char *)ast_config_AST_CONFIG_DIR, (char *)data);
	/* Placeholder for options */		
	c = strchr(filename, '|');
	if (c)
		*c = '\0';	
	res = icesencode(filename, fds[0]);
	close(fds[0]);
	if (res >= 0) {
		pid = res;
		for (;;) {
			/* Wait for audio, and stream */
			ms = ast_waitfor(chan, -1);
			if (ms < 0) {
				ast_log(LOG_DEBUG, "Hangup detected\n");
				res = -1;
				break;
			}
			f = ast_read(chan);
			if (!f) {
				ast_log(LOG_DEBUG, "Null frame == hangup() detected\n");
				res = -1;
				break;
			}
			if (f->frametype == AST_FRAME_VOICE) {
				res = write(fds[1], f->data, f->datalen);
				if (res < 0) {
					if (errno != EAGAIN) {
						ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
						res = -1;
						break;
					}
				}
			}
			ast_frfree(f);
		}
	}
	close(fds[1]);
	LOCAL_USER_REMOVE(u);
	if (pid > -1)
		kill(pid, SIGKILL);
	if (!res && oreadformat)
		ast_set_read_format(chan, oreadformat);
	return res;
}
Example #20
0
static int fax_exec(struct cw_channel *chan, int argc, char **argv)
{
    fax_state_t fax;
    t38_terminal_state_t t38;
    t30_state_t *t30;

    const char *file_name;
    int res = 0;
    int ready;

    int calling_party;
    int verbose;
    
    struct localuser *u;

    int original_read_fmt;
    int original_write_fmt;

    /* Basic initial checkings */

    if (chan == NULL)
    {
        cw_log(LOG_WARNING, "Fax transmit channel is NULL. Giving up.\n");
        return -1;
    }

    /* Make sure they are initialized to zero */
    memset(&fax, 0, sizeof(fax));
    memset(&t38, 0, sizeof(t38));

    if (argc < 1  ||  argc > 4)
    {
        cw_log(LOG_ERROR, "Syntax: %s\n", fax_syntax);
        return -1;
    }

    /* Resetting channel variables related to T38 */
    
    pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", "");
    pbx_builtin_setvar_helper(chan, "FAXPAGES", "");
    pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", "");
    pbx_builtin_setvar_helper(chan, "FAXBITRATE", "");
    pbx_builtin_setvar_helper(chan, "PHASEESTATUS", "");
    pbx_builtin_setvar_helper(chan, "PHASEESTRING", "");

    /* Parsing parameters */
    calling_party = FALSE;
    verbose = FALSE;

    file_name = argv[0];

    while (argv++, --argc)
    {
        if (strcmp(argv[0], "caller") == 0)
        {
            calling_party = TRUE;
        }
        else if (strcmp(argv[0], "debug") == 0)
        {
            verbose = TRUE;
        }
    }

    /* Done parsing */

    LOCAL_USER_ADD(u);

    if (chan->_state != CW_STATE_UP)
    {
        /* Shouldn't need this, but checking to see if channel is already answered
         * Theoretically the PBX should already have answered before running the app */
        res = cw_answer(chan);
        if (!res)
        {
            cw_log(LOG_DEBUG, "Could not answer channel '%s'\n", chan->name);
            //LOCAL_USER_REMOVE(u);
            //return res;
        }
    }

    /* Setting read and write formats */
    
    original_read_fmt = chan->readformat;
    if (original_read_fmt != CW_FORMAT_SLINEAR)
    {
        res = cw_set_read_format(chan, CW_FORMAT_SLINEAR);
        if (res < 0)
        {
            cw_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
            LOCAL_USER_REMOVE(u);
            return -1;
        }
    }

    original_write_fmt = chan->writeformat;
    if (original_write_fmt != CW_FORMAT_SLINEAR)
    {
        res = cw_set_write_format(chan, CW_FORMAT_SLINEAR);
        if (res < 0)
        {
            cw_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
            res = cw_set_read_format(chan, original_read_fmt);
            if (res)
                cw_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
            LOCAL_USER_REMOVE(u);
            return -1;
        }
    }

    /* This is the main loop */
    ready = TRUE;        
    if (chan->t38_status == T38_NEGOTIATED)
        t30 = t38_terminal_get_t30_state(&t38);
    else
        t30 = fax_get_t30_state(&fax);
    while (ready  &&  ready_to_talk(chan))
    {
        if (ready  &&  chan->t38_status != T38_NEGOTIATED)
        {
            t30 = fax_get_t30_state(&fax);
            ready = fax_audio(chan, &fax, file_name, calling_party, verbose);
        }
        if (ready  &&  chan->t38_status == T38_NEGOTIATED)
        {
            t30 = t38_terminal_get_t30_state(&t38);
            ready = fax_t38(chan, &t38, file_name, calling_party, verbose);
        }
        if (chan->t38_status != T38_NEGOTIATING)
            ready = FALSE; // 1 loop is enough. This could be useful if we want to turn from udptl to RTP later.
    }

    t30_terminate(t30);

    fax_release(&fax);
    t38_terminal_release(&t38);

    /* Restoring initial channel formats. */
    if (original_read_fmt != CW_FORMAT_SLINEAR)
    {
        if ((res = cw_set_read_format(chan, original_read_fmt)))
            cw_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
    }
    if (original_write_fmt != CW_FORMAT_SLINEAR)
    {
        if ((res = cw_set_write_format(chan, original_write_fmt)))
            cw_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
    }

    return ready;
}
static int pickup_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	struct localuser *u = NULL;
	struct ast_channel *origin = NULL, *target = NULL;
	char *tmp = NULL, *exten = NULL, *context = NULL, *rest=data;
	char workspace[256] = "";
	const char *tmp2 = NULL;

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

	LOCAL_USER_ADD(u);
	
	while (!target && (exten = rest) ) {
		res = 0;
		rest = strchr(exten, '&');
		if (rest)
			*rest++ = 0;

		/* Get the extension and context if present */
		context = strchr(exten, '@');
		if (context)
			*context++ = '\0';

		/* If the context is the pickup mark, iterate through all channels finding the right origin one */
		if (!strcmp(context, PICKUPMARK)) {
			while ((origin = ast_channel_walk_locked(origin))) {
				if (origin) {
					tmp2 = pbx_builtin_getvar_helper(origin, PICKUPMARK);
					if (tmp2 && !strcmp(tmp2, exten))
						break;
					ast_mutex_unlock(&origin->lock);
				}
			}
		} else {
			/* Use the classic mode of searching */
			origin = ast_get_channel_by_exten_locked(exten, context);
		}

		if (origin) {
			ast_cdr_getvar(origin->cdr, "dstchannel", &tmp, workspace,
					sizeof(workspace), 0, 0);
			if (tmp) {
				/* We have a possible channel... now we need to find it! */
				target = ast_get_channel_by_name_locked(tmp);
			} else {
				ast_log(LOG_NOTICE, "No target channel found for %s.\n", exten);
				res = -1;
			}
			ast_mutex_unlock(&origin->lock);

		} else {
			ast_log(LOG_DEBUG, "No originating channel found.\n");
		}

		if (res)
			continue;

		if (target && (!target->pbx) && ((target->_state == AST_STATE_RINGING) || (target->_state == AST_STATE_RING) ) ) {
			ast_log(LOG_DEBUG, "Call pickup on chan '%s' by '%s'\n", target->name,
					chan->name);
			res = ast_answer(chan);
			if (res) {
				ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
				res = -1;
				break;
			}
			res = ast_queue_control(chan, AST_CONTROL_ANSWER);
			if (res) {
				ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n",
						chan->name);
				res = -1;
				break;
			}
			res = ast_channel_masquerade(target, chan);
			if (res) {
				ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
				res = -1;
				break;
			}
		} else {
			ast_log(LOG_NOTICE, "No call pickup possible for %s...\n", exten);
			res = -1;
		}
	}
	if (target) 
		ast_mutex_unlock(&target->lock);
	
	LOCAL_USER_REMOVE(u);

	return res;
}
Example #22
0
static int auth_exec(struct ast_channel *chan, void *data)
{
	int res=0;
	int retries;
	struct localuser *u;
	char password[256]="";
	char passwd[256];
	char *opts;
	char *prompt;
	if (!data || ast_strlen_zero(data)) {
		ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n");
		return -1;
	}
	LOCAL_USER_ADD(u);
	if (chan->_state != AST_STATE_UP) {
		res = ast_answer(chan);
		if (res) {
			LOCAL_USER_REMOVE(u);
			return -1;
		}
	}
	strncpy(password, data, sizeof(password) - 1);
	opts=strchr(password, '|');
	if (opts) {
		*opts = 0;
		opts++;
	} else
		opts = "";
	/* Start asking for password */
	prompt = "agent-pass";
	for (retries = 0; retries < 3; retries++) {
		res = ast_app_getdata(chan, prompt, passwd, sizeof(passwd) - 2, 0);
		if (res < 0)
			break;
		res = 0;
		if (password[0] == '/') {
			if (strchr(opts, 'd')) {
				char tmp[256];
				/* Compare against a database key */
				if (!ast_db_get(password + 1, passwd, tmp, sizeof(tmp))) {
					/* It's a good password */
					if (strchr(opts, 'r')) {
						ast_db_del(password + 1, passwd);
					}
					break;
				}
			} else {
				/* Compare against a file */
				FILE *f;
				f = fopen(password, "r");
				if (f) {
					char buf[256] = "";
					while(!feof(f)) {
						fgets(buf, sizeof(buf), f);
						if (!feof(f) && !ast_strlen_zero(buf)) {
							buf[strlen(buf) - 1] = '\0';
							if (!ast_strlen_zero(buf) && !strcmp(passwd, buf))
								break;
						}
					}
					fclose(f);
					if (!ast_strlen_zero(buf) && !strcmp(passwd, buf))
						break;
				} else 
					ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno));
			}
		} else {
			/* Compare against a fixed password */
			if (!strcmp(passwd, password)) 
				break;
		}
		prompt="auth-incorrect";
	}
	if ((retries < 3) && !res) {
		if (strchr(opts, 'a')) 
			ast_cdr_setaccount(chan, passwd);
		res = ast_streamfile(chan, "auth-thankyou", chan->language);
		if (!res)
			res = ast_waitstream(chan, "");
	} else {
		if (!res)
			res = ast_streamfile(chan, "vm-goodbye", chan->language);
		if (!res)
			res = ast_waitstream(chan, "");
		res = -1;
	}
	LOCAL_USER_REMOVE(u);
	return res;
}
Example #23
0
static int _while_exec(struct cw_channel *chan, int argc, char **argv, int end)
{
	int res=0;
	struct localuser *u;
	char *while_pri = NULL;
	char *goto_str = NULL, *my_name = NULL;
	char *label = NULL;
	char varname[VAR_SIZE], end_varname[VAR_SIZE];
	const char *prefix = "WHILE";
	size_t size=0;
	int used_index_i = -1, x=0;
	char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0";

	if (!end && argc != 1) {
		cw_log(LOG_ERROR, "Syntax: %s\n", while_syntax);
		return -1;
	}

	if (!chan) {
		/* huh ? */
		return -1;
	}

	LOCAL_USER_ADD(u);

	/* dont want run away loops if the chan isn't even up
	   this is up for debate since it slows things down a tad ......
	*/
	if (cw_waitfordigit(chan,1) < 0)
		ALL_DONE(u,-1);


	for (x=0;;x++) {
		if (get_index(chan, prefix, x)) {
			used_index_i = x;
		} else 
			break;
	}
	
	snprintf(used_index, VAR_SIZE, "%d", used_index_i);
	snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1);
	
	size = strlen(chan->context) + strlen(chan->exten) + 32;
	my_name = alloca(size);
	snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority);
	
	if (cw_strlen_zero(label)) {
		if (end) 
			label = used_index;
		else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
			label = new_index;
			pbx_builtin_setvar_helper(chan, my_name, label);
		}
		
	}
	
	snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
	while_pri = pbx_builtin_getvar_helper(chan, varname);
	
	if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
		snprintf(end_varname, VAR_SIZE, "END_%s", varname);
	}
	

	if (!end && !cw_true(argv[0])) {
		/* Condition Met (clean up helper vars) */
		pbx_builtin_setvar_helper(chan, varname, NULL);
		pbx_builtin_setvar_helper(chan, my_name, NULL);
		snprintf(end_varname, VAR_SIZE, "END_%s", varname);
		if ((goto_str=pbx_builtin_getvar_helper(chan, end_varname))) {
			pbx_builtin_setvar_helper(chan, end_varname, NULL);
			cw_parseable_goto(chan, goto_str);
		} else {
			int pri = find_matching_endwhile(chan);
			if (pri > 0) {
				if (option_verbose > 2)
					cw_verbose(VERBOSE_PREFIX_3 "Jumping to priority %d\n", pri);
				chan->priority = pri;
			} else {
				cw_log(LOG_WARNING, "Couldn't find matching EndWhile? (While at %s@%s priority %d)\n", chan->context, chan->exten, chan->priority);
			}
		}
		ALL_DONE(u,res);
	}

	if (!end && !while_pri) {
		size = strlen(chan->context) + strlen(chan->exten) + 32;
		goto_str = alloca(size);
		snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority);
		pbx_builtin_setvar_helper(chan, varname, goto_str);
	} 

	else if (end && while_pri) {
		/* END of loop */
		snprintf(end_varname, VAR_SIZE, "END_%s", varname);
		if (! pbx_builtin_getvar_helper(chan, end_varname)) {
			size = strlen(chan->context) + strlen(chan->exten) + 32;
			goto_str = alloca(size);
			snprintf(goto_str, size, "%s,%s,%d", chan->context, chan->exten, chan->priority+1);
			pbx_builtin_setvar_helper(chan, end_varname, goto_str);
		}
		cw_parseable_goto(chan, while_pri);
	}
	



	ALL_DONE(u, res);
}
static int record_exec(struct ast_channel *chan, void *data)
{
	int res = 0;
	int count = 0;
	int percentflag = 0;
	char *filename, *ext = NULL, *silstr, *maxstr, *options;
	char *vdata, *p;
	int i = 0;
	char tmp[256];

	struct ast_filestream *s = '\0';
	struct localuser *u;
	struct ast_frame *f = NULL;
	
	struct ast_dsp *sildet = NULL;   	/* silence detector dsp */
	int totalsilence = 0;
	int dspsilence = 0;
	int silence = 0;		/* amount of silence to allow */
	int gotsilence = 0;		/* did we timeout for silence? */
	int maxduration = 0;		/* max duration of recording in milliseconds */
	int gottimeout = 0;		/* did we timeout for maxduration exceeded? */
	int option_skip = 0;
	int option_noanswer = 0;
	int option_append = 0;
	int terminator = '#';
	int option_quiet = 0;
	int rfmt = 0;
	int flags;
	int waitres;
	struct ast_silence_generator *silgen = NULL;
	
	/* The next few lines of code parse out the filename and header from the input string */
	if (ast_strlen_zero(data)) { /* no data implies no filename or anything is present */
		ast_log(LOG_WARNING, "Record requires an argument (filename)\n");
		return -1;
	}

	LOCAL_USER_ADD(u);

	/* Yay for strsep being easy */
	vdata = ast_strdupa(data);
	if (!vdata) {
		ast_log(LOG_ERROR, "Out of memory\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}

	p = vdata;
	filename = strsep(&p, "|");
	silstr = strsep(&p, "|");
	maxstr = strsep(&p, "|");	
	options = strsep(&p, "|");
	
	if (filename) {
		if (strstr(filename, "%d"))
			percentflag = 1;
		ext = strrchr(filename, '.'); /* to support filename with a . in the filename, not format */
		if (!ext)
			ext = strchr(filename, ':');
		if (ext) {
			*ext = '\0';
			ext++;
		}
	}
	if (!ext) {
		ast_log(LOG_WARNING, "No extension specified to filename!\n");
		LOCAL_USER_REMOVE(u);
		return -1;
	}
	if (silstr) {
		if ((sscanf(silstr, "%d", &i) == 1) && (i > -1)) {
			silence = i * 1000;
		} else if (!ast_strlen_zero(silstr)) {
			ast_log(LOG_WARNING, "'%s' is not a valid silence duration\n", silstr);
		}
	}
	
	if (maxstr) {
		if ((sscanf(maxstr, "%d", &i) == 1) && (i > -1))
			/* Convert duration to milliseconds */
			maxduration = i * 1000;
		else if (!ast_strlen_zero(maxstr))
			ast_log(LOG_WARNING, "'%s' is not a valid maximum duration\n", maxstr);
	}
	if (options) {
		/* Retain backwards compatibility with old style options */
		if (!strcasecmp(options, "skip"))
			option_skip = 1;
		else if (!strcasecmp(options, "noanswer"))
			option_noanswer = 1;
		else {
			if (strchr(options, 's'))
				option_skip = 1;
			if (strchr(options, 'n'))
				option_noanswer = 1;
			if (strchr(options, 'a'))
				option_append = 1;
			if (strchr(options, 't'))
				terminator = '*';
			if (strchr(options, 'q'))
				option_quiet = 1;
		}
	}
	
	/* done parsing */
	
	/* these are to allow the use of the %d in the config file for a wild card of sort to
	  create a new file with the inputed name scheme */
	if (percentflag) {
		do {
			snprintf(tmp, sizeof(tmp), filename, count);
			count++;
		} while ( ast_fileexists(tmp, ext, chan->language) != -1 );
		pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
	} else
		strncpy(tmp, filename, sizeof(tmp)-1);
	/* end of routine mentioned */
	
	
	
	if (chan->_state != AST_STATE_UP) {
		if (option_skip) {
			/* At the user's option, skip if the line is not up */
			LOCAL_USER_REMOVE(u);
			return 0;
		} else if (!option_noanswer) {
			/* Otherwise answer unless we're supposed to record while on-hook */
			res = ast_answer(chan);
		}
	}
	
	if (res) {
		ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
		goto out;
	}
	
	if (!option_quiet) {
		/* Some code to play a nice little beep to signify the start of the record operation */
		res = ast_streamfile(chan, "beep", chan->language);
		if (!res) {
			res = ast_waitstream(chan, "");
		} else {
			ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", chan->name);
		}
		ast_stopstream(chan);
	}
		
	/* The end of beep code.  Now the recording starts */
		
	if (silence > 0) {
		rfmt = chan->readformat;
		res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
		if (res < 0) {
			ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
			LOCAL_USER_REMOVE(u);
			return -1;
		}
		sildet = ast_dsp_new();
		if (!sildet) {
			ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
			LOCAL_USER_REMOVE(u);
			return -1;
		}
		ast_dsp_set_threshold(sildet, 256);
	} 
		
		
	flags = option_append ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
	s = ast_writefile( tmp, ext, NULL, flags , 0, 0644);
		
	if (!s) {
		ast_log(LOG_WARNING, "Could not create file %s\n", filename);
		goto out;
	}

	if (option_transmit_silence_during_record)
		silgen = ast_channel_start_silence_generator(chan);
	
	/* Request a video update */
	ast_indicate(chan, AST_CONTROL_VIDUPDATE);
	
	if (maxduration <= 0)
		maxduration = -1;
	
	while ((waitres = ast_waitfor(chan, maxduration)) > -1) {
		if (maxduration > 0) {
			if (waitres == 0) {
				gottimeout = 1;
				break;
			}
			maxduration = waitres;
		}
		
		f = ast_read(chan);
		if (!f) {
			res = -1;
			break;
		}
		if (f->frametype == AST_FRAME_VOICE) {
			res = ast_writestream(s, f);
			
			if (res) {
				ast_log(LOG_WARNING, "Problem writing frame\n");
				ast_frfree(f);
				break;
			}
			
			if (silence > 0) {
				dspsilence = 0;
				ast_dsp_silence(sildet, f, &dspsilence);
				if (dspsilence) {
					totalsilence = dspsilence;
				} else {
					totalsilence = 0;
				}
				if (totalsilence > silence) {
					/* Ended happily with silence */
					ast_frfree(f);
					gotsilence = 1;
					break;
				}
			}
		} else if (f->frametype == AST_FRAME_VIDEO) {
			res = ast_writestream(s, f);
			
			if (res) {
				ast_log(LOG_WARNING, "Problem writing frame\n");
				ast_frfree(f);
				break;
			}
		} else if ((f->frametype == AST_FRAME_DTMF) &&
		    (f->subclass == terminator)) {
			ast_frfree(f);
			break;
		}
		ast_frfree(f);
	}
	if (!f) {
		ast_log(LOG_DEBUG, "Got hangup\n");
		res = -1;
	}
			
	if (gotsilence) {
		ast_stream_rewind(s, silence-1000);
		ast_truncstream(s);
	} else if (!gottimeout) {
		/* Strip off the last 1/4 second of it */
		ast_stream_rewind(s, 250);
		ast_truncstream(s);
	}
	ast_closestream(s);

	if (silgen)
		ast_channel_stop_silence_generator(chan, silgen);
	
 out:
	if ((silence > 0) && rfmt) {
		res = ast_set_read_format(chan, rfmt);
		if (res)
			ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
		if (sildet)
			ast_dsp_free(sildet);
	}

	LOCAL_USER_REMOVE(u);

	return res;
}