ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/external/subpack/libs/postgresql/Makefile b/external/subpack/libs/postgresql/Makefile
new file mode 100644
index 0000000..f0cd1b2
--- /dev/null
+++ b/external/subpack/libs/postgresql/Makefile
@@ -0,0 +1,257 @@
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=postgresql
+PKG_VERSION:=15.6
+PKG_RELEASE:=1
+PKG_MAINTAINER:=Daniel Golle <daniel@makrotopia.org>
+PKG_LICENSE:=PostgreSQL
+PKG_CPE_ID:=cpe:/a:postgresql:postgresql
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
+PKG_SOURCE_URL:=\
+	https://ftp.postgresql.org/pub/source/v$(PKG_VERSION) \
+	http://ftp.postgresql.org/pub/source/v$(PKG_VERSION) \
+	ftp://ftp.postgresql.org/pub/source/v$(PKG_VERSION)
+
+PKG_HASH:=8455146ed9c69c93a57de954aead0302cafad035c2b242175d6aa1e17ebcb2fb
+
+PKG_BUILD_FLAGS:=no-mips16
+PKG_FIXUP:=autoreconf
+PKG_MACRO_PATHS:=config
+PKG_BUILD_DEPENDS:=postgresql/host
+PKG_INSTALL:=1
+
+include $(INCLUDE_DIR)/host-build.mk
+include $(INCLUDE_DIR)/package.mk
+
+define Package/libpq
+  SECTION:=libs
+  CATEGORY:=Libraries
+  DEPENDS:=+libpthread
+  TITLE:=PostgreSQL client library
+  URL:=http://www.postgresql.org/
+  SUBMENU:=Database
+endef
+
+define Package/libpq/description
+PostgreSQL client library.
+endef
+
+define Package/pgsql-cli
+  SECTION:=utils
+  CATEGORY:=Utilities
+  DEPENDS:=+libncursesw +libpq +libreadline +librt +zlib
+  TITLE:=Command Line Interface (CLI) to PostgreSQL databases
+  URL:=http://www.postgresql.org/
+  SUBMENU:=Database
+endef
+
+define Package/pgsql-cli/description
+Command Line Interface (CLI) to PostgreSQL databases.
+endef
+
+define Package/pgsql-cli-extra
+  SECTION:=utils
+  CATEGORY:=Utilities
+  DEPENDS:=+libncursesw +libpq +libreadline +librt +zlib
+  TITLE:=Command Line extras for PostgreSQL databases
+  URL:=http://www.postgresql.org/
+  SUBMENU:=Database
+endef
+
+define Package/pgsql-cli-extra/description
+Command Line extras for PostgreSQL databases.
+endef
+
+define Package/pgsql-server
+  SECTION:=utils
+  CATEGORY:=Utilities
+  DEPENDS:=+pgsql-cli +blockd
+  TITLE:=PostgreSQL databases Server
+  URL:=http://www.postgresql.org/
+  SUBMENU:=Database
+  USERID:=postgres=5432:postgres=5432
+endef
+
+define Package/pgsql-server/description
+PostgreSQL databases Server.
+endef
+
+PGSQL_SERVER_BIN := \
+	pg_amcheck \
+	pg_archivecleanup \
+	pg_basebackup \
+	pg_checksums \
+	pg_controldata \
+	pg_ctl \
+	pg_dump \
+	pg_dumpall \
+	pg_isready \
+	pg_recvlogical \
+	pg_receivewal \
+	pg_resetwal \
+	pg_restore \
+	pg_rewind \
+	pg_upgrade \
+	pg_verifybackup \
+	pg_waldump \
+	postgres \
+	initdb
+
+PGSQL_CLI_EXTRA_BIN := \
+	clusterdb	\
+	createdb	\
+	createuser	\
+	dropdb		\
+	dropuser	\
+	oid2name	\
+	pgbench		\
+	reindexdb	\
+	vacuumdb	\
+	vacuumlo
+
+PGSQL_CONFIG_VARS:= \
+	pgac_cv_snprintf_long_long_int_format="%lld" \
+	pgac_cv_snprintf_size_t_support=yes \
+	USE_DEV_URANDOM=1 \
+	ac_cv_file__dev_urandom="/dev/urandom" \
+	ZIC=zic
+
+ifeq ($(CONFIG_USE_UCLIBC),y)
+# PostgreSQL does not build against uClibc with locales
+# enabled, due to an uClibc bug, see
+# http://lists.uclibc.org/pipermail/uclibc/2014-April/048326.html
+# so overwrite automatic detection and disable locale support
+PGSQL_CONFIG_VARS+= \
+		pgac_cv_type_locale_t=no
+endif
+
+TARGET_CONFIGURE_OPTS+=$(PGSQL_CONFIG_VARS)
+
+HOST_CONFIGURE_ARGS += \
+			--disable-nls \
+			--disable-rpath \
+			--without-bonjour \
+			--without-gssapi \
+			--without-ldap \
+			--without-openssl \
+			--without-pam \
+			--without-perl \
+			--without-python \
+			--without-readline \
+			--without-tcl \
+			--without-systemd \
+			--with-zlib="yes" \
+			--enable-depend
+
+CONFIGURE_ARGS += \
+			$(DISABLE_NLS) \
+			--disable-rpath \
+			--without-bonjour \
+			--without-gssapi \
+			--without-ldap \
+			--without-openssl \
+			--without-pam \
+			--without-perl \
+			--without-python \
+			--without-tcl \
+			--without-systemd \
+			--with-zlib="yes" \
+			--enable-depend \
+			$(if $(CONFIG_arc),--disable-spinlocks)
+
+HOST_CFLAGS += -std=gnu99
+
+# Need a native zic and pg_config for build
+define Host/Compile
+	+$(HOST_MAKE_VARS) MAKELEVEL=0 $(MAKE) -C $(HOST_BUILD_DIR)/src/bin/pg_config CC="$(HOSTCC)"
+	+$(HOST_MAKE_VARS) MAKELEVEL=0 $(MAKE) -C $(HOST_BUILD_DIR)/src/timezone CC="$(HOSTCC)"
+endef
+
+define Host/Install
+	$(INSTALL_DIR) $(STAGING_DIR_HOSTPKG)/lib/
+	$(INSTALL_BIN) $(HOST_BUILD_DIR)/src/common/libpgcommon.a $(STAGING_DIR_HOSTPKG)/lib/
+	$(INSTALL_BIN) $(HOST_BUILD_DIR)/src/port/libpgport.a $(STAGING_DIR_HOSTPKG)/lib/
+	$(INSTALL_BIN) $(HOST_BUILD_DIR)/src/bin/pg_config/pg_config $(STAGING_DIR_HOSTPKG)/lib/
+	$(INSTALL_DIR) $(STAGING_DIR_HOSTPKG)/bin/
+	$(INSTALL_BIN) $(HOST_BUILD_DIR)/src/timezone/zic $(STAGING_DIR_HOSTPKG)/bin/
+endef
+
+define Build/Compile
+	$(MAKE) -C $(PKG_BUILD_DIR) MAKELEVEL=0 all contrib
+endef
+
+# because PROFILE means something else in the project Makefile
+unexport PROFILE
+
+define Package/libpq/install
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libpq.so.* $(1)/usr/lib/
+endef
+
+define Package/pgsql-cli/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/psql $(1)/usr/bin/
+endef
+
+define Package/pgsql-cli-extra/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(foreach bin,$(PGSQL_CLI_EXTRA_BIN),$(PKG_INSTALL_DIR)/usr/bin/$(bin)) $(1)/usr/bin/
+endef
+
+define Package/pgsql-server/conffiles
+/etc/config/postgresql
+endef
+
+define Package/pgsql-server/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(foreach bin,$(PGSQL_SERVER_BIN),$(PKG_INSTALL_DIR)/usr/bin/$(bin)) $(1)/usr/bin/
+
+	ln -sf postgres $(1)/usr/bin/postmaster
+
+	$(INSTALL_DIR) $(1)/usr/share/postgresql
+	$(CP) $(PKG_INSTALL_DIR)/usr/share/postgresql/* \
+		$(1)/usr/share/postgresql
+
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/postgresql \
+		$(1)/usr/lib/
+
+	$(INSTALL_DIR) $(1)/lib/functions
+	$(INSTALL_BIN) ./files/postgresql.sh $(1)/lib/functions/
+
+	$(INSTALL_DIR) $(1)/etc/config
+	$(INSTALL_DATA) ./files/postgresql.config $(1)/etc/config/postgresql
+
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_BIN) ./files/postgresql.init $(1)/etc/init.d/postgresql
+endef
+
+define Build/InstallDev
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(CP) $(STAGING_DIR_HOSTPKG)/lib/pg_config $(1)/usr/bin
+	$(INSTALL_DIR) $(1)/host/bin/
+	$(LN) $(STAGING_DIR)/usr/bin/pg_config $(1)/host/bin
+	$(INSTALL_DIR) $(1)/usr/include
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/libpq $(1)/usr/include/
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/libpq-fe.h $(1)/usr/include/
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/pg_config.h $(1)/usr/include/
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/pg_config_manual.h $(1)/usr/include/
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/postgres_ext.h $(1)/usr/include/
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/pg_config_ext.h $(1)/usr/include/
+	$(CP) $(PKG_INSTALL_DIR)/usr/include/postgresql $(1)/usr/include/
+	$(INSTALL_DIR) $(1)/usr/lib
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/libpq.{a,so*} $(1)/usr/lib/
+	$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
+	$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libpq.pc $(1)/usr/lib/pkgconfig/
+endef
+
+$(eval $(call HostBuild))
+$(eval $(call BuildPackage,libpq))
+$(eval $(call BuildPackage,pgsql-cli))
+$(eval $(call BuildPackage,pgsql-cli-extra))
+$(eval $(call BuildPackage,pgsql-server))
diff --git a/external/subpack/libs/postgresql/files/postgresql.config b/external/subpack/libs/postgresql/files/postgresql.config
new file mode 100644
index 0000000..4760bf1
--- /dev/null
+++ b/external/subpack/libs/postgresql/files/postgresql.config
@@ -0,0 +1,2 @@
+config postgresql config
+	option PGDATA	/var/postgresql/data
diff --git a/external/subpack/libs/postgresql/files/postgresql.init b/external/subpack/libs/postgresql/files/postgresql.init
new file mode 100644
index 0000000..5761336
--- /dev/null
+++ b/external/subpack/libs/postgresql/files/postgresql.init
@@ -0,0 +1,92 @@
+#!/bin/sh /etc/rc.common
+# Copyright (C) 2006-2015 OpenWrt.org
+START=50
+
+PROG=/usr/bin/postmaster
+
+USE_PROCD=1
+
+fix_hosts() {
+	# make sure localhost (without a dot) is in /etc/hosts
+	grep -q 'localhost$' /etc/hosts || echo '127.0.0.1 localhost' >> /etc/hosts
+}
+
+fix_perms() {
+	# for whatever reason, /dev/null gets wrong perms
+	chmod a+w /dev/null
+}
+
+cleanup() {
+	if [ -f "$1/postmaster.pid" ]; then
+		rm "$1/postmaster.pid"
+	fi
+}
+
+start_service() {
+	. /lib/functions/postgresql.sh
+
+	config_load "postgresql"
+	config_get pgdata config PGDATA
+	config_get pgopts config PGOPTS
+
+	user_exists postgres 5432 || user_add postgres 5432
+	group_exists postgres 5432 || group_add postgres 5432
+
+	[ "$_BOOT" = "1" ] &&
+		[ "$(procd_get_mountpoints $pgdata)" ] && return 0
+
+	fix_perms
+	fix_hosts
+
+	if [ ! -e "${pgdata}/PG_VERSION" ]; then
+		pg_init_data ${pgdata}
+		[ $? -gt 0 ] && return 1
+	fi
+
+	cleanup "${pgdata}"
+
+	mkdir -m 0755 -p /var/run/postgresql
+	chmod 0750 /var/run/postgresql
+	chown postgres:postgres /var/run/postgresql
+	procd_open_instance postmaster
+	procd_set_param user postgres
+	procd_set_param command $PROG
+	procd_append_param command -D "${pgdata}"
+	procd_append_param command -k "/var/run/postgresql"
+	[ -n "${pgopts}" ] && procd_append_param command -o "${pgopts}"
+	procd_set_param respawn retry=60
+	procd_add_jail postgresql log
+	procd_add_jail_mount /usr/lib/postgresql /usr/share/postgresql
+	procd_add_jail_mount_rw /var/run/postgresql "${pgdata}"
+	procd_add_jail_mount_rw /dev/shm
+	procd_set_param stderr 1
+	procd_set_param stdout 1
+	procd_close_instance
+
+	procd_open_instance uci_dbinit
+	procd_set_param user postgres
+	procd_set_param command /lib/functions/postgresql.sh init "${pgdata}"
+	procd_set_param stdout 1
+	procd_set_param stderr 1
+	procd_close_instance
+}
+
+boot() {
+	_BOOT=1 start
+}
+
+service_triggers() {
+	config_load "postgresql"
+	config_get pgdata config PGDATA
+	procd_add_restart_mount_trigger "${pgdata}"
+}
+
+stop_service() {
+	procd_send_signal "postgresql" postmaster SIGTERM
+}
+
+status_service() {
+	config_load "postgresql"
+	config_get pgdata config PGDATA
+	/usr/bin/pg_ctl status -U postgres -D "${pgdata}"
+}
diff --git a/external/subpack/libs/postgresql/files/postgresql.sh b/external/subpack/libs/postgresql/files/postgresql.sh
new file mode 100644
index 0000000..e1076d5
--- /dev/null
+++ b/external/subpack/libs/postgresql/files/postgresql.sh
@@ -0,0 +1,99 @@
+#!/bin/sh
+
+PSQL="/usr/bin/psql"
+
+free_megs() {
+	fsdir=$1
+	while [ ! -d "$fsdir" ]; do
+		fsdir="$(dirname "$fsdir")"
+	done
+	df -m $fsdir | while read fs bl us av cap mnt; do [ "$av" = "Available" ] || echo $av; done
+}
+
+pg_init_data() {
+	# make sure we got at least 50MB of free space
+	[ $(free_megs "$1") -lt 50 ] && return 1
+	pg_ctl initdb -U postgres -D "$1"
+}
+
+pg_server_ready() {
+	t=0
+	while [ $t -le 90 ]; do
+		psql -h /var/run/postgresql/ -U postgres -c "\q" 1>/dev/null 2>/dev/null && return 0
+		t=$((t+1))
+		sleep 1
+	done
+	return 1
+}
+
+
+pg_test_db() {
+	echo "SELECT datname FROM pg_catalog.pg_database WHERE datname = '$1';" |
+		$PSQL -h /var/run/postgresql -w -U "postgres" -d "template1" -q |
+			grep -q "0 rows" && return 1
+
+	return 0
+}
+
+pg_include_sql() {
+	if [ "$3" ]; then
+		env PGPASSWORD="$3" $PSQL -h /var/run/postgresql -U "$2" -d "$1" -e -f "$4"
+		return $?
+	else
+		$PSQL -w -h /var/run/postgresql -U "$2" -d "$1" -e -f "$4"
+		return $?
+	fi
+}
+
+# $1: dbname, $2: username, $3: password, $4: sql populate script
+pg_require_db() {
+	local ret
+	local dbname="$1"
+	local dbuser="$2"
+	local dbpass="$3"
+	local exuser
+
+	pg_test_db $@ && return 0
+
+	shift ; shift ; shift
+
+	echo "CREATE DATABASE $dbname;" |
+		$PSQL -h /var/run/postgresql -U postgres -d template1 -e || return $?
+
+	if [ "$dbuser" ]; then
+		echo "SELECT usename FROM pg_catalog.pg_user WHERE usename = '$dbuser';" |
+			$PSQL -h /var/run/postgresql -U postgres -d template1 -e | grep -q "0 rows" &&
+			( echo -n "CREATE USER $dbuser"
+			[ "$dbpass" ] && echo -n " WITH PASSWORD '$dbpass'"
+			echo " NOCREATEDB NOSUPERUSER NOCREATEROLE NOINHERIT;" ) |
+				$PSQL -h /var/run/postgresql -U postgres -d template1 -e
+
+		echo "GRANT ALL PRIVILEGES ON DATABASE \"$dbname\" TO $dbuser;" |
+			$PSQL -h /var/run/postgresql -U postgres -d template1 -e
+	fi
+
+	while [ "$1" ]; do
+		pg_include_sql "$dbname" "$dbuser" "$dbpass" "$1"
+		ret=$?
+		[ $ret != 0 ] && break
+		shift
+	done
+
+	return $ret
+}
+
+uci_require_db() {
+	local dbname dbuser dbpass dbscript
+	config_get dbname $1 name
+	config_get dbuser $1 user
+	config_get dbpass $1 pass
+	config_get dbscript $1 script
+	pg_require_db "$dbname" "$dbuser" "$dbpass" $dbscript
+}
+
+[ "$1" = "init" ] && {
+	. /lib/functions.sh
+	pg_server_ready $2 || exit 1
+	config_load postgresql
+	config_foreach uci_require_db postgres-db
+}
diff --git a/external/subpack/libs/postgresql/patches/050-build-contrib.patch b/external/subpack/libs/postgresql/patches/050-build-contrib.patch
new file mode 100644
index 0000000..88a23f0
--- /dev/null
+++ b/external/subpack/libs/postgresql/patches/050-build-contrib.patch
@@ -0,0 +1,11 @@
+--- a/GNUmakefile.in
++++ b/GNUmakefile.in
+@@ -8,7 +8,7 @@ subdir =
+ top_builddir = .
+ include $(top_builddir)/src/Makefile.global
+ 
+-$(call recurse,all install,src config)
++$(call recurse,all install,src config contrib)
+ 
+ docs:
+ 	$(MAKE) -C doc all
diff --git a/external/subpack/libs/postgresql/patches/200-ranlib.patch b/external/subpack/libs/postgresql/patches/200-ranlib.patch
new file mode 100644
index 0000000..d4184a3
--- /dev/null
+++ b/external/subpack/libs/postgresql/patches/200-ranlib.patch
@@ -0,0 +1,10 @@
+--- a/src/port/Makefile
++++ b/src/port/Makefile
+@@ -83,6 +83,7 @@ uninstall:
+ libpgport.a: $(OBJS)
+ 	rm -f $@
+ 	$(AR) $(AROPT) $@ $^
++	$(RANLIB) libpgport.a
+ 
+ # getaddrinfo.o and getaddrinfo_shlib.o need PTHREAD_CFLAGS (but getaddrinfo_srv.o does not)
+ getaddrinfo.o: CFLAGS+=$(PTHREAD_CFLAGS)
diff --git a/external/subpack/libs/postgresql/patches/300-fix-includes.patch b/external/subpack/libs/postgresql/patches/300-fix-includes.patch
new file mode 100644
index 0000000..3611c8e
--- /dev/null
+++ b/external/subpack/libs/postgresql/patches/300-fix-includes.patch
@@ -0,0 +1,14 @@
+--- a/src/bin/pg_ctl/pg_ctl.c
++++ b/src/bin/pg_ctl/pg_ctl.c
+@@ -12,9 +12,11 @@
+ #include "postgres_fe.h"
+ 
+ #include <fcntl.h>
++#include <pwd.h>
+ #include <signal.h>
+ #include <time.h>
+ #include <sys/stat.h>
++#include <sys/types.h>
+ #include <sys/wait.h>
+ #include <unistd.h>
+ 
diff --git a/external/subpack/libs/postgresql/patches/700-no-arm-crc-march-change.patch b/external/subpack/libs/postgresql/patches/700-no-arm-crc-march-change.patch
new file mode 100644
index 0000000..33637f5
--- /dev/null
+++ b/external/subpack/libs/postgresql/patches/700-no-arm-crc-march-change.patch
@@ -0,0 +1,15 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -2239,9 +2239,9 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
+ # flags. If not, check if adding -march=armv8-a+crc flag helps.
+ # CFLAGS_ARMV8_CRC32C is set if the extra flag is required.
+ PGAC_ARMV8_CRC32C_INTRINSICS([])
+-if test x"$pgac_armv8_crc32c_intrinsics" != x"yes"; then
+-  PGAC_ARMV8_CRC32C_INTRINSICS([-march=armv8-a+crc])
+-fi
++#if test x"$pgac_armv8_crc32c_intrinsics" != x"yes"; then
++#  PGAC_ARMV8_CRC32C_INTRINSICS([-march=armv8-a+crc])
++#fi
+ AC_SUBST(CFLAGS_ARMV8_CRC32C)
+ 
+ # Select CRC-32C implementation.
diff --git a/external/subpack/libs/postgresql/patches/800-busybox-default-pager.patch b/external/subpack/libs/postgresql/patches/800-busybox-default-pager.patch
new file mode 100644
index 0000000..b1222cb
--- /dev/null
+++ b/external/subpack/libs/postgresql/patches/800-busybox-default-pager.patch
@@ -0,0 +1,14 @@
+--- a/src/include/fe_utils/print.h
++++ b/src/include/fe_utils/print.h
+@@ -19,11 +19,7 @@
+ 
+ 
+ /* This is not a particularly great place for this ... */
+-#ifndef __CYGWIN__
+-#define DEFAULT_PAGER "more"
+-#else
+ #define DEFAULT_PAGER "less"
+-#endif
+ 
+ enum printFormat
+ {
diff --git a/external/subpack/libs/postgresql/patches/900-pg_ctl-setuid.patch b/external/subpack/libs/postgresql/patches/900-pg_ctl-setuid.patch
new file mode 100644
index 0000000..64d558f
--- /dev/null
+++ b/external/subpack/libs/postgresql/patches/900-pg_ctl-setuid.patch
@@ -0,0 +1,107 @@
+--- a/src/bin/pg_ctl/pg_ctl.c
++++ b/src/bin/pg_ctl/pg_ctl.c
+@@ -96,6 +96,7 @@ static char *event_source = NULL;
+ static char *register_servicename = "PostgreSQL";	/* FIXME: + version ID? */
+ static char *register_username = NULL;
+ static char *register_password = NULL;
++static char *username = "";
+ static char *argv0 = NULL;
+ static bool allow_core_files = false;
+ static time_t start_time;
+@@ -2086,6 +2087,9 @@ do_help(void)
+ #endif
+ 	printf(_("  -s, --silent           only print errors, no informational messages\n"));
+ 	printf(_("  -t, --timeout=SECS     seconds to wait when using -w option\n"));
++#if !defined(WIN32) && !defined(__CYGWIN__)
++	printf(_("  -U, --username=NAME    user name of account PostgreSQL server is running as\n"));
++#endif
+ 	printf(_("  -V, --version          output version information, then exit\n"));
+ 	printf(_("  -w, --wait             wait until operation completes (default)\n"));
+ 	printf(_("  -W, --no-wait          do not wait until operation completes\n"));
+@@ -2298,6 +2302,7 @@ main(int argc, char **argv)
+ 		{"options", required_argument, NULL, 'o'},
+ 		{"silent", no_argument, NULL, 's'},
+ 		{"timeout", required_argument, NULL, 't'},
++		{"username", required_argument, NULL, 'U'},
+ 		{"core-files", no_argument, NULL, 'c'},
+ 		{"wait", no_argument, NULL, 'w'},
+ 		{"no-wait", no_argument, NULL, 'W'},
+@@ -2338,20 +2343,6 @@ main(int argc, char **argv)
+ 		}
+ 	}
+ 
+-	/*
+-	 * Disallow running as root, to forestall any possible security holes.
+-	 */
+-#ifndef WIN32
+-	if (geteuid() == 0)
+-	{
+-		write_stderr(_("%s: cannot be run as root\n"
+-					   "Please log in (using, e.g., \"su\") as the "
+-					   "(unprivileged) user that will\n"
+-					   "own the server process.\n"),
+-					 progname);
+-		exit(1);
+-	}
+-#endif
+ 
+ 	env_wait = getenv("PGCTLTIMEOUT");
+ 	if (env_wait != NULL)
+@@ -2437,11 +2428,15 @@ main(int argc, char **argv)
+ 					wait_seconds_arg = true;
+ 					break;
+ 				case 'U':
++#if defined(WIN32) || defined(__CYGWIN__)
+ 					if (strchr(optarg, '\\'))
+ 						register_username = pg_strdup(optarg);
+ 					else
+ 						/* Prepend .\ for local accounts */
+ 						register_username = psprintf(".\\%s", optarg);
++#else
++					username = pg_strdup(optarg);
++#endif
+ 					break;
+ 				case 'w':
+ 					do_wait = true;
+@@ -2523,6 +2518,41 @@ main(int argc, char **argv)
+ 		exit(1);
+ 	}
+ 
++	/*
++	 * Disallow running as root, to forestall any possible security holes.
++	 */
++#if !defined(WIN32) && !defined(__CYGWIN__)
++	if (geteuid() == 0)
++	{
++		struct passwd *p;
++		if (!username || !strlen(username)) {
++			fprintf(stderr,
++					_("%s: when run as root, username needs to be provided\n"),
++					progname);
++			exit(1);
++		}
++		p = getpwnam(username);
++		if (!p) {
++			fprintf(stderr,
++					_("%s: invalid username: %s\n"),
++					progname, username);
++			exit(1);
++		}
++		if (!p->pw_uid) {
++			fprintf(stderr,
++					_("%s: user needs to be non-root\n"),
++					progname);
++			exit(1);
++		}
++		if (setgid(p->pw_gid) || setuid(p->pw_uid)) {
++			fprintf(stderr,
++					_("%s: failed to set user id %d: %d (%s)\n"),
++					progname, p->pw_uid, errno, strerror(errno));
++			exit(1);
++		}
++	}
++#endif
++
+ 	/* Note we put any -D switch into the env var above */
+ 	pg_config = getenv("PGDATA");
+ 	if (pg_config)