--- asterisk-1.4.13/apps/app_read.c.orig	2006-09-07 12:54:36.000000000 -0600
+++ asterisk-1.4.13/apps/app_read.c	2007-10-15 20:48:20.000000000 -0600
@@ -49,12 +49,14 @@
 	OPT_SKIP = (1 << 0),
 	OPT_INDICATION = (1 << 1),
 	OPT_NOANSWER = (1 << 2),
+	OPT_USE_DEFAULT = (1 << 3),
 } read_option_flags;
 
 AST_APP_OPTIONS(read_app_options, {
 	AST_APP_OPTION('s', OPT_SKIP),
 	AST_APP_OPTION('i', OPT_INDICATION),
 	AST_APP_OPTION('n', OPT_NOANSWER),
+	AST_APP_OPTION('d', OPT_USE_DEFAULT),
 });
 
 static char *app = "Read";
@@ -71,10 +73,11 @@
 "                press the '#' key).\n"
 "                Defaults to 0 - no limit - wait for the user press the '#' key.\n"
 "                Any value below 0 means the same. Max accepted value is 255.\n"
-"  option     -- options are 's' , 'i', 'n'\n"
+"  option     -- options are 's', 'i', 'n', 'd'\n"
 "                's' to return immediately if the line is not up,\n"
-"                'i' to play  filename as an indication tone from your indications.conf\n"
-"                'n' to read digits even if the line is not up.\n"
+"                'i' to play filename as an indication tone from your indications.conf\n"
+"                'n' to read digits even if the line is not up,\n"
+"                'd' to use the current value of the variable as default on timeout.\n"
 "  attempts   -- if greater than 1, that many attempts will be made in the \n"
 "                event no data is entered.\n"
 "  timeout    -- An integer number of seconds to wait for a digit response. If greater\n"
@@ -126,11 +129,19 @@
 	}
 
 	if (!ast_strlen_zero(arglist.timeout)) {
-		to = atoi(arglist.timeout);
-		if (to <= 0)
+		/* Allow fractional timeouts. */
+		double to_d;
+		to_d = atof(arglist.timeout);
+		if (to_d <= 0) {
 			to = 0;
-		else
-			to *= 1000;
+		} else {
+			/* A fractional timeout, so force it to be at
+			   least one millisecond. */
+			to = to_d * 1000;
+			if (to <= 0) {
+				to = 1;
+			}
+		}
 	}
 
 	if (ast_strlen_zero(arglist.filename)) {
@@ -148,6 +159,17 @@
 		ast_module_user_remove(u);
 		return -1;
 	}
+	if (ast_test_flag(&flags,OPT_USE_DEFAULT)) {
+		const char *defaultvalue = pbx_builtin_getvar_helper(chan, arglist.variable);
+		if (defaultvalue) {
+			size_t len = strlen(defaultvalue) + 1;
+			if (len >= sizeof(tmp)) {
+				len = sizeof(tmp) - 1;
+			}
+			memcpy(tmp, defaultvalue, len);
+			tmp[len] = '\0';
+		}
+	}
 	ts=NULL;
 	if (ast_test_flag(&flags,OPT_INDICATION)) {
 		if (!ast_strlen_zero(arglist.filename)) {
@@ -157,7 +179,7 @@
 	if (chan->_state != AST_STATE_UP) {
 		if (ast_test_flag(&flags,OPT_SKIP)) {
 			/* At the user's option, skip if the line is not up */
-			pbx_builtin_setvar_helper(chan, arglist.variable, "\0");
+			pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
 			ast_module_user_remove(u);
 			return 0;
 		} else if (!ast_test_flag(&flags,OPT_NOANSWER)) {
@@ -176,7 +198,9 @@
 					res = ast_waitfordigit(chan, to);
 					ast_playtones_stop(chan);
 					if (res < 1) {
-						tmp[x]='\0';
+						if (x > 0 || !ast_test_flag(&flags,OPT_USE_DEFAULT)) {
+							tmp[x]='\0';
+						}
 						break;
 					}
 					tmp[x++] = res;
@@ -186,7 +210,7 @@
 					}
 				}
 			} else {
-				res = ast_app_getdata(chan, arglist.filename, tmp, maxdigits, to);
+				res = ast_app_getdata_use_default(chan, arglist.filename, tmp, maxdigits, to);
 			}
 			if (res > -1) {
 				pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
--- asterisk-1.4.13/main/channel.c.orig	2007-10-09 15:55:06.000000000 -0600
+++ asterisk-1.4.13/main/channel.c	2007-10-15 20:57:57.000000000 -0600
@@ -3313,7 +3313,11 @@
 
 int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders)
 {
-	return ast_readstring_full(c, s, len, timeout, ftimeout, enders, -1, -1);
+	/* For compatibility with the version where S does not contain a default value. */
+	int ret = ast_readstring_full(c, s, len, timeout, ftimeout, enders, -1, -1);
+	if (ret == 1 && len > 0) {
+		s[0] = '\0';
+	}
 }
 
 int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int ftimeout, char *enders, int audiofd, int ctrlfd)
@@ -3340,7 +3344,10 @@
 		if (d < 0)
 			return -1;
 		if (d == 0) {
-			s[pos]='\0';
+			/* Time is up, so don't modify the return
+			   string if it is the default value. */
+			if (pos > 0)
+				s[pos]='\0';
 			return 1;
 		}
 		if (d == 1) {
--- asterisk-1.4.13/main/app.c.orig	2007-09-25 08:13:25.000000000 -0600
+++ asterisk-1.4.13/main/app.c	2007-10-15 20:52:23.000000000 -0600
@@ -106,10 +106,15 @@
  *      "ludicrous time" (essentially never times out) */
 int ast_app_getdata(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout)
 {
-	int res,to,fto;
-	/* XXX Merge with full version? XXX */
 	if (maxlen)
 		s[0] = '\0';
+	return ast_app_getdata_use_default(c, prompt, s, maxlen, timeout);
+}
+
+int ast_app_getdata_use_default(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout)
+{
+	int res,to,fto;
+	/* XXX Merge with full version? XXX */
 	if (prompt) {
 		res = ast_streamfile(c, prompt, c->language);
 		if (res < 0)
@@ -122,7 +127,7 @@
 		fto = to = timeout;
 	if (timeout < 0) 
 		fto = to = 1000000000;
-	res = ast_readstring(c, s, maxlen, to, fto, "#");
+	res = ast_readstring_full(c, s, maxlen, to, fto, "#", -1, -1);
 	return res;
 }
 
--- asterisk-1.4.13/include/asterisk/app.h.orig	2007-05-31 12:41:58.000000000 -0600
+++ asterisk-1.4.13/include/asterisk/app.h	2007-10-15 20:28:34.000000000 -0600
@@ -96,6 +96,9 @@
  */
 int ast_app_getdata(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout);
 
+/* ast_app_getdata_use_default is the same, except it doesn't zero S if the TIMEOUT expires. */
+int ast_app_getdata_use_default(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout);
+
 /*! \brief Full version with audiofd and controlfd.  NOTE: returns '2' on ctrlfd available, not '1' like other full functions */
 int ast_app_getdata_full(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd);
 
