diff -durpN postgresql.1/doc/src/sgml/ref/pg_basebackup.sgml postgresql.2/doc/src/sgml/ref/pg_basebackup.sgml
--- postgresql.1/doc/src/sgml/ref/pg_basebackup.sgml	2012-08-24 09:49:22.960530329 +0200
+++ postgresql.2/doc/src/sgml/ref/pg_basebackup.sgml	2012-10-14 13:09:58.913513268 +0200
@@ -189,6 +189,37 @@ PostgreSQL documentation
      </varlistentry>
 
      <varlistentry>
+      <term><option>-R</option></term>
+      <term><option>--write-recovery-conf</option></term>
+      <listitem>
+
+       <para>
+        Write a minimal recovery.conf into the output directory (or into
+        the base archive file if <option>--format=tar</option> was specified)
+        using the connection parameters from the command line to ease
+        setting up the standby. Since creating a backup for a standalone
+        server with <option>-x</option> or <option>-X</option> and adding
+        a recovery.conf to it wouldn't make a working standby, these options
+        naturally conflict.
+       </para>
+
+       <para>
+        The password written into recovery.conf is not escaped even if special
+        characters appear in it. The administrator must review recovery.conf
+        to ensure proper escaping.
+       </para>
+
+       <para>
+        When this option is specified and taking the base backup succeeded,
+        failing to write the <filename>recovery.conf</filename> results
+        in the error code 2. This way, scripts can distinguish between different
+        failure cases of <application>pg_basebackup</application>.
+       </para>
+
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
       <term><option>-x</option></term>
       <term><option>--xlog</option></term>
       <listitem>
diff -durpN postgresql.1/src/bin/pg_basebackup/pg_basebackup.c postgresql.2/src/bin/pg_basebackup/pg_basebackup.c
--- postgresql.1/src/bin/pg_basebackup/pg_basebackup.c	2012-10-03 10:40:48.297207389 +0200
+++ postgresql.2/src/bin/pg_basebackup/pg_basebackup.c	2012-10-14 13:07:10.303472940 +0200
@@ -25,6 +25,7 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <time.h>
 
 #ifdef HAVE_LIBZ
 #include <zlib.h>
@@ -46,6 +47,7 @@ int			compresslevel = 0;
 bool		includewal = false;
 bool		streamwal = false;
 bool		fastcheckpoint = false;
+bool		writerecoveryconf = false;
 int			standby_message_timeout = 10 * 1000;		/* 10 sec = default */
 
 /* Progress counters */
@@ -70,6 +72,10 @@ static int	has_xlogendptr = 0;
 static volatile LONG has_xlogendptr = 0;
 #endif
 
+#define RCBUFSZ	(1024)
+static size_t	recoveryconf_length = 0;
+static char	   *recoveryconf = NULL;
+
 /* Function headers */
 static void usage(void);
 static void verify_dir_is_empty_or_create(char *dirname);
@@ -77,6 +83,13 @@ static void progress_report(int tablespa
 
 static void ReceiveTarFile(PGconn *conn, PGresult *res, int rownum);
 static void ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum);
+static void _reallocRCBuffer(char **buf, int *bufsz, int currsz,
+					PQconninfoOption *option, int extrasz);
+static void CreateRecoveryConf(PGconn *conn);
+static void WriteRecoveryConf(void);
+static int  _tarChecksum(char *header);
+static void print_val(char *s, uint64 val, unsigned int base, size_t len);
+static void _tarCreateHeader(char *header);
 static void BaseBackup(void);
 
 static bool reached_end_position(XLogRecPtr segendpos, uint32 timeline,
@@ -107,6 +120,8 @@ usage(void)
 	printf(_("\nOptions controlling the output:\n"));
 	printf(_("  -D, --pgdata=DIRECTORY receive base backup into directory\n"));
 	printf(_("  -F, --format=p|t       output format (plain (default), tar)\n"));
+	printf(_("  -R, --write-recovery-conf\n"
+			 "                         write recovery.conf after backup\n"));
 	printf(_("  -x, --xlog             include required WAL files in backup (fetch mode)\n"));
 	printf(_("  -X, --xlog-method=fetch|stream\n"
 			 "                         include required WAL files with specified method\n"));
@@ -598,13 +613,66 @@ ReceiveTarFile(PGconn *conn, PGresult *r
 		if (r == -1)
 		{
 			/*
-			 * End of chunk. Close file (but not stdout).
+			 * End of chunk. Write recovery.conf into the tar file (if it
+			 * was requested) and close file (but not stdout).
 			 *
 			 * Also, write two completely empty blocks at the end of the tar
 			 * file, as required by some tar programs.
 			 */
 			char		zerobuf[1024];
 
+			if (rownum == 0 && writerecoveryconf)
+			{
+				char		header[512];
+				
+				_tarCreateHeader(header);
+#ifdef HAVE_LIBZ
+				if (ztarfile != NULL)
+				{
+					if (gzwrite(ztarfile, header, sizeof(header)) !=
+						sizeof(header))
+					{
+						fprintf(stderr,
+						_("%s: could not write to compressed file \"%s\": %s\n"),
+								progname, filename, get_gz_error(ztarfile));
+						disconnect_and_exit(1);
+					}
+
+					if (gzwrite(ztarfile, recoveryconf, recoveryconf_length) != 
+						recoveryconf_length)
+					{
+						fprintf(stderr,
+						_("%s: could not write to compressed file \"%s\": %s\n"),
+								progname, filename, get_gz_error(ztarfile));
+						disconnect_and_exit(1);
+					}
+				}
+				else
+#endif
+				{
+					if (fwrite(header, sizeof(header), 1, tarfile) != 1)
+					{
+						fprintf(stderr,
+								_("%s: could not write to file \"%s\": %s\n"),
+								progname, filename, strerror(errno));
+								disconnect_and_exit(1);
+					}
+
+					if (fwrite(recoveryconf, recoveryconf_length, 1, tarfile) != 1)
+					{
+						fprintf(stderr,
+								_("%s: could not write to file \"%s\": %s\n"),
+								progname, filename, strerror(errno));
+								disconnect_and_exit(1);
+					}
+				}
+				fprintf(stderr, _("%s: recovery.conf written in to the base backup. "
+						"Please, add escaping to the password field in "
+						"\"primary_conninfo\" if needed.\n"), progname);
+
+				free(recoveryconf);
+			}
+
 			MemSet(zerobuf, 0, sizeof(zerobuf));
 #ifdef HAVE_LIBZ
 			if (ztarfile != NULL)
@@ -937,6 +1005,264 @@ ReceiveAndUnpackTarFile(PGconn *conn, PG
 
 	if (copybuf != NULL)
 		PQfreemem(copybuf);
+
+	if (rownum == 0)
+		WriteRecoveryConf();
+}
+
+static int
+_tarChecksum(char *header)
+{
+	int			i,
+				sum;
+
+	/*
+	 * Per POSIX, the checksum is the simple sum of all bytes in the header,
+	 * treating the bytes as unsigned, and treating the checksum field (at
+	 * offset 148) as though it contained 8 spaces.
+	 */
+	sum = 8 * ' ';				/* presumed value for checksum field */
+	for (i = 0; i < 512; i++)
+		if (i < 148 || i >= 156)
+			sum += 0xFF & header[i];
+	return sum;
+}
+
+
+/*
+ * Utility routine to print possibly larger than 32 bit integers in a
+ * portable fashion.  Filled with zeros.
+ */
+static void
+print_val(char *s, uint64 val, unsigned int base, size_t len)
+{
+	int			i;
+
+	for (i = len; i > 0; i--)
+	{
+		int			digit = val % base;
+
+		s[i - 1] = '0' + digit;
+		val = val / base;
+	}
+}
+
+
+static void
+_tarCreateHeader(char *header)
+{
+	/*
+	 * Note: most of the fields in a tar header are not supposed to be
+	 * null-terminated.  We use sprintf, which will write a null after the
+	 * required bytes; that null goes into the first byte of the next field.
+	 * This is okay as long as we fill the fields in order.
+	 */
+	memset(header, 0, 512 /* sizeof the tar header */);
+
+	/* Name 100 */
+	sprintf(&header[0], "%.99s", "recovery.conf");
+
+	/* Mode 8 */
+	sprintf(&header[100], "0000600 ");
+
+	/* User ID 8 */
+	sprintf(&header[108], "0004000 ");
+
+	/* Group 8 */
+	sprintf(&header[116], "0002000 ");
+
+	/* File size 12 - 11 digits, 1 space; use print_val for 64 bit support */
+	print_val(&header[124], recoveryconf_length, 8, 11);
+	sprintf(&header[135], " ");
+
+	/* Mod Time 12 */
+	sprintf(&header[136], "%011o ", (int) time(NULL));
+
+	/* Checksum 8 cannot be calculated until we've filled all other fields */
+
+	/* Type - regular file */
+	sprintf(&header[156], "0");
+
+	/* Link Name 100 (leave as nulls) */
+
+	/* Magic 6 */
+	sprintf(&header[257], "ustar");
+
+	/* Version 2 */
+	sprintf(&header[263], "00");
+
+	/* User 32 */
+	/* XXX: Do we need to care about setting correct username? */
+	sprintf(&header[265], "%.31s", "postgres");
+
+	/* Group 32 */
+	/* XXX: Do we need to care about setting correct group name? */
+	sprintf(&header[297], "%.31s", "postgres");
+
+	/* Major Dev 8 */
+	sprintf(&header[329], "%07o ", 0);
+
+	/* Minor Dev 8 */
+	sprintf(&header[337], "%07o ", 0);
+
+	/* Prefix 155 - not used, leave as nulls */
+
+	/*
+	 * We mustn't overwrite the next field while inserting the checksum.
+	 * Fortunately, the checksum can't exceed 6 octal digits, so we just write
+	 * 6 digits, a space, and a null, which is legal per POSIX.
+	 */
+	sprintf(&header[148], "%06o ", _tarChecksum(header));
+}
+
+/*
+ * Reallocate the buffer for recovery.conf if needed
+ */
+static void
+_reallocRCBuffer(char **buf, int *bufsz, int currsz, PQconninfoOption *option, int extrasz)
+{
+	int	kw_val_len;
+
+	if (option != NULL)
+		kw_val_len = strlen(option->keyword) + strlen(option->val);
+	else
+		kw_val_len = 0;
+
+	if (*bufsz < currsz + kw_val_len + extrasz)
+	{
+		char	   *tmp;
+
+		tmp = realloc(*buf, *bufsz + RCBUFSZ);
+		if (tmp == NULL)
+		{
+			fprintf(stderr, _("%s: out of memory"), progname);
+			disconnect_and_exit(1)
+		}
+		*buf = tmp;
+		*bufsz += RCBUFSZ;
+	}
+}
+
+/*
+ * Try to create recovery.conf in memory and set the length to write later.
+ */
+static void
+CreateRecoveryConf(PGconn *conn)
+{
+	char		   *buf = NULL;
+	PQconninfoOption   *connOptions;
+	PQconninfoOption   *option;
+	int		bufsz;
+	int		total = 0;
+	int		written;
+
+	if (!writerecoveryconf)
+		return;
+
+	connOptions = PQconninfo(conn, true);
+	if (connOptions == NULL)
+	{
+		fprintf(stderr, _("%s: out of memory"), progname);
+		disconnect_and_exit(1);
+	}
+
+
+	bufsz = RCBUFSZ;
+	buf = malloc(bufsz);
+	if (buf == NULL)
+	{
+		fprintf(stderr, _("%s: out of memory"), progname);
+		disconnect_and_exit(1);
+	}
+
+	written = sprintf(&buf[total], "standby_mode = 'on'\n");
+	if (written < 0)
+	{
+		fprintf(stderr, _("%s: cannot write to string: %s"), progname, strerror(errno));
+		disconnect_and_exit(1);
+	}
+	total += written;
+
+	written = sprintf(&buf[total], "primary_conninfo = '");
+	if (written < 0)
+	{
+		fprintf(stderr, _("%s: cannot write to string: %s"), progname, strerror(errno));
+		disconnect_and_exit(1);
+	}
+	total += written;
+
+	for (option = connOptions; option && option->keyword; option++)
+	{
+		/*
+		 * Do not emit this setting if not set, empty or default.
+		 * The list of options was already pre-filtered for options
+		 * usable for replication with PQconninfo(conn, true).
+		 */
+		if (option->val == NULL ||
+				(option->val != NULL && option->val[0] == '\0') ||
+				(option->val &&
+					option->compiled &&
+					strcmp(option->val, option->compiled) == 0))
+			continue;
+
+		/* Write "keyword='value'" pieces, single quotes doubled */
+		_reallocRCBuffer(&buf, &bufsz, total, option, 6);
+		written = sprintf(&buf[total], "%s=''%s'' ", option->keyword, option->val);
+		if (written < 0)
+		{
+			fprintf(stderr, _("%s: cannot write to string: %s"), progname, strerror(errno));
+			disconnect_and_exit(1);
+		}
+		total += written;
+	}
+
+	_reallocRCBuffer(&buf, &bufsz, total, NULL, 2);
+	written = sprintf(&buf[total], "'\n");
+	if (written < 0)
+	{
+		fprintf(stderr, _("%s: cannot write to string: %s"), progname, strerror(errno));
+		disconnect_and_exit(1);
+	}
+	total += written;
+
+	recoveryconf = buf;
+	recoveryconf_length = total;
+
+	PQconninfoFree(connOptions);
+}
+
+
+static void
+WriteRecoveryConf(void)
+{
+	char		filename[MAXPGPATH];
+	FILE	   *cf;
+
+	if (!writerecoveryconf)
+		return;
+
+	sprintf(filename, "%s/recovery.conf", basedir);
+
+	cf = fopen(filename, "w");
+	if (cf == NULL)
+	{
+		fprintf(stderr, _("%s: cannot create %s: %s"), progname, filename, strerror(errno));
+		disconnect_and_exit(1);
+	}
+
+	if (fwrite(recoveryconf, recoveryconf_length, 1, cf) != 1)
+	{
+		fprintf(stderr,
+				_("%s: could not write to file \"%s\": %s\n"),
+				progname, filename, strerror(errno));
+		disconnect_and_exit(1);
+	}
+
+	fclose(cf);
+
+	fprintf(stderr, _("%s: recovery.conf written. "
+			"Please, add escaping to the password field in "
+			"\"primary_conninfo\" if needed.\n"), progname);
 }
 
 
@@ -960,6 +1286,8 @@ BaseBackup(void)
 		/* Error message already written in GetConnection() */
 		exit(1);
 
+	CreateRecoveryConf(conn);
+
 	/*
 	 * Run IDENTIFY_SYSTEM so we can get the timeline
 	 */
@@ -1243,6 +1571,7 @@ main(int argc, char **argv)
 		{"pgdata", required_argument, NULL, 'D'},
 		{"format", required_argument, NULL, 'F'},
 		{"checkpoint", required_argument, NULL, 'c'},
+		{"write-recovery-conf", no_argument, NULL, 'R'},
 		{"xlog", no_argument, NULL, 'x'},
 		{"xlog-method", required_argument, NULL, 'X'},
 		{"gzip", no_argument, NULL, 'z'},
@@ -1280,7 +1609,7 @@ main(int argc, char **argv)
 		}
 	}
 
-	while ((c = getopt_long(argc, argv, "D:F:xX:l:zZ:c:h:p:U:s:wWvP",
+	while ((c = getopt_long(argc, argv, "D:F:RxX:l:zZ:c:h:p:U:s:wWvP",
 							long_options, &option_index)) != -1)
 	{
 		switch (c)
@@ -1301,6 +1630,9 @@ main(int argc, char **argv)
 					exit(1);
 				}
 				break;
+			case 'R':
+				writerecoveryconf = true;
+				break;
 			case 'x':
 				if (includewal)
 				{
@@ -1466,6 +1798,13 @@ main(int argc, char **argv)
 	}
 #endif
 
+	if (writerecoveryconf && includewal)
+	{
+		fprintf(stderr,
+				_("--xlog and --writerecoveryconf are mutually exclusive\n"));
+		exit(1);
+	}
+
 	/*
 	 * Verify that the target directory exists, or create it. For plaintext
 	 * backups, always require the directory. For tar backups, require it
