summaryrefslogtreecommitdiffstats
path: root/pg_wrapper
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 01:48:40 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 01:48:40 +0000
commit73e1fa4347d6c81c6e64054957ab436fa358ced1 (patch)
treef1cf86462dba1a85afd6005fca0a45b7e574c23c /pg_wrapper
parentInitial commit. (diff)
downloadpostgresql-common-73e1fa4347d6c81c6e64054957ab436fa358ced1.tar.xz
postgresql-common-73e1fa4347d6c81c6e64054957ab436fa358ced1.zip
Adding upstream version 200+deb10u5.upstream/200+deb10u5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'pg_wrapper')
-rwxr-xr-xpg_wrapper295
1 files changed, 295 insertions, 0 deletions
diff --git a/pg_wrapper b/pg_wrapper
new file mode 100755
index 0000000..8445df5
--- /dev/null
+++ b/pg_wrapper
@@ -0,0 +1,295 @@
+#!/usr/bin/perl
+# Call a PostgreSQL client program with the version, cluster and default
+# database specified in ~/.postgresqlrc or
+# /etc/postgresql-common/user_clusters.
+#
+# (C) 2005-2009 Martin Pitt <mpitt@debian.org>
+# (C) 2013-2017 Christoph Berg <myon@debian.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+use warnings;
+use strict;
+use POSIX;
+use PgCommon;
+
+my ($version, $cluster);
+my $explicit_host = exists $ENV{PGHOST};
+my $explicit_port = exists $ENV{PGPORT};
+my $explicit_service = exists $ENV{PGSERVICE};
+
+# Evaluate PGCLUSTER (unless PGHOST is set as well)
+if (exists $ENV{'PGCLUSTER'} and not $explicit_host) {
+ ($version, $cluster) = split ('/', $ENV{'PGCLUSTER'}, 2);
+ error "Invalid version $version specified in PGCLUSTER" unless version_exists $version;
+ error 'No cluster specified with $PGCLUSTER' unless $cluster;
+}
+
+# Check for --cluster argument and filter it out
+for (my $i = 0; $i <= $#ARGV; ++$i) {
+ last if $ARGV[$i] eq '--';
+
+ if ($ARGV[$i] eq '--cluster') {
+ error '--cluster option needs an argument (<version>/<cluster>)' if ($i >= $#ARGV);
+
+ ($version, $cluster) = split ('/', $ARGV[$i+1], 2);
+ error "Invalid version $version specified with --cluster" unless version_exists $version;
+ error 'No cluster specified with --cluster' unless $cluster;
+
+ splice @ARGV, $i, 2;
+ last;
+ } elsif ($ARGV[$i] =~ /^--cluster=(\d+\.?\d)\/(.+)/) {
+ ($version, $cluster) = ($1, $2);
+ error "Invalid version $version specified with --cluster" unless version_exists $version;
+ error 'No cluster specified with --cluster' unless $cluster;
+
+ splice @ARGV, $i, 1;
+ last;
+ }
+ # --host or -h on command line, drop info from PGCLUSTER
+ if ($ARGV[$i] =~ /^--host\b/ || $ARGV[$i] =~ /^-\w*h\w*$/) {
+ ($version, $cluster) = (undef, undef);
+ $explicit_host = 1;
+ delete $ENV{PGCLUSTER};
+ }
+ # --port or -p on command line
+ if ($ARGV[$i] =~ /^--port\b/ || $ARGV[$i] =~ /^-\w*p\w*$/) {
+ $explicit_port = 1;
+ }
+ # "service=" in connection string
+ if ($ARGV[$i] =~ /\bservice=/) {
+ $explicit_service = 1;
+ }
+}
+
+my ($db);
+
+# if we don't have a cluster, and no specific host was given, consult postgresqlrc
+# or fall back to default port cluster (on 5432), or undef otherwise
+($version, $cluster, $db) = user_cluster_map() unless ($cluster or $explicit_host);
+
+my ($host, $port);
+
+if ($cluster) {
+ # check if we have a network cluster (N.N/the.host.name:port)
+ if ($cluster =~ /^(\S+):(\d*)$/) {
+ $host = $1;
+ $port = $2 || $PgCommon::defaultport;
+ } elsif (not cluster_exists($version, $cluster)) {
+ # a specific cluster was requested, error out because it doesn't exist
+ error "Cluster $version $cluster does not exist";
+ } else {
+ $host = get_cluster_socketdir ($version, $cluster);
+ $port = get_cluster_port($version, $cluster);
+ }
+ # set PGCLUSTER variable for information
+ $ENV{PGCLUSTER} = "$version/$cluster";
+}
+
+# setup environment
+$ENV{'PGSYSCONFDIR'} //= '/etc/postgresql-common';
+$ENV{'PGHOST'} = $host if ($host);
+$ENV{'PGPORT'} = $port if $port && !$ENV{'PGPORT'};
+$ENV{'PGDATABASE'} = $db if $db && !$ENV{'PGDATABASE'};
+
+# check under which name we were called
+my $cmdname = (split '/', $0)[-1];
+
+unless ($version or $explicit_host or $explicit_port or $explicit_service) {
+ print STDERR "Warning: No existing local cluster is suitable as a default target. Please see man pg_wrapper(1) how to specify one.\n";
+}
+
+# if we have no version yet, use the latest version. We were called as psql,
+# pg_archivecleanup, or pg_isready, always use latest version
+if (not $version or $cmdname =~ /^(psql|pg_archivecleanup|pg_isready)$/) {
+ $version = get_newest_version;
+}
+unless ($version) {
+ error 'You must install at least one postgresql-client-<version> package';
+}
+error "PostgreSQL version $version is not installed" unless -d "$PgCommon::binroot$version";
+
+my $cmd;
+if ($cmdname eq 'pg_wrapper') {
+ error "pg_wrapper called directly but no program given as argument"
+ if (@ARGV == 0);
+ $cmd = shift; # will be unshifted back below
+} else {
+ $cmd = get_program_path ($cmdname, $version);
+}
+
+# libreadline is a lot better than libedit, so prefer that
+if ($cmdname eq 'psql' and not $PgCommon::rpm) {
+ my @readlines;
+ # non-multiarch path
+ @readlines = sort(</lib/libreadline.so.?>);
+
+ unless (@readlines) {
+ # get multiarch dir for our architecture
+ if (open PS, '-|', '/usr/bin/ldd', $cmd) {
+ my $out;
+ read PS, $out, 10000;
+ close PS;
+ if ($out =~ m!/libreadline.so!) {
+ # already linked against libreadline
+ @readlines = ();
+ }
+ else
+ {
+ my ($lib_path) = $out =~ m!(/lib/.*)/libedit.so!;
+
+ @readlines = sort(<$lib_path/libreadline.so.?>);
+ }
+ }
+ }
+
+ if (@readlines) {
+ $ENV{'LD_PRELOAD'} = ($ENV{'LD_PRELOAD'} or '') . ':' . $readlines[-1];
+ }
+}
+
+error "pg_wrapper: $cmdname was not found in $PgCommon::binroot$version/bin" unless $cmd;
+unshift @ARGV, $cmd;
+exec @ARGV;
+
+__END__
+
+=head1 NAME
+
+pg_wrapper - wrapper for PostgreSQL client commands
+
+=head1 SYNOPSIS
+
+I<client-program> [B<--cluster> I<version>/I<cluster>] [...]
+
+(I<client-program>: B<psql>, B<createdb>, B<dropuser>, and all other client
+programs installed in C</usr/lib/postgresql/>I<version>C</bin>).
+
+=head1 DESCRIPTION
+
+This program is run only as a link to names which correspond to PostgreSQL
+programs in C</usr/lib/postgresql/>I<version>C</bin>. It determines the
+configured cluster and database for the user and calls the appropriate version
+of the desired program to connect to that cluster and database, supplying any
+specified options to that command.
+
+The target cluster is selected by the following means, in descending order of
+precedence:
+
+=over
+
+=item 1.
+
+explicit specification with the B<--host> option
+
+=item 2.
+
+explicit specification with the B<--cluster> option
+
+=item 3.
+
+if the B<PGHOST> environment variable is set, no further cluster selection is
+performed. The default PostgreSQL version and port number (from the command
+line, the environment variable B<PGPORT>, or default 5432) will be used.
+
+=item 4.
+
+explicit specification with the B<PGCLUSTER> environment variable
+
+=item 5.
+
+matching entry in C<~/.postgresqlrc> (see L<postgresqlrc(5)>), if that
+file exists
+
+=item 6.
+
+matching entry in C</etc/postgresql-common/user_clusters> (see
+L<user_clusters(5)>), if that file exists
+
+=item 7.
+
+If only one local cluster exists, that one will be selected.
+
+=item 8.
+
+If several local clusters exist, the one listening on the default port 5432
+will be selected.
+
+=back
+
+If none of these rules match, B<pg_wrapper> does not set any environment
+variables and the program called will likely error out with a message like
+"could not connect to server: Connection refused".
+
+For B<psql>, B<pg_archivecleanup>, and B<pg_isready>, B<pg_wrapper> will always use the binary from
+the newest PostgreSQL version installed, as these are downwards compatible.
+
+=head1 OPTIONS
+
+=over
+
+=item B<--cluster> I<version>B</>I<cluster>
+
+=item B<--cluster> I<version>B</>I<host>B<:>[I<port>]
+
+I<cluster> is either the name of a local cluster, or takes the form
+I<host>:I<port> for a remote cluster. If I<port> is left empty (i. e. you just
+specify I<host:>), it defaults to 5432.
+
+=back
+
+=head1 ENVIRONMENT
+
+=over
+
+=item B<PGCLUSTER>
+
+If C<$PGCLUSTER> is set, its value (of the form I<version>/I<cluster>)
+specifies the desired cluster, similar to the B<--cluster> option. However, if
+B<--cluster> is specified, it overrides the value of C<$PGCLUSTER>.
+
+=item B<PG_CLUSTER_CONF_ROOT>
+
+This specifies an alternative base directory for cluster configurations. This
+is usually C</etc/postgresql/>, but for testing/development purposes you can
+change this to point to e. g. your home directory, so that you can use the
+postgresql-common tools without root privileges.
+
+=item B<PGSYSCONFDIR>
+
+This is the location of PostgreSQL's and postgresql-common's global
+configuration (e. g. C<pg_service.conf>, L<user_clusters(5)>). The default is
+C</etc/postgresql-common/>.
+
+=back
+
+=head1 FILES
+
+=over
+
+=item C</etc/postgresql-common/user_clusters>
+
+stores the default cluster and database for users and groups as set by
+the administrators.
+
+=item C<$HOME/.postgresqlrc>
+
+stores defaults set by the user himself.
+
+=back
+
+=head1 SEE ALSO
+
+L<user_clusters(5)>, L<postgresqlrc(5)>
+
+=head1 AUTHOR
+
+Martin Pitt L<E<lt>mpitt@debian.orgE<gt>>