Index: apps/app_dial.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_dial.c,v
retrieving revision 1.124
diff -u -r1.124 app_dial.c
--- apps/app_dial.c	10 Jan 2005 14:46:59 -0000	1.124
+++ apps/app_dial.c	11 Jan 2005 02:15:38 -0000
@@ -111,6 +111,25 @@
 "             CHANUNAVAIL | CONGESTION | NOANSWER | BUSY | ANSWER | CANCEL\n"
 "";
 
+/* RetryDial App by Anthony Minessale II <anthmct@yahoo.com> Jan/2005 */
+static char *rapp = "RetryDial";
+static char *rsynopsis = "Place a call, retrying on failure allowing optional exit extension.\n";
+static char *rdescrip =
+"  RetryDial(announce[|context][|sleep][|loops]:Technology/resource[&Technology2/resource2...][|timeout][|options][|URL]):\n"
+"Attempt to place a call.  If no channel can be reached, play the file\n"
+"defined by 'announce' waiting 'sleep' seconds to retry the call.\n"
+"If the specified number of attempts matches 'loops' the call will be transferred to\n"
+"the extension 'v' in the context defined by 'context'\n"
+"\nIf 'loops' is set to 0, the call will retry endlessly.\n\n"
+"While waiting, a 1 digit extension may be dialed.  If that extension exists in 'context',\n"
+"The call will exit the application to that extension immmediately.\n\n"
+
+"If unspecified, 'loops' defaults to 12, 'sleep' defaults to 10\n"
+"and 'context' defaults to the current context\n\n"
+"All the arguements after the first ':' are passed directly to Dial() (show application Dial)\n\n"
+"";
+
+
 /* We define a customer "local user" structure because we
    use it not only for keeping track of what is in use but
    also for keeping track of who we're dialing. */
@@ -628,7 +647,7 @@
 					play_warning = atol(var);
 					playargs++;
 					var = strsep(&stack, ":");
-					if(var) {
+					if (var) {
 						warning_freq = atol(var);
 						playargs++;
 					}
@@ -982,7 +1001,7 @@
 		if (numsubst)
 			pbx_builtin_setvar_helper(chan, "DIALEDPEERNUMBER", numsubst);
  		/* JDG: sendurl */
- 		if( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
+ 		if ( url && !ast_strlen_zero(url) && ast_channel_supports_html(peer) ) {
  			ast_log(LOG_DEBUG, "app_dial: sendurl=%s.\n", url);
  			ast_channel_sendurl( peer, url );
  		} /* /JDG */
@@ -1015,8 +1034,8 @@
 			app = pbx_findapp("Macro");
 
 			if (app && !res) {
-				for(res=0;res<strlen(macroname);res++)
-					if(macroname[res] == '^')
+				for (res=0;res<strlen(macroname);res++)
+					if (macroname[res] == '^')
 						macroname[res] = '|';
 				res = pbx_exec(peer, app, macroname, 1);
 				ast_log(LOG_DEBUG, "Macro exited with status %d\n", res);
@@ -1055,16 +1074,16 @@
 					} else if (!strcasecmp(macro_result, "ABORT")) {
 						/* Hangup both ends unless the caller has the g flag */
 						res = -1;
-					} else if(!strncasecmp(macro_result, "GOTO:",5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
+					} else if (!strncasecmp(macro_result, "GOTO:",5) && (macro_transfer_dest = ast_strdupa(macro_result + 5))) {
 						res = -1;
 						/* perform a transfer to a new extension */
-						if(strchr(macro_transfer_dest,'^')) { /* context^exten^priority*/
+						if (strchr(macro_transfer_dest,'^')) { /* context^exten^priority*/
 							/* no brainer mode... substitute ^ with | and feed it to builtin goto */
-							for(res=0;res<strlen(macro_transfer_dest);res++)
-								if(macro_transfer_dest[res] == '^')
+							for (res=0;res<strlen(macro_transfer_dest);res++)
+								if (macro_transfer_dest[res] == '^')
 									macro_transfer_dest[res] = '|';
 
-							if(!ast_parseable_goto(chan, macro_transfer_dest))
+							if (!ast_parseable_goto(chan, macro_transfer_dest))
 								ast_set_flag(&peerflags, DIAL_GO_ON);
 
 						}
@@ -1152,22 +1171,123 @@
 	
 	LOCAL_USER_REMOVE(u);
 	
-	if((ast_test_flag(&peerflags, DIAL_GO_ON)) && (!chan->_softhangup))
+	if ((ast_test_flag(&peerflags, DIAL_GO_ON)) && (!chan->_softhangup))
 	    res=0;
 	    
 	return res;
 }
 
+static int retrydial_exec(struct ast_channel *chan, void *data)
+{
+	char *mydata = NULL, *dialdata = NULL;
+	int res = 0;
+	struct localuser *u = NULL;
+	char rexten[2], *announce = NULL, *context = NULL, *sleep = NULL, *loops = NULL;
+	int sleep_i = 10000, loops_i = 12;
+	
+	if (!(mydata = ast_strdupa(data))) {
+		ast_log(LOG_ERROR,"Out of memory!\n");
+		return -1;
+	}
+
+	if ((dialdata = strchr(mydata,':'))) {
+		*dialdata = '\0';
+		dialdata++;
+	} else {
+		ast_log(LOG_ERROR,"Invalid Input!\n");
+        return -1;
+	}
+
+	if ((announce = mydata)) {
+		if ((context = strchr(announce,'|'))) {
+			*context = '\0';
+			context++;
+			if ((sleep = strchr(context,'|'))) {
+				*sleep = '\0';
+				sleep++;
+				sleep_i = atoi(sleep) * 1000;
+				if ((loops = strchr(sleep, '|'))) {
+					*loops = '\0';
+					loops++;
+					loops_i = atoi(loops);
+				}
+			}
+		}
+	}
+
+	if (!(announce && dialdata)) {
+		ast_log(LOG_ERROR,"Missing Information!\n");
+        return -1;
+	}
+	LOCAL_USER_ADD(u);
+
+	if (!context)
+		context = chan->context;
+
+	if (loops_i < 1)
+		loops_i = -1;
+
+	if (sleep_i < 1000)
+		sleep_i = 10000;
+	
+	if (!loops_i)
+		loops_i = -1;
+	
+	while(loops_i) {
+		chan->data = "Retrying";
+		if (ast_test_flag(chan, AST_FLAG_MOH))
+			ast_moh_stop(chan);
+		if ((res = dial_exec(chan, dialdata)))
+			break;
+
+		if (!(res = ast_streamfile(chan, announce, chan->language)))
+			res = ast_waitstream(chan, AST_DIGIT_ANY);
+		
+		if (!res) {
+			if (!ast_test_flag(chan, AST_FLAG_MOH))
+				ast_moh_start(chan, NULL);
+			res = ast_waitfordigit(chan, sleep_i);
+		}
+		if (res < 0)
+			break;
+
+		if (res) {
+			snprintf(rexten,sizeof(rexten),"%c", res);
+			if (ast_exists_extension(chan, context, rexten, 1, chan->cid.cid_num)) {
+				ast_explicit_goto(chan, context, rexten, 0);
+				res = 0;
+				break;
+			}
+		}
+
+		loops_i--;
+	}
+	
+	if (!loops_i && (ast_exists_extension(chan, context, "v", 1, chan->cid.cid_num)) ) {
+		ast_explicit_goto(chan, context, "v", 0);
+		res = 0;
+	}
+
+	if (ast_test_flag(chan, AST_FLAG_MOH))
+		ast_moh_stop(chan);
+
+	LOCAL_USER_REMOVE(u);
+	return res;
+
+}
+
 int unload_module(void)
 {
 	STANDARD_HANGUP_LOCALUSERS;
-	return ast_unregister_application(app);
+	ast_unregister_application(app);
+	return ast_unregister_application(rapp);
 }
 
 int load_module(void)
 {
 	int res;
-	res = ast_register_application(app, dial_exec, synopsis, descrip);
+	if (!(res = ast_register_application(app, dial_exec, synopsis, descrip)))
+		res = ast_register_application(rapp, retrydial_exec, rsynopsis, rdescrip);
 	return res;
 }
 
