Allow manager originate to specifiy more than one variable to be set.
[asterisk/asterisk.git] / pbx.c
diff --git a/pbx.c b/pbx.c
index 3d1d002..be56630 100755 (executable)
--- a/pbx.c
+++ b/pbx.c
@@ -4742,15 +4742,14 @@ int ast_pbx_outgoing_cdr_failed(void)
        return 0;  /* success */
 }
 
-int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, const char *variable, const char *account, struct ast_channel **channel)
+int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, struct ast_channel **channel)
 {
        struct ast_channel *chan;
        struct async_stat *as;
        int res = -1, cdr_res = -1;
-       char *var, *tmp;
        struct outgoing_helper oh;
        pthread_attr_t attr;
-               
+
        if (sync) {
                LOAD_OH(oh);
                chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
@@ -4760,25 +4759,21 @@ int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout
                                ast_mutex_lock(&chan->lock);
                }
                if (chan) {
-                       
-                       if (account)
-                               ast_cdr_setaccount(chan, account);
-                       
                        if(chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
                                ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name);
                        } else {
                                chan->cdr = ast_cdr_alloc();   /* allocate a cdr for the channel */
-                               if(!chan->cdr) {
+                               if (!chan->cdr) {
                                        /* allocation of the cdr failed */
                                        ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
                                        free(chan->pbx);
-                                       return -1;  /* return failure */
+                                       res = -1;
+                                       goto outgoing_exten_cleanup;
                                }
                                /* allocation of the cdr was successful */
                                ast_cdr_init(chan->cdr, chan);  /* initilize our channel's cdr */
                                ast_cdr_start(chan->cdr);
                        }
-
                        if (chan->_state == AST_STATE_UP) {
                                        res = 0;
                                if (option_verbose > 3)
@@ -4805,7 +4800,7 @@ int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout
                                if(chan->cdr) { /* update the cdr */
                                        /* here we update the status of the call, which sould be busy.
                                         * if that fails then we set the status to failed */
-                                       if(ast_cdr_disposition(chan->cdr, chan->hangupcause))
+                                       if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
                                                ast_cdr_failed(chan->cdr);
                                }
                        
@@ -4814,29 +4809,26 @@ int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout
                }
 
                if(res < 0) { /* the call failed for some reason */
-                       if(*reason == 0) { /* if the call failed (not busy or no answer)
+                       if (*reason == 0) { /* if the call failed (not busy or no answer)
                                            * update the cdr with the failed message */
                                cdr_res = ast_pbx_outgoing_cdr_failed();
-                               if(cdr_res != 0)
-                                       return cdr_res;
+                               if (cdr_res != 0) {
+                                       res = cdr_res;
+                                       goto outgoing_exten_cleanup;
+                               }
                        }
                        
                        /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
                        /* check if "failed" exists */
                        if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
                                chan = ast_channel_alloc(0);
-                               if(chan) {
+                               if (chan) {
                                        ast_copy_string(chan->name, "OutgoingSpoolFailed", sizeof(chan->name));
                                        if (context && !ast_strlen_zero(context))
                                                ast_copy_string(chan->context, context, sizeof(chan->context));
                                        ast_copy_string(chan->exten, "failed", sizeof(chan->exten));
                                        chan->priority = 1;
-                                       if (variable) {
-                                               tmp = ast_strdupa(variable);
-                                               for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp)) {
-                                                       pbx_builtin_setvar( chan, var );
-                                               }
-                                       }
+                                       ast_set_variables(chan, vars);
                                        ast_pbx_run(chan);      
                                } else 
                                        ast_log(LOG_WARNING, "Can't allocate the channel structure, skipping execution of extension 'failed'\n");
@@ -4844,8 +4836,10 @@ int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout
                }
        } else {
                as = malloc(sizeof(struct async_stat));
-               if (!as)
-                       return -1;
+               if (!as) {
+                       res = -1;
+                       goto outgoing_exten_cleanup;
+               }       
                memset(as, 0, sizeof(struct async_stat));
                chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
                if (channel) {
@@ -4855,30 +4849,28 @@ int ast_pbx_outgoing_exten(const char *type, int format, void *data, int timeout
                }
                if (!chan) {
                        free(as);
-                       return -1;
+                       res = -1;
+                       goto outgoing_exten_cleanup;
                }
-               if (account)
-                       ast_cdr_setaccount(chan, account);
                as->chan = chan;
                ast_copy_string(as->context, context, sizeof(as->context));
                ast_copy_string(as->exten,  exten, sizeof(as->exten));
                as->priority = priority;
                as->timeout = timeout;
-               if (variable) {
-                       tmp = ast_strdupa(variable);
-                       for (var = strtok_r(tmp, "|", &tmp); var; var = strtok_r(NULL, "|", &tmp))
-                               pbx_builtin_setvar( chan, var );
-               }
+               ast_set_variables(chan, vars);
                pthread_attr_init(&attr);
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
                if (ast_pthread_create(&as->p, &attr, async_wait, as)) {
                        ast_log(LOG_WARNING, "Failed to start async wait\n");
                        free(as);
                        ast_hangup(chan);
-                       return -1;
+                       res = -1;
+                       goto outgoing_exten_cleanup;
                }
                res = 0;
        }
+outgoing_exten_cleanup:
+       ast_variables_destroy(vars);
        return res;
 }
 
@@ -4905,26 +4897,28 @@ static void *ast_pbx_run_app(void *data)
        return NULL;
 }
 
-int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, const char *variable, const char *account, struct ast_channel **locked_channel)
+int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, struct ast_channel **locked_channel)
 {
        struct ast_channel *chan;
        struct async_stat *as;
        struct app_tmp *tmp;
-       char *var, *vartmp;
        int res = -1, cdr_res = -1;
+       struct outgoing_helper oh;
        pthread_attr_t attr;
        
+       memset(&oh, 0, sizeof(oh));
+       oh.vars = vars; 
+
        if (locked_channel) 
                *locked_channel = NULL;
-       if (!app || ast_strlen_zero(app))
-               return -1;
+       if (!app || ast_strlen_zero(app)) {
+               res = -1;
+               goto outgoing_app_cleanup;      
+       }
        if (sync) {
-               chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
+               chan = __ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name, &oh);
                if (chan) {
-                       if (account)
-                               ast_cdr_setaccount(chan, account);
-                       
-                       if(chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
+                       if (chan->cdr) { /* check if the channel already has a cdr record, if not give it one */
                                ast_log(LOG_WARNING, "%s already has a call record??\n", chan->name);
                        } else {
                                chan->cdr = ast_cdr_alloc();   /* allocate a cdr for the channel */
@@ -4932,19 +4926,14 @@ int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout,
                                        /* allocation of the cdr failed */
                                        ast_log(LOG_WARNING, "Unable to create Call Detail Record\n");
                                        free(chan->pbx);
-                                       return -1;  /* return failure */
+                                       res = -1;
+                                       goto outgoing_app_cleanup;
                                }
                                /* allocation of the cdr was successful */
                                ast_cdr_init(chan->cdr, chan);  /* initilize our channel's cdr */
                                ast_cdr_start(chan->cdr);
                        }
-                       
-                       if (variable) {
-                               vartmp = ast_strdupa(variable);
-                               for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp)) {
-                                       pbx_builtin_setvar( chan, var );
-                               }
-                       }
+                       ast_set_variables(chan, vars);
                        if (chan->_state == AST_STATE_UP) {
                                res = 0;
                                if (option_verbose > 3)
@@ -4984,47 +4973,46 @@ int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout,
                        } else {
                                if (option_verbose > 3)
                                        ast_verbose(VERBOSE_PREFIX_4 "Channel %s was never answered.\n", chan->name);
-                               if(chan->cdr) { /* update the cdr */
+                               if (chan->cdr) { /* update the cdr */
                                        /* here we update the status of the call, which sould be busy.
                                         * if that fails then we set the status to failed */
-                                       if(ast_cdr_disposition(chan->cdr, chan->hangupcause))
+                                       if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
                                                ast_cdr_failed(chan->cdr);
                                }
                                ast_hangup(chan);
                        }
                }
                
-               if(res < 0) { /* the call failed for some reason */
-                       if(*reason == 0) { /* if the call failed (not busy or no answer)
+               if (res < 0) { /* the call failed for some reason */
+                       if (*reason == 0) { /* if the call failed (not busy or no answer)
                                            * update the cdr with the failed message */
                                cdr_res = ast_pbx_outgoing_cdr_failed();
-                               if(cdr_res != 0)
-                                       return cdr_res;
+                               if (cdr_res != 0) {
+                                       res = cdr_res;
+                                       goto outgoing_app_cleanup;
+                               }
                        }
                }
 
        } else {
                as = malloc(sizeof(struct async_stat));
-               if (!as)
-                       return -1;
+               if (!as) {
+                       res = -1;
+                       goto outgoing_app_cleanup;
+               }
                memset(as, 0, sizeof(struct async_stat));
                chan = ast_request_and_dial(type, format, data, timeout, reason, cid_num, cid_name);
                if (!chan) {
                        free(as);
-                       return -1;
+                       res = -1;
+                       goto outgoing_app_cleanup;
                }
-               if (account)
-                       ast_cdr_setaccount(chan, account);
                as->chan = chan;
                ast_copy_string(as->app, app, sizeof(as->app));
                if (appdata)
                        ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
                as->timeout = timeout;
-               if (variable) {
-                       vartmp = ast_strdupa(variable);
-                       for (var = strtok_r(vartmp, "|", &vartmp); var; var = strtok_r(NULL, "|", &vartmp))
-                               pbx_builtin_setvar( chan, var );
-               }
+               ast_set_variables(chan, vars);
                /* Start a new thread, and get something handling this channel. */
                pthread_attr_init(&attr);
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
@@ -5036,13 +5024,16 @@ int ast_pbx_outgoing_app(const char *type, int format, void *data, int timeout,
                        if (locked_channel) 
                                ast_mutex_unlock(&chan->lock);
                        ast_hangup(chan);
-                       return -1;
+                       res = -1;
+                       goto outgoing_app_cleanup;
                } else {
                        if (locked_channel)
                                *locked_channel = chan;
                }
                res = 0;
        }
+outgoing_app_cleanup:
+       ast_variables_destroy(vars);
        return res;
 }