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-11-08 13:13:04.151630632 +0100
+++ postgresql.2/doc/src/sgml/ref/pg_basebackup.sgml	2013-01-02 10:46:41.642608888 +0100
@@ -189,6 +189,21 @@ 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.
+       </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	2013-01-02 09:19:03.856521815 +0100
+++ postgresql.2/src/bin/pg_basebackup/pg_basebackup.c	2013-01-02 11:29:05.353701197 +0100
@@ -13,12 +13,14 @@
 
 #include "postgres_fe.h"
 #include "libpq-fe.h"
+#include "pqexpbuffer.h"
 
 #include <unistd.h>
 #include <dirent.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <time.h>
 
 #ifdef HAVE_LIBZ
 #include <zlib.h>
@@ -40,6 +42,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 */
@@ -64,13 +67,18 @@ static int	has_xlogendptr = 0;
 static volatile LONG has_xlogendptr = 0;
 #endif
 
+PQExpBuffer rcExpBuf = NULL;
+
 /* Function headers */
 static void usage(void);
 static void verify_dir_is_empty_or_create(char *dirname);
 static void progress_report(int tablespacenum, const char *filename);
 
+static void scan_val(char *s, uint64 *val, unsigned int base, size_t len);
 static void ReceiveTarFile(PGconn *conn, PGresult *res, int rownum);
 static void ReceiveAndUnpackTarFile(PGconn *conn, PGresult *res, int rownum);
+static void CreateRecoveryConf(PGconn *conn);
+static void WriteRecoveryConf(void);
 static void BaseBackup(void);
 
 static bool reached_end_position(XLogRecPtr segendpos, uint32 timeline,
@@ -101,6 +109,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"));
@@ -446,6 +456,65 @@ progress_report(int tablespacenum, const
 
 
 /*
+ * Inverse of print_val()
+ */
+static void
+scan_val(char *s, uint64 *val, unsigned int base, size_t len)
+{
+	uint64			tmp = 0;
+	int			i;
+
+	for (i = 0; i < len; i++)
+	{
+		int		digit = s[i] - '0';
+
+		tmp = tmp * base + digit;
+	}
+
+	*val = tmp;
+}
+
+
+/*
+ * Write a piece of tar data
+ */
+static void
+writeTarData(
+#ifdef HAVE_LIBZ
+	gzFile ztarfile,
+#endif
+	FILE *tarfile, char *buf, int r, char *current_file)
+{
+#ifdef HAVE_LIBZ
+	if (ztarfile != NULL)
+	{
+		if (gzwrite(ztarfile, buf, r) != r)
+		{
+			fprintf(stderr,
+				_("%s: could not write to compressed file \"%s\": %s\n"),
+					progname, current_file, get_gz_error(ztarfile));
+			disconnect_and_exit(1);
+		}
+	}
+	else
+#endif
+	{
+		if (fwrite(buf, r, 1, tarfile) != 1)
+		{
+			fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"),
+					progname, current_file, strerror(errno));
+			disconnect_and_exit(1);
+		}
+	}
+}
+
+#ifdef HAVE_LIBZ
+#define WRITE_TAR_DATA(buf, sz)	writeTarData(ztarfile, tarfile, buf, sz, filename)
+#else
+#define WRITE_TAR_DATA(buf, sz)	writeTarData(tarfile, buf, sz, filename)
+#endif
+
+/*
  * Receive a tar format file from the connection to the server, and write
  * the data from this file directly into a tar file. If compression is
  * enabled, the data will be compressed while written to the file.
@@ -461,12 +530,17 @@ ReceiveTarFile(PGconn *conn, PGresult *r
 	char		filename[MAXPGPATH];
 	char	   *copybuf = NULL;
 	FILE	   *tarfile = NULL;
+	char		tarhdr[512];
+	bool		basetablespace = PQgetisnull(res, rownum, 0);
+	bool		in_tarhdr, skip_file;
+	size_t		tarhdrsz;
+	uint64		filesz;
 
 #ifdef HAVE_LIBZ
 	gzFile		ztarfile = NULL;
 #endif
 
-	if (PQgetisnull(res, rownum, 0))
+	if (basetablespace)
 	{
 		/*
 		 * Base tablespaces
@@ -578,6 +652,16 @@ ReceiveTarFile(PGconn *conn, PGresult *r
 		disconnect_and_exit(1);
 	}
 
+	/*
+	 * Initialize our variables for tracking
+	 * individual files inside the TAR stream.
+	 * For more detailed explanation, see below.
+	 */
+	in_tarhdr = true;
+	skip_file = false;
+	tarhdrsz = 0;
+	filesz = 0;
+
 	while (1)
 	{
 		int			r;
@@ -592,7 +676,8 @@ 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.
@@ -600,30 +685,30 @@ ReceiveTarFile(PGconn *conn, PGresult *r
 			char		zerobuf[1024];
 
 			MemSet(zerobuf, 0, sizeof(zerobuf));
-#ifdef HAVE_LIBZ
-			if (ztarfile != NULL)
-			{
-				if (gzwrite(ztarfile, zerobuf, sizeof(zerobuf)) !=
-					sizeof(zerobuf))
-				{
-					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 (basetablespace && writerecoveryconf)
 			{
-				if (fwrite(zerobuf, sizeof(zerobuf), 1, tarfile) != 1)
-				{
-					fprintf(stderr,
-							_("%s: could not write to file \"%s\": %s\n"),
-							progname, filename, strerror(errno));
-					disconnect_and_exit(1);
-				}
+				char		header[512];
+				int		padding;
+
+				tarCreateHeader(header, "recovery.conf", NULL,
+									rcExpBuf->len,
+									0600, 04000, 02000,
+									time(NULL));
+
+				padding = ((rcExpBuf->len + 511) & ~511) - rcExpBuf->len;
+
+				WRITE_TAR_DATA(header, sizeof(header));
+				WRITE_TAR_DATA(rcExpBuf->data, rcExpBuf->len);
+				if (padding)
+					WRITE_TAR_DATA(zerobuf, padding);
+
+				if (verbose)
+					fprintf(stderr, _("%s: recovery.conf written into '%s'\n"), progname, filename);
 			}
 
+			WRITE_TAR_DATA(zerobuf, sizeof(zerobuf));
+
 #ifdef HAVE_LIBZ
 			if (ztarfile != NULL)
 			{
@@ -659,25 +744,124 @@ ReceiveTarFile(PGconn *conn, PGresult *r
 			disconnect_and_exit(1);
 		}
 
-#ifdef HAVE_LIBZ
-		if (ztarfile != NULL)
+		if (!writerecoveryconf || !basetablespace)
 		{
-			if (gzwrite(ztarfile, copybuf, r) != r)
-			{
-				fprintf(stderr,
-					_("%s: could not write to compressed file \"%s\": %s\n"),
-						progname, filename, get_gz_error(ztarfile));
-				disconnect_and_exit(1);
-			}
+			/*
+			 * If --write-recovery-conf was not requested or this
+			 * is not the base tablespace, simply pass the received
+			 * data into the TAR file, either compressed or not.
+			 */
+		
+			WRITE_TAR_DATA(copybuf, r);
 		}
 		else
-#endif
 		{
-			if (fwrite(copybuf, r, 1, tarfile) != 1)
+			/*
+			 * If --write-recovery-conf was requested AND this
+			 * is the base tablespace, the TAR stream may contain
+			 * a recovery.conf file if the backup is coming from
+			 * a standby server. We have to skip this file in
+			 * the stream and add a new one constructed by
+			 * CreateRecoveryConf() at the end of the stream.
+			 *
+			 * To do this, we have to process the individual files
+			 * inside the TAR stream. The stream consists of a header
+			 * and zero or more chunks, all 512 bytes long. The stream
+			 * from the server is broken up into smaller pieces, so
+			 * we have to track the size of the files to find the next
+			 * header structure.
+			 */
+			int	rr = r; /* Save the value returned by PQgetCopyData */
+			int	pos = 0;
+
+			while (rr > 0)
 			{
-				fprintf(stderr, _("%s: could not write to file \"%s\": %s\n"),
-						progname, filename, strerror(errno));
-				disconnect_and_exit(1);
+				if (in_tarhdr)
+				{
+					/*
+					 * We're currently reading a header structure
+					 * inside the TAR stream, i.e. the file metadata.
+					 */
+					if (tarhdrsz < 512)
+					{
+						/*
+						 * Copy the header structure into tarhdr[]
+						 * in case the header is not aligned to 512 bytes
+						 * or it's not returned in whole by the last
+						 * PQgetCopyData call.
+						 */
+						int	hdrleft, bytes2copy;
+
+						hdrleft = 512 - tarhdrsz;
+						bytes2copy = (rr > hdrleft ? hdrleft : rr);
+
+						memcpy(&tarhdr[tarhdrsz], copybuf + pos, bytes2copy);
+
+						rr -= bytes2copy;
+						pos += bytes2copy;
+						tarhdrsz += bytes2copy;
+					}
+					else
+					{
+						/*
+						 * We have the whole header structure in tarhdr[],
+						 * look at the file metadata:
+						 * - the subsequent file contents have to be skipped
+						 *   if the filename is recovery.conf
+						 * - find out the size of the file padded to the next
+						 *   multiple of 512
+						 */
+						int64	padding;
+
+						skip_file = (strcmp(&tarhdr[0], "recovery.conf") == 0);
+
+						scan_val(&tarhdr[124], &filesz, 8, 11);
+
+						padding = ((filesz + 511) & ~511) - filesz;
+						filesz += padding;
+
+						/* Indicate that the subsequent data is the file content. */
+						in_tarhdr = false;
+
+						if (!skip_file)
+							WRITE_TAR_DATA(tarhdr, 512);
+					}
+				}
+				else
+				{
+					/*
+					 * We're processing a file's contents.
+					 */
+					if (filesz > 0)
+					{
+						/*
+						 * We still have data to read (and possibly write).
+						 */
+						int	bytes2write;
+
+						bytes2write = (filesz > rr ? rr : filesz);
+
+						if (!skip_file)
+							WRITE_TAR_DATA(copybuf + pos, bytes2write);
+
+						rr -= bytes2write;
+						pos += bytes2write;
+						filesz -= bytes2write;
+					}
+					else
+					{
+						/*
+						 * No more data in the current file,
+						 * the next piece of data (if any) will
+						 * be a new file header structure.
+						 * Reinitialize all our variables.
+						 */
+						in_tarhdr = true;
+						skip_file = false;
+						tarhdrsz = 0;
+						filesz = 0;
+					}
+				}
 			}
 		}
 		totaldone += r;
@@ -706,10 +890,11 @@ ReceiveAndUnpackTarFile(PGconn *conn, PG
 	char		filename[MAXPGPATH];
 	int			current_len_left;
 	int			current_padding = 0;
+	bool			basetablespace = PQgetisnull(res, rownum, 0);
 	char	   *copybuf = NULL;
 	FILE	   *file = NULL;
 
-	if (PQgetisnull(res, rownum, 0))
+	if (basetablespace)
 		strcpy(current_path, basedir);
 	else
 		strcpy(current_path, PQgetvalue(res, rownum, 1));
@@ -931,6 +1116,131 @@ ReceiveAndUnpackTarFile(PGconn *conn, PG
 
 	if (copybuf != NULL)
 		PQfreemem(copybuf);
+
+	if (basetablespace)
+		WriteRecoveryConf();
+}
+
+static char *
+escape_quotes(const char *src)
+{
+	char *result = escape_single_quotes_ascii(src);
+	if (!result)
+	{
+		fprintf(stderr, _("%s: out of memory\n"), progname);
+		exit(1);
+	}
+	return result;
+}
+
+/*
+ * Create the new recovery.conf in memory
+ */
+static void
+CreateRecoveryConf(PGconn *conn)
+{
+	PQconninfoOption   *connOptions;
+	PQconninfoOption   *option;
+
+	if (!writerecoveryconf)
+		return;
+
+	connOptions = PQconninfo(conn);
+	if (connOptions == NULL)
+	{
+		fprintf(stderr, _("%s: out of memory"), progname);
+		disconnect_and_exit(1);
+	}
+
+	appendPQExpBufferStr(rcExpBuf, "standby_mode = 'on'\n");
+	if (PQExpBufferBroken(rcExpBuf))
+	{
+		fprintf(stderr, _("%s: out of memory"), progname);
+		disconnect_and_exit(1);
+	}
+
+	appendPQExpBufferStr(rcExpBuf, "primary_conninfo = '");
+	if (PQExpBufferBroken(rcExpBuf))
+	{
+		fprintf(stderr, _("%s: out of memory"), progname);
+		disconnect_and_exit(1);
+	}
+
+	for (option = connOptions; option && option->keyword; option++)
+	{
+		char	   *escaped;
+
+		/*
+		 * Do not emit this setting if:
+		 * - the setting is "replication", "dbname" or
+		 *   "fallback_application_name", since these would be
+		 *   overridden by the libpqwalreceiver module anyway.
+		 * - not set or empty.
+		 */
+		if (strcmp(option->keyword, "replication") == 0 ||
+			strcmp(option->keyword, "dbname") == 0 ||
+			strcmp(option->keyword, "fallback_application_name") == 0 ||
+			(option->val == NULL) ||
+			(option->val != NULL && option->val[0] == '\0'))
+			continue;
+
+		/*
+		 * Write "keyword='value'" pieces, the value string is escaped
+		 * if necessary and doubled single quotes around the value string.
+		 */
+		escaped = escape_quotes(option->val);
+
+		appendPQExpBuffer(rcExpBuf, "%s=''%s'' ", option->keyword, escaped);
+		if (PQExpBufferBroken(rcExpBuf))
+		{
+			fprintf(stderr, _("%s: out of memory"), progname);
+			disconnect_and_exit(1);
+		}
+
+		free(escaped);
+	}
+
+	appendPQExpBufferStr(rcExpBuf, "'\n");
+	if (PQExpBufferBroken(rcExpBuf))
+	{
+		fprintf(stderr, _("%s: out of memory"), progname);
+		disconnect_and_exit(1);
+	}
+
+	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(rcExpBuf->data, rcExpBuf->len, 1, cf) != 1)
+	{
+		fprintf(stderr,
+				_("%s: could not write to file \"%s\": %s\n"),
+				progname, filename, strerror(errno));
+		disconnect_and_exit(1);
+	}
+
+	fclose(cf);
+
+	if (verbose)
+		fprintf(stderr, _("%s: recovery.conf written.\n"), progname);
 }
 
 
@@ -954,6 +1264,15 @@ BaseBackup(void)
 		/* Error message already written in GetConnection() */
 		exit(1);
 
+	rcExpBuf = createPQExpBuffer();
+	if (!rcExpBuf)
+	{
+		fprintf(stderr, _("%s: out of memory"), progname);
+		disconnect_and_exit(1);
+	}
+
+	CreateRecoveryConf(conn);
+
 	/*
 	 * Run IDENTIFY_SYSTEM so we can get the timeline
 	 */
@@ -1217,6 +1536,9 @@ BaseBackup(void)
 #endif
 	}
 
+	/* Free the recovery.conf contents */
+	destroyPQExpBuffer(rcExpBuf);
+
 	/*
 	 * End of copy data. Final result is already checked inside the loop.
 	 */
@@ -1237,6 +1559,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'},
@@ -1274,7 +1597,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)
@@ -1295,6 +1618,9 @@ main(int argc, char **argv)
 					exit(1);
 				}
 				break;
+			case 'R':
+				writerecoveryconf = true;
+				break;
 			case 'x':
 				if (includewal)
 				{
