/*! * \internal * \brief Check if Monitor needs to be started on a channel. * \since 12.0.0 * * \param chan The bridge considers this channel the caller. * \param peer The bridge considers this channel the callee. * * \return Nothing */ static void bridge_check_monitor(struct ast_channel *chan, struct ast_channel *peer) { const char *value; const char *monitor_args = NULL; struct ast_channel *monitor_chan = NULL; ast_channel_lock(chan); value = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"); if (!ast_strlen_zero(value)) { monitor_args = ast_strdupa(value); monitor_chan = chan; } ast_channel_unlock(chan); if (!monitor_chan) { ast_channel_lock(peer); value = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"); if (!ast_strlen_zero(value)) { monitor_args = ast_strdupa(value); monitor_chan = peer; } ast_channel_unlock(peer); } if (monitor_chan) { struct ast_app *monitor_app; monitor_app = pbx_findapp("Monitor"); if (monitor_app) { pbx_exec(monitor_chan, monitor_app, monitor_args); } } }
static int fax_set_common(struct cw_channel *chan, t30_state_t *t30, const char *file, int calling_party, int verbose) { char *x; x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"); if (x && x[0]) t30_set_tx_ident(t30, x); x = pbx_builtin_getvar_helper(chan, "LOCALSUBADDRESS"); if (x && x[0]) t30_set_tx_sub_address(t30, x); x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"); if (x && x[0]) t30_set_tx_page_header_info(t30, x); t30_set_rx_file(t30, file, -1); x = pbx_builtin_getvar_helper(chan, "FAX_DISABLE_V17"); if (x && x[0]) t30_set_supported_modems(t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER); x = pbx_builtin_getvar_helper(chan, "FAX_DISABLE_ECM"); if (x && x[0]) { t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION); cw_log(LOG_DEBUG, "Disabling ECM mode\n"); } else { t30_set_ecm_capability(t30, TRUE); t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION); } t30_set_supported_image_sizes(t30, T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH | T30_SUPPORT_UNLIMITED_LENGTH | T30_SUPPORT_215MM_WIDTH | T30_SUPPORT_255MM_WIDTH | T30_SUPPORT_303MM_WIDTH); t30_set_supported_resolutions(t30, T30_SUPPORT_STANDARD_RESOLUTION | T30_SUPPORT_FINE_RESOLUTION | T30_SUPPORT_SUPERFINE_RESOLUTION | T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION); //t30_set_phase_b_handler(t30, phase_b_handler, chan); t30_set_phase_d_handler(t30, phase_d_handler, chan); t30_set_phase_e_handler(t30, phase_e_handler, chan); return 0; }
static void set_local_info(t30_state_t *state, fax_session *s) { const char *x; x = pbx_builtin_getvar_helper(s->chan, "LOCALSTATIONID"); if (!ast_strlen_zero(x)) t30_set_tx_ident(state, x); x = pbx_builtin_getvar_helper(s->chan, "LOCALHEADERINFO"); if (!ast_strlen_zero(x)) t30_set_tx_page_header_info(state, x); }
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; }
static void ast_eivr_getvariable(struct ast_channel *chan, char *data, char *outbuf, int outbuflen) { /* original input data: "G,var1,var2," */ /* data passed as "data": "var1,var2" */ char *inbuf, *variable; const char *value; int j; struct ast_str *newstring = ast_str_alloca(outbuflen); outbuf[0] = '\0'; for (j = 1, inbuf = data; ; j++) { variable = strsep(&inbuf, ","); if (variable == NULL) { int outstrlen = strlen(outbuf); if (outstrlen && outbuf[outstrlen - 1] == ',') { outbuf[outstrlen - 1] = 0; } break; } ast_channel_lock(chan); if (!(value = pbx_builtin_getvar_helper(chan, variable))) { value = ""; } ast_str_append(&newstring, 0, "%s=%s,", variable, value); ast_channel_unlock(chan); ast_copy_string(outbuf, ast_str_buffer(newstring), outbuflen); } }
int cw_app_group_match_get_count(char *groupmatch, char *category) { regex_t regexbuf; struct cw_channel *chan; int count = 0; char *test; char cat[80]; char *s; if (cw_strlen_zero(groupmatch)) return 0; /* if regex compilation fails, return zero matches */ if (regcomp(®exbuf, groupmatch, REG_EXTENDED | REG_NOSUB)) return 0; s = (!cw_strlen_zero(category)) ? category : GROUP_CATEGORY_PREFIX; cw_copy_string(cat, s, sizeof(cat)); chan = NULL; while ((chan = cw_channel_walk_locked(chan)) != NULL) { test = pbx_builtin_getvar_helper(chan, cat); if (test && !regexec(®exbuf, test, 0, NULL, 0)) count++; cw_mutex_unlock(&chan->lock); } regfree(®exbuf); return count; }
char *replace_cw_vars(struct cw_channel *chan, const char *_string) { char *var_start, *var_end, *key, *value, *string; int begin, end; if (!_string) return ""; string = (char *)malloc((strlen(_string)+1)*sizeof(char)); memcpy(string, _string, strlen(_string)+1); while((var_start = strstr(string, "${")) && (var_end = strchr(var_start,'}'))) { begin = strlen(string)-strlen(var_start); end = strlen(string)-strlen(var_end); key = (char *)alloca((end-begin-1)*sizeof(char)); memcpy(key, var_start+2, end-begin-2); key[end-begin-2] = '\0'; value = pbx_builtin_getvar_helper(chan, key); if (value) { string = (char *)realloc(string, (strlen(string)-(end-begin+1)+strlen(value)+1)*sizeof(char)); memmove(var_start+strlen(value), var_end+1, strlen(var_end+1)+1); memcpy(var_start, value, strlen(value)); } else { memmove(var_start, var_end+1, strlen(var_end+1)+1); } } return string; }
static int checkMax(struct ast_channel *chan, struct roomdetails *dtmfmatch) { int res=0; struct ast_app *app; char getvar[30]="AstVar"; char roomno[30]=""; char maxusers[30]=""; char currentusers[30]=""; char prompt[50]=""; char arg[255]=""; strcpy(maxusers,dtmfmatch->maxusers); strcpy(roomno,dtmfmatch->roomno); strcat(arg,roomno); strcat(arg,","); strcat(arg,getvar); if(!(app = pbx_findapp(ConfAppCount))) { ast_log(LOG_WARNING, "Invalid participant count application: %s\n", ConfAppCount); return -1; } res = pbx_exec(chan, app, arg); strcpy(currentusers, pbx_builtin_getvar_helper(chan, getvar)); if(atoi(currentusers) < atoi(maxusers)){ ast_log(LOG_NOTICE, "Currentusers: %i\n", atoi(currentusers)); if(atoi(currentusers)>0){ strcpy(prompt,"conf-thereare"); if (!ast_streamfile(chan, "conf-thereare", chan->language)){ res = ast_waitstream(chan,""); ast_stopstream(chan); if (!ast_say_number(chan, (atoi(currentusers)), AST_DIGIT_ANY, chan->language, (char *) NULL)){ res = ast_waitstream(chan,""); ast_stopstream(chan); } if (!ast_streamfile(chan, "conf-otherinparty", chan->language)){ res = ast_waitstream(chan,""); ast_stopstream(chan); } } } res=1; } else{ ast_log(LOG_NOTICE, "Maximum users exeeded, Current users in room: %s\n",currentusers); strcpy(prompt, "conf-locked"); if (!ast_streamfile(chan, prompt, chan->language)){ res = ast_waitstream(chan,""); ast_stopstream(chan); } res=-1; } return res; }
static int global_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len) { const char *var = pbx_builtin_getvar_helper(NULL, data); *buf = '\0'; if (var) ast_copy_string(buf, var, len); return 0; }
static int mcd_write( struct ast_channel *chan, const char *cmd, char *parse, const char *value ) { memcached_return_t rc; memcached_st *mcd = memcached_pool_fetch(mcdpool, &to, &rc); if (rc) { ast_log(LOG_WARNING, "mcd_write: memcached pool error: %d\n", rc); return 0; } char *key = (char *)ast_malloc(MEMCACHED_MAX_KEY); unsigned int timeout = mcdttl; mcd_set_operation_result(chan, MEMCACHED_SUCCESS); // the app argument is the key to set if (ast_strlen_zero(parse)) { ast_log(LOG_WARNING, "MCD() requires argument (key)\n"); mcd_set_operation_result(chan, MEMCACHED_ARGUMENT_NEEDED); free(key); return 0; } strcpy(key, parse); ast_log(LOG_DEBUG, "setting value for key: %s=%s\n", key, value); const char *ttlval = pbx_builtin_getvar_helper(chan, "MCDTTL"); if (ttlval) { timeout = atoi(ttlval); if ((timeout == 0) && (strcmp(ttlval, "0") != 0)) { ast_log(LOG_WARNING, "dialplan variable MCDTTL=%s (not numeric), will use time-to-live value in the config file\n", ttlval); timeout = mcdttl; } } ast_log(LOG_DEBUG, "timeout: %d\n", timeout); memcached_return_t mcdret = MEMCACHED_FAILURE; mcdret = memcached_set(mcd, key, strlen(key), value, strlen(value), (time_t)timeout, (uint32_t)0 ); if (mcdret) ast_log(LOG_WARNING, "memcached_%s() error %d: %s\n", cmd, mcdret, memcached_strerror(mcd, mcdret) ); mcd_set_operation_result(chan, mcdret); free(key); memcached_pool_release(mcdpool, mcd); return 0; }
static int return_exec(struct ast_channel *chan, void *data) { char *label = pbx_builtin_getvar_helper(chan, STACKVAR); if (ast_strlen_zero(label)) { ast_log(LOG_ERROR, "Return without Gosub: stack is empty\n"); return -1; } else if (ast_parseable_goto(chan, label)) { ast_log(LOG_WARNING, "No next statement after Gosub?\n"); return -1; } pbx_builtin_setvar_helper(chan, STACKVAR, NULL); return 0; }
static int find_by_mark(void *obj, void *arg, void *data, int flags) { struct ast_channel *target = obj;/*!< Potential pickup target */ const char *mark = data; const char *tmp; ast_channel_lock(target); tmp = pbx_builtin_getvar_helper(target, PICKUPMARK); if (tmp && !strcasecmp(tmp, mark) && ast_can_pickup(target)) { /* Return with the channel still locked on purpose */ return CMP_MATCH | CMP_STOP; } ast_channel_unlock(target); return 0; }
static void macro_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan) { int i; char varname[10]; pbx_builtin_setvar_helper(new_chan, "MACRO_DEPTH", "0"); pbx_builtin_setvar_helper(new_chan, "MACRO_CONTEXT", NULL); pbx_builtin_setvar_helper(new_chan, "MACRO_EXTEN", NULL); pbx_builtin_setvar_helper(new_chan, "MACRO_PRIORITY", NULL); pbx_builtin_setvar_helper(new_chan, "MACRO_OFFSET", NULL); for (i = 1; i < 100; i++) { snprintf(varname, sizeof(varname), "ARG%d", i); while (pbx_builtin_getvar_helper(new_chan, varname)) { /* Kill all levels of arguments */ pbx_builtin_setvar_helper(new_chan, varname, NULL); } } }
static void set_touch_variable(enum set_touch_variables_res *res, struct ast_channel *chan, const char *var_name, char **touch) { const char *c_touch; if (*res == SET_TOUCH_ALLOC_FAILURE) { return; } c_touch = pbx_builtin_getvar_helper(chan, var_name); if (!ast_strlen_zero(c_touch)) { *touch = ast_strdup(c_touch); if (!*touch) { *res = SET_TOUCH_ALLOC_FAILURE; } else { *res = SET_TOUCH_SUCCESS; } } }
/* Attempt to pick up specified mark */ static int pickup_by_mark(struct ast_channel *chan, char *mark) { int res = -1; const char *tmp = NULL; struct ast_channel *target = NULL; while ((target = ast_channel_walk_locked(target))) { if ((tmp = pbx_builtin_getvar_helper(target, PICKUPMARK)) && !strcasecmp(tmp, mark) && can_pickup(target)) { res = pickup_do(chan, target); ast_channel_unlock(target); break; } ast_channel_unlock(target); } return res; }
int cw_app_group_get_count(char *group, char *category) { struct cw_channel *chan; int count = 0; char *test; char cat[80]; char *s; if (cw_strlen_zero(group)) return 0; s = (!cw_strlen_zero(category)) ? category : GROUP_CATEGORY_PREFIX; cw_copy_string(cat, s, sizeof(cat)); chan = NULL; while ((chan = cw_channel_walk_locked(chan)) != NULL) { test = pbx_builtin_getvar_helper(chan, cat); if (test && !strcasecmp(test, group)) count++; cw_mutex_unlock(&chan->lock); } return count; }
/*! * \brief Receive Ademco ContactID or other format Data String * * \param chan Asterisk Channel * \param ehead Pointer to events list * \param signalling_type Expected signalling type for the message * \param no_checksum Should we calculate checksum for the message * * \retval 0 success * \retval -1 failure */ static int receive_ademco_event(struct ast_channel *chan, event_node_t **ehead, char *signalling_type, int *no_checksum) { int res = 0; const char *limit; char event[17]; event_node_t *enew, *elp; int got_some_digits = 0; int events_received = 0; int ack_retries = 0; int limit_retries = 0; int expected_length = sizeof(event) - 1; database_increment("calls-received"); /* Wait for first event */ ast_verb(4, "AlarmReceiver: Waiting for first event from panel...\n"); while (res >= 0) { int digits_received = 0; res = 0; if (log_individual_events) { sprintf(signalling_type, "%s", UNKNOWN_FORMAT); expected_length = 16; *no_checksum = 0; } if (got_some_digits == 0) { /* Send ACK tone sequence */ ast_verb(4, "AlarmReceiver: Sending 1400Hz 100ms burst (ACK)\n"); res = send_tone_burst(chan, "1400", 100, 0); if (!res) { ast_verb(4, "AlarmReceiver: Sending 2300Hz 100ms burst (ACK)\n"); res = send_tone_burst(chan, "2300", 100, 100); } } if (res) { return -1; } res = receive_dtmf_digits(chan, event, sizeof(event), expected_length, &digits_received); if (res < 0) { if (events_received == 0) { /* Hangup with no events received should be logged in the DB */ database_increment("no-events-received"); ast_verb(4, "AlarmReceiver: No events received!\n"); } else { if (ack_retries) { database_increment("ack-retries"); ast_verb(4, "AlarmReceiver: ACK retries during this call: %d\n", ack_retries); } } ast_verb(4, "AlarmReceiver: App exiting...\n"); break; } if (!strcmp(signalling_type, UNKNOWN_FORMAT) && digits_received > 5) { expected_length = ademco_detect_format(signalling_type, event, no_checksum); if (res > 0) { if (digits_received == expected_length) { res = limit_retries = 0; } else if (digits_received == expected_length - 1 && (!strcmp(signalling_type, ADEMCO_EXPRESS_4_2) || !strcmp(signalling_type, ADEMCO_EXPRESS_4_1))) { /* ADEMCO EXPRESS without checksum */ res = limit_retries = 0; expected_length--; *no_checksum = 1; ast_verb(4, "AlarmMonitoring: Skipping checksum for format %s.\n", signalling_type); ast_debug(1, "AlarmMonitoring: Skipping checksum for format %s.\n", signalling_type); } } } ast_channel_lock(chan); limit = pbx_builtin_getvar_helper(chan, "ALARMRECEIVER_CALL_LIMIT"); if (!ast_strlen_zero(limit)) { if (ast_tvdiff_ms(ast_tvnow(), call_start_time) > atoi(limit)) { ast_channel_unlock(chan); return -1; } } limit = pbx_builtin_getvar_helper(chan, "ALARMRECEIVER_RETRIES_LIMIT"); ast_channel_unlock(chan); if (!ast_strlen_zero(limit)) { if (limit_retries + 1 >= atoi(limit)) { return -1; } } if (res) { /* Didn't get all of the digits */ ast_verb(2, "AlarmReceiver: Incomplete string: %s, trying again...\n", event); limit_retries++; if (!events_received && strcmp(signalling_type, UNKNOWN_FORMAT)) { sprintf(signalling_type, "%s", UNKNOWN_FORMAT); expected_length = sizeof(event) - 1; } if (!got_some_digits) { got_some_digits = (!ast_strlen_zero(event)) ? 1 : 0; ack_retries++; } continue; } got_some_digits = 1; ast_verb(2, "AlarmReceiver: Received Event %s\n", event); ast_debug(1, "AlarmReceiver: Received event: %s\n", event); /* Calculate checksum */ if (!(*no_checksum) && ademco_verify_checksum(event, expected_length)) { database_increment("checksum-errors"); ast_verb(2, "AlarmReceiver: Nonzero checksum\n"); ast_debug(1, "AlarmReceiver: Nonzero checksum\n"); continue; } /* Check the message type for correctness */ if (ademco_check_valid(signalling_type, event)) { database_increment("format-errors"); ast_verb(2, "AlarmReceiver: Wrong message type\n"); ast_debug(1, "AlarmReceiver: Wrong message type\n"); continue; } events_received++; /* Queue the Event */ if (!(enew = ast_calloc(1, sizeof(*enew)))) { return -1; } enew->next = NULL; ast_copy_string(enew->data, event, sizeof(enew->data)); /* Insert event onto end of list */ if (*ehead == NULL) { *ehead = enew; } else { for (elp = *ehead; elp->next != NULL; elp = elp->next) { ; } elp->next = enew; } /* Let the user have the option of logging the single event before sending the kissoff tone */ if (log_individual_events && log_events(chan, signalling_type, enew, *no_checksum)) { return -1; } /* Send the kissoff tone (1400 Hz, 900 ms, after 200ms delay) */ if (send_tone_burst(chan, "1400", 900, 200)) { return -1; } /* If audio call follows, exit alarm receiver app */ if (!strcmp(signalling_type, ADEMCO_CONTACT_ID) && !strncmp(event + 7, ADEMCO_AUDIO_CALL_NEXT, 3)) { ast_verb(4, "AlarmReceiver: App exiting... Audio call next!\n"); return 0; } } return res; }
static int conf_do_originate(struct cw_conf_member *member, char *ext) { int res; pthread_t th; pthread_attr_t attr; struct fast_originate_helper *fast = malloc(sizeof(struct fast_originate_helper)); char dst[80]=""; char appdata[80]=""; char *var; if (!fast) { res = -1; } else { memset(fast, 0, sizeof(struct fast_originate_helper)); if ( (var = pbx_builtin_getvar_helper(member->chan, "NCONF_OUTBOUND_TIMEOUT")) ) { fast->timeout = atoi(var) * 1000; } else fast->timeout = 30000; strcat(dst,ext); strcat(dst,"@"); if ( (var = pbx_builtin_getvar_helper(member->chan, "NCONF_OUTBOUND_CONTEXT")) ) strcat(dst,var); else strcat(dst,member->chan->context); strcat(appdata,member->id); strcat(appdata,"/"); if ( (var = pbx_builtin_getvar_helper(member->chan, "NCONF_OUTBOUND_PARAMS")) ) strcat(appdata,var); else { strcat(appdata,"Sdq"); #if ENABLE_VAD strcat(appdata,"V"); #endif } cw_copy_string( fast->tech, "Local", sizeof(fast->tech) ); cw_copy_string( fast->data, dst, sizeof(fast->data) ); cw_copy_string( fast->app, APP_CONFERENCE_NAME, sizeof(fast->app) ); cw_copy_string( fast->appdata, appdata, sizeof(fast->appdata) ); if ( (var = pbx_builtin_getvar_helper(member->chan, "NCONF_OUTBOUND_CID_NAME")) ) cw_copy_string( fast->cid_name, var, sizeof(fast->cid_name) ); else cw_copy_string( fast->cid_name,"NavyConference",sizeof(fast->cid_name) ); if ( (var = pbx_builtin_getvar_helper(member->chan, "NCONF_OUTBOUND_CID_NUM")) ) cw_copy_string( fast->cid_num, var,sizeof(fast->cid_num) ); else cw_copy_string( fast->cid_num, member->id,sizeof(fast->cid_num) ); cw_copy_string( fast->context, "internal", sizeof(fast->context) ); cw_copy_string( fast->exten, ext, sizeof(fast->exten) ); fast->priority = 1; fast->vars=NULL; /**/ fast->frommember=member; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); if (cw_pthread_create(&th, &attr, fast_originate, fast)) { free(fast); res = -1; } else { res = 0; } } cw_mutex_unlock(&member->chan->lock); cw_conf_member_genactivate( member ) ; return res; }
/* Stop monitoring a channel */ int ast_monitor_stop(struct ast_channel *chan, int need_lock) { int delfiles = 0; LOCK_IF_NEEDED(chan, need_lock); if (chan->monitor) { char filename[ FILENAME_MAX ]; if (chan->monitor->read_stream) { ast_closestream(chan->monitor->read_stream); } if (chan->monitor->write_stream) { ast_closestream(chan->monitor->write_stream); } if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) { if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) { snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base); if (ast_fileexists(filename, NULL, NULL) > 0) { ast_filedelete(filename, NULL); } ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format); } else { ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename); } if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) { snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base); if (ast_fileexists(filename, NULL, NULL) > 0) { ast_filedelete(filename, NULL); } ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format); } else { ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename); } } if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) { char tmp[1024]; char tmp2[1024]; char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format; char *name = chan->monitor->filename_base; int directory = strchr(name, '/') ? 1 : 0; char *dir = directory ? "" : ast_config_AST_MONITOR_DIR; const char *execute, *execute_args; /* Set the execute application */ execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC"); if (ast_strlen_zero(execute)) { execute = "nice -n 19 soxmix"; delfiles = 1; } execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS"); if (ast_strlen_zero(execute_args)) { execute_args = ""; } snprintf(tmp, sizeof(tmp), "%s \"%s/%s-in.%s\" \"%s/%s-out.%s\" \"%s/%s.%s\" %s &", execute, dir, name, format, dir, name, format, dir, name, format,execute_args); if (delfiles) { snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s/%s-\"* ) &",tmp, dir ,name); /* remove legs when done mixing */ ast_copy_string(tmp, tmp2, sizeof(tmp)); } ast_log(LOG_DEBUG,"monitor executing %s\n",tmp); if (ast_safe_system(tmp) == -1) ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp); } free(chan->monitor->format); free(chan->monitor); chan->monitor = NULL; } UNLOCK_IF_NEEDED(chan, need_lock); return 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 common_exec(struct ast_channel *chan, struct ast_flags *flags, int volfactor, const int fd, struct spy_dtmf_options *user_options, const char *mygroup, const char *myenforced, const char *spec, const char *exten, const char *context, const char *mailbox, const char *name_context) { char nameprefix[AST_NAME_STRLEN]; char peer_name[AST_NAME_STRLEN + 5]; char exitcontext[AST_MAX_CONTEXT] = ""; signed char zero_volume = 0; int waitms; int res; char *ptr; int num; int num_spyed_upon = 1; struct ast_channel_iterator *iter = NULL; if (ast_test_flag(flags, OPTION_EXIT)) { const char *c; ast_channel_lock(chan); if ((c = pbx_builtin_getvar_helper(chan, "SPY_EXIT_CONTEXT"))) { ast_copy_string(exitcontext, c, sizeof(exitcontext)); } else if (!ast_strlen_zero(chan->macrocontext)) { ast_copy_string(exitcontext, chan->macrocontext, sizeof(exitcontext)); } else { ast_copy_string(exitcontext, chan->context, sizeof(exitcontext)); } ast_channel_unlock(chan); } if (chan->_state != AST_STATE_UP) ast_answer(chan); ast_set_flag(chan, AST_FLAG_SPYING); /* so nobody can spy on us while we are spying */ waitms = 100; for (;;) { struct ast_autochan *autochan = NULL, *next_autochan = NULL; struct ast_channel *prev = NULL; if (!ast_test_flag(flags, OPTION_QUIET) && num_spyed_upon) { res = ast_streamfile(chan, "beep", chan->language); if (!res) res = ast_waitstream(chan, ""); else if (res < 0) { ast_clear_flag(chan, AST_FLAG_SPYING); break; } if (!ast_strlen_zero(exitcontext)) { char tmp[2]; tmp[0] = res; tmp[1] = '\0'; if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) goto exit; else ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext); } } /* Set up the iterator we'll be using during this call */ if (!ast_strlen_zero(spec)) { iter = ast_channel_iterator_by_name_new(spec, strlen(spec)); } else if (!ast_strlen_zero(exten)) { iter = ast_channel_iterator_by_exten_new(exten, context); } else { iter = ast_channel_iterator_all_new(); } if (!iter) { return -1; } res = ast_waitfordigit(chan, waitms); if (res < 0) { ast_clear_flag(chan, AST_FLAG_SPYING); break; } if (!ast_strlen_zero(exitcontext)) { char tmp[2]; tmp[0] = res; tmp[1] = '\0'; if (!ast_goto_if_exists(chan, exitcontext, tmp, 1)) goto exit; else ast_debug(2, "Exit by single digit did not work in chanspy. Extension %s does not exist in context %s\n", tmp, exitcontext); } /* reset for the next loop around, unless overridden later */ waitms = 100; num_spyed_upon = 0; for (autochan = next_channel(iter, autochan, chan); autochan; prev = autochan->chan, ast_autochan_destroy(autochan), autochan = next_autochan ? next_autochan : next_channel(iter, autochan, chan), next_autochan = NULL) { int igrp = !mygroup; int ienf = !myenforced; char *s; if (autochan->chan == prev) { ast_autochan_destroy(autochan); break; } if (ast_check_hangup(chan)) { ast_autochan_destroy(autochan); break; } if (ast_test_flag(flags, OPTION_BRIDGED) && !ast_bridged_channel(autochan->chan)) { continue; } if (ast_check_hangup(autochan->chan) || ast_test_flag(autochan->chan, AST_FLAG_SPYING)) { continue; } if (mygroup) { int num_groups = 0; int num_mygroups = 0; char dup_group[512]; char dup_mygroup[512]; char *groups[NUM_SPYGROUPS]; char *mygroups[NUM_SPYGROUPS]; const char *group = NULL; int x; int y; ast_copy_string(dup_mygroup, mygroup, sizeof(dup_mygroup)); num_mygroups = ast_app_separate_args(dup_mygroup, ':', mygroups, ARRAY_LEN(mygroups)); /* Before dahdi scan was part of chanspy, it would use the "GROUP" variable * rather than "SPYGROUP", this check is done to preserve expected behavior */ if (ast_test_flag(flags, OPTION_DAHDI_SCAN)) { group = pbx_builtin_getvar_helper(autochan->chan, "GROUP"); } else { group = pbx_builtin_getvar_helper(autochan->chan, "SPYGROUP"); } if (!ast_strlen_zero(group)) { ast_copy_string(dup_group, group, sizeof(dup_group)); num_groups = ast_app_separate_args(dup_group, ':', groups, ARRAY_LEN(groups)); } for (y = 0; y < num_mygroups; y++) { for (x = 0; x < num_groups; x++) { if (!strcmp(mygroups[y], groups[x])) { igrp = 1; break; } } } } if (!igrp) { continue; } if (myenforced) { char ext[AST_CHANNEL_NAME + 3]; char buffer[512]; char *end; snprintf(buffer, sizeof(buffer) - 1, ":%s:", myenforced); ast_copy_string(ext + 1, autochan->chan->name, sizeof(ext) - 1); if ((end = strchr(ext, '-'))) { *end++ = ':'; *end = '\0'; } ext[0] = ':'; if (strcasestr(buffer, ext)) { ienf = 1; } } if (!ienf) { continue; } strcpy(peer_name, "spy-"); strncat(peer_name, autochan->chan->name, AST_NAME_STRLEN - 4 - 1); ptr = strchr(peer_name, '/'); *ptr++ = '\0'; ptr = strsep(&ptr, "-"); for (s = peer_name; s < ptr; s++) *s = tolower(*s); if (!ast_test_flag(flags, OPTION_QUIET)) { if (ast_test_flag(flags, OPTION_NAME)) { const char *local_context = S_OR(name_context, "default"); const char *local_mailbox = S_OR(mailbox, ptr); res = ast_app_sayname(chan, local_mailbox, local_context); } if (!ast_test_flag(flags, OPTION_NAME) || res < 0) { if (!ast_test_flag(flags, OPTION_NOTECH)) { if (ast_fileexists(peer_name, NULL, NULL) > 0) { res = ast_streamfile(chan, peer_name, chan->language); if (!res) { res = ast_waitstream(chan, ""); } if (res) { ast_autochan_destroy(autochan); break; } } else { res = ast_say_character_str(chan, peer_name, "", chan->language); } } if ((num = atoi(ptr))) ast_say_digits(chan, atoi(ptr), "", chan->language); } } res = channel_spy(chan, autochan, &volfactor, fd, user_options, flags, exitcontext); num_spyed_upon++; if (res == -1) { ast_autochan_destroy(autochan); goto exit; } else if (res == -2) { res = 0; ast_autochan_destroy(autochan); goto exit; } else if (res > 1 && spec) { struct ast_channel *next; snprintf(nameprefix, AST_NAME_STRLEN, "%s/%d", spec, res); if ((next = ast_channel_get_by_name_prefix(nameprefix, strlen(nameprefix)))) { next_autochan = ast_autochan_setup(next); next = ast_channel_unref(next); } else { /* stay on this channel, if it is still valid */ if (!ast_check_hangup(autochan->chan)) { next_autochan = ast_autochan_setup(autochan->chan); } else { /* the channel is gone */ next_autochan = NULL; } } } else if (res == 0 && ast_test_flag(flags, OPTION_EXITONHANGUP)) { goto exit; } } iter = ast_channel_iterator_destroy(iter); if (res == -1 || ast_check_hangup(chan)) break; if (ast_test_flag(flags, OPTION_STOP) && !next_autochan) { break; } } exit: ast_clear_flag(chan, AST_FLAG_SPYING); ast_channel_setoption(chan, AST_OPTION_TXGAIN, &zero_volume, sizeof(zero_volume), 0); return res; }
/*! \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(¤t); 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; }
static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive) { const char *s; char *tmp; char *cur, *rest; char *macro; char fullmacro[80]; char varname[80]; char runningapp[80], runningdata[1024]; char *oldargs[MAX_ARGS + 1] = { NULL, }; int argc, x; int res=0; char oldexten[256]=""; int oldpriority, gosub_level = 0; char pc[80], depthc[12]; char oldcontext[AST_MAX_CONTEXT] = ""; const char *inhangupc; int offset, depth = 0, maxdepth = 7; int setmacrocontext=0; int autoloopflag, inhangup = 0; struct ast_str *tmp_subst = NULL; char *save_macro_exten; char *save_macro_context; char *save_macro_priority; char *save_macro_offset; struct ast_datastore *macro_store = ast_channel_datastore_find(chan, ¯o_ds_info, NULL); if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "Macro() requires arguments. See \"core show application macro\" for help.\n"); return -1; } do { if (macro_store) { break; } if (!(macro_store = ast_datastore_alloc(¯o_ds_info, NULL))) { ast_log(LOG_WARNING, "Unable to allocate new datastore.\n"); break; } /* Just the existence of this datastore is enough. */ macro_store->inheritance = DATASTORE_INHERIT_FOREVER; ast_channel_datastore_add(chan, macro_store); } while (0); /* does the user want a deeper rabbit hole? */ ast_channel_lock(chan); if ((s = pbx_builtin_getvar_helper(chan, "MACRO_RECURSION"))) { sscanf(s, "%30d", &maxdepth); } /* Count how many levels deep the rabbit hole goes */ if ((s = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH"))) { sscanf(s, "%30d", &depth); } /* Used for detecting whether to return when a Macro is called from another Macro after hangup */ if (strcmp(ast_channel_exten(chan), "h") == 0) pbx_builtin_setvar_helper(chan, "MACRO_IN_HANGUP", "1"); if ((inhangupc = pbx_builtin_getvar_helper(chan, "MACRO_IN_HANGUP"))) { sscanf(inhangupc, "%30d", &inhangup); } ast_channel_unlock(chan); if (depth >= maxdepth) { ast_log(LOG_ERROR, "Macro(): possible infinite loop detected. Returning early.\n"); return 0; } snprintf(depthc, sizeof(depthc), "%d", depth + 1); tmp = ast_strdupa(data); rest = tmp; macro = strsep(&rest, ","); if (ast_strlen_zero(macro)) { ast_log(LOG_WARNING, "Invalid macro name specified\n"); return 0; } snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro); if (!ast_exists_extension(chan, fullmacro, "s", 1, S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) { if (!ast_context_find(fullmacro)) ast_log(LOG_WARNING, "No such context '%s' for macro '%s'. Was called by %s@%s\n", fullmacro, macro, ast_channel_exten(chan), ast_channel_context(chan)); else ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro); return 0; } /* If we are to run the macro exclusively, take the mutex */ if (exclusive) { ast_debug(1, "Locking macrolock for '%s'\n", fullmacro); ast_autoservice_start(chan); if (ast_context_lockmacro(fullmacro)) { ast_log(LOG_WARNING, "Failed to lock macro '%s' as in-use\n", fullmacro); ast_autoservice_stop(chan); return 0; } ast_autoservice_stop(chan); } if (!(tmp_subst = ast_str_create(16))) { return -1; } /* Save old info */ oldpriority = ast_channel_priority(chan); ast_copy_string(oldexten, ast_channel_exten(chan), sizeof(oldexten)); ast_copy_string(oldcontext, ast_channel_context(chan), sizeof(oldcontext)); if (ast_strlen_zero(ast_channel_macrocontext(chan))) { ast_channel_macrocontext_set(chan, ast_channel_context(chan)); ast_channel_macroexten_set(chan, ast_channel_exten(chan)); ast_channel_macropriority_set(chan, ast_channel_priority(chan)); setmacrocontext=1; } argc = 1; /* Save old macro variables */ save_macro_exten = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_EXTEN")); pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten); save_macro_context = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT")); pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext); save_macro_priority = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY")); snprintf(pc, sizeof(pc), "%d", oldpriority); pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc); save_macro_offset = ast_strdup(pbx_builtin_getvar_helper(chan, "MACRO_OFFSET")); pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL); pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc); /* Setup environment for new run */ ast_channel_exten_set(chan, "s"); ast_channel_context_set(chan, fullmacro); ast_channel_priority_set(chan, 1); ast_channel_lock(chan); while((cur = strsep(&rest, ",")) && (argc < MAX_ARGS)) { const char *argp; /* Save copy of old arguments if we're overwriting some, otherwise let them pass through to the other macro */ snprintf(varname, sizeof(varname), "ARG%d", argc); if ((argp = pbx_builtin_getvar_helper(chan, varname))) { oldargs[argc] = ast_strdup(argp); } pbx_builtin_setvar_helper(chan, varname, cur); argc++; } ast_channel_unlock(chan); autoloopflag = ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP); ast_set_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP); while (ast_exists_extension(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) { struct ast_context *c; struct ast_exten *e; int foundx; runningapp[0] = '\0'; runningdata[0] = '\0'; /* What application will execute? */ if (ast_rdlock_contexts()) { ast_log(LOG_WARNING, "Failed to lock contexts list\n"); } else { for (c = ast_walk_contexts(NULL), e = NULL; c; c = ast_walk_contexts(c)) { if (!strcmp(ast_get_context_name(c), ast_channel_context(chan))) { if (ast_rdlock_context(c)) { ast_log(LOG_WARNING, "Unable to lock context?\n"); } else { e = find_matching_priority(c, ast_channel_exten(chan), ast_channel_priority(chan), S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)); if (e) { /* This will only be undefined for pbx_realtime, which is majorly broken. */ ast_copy_string(runningapp, ast_get_extension_app(e), sizeof(runningapp)); ast_copy_string(runningdata, ast_get_extension_app_data(e), sizeof(runningdata)); } ast_unlock_context(c); } break; } } } ast_unlock_contexts(); /* Reset the macro depth, if it was changed in the last iteration */ pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc); res = ast_spawn_extension(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL), &foundx, 1); if (res) { /* Something bad happened, or a hangup has been requested. */ if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) || (res == '*') || (res == '#')) { /* Just return result as to the previous application as if it had been dialed */ ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res); break; } switch(res) { case MACRO_EXIT_RESULT: res = 0; goto out; default: ast_debug(2, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), ast_channel_name(chan), macro); ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), ast_channel_name(chan), macro); goto out; } } ast_debug(1, "Executed application: %s\n", runningapp); if (!strcasecmp(runningapp, "GOSUB")) { gosub_level++; ast_debug(1, "Incrementing gosub_level\n"); } else if (!strcasecmp(runningapp, "GOSUBIF")) { char *cond, *app_arg; char *app2; ast_str_substitute_variables(&tmp_subst, 0, chan, runningdata); app2 = ast_str_buffer(tmp_subst); cond = strsep(&app2, "?"); app_arg = strsep(&app2, ":"); if (pbx_checkcondition(cond)) { if (!ast_strlen_zero(app_arg)) { gosub_level++; ast_debug(1, "Incrementing gosub_level\n"); } } else { if (!ast_strlen_zero(app2)) { gosub_level++; ast_debug(1, "Incrementing gosub_level\n"); } } } else if (!strcasecmp(runningapp, "RETURN")) { gosub_level--; ast_debug(1, "Decrementing gosub_level\n"); } else if (!strcasecmp(runningapp, "STACKPOP")) { gosub_level--; ast_debug(1, "Decrementing gosub_level\n"); } else if (!strncasecmp(runningapp, "EXEC", 4)) { /* Must evaluate args to find actual app */ char *tmp2, *tmp3 = NULL; ast_str_substitute_variables(&tmp_subst, 0, chan, runningdata); tmp2 = ast_str_buffer(tmp_subst); if (!strcasecmp(runningapp, "EXECIF")) { if ((tmp3 = strchr(tmp2, '|'))) { *tmp3++ = '\0'; } if (!pbx_checkcondition(tmp2)) { tmp3 = NULL; } } else { tmp3 = tmp2; } if (tmp3) { ast_debug(1, "Last app: %s\n", tmp3); } if (tmp3 && !strncasecmp(tmp3, "GOSUB", 5)) { gosub_level++; ast_debug(1, "Incrementing gosub_level\n"); } else if (tmp3 && !strncasecmp(tmp3, "RETURN", 6)) { gosub_level--; ast_debug(1, "Decrementing gosub_level\n"); } else if (tmp3 && !strncasecmp(tmp3, "STACKPOP", 8)) { gosub_level--; ast_debug(1, "Decrementing gosub_level\n"); } } if (gosub_level == 0 && strcasecmp(ast_channel_context(chan), fullmacro)) { ast_verb(2, "Channel '%s' jumping out of macro '%s'\n", ast_channel_name(chan), macro); break; } /* don't stop executing extensions when we're in "h" */ if (ast_check_hangup(chan) && !inhangup) { ast_debug(1, "Extension %s, macroexten %s, priority %d returned normally even though call was hung up\n", ast_channel_exten(chan), ast_channel_macroexten(chan), ast_channel_priority(chan)); goto out; } ast_channel_priority_set(chan, ast_channel_priority(chan) + 1); } out: /* Don't let the channel change now. */ ast_channel_lock(chan); /* Reset the depth back to what it was when the routine was entered (like if we called Macro recursively) */ snprintf(depthc, sizeof(depthc), "%d", depth); pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc); ast_set2_flag(ast_channel_flags(chan), autoloopflag, AST_FLAG_IN_AUTOLOOP); for (x = 1; x < argc; x++) { /* Restore old arguments and delete ours */ snprintf(varname, sizeof(varname), "ARG%d", x); if (oldargs[x]) { pbx_builtin_setvar_helper(chan, varname, oldargs[x]); ast_free(oldargs[x]); } else { pbx_builtin_setvar_helper(chan, varname, NULL); } } /* Restore macro variables */ pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten); pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context); pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority); if (save_macro_exten) ast_free(save_macro_exten); if (save_macro_context) ast_free(save_macro_context); if (save_macro_priority) ast_free(save_macro_priority); if (setmacrocontext) { ast_channel_macrocontext_set(chan, ""); ast_channel_macroexten_set(chan, ""); ast_channel_macropriority_set(chan, 0); } if (!strcasecmp(ast_channel_context(chan), fullmacro)) { const char *offsets; /* If we're leaving the macro normally, restore original information */ ast_channel_priority_set(chan, oldpriority); ast_channel_context_set(chan, oldcontext); ast_channel_exten_set(chan, oldexten); if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) { /* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue normally if there is any problem */ if (sscanf(offsets, "%30d", &offset) == 1) { if (ast_exists_extension(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan) + offset + 1, S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) { ast_channel_priority_set(chan, ast_channel_priority(chan) + offset); } } } } pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset); if (save_macro_offset) ast_free(save_macro_offset); /* Unlock the macro */ if (exclusive) { ast_debug(1, "Unlocking macrolock for '%s'\n", fullmacro); if (ast_context_unlockmacro(fullmacro)) { ast_log(LOG_ERROR, "Failed to unlock macro '%s' - that isn't good\n", fullmacro); res = 0; } } ast_channel_unlock(chan); ast_free(tmp_subst); return res; }
static int conf_exec(struct ast_channel *chan, void *data) { int res=-1; int confflags = 0; int confno = 0; char confnostr[80] = "", *tmp = NULL; struct ast_channel *tempchan = NULL, *lastchan = NULL, *ichan = NULL; struct ast_frame *f; char *desired_group; int input = 0, search_group = 0; if (chan->_state != AST_STATE_UP) ast_answer(chan); desired_group = ast_strdupa(data); if (!ast_strlen_zero(desired_group)) { ast_verb(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_dahdi_channel_locked(input); input = 0; } tempchan = ichan ? ichan : ast_channel_walk_locked(tempchan); if (!tempchan && !lastchan) { break; } if (tempchan && search_group) { const char *mygroup; if ((mygroup = pbx_builtin_getvar_helper(tempchan, "GROUP")) && (!strcmp(mygroup, desired_group))) { ast_verb(3, "Found Matching Channel %s in group %s\n", tempchan->name, desired_group); } else { ast_channel_unlock(tempchan); lastchan = tempchan; continue; } } if (tempchan && (!strcmp(tempchan->tech->type, "DAHDI")) && (tempchan != chan)) { ast_verb(3, "DAHDI channel %s is in-use, monitoring...\n", tempchan->name); ast_copy_string(confnostr, tempchan->name, sizeof(confnostr)); ast_channel_unlock(tempchan); if ((tmp = strchr(confnostr, '-'))) { *tmp = '\0'; } confno = atoi(strchr(confnostr, '/') + 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_channel_unlock(tempchan); } lastchan = tempchan; } return res; }
static int txfax_exec(struct ast_channel *chan, void *data) { int res = 0; char source_file[256]; char *x; char *s; char *t; char *v; int option; int len; t30_state_t fax; int calling_party; int verbose; int samples; struct localuser *u; struct ast_frame *inf = NULL; struct ast_frame outf; int original_read_fmt; int original_write_fmt; uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET]; uint8_t *buf = __buf + AST_FRIENDLY_OFFSET; if (chan == NULL) { ast_log(LOG_WARNING, "Fax transmit channel is NULL. Giving up.\n"); return -1; } span_set_message_handler(span_message); /* The next few lines of code parse out the filename and header from the input string */ if (data == NULL) { /* No data implies no filename or anything is present */ ast_log(LOG_WARNING, "Txfax requires an argument (filename)\n"); return -1; } calling_party = FALSE; verbose = FALSE; source_file[0] = '\0'; for (option = 0, v = s = data; v; option++, s++) { t = s; v = strchr(s, '|'); s = (v) ? v : s + strlen(s); strncpy((char *) buf, t, s - t); buf[s - t] = '\0'; if (option == 0) { /* The first option is always the file name */ len = s - t; if (len > 255) len = 255; strncpy(source_file, t, len); source_file[len] = '\0'; } else if (strncmp("caller", t, s - t) == 0) { calling_party = TRUE; } else if (strncmp("debug", t, s - t) == 0) { verbose = TRUE; } } /* Done parsing */ LOCAL_USER_ADD(u); if (chan->_state != AST_STATE_UP) { /* Shouldn't need this, but checking to see if channel is already answered * Theoretically asterisk should already have answered before running the app */ res = ast_answer(chan); } if (!res) { original_read_fmt = chan->readformat; if (original_read_fmt != AST_FORMAT_SLINEAR) { res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); if (res < 0) { ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n"); return -1; } } original_write_fmt = chan->writeformat; if (original_write_fmt != AST_FORMAT_SLINEAR) { res = ast_set_write_format(chan, AST_FORMAT_SLINEAR); if (res < 0) { ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n"); res = ast_set_read_format(chan, original_read_fmt); if (res) ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); return -1; } } fax_init(&fax, calling_party, NULL); if (verbose) fax.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"); if (x && x[0]) t30_set_local_ident(&fax, x); x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"); if (x && x[0]) t30_set_header_info(&fax, x); t30_set_tx_file(&fax, source_file, -1, -1); //t30_set_phase_b_handler(&fax, phase_b_handler, chan); //t30_set_phase_d_handler(&fax, phase_d_handler, chan); t30_set_phase_e_handler(&fax, phase_e_handler, chan); while (ast_waitfor(chan, -1) > -1) { inf = ast_read(chan); if (inf == NULL) { res = -1; break; } if (inf->frametype == AST_FRAME_VOICE) { if (fax_rx(&fax, inf->data, inf->samples)) break; samples = (inf->samples <= MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE; len = fax_tx(&fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples); if (len) { memset(&outf, 0, sizeof(outf)); outf.frametype = AST_FRAME_VOICE; outf.subclass = AST_FORMAT_SLINEAR; outf.datalen = len*sizeof(int16_t); outf.samples = len; outf.data = &buf[AST_FRIENDLY_OFFSET]; outf.offset = AST_FRIENDLY_OFFSET; if (ast_write(chan, &outf) < 0) { ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno)); break; } } } ast_frfree(inf); } if (inf == NULL) { ast_log(LOG_DEBUG, "Got hangup\n"); res = -1; } if (original_read_fmt && original_read_fmt != AST_FORMAT_SLINEAR) { res = ast_set_read_format(chan, original_read_fmt); if (res) ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); } if (original_write_fmt && original_write_fmt != AST_FORMAT_SLINEAR) { res = ast_set_write_format(chan, original_write_fmt); if (res) ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name); } fax_release(&fax); } else { ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name); } LOCAL_USER_REMOVE(u); return res; }
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; }
static int macro_exec(struct ast_channel *chan, void *data) { char *tmp; char *cur, *rest; char *macro; char fullmacro[80]; char varname[80]; char *oldargs[MAX_ARGS + 1] = { NULL, }; int argc, x; int res=0; char oldexten[256]=""; int oldpriority; char pc[80], depthc[12]; char oldcontext[AST_MAX_CONTEXT] = ""; char *offsets; int offset, depth; int setmacrocontext=0; int autoloopflag; char *save_macro_exten; char *save_macro_context; char *save_macro_priority; char *save_macro_offset; struct localuser *u; if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "Macro() requires arguments. See \"show application macro\" for help.\n"); return -1; } LOCAL_USER_ADD(u); /* Count how many levels deep the rabbit hole goes */ tmp = pbx_builtin_getvar_helper(chan, "MACRO_DEPTH"); if (tmp) { sscanf(tmp, "%d", &depth); } else { depth = 0; } if (depth >= 7) { ast_log(LOG_ERROR, "Macro(): possible infinite loop detected. Returning early.\n"); LOCAL_USER_REMOVE(u); return 0; } snprintf(depthc, sizeof(depthc), "%d", depth + 1); pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc); tmp = ast_strdupa(data); rest = tmp; macro = strsep(&rest, "|"); if (ast_strlen_zero(macro)) { ast_log(LOG_WARNING, "Invalid macro name specified\n"); LOCAL_USER_REMOVE(u); return 0; } snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro); if (!ast_exists_extension(chan, fullmacro, "s", 1, chan->cid.cid_num)) { if (!ast_context_find(fullmacro)) ast_log(LOG_WARNING, "No such context '%s' for macro '%s'\n", fullmacro, macro); else ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro); LOCAL_USER_REMOVE(u); return 0; } /* Save old info */ oldpriority = chan->priority; ast_copy_string(oldexten, chan->exten, sizeof(oldexten)); ast_copy_string(oldcontext, chan->context, sizeof(oldcontext)); if (ast_strlen_zero(chan->macrocontext)) { ast_copy_string(chan->macrocontext, chan->context, sizeof(chan->macrocontext)); ast_copy_string(chan->macroexten, chan->exten, sizeof(chan->macroexten)); chan->macropriority = chan->priority; setmacrocontext=1; } argc = 1; /* Save old macro variables */ save_macro_exten = pbx_builtin_getvar_helper(chan, "MACRO_EXTEN"); if (save_macro_exten) save_macro_exten = strdup(save_macro_exten); pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", oldexten); save_macro_context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT"); if (save_macro_context) save_macro_context = strdup(save_macro_context); pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", oldcontext); save_macro_priority = pbx_builtin_getvar_helper(chan, "MACRO_PRIORITY"); if (save_macro_priority) save_macro_priority = strdup(save_macro_priority); snprintf(pc, sizeof(pc), "%d", oldpriority); pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", pc); save_macro_offset = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"); if (save_macro_offset) save_macro_offset = strdup(save_macro_offset); pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", NULL); /* Setup environment for new run */ chan->exten[0] = 's'; chan->exten[1] = '\0'; ast_copy_string(chan->context, fullmacro, sizeof(chan->context)); chan->priority = 1; while((cur = strsep(&rest, "|")) && (argc < MAX_ARGS)) { /* Save copy of old arguments if we're overwriting some, otherwise let them pass through to the other macro */ snprintf(varname, sizeof(varname), "ARG%d", argc); oldargs[argc] = pbx_builtin_getvar_helper(chan, varname); if (oldargs[argc]) oldargs[argc] = strdup(oldargs[argc]); pbx_builtin_setvar_helper(chan, varname, cur); argc++; } autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP); ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP); while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) { /* Reset the macro depth, if it was changed in the last iteration */ pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc); if ((res = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num))) { /* Something bad happened, or a hangup has been requested. */ if (((res >= '0') && (res <= '9')) || ((res >= 'A') && (res <= 'F')) || (res == '*') || (res == '#')) { /* Just return result as to the previous application as if it had been dialed */ ast_log(LOG_DEBUG, "Oooh, got something to jump out with ('%c')!\n", res); break; } switch(res) { case MACRO_EXIT_RESULT: res = 0; goto out; case AST_PBX_KEEPALIVE: if (option_debug) ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited KEEPALIVE in macro %s on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name); else if (option_verbose > 1) ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited KEEPALIVE in macro '%s' on '%s'\n", chan->context, chan->exten, chan->priority, macro, chan->name); goto out; break; default: if (option_debug) ast_log(LOG_DEBUG, "Spawn extension (%s,%s,%d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro); else if (option_verbose > 1) ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s' in macro '%s'\n", chan->context, chan->exten, chan->priority, chan->name, macro); goto out; } } if (strcasecmp(chan->context, fullmacro)) { if (option_verbose > 1) ast_verbose(VERBOSE_PREFIX_2 "Channel '%s' jumping out of macro '%s'\n", chan->name, macro); break; } /* don't stop executing extensions when we're in "h" */ if (chan->_softhangup && strcasecmp(oldexten,"h")) { ast_log(LOG_DEBUG, "Extension %s, priority %d returned normally even though call was hung up\n", chan->exten, chan->priority); goto out; } chan->priority++; } out: /* Reset the depth back to what it was when the routine was entered (like if we called Macro recursively) */ snprintf(depthc, sizeof(depthc), "%d", depth); pbx_builtin_setvar_helper(chan, "MACRO_DEPTH", depthc); ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP); for (x=1; x<argc; x++) { /* Restore old arguments and delete ours */ snprintf(varname, sizeof(varname), "ARG%d", x); if (oldargs[x]) { pbx_builtin_setvar_helper(chan, varname, oldargs[x]); free(oldargs[x]); } else { pbx_builtin_setvar_helper(chan, varname, NULL); } } /* Restore macro variables */ pbx_builtin_setvar_helper(chan, "MACRO_EXTEN", save_macro_exten); if (save_macro_exten) free(save_macro_exten); pbx_builtin_setvar_helper(chan, "MACRO_CONTEXT", save_macro_context); if (save_macro_context) free(save_macro_context); pbx_builtin_setvar_helper(chan, "MACRO_PRIORITY", save_macro_priority); if (save_macro_priority) free(save_macro_priority); if (setmacrocontext) { chan->macrocontext[0] = '\0'; chan->macroexten[0] = '\0'; chan->macropriority = 0; } if (!strcasecmp(chan->context, fullmacro)) { /* If we're leaving the macro normally, restore original information */ chan->priority = oldpriority; ast_copy_string(chan->context, oldcontext, sizeof(chan->context)); if (!(chan->_softhangup & AST_SOFTHANGUP_ASYNCGOTO)) { /* Copy the extension, so long as we're not in softhangup, where we could be given an asyncgoto */ ast_copy_string(chan->exten, oldexten, sizeof(chan->exten)); if ((offsets = pbx_builtin_getvar_helper(chan, "MACRO_OFFSET"))) { /* Handle macro offset if it's set by checking the availability of step n + offset + 1, otherwise continue normally if there is any problem */ if (sscanf(offsets, "%d", &offset) == 1) { if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + offset + 1, chan->cid.cid_num)) { chan->priority += offset; } } } } } pbx_builtin_setvar_helper(chan, "MACRO_OFFSET", save_macro_offset); if (save_macro_offset) free(save_macro_offset); LOCAL_USER_REMOVE(u); return res; }
static int conf_run(struct ast_channel *chan, struct ast_conference *conf, int confflags) { struct ast_conference *prev=NULL, *cur; struct ast_conf_user *user = malloc(sizeof(struct ast_conf_user)); int fd; struct zt_confinfo ztc; struct ast_frame *f; struct ast_channel *c; struct ast_frame fr; int outfd; int ms; int nfds; int res; int flags; int retryzap; int origfd; int musiconhold = 0; int firstpass = 0; int origquiet; int ret = -1; int x; int menu_active = 0; int using_pseudo = 0; struct ast_app *app; char *agifile; char *agifiledefault = "conf-background.agi"; char meetmesecs[30] = ""; char exitcontext[AST_MAX_EXTENSION] = ""; int dtmf; ZT_BUFFERINFO bi; char __buf[CONF_SIZE + AST_FRIENDLY_OFFSET]; char *buf = __buf + AST_FRIENDLY_OFFSET; if (!user) { ast_log(LOG_ERROR, "Out of memory\n"); return(ret); } memset(user, 0, sizeof(struct ast_conf_user)); user->user_no = 0; /* User number 0 means starting up user! (dead - not in the list!) */ time(&user->jointime); if (conf->locked) { /* Sorry, but this confernce is locked! */ if (!ast_streamfile(chan, "conf-locked", chan->language)) ast_waitstream(chan, ""); goto outrun; } conf->users++; if (confflags & CONFFLAG_MARKEDUSER) conf->markedusers++; ast_mutex_lock(&conflock); if (conf->firstuser == NULL) { /* Fill the first new User struct */ user->user_no = 1; user->nextuser = NULL; user->prevuser = NULL; conf->firstuser = user; conf->lastuser = user; } else { /* Fill the new user struct */ user->user_no = conf->lastuser->user_no + 1; user->prevuser = conf->lastuser; user->nextuser = NULL; if (conf->lastuser->nextuser != NULL) { ast_log(LOG_WARNING, "Error in User Management!\n"); ast_mutex_unlock(&conflock); goto outrun; } else { conf->lastuser->nextuser = user; conf->lastuser = user; } } user->chan = chan; user->userflags = confflags; user->adminflags = 0; ast_mutex_unlock(&conflock); origquiet = confflags & CONFFLAG_QUIET; if (confflags & CONFFLAG_EXIT_CONTEXT) { if ((agifile = pbx_builtin_getvar_helper(chan, "MEETME_EXIT_CONTEXT"))) strncpy(exitcontext, agifile, sizeof(exitcontext) - 1); else if (!ast_strlen_zero(chan->macrocontext)) strncpy(exitcontext, chan->macrocontext, sizeof(exitcontext) - 1); else strncpy(exitcontext, chan->context, sizeof(exitcontext) - 1); } while((confflags & CONFFLAG_WAITMARKED) && (conf->markedusers == 0)) { confflags &= ~CONFFLAG_QUIET; confflags |= origquiet; /* XXX Announce that we're waiting on the conference lead to join */ if (!(confflags & CONFFLAG_QUIET)) { res = ast_streamfile(chan, "vm-dialout", chan->language); if (!res) res = ast_waitstream(chan, ""); } else res = 0; /* If we're waiting with hold music, set to silent mode */ if (!res) { confflags |= CONFFLAG_QUIET; ast_moh_start(chan, NULL); res = ast_safe_sleep_conditional(chan, 60000, confnonzero, conf); ast_moh_stop(chan); } if (res < 0) { ast_log(LOG_DEBUG, "Got hangup on '%s' already\n", chan->name); goto outrun; } } if (!(confflags & CONFFLAG_QUIET) && conf->users == 1) { if (!ast_streamfile(chan, "conf-onlyperson", chan->language)) { if (ast_waitstream(chan, "") < 0) goto outrun; } else goto outrun; } /* Set it into linear mode (write) */ if (ast_set_write_format(chan, AST_FORMAT_SLINEAR) < 0) { ast_log(LOG_WARNING, "Unable to set '%s' to write linear mode\n", chan->name); goto outrun; } /* Set it into linear mode (read) */ if (ast_set_read_format(chan, AST_FORMAT_SLINEAR) < 0) { ast_log(LOG_WARNING, "Unable to set '%s' to read linear mode\n", chan->name); goto outrun; } ast_indicate(chan, -1); retryzap = strcasecmp(chan->type, "Zap"); zapretry: origfd = chan->fds[0]; if (retryzap) { fd = open("/dev/zap/pseudo", O_RDWR); if (fd < 0) { ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno)); goto outrun; } using_pseudo = 1; /* Make non-blocking */ flags = fcntl(fd, F_GETFL); if (flags < 0) { ast_log(LOG_WARNING, "Unable to get flags: %s\n", strerror(errno)); close(fd); goto outrun; } if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { ast_log(LOG_WARNING, "Unable to set flags: %s\n", strerror(errno)); close(fd); goto outrun; } /* Setup buffering information */ memset(&bi, 0, sizeof(bi)); bi.bufsize = CONF_SIZE/2; bi.txbufpolicy = ZT_POLICY_IMMEDIATE; bi.rxbufpolicy = ZT_POLICY_IMMEDIATE; bi.numbufs = 4; if (ioctl(fd, ZT_SET_BUFINFO, &bi)) { ast_log(LOG_WARNING, "Unable to set buffering information: %s\n", strerror(errno)); close(fd); goto outrun; } x = 1; if (ioctl(fd, ZT_SETLINEAR, &x)) { ast_log(LOG_WARNING, "Unable to set linear mode: %s\n", strerror(errno)); close(fd); goto outrun; } nfds = 1; } else { /* XXX Make sure we're not running on a pseudo channel XXX */ fd = chan->fds[0]; nfds = 0; } memset(&ztc, 0, sizeof(ztc)); /* Check to see if we're in a conference... */ ztc.chan = 0; if (ioctl(fd, ZT_GETCONF, &ztc)) { ast_log(LOG_WARNING, "Error getting conference\n"); close(fd); goto outrun; } if (ztc.confmode) { /* Whoa, already in a conference... Retry... */ if (!retryzap) { ast_log(LOG_DEBUG, "Zap channel is in a conference already, retrying with pseudo\n"); retryzap = 1; goto zapretry; } } memset(&ztc, 0, sizeof(ztc)); /* Add us to the conference */ ztc.chan = 0; ztc.confno = conf->zapconf; if (confflags & CONFFLAG_MONITOR) ztc.confmode = ZT_CONF_CONFMON | ZT_CONF_LISTENER; else if (confflags & CONFFLAG_TALKER) ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER; else ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; if (ioctl(fd, ZT_SETCONF, &ztc)) { ast_log(LOG_WARNING, "Error setting conference\n"); close(fd); goto outrun; } ast_log(LOG_DEBUG, "Placed channel %s in ZAP conf %d\n", chan->name, conf->zapconf); manager_event(EVENT_FLAG_CALL, "MeetmeJoin", "Channel: %s\r\n" "Uniqueid: %s\r\n" "Meetme: %s\r\n" "Usernum: %i\r\n", chan->name, chan->uniqueid, conf->confno, user->user_no); if (!firstpass && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) { firstpass = 1; if (!(confflags & CONFFLAG_QUIET)) conf_play(conf, ENTER); } if (confflags & CONFFLAG_AGI) { /* Get name of AGI file to run from $(MEETME_AGI_BACKGROUND) or use default filename of conf-background.agi */ agifile = pbx_builtin_getvar_helper(chan,"MEETME_AGI_BACKGROUND"); if (!agifile) agifile = agifiledefault; if (!strcasecmp(chan->type,"Zap")) { /* Set CONFMUTE mode on Zap channel to mute DTMF tones */ x = 1; ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); } /* Find a pointer to the agi app and execute the script */ app = pbx_findapp("agi"); if (app) { ret = pbx_exec(chan, app, agifile, 1); } else { ast_log(LOG_WARNING, "Could not find application (agi)\n"); ret = -2; } if (!strcasecmp(chan->type,"Zap")) { /* Remove CONFMUTE mode on Zap channel */ x = 0; ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); } } else { if (!strcasecmp(chan->type,"Zap") && (confflags & CONFFLAG_STARMENU)) { /* Set CONFMUTE mode on Zap channel to mute DTMF tones when the menu is enabled */ x = 1; ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); } for(;;) { outfd = -1; ms = -1; c = ast_waitfor_nandfds(&chan, 1, &fd, nfds, NULL, &outfd, &ms); /* Update the struct with the actual confflags */ user->userflags = confflags; /* trying to add moh for single person conf */ if (confflags & CONFFLAG_MOH) { if (conf->users == 1) { if (musiconhold == 0) { ast_moh_start(chan, NULL); musiconhold = 1; } } else { if (musiconhold) { ast_moh_stop(chan); musiconhold = 0; } } } /* Leave if the last marked user left */ if (conf->markedusers == 0 && confflags & CONFFLAG_MARKEDEXIT) { ret = -1; break; } /* Check if the admin changed my modes */ if (user->adminflags) { /* Set the new modes */ if ((user->adminflags & ADMINFLAG_MUTED) && (ztc.confmode & ZT_CONF_TALKER)) { ztc.confmode ^= ZT_CONF_TALKER; if (ioctl(fd, ZT_SETCONF, &ztc)) { ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); ret = -1; break; } } if (!(user->adminflags & ADMINFLAG_MUTED) && !(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) { ztc.confmode |= ZT_CONF_TALKER; if (ioctl(fd, ZT_SETCONF, &ztc)) { ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); ret = -1; break; } } if (user->adminflags & ADMINFLAG_KICKME) { //You have been kicked. if (!ast_streamfile(chan, "conf-kicked", chan->language)) ast_waitstream(chan, ""); ret = 0; break; } } else if (!(confflags & CONFFLAG_MONITOR) && !(ztc.confmode & ZT_CONF_TALKER)) { ztc.confmode |= ZT_CONF_TALKER; if (ioctl(fd, ZT_SETCONF, &ztc)) { ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); ret = -1; break; } } if (c) { if (c->fds[0] != origfd) { if (using_pseudo) { /* Kill old pseudo */ close(fd); } ast_log(LOG_DEBUG, "Ooh, something swapped out under us, starting over\n"); retryzap = 0; using_pseudo = 0; goto zapretry; } f = ast_read(c); if (!f) break; if ((f->frametype == AST_FRAME_DTMF) && (confflags & CONFFLAG_EXIT_CONTEXT)) { char tmp[2]; tmp[0] = f->subclass; tmp[1] = '\0'; if (ast_exists_extension(chan, exitcontext, tmp, 1, chan->callerid)) { strncpy(chan->context, exitcontext, sizeof(chan->context) - 1); strncpy(chan->exten, tmp, sizeof(chan->exten) - 1); chan->priority = 0; ret = 0; break; } } else if ((f->frametype == AST_FRAME_DTMF) && (f->subclass == '#') && (confflags & CONFFLAG_POUNDEXIT)) { ret = 0; break; } else if (((f->frametype == AST_FRAME_DTMF) && (f->subclass == '*') && (confflags & CONFFLAG_STARMENU)) || ((f->frametype == AST_FRAME_DTMF) && menu_active)) { if (musiconhold) { ast_moh_stop(chan); } if ((confflags & CONFFLAG_ADMIN)) { /* Admin menu */ if (!menu_active) { menu_active = 1; /* Record this sound! */ if (!ast_streamfile(chan, "conf-adminmenu", chan->language)) dtmf = ast_waitstream(chan, AST_DIGIT_ANY); else dtmf = 0; } else dtmf = f->subclass; if (dtmf) { switch(dtmf) { case '1': /* Un/Mute */ menu_active = 0; if (ztc.confmode & ZT_CONF_TALKER) { ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER; confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER; } else { ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER; } if (ioctl(fd, ZT_SETCONF, &ztc)) { ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); ret = -1; break; } if (ztc.confmode & ZT_CONF_TALKER) { if (!ast_streamfile(chan, "conf-unmuted", chan->language)) ast_waitstream(chan, ""); } else { if (!ast_streamfile(chan, "conf-muted", chan->language)) ast_waitstream(chan, ""); } break; case '2': /* Un/Lock the Conference */ menu_active = 0; if (conf->locked) { conf->locked = 0; if (!ast_streamfile(chan, "conf-unlockednow", chan->language)) ast_waitstream(chan, ""); } else { conf->locked = 1; if (!ast_streamfile(chan, "conf-lockednow", chan->language)) ast_waitstream(chan, ""); } break; default: menu_active = 0; /* Play an error message! */ if (!ast_streamfile(chan, "conf-errormenu", chan->language)) ast_waitstream(chan, ""); break; } } } else { /* User menu */ if (!menu_active) { menu_active = 1; /* Record this sound! */ if (!ast_streamfile(chan, "conf-usermenu", chan->language)) dtmf = ast_waitstream(chan, AST_DIGIT_ANY); else dtmf = 0; } else dtmf = f->subclass; if (dtmf) { switch(dtmf) { case '1': /* Un/Mute */ menu_active = 0; if (ztc.confmode & ZT_CONF_TALKER) { ztc.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER; confflags |= CONFFLAG_MONITOR ^ CONFFLAG_TALKER; } else if (!(user->adminflags & ADMINFLAG_MUTED)) { ztc.confmode = ZT_CONF_CONF | ZT_CONF_TALKER | ZT_CONF_LISTENER; confflags ^= CONFFLAG_MONITOR | CONFFLAG_TALKER; } if (ioctl(fd, ZT_SETCONF, &ztc)) { ast_log(LOG_WARNING, "Error setting conference - Un/Mute \n"); ret = -1; break; } if (ztc.confmode & ZT_CONF_TALKER) { if (!ast_streamfile(chan, "conf-unmuted", chan->language)) ast_waitstream(chan, ""); } else { if (!ast_streamfile(chan, "conf-muted", chan->language)) ast_waitstream(chan, ""); } break; default: menu_active = 0; /* Play an error message! */ if (!ast_streamfile(chan, "conf-errormenu", chan->language)) ast_waitstream(chan, ""); break; } } } if (musiconhold) { ast_moh_start(chan, NULL); } } else if (using_pseudo) { if (f->frametype == AST_FRAME_VOICE) { if (f->subclass == AST_FORMAT_SLINEAR) { /* Carefully write */ careful_write(fd, f->data, f->datalen); } else ast_log(LOG_WARNING, "Huh? Got a non-linear (%d) frame in the conference\n", f->subclass); } } ast_frfree(f); } else if (outfd > -1) { res = read(outfd, buf, CONF_SIZE); if (res > 0) { memset(&fr, 0, sizeof(fr)); fr.frametype = AST_FRAME_VOICE; fr.subclass = AST_FORMAT_SLINEAR; fr.datalen = res; fr.samples = res/2; fr.data = buf; fr.offset = AST_FRIENDLY_OFFSET; if (ast_write(chan, &fr) < 0) { ast_log(LOG_WARNING, "Unable to write frame to channel: %s\n", strerror(errno)); /* break; */ } } else ast_log(LOG_WARNING, "Failed to read frame: %s\n", strerror(errno)); } } } if (using_pseudo) close(fd); else { /* Take out of conference */ /* Add us to the conference */ ztc.chan = 0; ztc.confno = 0; ztc.confmode = 0; if (ioctl(fd, ZT_SETCONF, &ztc)) { ast_log(LOG_WARNING, "Error setting conference\n"); } } if (!(confflags & CONFFLAG_QUIET) && !(confflags & CONFFLAG_MONITOR) && !(confflags & CONFFLAG_ADMIN)) conf_play(conf, LEAVE); outrun: ast_mutex_lock(&conflock); if (user->user_no) { /* Only cleanup users who really joined! */ manager_event(EVENT_FLAG_CALL, "MeetmeLeave", "Channel: %s\r\n" "Uniqueid: %s\r\n" "Meetme: %s\r\n" "Usernum: %i\r\n", chan->name, chan->uniqueid, conf->confno, user->user_no); prev = NULL; conf->users--; if (confflags & CONFFLAG_MARKEDUSER) conf->markedusers--; cur = confs; if (!conf->users) { /* No more users -- close this one out */ while(cur) { if (cur == conf) { if (prev) prev->next = conf->next; else confs = conf->next; break; } prev = cur; cur = cur->next; } if (!cur) ast_log(LOG_WARNING, "Conference not found\n"); if (conf->chan) ast_hangup(conf->chan); else close(conf->fd); free(conf); } else { /* Remove the user struct */ if (user == conf->firstuser) { if (user->nextuser) { /* There is another entry */ user->nextuser->prevuser = NULL; } else { /* We are the only entry */ conf->lastuser = NULL; } /* In either case */ conf->firstuser = user->nextuser; } else if (user == conf->lastuser){ if (user->prevuser) user->prevuser->nextuser = NULL; else ast_log(LOG_ERROR, "Bad bad bad! We're the last, not the first, but nobody before us??\n"); conf->lastuser = user->prevuser; } else { if (user->nextuser) user->nextuser->prevuser = user->prevuser; else ast_log(LOG_ERROR, "Bad! Bad! Bad! user->nextuser is NULL but we're not the end!\n"); if (user->prevuser) user->prevuser->nextuser = user->nextuser; else ast_log(LOG_ERROR, "Bad! Bad! Bad! user->prevuser is NULL but we're not the beginning!\n"); } } /* Return the number of seconds the user was in the conf */ snprintf(meetmesecs, sizeof(meetmesecs), "%i", (int) (time(NULL) - user->jointime)); pbx_builtin_setvar_helper(chan, "MEETMESECS", meetmesecs); } free(user); ast_mutex_unlock(&conflock); return ret; }
/*! * \brief Stop monitoring channel * \param chan * \param need_lock * Stop the recording, close any open streams, mix in/out channels if required * \return Always 0 */ int AST_OPTIONAL_API_NAME(ast_monitor_stop)(struct ast_channel *chan, int need_lock) { int delfiles = 0; LOCK_IF_NEEDED(chan, need_lock); if (ast_channel_monitor(chan)) { char filename[ FILENAME_MAX ]; if (ast_channel_monitor(chan)->read_stream) { ast_closestream(ast_channel_monitor(chan)->read_stream); } if (ast_channel_monitor(chan)->write_stream) { ast_closestream(ast_channel_monitor(chan)->write_stream); } if (ast_channel_monitor(chan)->filename_changed && !ast_strlen_zero(ast_channel_monitor(chan)->filename_base)) { if (ast_channel_monitor(chan)->read_stream) { if (ast_fileexists(ast_channel_monitor(chan)->read_filename,NULL,NULL) > 0) { snprintf(filename, FILENAME_MAX, "%s-in", ast_channel_monitor(chan)->filename_base); if (ast_fileexists(filename, NULL, NULL) > 0) { ast_filedelete(filename, NULL); } ast_filerename(ast_channel_monitor(chan)->read_filename, filename, ast_channel_monitor(chan)->format); } else { ast_log(LOG_WARNING, "File %s not found\n", ast_channel_monitor(chan)->read_filename); } } if (ast_channel_monitor(chan)->write_stream) { if (ast_fileexists(ast_channel_monitor(chan)->write_filename,NULL,NULL) > 0) { snprintf(filename, FILENAME_MAX, "%s-out", ast_channel_monitor(chan)->filename_base); if (ast_fileexists(filename, NULL, NULL) > 0) { ast_filedelete(filename, NULL); } ast_filerename(ast_channel_monitor(chan)->write_filename, filename, ast_channel_monitor(chan)->format); } else { ast_log(LOG_WARNING, "File %s not found\n", ast_channel_monitor(chan)->write_filename); } } } if (ast_channel_monitor(chan)->joinfiles && !ast_strlen_zero(ast_channel_monitor(chan)->filename_base)) { char tmp[1024]; char tmp2[1024]; const char *format = !strcasecmp(ast_channel_monitor(chan)->format,"wav49") ? "WAV" : ast_channel_monitor(chan)->format; char *fname_base = ast_channel_monitor(chan)->filename_base; const char *execute, *execute_args; /* at this point, fname_base really is the full path */ /* Set the execute application */ execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC"); if (ast_strlen_zero(execute)) { #ifdef HAVE_SOXMIX execute = "nice -n 19 soxmix"; #else execute = "nice -n 19 sox -m"; #endif format = get_soxmix_format(format); delfiles = 1; } execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS"); if (ast_strlen_zero(execute_args)) { execute_args = ""; } snprintf(tmp, sizeof(tmp), "%s \"%s-in.%s\" \"%s-out.%s\" \"%s.%s\" %s &", execute, fname_base, format, fname_base, format, fname_base, format,execute_args); if (delfiles) { snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s-\"* ) &",tmp, fname_base); /* remove legs when done mixing */ ast_copy_string(tmp, tmp2, sizeof(tmp)); } ast_debug(1,"monitor executing %s\n",tmp); if (ast_safe_system(tmp) == -1) ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp); } ast_free(ast_channel_monitor(chan)->format); ast_free(ast_channel_monitor(chan)); ast_channel_monitor_set(chan, NULL); ast_manager_event(chan, EVENT_FLAG_CALL, "MonitorStop", "Channel: %s\r\n" "Uniqueid: %s\r\n", ast_channel_name(chan), ast_channel_uniqueid(chan) ); pbx_builtin_setvar_helper(chan, "MONITORED", NULL); } pbx_builtin_setvar_helper(chan, "AUTO_MONITOR", NULL); UNLOCK_IF_NEEDED(chan, need_lock); return 0; }
static char *get_index(struct cw_channel *chan, const char *prefix, int index) { char varname[VAR_SIZE]; snprintf(varname, VAR_SIZE, "%s_%d", prefix, index); return pbx_builtin_getvar_helper(chan, varname); }