8bec88b7692112d6e63cfd4958a71f533d3db382
[asterisk/asterisk.git] / apps / app_dial.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief dial() & retrydial() - Trivial application to dial a channel and send an URL on answer
22  *
23  * \author Mark Spencer <markster@digium.com>
24  * 
25  * \ingroup applications
26  */
27
28 #include "asterisk.h"
29
30 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
31
32 #include <stdlib.h>
33 #include <errno.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <sys/time.h>
39 #include <sys/signal.h>
40 #include <sys/stat.h>
41 #include <netinet/in.h>
42
43 #include "asterisk/lock.h"
44 #include "asterisk/file.h"
45 #include "asterisk/logger.h"
46 #include "asterisk/channel.h"
47 #include "asterisk/pbx.h"
48 #include "asterisk/options.h"
49 #include "asterisk/module.h"
50 #include "asterisk/translate.h"
51 #include "asterisk/say.h"
52 #include "asterisk/config.h"
53 #include "asterisk/features.h"
54 #include "asterisk/musiconhold.h"
55 #include "asterisk/callerid.h"
56 #include "asterisk/utils.h"
57 #include "asterisk/app.h"
58 #include "asterisk/causes.h"
59 #include "asterisk/rtp.h"
60 #include "asterisk/manager.h"
61 #include "asterisk/privacy.h"
62 #include "asterisk/stringfields.h"
63
64 static char *app = "Dial";
65
66 static char *synopsis = "Place a call and connect to the current channel";
67
68 static char *descrip =
69 "  Dial(Technology/resource[&Tech2/resource2...][|timeout][|options][|URL]):\n"
70 "This application will place calls to one or more specified channels. As soon\n"
71 "as one of the requested channels answers, the originating channel will be\n"
72 "answered, if it has not already been answered. These two channels will then\n"
73 "be active in a bridged call. All other channels that were requested will then\n"
74 "be hung up.\n"
75 "  Unless there is a timeout specified, the Dial application will wait\n"
76 "indefinitely until one of the called channels answers, the user hangs up, or\n"
77 "if all of the called channels are busy or unavailable. Dialplan executing will\n"
78 "continue if no requested channels can be called, or if the timeout expires.\n\n"
79 "  This application sets the following channel variables upon completion:\n"
80 "    DIALEDTIME   - This is the time from dialing a channel until when it\n"
81 "                   is disconnected.\n" 
82 "    ANSWEREDTIME - This is the amount of time for actual call.\n"
83 "    DIALSTATUS   - This is the status of the call:\n"
84 "                   CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n" 
85 "                   DONTCALL | TORTURE | INVALIDARGS\n"
86 "  For the Privacy and Screening Modes, the DIALSTATUS variable will be set to\n"
87 "DONTCALL if the called party chooses to send the calling party to the 'Go Away'\n"
88 "script. The DIALSTATUS variable will be set to TORTURE if the called party\n"
89 "wants to send the caller to the 'torture' script.\n"
90 "  This application will report normal termination if the originating channel\n"
91 "hangs up, or if the call is bridged and either of the parties in the bridge\n"
92 "ends the call.\n"
93 "  The optional URL will be sent to the called party if the channel supports it.\n"
94 "  If the OUTBOUND_GROUP variable is set, all peer channels created by this\n"
95 "application will be put into that group (as in Set(GROUP()=...).\n"
96 "  If the OUTBOUND_GROUP_ONCE variable is set, all peer channels created by this\n"
97 "application will be put into that group (as in Set(GROUP()=...). Unlike OUTBOUND_GROUP,\n"
98 "however, the variable will be unset after use.\n\n"
99 "  Options:\n"
100 "    A(x) - Play an announcement to the called party, using 'x' as the file.\n"
101 "    C    - Reset the CDR for this call.\n"
102 "    d    - Allow the calling user to dial a 1 digit extension while waiting for\n"
103 "           a call to be answered. Exit to that extension if it exists in the\n"
104 "           current context, or the context defined in the EXITCONTEXT variable,\n"
105 "           if it exists.\n"
106 "    D([called][:calling]) - Send the specified DTMF strings *after* the called\n"
107 "           party has answered, but before the call gets bridged. The 'called'\n"
108 "           DTMF string is sent to the called party, and the 'calling' DTMF\n"
109 "           string is sent to the calling party. Both parameters can be used\n"
110 "           alone.\n"   
111 "    f    - Force the callerid of the *calling* channel to be set as the\n"
112 "           extension associated with the channel using a dialplan 'hint'.\n"
113 "           For example, some PSTNs do not allow CallerID to be set to anything\n"
114 "           other than the number assigned to the caller.\n"
115 "    g    - Proceed with dialplan execution at the current extension if the\n"
116 "           destination channel hangs up.\n"
117 "    G(context^exten^pri) - If the call is answered, transfer the calling party to\n"
118 "           the specified priority and the called party to the specified priority+1.\n"
119 "           Optionally, an extension, or extension and context may be specified. \n"
120 "           Otherwise, the current extension is used. You cannot use any additional\n"
121 "           action post answer options in conjunction with this option.\n" 
122 "    h    - Allow the called party to hang up by sending the '*' DTMF digit.\n"
123 "    H    - Allow the calling party to hang up by hitting the '*' DTMF digit.\n"
124 "    i    - Asterisk will ignore any forwarding requests it may receive on this\n"
125 "           dial attempt.\n"
126 "    k    - Allow the called party to enable parking of the call by sending\n"
127 "           the DTMF sequence defined for call parking in features.conf.\n"
128 "    K    - Allow the calling party to enable parking of the call by sending\n"
129 "           the DTMF sequence defined for call parking in features.conf.\n"
130 "    L(x[:y][:z]) - Limit the call to 'x' ms. Play a warning when 'y' ms are\n"
131 "           left. Repeat the warning every 'z' ms. The following special\n"
132 "           variables can be used with this option:\n"
133 "           * LIMIT_PLAYAUDIO_CALLER   yes|no (default yes)\n"
134 "                                      Play sounds to the caller.\n"
135 "           * LIMIT_PLAYAUDIO_CALLEE   yes|no\n"
136 "                                      Play sounds to the callee.\n"
137 "           * LIMIT_TIMEOUT_FILE       File to play when time is up.\n"
138 "           * LIMIT_CONNECT_FILE       File to play when call begins.\n"
139 "           * LIMIT_WARNING_FILE       File to play as warning if 'y' is defined.\n"
140 "                                      The default is to say the time remaining.\n"
141 "    m([class]) - Provide hold music to the calling party until a requested\n"
142 "           channel answers. A specific MusicOnHold class can be\n"
143 "           specified.\n"
144 "    M(x[^arg]) - Execute the Macro for the *called* channel before connecting\n"
145 "           to the calling channel. Arguments can be specified to the Macro\n"
146 "           using '^' as a delimeter. The Macro can set the variable\n"
147 "           MACRO_RESULT to specify the following actions after the Macro is\n" 
148 "           finished executing.\n"
149 "           * ABORT        Hangup both legs of the call.\n"
150 "           * CONGESTION   Behave as if line congestion was encountered.\n"
151 "           * BUSY         Behave as if a busy signal was encountered.\n"
152 "           * CONTINUE     Hangup the called party and allow the calling party\n"
153 "                          to continue dialplan execution at the next priority.\n"
154 "           * GOTO:<context>^<exten>^<priority> - Transfer the call to the\n"
155 "                          specified priority. Optionally, an extension, or\n"
156 "                          extension and priority can be specified.\n"
157 "           You cannot use any additional action post answer options in conjunction\n"
158 "           with this option. Also, pbx services are not run on the peer (called) channel,\n"
159 "           so you will not be able to set timeouts via the TIMEOUT() function in this macro.\n"
160 "    n    - This option is a modifier for the screen/privacy mode. It specifies\n"
161 "           that no introductions are to be saved in the priv-callerintros\n"
162 "           directory.\n"
163 "    N    - This option is a modifier for the screen/privacy mode. It specifies\n"
164 "           that if callerID is present, do not screen the call.\n"
165 "    o    - Specify that the CallerID that was present on the *calling* channel\n"
166 "           be set as the CallerID on the *called* channel. This was the\n"
167 "           behavior of Asterisk 1.0 and earlier.\n"
168 "    O([x]) - \"Operator Services\" mode (Zaptel channel to Zaptel channel\n"
169 "             only, if specified on non-Zaptel interface, it will be ignored).\n"
170 "             When the destination answers (presumably an operator services\n"
171 "             station), the originator no longer has control of their line.\n"
172 "             They may hang up, but the switch will not release their line\n"
173 "             until the destination party hangs up (the operator). Specified\n"
174 "             without an arg, or with 1 as an arg, the originator hanging up\n"
175 "             will cause the phone to ring back immediately. With a 2 specified,\n"
176 "             when the \"operator\" flashes the trunk, it will ring their phone\n"
177 "             back.\n"
178 "    p    - This option enables screening mode. This is basically Privacy mode\n"
179 "           without memory.\n"
180 "    P([x]) - Enable privacy mode. Use 'x' as the family/key in the database if\n"
181 "           it is provided. The current extension is used if a database\n"
182 "           family/key is not specified.\n"
183 "    r    - Indicate ringing to the calling party. Pass no audio to the calling\n"
184 "           party until the called channel has answered.\n"
185 "    S(x) - Hang up the call after 'x' seconds *after* the called party has\n"
186 "           answered the call.\n"       
187 "    t    - Allow the called party to transfer the calling party by sending the\n"
188 "           DTMF sequence defined in features.conf.\n"
189 "    T    - Allow the calling party to transfer the called party by sending the\n"
190 "           DTMF sequence defined in features.conf.\n"
191 "    U(x[^arg]) - Execute via Gosub the routine 'x' for the *called* channel before connecting\n"
192 "           to the calling channel. Arguments can be specified to the Gosub\n"
193 "           using '^' as a delimeter. The Gosub routine can set the variable\n"
194 "           GOSUB_RESULT to specify the following actions after the Gosub returns.\n" 
195 "           * ABORT        Hangup both legs of the call.\n"
196 "           * CONGESTION   Behave as if line congestion was encountered.\n"
197 "           * BUSY         Behave as if a busy signal was encountered.\n"
198 "           * CONTINUE     Hangup the called party and allow the calling party\n"
199 "                          to continue dialplan execution at the next priority.\n"
200 "           * GOTO:<context>^<exten>^<priority> - Transfer the call to the\n"
201 "                          specified priority. Optionally, an extension, or\n"
202 "                          extension and priority can be specified.\n"
203 "           You cannot use any additional action post answer options in conjunction\n"
204 "           with this option. Also, pbx services are not run on the peer (called) channel,\n"
205 "           so you will not be able to set timeouts via the TIMEOUT() function in this routine.\n"
206 "    w    - Allow the called party to enable recording of the call by sending\n"
207 "           the DTMF sequence defined for one-touch recording in features.conf.\n"
208 "    W    - Allow the calling party to enable recording of the call by sending\n"
209 "           the DTMF sequence defined for one-touch recording in features.conf.\n";
210
211 /* RetryDial App by Anthony Minessale II <anthmct@yahoo.com> Jan/2005 */
212 static char *rapp = "RetryDial";
213 static char *rsynopsis = "Place a call, retrying on failure allowing optional exit extension.";
214 static char *rdescrip =
215 "  RetryDial(announce|sleep|retries|dialargs): This application will attempt to\n"
216 "place a call using the normal Dial application. If no channel can be reached,\n"
217 "the 'announce' file will be played. Then, it will wait 'sleep' number of\n"
218 "seconds before retying the call. After 'retires' number of attempts, the\n"
219 "calling channel will continue at the next priority in the dialplan. If the\n"
220 "'retries' setting is set to 0, this application will retry endlessly.\n"
221 "  While waiting to retry a call, a 1 digit extension may be dialed. If that\n"
222 "extension exists in either the context defined in ${EXITCONTEXT} or the current\n"
223 "one, The call will jump to that extension immediately.\n"
224 "  The 'dialargs' are specified in the same format that arguments are provided\n"
225 "to the Dial application.\n";
226
227 static char *kapp = "KeepAlive";
228 static char *ksynopsis = "DO NOT USE";
229 static char *kdescrip = "";
230
231 enum {
232         OPT_ANNOUNCE =          (1 << 0),
233         OPT_RESETCDR =          (1 << 1),
234         OPT_DTMF_EXIT =         (1 << 2),
235         OPT_SENDDTMF =          (1 << 3),
236         OPT_FORCECLID =         (1 << 4),
237         OPT_GO_ON =             (1 << 5),
238         OPT_CALLEE_HANGUP =     (1 << 6),
239         OPT_CALLER_HANGUP =     (1 << 7),
240         OPT_DURATION_LIMIT =    (1 << 9),
241         OPT_MUSICBACK =         (1 << 10),
242         OPT_CALLEE_MACRO =      (1 << 11),
243         OPT_SCREEN_NOINTRO =    (1 << 12),
244         OPT_SCREEN_NOCLID =     (1 << 13),
245         OPT_ORIGINAL_CLID =     (1 << 14),
246         OPT_SCREENING =         (1 << 15),
247         OPT_PRIVACY =           (1 << 16),
248         OPT_RINGBACK =          (1 << 17),
249         OPT_DURATION_STOP =     (1 << 18),
250         OPT_CALLEE_TRANSFER =   (1 << 19),
251         OPT_CALLER_TRANSFER =   (1 << 20),
252         OPT_CALLEE_MONITOR =    (1 << 21),
253         OPT_CALLER_MONITOR =    (1 << 22),
254         OPT_GOTO =              (1 << 23),
255         OPT_OPERMODE =          (1 << 24),
256         OPT_CALLEE_PARK =       (1 << 25),
257         OPT_CALLER_PARK =       (1 << 26),
258         OPT_IGNORE_FORWARDING = (1 << 27),
259         OPT_CALLEE_GOSUB =      (1 << 28),
260 };
261
262 #define DIAL_STILLGOING                 (1 << 30)
263 #define DIAL_NOFORWARDHTML              (1 << 31)
264
265 enum {
266         OPT_ARG_ANNOUNCE = 0,
267         OPT_ARG_SENDDTMF,
268         OPT_ARG_GOTO,
269         OPT_ARG_DURATION_LIMIT,
270         OPT_ARG_MUSICBACK,
271         OPT_ARG_CALLEE_MACRO,
272         OPT_ARG_CALLEE_GOSUB,
273         OPT_ARG_PRIVACY,
274         OPT_ARG_DURATION_STOP,
275         OPT_ARG_OPERMODE,
276         /* note: this entry _MUST_ be the last one in the enum */
277         OPT_ARG_ARRAY_SIZE,
278 };
279
280 AST_APP_OPTIONS(dial_exec_options, {
281         AST_APP_OPTION_ARG('A', OPT_ANNOUNCE, OPT_ARG_ANNOUNCE),
282         AST_APP_OPTION('C', OPT_RESETCDR),
283         AST_APP_OPTION('d', OPT_DTMF_EXIT),
284         AST_APP_OPTION_ARG('D', OPT_SENDDTMF, OPT_ARG_SENDDTMF),
285         AST_APP_OPTION('f', OPT_FORCECLID),
286         AST_APP_OPTION('g', OPT_GO_ON),
287         AST_APP_OPTION_ARG('G', OPT_GOTO, OPT_ARG_GOTO),
288         AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
289         AST_APP_OPTION('H', OPT_CALLER_HANGUP),
290         AST_APP_OPTION('i', OPT_IGNORE_FORWARDING),
291         AST_APP_OPTION('k', OPT_CALLEE_PARK),
292         AST_APP_OPTION('K', OPT_CALLER_PARK),
293         AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
294         AST_APP_OPTION_ARG('m', OPT_MUSICBACK, OPT_ARG_MUSICBACK),
295         AST_APP_OPTION_ARG('M', OPT_CALLEE_MACRO, OPT_ARG_CALLEE_MACRO),
296         AST_APP_OPTION('n', OPT_SCREEN_NOINTRO),
297         AST_APP_OPTION('N', OPT_SCREEN_NOCLID),
298         AST_APP_OPTION_ARG('O', OPT_OPERMODE,OPT_ARG_OPERMODE),
299         AST_APP_OPTION('o', OPT_ORIGINAL_CLID),
300         AST_APP_OPTION('p', OPT_SCREENING),
301         AST_APP_OPTION_ARG('P', OPT_PRIVACY, OPT_ARG_PRIVACY),
302         AST_APP_OPTION('r', OPT_RINGBACK),
303         AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
304         AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
305         AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
306         AST_APP_OPTION_ARG('U', OPT_CALLEE_GOSUB, OPT_ARG_CALLEE_GOSUB),
307         AST_APP_OPTION('w', OPT_CALLEE_MONITOR),
308         AST_APP_OPTION('W', OPT_CALLER_MONITOR),
309 });
310
311 /*
312  * The list of active channels
313  */
314 struct chanlist {
315         struct chanlist *next;
316         struct ast_channel *chan;
317         unsigned int flags;
318         int forwards;
319 };
320
321
322 static void hanguptree(struct chanlist *outgoing, struct ast_channel *exception)
323 {
324         /* Hang up a tree of stuff */
325         struct chanlist *oo;
326         while (outgoing) {
327                 /* Hangup any existing lines we have open */
328                 if (outgoing->chan && (outgoing->chan != exception))
329                         ast_hangup(outgoing->chan);
330                 oo = outgoing;
331                 outgoing=outgoing->next;
332                 ast_free(oo);
333         }
334 }
335
336 #define AST_MAX_FORWARDS   8
337
338 #define AST_MAX_WATCHERS 256
339
340 /*
341  * argument to handle_cause() and other functions.
342  */
343 struct cause_args {
344         struct ast_channel *chan;
345         int busy;
346         int congestion;
347         int nochan;
348 };
349
350 static void handle_cause(int cause, struct cause_args *num)
351 {
352         struct ast_cdr *cdr = num->chan->cdr;
353
354         switch(cause) {
355         case AST_CAUSE_BUSY:
356                 if (cdr)
357                         ast_cdr_busy(cdr);
358                 num->busy++;
359                 break;
360
361         case AST_CAUSE_CONGESTION:
362                 if (cdr)
363                         ast_cdr_failed(cdr);
364                 num->congestion++;
365                 break;
366
367         case AST_CAUSE_UNREGISTERED:
368                 if (cdr)
369                         ast_cdr_failed(cdr);
370                 num->nochan++;
371                 break;
372
373         case AST_CAUSE_NORMAL_CLEARING:
374                 break;
375
376         default:
377                 num->nochan++;
378                 break;
379         }
380 }
381
382 /* free the buffer if allocated, and set the pointer to the second arg */
383 #define S_REPLACE(s, new_val)           \
384         do {                            \
385                 if (s)                  \
386                         free(s);        \
387                 s = (new_val);          \
388         } while (0)
389
390 static int onedigit_goto(struct ast_channel *chan, const char *context, char exten, int pri) 
391 {
392         char rexten[2] = { exten, '\0' };
393
394         if (context) {
395                 if (!ast_goto_if_exists(chan, context, rexten, pri))
396                         return 1;
397         } else {
398                 if (!ast_goto_if_exists(chan, chan->context, rexten, pri))
399                         return 1;
400                 else if (!ast_strlen_zero(chan->macrocontext)) {
401                         if (!ast_goto_if_exists(chan, chan->macrocontext, rexten, pri))
402                                 return 1;
403                 }
404         }
405         return 0;
406 }
407
408
409 static const char *get_cid_name(char *name, int namelen, struct ast_channel *chan)
410 {
411         const char *context = S_OR(chan->macrocontext, chan->context);
412         const char *exten = S_OR(chan->macroexten, chan->exten);
413
414         return ast_get_hint(NULL, 0, name, namelen, chan, context, exten) ? name : "";
415 }
416
417 static void senddialevent(struct ast_channel *src, struct ast_channel *dst)
418 {
419         manager_event(EVENT_FLAG_CALL, "Dial", 
420                            "SubEvent: Begin\r\n"
421                            "Source: %s\r\n"
422                            "Destination: %s\r\n"
423                            "CallerIDNum: %s\r\n"
424                            "CallerIDName: %s\r\n"
425                            "SrcUniqueID: %s\r\n"
426                            "DestUniqueID: %s\r\n",
427                            src->name, dst->name, S_OR(src->cid.cid_num, "<unknown>"),
428                            S_OR(src->cid.cid_name, "<unknown>"), src->uniqueid,
429                            dst->uniqueid);
430 }
431
432 static void senddialendevent(const struct ast_channel *src, const char *dialstatus)
433 {
434         manager_event(EVENT_FLAG_CALL, "Dial",
435                                         "SubEvent: End\r\n"
436                                         "Channel: %s\r\n"
437                                         "DialStatus: %s\r\n",
438                                         src->name, dialstatus);
439 }       
440
441 /*!
442  * helper function for wait_for_answer()
443  *
444  * XXX this code is highly suspicious, as it essentially overwrites
445  * the outgoing channel without properly deleting it.
446  */
447 static void do_forward(struct chanlist *o,
448         struct cause_args *num, struct ast_flags *peerflags, int single)
449 {
450         char tmpchan[256];
451         struct ast_channel *original = o->chan;
452         struct ast_channel *c = o->chan; /* the winner */
453         struct ast_channel *in = num->chan; /* the input channel */
454         char *stuff;
455         char *tech;
456         int cause;
457
458         ast_copy_string(tmpchan, c->call_forward, sizeof(tmpchan));
459         if ((stuff = strchr(tmpchan, '/'))) {
460                 *stuff++ = '\0';
461                 tech = tmpchan;
462         } else {
463                 const char *forward_context = pbx_builtin_getvar_helper(c, "FORWARD_CONTEXT");
464                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", c->call_forward, forward_context ? forward_context : c->context);
465                 stuff = tmpchan;
466                 tech = "Local";
467         }
468         /* Before processing channel, go ahead and check for forwarding */
469         o->forwards++;
470         if (o->forwards < AST_MAX_FORWARDS) {
471                 if (option_verbose > 2)
472                         ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n", in->name, tech, stuff, c->name);
473                 /* If we have been told to ignore forwards, just set this channel to null and continue processing extensions normally */
474                 if (ast_test_flag(peerflags, OPT_IGNORE_FORWARDING)) {
475                         if (option_verbose > 2)
476                                 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n", in->name, tech, stuff);
477                         c = o->chan = NULL;
478                         cause = AST_CAUSE_BUSY;
479                 } else {
480                         /* Setup parameters */
481                         c = o->chan = ast_request(tech, in->nativeformats, stuff, &cause);
482                         if (c) {
483                                 if (single)
484                                         ast_channel_make_compatible(o->chan, in);
485                                 ast_channel_inherit_variables(in, o->chan);
486                         } else
487                                 ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
488                 }
489         } else {
490                 if (option_verbose > 2)
491                         ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", c->name);
492                 cause = AST_CAUSE_CONGESTION;
493                 c = o->chan = NULL;
494         }
495         if (!c) {
496                 ast_clear_flag(o, DIAL_STILLGOING);     
497                 handle_cause(cause, num);
498         } else {
499                 char *new_cid_num, *new_cid_name;
500                 struct ast_channel *src;
501
502                 ast_rtp_make_compatible(c, in, single);
503                 if (ast_test_flag(o, OPT_FORCECLID)) {
504                         new_cid_num = ast_strdup(S_OR(in->macroexten, in->exten));
505                         new_cid_name = NULL; /* XXX no name ? */
506                         src = c;        /* XXX possible bug in previous code, which used 'winner' ? it may have changed */
507                 } else {
508                         new_cid_num = ast_strdup(in->cid.cid_num);
509                         new_cid_name = ast_strdup(in->cid.cid_name);
510                         src = in;
511                 }
512                 ast_string_field_set(c, accountcode, src->accountcode);
513                 c->cdrflags = src->cdrflags;
514                 S_REPLACE(c->cid.cid_num, new_cid_num);
515                 S_REPLACE(c->cid.cid_name, new_cid_name);
516
517                 if (in->cid.cid_ani) { /* XXX or maybe unconditional ? */
518                         S_REPLACE(c->cid.cid_ani, ast_strdup(in->cid.cid_ani));
519                 }
520                 S_REPLACE(c->cid.cid_rdnis, ast_strdup(S_OR(in->macroexten, in->exten)));
521                 if (ast_call(c, tmpchan, 0)) {
522                         ast_log(LOG_NOTICE, "Failed to dial on local channel for call forward to '%s'\n", tmpchan);
523                         ast_clear_flag(o, DIAL_STILLGOING);     
524                         ast_hangup(original);
525                         c = o->chan = NULL;
526                         num->nochan++;
527                 } else {
528                         senddialevent(in, c);
529                         /* After calling, set callerid to extension */
530                         if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID)) {
531                                 char cidname[AST_MAX_EXTENSION] = "";
532                                 ast_set_callerid(c, S_OR(in->macroexten, in->exten), get_cid_name(cidname, sizeof(cidname), in), NULL);
533                         }
534                         /* Hangup the original channel now, in case we needed it */
535                         ast_hangup(original);
536                 }
537         }
538 }
539
540 /* argument used for some functions. */
541 struct privacy_args {
542         int sentringing;
543         int privdb_val;
544         char privcid[256];
545         char privintro[1024];
546         char status[256];
547 };
548
549 static struct ast_channel *wait_for_answer(struct ast_channel *in,
550         struct chanlist *outgoing, int *to, struct ast_flags *peerflags,
551         struct privacy_args *pa,
552         const struct cause_args *num_in, int *result)
553 {
554         struct cause_args num = *num_in;
555         int prestart = num.busy + num.congestion + num.nochan;
556         int orig = *to;
557         struct ast_channel *peer = NULL;
558         /* single is set if only one destination is enabled */
559         int single = outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
560         
561         if (single) {
562                 /* Turn off hold music, etc */
563                 ast_deactivate_generator(in);
564                 /* If we are calling a single channel, make them compatible for in-band tone purpose */
565                 ast_channel_make_compatible(outgoing->chan, in);
566         }
567         
568         
569         while (*to && !peer) {
570                 struct chanlist *o;
571                 int pos = 0;    /* how many channels do we handle */
572                 int numlines = prestart;
573                 struct ast_channel *winner;
574                 struct ast_channel *watchers[AST_MAX_WATCHERS];
575
576                 watchers[pos++] = in;
577                 for (o = outgoing; o; o = o->next) {
578                         /* Keep track of important channels */
579                         if (ast_test_flag(o, DIAL_STILLGOING) && o->chan)
580                                 watchers[pos++] = o->chan;
581                         numlines++;
582                 }
583                 if (pos == 1) { /* only the input channel is available */
584                         if (numlines == (num.busy + num.congestion + num.nochan)) {
585                                 if (option_verbose > 2)
586                                         ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time (%d:%d/%d/%d)\n", numlines, num.busy, num.congestion, num.nochan);
587                                 if (num.busy)
588                                         strcpy(pa->status, "BUSY");     
589                                 else if (num.congestion)
590                                         strcpy(pa->status, "CONGESTION");
591                                 else if (num.nochan)
592                                         strcpy(pa->status, "CHANUNAVAIL");
593                         } else {
594                                 if (option_verbose > 2)
595                                         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);
596                         }
597                         *to = 0;
598                         return NULL;
599                 }
600                 winner = ast_waitfor_n(watchers, pos, to);
601                 for (o = outgoing; o; o = o->next) {
602                         struct ast_frame *f;
603                         struct ast_channel *c = o->chan;
604
605                         if (c == NULL)
606                                 continue;
607                         if (ast_test_flag(o, DIAL_STILLGOING) && c->_state == AST_STATE_UP) {
608                                 if (!peer) {
609                                         if (option_verbose > 2)
610                                                 ast_verbose(VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name);
611                                         peer = c;
612                                         ast_copy_flags(peerflags, o,
613                                                        OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
614                                                        OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
615                                                        OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
616                                                        OPT_CALLEE_PARK | OPT_CALLER_PARK |
617                                                        DIAL_NOFORWARDHTML);
618                                         ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext));
619                                         ast_copy_string(c->exten, "", sizeof(c->exten));
620                                 }
621                                 continue;
622                         }
623                         if (c != winner)
624                                 continue;
625                         /* here, o->chan == c == winner */
626                         if (!ast_strlen_zero(c->call_forward)) {
627                                 do_forward(o, &num, peerflags, single);
628                                 continue;
629                         }
630                         f = ast_read(winner);
631                         if (!f) {
632                                 in->hangupcause = c->hangupcause;
633                                 ast_hangup(c);
634                                 c = o->chan = NULL;
635                                 ast_clear_flag(o, DIAL_STILLGOING);
636                                 handle_cause(in->hangupcause, &num);
637                                 continue;
638                         }
639                         if (f->frametype == AST_FRAME_CONTROL) {
640                                 switch(f->subclass) {
641                                 case AST_CONTROL_ANSWER:
642                                         /* This is our guy if someone answered. */
643                                         if (!peer) {
644                                                 if (option_verbose > 2)
645                                                         ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", c->name, in->name);
646                                                 peer = c;
647                                                 ast_copy_flags(peerflags, o,
648                                                                OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
649                                                                OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
650                                                                OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
651                                                                OPT_CALLEE_PARK | OPT_CALLER_PARK |
652                                                                DIAL_NOFORWARDHTML);
653                                                 ast_copy_string(c->dialcontext, "", sizeof(c->dialcontext));
654                                                 ast_copy_string(c->exten, "", sizeof(c->exten));
655                                                 /* Setup early bridge if appropriate */
656                                                 ast_channel_early_bridge(in, peer);
657                                         }
658                                         /* If call has been answered, then the eventual hangup is likely to be normal hangup */
659                                         in->hangupcause = AST_CAUSE_NORMAL_CLEARING;
660                                         c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
661                                         break;
662                                 case AST_CONTROL_BUSY:
663                                         if (option_verbose > 2)
664                                                 ast_verbose(VERBOSE_PREFIX_3 "%s is busy\n", c->name);
665                                         in->hangupcause = c->hangupcause;
666                                         ast_hangup(c);
667                                         c = o->chan = NULL;
668                                         ast_clear_flag(o, DIAL_STILLGOING);     
669                                         handle_cause(AST_CAUSE_BUSY, &num);
670                                         break;
671                                 case AST_CONTROL_CONGESTION:
672                                         if (option_verbose > 2)
673                                                 ast_verbose(VERBOSE_PREFIX_3 "%s is circuit-busy\n", c->name);
674                                         in->hangupcause = c->hangupcause;
675                                         ast_hangup(c);
676                                         c = o->chan = NULL;
677                                         ast_clear_flag(o, DIAL_STILLGOING);
678                                         handle_cause(AST_CAUSE_CONGESTION, &num);
679                                         break;
680                                 case AST_CONTROL_RINGING:
681                                         if (option_verbose > 2)
682                                                 ast_verbose(VERBOSE_PREFIX_3 "%s is ringing\n", c->name);
683                                         /* Setup early media if appropriate */
684                                         if (single)
685                                                 ast_channel_early_bridge(in, c);
686                                         if (!(pa->sentringing) && !ast_test_flag(outgoing, OPT_MUSICBACK)) {
687                                                 ast_indicate(in, AST_CONTROL_RINGING);
688                                                 pa->sentringing++;
689                                         }
690                                         break;
691                                 case AST_CONTROL_PROGRESS:
692                                         if (option_verbose > 2)
693                                                 ast_verbose (VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", c->name, in->name);
694                                         /* Setup early media if appropriate */
695                                         if (single)
696                                                 ast_channel_early_bridge(in, c);
697                                         if (!ast_test_flag(outgoing, OPT_RINGBACK))
698                                                 ast_indicate(in, AST_CONTROL_PROGRESS);
699                                         break;
700                                 case AST_CONTROL_VIDUPDATE:
701                                         if (option_verbose > 2)
702                                                 ast_verbose (VERBOSE_PREFIX_3 "%s requested a video update, passing it to %s\n", c->name, in->name);
703                                         ast_indicate(in, AST_CONTROL_VIDUPDATE);
704                                         break;
705                                 case AST_CONTROL_PROCEEDING:
706                                         if (option_verbose > 2)
707                                                 ast_verbose (VERBOSE_PREFIX_3 "%s is proceeding passing it to %s\n", c->name, in->name);
708                                         if (single)
709                                                 ast_channel_early_bridge(in, c);
710                                         if (!ast_test_flag(outgoing, OPT_RINGBACK))
711                                                 ast_indicate(in, AST_CONTROL_PROCEEDING);
712                                         break;
713                                 case AST_CONTROL_HOLD:
714                                         if (option_verbose > 2)
715                                                 ast_verbose(VERBOSE_PREFIX_3 "Call on %s placed on hold\n", c->name);
716                                         ast_indicate(in, AST_CONTROL_HOLD);
717                                         break;
718                                 case AST_CONTROL_UNHOLD:
719                                         if (option_verbose > 2)
720                                                 ast_verbose(VERBOSE_PREFIX_3 "Call on %s left from hold\n", c->name);
721                                         ast_indicate(in, AST_CONTROL_UNHOLD);
722                                         break;
723                                 case AST_CONTROL_OFFHOOK:
724                                 case AST_CONTROL_FLASH:
725                                         /* Ignore going off hook and flash */
726                                         break;
727                                 case -1:
728                                         if (!ast_test_flag(outgoing, OPT_RINGBACK | OPT_MUSICBACK)) {
729                                                 if (option_verbose > 2)
730                                                         ast_verbose(VERBOSE_PREFIX_3 "%s stopped sounds\n", c->name);
731                                                 ast_indicate(in, -1);
732                                                 pa->sentringing = 0;
733                                         }
734                                         break;
735                                 default:
736                                         ast_debug(1, "Dunno what to do with control type %d\n", f->subclass);
737                                 }
738                         } else if (single) {
739                                 /* XXX are we sure the logic is correct ? or we should just switch on f->frametype ? */
740                                 if (f->frametype == AST_FRAME_VOICE && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) {
741                                         if (ast_write(in, f)) 
742                                                 ast_log(LOG_WARNING, "Unable to forward voice frame\n");
743                                 } else if (f->frametype == AST_FRAME_IMAGE && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) {
744                                         if (ast_write(in, f))
745                                                 ast_log(LOG_WARNING, "Unable to forward image\n");
746                                 } else if (f->frametype == AST_FRAME_TEXT && !ast_test_flag(outgoing, OPT_RINGBACK|OPT_MUSICBACK)) {
747                                         if (ast_write(in, f))
748                                                 ast_log(LOG_WARNING, "Unable to send text\n");
749                                 } else if (f->frametype == AST_FRAME_HTML && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) {
750                                         if (ast_channel_sendhtml(in, f->subclass, f->data, f->datalen) == -1)
751                                                 ast_log(LOG_WARNING, "Unable to send URL\n");
752                                 }
753                         }
754                         ast_frfree(f);
755                 } /* end for */
756                 if (winner == in) {
757                         struct ast_frame *f = ast_read(in);
758 #if 0
759                         if (f && (f->frametype != AST_FRAME_VOICE))
760                                 printf("Frame type: %d, %d\n", f->frametype, f->subclass);
761                         else if (!f || (f->frametype != AST_FRAME_VOICE))
762                                 printf("Hangup received on %s\n", in->name);
763 #endif
764                         if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_HANGUP))) {
765                                 /* Got hung up */
766                                 *to = -1;
767                                 strcpy(pa->status, "CANCEL");
768                                 ast_cdr_noanswer(in->cdr);
769                                 if (f)
770                                         ast_frfree(f);
771                                 return NULL;
772                         }
773
774                         /* now f is guaranteed non-NULL */
775                         if (f->frametype == AST_FRAME_DTMF) {
776                                 if (ast_test_flag(peerflags, OPT_DTMF_EXIT)) {
777                                         const char *context = pbx_builtin_getvar_helper(in, "EXITCONTEXT");
778                                         if (onedigit_goto(in, context, (char) f->subclass, 1)) {
779                                                 if (option_verbose > 2)
780                                                         ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
781                                                 *to=0;
782                                                 ast_cdr_noanswer(in->cdr);
783                                                 *result = f->subclass;
784                                                 strcpy(pa->status, "CANCEL");
785                                                 ast_frfree(f);
786                                                 return NULL;
787                                         }
788                                 }
789
790                                 if (ast_test_flag(peerflags, OPT_CALLER_HANGUP) && 
791                                                   (f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */
792                                         if (option_verbose > 2)
793                                                 ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
794                                         *to=0;
795                                         strcpy(pa->status, "CANCEL");
796                                         ast_cdr_noanswer(in->cdr);
797                                         ast_frfree(f);
798                                         return NULL;
799                                 }
800                         }
801
802                         /* Forward HTML stuff */
803                         if (single && (f->frametype == AST_FRAME_HTML) && !ast_test_flag(outgoing, DIAL_NOFORWARDHTML)) 
804                                 if(ast_channel_sendhtml(outgoing->chan, f->subclass, f->data, f->datalen) == -1)
805                                         ast_log(LOG_WARNING, "Unable to send URL\n");
806                         
807
808                         if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF_BEGIN) || (f->frametype == AST_FRAME_DTMF_END)))  {
809                                 if (ast_write(outgoing->chan, f))
810                                         ast_log(LOG_WARNING, "Unable to forward voice or dtmf\n");
811                         }
812                         if (single && (f->frametype == AST_FRAME_CONTROL) && 
813                                 ((f->subclass == AST_CONTROL_HOLD) || 
814                                  (f->subclass == AST_CONTROL_UNHOLD) || 
815                                  (f->subclass == AST_CONTROL_VIDUPDATE))) {
816                                 if (option_verbose > 2)
817                                         ast_verbose(VERBOSE_PREFIX_3 "%s requested special control %d, passing it to %s\n", in->name, f->subclass, outgoing->chan->name);
818                                 ast_indicate_data(outgoing->chan, f->subclass, f->data, f->datalen);
819                         }
820                         ast_frfree(f);
821                 }
822                 if (!*to && (option_verbose > 2))
823                         ast_verbose(VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig);
824                 if (!*to || ast_check_hangup(in)) {
825                         ast_cdr_noanswer(in->cdr);
826                 }
827                 
828         }
829
830         return peer;
831 }
832
833 static void replace_macro_delimiter(char *s)
834 {
835         for (; *s; s++)
836                 if (*s == '^')
837                         *s = '|';
838 }
839
840
841 /* returns true if there is a valid privacy reply */
842 static int valid_priv_reply(struct ast_flags *opts, int res)
843 {
844         if (res < '1')
845                 return 0;
846         if (ast_test_flag(opts, OPT_PRIVACY) && res <= '5')
847                 return 1;
848         if (ast_test_flag(opts, OPT_SCREENING) && res <= '4')
849                 return 1;
850         return 0;
851 }
852
853 static int do_timelimit(struct ast_channel *chan, struct ast_bridge_config *config,
854         char *parse, unsigned int *calldurationlimit)
855 {
856         char *stringp = ast_strdupa(parse);
857         char *limit_str, *warning_str, *warnfreq_str;
858         const char *var;
859         int play_to_caller=0,play_to_callee=0;
860         int delta;
861
862         limit_str = strsep(&stringp, ":");
863         warning_str = strsep(&stringp, ":");
864         warnfreq_str = strsep(&stringp, ":");
865
866         config->timelimit = atol(limit_str);
867         if (warning_str)
868                 config->play_warning = atol(warning_str);
869         if (warnfreq_str)
870                 config->warning_freq = atol(warnfreq_str);
871
872         if (!config->timelimit) {
873                 ast_log(LOG_WARNING, "Dial does not accept L(%s), hanging up.\n", limit_str);
874                 config->timelimit = config->play_warning = config->warning_freq = 0;
875                 config->warning_sound = NULL;
876                 return -1;      /* error */
877         } else if ( (delta = config->play_warning - config->timelimit) > 0) {
878                 int w = config->warning_freq;
879
880                 /* If the first warning is requested _after_ the entire call would end,
881                    and no warning frequency is requested, then turn off the warning. If
882                    a warning frequency is requested, reduce the 'first warning' time by
883                    that frequency until it falls within the call's total time limit.
884                    Graphically:
885                                   timelim->|    delta        |<-playwarning
886                         0__________________|_________________|
887                                          | w  |    |    |    |
888
889                    so the number of intervals to cut is 1+(delta-1)/w
890                 */
891
892                 if (w == 0) {
893                         config->play_warning = 0;
894                 } else {
895                         config->play_warning -= w * ( 1 + (delta-1)/w );
896                         if (config->play_warning < 1)
897                                 config->play_warning = config->warning_freq = 0;
898                 }
899         }
900
901         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLER");
902         play_to_caller = var ? ast_true(var) : 1;
903         
904         var = pbx_builtin_getvar_helper(chan,"LIMIT_PLAYAUDIO_CALLEE");
905         play_to_callee = var ? ast_true(var) : 0;
906         
907         if (!play_to_caller && !play_to_callee)
908                 play_to_caller = 1;
909         
910         var = pbx_builtin_getvar_helper(chan,"LIMIT_WARNING_FILE");
911         config->warning_sound = S_OR(var, "timeleft");
912
913         /* The code looking at config wants a NULL, not just "", to decide
914          * that the message should not be played, so we replace "" with NULL.
915          * Note, pbx_builtin_getvar_helper _can_ return NULL if the variable is
916          * not found.
917          */
918         var = pbx_builtin_getvar_helper(chan,"LIMIT_TIMEOUT_FILE");
919         config->end_sound = S_OR(var, NULL);
920         var = pbx_builtin_getvar_helper(chan,"LIMIT_CONNECT_FILE");
921         config->start_sound = S_OR(var, NULL);
922
923         /* undo effect of S(x) in case they are both used */
924         *calldurationlimit = 0;
925         /* more efficient to do it like S(x) does since no advanced opts */
926         if (!config->play_warning && !config->start_sound && !config->end_sound && config->timelimit) {
927                 *calldurationlimit = config->timelimit / 1000;
928                 if (option_verbose > 2)
929                         ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n",
930                                 *calldurationlimit);
931                 config->timelimit = play_to_caller = play_to_callee =
932                 config->play_warning = config->warning_freq = 0;
933         } else if (option_verbose > 2) {
934                 ast_verbose(VERBOSE_PREFIX_3 "Limit Data for this call:\n");
935                 ast_verbose(VERBOSE_PREFIX_4 "timelimit      = %ld\n", config->timelimit);
936                 ast_verbose(VERBOSE_PREFIX_4 "play_warning   = %ld\n", config->play_warning);
937                 ast_verbose(VERBOSE_PREFIX_4 "play_to_caller = %s\n", play_to_caller ? "yes" : "no");
938                 ast_verbose(VERBOSE_PREFIX_4 "play_to_callee = %s\n", play_to_callee ? "yes" : "no");
939                 ast_verbose(VERBOSE_PREFIX_4 "warning_freq   = %ld\n", config->warning_freq);
940                 ast_verbose(VERBOSE_PREFIX_4 "start_sound    = %s\n", S_OR(config->start_sound, ""));
941                 ast_verbose(VERBOSE_PREFIX_4 "warning_sound  = %s\n", config->warning_sound);
942                 ast_verbose(VERBOSE_PREFIX_4 "end_sound      = %s\n", S_OR(config->end_sound, ""));
943         }
944         if (play_to_caller)
945                 ast_set_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING);
946         if (play_to_callee)
947                 ast_set_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING);
948         return 0;
949 }
950
951 static int do_privacy(struct ast_channel *chan, struct ast_channel *peer,
952     struct ast_flags *opts, char **opt_args, struct privacy_args *pa)
953 {
954
955         int res2;
956         int loopcount = 0;
957
958         /* Get the user's intro, store it in priv-callerintros/$CID, 
959            unless it is already there-- this should be done before the 
960            call is actually dialed  */
961
962         /* all ring indications and moh for the caller has been halted as soon as the 
963            target extension was picked up. We are going to have to kill some
964            time and make the caller believe the peer hasn't picked up yet */
965
966         if (ast_test_flag(opts, OPT_MUSICBACK) && !ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
967                 char *original_moh = ast_strdupa(chan->musicclass);
968                 ast_indicate(chan, -1);
969                 ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
970                 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
971                 ast_string_field_set(chan, musicclass, original_moh);
972         } else if (ast_test_flag(opts, OPT_RINGBACK)) {
973                 ast_indicate(chan, AST_CONTROL_RINGING);
974                 pa->sentringing++;
975         }
976
977         /* Start autoservice on the other chan ?? */
978         res2 = ast_autoservice_start(chan);
979         /* Now Stream the File */
980         for (loopcount = 0; loopcount < 3; loopcount++) {
981                 if (res2 && loopcount == 0)     /* error in ast_autoservice_start() */
982                         break;
983                 if (!res2)      /* on timeout, play the message again */
984                         res2 = ast_play_and_wait(peer,"priv-callpending");
985                 if (!valid_priv_reply(opts, res2))
986                         res2 = 0;
987                 /* priv-callpending script: 
988                    "I have a caller waiting, who introduces themselves as:"
989                 */
990                 if (!res2)
991                         res2 = ast_play_and_wait(peer, pa->privintro);
992                 if (!valid_priv_reply(opts, res2))
993                         res2 = 0;
994                 /* now get input from the called party, as to their choice */
995                 if( !res2 ) {
996                         /* XXX can we have both, or they are mutually exclusive ? */
997                         if( ast_test_flag(opts, OPT_PRIVACY) )
998                                 res2 = ast_play_and_wait(peer,"priv-callee-options");
999                         if( ast_test_flag(opts, OPT_SCREENING) )
1000                                 res2 = ast_play_and_wait(peer,"screen-callee-options");
1001                 }
1002                 /*! \page DialPrivacy Dial Privacy scripts
1003                 \par priv-callee-options script:
1004                         "Dial 1 if you wish this caller to reach you directly in the future,
1005                                 and immediately connect to their incoming call
1006                          Dial 2 if you wish to send this caller to voicemail now and 
1007                                 forevermore.
1008                          Dial 3 to send this caller to the torture menus, now and forevermore.
1009                          Dial 4 to send this caller to a simple "go away" menu, now and forevermore.
1010                          Dial 5 to allow this caller to come straight thru to you in the future,
1011                                 but right now, just this once, send them to voicemail."
1012                 \par screen-callee-options script:
1013                         "Dial 1 if you wish to immediately connect to the incoming call
1014                          Dial 2 if you wish to send this caller to voicemail.
1015                          Dial 3 to send this caller to the torture menus.
1016                          Dial 4 to send this caller to a simple "go away" menu.
1017                 */
1018                 if (valid_priv_reply(opts, res2))
1019                         break;
1020                 /* invalid option */
1021                 res2 = ast_play_and_wait(peer, "vm-sorry");
1022         }
1023
1024         if (ast_test_flag(opts, OPT_MUSICBACK)) {
1025                 ast_moh_stop(chan);
1026         } else if (ast_test_flag(opts, OPT_RINGBACK)) {
1027                 ast_indicate(chan, -1);
1028                 pa->sentringing=0;
1029         }
1030         ast_autoservice_stop(chan);
1031         if(ast_test_flag(opts, OPT_PRIVACY) && (res2 >= '1' && res2 <= '5')) {
1032                 /* map keypresses to various things, the index is res2 - '1' */
1033                 static const char *_val[] = { "ALLOW", "DENY", "TORTURE", "KILL", "ALLOW" };
1034                 static const int _flag[] = { AST_PRIVACY_ALLOW, AST_PRIVACY_DENY, AST_PRIVACY_TORTURE, AST_PRIVACY_KILL, AST_PRIVACY_ALLOW};
1035                 int i = res2 - '1';
1036                 if (option_verbose > 2)
1037                         ast_verbose(VERBOSE_PREFIX_3 "--Set privacy database entry %s/%s to %s\n",
1038                                              opt_args[OPT_ARG_PRIVACY], pa->privcid, _val[i]);
1039                 ast_privacy_set(opt_args[OPT_ARG_PRIVACY], pa->privcid, _flag[i]);
1040         }
1041         switch (res2) {
1042         case '1':
1043                 break;
1044         case '2':
1045                 ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status));
1046                 break;
1047         case '3':
1048                 ast_copy_string(pa->status, "TORTURE", sizeof(pa->status));
1049                 break;
1050         case '4':
1051                 ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status));
1052                 break;
1053         case '5':
1054                 /* XXX should we set status to DENY ? */
1055                 if( ast_test_flag(opts, OPT_PRIVACY) )
1056                         break;
1057                 /* if not privacy, then 5 is the same as "default" case */
1058         default:        /* bad input or -1 if failure to start autoservice */
1059                 /* well, if the user messes up, ... he had his chance... What Is The Best Thing To Do?  */
1060                 /* well, there seems basically two choices. Just patch the caller thru immediately,
1061                           or,... put 'em thru to voicemail. */
1062                 /* since the callee may have hung up, let's do the voicemail thing, no database decision */
1063                 ast_log(LOG_NOTICE, "privacy: no valid response from the callee. Sending the caller to voicemail, the callee isn't responding\n");
1064                 /* XXX should we set status to DENY ? */
1065                 /* XXX what about the privacy flags ? */
1066                 break;
1067         }
1068
1069         if (res2 == '1') {      /* the only case where we actually connect */
1070                 /* if the intro is NOCALLERID, then there's no reason to leave it on disk, it'll 
1071                    just clog things up, and it's not useful information, not being tied to a CID */
1072                 if( strncmp(pa->privcid,"NOCALLERID",10) == 0 || ast_test_flag(opts, OPT_SCREEN_NOINTRO) ) {
1073                         ast_filedelete(pa->privintro, NULL);
1074                         if( ast_fileexists(pa->privintro, NULL, NULL ) > 0 )
1075                                 ast_log(LOG_NOTICE, "privacy: ast_filedelete didn't do its job on %s\n", pa->privintro);
1076                         else if (option_verbose > 2)
1077                                 ast_verbose(VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", pa->privintro);
1078                 }
1079                 return 0;       /* the good exit path */
1080         } else {
1081                 ast_hangup(peer); /* hang up on the callee -- he didn't want to talk anyway! */
1082                 return -1;
1083         }
1084 }
1085
1086 /*! \brief returns 1 if successful, 0 or <0 if the caller should 'goto out' */
1087 static int setup_privacy_args(struct privacy_args *pa,
1088         struct ast_flags *opts, char *opt_args[], struct ast_channel *chan)
1089 {
1090         char callerid[60];
1091         int res;
1092         char *l;
1093
1094         if (!ast_strlen_zero(chan->cid.cid_num)) {
1095                 l = ast_strdupa(chan->cid.cid_num);
1096                 ast_shrink_phone_number(l);
1097                 if (ast_test_flag(opts, OPT_PRIVACY) ) {
1098                         if (option_verbose > 2)
1099                                 ast_verbose(VERBOSE_PREFIX_3  "Privacy DB is '%s', clid is '%s'\n",
1100                                              opt_args[OPT_ARG_PRIVACY], l);
1101                         pa->privdb_val = ast_privacy_check(opt_args[OPT_ARG_PRIVACY], l);
1102                 } else {
1103                         if (option_verbose > 2)
1104                                 ast_verbose(VERBOSE_PREFIX_3  "Privacy Screening, clid is '%s'\n", l);
1105                         pa->privdb_val = AST_PRIVACY_UNKNOWN;
1106                 }
1107         } else {
1108                 char *tnam, *tn2;
1109
1110                 tnam = ast_strdupa(chan->name);
1111                 /* clean the channel name so slashes don't try to end up in disk file name */
1112                 for (tn2 = tnam; *tn2; tn2++) {
1113                         if (*tn2=='/')  /* any other chars to be afraid of? */
1114                                 *tn2 = '=';
1115                 }
1116                 if (option_verbose > 2)
1117                         ast_verbose(VERBOSE_PREFIX_3  "Privacy-- callerid is empty\n");
1118
1119                 snprintf(callerid, sizeof(callerid), "NOCALLERID_%s%s", chan->exten, tnam);
1120                 l = callerid;
1121                 pa->privdb_val = AST_PRIVACY_UNKNOWN;
1122         }
1123         
1124         ast_copy_string(pa->privcid,l,sizeof(pa->privcid));
1125
1126         if( strncmp(pa->privcid,"NOCALLERID",10) != 0 && ast_test_flag(opts, OPT_SCREEN_NOCLID) ) { /* if callerid is set, and ast_test_flag(&opts, OPT_SCREEN_NOCLID) is set also */  
1127                 if (option_verbose > 2)
1128                         ast_verbose( VERBOSE_PREFIX_3  "CallerID set (%s); N option set; Screening should be off\n", pa->privcid);
1129                 pa->privdb_val = AST_PRIVACY_ALLOW;
1130         } else if (ast_test_flag(opts, OPT_SCREEN_NOCLID) && strncmp(pa->privcid,"NOCALLERID",10) == 0 ) {
1131                 if (option_verbose > 2)
1132                         ast_verbose( VERBOSE_PREFIX_3  "CallerID blank; N option set; Screening should happen; dbval is %d\n", pa->privdb_val);
1133         }
1134         
1135         if (pa->privdb_val == AST_PRIVACY_DENY ) {
1136                 ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status));
1137                 if (option_verbose > 2)
1138                         ast_verbose( VERBOSE_PREFIX_3  "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
1139                 return 0;
1140         } else if (pa->privdb_val == AST_PRIVACY_KILL ) {
1141                 ast_copy_string(pa->status, "DONTCALL", sizeof(pa->status));
1142                 return 0; /* Is this right? */
1143         } else if (pa->privdb_val == AST_PRIVACY_TORTURE ) {
1144                 ast_copy_string(pa->status, "TORTURE", sizeof(pa->status));
1145                 return 0; /* is this right??? */
1146         } else if (pa->privdb_val == AST_PRIVACY_UNKNOWN ) {
1147                 /* Get the user's intro, store it in priv-callerintros/$CID, 
1148                    unless it is already there-- this should be done before the 
1149                    call is actually dialed  */
1150
1151                 /* make sure the priv-callerintros dir actually exists */
1152                 snprintf(pa->privintro, sizeof(pa->privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR);
1153                 if (mkdir(pa->privintro, 0755) && errno != EEXIST) {
1154                         ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(errno));
1155                         return -1;
1156                 }
1157
1158                 snprintf(pa->privintro,sizeof(pa->privintro), "priv-callerintros/%s", pa->privcid);
1159                 if (ast_fileexists(pa->privintro,NULL,NULL ) > 0 && strncmp(pa->privcid,"NOCALLERID",10) != 0) {
1160                         /* the DELUX version of this code would allow this caller the
1161                            option to hear and retape their previously recorded intro.
1162                         */
1163                 } else {
1164                         int duration; /* for feedback from play_and_wait */
1165                         /* the file doesn't exist yet. Let the caller submit his
1166                            vocal intro for posterity */
1167                         /* priv-recordintro script:
1168
1169                            "At the tone, please say your name:"
1170
1171                         */
1172                         ast_answer(chan);
1173                         res = ast_play_and_record(chan, "priv-recordintro", pa->privintro, 4, "gsm", &duration, 128, 2000, 0);  /* NOTE: I've reduced the total time to 4 sec */
1174                                                                         /* don't think we'll need a lock removed, we took care of
1175                                                                            conflicts by naming the pa.privintro file */
1176                         if (res == -1) {
1177                                 /* Delete the file regardless since they hung up during recording */
1178                                 ast_filedelete(pa->privintro, NULL);
1179                                 if (ast_fileexists(pa->privintro,NULL,NULL ) > 0 )
1180                                         ast_log(LOG_NOTICE,"privacy: ast_filedelete didn't do its job on %s\n", pa->privintro);
1181                                 else if (option_verbose > 2)
1182                                         ast_verbose( VERBOSE_PREFIX_3 "Successfully deleted %s intro file\n", pa->privintro);
1183                                 return -1;
1184                         }
1185                         if (!ast_streamfile(chan, "vm-dialout", chan->language) )
1186                                 ast_waitstream(chan, "");
1187                 }
1188         }
1189         return 1;       /* success */
1190 }
1191
1192 static int dial_exec_full(struct ast_channel *chan, void *data, struct ast_flags *peerflags, int *continue_exec)
1193 {
1194         int res = -1;   /* default: error */
1195         struct ast_module_user *u;
1196         char *rest, *cur;       /* scan the list of destinations */
1197         struct chanlist *outgoing = NULL;       /* list of destinations */
1198         struct ast_channel *peer;
1199         int to; /* timeout */
1200         struct cause_args num = { chan, 0, 0, 0 };
1201         int cause;
1202         char numsubst[256];
1203         char cidname[AST_MAX_EXTENSION] = "";
1204
1205         struct ast_bridge_config config;
1206         unsigned int calldurationlimit = 0;
1207         char *dtmfcalled = NULL, *dtmfcalling = NULL;
1208         struct privacy_args pa = {
1209                 .sentringing = 0,
1210                 .privdb_val = 0,
1211                 .status = "INVALIDARGS",
1212         };
1213         int sentringing = 0, moh = 0;
1214         const char *outbound_group = NULL;
1215         int result = 0;
1216         time_t start_time;
1217         char *parse;
1218         int opermode = 0;
1219         AST_DECLARE_APP_ARGS(args,
1220                              AST_APP_ARG(peers);
1221                              AST_APP_ARG(timeout);
1222                              AST_APP_ARG(options);
1223                              AST_APP_ARG(url);
1224         );
1225         struct ast_flags opts = { 0, };
1226         char *opt_args[OPT_ARG_ARRAY_SIZE];
1227
1228         if (ast_strlen_zero(data)) {
1229                 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
1230                 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
1231                 return -1;
1232         }
1233
1234         u = ast_module_user_add(chan);  /* XXX is this the right place ? */
1235
1236         parse = ast_strdupa(data);
1237         
1238         AST_STANDARD_APP_ARGS(args, parse);
1239
1240         memset(&config,0,sizeof(struct ast_bridge_config));
1241
1242         if (!ast_strlen_zero(args.options) &&
1243                         ast_app_parse_options(dial_exec_options, &opts, opt_args, args.options)) {
1244                 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
1245                 goto done;
1246         }
1247
1248         if (ast_strlen_zero(args.peers)) {
1249                 ast_log(LOG_WARNING, "Dial requires an argument (technology/number)\n");
1250                 pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
1251                 goto done;
1252         }
1253
1254         if (ast_test_flag(&opts, OPT_OPERMODE)) {
1255                 opermode = ast_strlen_zero(opt_args[OPT_ARG_OPERMODE]) ? 1 : atoi(opt_args[OPT_ARG_OPERMODE]);
1256                 if (option_verbose > 2)
1257                         ast_verbose(VERBOSE_PREFIX_3 "Setting operator services mode to %d.\n", opermode);
1258         }
1259         
1260         if (ast_test_flag(&opts, OPT_DURATION_STOP) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_STOP])) {
1261                 calldurationlimit = atoi(opt_args[OPT_ARG_DURATION_STOP]);
1262                 if (!calldurationlimit) {
1263                         ast_log(LOG_WARNING, "Dial does not accept S(%s), hanging up.\n", opt_args[OPT_ARG_DURATION_STOP]);
1264                         pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
1265                         goto done;
1266                 }
1267                 if (option_verbose > 2)
1268                         ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %d seconds.\n", calldurationlimit);
1269         }
1270
1271         if (ast_test_flag(&opts, OPT_SENDDTMF) && !ast_strlen_zero(opt_args[OPT_ARG_SENDDTMF])) {
1272                 dtmfcalling = opt_args[OPT_ARG_SENDDTMF];
1273                 dtmfcalled = strsep(&dtmfcalling, ":");
1274         }
1275
1276         if (ast_test_flag(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT])) {
1277                 if (do_timelimit(chan, &config, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit))
1278                         goto done;
1279         }
1280
1281         if (ast_test_flag(&opts, OPT_RESETCDR) && chan->cdr)
1282                 ast_cdr_reset(chan->cdr, NULL);
1283         if (ast_test_flag(&opts, OPT_PRIVACY) && ast_strlen_zero(opt_args[OPT_ARG_PRIVACY]))
1284                 opt_args[OPT_ARG_PRIVACY] = ast_strdupa(chan->exten);
1285
1286         if (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) {
1287                 res = setup_privacy_args(&pa, &opts, opt_args, chan);
1288                 if (res <= 0)
1289                         goto out;
1290                 res = -1;       /* reset default */
1291         }
1292
1293         if (continue_exec)
1294                 *continue_exec = 0;
1295         
1296         /* If a channel group has been specified, get it for use when we create peer channels */
1297         if ((outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP_ONCE"))) {
1298                 outbound_group = ast_strdupa(outbound_group);
1299                 pbx_builtin_setvar_helper(chan, "OUTBOUND_GROUP_ONCE", NULL);
1300         } else {
1301                 outbound_group = pbx_builtin_getvar_helper(chan, "OUTBOUND_GROUP");
1302         }
1303             
1304         ast_copy_flags(peerflags, &opts, OPT_DTMF_EXIT | OPT_GO_ON | OPT_ORIGINAL_CLID | OPT_CALLER_HANGUP | OPT_IGNORE_FORWARDING);
1305         /* loop through the list of dial destinations */
1306         rest = args.peers;
1307         while ((cur = strsep(&rest, "&")) ) {
1308                 struct chanlist *tmp;
1309                 struct ast_channel *tc; /* channel for this destination */
1310                 /* Get a technology/[device:]number pair */
1311                 char *number = cur;
1312                 char *tech = strsep(&number, "/");
1313                 if (!number) {
1314                         ast_log(LOG_WARNING, "Dial argument takes format (technology/[device:]number1)\n");
1315                         goto out;
1316                 }
1317                 if (!(tmp = ast_calloc(1, sizeof(*tmp))))
1318                         goto out;
1319                 if (opts.flags) {
1320                         ast_copy_flags(tmp, &opts,
1321                                        OPT_CALLEE_TRANSFER | OPT_CALLER_TRANSFER |
1322                                        OPT_CALLEE_HANGUP | OPT_CALLER_HANGUP |
1323                                        OPT_CALLEE_MONITOR | OPT_CALLER_MONITOR |
1324                                        OPT_CALLEE_PARK | OPT_CALLER_PARK |
1325                                        OPT_RINGBACK | OPT_MUSICBACK | OPT_FORCECLID);
1326                         ast_set2_flag(tmp, args.url, DIAL_NOFORWARDHTML);       
1327                 }
1328                 ast_copy_string(numsubst, number, sizeof(numsubst));
1329                 /* Request the peer */
1330                 tc = ast_request(tech, chan->nativeformats, numsubst, &cause);
1331                 if (!tc) {
1332                         /* If we can't, just go on to the next call */
1333                         ast_log(LOG_WARNING, "Unable to create channel of type '%s' (cause %d - %s)\n",
1334                                     tech, cause, ast_cause2str(cause));
1335                         handle_cause(cause, &num);
1336                         if (!rest)      /* we are on the last destination */
1337                                 chan->hangupcause = cause;
1338                         ast_free(tmp);
1339                         continue;
1340                 }
1341                 pbx_builtin_setvar_helper(tc, "DIALEDPEERNUMBER", numsubst);
1342                 if (!ast_strlen_zero(tc->call_forward)) {
1343                         char tmpchan[256];
1344                         char *stuff;
1345                         char *tech;
1346                         ast_copy_string(tmpchan, tc->call_forward, sizeof(tmpchan));
1347                         if ((stuff = strchr(tmpchan, '/'))) {
1348                                 *stuff++ = '\0';
1349                                 tech = tmpchan;
1350                         } else {
1351                                 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", tc->call_forward, tc->context);
1352                                 stuff = tmpchan;
1353                                 tech = "Local";
1354                         }
1355                         tmp->forwards++;
1356                         if (tmp->forwards < AST_MAX_FORWARDS) {
1357                                 if (option_verbose > 2)
1358                                         ast_verbose(VERBOSE_PREFIX_3 "Now forwarding %s to '%s/%s' (thanks to %s)\n",
1359                                         chan->name, tech, stuff, tc->name);
1360                                 ast_hangup(tc);
1361                                 /* If we have been told to ignore forwards, just set this channel to null
1362                                  * and continue processing extensions normally */
1363                                 if (ast_test_flag(&opts, OPT_IGNORE_FORWARDING)) {
1364                                         tc = NULL;
1365                                         cause = AST_CAUSE_BUSY;
1366                                         if (option_verbose > 2)
1367                                                 ast_verbose(VERBOSE_PREFIX_3 "Forwarding %s to '%s/%s' prevented.\n",
1368                                                         chan->name, tech, stuff);
1369                                 } else {
1370                                         tc = ast_request(tech, chan->nativeformats, stuff, &cause);
1371                                 }
1372                                 if (!tc)
1373                                         ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s' (cause = %d)\n", tech, stuff, cause);
1374                                 else
1375                                         ast_channel_inherit_variables(chan, tc);
1376                         } else {
1377                                 if (option_verbose > 2)
1378                                         ast_verbose(VERBOSE_PREFIX_3 "Too many forwards from %s\n", tc->name);
1379                                 ast_hangup(tc);
1380                                 tc = NULL;
1381                                 cause = AST_CAUSE_CONGESTION;
1382                         }
1383                         if (!tc) {
1384                                 handle_cause(cause, &num);
1385                                 ast_free(tmp);
1386                                 continue;
1387                         }
1388                 }
1389
1390                 /* Setup outgoing SDP to match incoming one */
1391                 ast_rtp_make_compatible(tc, chan, !outgoing && !rest);
1392                 
1393                 /* Inherit specially named variables from parent channel */
1394                 ast_channel_inherit_variables(chan, tc);
1395
1396                 tc->appl = "AppDial";
1397                 tc->data = "(Outgoing Line)";
1398                 tc->whentohangup = 0;
1399
1400                 S_REPLACE(tc->cid.cid_num, ast_strdup(chan->cid.cid_num));
1401                 S_REPLACE(tc->cid.cid_name, ast_strdup(chan->cid.cid_name));
1402                 S_REPLACE(tc->cid.cid_ani, ast_strdup(chan->cid.cid_ani));
1403                 S_REPLACE(tc->cid.cid_rdnis, ast_strdup(chan->cid.cid_rdnis));
1404                 
1405                 /* Copy language from incoming to outgoing */
1406                 ast_string_field_set(tc, language, chan->language);
1407                 ast_string_field_set(tc, accountcode, chan->accountcode);
1408                 tc->cdrflags = chan->cdrflags;
1409                 if (ast_strlen_zero(tc->musicclass))
1410                         ast_string_field_set(tc, musicclass, chan->musicclass);
1411                 /* Pass callingpres, type of number, tns, ADSI CPE, transfer capability */
1412                 tc->cid.cid_pres = chan->cid.cid_pres;
1413                 tc->cid.cid_ton = chan->cid.cid_ton;
1414                 tc->cid.cid_tns = chan->cid.cid_tns;
1415                 tc->adsicpe = chan->adsicpe;
1416                 tc->transfercapability = chan->transfercapability;
1417
1418                 /* If we have an outbound group, set this peer channel to it */
1419                 if (outbound_group)
1420                         ast_app_group_set_channel(tc, outbound_group);
1421
1422                 /* Inherit context and extension */
1423                 if (!ast_strlen_zero(chan->macrocontext))
1424                         ast_copy_string(tc->dialcontext, chan->macrocontext, sizeof(tc->dialcontext));
1425                 else
1426                         ast_copy_string(tc->dialcontext, chan->context, sizeof(tc->dialcontext));
1427                 if (!ast_strlen_zero(chan->macroexten))
1428                         ast_copy_string(tc->exten, chan->macroexten, sizeof(tc->exten));
1429                 else
1430                         ast_copy_string(tc->exten, chan->exten, sizeof(tc->exten));
1431
1432                 res = ast_call(tc, numsubst, 0);        /* Place the call, but don't wait on the answer */
1433
1434                 /* Save the info in cdr's that we called them */
1435                 if (chan->cdr)
1436                         ast_cdr_setdestchan(chan->cdr, tc->name);
1437
1438                 /* check the results of ast_call */
1439                 if (res) {
1440                         /* Again, keep going even if there's an error */
1441                         ast_debug(1, "ast call on peer returned %d\n", res);
1442                         if (option_verbose > 2)
1443                                 ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
1444                         ast_hangup(tc);
1445                         tc = NULL;
1446                         ast_free(tmp);
1447                         continue;
1448                 } else {
1449                         senddialevent(chan, tc);
1450                         if (option_verbose > 2)
1451                                 ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
1452                         if (!ast_test_flag(peerflags, OPT_ORIGINAL_CLID))
1453                                 ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), get_cid_name(cidname, sizeof(cidname), chan), NULL);
1454                 }
1455                 /* Put them in the list of outgoing thingies...  We're ready now. 
1456                    XXX If we're forcibly removed, these outgoing calls won't get
1457                    hung up XXX */
1458                 ast_set_flag(tmp, DIAL_STILLGOING);     
1459                 tmp->chan = tc;
1460                 tmp->next = outgoing;
1461                 outgoing = tmp;
1462                 /* If this line is up, don't try anybody else */
1463                 if (outgoing->chan->_state == AST_STATE_UP)
1464                         break;
1465         }
1466         
1467         if (ast_strlen_zero(args.timeout)) {
1468                 to = -1;
1469         } else {
1470                 to = atoi(args.timeout);
1471                 if (to > 0)
1472                         to *= 1000;
1473                 else
1474                         ast_log(LOG_WARNING, "Invalid timeout specified: '%s'\n", args.timeout);
1475         }
1476
1477         if (!outgoing) {
1478                 strcpy(pa.status, "CHANUNAVAIL");
1479         } else {
1480                 /* Our status will at least be NOANSWER */
1481                 strcpy(pa.status, "NOANSWER");
1482                 if (ast_test_flag(outgoing, OPT_MUSICBACK)) {
1483                         moh = 1;
1484                         if (!ast_strlen_zero(opt_args[OPT_ARG_MUSICBACK])) {
1485                                 char *original_moh = ast_strdupa(chan->musicclass);
1486                                 ast_string_field_set(chan, musicclass, opt_args[OPT_ARG_MUSICBACK]);
1487                                 ast_moh_start(chan, opt_args[OPT_ARG_MUSICBACK], NULL);
1488                                 ast_string_field_set(chan, musicclass, original_moh);
1489                         } else {
1490                                 ast_moh_start(chan, NULL, NULL);
1491                         }
1492                         ast_indicate(chan, AST_CONTROL_PROGRESS);
1493                 } else if (ast_test_flag(outgoing, OPT_RINGBACK)) {
1494                         ast_indicate(chan, AST_CONTROL_RINGING);
1495                         sentringing++;
1496                 }
1497         }
1498
1499         time(&start_time);
1500         peer = wait_for_answer(chan, outgoing, &to, peerflags, &pa, &num, &result);
1501         
1502         if (!peer) {
1503                 if (result) {
1504                         res = result;
1505                 } else if (to) { /* Musta gotten hung up */
1506                         res = -1;
1507                 } else { /* Nobody answered, next please? */
1508                         res = 0;
1509                 }
1510                 /* almost done, although the 'else' block is 400 lines */
1511         } else {
1512                 const char *number;
1513                 time_t end_time, answer_time = time(NULL);
1514                 char toast[80]; /* buffer to set variables */
1515
1516                 strcpy(pa.status, "ANSWER");
1517                 /* Ah ha!  Someone answered within the desired timeframe.  Of course after this
1518                    we will always return with -1 so that it is hung up properly after the 
1519                    conversation.  */
1520                 hanguptree(outgoing, peer);
1521                 outgoing = NULL;
1522                 /* If appropriate, log that we have a destination channel */
1523                 if (chan->cdr)
1524                         ast_cdr_setdestchan(chan->cdr, peer->name);
1525                 if (peer->name)
1526                         pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", peer->name);
1527
1528                 number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
1529                 if (!number)
1530                         number = numsubst;
1531                 pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", number);
1532                 if (!ast_strlen_zero(args.url) && ast_channel_supports_html(peer) ) {
1533                         ast_debug(1, "app_dial: sendurl=%s.\n", args.url);
1534                         ast_channel_sendurl( peer, args.url );
1535                 }
1536                 if ( (ast_test_flag(&opts, OPT_PRIVACY) || ast_test_flag(&opts, OPT_SCREENING)) && pa.privdb_val == AST_PRIVACY_UNKNOWN) {
1537                         if (do_privacy(chan, peer, &opts, opt_args, &pa)) {
1538                                 res = 0;
1539                                 goto out;
1540                         }
1541                 }
1542                 if (!ast_test_flag(&opts, OPT_ANNOUNCE) || ast_strlen_zero(opt_args[OPT_ARG_ANNOUNCE])) {
1543                         res = 0;
1544                 } else {
1545                         int digit = 0;
1546                         /* Start autoservice on the other chan */
1547                         res = ast_autoservice_start(chan);
1548                         /* Now Stream the File */
1549                         if (!res)
1550                                 res = ast_streamfile(peer, opt_args[OPT_ARG_ANNOUNCE], peer->language);
1551                         if (!res) {
1552                                 digit = ast_waitstream(peer, AST_DIGIT_ANY); 
1553                         }
1554                         /* Ok, done. stop autoservice */
1555                         res = ast_autoservice_stop(chan);
1556                         if (digit > 0 && !res)
1557                                 res = ast_senddigit(chan, digit); 
1558                         else
1559                                 res = digit;
1560
1561                 }
1562
1563                 if (chan && peer && ast_test_flag(&opts, OPT_GOTO) && !ast_strlen_zero(opt_args[OPT_ARG_GOTO])) {
1564                         replace_macro_delimiter(opt_args[OPT_ARG_GOTO]);
1565                         ast_parseable_goto(chan, opt_args[OPT_ARG_GOTO]);
1566                         ast_parseable_goto(peer, opt_args[OPT_ARG_GOTO]);
1567                         peer->priority++;
1568                         ast_pbx_start(peer);
1569                         hanguptree(outgoing, NULL);
1570                         if (continue_exec)
1571                                 *continue_exec = 1;
1572                         res = 0;
1573                         goto done;
1574                 }
1575
1576                 if (ast_test_flag(&opts, OPT_CALLEE_MACRO) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_MACRO])) {
1577                         struct ast_app *theapp;
1578                         const char *macro_result;
1579
1580                         res = ast_autoservice_start(chan);
1581                         if (res) {
1582                                 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
1583                                 res = -1;
1584                         }
1585
1586                         theapp = pbx_findapp("Macro");
1587
1588                         if (theapp && !res) {   /* XXX why check res here ? */
1589                                 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_MACRO]);
1590                                 res = pbx_exec(peer, theapp, opt_args[OPT_ARG_CALLEE_MACRO]);
1591                                 ast_debug(1, "Macro exited with status %d\n", res);
1592                                 res = 0;
1593                         } else {
1594                                 ast_log(LOG_ERROR, "Could not find application Macro\n");
1595                                 res = -1;
1596                         }
1597
1598                         if (ast_autoservice_stop(chan) < 0) {
1599                                 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
1600                                 res = -1;
1601                         }
1602
1603                         if (!res && (macro_result = pbx_builtin_getvar_helper(peer, "MACRO_RESULT"))) {
1604                                 char *macro_transfer_dest;
1605
1606                                 if (!strcasecmp(macro_result, "BUSY")) {
1607                                         ast_copy_string(pa.status, macro_result, sizeof(pa.status));
1608                                         ast_set_flag(peerflags, OPT_GO_ON);
1609                                         res = -1;
1610                                 } else if (!strcasecmp(macro_result, "CONGESTION") || !strcasecmp(macro_result, "CHANUNAVAIL")) {
1611                                         ast_copy_string(pa.status, macro_result, sizeof(pa.status));
1612                                         ast_set_flag(peerflags, OPT_GO_ON);     
1613                                         res = -1;
1614                                 } else if (!strcasecmp(macro_result, "CONTINUE")) {
1615                                         /* hangup peer and keep chan alive assuming the macro has changed 
1616                                            the context / exten / priority or perhaps 
1617                                            the next priority in the current exten is desired.
1618                                         */
1619                                         ast_set_flag(peerflags, OPT_GO_ON);     
1620                                         res = -1;
1621                                 } else if (!strcasecmp(macro_result, "ABORT")) {
1622                                         /* Hangup both ends unless the caller has the g flag */
1623                                         res = -1;
1624                                 } else if (!strncasecmp(macro_result, "GOTO:", 5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
1625                                         res = -1;
1626                                         /* perform a transfer to a new extension */
1627                                         if (strchr(macro_transfer_dest, '^')) { /* context^exten^priority*/
1628                                                 replace_macro_delimiter(macro_transfer_dest);
1629                                                 if (!ast_parseable_goto(chan, macro_transfer_dest))
1630                                                         ast_set_flag(peerflags, OPT_GO_ON);
1631                                         }
1632                                 }
1633                         }
1634                 }
1635
1636                 if (ast_test_flag(&opts, OPT_CALLEE_GOSUB) && !ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GOSUB])) {
1637                         struct ast_app *theapp;
1638                         const char *gosub_result;
1639                         char *gosub_args, *gosub_argstart;
1640                         ast_log(LOG_ERROR, "In OPT_CALLEE_GOSUB code!\n");
1641
1642                         res = ast_autoservice_start(chan);
1643                         if (res) {
1644                                 ast_log(LOG_ERROR, "Unable to start autoservice on calling channel\n");
1645                                 res = -1;
1646                         }
1647
1648                         theapp = pbx_findapp("Gosub");
1649
1650                         if (theapp && !res) {   /* XXX why check res here ? */
1651                                 replace_macro_delimiter(opt_args[OPT_ARG_CALLEE_GOSUB]);
1652
1653                                 /* Set where we came from */
1654                                 ast_copy_string(peer->context, "app_dial_gosub_virtual_context", sizeof(peer->context));
1655                                 ast_copy_string(peer->exten, "s", sizeof(peer->exten));
1656                                 peer->priority = 0;
1657
1658                                 ast_log(LOG_ERROR, "Gosub stuff is: %s\n", opt_args[OPT_ARG_CALLEE_GOSUB]);
1659                                 gosub_argstart = strchr(opt_args[OPT_ARG_CALLEE_GOSUB], '|');
1660                                 if (gosub_argstart) {
1661                                         *gosub_argstart = 0;
1662                                         asprintf(&gosub_args, "%s|s|1(%s)", opt_args[OPT_ARG_CALLEE_GOSUB], gosub_argstart + 1);
1663                                         *gosub_argstart = '|';
1664                                 } else {
1665                                         asprintf(&gosub_args, "%s|s|1", opt_args[OPT_ARG_CALLEE_GOSUB]);
1666                                 }
1667                                 ast_log(LOG_DEBUG, "Gosub_args is: %s\n", gosub_args);
1668                                 if (gosub_args) {
1669                                         ast_log(LOG_ERROR, "About to pbx_exec!\n");
1670                                         res = pbx_exec(peer, theapp, gosub_args);
1671                                         ast_pbx_run(peer);
1672                                         ast_log(LOG_ERROR, "pbx_exec returns %d!\n", res);
1673                                         free(gosub_args);
1674                                         if (option_debug)
1675                                                 ast_log(LOG_DEBUG, "Gosub exited with status %d\n", res);
1676                                 } else
1677                                         ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n");
1678                                 
1679                                 res = 0;
1680                         } else {
1681                                 ast_log(LOG_ERROR, "Could not find application Gosub\n");
1682                                 res = -1;
1683                         }
1684
1685                         if (ast_autoservice_stop(chan) < 0) {
1686                                 ast_log(LOG_ERROR, "Could not stop autoservice on calling channel\n");
1687                                 res = -1;
1688                         }
1689
1690                         if (!res && (gosub_result = pbx_builtin_getvar_helper(peer, "GOSUB_RESULT"))) {
1691                                 char *gosub_transfer_dest;
1692
1693                                 if (!strcasecmp(gosub_result, "BUSY")) {
1694                                         ast_copy_string(pa.status, gosub_result, sizeof(pa.status));
1695                                         ast_set_flag(peerflags, OPT_GO_ON);
1696                                         res = -1;
1697                                 } else if (!strcasecmp(gosub_result, "CONGESTION") || !strcasecmp(gosub_result, "CHANUNAVAIL")) {
1698                                         ast_copy_string(pa.status, gosub_result, sizeof(pa.status));
1699                                         ast_set_flag(peerflags, OPT_GO_ON);     
1700                                         res = -1;
1701                                 } else if (!strcasecmp(gosub_result, "CONTINUE")) {
1702                                         /* hangup peer and keep chan alive assuming the macro has changed 
1703                                            the context / exten / priority or perhaps 
1704                                            the next priority in the current exten is desired.
1705                                         */
1706                                         ast_set_flag(peerflags, OPT_GO_ON);     
1707                                         res = -1;
1708                                 } else if (!strcasecmp(gosub_result, "ABORT")) {
1709                                         /* Hangup both ends unless the caller has the g flag */
1710                                         res = -1;
1711                                 } else if (!strncasecmp(gosub_result, "GOTO:", 5) && (gosub_transfer_dest = ast_strdupa(gosub_result + 5))) {
1712                                         res = -1;
1713                                         /* perform a transfer to a new extension */
1714                                         if (strchr(gosub_transfer_dest, '^')) { /* context^exten^priority*/
1715                                                 replace_macro_delimiter(gosub_transfer_dest);
1716                                                 if (!ast_parseable_goto(chan, gosub_transfer_dest))
1717                                                         ast_set_flag(peerflags, OPT_GO_ON);
1718                                         }
1719                                 }
1720                         }
1721                 }
1722
1723                 if (!res) {
1724                         if (calldurationlimit > 0) {
1725                                 peer->whentohangup = time(NULL) + calldurationlimit;
1726                         }
1727                         if (!ast_strlen_zero(dtmfcalled)) { 
1728                                 if (option_verbose > 2)
1729                                         ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the called party.\n", dtmfcalled);
1730                                 res = ast_dtmf_stream(peer,chan,dtmfcalled,250);
1731                         }
1732                         if (!ast_strlen_zero(dtmfcalling)) {
1733                                 if (option_verbose > 2)
1734                                         ast_verbose(VERBOSE_PREFIX_3 "Sending DTMF '%s' to the calling party.\n", dtmfcalling);
1735                                 res = ast_dtmf_stream(chan,peer,dtmfcalling,250);
1736                         }
1737                 }
1738                 
1739                 if (res) {      /* some error */
1740                         res = -1;
1741                         end_time = time(NULL);
1742                 } else {
1743                         if (ast_test_flag(peerflags, OPT_CALLEE_TRANSFER))
1744                                 ast_set_flag(&(config.features_callee), AST_FEATURE_REDIRECT);
1745                         if (ast_test_flag(peerflags, OPT_CALLER_TRANSFER))
1746                                 ast_set_flag(&(config.features_caller), AST_FEATURE_REDIRECT);
1747                         if (ast_test_flag(peerflags, OPT_CALLEE_HANGUP))
1748                                 ast_set_flag(&(config.features_callee), AST_FEATURE_DISCONNECT);
1749                         if (ast_test_flag(peerflags, OPT_CALLER_HANGUP))
1750                                 ast_set_flag(&(config.features_caller), AST_FEATURE_DISCONNECT);
1751                         if (ast_test_flag(peerflags, OPT_CALLEE_MONITOR))
1752                                 ast_set_flag(&(config.features_callee), AST_FEATURE_AUTOMON);
1753                         if (ast_test_flag(peerflags, OPT_CALLER_MONITOR)) 
1754                                 ast_set_flag(&(config.features_caller), AST_FEATURE_AUTOMON);
1755                         if (ast_test_flag(peerflags, OPT_CALLEE_PARK))
1756                                 ast_set_flag(&(config.features_callee), AST_FEATURE_PARKCALL);
1757                         if (ast_test_flag(peerflags, OPT_CALLER_PARK))
1758                                 ast_set_flag(&(config.features_caller), AST_FEATURE_PARKCALL);
1759
1760                         if (moh) {
1761                                 moh = 0;
1762                                 ast_moh_stop(chan);
1763                         } else if (sentringing) {
1764                                 sentringing = 0;
1765                                 ast_indicate(chan, -1);
1766                         }
1767                         /* Be sure no generators are left on it */
1768                         ast_deactivate_generator(chan);
1769                         /* Make sure channels are compatible */
1770                         res = ast_channel_make_compatible(chan, peer);
1771                         if (res < 0) {
1772                                 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", chan->name, peer->name);
1773                                 ast_hangup(peer);
1774                                 res = -1;
1775                                 goto done;
1776                         }
1777                         if (opermode && !strncmp(chan->name,"Zap",3) && !strncmp(peer->name,"Zap",3)) {
1778                                 /* XXX what's this special handling for Zap <-> Zap ? */
1779                                 struct oprmode oprmode;
1780
1781                                 oprmode.peer = peer;
1782                                 oprmode.mode = opermode;
1783
1784                                 ast_channel_setoption(chan,
1785                                         AST_OPTION_OPRMODE,&oprmode,sizeof(struct oprmode),0);
1786                         }
1787                         res = ast_bridge_call(chan,peer,&config);
1788                         end_time = time(NULL);
1789                         snprintf(toast, sizeof(toast), "%ld", (long)(end_time - answer_time));
1790                         pbx_builtin_setvar_helper(chan, "ANSWEREDTIME", toast);
1791                 }
1792
1793                 snprintf(toast, sizeof(toast), "%ld", (long)(end_time - start_time));
1794                 pbx_builtin_setvar_helper(chan, "DIALEDTIME", toast);
1795
1796                 if (res != AST_PBX_NO_HANGUP_PEER) {
1797                         if (!chan->_softhangup)
1798                                 chan->hangupcause = peer->hangupcause;
1799                         ast_hangup(peer);
1800                 }
1801         }       
1802 out:
1803         if (moh) {
1804                 moh = 0;
1805                 ast_moh_stop(chan);
1806         } else if (sentringing) {
1807                 sentringing = 0;
1808                 ast_indicate(chan, -1);
1809         }
1810         ast_channel_early_bridge(chan, NULL);
1811         hanguptree(outgoing, NULL);
1812         pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
1813         senddialendevent(chan, pa.status);
1814         ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);
1815         
1816         if ((ast_test_flag(peerflags, OPT_GO_ON)) && (!chan->_softhangup) && (res != AST_PBX_KEEPALIVE)) {
1817                 if (calldurationlimit)
1818                         chan->whentohangup = 0;
1819                 res = 0;
1820         }
1821
1822 done:
1823         ast_module_user_remove(u);      /* XXX probably not the right place for this. */
1824         return res;
1825 }
1826
1827 static int dial_exec(struct ast_channel *chan, void *data)
1828 {
1829         struct ast_flags peerflags;
1830
1831         memset(&peerflags, 0, sizeof(peerflags));
1832
1833         return dial_exec_full(chan, data, &peerflags, NULL);
1834 }
1835
1836 static int retrydial_exec(struct ast_channel *chan, void *data)
1837 {
1838         char *announce = NULL, *dialdata = NULL;
1839         const char *context = NULL;
1840         int sleep = 0, loops = 0, res = -1;
1841         struct ast_module_user *u;
1842         struct ast_flags peerflags;
1843         
1844         if (ast_strlen_zero(data)) {
1845                 ast_log(LOG_WARNING, "RetryDial requires an argument!\n");
1846                 return -1;
1847         }       
1848
1849         u = ast_module_user_add(chan);
1850
1851         announce = ast_strdupa(data);
1852
1853         memset(&peerflags, 0, sizeof(peerflags));
1854
1855         if ((dialdata = strchr(announce, '|'))) {
1856                 *dialdata++ = '\0';
1857                 if ((sleep = atoi(dialdata))) {
1858                         sleep *= 1000;
1859                 } else {
1860                         ast_log(LOG_ERROR, "%s requires the numerical argument <sleep>\n",rapp);
1861                         goto done;
1862                 }
1863                 if ((dialdata = strchr(dialdata, '|'))) {
1864                         *dialdata++ = '\0';
1865                         if (!(loops = atoi(dialdata))) {
1866                                 ast_log(LOG_ERROR, "%s requires the numerical argument <loops>\n",rapp);
1867                                 goto done;
1868                         }
1869                 }
1870         }
1871         
1872         if ((dialdata = strchr(dialdata, '|'))) {
1873                 *dialdata++ = '\0';
1874         } else {
1875                 ast_log(LOG_ERROR, "%s requires more arguments\n",rapp);
1876                 goto done;
1877         }
1878                 
1879         if (sleep < 1000)
1880                 sleep = 10000;
1881
1882         if (!loops)
1883                 loops = -1;     /* run forever */
1884         
1885         context = pbx_builtin_getvar_helper(chan, "EXITCONTEXT");
1886
1887         res = 0;
1888         while (loops) {
1889                 int continue_exec;
1890
1891                 chan->data = "Retrying";
1892                 if (ast_test_flag(chan, AST_FLAG_MOH))
1893                         ast_moh_stop(chan);
1894
1895                 res = dial_exec_full(chan, dialdata, &peerflags, &continue_exec);
1896                 if (continue_exec)
1897                         break;
1898                 if (res == 0) {
1899                         if (ast_test_flag(&peerflags, OPT_DTMF_EXIT)) {
1900                                 if (!(res = ast_streamfile(chan, announce, chan->language)))
1901                                         res = ast_waitstream(chan, AST_DIGIT_ANY);
1902                                 if (!res && sleep) {
1903                                         if (!ast_test_flag(chan, AST_FLAG_MOH))
1904                                                 ast_moh_start(chan, NULL, NULL);
1905                                         res = ast_waitfordigit(chan, sleep);
1906                                 }
1907                         } else {
1908                                 if (!(res = ast_streamfile(chan, announce, chan->language)))
1909                                         res = ast_waitstream(chan, "");
1910                                 if (sleep) {
1911                                         if (!ast_test_flag(chan, AST_FLAG_MOH))
1912                                                 ast_moh_start(chan, NULL, NULL);
1913                                         if (!res) 
1914                                                 res = ast_waitfordigit(chan, sleep);
1915                                 }
1916                         }
1917                 }
1918
1919                 if (res < 0)
1920                         break;
1921                 else if (res > 0) { /* Trying to send the call elsewhere (1 digit ext) */
1922                         if (onedigit_goto(chan, context, (char) res, 1)) {
1923                                 res = 0;
1924                                 break;
1925                         }
1926                 }
1927                 loops--;
1928         }
1929         if (loops == 0)
1930                 res = 0;
1931         else if (res == 1)
1932                 res = 0;
1933
1934         if (ast_test_flag(chan, AST_FLAG_MOH))
1935                 ast_moh_stop(chan);
1936  done:
1937         ast_module_user_remove(u);
1938         return res;
1939 }
1940
1941 static int keepalive_exec(struct ast_channel *chan, void *data)
1942 {
1943         return AST_PBX_KEEPALIVE;
1944 }
1945
1946 static int unload_module(void)
1947 {
1948         int res;
1949         struct ast_context *con;
1950
1951         res = ast_unregister_application(app);
1952         res |= ast_unregister_application(rapp);
1953         res |= ast_unregister_application(kapp);
1954
1955         ast_module_user_hangup_all();
1956
1957         if ((con = ast_context_find("app_dial_gosub_virtual_context"))) {
1958                 ast_context_remove_extension2(con, "s", 1, NULL);
1959         }
1960
1961         return res;
1962 }
1963
1964 static int load_module(void)
1965 {
1966         int res;
1967         struct ast_context *con;
1968
1969         con = ast_context_find("app_dial_gosub_virtual_context");
1970         if (!con)
1971                 con = ast_context_create(NULL, "app_dial_gosub_virtual_context", "app_dial");
1972         if (!con)
1973                 ast_log(LOG_ERROR, "Dial virtual context 'app_dial_gosub_virtual_context' does not exist and unable to create\n");
1974         else
1975                 ast_add_extension2(con, 1, "s", 1, NULL, NULL, "KeepAlive", ast_strdup(""), ast_free, "app_dial");
1976
1977         res = ast_register_application(app, dial_exec, synopsis, descrip);
1978         res |= ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);
1979         res |= ast_register_application(kapp, keepalive_exec, ksynopsis, kdescrip);
1980         
1981         return res;
1982 }
1983
1984 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialing Application");