include "logger.h" and errno.h from asterisk.h - usage shows that they
[asterisk/asterisk.git] / apps / app_dial.c
index 29f059a..dfaa682 100644 (file)
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
 #include <sys/time.h>
 #include <sys/signal.h>
 #include <sys/stat.h>
@@ -42,7 +36,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include "asterisk/lock.h"
 #include "asterisk/file.h"
-#include "asterisk/logger.h"
 #include "asterisk/channel.h"
 #include "asterisk/pbx.h"
 #include "asterisk/options.h"
@@ -66,7 +59,7 @@ static char *app = "Dial";
 static char *synopsis = "Place a call and connect to the current channel";
 
 static char *descrip =
-"  Dial(Technology/resource[&Tech2/resource2...][|timeout][|options][|URL]):\n"
+"  Dial(Technology/resource[&Tech2/resource2...][,timeout][,options][,URL]):\n"
 "This application will place calls to one or more specified channels. As soon\n"
 "as one of the requested channels answers, the originating channel will be\n"
 "answered, if it has not already been answered. These two channels will then\n"
@@ -215,7 +208,7 @@ static char *descrip =
 static char *rapp = "RetryDial";
 static char *rsynopsis = "Place a call, retrying on failure allowing optional exit extension.";
 static char *rdescrip =
-"  RetryDial(announce|sleep|retries|dialargs): This application will attempt to\n"
+"  RetryDial(announce,sleep,retries,dialargs): This application will attempt to\n"
 "place a call using the normal Dial application. If no channel can be reached,\n"
 "the 'announce' file will be played. Then, it will wait 'sleep' number of\n"
 "seconds before retying the call. After 'retires' number of attempts, the\n"
@@ -278,7 +271,7 @@ enum {
        OPT_ARG_ARRAY_SIZE,
 };
 
-AST_APP_OPTIONS(dial_exec_options, {
+AST_APP_OPTIONS(dial_exec_options, BEGIN_OPTIONS
        AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE),
        AST_APP_OPTION('C', OPT_RESETCDR),
        AST_APP_OPTION('c', OPT_CANCEL_ELSEWHERE),
@@ -293,13 +286,15 @@ AST_APP_OPTIONS(dial_exec_options, {
        AST_APP_OPTION('i', OPT_IGNORE_FORWARDING),
        AST_APP_OPTION('k', OPT_CALLEE_PARK),
        AST_APP_OPTION('K', OPT_CALLER_PARK),
+       AST_APP_OPTION('k', OPT_CALLEE_PARK),
+       AST_APP_OPTION('K', OPT_CALLER_PARK),
        AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
        AST_APP_OPTION_ARG('m', OPT_MUSICBACK, OPT_ARG_MUSICBACK),
        AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO),
        AST_APP_OPTION('n', OPT_SCREEN_NOINTRO),
        AST_APP_OPTION('N', OPT_SCREEN_NOCLID),
-       AST_APP_OPTION_ARG('O', OPT_OPERMODE,OPT_ARG_OPERMODE),
        AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
+       AST_APP_OPTION_ARG('O', OPT_OPERMODE,OPT_ARG_OPERMODE),
        AST_APP_OPTION('p', OPT_SCREENING),
        AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
        AST_APP_OPTION('r', OPT_RINGBACK),
@@ -309,7 +304,11 @@ AST_APP_OPTIONS(dial_exec_options, {
        AST_APP_OPTION_ARG('U', OPT_CALLEE_GOSUB, OPT_ARG_CALLEE_GOSUB),
        AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
        AST_APP_OPTION('W', OPT_CALLER_MONITOR),
-});
+END_OPTIONS );
+
+#define CAN_EARLY_BRIDGE(flags) (!ast_test_flag64(flags, OPT_CALLEE_HANGUP | \
+       OPT_CALLER_HANGUP | OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER | \
+       OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR | OPT_CALLEE_PARK | OPT_CALLER_PARK))
 
 /*
  * The list of active channels
@@ -474,12 +473,10 @@ static void do_forward(struct chanlist *o,
        /* Before processing channel, go ahead and check for forwarding */
        o->forwards++;
        if (o->forwards < AST_MAX_FORWARDS) {
-               if (option_verbose > 2)
-                       ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
+               ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
                /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
                if (ast_test_flag64(peerflags, OPT_IGNORE_FORWARDING)) {
-                       if (option_verbose > 2)
-                               ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
+                       ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
                        c = o->chan = NULL;
                        cause = AST_CAUSE_BUSY;
                } else {
@@ -493,8 +490,7 @@ static void do_forward(struct chanlist *o,
                                ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
                }
        } else {
-               if (option_verbose > 2)
-                       ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", c->name);
+               ast_verb(3, "Too many forwards from %s\n", c->name);
                cause = AST_CAUSE_CONGESTION;
                c = o->chan = NULL;
        }
@@ -563,6 +559,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
        struct ast_channel *peer = NULL;
        /* single is set if only one destination is enabled */
        int single = outgoing && !outgoing->next && !ast_test_flag64(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
+#ifdef HAVE_EPOLL
+       struct chanlist *epollo;
+#endif
        
        if (single) {
                /* Turn off hold music, etc */
@@ -570,7 +569,11 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                /* If we are calling a single channel, make them compatible for in-band tone purpose */
                ast_channel_make_compatible(outgoing->chan, in);
        }
-       
+
+#ifdef HAVE_EPOLL
+       for (epollo = outgoing; epollo; epollo = epollo->next)
+               ast_poll_channel_add(in, epollo->chan);
+#endif 
        
        while (*to && !peer) {
                struct chanlist *o;
@@ -588,8 +591,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                }
                if (pos == 1) { /* only the input channel is available */
                        if (numlines == (num.busy + num.congestion + num.nochan)) {
-                               if (option_verbose > 2)
-                                       ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
+                               ast_verb(2, "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
                                if (num.busy)
                                        strcpy(pa->status, "BUSY");     
                                else if (num.congestion)
@@ -597,8 +599,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                else if (num.nochan)
                                        strcpy(pa->status, "CHANUNAVAIL");
                        } else {
-                               if (option_verbose > 2)
-                                       ast_verbose(VERBOSE_PREFIX_3 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
+                               ast_verb(3, "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
                        }
                        *to = 0;
                        return NULL;
@@ -612,8 +613,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                continue;
                        if (ast_test_flag64(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) {
                                if (!peer) {
-                                       if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name);
+                                       ast_verb(3, "%s answered %s\n", c->name, in->name);
                                        peer = c;
                                        ast_copy_flags64(peerflags, o,
                                                       OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
@@ -647,8 +647,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                case AST_CONTROL_ANSWER:
                                        /* This is our guy if someone answered. */
                                        if (!peer) {
-                                               if (option_verbose > 2)
-                                                       ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name);
+                                               ast_verb(3, "%s answered %s\n", c->name, in->name);
                                                peer = c;
                                                ast_copy_flags64(peerflags, o,
                                                               OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
@@ -658,16 +657,16 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                                               DIAL_NOFORWARDHTML);
                                                ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext));
                                                ast_copy_string(c->exten, "", sizeof(c->exten));
-                                               /* Setup early bridge if appropriate */
-                                               ast_channel_early_bridge(in, peer);
+                                               if (CAN_EARLY_BRIDGE(peerflags))
+                                                       /* Setup early bridge if appropriate */
+                                                       ast_channel_early_bridge(in, peer);
                                        }
                                        /* If call has been answered, then the eventual hangup is likely to be normal hangup */
                                        in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
                                        c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
                                        break;
                                case AST_CONTROL_BUSY:
-                                       if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", c->name);
+                                       ast_verb(3, "%s is busy\n", c->name);
                                        in->hangupcause = c->hangupcause;
                                        ast_hangup(c);
                                        c = o->chan = NULL;
@@ -675,8 +674,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                        handle_cause(AST_CAUSE_BUSY, &num);
                                        break;
                                case AST_CONTROL_CONGESTION:
-                                       if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_3 "%s is circuit-busy\n", c->name);
+                                       ast_verb(3, "%s is circuit-busy\n", c->name);
                                        in->hangupcause = c->hangupcause;
                                        ast_hangup(c);
                                        c = o->chan = NULL;
@@ -684,10 +682,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                        handle_cause(AST_CAUSE_CONGESTION, &num);
                                        break;
                                case AST_CONTROL_RINGING:
-                                       if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", c->name);
+                                       ast_verb(3, "%s is ringing\n", c->name);
                                        /* Setup early media if appropriate */
-                                       if (single)
+                                       if (single && CAN_EARLY_BRIDGE(peerflags))
                                                ast_channel_early_bridge(in, c);
                                        if (!(pa->sentringing) && !ast_test_flag64(outgoing, OPT_MUSICBACK)) {
                                                ast_indicate(in, AST_CONTROL_RINGING);
@@ -695,35 +692,30 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                        }
                                        break;
                                case AST_CONTROL_PROGRESS:
-                                       if (option_verbose > 2)
-                                               ast_verbose (VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", c->name, in->name);
+                                       ast_verb(3, "%s is making progress passing it to %s\n", c->name, in->name);
                                        /* Setup early media if appropriate */
-                                       if (single)
+                                       if (single && CAN_EARLY_BRIDGE(peerflags))
                                                ast_channel_early_bridge(in, c);
                                        if (!ast_test_flag64(outgoing, OPT_RINGBACK))
                                                ast_indicate(in, AST_CONTROL_PROGRESS);
                                        break;
                                case AST_CONTROL_VIDUPDATE:
-                                       if (option_verbose > 2)
-                                               ast_verbose (VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", c->name, in->name);
+                                       ast_verb(3, "%s requested a video update, passing it to %s\n", c->name, in->name);
                                        ast_indicate(in, AST_CONTROL_VIDUPDATE);
                                        break;
                                case AST_CONTROL_PROCEEDING:
-                                       if (option_verbose > 2)
-                                               ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", c->name, in->name);
-                                       if (single)
+                                       ast_verb(3, "%s is proceeding passing it to %s\n", c->name, in->name);
+                                       if (single && CAN_EARLY_BRIDGE(peerflags))
                                                ast_channel_early_bridge(in, c);
                                        if (!ast_test_flag64(outgoing, OPT_RINGBACK))
                                                ast_indicate(in, AST_CONTROL_PROCEEDING);
                                        break;
                                case AST_CONTROL_HOLD:
-                                       if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", c->name);
+                                       ast_verb(3, "Call on %s placed on hold\n", c->name);
                                        ast_indicate(in, AST_CONTROL_HOLD);
                                        break;
                                case AST_CONTROL_UNHOLD:
-                                       if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", c->name);
+                                       ast_verb(3, "Call on %s left from hold\n", c->name);
                                        ast_indicate(in, AST_CONTROL_UNHOLD);
                                        break;
                                case AST_CONTROL_OFFHOOK:
@@ -732,8 +724,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                        break;
                                case -1:
                                        if (!ast_test_flag64(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) {
-                                               if (option_verbose > 2)
-                                                       ast_verbose(VERBOSE_PREFIX_3 "%s stopped sounds\n", c->name);
+                                               ast_verb(3, "%s stopped sounds\n", c->name);
                                                ast_indicate(in, -1);
                                                pa->sentringing = 0;
                                        }
@@ -782,8 +773,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                if (ast_test_flag64(peerflags, OPT_DTMF_EXIT)) {
                                        const char *context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
                                        if (onedigit_goto(in, context, (char) f->subclass, 1)) {
-                                               if (option_verbose > 2)
-                                                       ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
+                                               ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
                                                *to=0;
                                                ast_cdr_noanswer(in->cdr);
                                                *result = f->subclass;
@@ -795,8 +785,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
 
                                if (ast_test_flag64(peerflags, OPT_CALLER_HANGUP) && 
                                                  (f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */
-                                       if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
+                                       ast_verb(3, "User hit %c to disconnect call.\n", f->subclass);
                                        *to=0;
                                        strcpy(pa->status, "CANCEL");
                                        ast_cdr_noanswer(in->cdr);
@@ -819,20 +808,24 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
                                ((f->subclass == AST_CONTROL_HOLD) || 
                                 (f->subclass == AST_CONTROL_UNHOLD) || 
                                 (f->subclass == AST_CONTROL_VIDUPDATE))) {
-                               if (option_verbose > 2)
-                                       ast_verbose(VERBOSE_PREFIX_3 "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
+                               ast_verb(3, "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
                                ast_indicate_data(outgoing->chan, f->subclass, f->data, f->datalen);
                        }
                        ast_frfree(f);
                }
-               if (!*to && (option_verbose > 2))
-                       ast_verbose(VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
+               if (!*to)
+                       ast_verb(3, "Nobody picked up in %d ms\n", orig);
                if (!*to || ast_check_hangup(in)) {
                        ast_cdr_noanswer(in->cdr);
                }
                
        }
 
+#ifdef HAVE_EPOLL
+       for (epollo = outgoing; epollo; epollo = epollo->next)
+               ast_poll_channel_del(in, epollo->chan);
+#endif
+
        return peer;
 }
 
@@ -840,7 +833,7 @@ static void replace_macro_delimiter(char *s)
 {
        for (; *s; s++)
                if (*s == '^')
-                       *s = '|';
+                       *s = ',';
 }
 
 
@@ -931,21 +924,20 @@ static int do_timelimit(struct ast_channel *chan, struct ast_bridge_config *conf
        /* more efficient to do it like S(x) does since no advanced opts */
        if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
                *calldurationlimit = config->timelimit / 1000;
-               if (option_verbose > 2)
-                       ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n",
+               ast_verb(3, "Setting call duration limit to %d seconds.\n",
                                *calldurationlimit);
                config->timelimit = play_to_caller = play_to_callee =
                config->play_warning = config->warning_freq = 0;
-       } else if (option_verbose > 2) {
-               ast_verbose(VERBOSE_PREFIX_3 "Limit Data for this call:\n");
-               ast_verbose(VERBOSE_PREFIX_4 "timelimit      = %ld\n", config->timelimit);
-               ast_verbose(VERBOSE_PREFIX_4 "play_warning   = %ld\n", config->play_warning);
-               ast_verbose(VERBOSE_PREFIX_4 "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
-               ast_verbose(VERBOSE_PREFIX_4 "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
-               ast_verbose(VERBOSE_PREFIX_4 "warning_freq   = %ld\n", config->warning_freq);
-               ast_verbose(VERBOSE_PREFIX_4 "start_sound    = %s\n", S_OR(config->start_sound, ""));
-               ast_verbose(VERBOSE_PREFIX_4 "warning_sound  = %s\n", config->warning_sound);
-               ast_verbose(VERBOSE_PREFIX_4 "end_sound      = %s\n", S_OR(config->end_sound, ""));
+       } else {
+               ast_verb(3, "Limit Data for this call:\n");
+               ast_verb(4, "timelimit      = %ld\n", config->timelimit);
+               ast_verb(4, "play_warning   = %ld\n", config->play_warning);
+               ast_verb(4, "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
+               ast_verb(4, "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
+               ast_verb(4, "warning_freq   = %ld\n", config->warning_freq);
+               ast_verb(4, "start_sound    = %s\n", S_OR(config->start_sound, ""));
+               ast_verb(4, "warning_sound  = %s\n", config->warning_sound);
+               ast_verb(4, "end_sound      = %s\n", S_OR(config->end_sound, ""));
        }
         if (play_to_caller)
                 ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
@@ -1039,8 +1031,7 @@ static int do_privacy(struct ast_channel *chan, struct ast_channel *peer,
                static const char *_val[] = { "ALLOW", "DENY", "TORTURE", "KILL", "ALLOW" };
                static const int _flag[] = { AST_PRIVACY_ALLOW, AST_PRIVACY_DENY, AST_PRIVACY_TORTURE, AST_PRIVACY_KILL, AST_PRIVACY_ALLOW};
                int i = res2 - '1';
-               if (option_verbose > 2)
-                       ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to %s\n",
+               ast_verb(3, "--Set privacy database entry %s/%s to %s\n",
                                             opt_args[OPT_ARG_PRIVACY], pa->privcid, _val[i]);
                ast_privacy_set(opt_args[OPT_ARG_PRIVACY], pa->privcid, _flag[i]);
        }
@@ -1079,8 +1070,8 @@ static int do_privacy(struct ast_channel *chan, struct ast_channel *peer,
                        ast_filedelete(pa->privintro, NULL);
                        if( ast_fileexists(pa->privintro, NULL, NULL ) > 0 )
                                ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro);
-                       else if (option_verbose > 2)
-                               ast_verbose(VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", pa->privintro);
+                       else
+                               ast_verb(3, "Successfully deleted %s intro file\n", pa->privintro);
                }
                return 0;       /* the good exit path */
        } else {
@@ -1101,13 +1092,11 @@ static int setup_privacy_args(struct privacy_args *pa,
                l = ast_strdupa(chan->cid.cid_num);
                ast_shrink_phone_number(l);
                if (ast_test_flag64(opts, OPT_PRIVACY) ) {
-                       if (option_verbose > 2)
-                               ast_verbose(VERBOSE_PREFIX_3  "Privacy DB is '%s', clid is '%s'\n",
+                       ast_verb(3, "Privacy DB is '%s', clid is '%s'\n",
                                             opt_args[OPT_ARG_PRIVACY], l);
                        pa->privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l);
                } else {
-                       if (option_verbose > 2)
-                               ast_verbose(VERBOSE_PREFIX_3  "Privacy Screening, clid is '%s'\n", l);
+                       ast_verb(3,  "Privacy Screening, clid is '%s'\n", l);
                        pa->privdb_val = AST_PRIVACY_UNKNOWN;
                }
        } else {
@@ -1119,8 +1108,7 @@ static int setup_privacy_args(struct privacy_args *pa,
                        if (*tn2=='/')  /* any other chars to be afraid of? */
                                *tn2 = '=';
                }
-               if (option_verbose > 2)
-                       ast_verbose(VERBOSE_PREFIX_3  "Privacy-- callerid is empty\n");
+               ast_verb(3, "Privacy-- callerid is empty\n");
 
                snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
                l = callerid;
@@ -1184,8 +1172,8 @@ static int setup_privacy_args(struct privacy_args *pa,
                                ast_filedelete(pa->privintro, NULL);
                                if (ast_fileexists(pa->privintro,NULL,NULL ) > 0 )
                                        ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", pa->privintro);
-                               else if (option_verbose > 2)
-                                       ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", pa->privintro);
+                               else
+                                       ast_verb(3, "Successfully deleted %s intro file\n", pa->privintro);
                                return -1;
                        }
                        if (!ast_streamfile(chan, "vm-dialout", chan->language) )
@@ -1256,8 +1244,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
 
        if (ast_test_flag64(&opts, OPT_OPERMODE)) {
                opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
-               if (option_verbose > 2)
-                       ast_verbose(VERBOSE_PREFIX_3 "Setting operator services mode to %d.\n", opermode);
+               ast_verb(3, "Setting operator services mode to %d.\n", opermode);
        }
        
        if (ast_test_flag64(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
@@ -1267,8 +1254,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                        pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
                        goto done;
                }
-               if (option_verbose > 2)
-                       ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n", calldurationlimit);
+               ast_verb(3, "Setting call duration limit to %d seconds.\n", calldurationlimit);
        }
 
        if (ast_test_flag64(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
@@ -1358,8 +1344,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                        }
                        tmp->forwards++;
                        if (tmp->forwards < AST_MAX_FORWARDS) {
-                               if (option_verbose > 2)
-                                       ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n",
+                               ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n",
                                        chan->name, tech, stuff, tc->name);
                                ast_hangup(tc);
                                /* If we have been told to ignore forwards, just set this channel to null
@@ -1367,8 +1352,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                                if (ast_test_flag64(&opts, OPT_IGNORE_FORWARDING)) {
                                        tc = NULL;
                                        cause = AST_CAUSE_BUSY;
-                                       if (option_verbose > 2)
-                                               ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n",
+                                       ast_verb(3, "Forwarding %s to '%s/%s' prevented.\n",
                                                        chan->name, tech, stuff);
                                } else {
                                        tc = ast_request(tech, chan->nativeformats, stuff, &cause);
@@ -1378,8 +1362,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                                else
                                        ast_channel_inherit_variables(chan, tc);
                        } else {
-                               if (option_verbose > 2)
-                                       ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tc->name);
+                               ast_verb(3, "Too many forwards from %s\n", tc->name);
                                ast_hangup(tc);
                                tc = NULL;
                                cause = AST_CAUSE_CONGESTION;
@@ -1416,6 +1399,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                tc->cid.cid_pres = chan->cid.cid_pres;
                tc->cid.cid_ton = chan->cid.cid_ton;
                tc->cid.cid_tns = chan->cid.cid_tns;
+               tc->cid.cid_ani2 = chan->cid.cid_ani2;
                tc->adsicpe = chan->adsicpe;
                tc->transfercapability = chan->transfercapability;
 
@@ -1443,16 +1427,14 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                if (res) {
                        /* Again, keep going even if there's an error */
                        ast_debug(1, "ast call on peer returned %d\n", res);
-                       if (option_verbose > 2)
-                               ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
+                       ast_verb(3, "Couldn't call %s\n", numsubst);
                        ast_hangup(tc);
                        tc = NULL;
                        ast_free(tmp);
                        continue;
                } else {
                        senddialevent(chan, tc);
-                       if (option_verbose > 2)
-                               ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
+                       ast_verb(3, "Called %s\n", numsubst);
                        if (!ast_test_flag64(peerflags, OPT_ORIGINAL_CLID))
                                ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), get_cid_name(cidname, sizeof(cidname), chan), NULL);
                }
@@ -1558,7 +1540,7 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                        /* Ok, done. stop autoservice */
                        res = ast_autoservice_stop(chan);
                        if (digit > 0 && !res)
-                               res = ast_senddigit(chan, digit); 
+                               res = ast_senddigit(chan, digit, 0); 
                        else
                                res = digit;
 
@@ -1727,12 +1709,12 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                        if (!ast_strlen_zero(dtmfcalled)) { 
                                if (option_verbose > 2)
                                        ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the called party.\n", dtmfcalled);
-                               res = ast_dtmf_stream(peer,chan,dtmfcalled,250);
+                               res = ast_dtmf_stream(peer,chan,dtmfcalled,250,0);
                        }
                        if (!ast_strlen_zero(dtmfcalling)) {
                                if (option_verbose > 2)
                                        ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the calling party.\n", dtmfcalling);
-                               res = ast_dtmf_stream(chan,peer,dtmfcalling,250);
+                               res = ast_dtmf_stream(chan,peer,dtmfcalling,250,0);
                        }
                }
                
@@ -1802,21 +1784,25 @@ static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags
                strcpy(peer->context, chan->context);
 
                if (ast_test_flag64(&opts, OPT_PEER_H) && ast_exists_extension(peer, peer->context, "h", 1, peer->cid.cid_num)) {
+                       int autoloopflag;
+                       int found;
                        strcpy(peer->exten, "h");
                        peer->priority = 1;
-                       while (ast_exists_extension(peer, peer->context, peer->exten, peer->priority, peer->cid.cid_num)) {
-                               if ((res = ast_spawn_extension(peer, peer->context, peer->exten, peer->priority, peer->cid.cid_num))) {
-                                       /* Something bad happened, or a hangup has been requested. */
-                                       ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
-                                       if (option_verbose > 1)
-                                               ast_verbose( VERBOSE_PREFIX_2 "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
-                                       break;
-                               }
+                       autoloopflag = ast_test_flag(peer, AST_FLAG_IN_AUTOLOOP);       /* save value to restore at the end */
+                       ast_set_flag(peer, AST_FLAG_IN_AUTOLOOP);
+                       
+                       while ((res = ast_spawn_extension(peer, peer->context, peer->exten, peer->priority, peer->cid.cid_num, &found,1))) {
                                peer->priority++;
                        }
+                       if (found && res) {
+                               /* Something bad happened, or a hangup has been requested. */
+                               ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
+                               ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", peer->context, peer->exten, peer->priority, peer->name);
+                       }
+                       ast_set2_flag(peer, autoloopflag, AST_FLAG_IN_AUTOLOOP);  /* set it back the way it was */
                }
                if (res != AST_PBX_NO_HANGUP_PEER) {
-                       if (!chan->_softhangup)
+                       if (!ast_check_hangup(chan))
                                chan->hangupcause = peer->hangupcause;
                        ast_hangup(peer);
                }
@@ -1835,7 +1821,7 @@ out:
        senddialendevent(chan, pa.status);
        ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);
        
-       if ((ast_test_flag64(peerflags, OPT_GO_ON)) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE)) {
+       if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_KEEPALIVE)) {
                if (calldurationlimit)
                        chan->whentohangup = 0;
                res = 0;
@@ -1856,41 +1842,33 @@ static int dial_exec(struct ast_channel *chan, void *data)
 
 static int retrydial_exec(struct ast_channel *chan, void *data)
 {
-       char *announce = NULL, *dialdata = NULL;
+       char *parse;
        const char *context = NULL;
        int sleep = 0, loops = 0, res = -1;
-       struct ast_flags64 peerflags;
-       
+       struct ast_flags64 peerflags = { 0, };
+       AST_DECLARE_APP_ARGS(args,
+               AST_APP_ARG(announce);
+               AST_APP_ARG(sleep);
+               AST_APP_ARG(retries);
+               AST_APP_ARG(dialdata);
+       );
+
        if (ast_strlen_zero(data)) {
                ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
                return -1;
        }       
 
-       announce = ast_strdupa(data);
-
-       memset(&peerflags, 0, sizeof(peerflags));
+       parse = ast_strdupa(data);
+       AST_STANDARD_APP_ARGS(args, parse);
 
-       if ((dialdata = strchr(announce, '|'))) {
-               *dialdata++ = '\0';
-               if (sscanf(dialdata, "%d", &sleep) == 1) {
-                       sleep *= 1000;
-               } else {
-                       ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp);
-                       goto done;
-               }
-               if ((dialdata = strchr(dialdata, '|'))) {
-                       *dialdata++ = '\0';
-                       if (sscanf(dialdata, "%d", &loops) != 1) {
-                               ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp);
-                               goto done;
-                       }
-               }
+       if ((sleep = atoi(args.sleep))) {
+               sleep *= 1000;
        }
-       
-       if ((dialdata = strchr(dialdata, '|'))) {
-               *dialdata++ = '\0';
-       } else {
-               ast_log(LOG_ERROR, "%s requires more arguments\n",rapp);
+
+       loops = atoi(args.retries);
+
+       if (!args.dialdata) {
+               ast_log(LOG_ERROR, "%s requires a 4th argument (dialdata)\n", rapp);
                goto done;
        }
                
@@ -1910,18 +1888,18 @@ static int retrydial_exec(struct ast_channel *chan, void *data)
                if (ast_test_flag(chan, AST_FLAG_MOH))
                        ast_moh_stop(chan);
 
-               res = dial_exec_full(chan, dialdata, &peerflags, &continue_exec);
+               res = dial_exec_full(chan, args.dialdata, &peerflags, &continue_exec);
                if (continue_exec)
                        break;
 
                if (res == 0) {
                        if (ast_test_flag64(&peerflags, OPT_DTMF_EXIT)) {
-                               if (!ast_strlen_zero(announce)) {
-                                       if (ast_fileexists(announce, NULL, chan->language) > 0) {
-                                               if(!(res = ast_streamfile(chan, announce, chan->language)))                                                             
+                               if (!ast_strlen_zero(args.announce)) {
+                                       if (ast_fileexists(args.announce, NULL, chan->language) > 0) {
+                                               if(!(res = ast_streamfile(chan, args.announce, chan->language)))                                                                
                                                        ast_waitstream(chan, AST_DIGIT_ANY);
                                        } else
-                                               ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce);
+                                               ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce);
                                }
                                if (!res && sleep) {
                                        if (!ast_test_flag(chan, AST_FLAG_MOH))
@@ -1929,12 +1907,12 @@ static int retrydial_exec(struct ast_channel *chan, void *data)
                                        res = ast_waitfordigit(chan, sleep);
                                }
                        } else {
-                               if (!ast_strlen_zero(announce)) {
-                                       if (ast_fileexists(announce, NULL, chan->language) > 0) {
-                                               if (!(res = ast_streamfile(chan, announce, chan->language)))
+                               if (!ast_strlen_zero(args.announce)) {
+                                       if (ast_fileexists(args.announce, NULL, chan->language) > 0) {
+                                               if (!(res = ast_streamfile(chan, args.announce, chan->language)))
                                                        res = ast_waitstream(chan, "");
                                        } else
-                                               ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", announce);
+                                               ast_log(LOG_WARNING, "Announce file \"%s\" specified in Retrydial does not exist\n", args.announce);
                                }
                                if (sleep) {
                                        if (!ast_test_flag(chan, AST_FLAG_MOH))
@@ -1991,7 +1969,7 @@ static int load_module(void)
        if (!con)
                ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n");
        else
-               ast_add_extension2(con, 1, "s", 1, NULL, NULL, "KeepAlive", ast_strdup(""), ast_free, "app_dial");
+               ast_add_extension2(con, 1, "s", 1, NULL, NULL, "KeepAlive", ast_strdup(""), ast_free_ptr, "app_dial");
 
        res = ast_register_application(app, dial_exec, synopsis, descrip);
        res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);