help text cleanups (bug #4072, with mods)
[asterisk/asterisk.git] / apps / app_dial.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Trivial application to dial a channel and send an URL on answer
5  * 
6  * Copyright (C) 1999 - 2005, Digium, Inc.
7  *
8  * Mark Spencer <markster@digium.com>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include "asterisk/lock.h"
15 #include "asterisk/file.h"
16 #include "asterisk/logger.h"
17 #include "asterisk/channel.h"
18 #include "asterisk/pbx.h"
19 #include "asterisk/options.h"
20 #include "asterisk/module.h"
21 #include "asterisk/translate.h"
22 #include "asterisk/say.h"
23 #include "asterisk/config.h"
24 #include "asterisk/features.h"
25 #include "asterisk/musiconhold.h"
26 #include "asterisk/callerid.h"
27 #include "asterisk/utils.h"
28 #include "asterisk/app.h"
29 #include "asterisk/causes.h"
30 #include "asterisk/manager.h"
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <sys/time.h>
38 #include <sys/signal.h>
39 #include <netinet/in.h>
40
41 static char *tdesc = "Dialing Application";
42
43 static char *app = "Dial";
44
45 static char *synopsis = "Place a call and connect to the current channel";
46
47 static char *descrip =
48 "  Dial(Technology/resource[&Technology2/resource2...][|timeout][|options][|URL]):\n"
49 "Requests one or more channels and places specified outgoing calls on them.\n"
50 "As soon as a channel answers, the Dial app will answer the originating\n"
51 "channel (if it needs to be answered) and will bridge a call with the channel\n"
52 "which first answered. All other calls placed by the Dial app will be hung up.\n"
53 "If a timeout is not specified, the Dial application will wait indefinitely\n"
54 "until either one of the called channels answers, the user hangs up, or all\n"
55 "channels return busy or error. In general, the dialer will return 0 if it\n"
56 "was unable to place the call, or the timeout expired. However, if all\n"
57 "channels were busy, and there exists an extension with priority n+101 (where\n"
58 "n is the priority of the dialer instance), then it will be the next\n"
59 "executed extension (this allows you to setup different behavior on busy from\n"
60 "no-answer).\n"
61 "  This application returns -1 if the originating channel hangs up, or if the\n"
62 "call is bridged and either of the parties in the bridge terminate the call.\n"
63 "The option string may contain zero or more of the following characters:\n"
64 "      'd' -- allow the calling user to dial a 1 digit extension while waiting for a call to\n"
65 "             be answered exiting to that extension if it exists in the context defined by\n"
66 "             ${EXITCONTEXT} or the current context.\n"
67 "      't' -- allow the called user to transfer the calling user by hitting #.\n"
68 "      'T' -- allow the calling user to transfer the call by hitting #.\n"
69 "      'w' -- allow the called user to write the conversation to disk via app_monitor\n"
70 "      'W' -- allow the calling user to write the conversation to disk via app_monitor\n"
71 "      'f' -- Forces callerid to be set as the extension of the line \n"
72 "             making/redirecting the outgoing call. For example, some PSTNs\n"
73 "             don't allow callerids from other extensions then the ones\n"
74 "             that are assigned to you.\n"
75 "      'o' -- Original (inbound) Caller*ID should be placed on the outbound leg of the call\n" 
76 "             instead of using the destination extension (old style asterisk behavior)\n"
77 "      'r' -- indicate ringing to the calling party, pass no audio until answered.\n"
78 "      'm[(class)]' -- provide hold music to the calling party until answered (optionally\n"
79 "                      with the specified class.\n"
80 "      'M(x[^arg])' -- Executes the macro (x with ^ delim arg list) upon connect of the call.\n"
81 "                      Also, the macro can set the MACRO_RESULT variable to do the following:\n"
82 "                     -- ABORT - Hangup both legs of the call.\n"
83 "                     -- CONGESTION - Behave as if line congestion was encountered.\n"
84 "                     -- BUSY - Behave as if a busy signal was encountered. (n+101)\n"
85 "                     -- CONTINUE - Hangup the called party and continue on in the dialplan.\n"
86 "                     -- GOTO:<context>^<exten>^<priority> - Transfer the call.\n"
87 "      'h' -- allow callee to hang up by hitting *.\n"
88 "      'H' -- allow caller to hang up by hitting *.\n"
89 "      'C' -- reset call detail record for this call.\n"
90 "      'P[(x)]' -- privacy mode, using 'x' as database if provided.\n"
91 "      'g' -- goes on in context if the destination channel hangs up\n"
92 "      'G(context^exten^pri)' -- If the call is answered transfer both parties to the specified exten.\n"
93 "      'A(x)' -- play an announcement to the called party, using x as file\n"
94 "      'S(x)' -- hangup the call after x seconds AFTER called party picked up\n"        
95 "      'D([called][:calling])'  -- Send DTMF strings *after* called party has answered, but before the\n"
96 "             call gets bridged. The 'called' DTMF string is sent to the called party, and the\n"
97 "             'calling' DTMF string is sent to the calling party. Both parameters can be used alone.\n"         
98 "      'L(x[:y][:z])' -- Limit the call to 'x' ms warning when 'y' ms are left\n"
99 "             repeated every 'z' ms) Only 'x' is required, 'y' and 'z' are optional.\n"
100 "             The following special variables are optional:\n"
101 "             * LIMIT_PLAYAUDIO_CALLER    yes|no (default yes)\n"
102 "                                         Play sounds to the caller.\n"
103 "             * LIMIT_PLAYAUDIO_CALLEE    yes|no\n"
104 "                                         Play sounds to the callee.\n"
105 "             * LIMIT_TIMEOUT_FILE        File to play when time is up.\n"
106 "             * LIMIT_CONNECT_FILE        File to play when call begins.\n"
107 "             * LIMIT_WARNING_FILE        File to play as warning if 'y' is defined.\n"
108 "                        'timeleft' is a special sound macro to auto-say the time \n"
109 "                        left and is the default.\n"
110 "       'n' -- Do not jump to n+101 if all of the channels were busy.\n\n"
111 "  In addition to transferring the call, a call may be parked and then picked\n"
112 "up by another user.\n"
113 "  The optional URL will be sent to the called party if the channel supports it.\n"
114 "  If the OUTBOUND_GROUP variable is set, all peer channels created by this\n"
115 "  application will be put into that group (as in SetGroup).\n"
116 "  This application sets the following channel variables upon completion:\n"
117 "      DIALEDTIME    Time from dial to answer\n" 
118 "      ANSWEREDTIME  Time for actual call\n"
119 "      DIALSTATUS    The status of the call as a text string, one of\n"
120 "             CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n"
121 "";
122
123 /* RetryDial App by Anthony Minessale II <anthmct@yahoo.com> Jan/2005 */
124 static char *rapp = "RetryDial";
125 static char *rsynopsis = "Place a call, retrying on failure allowing optional exit extension.";
126 static char *rdescrip =
127 "  RetryDial(announce|sleep|loops|Technology/resource[&Technology2/resource2...][|timeout][|options][|URL]):\n"
128 "Attempt to place a call.  If no channel can be reached, play the file defined by 'announce'\n"
129 "waiting 'sleep' seconds to retry the call.  If the specified number of attempts matches \n"
130 "'loops' the call will continue in the dialplan.  If 'loops' is set to 0, the call will retry endlessly.\n\n"
131 "While waiting, a 1 digit extension may be dialed.  If that extension exists in either\n"
132 "the context defined in ${EXITCONTEXT} or the current one, The call will transfer\n"
133 "to that extension immmediately.\n\n"
134 "All arguments after 'loops' are passed directly to the Dial() application.\n"
135 "";
136
137
138 /* We define a customer "local user" structure because we
139    use it not only for keeping track of what is in use but
140    also for keeping track of who we're dialing. */
141
142 #define DIAL_STILLGOING                 (1 << 0)
143 #define DIAL_ALLOWREDIRECT_IN           (1 << 1)
144 #define DIAL_ALLOWREDIRECT_OUT          (1 << 2)
145 #define DIAL_ALLOWDISCONNECT_IN         (1 << 3)
146 #define DIAL_ALLOWDISCONNECT_OUT        (1 << 4)
147 #define DIAL_RINGBACKONLY               (1 << 5)
148 #define DIAL_MUSICONHOLD                (1 << 6)
149 #define DIAL_FORCECALLERID              (1 << 7)
150 #define DIAL_MONITOR_IN                 (1 << 8)
151 #define DIAL_MONITOR_OUT                (1 << 9)
152 #define DIAL_GO_ON                      (1 << 10)
153 #define DIAL_HALT_ON_DTMF               (1 << 11)
154 #define DIAL_PRESERVE_CALLERID          (1 << 12)
155 #define DIAL_NOFORWARDHTML              (1 << 13)
156
157 struct localuser {
158         struct ast_channel *chan;
159         unsigned int flags;
160         int forwards;
161         struct localuser *next;
162 };
163
164 LOCAL_USER_DECL;
165
166 static void hanguptree(struct localuser *outgoing, struct ast_channel *exception)
167 {
168         /* Hang up a tree of stuff */
169         struct localuser *oo;
170         while (outgoing) {
171                 /* Hangup any existing lines we have open */
172                 if (outgoing->chan && (outgoing->chan != exception))
173                         ast_hangup(outgoing->chan);
174                 oo = outgoing;
175                 outgoing=outgoing->next;
176                 free(oo);
177         }
178 }
179
180 #define AST_MAX_FORWARDS   8
181
182 #define AST_MAX_WATCHERS 256
183
184 #define HANDLE_CAUSE(cause, chan) do { \
185         switch(cause) { \
186         case AST_CAUSE_BUSY: \
187                 if (chan->cdr) \
188                         ast_cdr_busy(chan->cdr); \
189                 numbusy++; \
190                 break; \
191         case AST_CAUSE_CONGESTION: \
192         case AST_CAUSE_UNREGISTERED: \
193                 if (chan->cdr) \
194                         ast_cdr_busy(chan->cdr); \
195                 numcongestion++; \
196                 break; \
197         default: \
198                 numnochan++; \
199                 break; \
200         } \
201 } while (0)
202
203
204 static int ast_onedigit_goto(struct ast_channel *chan, char *context, char exten, int pri, char *cid) 
205 {
206         char rexten[2];
207         snprintf(rexten, 2, "%c", exten);
208         if (context) {
209                 if (ast_exists_extension(chan, context, rexten, pri, cid)) {
210                         ast_explicit_goto(chan, context, rexten, pri-1);
211                         return 1;
212                 }
213         } else {
214                 if (ast_exists_extension(chan, chan->context, rexten, pri, cid)) {
215                         ast_explicit_goto(chan, chan->context, rexten, pri-1);
216                         return 1;
217                 } else if (!ast_strlen_zero(chan->macrocontext)) {
218                         if (ast_exists_extension(chan, chan->macrocontext, rexten, pri, cid)) {
219                                 ast_explicit_goto(chan, chan->macrocontext, rexten, pri-1);
220                                 return 1;
221                         }
222                 }
223         }
224         return 0;
225 }
226
227
228 static char *get_cid_name(char *name, int namelen, struct ast_channel *chan)
229 {
230         char *context;
231         char *exten;
232         if (!ast_strlen_zero(chan->macrocontext))
233                 context = chan->macrocontext;
234         else
235                 context = chan->context;
236
237         if (!ast_strlen_zero(chan->macroexten))
238                 exten = chan->macroexten;
239         else
240                 exten = chan->exten;
241
242         if (ast_get_hint(NULL, 0, name, namelen, chan, context, exten))
243                 return name;
244         else
245                 return "";
246 }
247
248 static void senddialevent(struct ast_channel *src, struct ast_channel *dst)
249 {
250         manager_event(EVENT_FLAG_CALL, "Dial", 
251                            "Source: %s\r\n"
252                            "Destination: %s\r\n"
253                            "CallerID: %s\r\n"
254                            "CallerIDName: %s\r\n"
255                            "SrcUniqueID: %s\r\n"
256                            "DestUniqueID: %s\r\n",
257                            src->name, dst->name, src->cid.cid_num ? src->cid.cid_num : "<unknown>",
258                            src->cid.cid_name ? src->cid.cid_name : "<unknown>", src->uniqueid,
259                            dst->uniqueid);
260 }
261
262 static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, struct ast_flags *peerflags, int *sentringing, char *status, size_t statussize, int busystart, int nochanstart, int congestionstart, int nojump, int *result)
263 {
264         struct localuser *o;
265         int found;
266         int numlines;
267         int numbusy = busystart;
268         int numcongestion = congestionstart;
269         int numnochan = nochanstart;
270         int prestart = busystart + congestionstart + nochanstart;
271         int cause;
272         int orig = *to;
273         struct ast_frame *f;
274         struct ast_channel *peer = NULL;
275         struct ast_channel *watchers[AST_MAX_WATCHERS];
276         int pos;
277         int single;
278         struct ast_channel *winner;
279         char *context = NULL;
280         char cidname[AST_MAX_EXTENSION];
281
282         single = (outgoing && !outgoing->next && !ast_test_flag(outgoing, DIAL_MUSICONHOLD | DIAL_RINGBACKONLY));
283         
284         if (single) {
285                 /* Turn off hold music, etc */
286                 ast_deactivate_generator(in);
287                 /* If we are calling a single channel, make them compatible for in-band tone purpose */
288                 ast_channel_make_compatible(outgoing->chan, in);
289         }
290         
291         
292         while (*to && !peer) {
293                 o = outgoing;
294                 found = -1;
295                 pos = 1;
296                 numlines = prestart;
297                 watchers[0] = in;
298                 while (o) {
299                         /* Keep track of important channels */
300                         if (ast_test_flag(o, DIAL_STILLGOING) && o->chan) {
301                                 watchers[pos++] = o->chan;
302                                 found = 1;
303                         }
304                         o = o->next;
305                         numlines++;
306                 }
307                 if (found < 0) {
308                         if (numlines == (numbusy + numcongestion + numnochan)) {
309                                 if (option_verbose > 2)
310                                         ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
311                                 if (numbusy)
312                                         strncpy(status, "BUSY", statussize - 1);
313                                 else if (numcongestion)
314                                         strncpy(status, "CONGESTION", statussize - 1);
315                                 else if (numnochan)
316                                         strncpy(status, "CHANUNAVAIL", statussize - 1);
317                                 /* See if there is a special busy message */
318                                 if (!nojump && ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->cid.cid_num)) 
319                                         in->priority+=100;
320                         } else {
321                                 if (option_verbose > 2)
322                                         ast_verbose( VERBOSE_PREFIX_2 "No one is available to answer at this time (%d:%d/%d/%d)\n", numlines, numbusy, numcongestion, numnochan);
323                         }
324                         *to = 0;
325                         return NULL;
326                 }
327                 winner = ast_waitfor_n(watchers, pos, to);
328                 o = outgoing;
329                 while (o) {
330                         if (ast_test_flag(o, DIAL_STILLGOING) && o->chan && (o->chan->_state == AST_STATE_UP)) {
331                                 if (!peer) {
332                                         if (option_verbose > 2)
333                                                 ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
334                                         peer = o->chan;
335                                         ast_copy_flags(peerflags, o, DIAL_ALLOWREDIRECT_IN|DIAL_ALLOWREDIRECT_OUT|DIAL_ALLOWDISCONNECT_IN|DIAL_ALLOWDISCONNECT_OUT|DIAL_NOFORWARDHTML);
336                                 }
337                         } else if (o->chan && (o->chan == winner)) {
338                                 if (!ast_strlen_zero(o->chan->call_forward)) {
339                                         char tmpchan[256]="";
340                                         char *stuff;
341                                         char *tech;
342                                         strncpy(tmpchan, o->chan->call_forward, sizeof(tmpchan) - 1);
343                                         if ((stuff = strchr(tmpchan, '/'))) {
344                                                 *stuff = '\0';
345                                                 stuff++;
346                                                 tech = tmpchan;
347                                         } else {
348                                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", o->chan->call_forward, o->chan->context);
349                                                 stuff = tmpchan;
350                                                 tech = "Local";
351                                         }
352                                         /* Before processing channel, go ahead and check for forwarding */
353                                         o->forwards++;
354                                         if (o->forwards < AST_MAX_FORWARDS) {
355                                                 if (option_verbose > 2)
356                                                         ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, o->chan->name);
357                                                 /* Setup parameters */
358                                                 o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
359                                                 if (!o->chan)
360                                                         ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
361                                         } else {
362                                                 if (option_verbose > 2)
363                                                         ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", o->chan->name);
364                                                 cause = AST_CAUSE_CONGESTION;
365                                                 o->chan = NULL;
366                                         }
367                                         if (!o->chan) {
368                                                 ast_clear_flag(o, DIAL_STILLGOING);     
369                                                 HANDLE_CAUSE(cause, in);
370                                         } else {
371                                                 if (o->chan->cid.cid_num)
372                                                         free(o->chan->cid.cid_num);
373                                                 o->chan->cid.cid_num = NULL;
374                                                 if (o->chan->cid.cid_name)
375                                                         free(o->chan->cid.cid_name);
376                                                 o->chan->cid.cid_name = NULL;
377
378                                                 if (ast_test_flag(o, DIAL_FORCECALLERID)) {
379                                                         char *newcid = NULL;
380
381                                                         if (strlen(in->macroexten))
382                                                                 newcid = in->macroexten;
383                                                         else
384                                                                 newcid = in->exten;
385                                                         o->chan->cid.cid_num = strdup(newcid);
386                                                         strncpy(o->chan->accountcode, winner->accountcode, sizeof(o->chan->accountcode) - 1);
387                                                         o->chan->cdrflags = winner->cdrflags;
388                                                         if (!o->chan->cid.cid_num)
389                                                                 ast_log(LOG_WARNING, "Out of memory\n");
390                                                 } else {
391                                                         if (in->cid.cid_num) {
392                                                                 o->chan->cid.cid_num = strdup(in->cid.cid_num);
393                                                                 if (!o->chan->cid.cid_num)
394                                                                         ast_log(LOG_WARNING, "Out of memory\n");        
395                                                         }
396                                                         if (in->cid.cid_name) {
397                                                                 o->chan->cid.cid_name = strdup(in->cid.cid_name);
398                                                                 if (!o->chan->cid.cid_name)
399                                                                         ast_log(LOG_WARNING, "Out of memory\n");        
400                                                         }
401                                                         strncpy(o->chan->accountcode, in->accountcode, sizeof(o->chan->accountcode) - 1);
402                                                         o->chan->cdrflags = in->cdrflags;
403                                                 }
404
405                                                 if (in->cid.cid_ani) {
406                                                         if (o->chan->cid.cid_ani)
407                                                                 free(o->chan->cid.cid_ani);
408                                                         o->chan->cid.cid_ani = malloc(strlen(in->cid.cid_ani) + 1);
409                                                         if (o->chan->cid.cid_ani)
410                                                                 strncpy(o->chan->cid.cid_ani, in->cid.cid_ani, strlen(in->cid.cid_ani) + 1);
411                                                         else
412                                                                 ast_log(LOG_WARNING, "Out of memory\n");
413                                                 }
414                                                 if (o->chan->cid.cid_rdnis) 
415                                                         free(o->chan->cid.cid_rdnis);
416                                                 if (!ast_strlen_zero(in->macroexten))
417                                                         o->chan->cid.cid_rdnis = strdup(in->macroexten);
418                                                 else
419                                                         o->chan->cid.cid_rdnis = strdup(in->exten);
420                                                 if (ast_call(o->chan, tmpchan, 0)) {
421                                                         ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
422                                                         ast_clear_flag(o, DIAL_STILLGOING);     
423                                                         ast_hangup(o->chan);
424                                                         o->chan = NULL;
425                                                         numnochan++;
426                                                 } else {
427                                                         senddialevent(in, o->chan);
428                                                         /* After calling, set callerid to extension */
429                                                         if (!ast_test_flag(peerflags, DIAL_PRESERVE_CALLERID))
430                                                                 ast_set_callerid(o->chan, ast_strlen_zero(in->macroexten) ? in->exten : in->macroexten, get_cid_name(cidname, sizeof(cidname), in), NULL);
431                                                 }
432                                         }
433                                         /* Hangup the original channel now, in case we needed it */
434                                         ast_hangup(winner);
435                                         continue;
436                                 }
437                                 f = ast_read(winner);
438                                 if (f) {
439                                         if (f->frametype == AST_FRAME_CONTROL) {
440                                                 switch(f->subclass) {
441                                             case AST_CONTROL_ANSWER:
442                                                         /* This is our guy if someone answered. */
443                                                         if (!peer) {
444                                                                 if (option_verbose > 2)
445                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
446                                                                 peer = o->chan;
447                                                                 ast_copy_flags(peerflags, o, DIAL_ALLOWREDIRECT_IN|DIAL_ALLOWREDIRECT_OUT|DIAL_ALLOWDISCONNECT_IN|DIAL_ALLOWDISCONNECT_OUT|DIAL_NOFORWARDHTML);
448                                                         }
449                                                         /* If call has been answered, then the eventual hangup is likely to be normal hangup */
450                                                         in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
451                                                         o->chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
452                                                         break;
453                                                 case AST_CONTROL_BUSY:
454                                                         if (option_verbose > 2)
455                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is busy\n", o->chan->name);
456                                                         in->hangupcause = o->chan->hangupcause;
457                                                         ast_hangup(o->chan);
458                                                         o->chan = NULL;
459                                                         ast_clear_flag(o, DIAL_STILLGOING);     
460                                                         HANDLE_CAUSE(AST_CAUSE_BUSY, in);
461                                                         break;
462                                                 case AST_CONTROL_CONGESTION:
463                                                         if (option_verbose > 2)
464                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is circuit-busy\n", o->chan->name);
465                                                         in->hangupcause = o->chan->hangupcause;
466                                                         ast_hangup(o->chan);
467                                                         o->chan = NULL;
468                                                         ast_clear_flag(o, DIAL_STILLGOING);
469                                                         HANDLE_CAUSE(AST_CAUSE_CONGESTION, in);
470                                                         break;
471                                                 case AST_CONTROL_RINGING:
472                                                         if (option_verbose > 2)
473                                                                 ast_verbose( VERBOSE_PREFIX_3 "%s is ringing\n", o->chan->name);
474                                                         if (!(*sentringing) && !ast_test_flag(outgoing, DIAL_MUSICONHOLD)) {
475                                                                 ast_indicate(in, AST_CONTROL_RINGING);
476                                                                 (*sentringing)++;
477                                                         }
478                                                         break;
479                                                 case AST_CONTROL_PROGRESS:
480                                                         if (option_verbose > 2)
481                                                                 ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name);
482                                                         if (!ast_test_flag(outgoing, DIAL_RINGBACKONLY))
483                                                                 ast_indicate(in, AST_CONTROL_PROGRESS);
484                                                         break;
485                                                 case AST_CONTROL_HOLD:
486                                                         if (option_verbose > 2)
487                                                                 ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", o->chan->name);
488                                                         ast_indicate(in, AST_CONTROL_HOLD);
489                                                         break;
490                                                 case AST_CONTROL_UNHOLD:
491                                                         if (option_verbose > 2)
492                                                                 ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", o->chan->name);
493                                                         ast_indicate(in, AST_CONTROL_UNHOLD);
494                                                         break;
495                                                 case AST_CONTROL_OFFHOOK:
496                                                 case AST_CONTROL_FLASH:
497                                                         /* Ignore going off hook and flash */
498                                                         break;
499                                                 case -1:
500                                                         if (!ast_test_flag(outgoing, DIAL_RINGBACKONLY | DIAL_MUSICONHOLD)) {
501                                                                 if (option_verbose > 2)
502                                                                         ast_verbose( VERBOSE_PREFIX_3 "%s stopped sounds\n", o->chan->name);
503                                                                 ast_indicate(in, -1);
504                                                                 (*sentringing) = 0;
505                                                         }
506                                                         break;
507                                                 default:
508                                                         ast_log(LOG_DEBUG, "Dunno what to do with control type %d\n", f->subclass);
509                                                 }
510                                         } else if (single && (f->frametype == AST_FRAME_VOICE) && 
511                                                                 !(ast_test_flag(outgoing, DIAL_RINGBACKONLY|DIAL_MUSICONHOLD))) {
512                                                 if (ast_write(in, f)) 
513                                                         ast_log(LOG_WARNING, "Unable to forward frame\n");
514                                         } else if (single && (f->frametype == AST_FRAME_IMAGE) && 
515                                                                 !(ast_test_flag(outgoing, DIAL_RINGBACKONLY|DIAL_MUSICONHOLD))) {
516                                                 if (ast_write(in, f))
517                                                         ast_log(LOG_WARNING, "Unable to forward image\n");
518                                         } else if (single && (f->frametype == AST_FRAME_TEXT) && 
519                                                                 !(ast_test_flag(outgoing, DIAL_RINGBACKONLY|DIAL_MUSICONHOLD))) {
520                                                 if (ast_write(in, f))
521                                                         ast_log(LOG_WARNING, "Unable to text\n");
522                                         } else if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML))
523                                                 ast_channel_sendhtml(in, f->subclass, f->data, f->datalen);
524
525                                         ast_frfree(f);
526                                 } else {
527                                         in->hangupcause = o->chan->hangupcause;
528                                         ast_hangup(o->chan);
529                                         o->chan = NULL;
530                                         ast_clear_flag(o, DIAL_STILLGOING);
531                                 }
532                         }
533                         o = o->next;
534                 }
535                 if (winner == in) {
536                         f = ast_read(in);
537 #if 0
538                         if (f && (f->frametype != AST_FRAME_VOICE))
539                                         printf("Frame type: %d, %d\n", f->frametype, f->subclass);
540                         else if (!f || (f->frametype != AST_FRAME_VOICE))
541                                 printf("Hangup received on %s\n", in->name);
542 #endif
543                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
544                                 /* Got hung up */
545                                 *to=-1;
546                                 strncpy(status, "CANCEL", statussize - 1);
547                                 if (f)
548                                         ast_frfree(f);
549                                 return NULL;
550                         }
551
552                         if (f && (f->frametype == AST_FRAME_DTMF)) {
553                                 if (ast_test_flag(peerflags, DIAL_HALT_ON_DTMF)) {
554                                         context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
555                                         if (ast_onedigit_goto(in, context, (char) f->subclass, 1, in->cid.cid_num)) {
556                                                 if (option_verbose > 3)
557                                                         ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
558                                                 *to=0;
559                                                 *result = f->subclass;
560                                                 strcpy(status, "CANCEL");
561                                                 ast_frfree(f);
562                                                 return NULL;
563                                         }
564                                 }
565
566                                 if (ast_test_flag(peerflags, DIAL_ALLOWDISCONNECT_OUT) && 
567                                                   (f->subclass == '*')) { /* hmm it it not guarenteed to be '*' anymore. */
568                                         if (option_verbose > 3)
569                                                 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
570                                         *to=0;
571                                         strcpy(status, "CANCEL");
572                                         ast_frfree(f);
573                                         return NULL;
574                                 }
575                         }
576
577                         /* Forward HTML stuff */
578                         if (single && f && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) 
579                                 ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen);
580                         
581
582                         if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF)))  {
583                                 if (ast_write(outgoing->chan, f))
584                                         ast_log(LOG_WARNING, "Unable to forward voice\n");
585                                 ast_frfree(f);
586                         }
587                 }
588                 if (!*to && (option_verbose > 2))
589                         ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
590         }
591
592         return peer;
593         
594 }
595
596
597 static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags *peerflags)
598 {
599         int res=-1;
600         struct localuser *u;
601         char *info, *peers, *timeout, *tech, *number, *rest, *cur;
602         char  privdb[256] = "", *s;
603         char  announcemsg[256] = "", *ann;
604         struct localuser *outgoing=NULL, *tmp;
605         struct ast_channel *peer;
606         int to;
607         int hasmacro = 0;
608         int privacy=0;
609         int announce=0;
610         int resetcdr=0;
611         int numbusy = 0;
612         int numcongestion = 0;
613         int numnochan = 0;
614         int cause;
615         char numsubst[AST_MAX_EXTENSION];
616         char restofit[AST_MAX_EXTENSION];
617         char cidname[AST_MAX_EXTENSION];
618         char *transfer = NULL;
619         char *newnum;
620         char *l;
621         char *url=NULL; /* JDG */
622         unsigned int calldurationlimit=0;
623         char *cdl;
624         time_t now;
625         struct ast_bridge_config config;
626         long timelimit = 0;
627         long play_warning = 0;
628         long warning_freq=0;
629         char *warning_sound=NULL;
630         char *end_sound=NULL;
631         char *start_sound=NULL;
632         char *limitptr;
633         char limitdata[256];
634         char *sdtmfptr;
635         char *dtmfcalled=NULL, *dtmfcalling=NULL;
636         char *stack,*var;
637         char *mac = NULL, *macroname = NULL;
638         char status[256]="";
639         char toast[80];
640         int play_to_caller=0,play_to_callee=0;
641         int playargs=0, sentringing=0, moh=0;
642         char *mohclass = NULL;
643         char *outbound_group = NULL;
644         char *macro_result = NULL, *macro_transfer_dest = NULL;
645         int digit = 0, result = 0;
646         time_t start_time, answer_time, end_time;
647         struct ast_app *app = NULL;
648         char *dblgoto = NULL;
649         int nojump = 0;
650
651         if (!data) {
652                 ast_log(LOG_WARNING, "Dial requires an argument (technology1/number1&technology2/number2...|optional timeout|options)\n");
653                 return -1;
654         }
655
656         if (!(info = ast_strdupa(data))) {
657                 ast_log(LOG_WARNING, "Unable to dupe data :(\n");
658                 return -1;
659         }
660         LOCAL_USER_ADD(u);
661         
662         peers = info;
663         if (peers) {
664                 
665                 timeout = strchr(info, '|');
666                 if (timeout) {
667                         *timeout = '\0';
668                         timeout++;
669                         transfer = strchr(timeout, '|');
670                         if (transfer) {
671                                 *transfer = '\0';
672                                 transfer++;
673                                 /* JDG */
674                                 url = strchr(transfer, '|');
675                                 if (url) {
676                                         *url = '\0';
677                                         url++;
678                                         if (option_debug)
679                                                 ast_log(LOG_DEBUG, "DIAL WITH URL=%s_\n", url);
680                                 } else 
681                                         if (option_debug) {
682                                                 ast_log(LOG_DEBUG, "SIMPLE DIAL (NO URL)\n");
683                                         }
684                                 /* /JDG */
685                         }
686                 }
687         } else
688                 timeout = NULL;
689         if (!peers || ast_strlen_zero(peers)) {
690                 ast_log(LOG_WARNING, "Dial argument takes format (technology1/number1&technology2/number2...|optional timeout)\n");
691                 goto out;
692         }
693         
694
695         if (transfer) {
696
697                 /* Extract call duration limit */
698                 if ((cdl = strstr(transfer, "S("))) {
699                         calldurationlimit=atoi(cdl+2);
700                         if (option_verbose > 2)
701                                 ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit);                 
702                 } 
703
704                 /* Extract DTMF strings to send upon successfull connect */
705                 if ((sdtmfptr = strstr(transfer, "D("))) {
706                         dtmfcalled = ast_strdupa(sdtmfptr + 2);
707                         dtmfcalling = strchr(dtmfcalled, ')');
708                         if (dtmfcalling)
709                                 *dtmfcalling = '\0';
710                         dtmfcalling = strchr(dtmfcalled, ':');
711                         if (dtmfcalling) {
712                                 *dtmfcalling = '\0';
713                                 dtmfcalling++;
714                         }                               
715                         /* Overwrite with X's what was the sdtmf info */
716                         while (*sdtmfptr && (*sdtmfptr != ')')) 
717                                 *(sdtmfptr++) = 'X';
718                         if (*sdtmfptr)
719                                 *sdtmfptr = 'X';
720                         else 
721                                 ast_log(LOG_WARNING, "D( Data lacking trailing ')'\n");
722                 }
723   
724                 /* XXX LIMIT SUPPORT */
725                 if ((limitptr = strstr(transfer, "L("))) {
726                         strncpy(limitdata, limitptr + 2, sizeof(limitdata) - 1);
727                         /* Overwrite with X's what was the limit info */
728                         while (*limitptr && (*limitptr != ')')) 
729                                 *(limitptr++) = 'X';
730                         if (*limitptr)
731                                 *limitptr = 'X';
732                         /* Now find the end */
733                         limitptr = strchr(limitdata, ')');
734                         if (limitptr)
735                                 *limitptr = '\0';
736                         else
737                                 ast_log(LOG_WARNING, "Limit Data lacking trailing ')'\n");
738
739                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
740                         play_to_caller = var ? ast_true(var) : 1;
741                   
742                         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
743                         play_to_callee = var ? ast_true(var) : 0;
744                   
745                         if (!play_to_caller && !play_to_callee)
746                                 play_to_caller=1;
747                   
748                         var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
749                         warning_sound = var ? var : "timeleft";
750
751                         var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
752                         end_sound = var ? var : NULL;
753
754                         var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
755                         start_sound = var ? var : NULL;
756
757                         var=stack=limitdata;
758
759                         var = strsep(&stack, ":");
760                         if (var) {
761                                 timelimit = atol(var);
762                                 playargs++;
763                                 var = strsep(&stack, ":");
764                                 if (var) {
765                                         play_warning = atol(var);
766                                         playargs++;
767                                         var = strsep(&stack, ":");
768                                         if (var) {
769                                                 warning_freq = atol(var);
770                                                 playargs++;
771                                         }
772                                 }
773                         }
774                   
775                         if (!timelimit) {
776                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
777                                 warning_sound=NULL;
778                         }
779                         /* undo effect of S(x) in case they are both used */
780                         calldurationlimit=0; 
781                         /* more efficient do it like S(x) does since no advanced opts*/
782                         if (!play_warning && !start_sound && !end_sound && timelimit) { 
783                                 calldurationlimit=timelimit/1000;
784                                 timelimit=play_to_caller=play_to_callee=play_warning=warning_freq=0;
785                         } else if (option_verbose > 2) {
786                                 ast_verbose(VERBOSE_PREFIX_3"Limit Data:\n");
787                                 ast_verbose(VERBOSE_PREFIX_3"timelimit=%ld\n",timelimit);
788                                 ast_verbose(VERBOSE_PREFIX_3"play_warning=%ld\n",play_warning);
789                                 ast_verbose(VERBOSE_PREFIX_3"play_to_caller=%s\n",play_to_caller ? "yes" : "no");
790                                 ast_verbose(VERBOSE_PREFIX_3"play_to_callee=%s\n",play_to_callee ? "yes" : "no");
791                                 ast_verbose(VERBOSE_PREFIX_3"warning_freq=%ld\n",warning_freq);
792                                 ast_verbose(VERBOSE_PREFIX_3"start_sound=%s\n",start_sound ? start_sound : "UNDEF");
793                                 ast_verbose(VERBOSE_PREFIX_3"warning_sound=%s\n",warning_sound ? warning_sound : "UNDEF");
794                                 ast_verbose(VERBOSE_PREFIX_3"end_sound=%s\n",end_sound ? end_sound : "UNDEF");
795                         }
796                 }
797                 
798                 /* XXX ANNOUNCE SUPPORT */
799                 if ((ann = strstr(transfer, "A("))) {
800                         announce = 1;
801                         strncpy(announcemsg, ann + 2, sizeof(announcemsg) - 1);
802                         /* Overwrite with X's what was the announce info */
803                         while (*ann && (*ann != ')')) 
804                                 *(ann++) = 'X';
805                         if (*ann)
806                                 *ann = 'X';
807                         /* Now find the end of the privdb */
808                         ann = strchr(announcemsg, ')');
809                         if (ann)
810                                 *ann = '\0';
811                         else {
812                                 ast_log(LOG_WARNING, "Transfer with Announce spec lacking trailing ')'\n");
813                                 announce = 0;
814                         }
815                 }
816
817                 /* Get the goto from the dial option string */
818                 if ((mac = strstr(transfer, "G("))) {
819
820
821                         dblgoto = ast_strdupa(mac + 2);
822                         while (*mac && (*mac != ')'))
823                                 *(mac++) = 'X';
824                         if (*mac)
825                                 *mac = 'X';
826                         else {
827                                 ast_log(LOG_WARNING, "Could not find exten to which we should jump.\n");
828                                 dblgoto = NULL;
829                         }
830                         mac = strchr(dblgoto, ')');
831                         if (mac)
832                                 *mac = '\0';
833                         else {
834                                 ast_log(LOG_WARNING, "Goto flag set without trailing ')'\n");
835                                 dblgoto = NULL;
836                         }
837                 }
838
839                 /* Get the macroname from the dial option string */
840                 if ((mac = strstr(transfer, "M("))) {
841                         hasmacro = 1;
842                         macroname = ast_strdupa(mac + 2);
843                         while (*mac && (*mac != ')'))
844                                 *(mac++) = 'X';
845                         if (*mac)
846                                 *mac = 'X';
847                         else {
848                                 ast_log(LOG_WARNING, "Could not find macro to which we should jump.\n");
849                                 hasmacro = 0;
850                         }
851                         mac = strchr(macroname, ')');
852                         if (mac)
853                                 *mac = '\0';
854                         else {
855                                 ast_log(LOG_WARNING, "Macro flag set without trailing ')'\n");
856                                 hasmacro = 0;
857                         }
858                 }
859                 /* Get music on hold class */
860                 if ((mac = strstr(transfer, "m("))) {
861                         mohclass = ast_strdupa(mac + 2);
862                         mac++; /* Leave the "m" in the string */
863                         while (*mac && (*mac != ')'))
864                                 *(mac++) = 'X';
865                         if (*mac) {
866                                 *mac = 'X';
867                                 mac = strchr(mohclass, ')');
868                                 if (mac)
869                                         *mac = '\0';
870                                 else {
871                                         ast_log(LOG_WARNING, "Music on hold class specified without trailing ')'\n");
872                                         mohclass = NULL;
873                                 }
874                         } else {
875                                 ast_log(LOG_WARNING, "Could not find music on hold class to use, assuming default.\n");
876                                 mohclass=NULL;
877                         }
878                 }
879                 /* Extract privacy info from transfer */
880                 if ((s = strstr(transfer, "P("))) {
881                         privacy = 1;
882                         strncpy(privdb, s + 2, sizeof(privdb) - 1);
883                         /* Overwrite with X's what was the privacy info */
884                         while (*s && (*s != ')')) 
885                                 *(s++) = 'X';
886                         if (*s)
887                                 *s = 'X';
888                         /* Now find the end of the privdb */
889                         s = strchr(privdb, ')');
890                         if (s)
891                                 *s = '\0';
892                         else {
893                                 ast_log(LOG_WARNING, "Transfer with privacy lacking trailing ')'\n");
894                                 privacy = 0;
895                         }
896                 } else if (strchr(transfer, 'P')) {
897                         /* No specified privdb */
898                         privacy = 1;
899                 } else if (strchr(transfer, 'C')) {
900                         resetcdr = 1;
901                 } else if (strchr(transfer, 'n')) {
902                         nojump = 1;
903                 }
904         }
905         if (resetcdr && chan->cdr)
906                 ast_cdr_reset(chan->cdr, 0);
907         if (ast_strlen_zero(privdb) && privacy) {
908                 /* If privdb is not specified and we are using privacy, copy from extension */
909                 strncpy(privdb, chan->exten, sizeof(privdb) - 1);
910         }
911         if (privacy) {
912                 l = chan->cid.cid_num;
913                 if (!l)
914                         l = "";
915                 ast_log(LOG_NOTICE, "Privacy DB is '%s', privacy is %d, clid is '%s'\n", privdb, privacy, l);
916         }
917
918         /* If a channel group has been specified, get it for use when we create peer channels */
919         outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
920
921         cur = peers;
922         do {
923                 /* Remember where to start next time */
924                 rest = strchr(cur, '&');
925                 if (rest) {
926                         *rest = 0;
927                         rest++;
928                 }
929                 /* Get a technology/[device:]number pair */
930                 tech = cur;
931                 number = strchr(tech, '/');
932                 if (!number) {
933                         ast_log(LOG_WARNING, "Dial argument takes format (technology1/[device:]number1&technology2/[device:]number2...|optional timeout)\n");
934                         goto out;
935                 }
936                 *number = '\0';
937                 number++;
938                 tmp = malloc(sizeof(struct localuser));
939                 if (!tmp) {
940                         ast_log(LOG_WARNING, "Out of memory\n");
941                         goto out;
942                 }
943                 memset(tmp, 0, sizeof(struct localuser));
944                 if (transfer) {
945                         ast_set2_flag(tmp, strchr(transfer, 't'), DIAL_ALLOWREDIRECT_IN);
946                         ast_set2_flag(tmp, strchr(transfer, 'T'), DIAL_ALLOWREDIRECT_OUT);
947                         ast_set2_flag(tmp, strchr(transfer, 'r'), DIAL_RINGBACKONLY);   
948                         ast_set2_flag(tmp, strchr(transfer, 'm'), DIAL_MUSICONHOLD);    
949                         ast_set2_flag(tmp, strchr(transfer, 'H'), DIAL_ALLOWDISCONNECT_OUT);    
950                         ast_set2_flag(peerflags, strchr(transfer, 'H'), DIAL_ALLOWDISCONNECT_OUT);      
951                         ast_set2_flag(tmp, strchr(transfer, 'h'), DIAL_ALLOWDISCONNECT_IN);
952                         ast_set2_flag(peerflags, strchr(transfer, 'h'), DIAL_ALLOWDISCONNECT_IN);
953                         ast_set2_flag(tmp, strchr(transfer, 'f'), DIAL_FORCECALLERID);  
954                         ast_set2_flag(tmp, url, DIAL_NOFORWARDHTML);    
955                         ast_set2_flag(peerflags, strchr(transfer, 'w'), DIAL_MONITOR_IN);       
956                         ast_set2_flag(peerflags, strchr(transfer, 'W'), DIAL_MONITOR_OUT);      
957                         ast_set2_flag(peerflags, strchr(transfer, 'd'), DIAL_HALT_ON_DTMF);     
958                         ast_set2_flag(peerflags, strchr(transfer, 'g'), DIAL_GO_ON);    
959                         ast_set2_flag(peerflags, strchr(transfer, 'o'), DIAL_PRESERVE_CALLERID);        
960                 }
961                 strncpy(numsubst, number, sizeof(numsubst)-1);
962                 /* If we're dialing by extension, look at the extension to know what to dial */
963                 if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
964                         strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
965                         snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", chan->exten,restofit);
966                         if (option_debug)
967                                 ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
968                 }
969                 /* Request the peer */
970                 tmp->chan = ast_request(tech, chan->nativeformats, numsubst, &cause);
971                 if (!tmp->chan) {
972                         /* If we can't, just go on to the next call */
973                         ast_log(LOG_NOTICE, "Unable to create channel of type '%s' (cause %d)\n", tech, cause);
974                         HANDLE_CAUSE(cause, chan);
975                         cur = rest;
976                         continue;
977                 }
978                 pbx_builtin_setvar_helper(tmp->chan, "DIALEDPEERNUMBER", numsubst);
979                 if (!ast_strlen_zero(tmp->chan->call_forward)) {
980                         char tmpchan[256]="";
981                         char *stuff;
982                         char *tech;
983                         strncpy(tmpchan, tmp->chan->call_forward, sizeof(tmpchan) - 1);
984                         if ((stuff = strchr(tmpchan, '/'))) {
985                                 *stuff = '\0';
986                                 stuff++;
987                                 tech = tmpchan;
988                         } else {
989                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tmp->chan->call_forward, tmp->chan->context);
990                                 stuff = tmpchan;
991                                 tech = "Local";
992                         }
993                         tmp->forwards++;
994                         if (tmp->forwards < AST_MAX_FORWARDS) {
995                                 if (option_verbose > 2)
996                                         ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", chan->name, tech, stuff, tmp->chan->name);
997                                 ast_hangup(tmp->chan);
998                                 /* Setup parameters */
999                                 tmp->chan = ast_request(tech, chan->nativeformats, stuff, &cause);
1000                                 if (!tmp->chan)
1001                                         ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
1002                         } else {
1003                                 if (option_verbose > 2)
1004                                         ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tmp->chan->name);
1005                                 ast_hangup(tmp->chan);
1006                                 tmp->chan = NULL;
1007                                 cause = AST_CAUSE_CONGESTION;
1008                         }
1009                         if (!tmp->chan) {
1010                                 HANDLE_CAUSE(cause, chan);
1011                                 cur = rest;
1012                                 continue;
1013                         }
1014                 }
1015
1016                 /* Inherit specially named variables from parent channel */
1017                 ast_channel_inherit_variables(chan, tmp->chan);
1018
1019                 tmp->chan->appl = "AppDial";
1020                 tmp->chan->data = "(Outgoing Line)";
1021                 tmp->chan->whentohangup = 0;
1022                 if (tmp->chan->cid.cid_num)
1023                         free(tmp->chan->cid.cid_num);
1024                 tmp->chan->cid.cid_num = NULL;
1025                 if (tmp->chan->cid.cid_name)
1026                         free(tmp->chan->cid.cid_name);
1027                 tmp->chan->cid.cid_name = NULL;
1028                 if (tmp->chan->cid.cid_ani)
1029                         free(tmp->chan->cid.cid_ani);
1030                 tmp->chan->cid.cid_ani = NULL;
1031
1032                 if (chan->cid.cid_num) 
1033                         tmp->chan->cid.cid_num = strdup(chan->cid.cid_num);
1034                 if (chan->cid.cid_name) 
1035                         tmp->chan->cid.cid_name = strdup(chan->cid.cid_name);
1036                 if (chan->cid.cid_ani) 
1037                         tmp->chan->cid.cid_ani = strdup(chan->cid.cid_ani);
1038                 
1039                 /* Copy language from incoming to outgoing */
1040                 strncpy(tmp->chan->language, chan->language, sizeof(tmp->chan->language) - 1);
1041                 strncpy(tmp->chan->accountcode, chan->accountcode, sizeof(tmp->chan->accountcode) - 1);
1042                 tmp->chan->cdrflags = chan->cdrflags;
1043                 if (ast_strlen_zero(tmp->chan->musicclass))
1044                         strncpy(tmp->chan->musicclass, chan->musicclass, sizeof(tmp->chan->musicclass) - 1);
1045                 if (chan->cid.cid_rdnis)
1046                         tmp->chan->cid.cid_rdnis = strdup(chan->cid.cid_rdnis);
1047                 /* Pass callingpres setting */
1048                 tmp->chan->cid.cid_pres = chan->cid.cid_pres;
1049                 /* Pass type of number */
1050                 tmp->chan->cid.cid_ton = chan->cid.cid_ton;
1051                 /* Pass type of tns */
1052                 tmp->chan->cid.cid_tns = chan->cid.cid_tns;
1053                 /* Presense of ADSI CPE on outgoing channel follows ours */
1054                 tmp->chan->adsicpe = chan->adsicpe;
1055                 /* Pass the transfer capability */
1056                 tmp->chan->transfercapability = chan->transfercapability;
1057
1058                 /* If we have an outbound group, set this peer channel to it */
1059                 if (outbound_group)
1060                         ast_app_group_set_channel(tmp->chan, outbound_group);
1061
1062                 /* Place the call, but don't wait on the answer */
1063                 res = ast_call(tmp->chan, numsubst, 0);
1064
1065                 /* Save the info in cdr's that we called them */
1066                 if (chan->cdr)
1067                         ast_cdr_setdestchan(chan->cdr, tmp->chan->name);
1068
1069                 /* check the results of ast_call */
1070                 if (res) {
1071                         /* Again, keep going even if there's an error */
1072                         if (option_debug)
1073                                 ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
1074                         else if (option_verbose > 2)
1075                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
1076                         ast_hangup(tmp->chan);
1077                         tmp->chan = NULL;
1078                         cur = rest;
1079                         continue;
1080                 } else {
1081                         senddialevent(chan, tmp->chan);
1082                         if (option_verbose > 2)
1083                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
1084                         if (!ast_test_flag(peerflags, DIAL_PRESERVE_CALLERID))
1085                                 ast_set_callerid(tmp->chan, ast_strlen_zero(chan->macroexten) ? chan->exten : chan->macroexten, get_cid_name(cidname, sizeof(cidname), chan), NULL);
1086                 }
1087                 /* Put them in the list of outgoing thingies...  We're ready now. 
1088                    XXX If we're forcibly removed, these outgoing calls won't get
1089                    hung up XXX */
1090                 ast_set_flag(tmp, DIAL_STILLGOING);     
1091                 tmp->next = outgoing;
1092                 outgoing = tmp;
1093                 /* If this line is up, don't try anybody else */
1094                 if (outgoing->chan->_state == AST_STATE_UP)
1095                         break;
1096                 cur = rest;
1097         } while (cur);
1098         
1099         if (timeout && !ast_strlen_zero(timeout)) {
1100                 to = atoi(timeout);
1101                 if (to > 0)
1102                         to *= 1000;
1103                 else
1104                         ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", timeout);
1105         } else
1106                 to = -1;
1107
1108         if (outgoing) {
1109                 /* Our status will at least be NOANSWER */
1110                 strncpy(status, "NOANSWER", sizeof(status) - 1);
1111                 if (ast_test_flag(outgoing, DIAL_MUSICONHOLD)) {
1112                         moh=1;
1113                         ast_moh_start(chan, mohclass);
1114                 } else if (ast_test_flag(outgoing, DIAL_RINGBACKONLY)) {
1115                         ast_indicate(chan, AST_CONTROL_RINGING);
1116                         sentringing++;
1117                 }
1118         } else
1119                 strncpy(status, "CHANUNAVAIL", sizeof(status) - 1);
1120
1121         time(&start_time);
1122         peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, nojump, &result);
1123         
1124         if (!peer) {
1125                 if (result) {
1126                         res = result;
1127                 }
1128                 else if (to) 
1129                         /* Musta gotten hung up */
1130                         res = -1;
1131                 else 
1132                         /* Nobody answered, next please? */
1133                         res=0;
1134                 
1135                 goto out;
1136         }
1137         if (peer) {
1138                 time(&answer_time);
1139 #ifdef OSP_SUPPORT
1140                 /* Once call is answered, ditch the OSP Handle */
1141                 pbx_builtin_setvar_helper(chan, "_OSPHANDLE", "");
1142 #endif          
1143                 strncpy(status, "ANSWER", sizeof(status) - 1);
1144                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
1145                    we will always return with -1 so that it is hung up properly after the 
1146                    conversation.  */
1147                 hanguptree(outgoing, peer);
1148                 outgoing = NULL;
1149                 /* If appropriate, log that we have a destination channel */
1150                 if (chan->cdr)
1151                         ast_cdr_setdestchan(chan->cdr, peer->name);
1152                 if (peer->name)
1153                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
1154
1155                 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
1156                 if (!number)
1157                         number = numsubst;
1158                 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
1159                 /* JDG: sendurl */
1160                 if ( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
1161                         ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
1162                         ast_channel_sendurl( peer, url );
1163                 } /* /JDG */
1164                 if (announce && announcemsg) {
1165                         /* Start autoservice on the other chan */
1166                         res = ast_autoservice_start(chan);
1167                         /* Now Stream the File */
1168                         if (!res)
1169                                 res = ast_streamfile(peer,announcemsg,peer->language);
1170                         if (!res) {
1171                                 digit = ast_waitstream(peer, AST_DIGIT_ANY); 
1172                         }
1173                         /* Ok, done. stop autoservice */
1174                         res = ast_autoservice_stop(chan);
1175                         if (digit > 0 && !res)
1176                                 res = ast_senddigit(chan, digit); 
1177                         else
1178                                 res = digit;
1179
1180                 } else
1181                         res = 0;
1182
1183                 if (chan && peer && dblgoto) {
1184                         for (mac=dblgoto; *mac; mac++) {
1185                                 if(*mac == '^') {
1186                                         *mac = '|';
1187                                 }
1188                         }
1189                         ast_parseable_goto(chan, dblgoto);
1190                         ast_parseable_goto(peer, dblgoto);
1191                         peer->priority++;
1192                         ast_pbx_start(peer);
1193                         hanguptree(outgoing, NULL);
1194                         LOCAL_USER_REMOVE(u);
1195                         return 0;
1196                 }
1197
1198                 if (hasmacro && macroname) {
1199                         res = ast_autoservice_start(chan);
1200                         if (res) {
1201                                 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
1202                                 res = -1;
1203                         }
1204
1205                         app = pbx_findapp("Macro");
1206
1207                         if (app && !res) {
1208                                 for (res=0;res<strlen(macroname);res++)
1209                                         if (macroname[res] == '^')
1210                                                 macroname[res] = '|';
1211                                 res = pbx_exec(peer, app, macroname, 1);
1212                                 ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
1213                                 res = 0;
1214                         } else {
1215                                 ast_log(LOG_ERROR, "Could not find application Macro\n");
1216                                 res = -1;
1217                         }
1218
1219                         if (ast_autoservice_stop(chan) < 0) {
1220                                 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
1221                                 res = -1;
1222                         }
1223
1224                         if (!res) {
1225                                 if ((macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
1226                                         if (!strcasecmp(macro_result, "BUSY")) {
1227                                                 strncpy(status, macro_result, sizeof(status) - 1);
1228                                                 if (!ast_goto_if_exists(chan, NULL, NULL, chan->priority + 101)) {
1229                                                         ast_set_flag(peerflags, DIAL_GO_ON);
1230                                                 }
1231                                                 res = -1;
1232                                         }
1233                                         else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
1234                                                 strncpy(status, macro_result, sizeof(status) - 1);
1235                                                 ast_set_flag(peerflags, DIAL_GO_ON);    
1236                                                 res = -1;
1237                                         }
1238                                         else if (!strcasecmp(macro_result, "CONTINUE")) {
1239                                                 /* hangup peer and keep chan alive assuming the macro has changed 
1240                                                    the context / exten / priority or perhaps 
1241                                                    the next priority in the current exten is desired.
1242                                                 */
1243                                                 ast_set_flag(peerflags, DIAL_GO_ON);    
1244                                                 res = -1;
1245                                         } else if (!strcasecmp(macro_result, "ABORT")) {
1246                                                 /* Hangup both ends unless the caller has the g flag */
1247                                                 res = -1;
1248                                         } else if (!strncasecmp(macro_result, "GOTO:",5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
1249                                                 res = -1;
1250                                                 /* perform a transfer to a new extension */
1251                                                 if (strchr(macro_transfer_dest,'^')) { /* context^exten^priority*/
1252                                                         /* no brainer mode... substitute ^ with | and feed it to builtin goto */
1253                                                         for (res=0;res<strlen(macro_transfer_dest);res++)
1254                                                                 if (macro_transfer_dest[res] == '^')
1255                                                                         macro_transfer_dest[res] = '|';
1256
1257                                                         if (!ast_parseable_goto(chan, macro_transfer_dest))
1258                                                                 ast_set_flag(peerflags, DIAL_GO_ON);
1259
1260                                                 }
1261                                         }
1262                                 }
1263                         }
1264                 }
1265
1266                 if (!res) {
1267                         if (calldurationlimit > 0) {
1268                                 time(&now);
1269                                 chan->whentohangup = now + calldurationlimit;
1270                         }
1271                         if (dtmfcalled && !ast_strlen_zero(dtmfcalled)) { 
1272                                 if (option_verbose > 2)
1273                                         ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the called party.\n",dtmfcalled);
1274                                 res = ast_dtmf_stream(peer,chan,dtmfcalled,250);
1275                         }
1276                         if (dtmfcalling && !ast_strlen_zero(dtmfcalling)) {
1277                                 if (option_verbose > 2)
1278                                         ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the calling party.\n",dtmfcalling);
1279                                 res = ast_dtmf_stream(chan,peer,dtmfcalling,250);
1280                         }
1281                 }
1282                 
1283                 if (!res) {
1284                         memset(&config,0,sizeof(struct ast_bridge_config));
1285                         if (play_to_caller)
1286                                 ast_set_flag(&(config.features_caller), AST_FEATURE_PLAY_WARNING);
1287                         if (play_to_callee)
1288                                 ast_set_flag(&(config.features_callee), AST_FEATURE_PLAY_WARNING);
1289                         if (ast_test_flag(peerflags, DIAL_ALLOWREDIRECT_IN))
1290                                 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1291                         if (ast_test_flag(peerflags, DIAL_ALLOWREDIRECT_OUT))
1292                                 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1293                         if (ast_test_flag(peerflags, DIAL_ALLOWDISCONNECT_IN))
1294                                 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
1295                         if (ast_test_flag(peerflags, DIAL_ALLOWDISCONNECT_OUT))
1296                                 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
1297                         if (ast_test_flag(peerflags, DIAL_MONITOR_IN))
1298                                 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
1299                         if (ast_test_flag(peerflags, DIAL_MONITOR_OUT)) 
1300                                 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
1301
1302                         config.timelimit = timelimit;
1303                         config.play_warning = play_warning;
1304                         config.warning_freq = warning_freq;
1305                         config.warning_sound = warning_sound;
1306                         config.end_sound = end_sound;
1307                         config.start_sound = start_sound;
1308                         if (moh) {
1309                                 moh = 0;
1310                                 ast_moh_stop(chan);
1311                         } else if (sentringing) {
1312                                 sentringing = 0;
1313                                 ast_indicate(chan, -1);
1314                         }
1315                         /* Be sure no generators are left on it */
1316                         ast_deactivate_generator(chan);
1317                         /* Make sure channels are compatible */
1318                         res = ast_channel_make_compatible(chan, peer);
1319                         if (res < 0) {
1320                                 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
1321                                 ast_hangup(peer);
1322                                 return -1;
1323                         }
1324                         res = ast_bridge_call(chan,peer,&config);
1325                         time(&end_time);
1326                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1327                         pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1328                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
1329                         pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
1330                         
1331                 } else 
1332                         res = -1;
1333                 
1334                 if (res != AST_PBX_NO_HANGUP_PEER) {
1335                         if (!chan->_softhangup)
1336                                 chan->hangupcause = peer->hangupcause;
1337                         ast_hangup(peer);
1338                 }
1339         }       
1340 out:
1341         if (moh) {
1342                 moh = 0;
1343                 ast_moh_stop(chan);
1344         } else if (sentringing) {
1345                 sentringing = 0;
1346                 ast_indicate(chan, -1);
1347         }
1348         hanguptree(outgoing, NULL);
1349         pbx_builtin_setvar_helper(chan, "DIALSTATUS", status);
1350         ast_log(LOG_DEBUG, "Exiting with DIALSTATUS=%s.\n", status);
1351         
1352         LOCAL_USER_REMOVE(u);
1353         
1354         if ((ast_test_flag(peerflags, DIAL_GO_ON)) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE))
1355             res=0;
1356             
1357         return res;
1358 }
1359
1360 static int dial_exec(struct ast_channel *chan, void *data)
1361 {
1362         struct ast_flags peerflags;
1363         memset(&peerflags, 0, sizeof(peerflags));
1364         return dial_exec_full(chan, data, &peerflags);
1365 }
1366
1367 static int retrydial_exec(struct ast_channel *chan, void *data)
1368 {
1369         char *announce = NULL, *context = NULL, *dialdata = NULL;
1370         int sleep = 0, loops = 0, res = 0;
1371         struct localuser *u = NULL;
1372         struct ast_flags peerflags;
1373         
1374         memset(&peerflags, 0, sizeof(peerflags));
1375
1376         LOCAL_USER_ADD(u);
1377         
1378         if (!data || !(announce = ast_strdupa(data))) {
1379                 ast_log(LOG_ERROR, "Out of memory!\n");
1380                 LOCAL_USER_REMOVE(u);
1381                 return -1;
1382         }
1383         
1384         if ((dialdata = strchr(announce, '|'))) {
1385                 *dialdata = '\0';
1386                 dialdata++;
1387                 if ((sleep = atoi(dialdata))) {
1388                         sleep *= 1000;
1389                 } else {
1390                         ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp);
1391                         LOCAL_USER_REMOVE(u);
1392                         return -1;
1393                 }
1394                 if ((dialdata = strchr(dialdata, '|'))) {
1395                         *dialdata = '\0';
1396                         dialdata++;
1397                         if (!(loops = atoi(dialdata))) {
1398                                 ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp);
1399                                 LOCAL_USER_REMOVE(u);
1400                                 return -1;
1401                         }
1402                 }
1403         }
1404         
1405         if ((dialdata = strchr(dialdata, '|'))) {
1406                 *dialdata = '\0';
1407                 dialdata++;
1408         } else {
1409                 ast_log(LOG_ERROR, "%s requires more arguments\n",rapp);
1410                 LOCAL_USER_REMOVE(u);
1411                 return -1;
1412         }
1413                 
1414         if (sleep < 1000)
1415                 sleep = 10000;
1416         
1417         if (!loops)
1418                 loops = -1;
1419         
1420         context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
1421         
1422         while (loops) {
1423                 chan->data = "Retrying";
1424                 if (ast_test_flag(chan, AST_FLAG_MOH))
1425                         ast_moh_stop(chan);
1426
1427                 if ((res = dial_exec_full(chan, dialdata, &peerflags)) == 0) {
1428                         if (ast_test_flag(&peerflags, DIAL_HALT_ON_DTMF)) {
1429                                 if (!(res = ast_streamfile(chan, announce, chan->language)))
1430                                         res = ast_waitstream(chan, AST_DIGIT_ANY);
1431                                 if (!res && sleep) {
1432                                         if (!ast_test_flag(chan, AST_FLAG_MOH))
1433                                                 ast_moh_start(chan, NULL);
1434                                         res = ast_waitfordigit(chan, sleep);
1435                                 }
1436                         } else {
1437                                 if (!(res = ast_streamfile(chan, announce, chan->language)))
1438                                         res = ast_waitstream(chan, "");
1439                                 if (sleep) {
1440                                         if (!ast_test_flag(chan, AST_FLAG_MOH))
1441                                                 ast_moh_start(chan, NULL);
1442                                         if (!res) 
1443                                                 res = ast_safe_sleep(chan, sleep);
1444                                 }
1445                         }
1446                 }
1447
1448                 if (res < 0)
1449                         break;
1450                 else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
1451                         if (ast_onedigit_goto(chan, context, (char) res, 1, chan->cid.cid_num)) {
1452                                 res = 0;
1453                                 break;
1454                         }
1455                 }
1456                 loops--;
1457         }
1458         
1459         if (ast_test_flag(chan, AST_FLAG_MOH))
1460                 ast_moh_stop(chan);
1461
1462         LOCAL_USER_REMOVE(u);
1463         return loops ? res : 0;
1464
1465 }
1466
1467 int unload_module(void)
1468 {
1469         STANDARD_HANGUP_LOCALUSERS;
1470         ast_unregister_application(app);
1471         return ast_unregister_application(rapp);
1472 }
1473
1474 int load_module(void)
1475 {
1476         int res;
1477         if (!(res = ast_register_application(app, dial_exec, synopsis, descrip)))
1478                 res = ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);
1479         return res;
1480 }
1481
1482 char *description(void)
1483 {
1484         return tdesc;
1485 }
1486
1487 int usecount(void)
1488 {
1489         int res;
1490         STANDARD_USECOUNT(res);
1491         return res;
1492 }
1493
1494 char *key()
1495 {
1496         return ASTERISK_GPL_KEY;
1497 }