Index: apps/app_read.c
===================================================================
--- apps/app_read.c	(revision 85883)
+++ apps/app_read.c	(working copy)
@@ -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    -- The number of seconds to wait for a digit response. If greater\n"
@@ -127,8 +130,13 @@
 		tosec = atof(arglist.timeout);
 		if (tosec <= 0)
 			to = 0;
-		else
+		else {
 			to = tosec * 1000.0;
+			if (to <= 0) {
+				/* Make sure we don't use the default timeout. */
+				to = 1;
+			}
+		}
 	}
 
 	if (ast_strlen_zero(arglist.filename)) {
@@ -145,6 +153,17 @@
 		ast_log(LOG_WARNING, "Invalid! Usage: Read(variable[,filename][,maxdigits][,option][,attempts][,timeout])\n\n");
 		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)) {
@@ -154,7 +173,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);
 			return 0;
 		} else if (!ast_test_flag(&flags,OPT_NOANSWER)) {
 			/* Otherwise answer unless we're supposed to read while on-hook */
@@ -172,7 +191,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;
@@ -182,7 +203,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);
Index: include/asterisk/channel.h
===================================================================
--- include/asterisk/channel.h	(revision 85883)
+++ include/asterisk/channel.h	(working copy)
@@ -1041,7 +1041,7 @@
 
 /*! Reads multiple digits 
  * \param c channel to read from
- * \param s string to read in to.  Must be at least the size of your length
+ * \param s string to read in to.  Must be at least the size of your length and is first set to zero
  * \param len how many digits to read (maximum)
  * \param timeout how long to timeout between digits
  * \param rtimeout timeout to wait on the first digit
@@ -1052,6 +1052,7 @@
    a timeout, any digits that were read before the timeout will still be available in s.  
    RETURNS 2 in full version when ctrlfd is available, NOT 1*/
 int ast_readstring(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders);
+/*! \brief Full version, which does not first set s to zero */
 int ast_readstring_full(struct ast_channel *c, char *s, int len, int timeout, int rtimeout, char *enders, int audiofd, int ctrlfd);
 
 /*! \brief Report DTMF on channel 0 */
Index: include/asterisk/app.h
===================================================================
--- include/asterisk/app.h	(revision 85883)
+++ include/asterisk/app.h	(working copy)
@@ -87,7 +87,7 @@
  * \param prompt File to pass to ast_streamfile (the one that you wish to play).
  *        It is also valid for this to be multiple files concatenated by "&".
  *        For example, "file1&file2&file3".
- * \param s The location where the DTMF data will be stored
+ * \param s The location where the DTMF data will be stored, and is first set to NUL
  * \param maxlen Max Length of the data
  * \param timeout Timeout length waiting for data(in milliseconds).  Set to 0 for standard timeout(six seconds), or -1 for no time out.
  *
@@ -98,6 +98,9 @@
  */
 int ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout);
 
+/*! \brief 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);
 
Index: main/channel.c
===================================================================
--- main/channel.c	(revision 85883)
+++ main/channel.c	(working copy)
@@ -3257,7 +3257,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)
@@ -3284,7 +3288,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) {
Index: main/app.c
===================================================================
--- main/app.c	(revision 85883)
+++ main/app.c	(working copy)
@@ -112,19 +112,32 @@
  * \brief ast_app_getdata
  * \param c The channel to read from
  * \param prompt The file to stream to the channel
- * \param s The string to read in to.  Must be at least the size of your length
+ * \param s The string to read in to.  Must be at least the size of your length, and is first set to NUL
  * \param maxlen How many digits to read (maximum)
  * \param timeout set timeout to 0 for "standard" timeouts. Set timeout to -1 for 
  *      "ludicrous time" (essentially never times out) */
 int ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
 {
+	if (maxlen)
+		s[0] = '\0';
+
+	return ast_app_getdata_use_default(c, prompt, s, maxlen, timeout);
+}
+
+/*!
+ * \brief ast_app_getdata_use_default
+ * \param c The channel to read from
+ * \param prompt The file to stream to the channel
+ * \param s The string to read in to.  Must be at least the size of your length, and is unchanged on timeout
+ * \param maxlen How many digits to read (maximum)
+ * \param timeout set timeout to 0 for "standard" timeouts. Set timeout to -1 for 
+ *      "ludicrous time" (essentially never times out) */
+int ast_app_getdata_use_default(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
+{
 	int res = 0, to, fto;
 	char *front, *filename;
 
 	/* XXX Merge with full version? XXX */
-	
-	if (maxlen)
-		s[0] = '\0';
 
 	if (!prompt)
 		prompt="";
@@ -152,7 +165,7 @@
 			fto = 50;
 			to = c->pbx ? c->pbx->dtimeout * 1000 : 2000;
 		}
-		res = ast_readstring(c, s, maxlen, to, fto, "#");
+		res = ast_readstring_full(c, s, maxlen, to, fto, "#", -1, -1);
 		if (!ast_strlen_zero(s))
 			return res;
 	}
@@ -179,6 +192,9 @@
 		fto = to = 1000000000;
 
 	res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
+	if (res == 1 && maxlen > 0) {
+		s[0] = '\0';
+	}
 
 	return res;
 }
