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