psql patch: new host/port
Folks,
Please find enclosed a patch that lets you use \c to connect
(optionally) to a new host and port without exiting psql.
Cheers,
D
--
David Fetter david@fetter.org http://fetter.org/
phone: +1 415 235 3778
Remember to vote!
Attachments:
psql_host_port.difftext/plain; charset=us-asciiDownload
Index: doc/src/sgml/ref/psql-ref.sgml
===================================================================
RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/psql-ref.sgml,v
retrieving revision 1.154
diff -c -r1.154 psql-ref.sgml
*** doc/src/sgml/ref/psql-ref.sgml 4 Nov 2005 23:14:02 -0000 1.154
--- doc/src/sgml/ref/psql-ref.sgml 9 Dec 2005 09:04:35 -0000
***************
*** 693,705 ****
</varlistentry>
<varlistentry>
! <term><literal>\connect</literal> (or <literal>\c</literal>) <literal>[ <replaceable class="parameter">dbname</replaceable> [ <replaceable class="parameter">username</replaceable> ] ]</literal></term>
<listitem>
<para>
Establishes a connection to a new database and/or under a user
name. The previous connection is closed. If <replaceable
class="parameter">dbname</replaceable> is <literal>-</literal>
! the current database name is assumed.
</para>
<para>
--- 693,707 ----
</varlistentry>
<varlistentry>
! <term><literal>\connect</literal> (or <literal>\c</literal>) <literal>[ <replaceable class="parameter">dbname</replaceable> [ <replaceable class="parameter">username</replaceable> ] [ <replaceable class="parameter">host</replaceable> ] [ <replaceable class="parameter">port</replaceable> ] ]</literal></term>
<listitem>
<para>
Establishes a connection to a new database and/or under a user
name. The previous connection is closed. If <replaceable
class="parameter">dbname</replaceable> is <literal>-</literal>
! the current database name is assumed. Similar consideration
! applies to <replaceable class="parameter">host</replaceable> and
! <replaceable class="parameter">port</replaceable>.
</para>
<para>
Index: src/bin/psql/command.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.155
diff -c -r1.155 command.c
*** src/bin/psql/command.c 8 Dec 2005 21:18:22 -0000 1.155
--- src/bin/psql/command.c 9 Dec 2005 09:04:37 -0000
***************
*** 55,61 ****
PsqlScanState scan_state,
PQExpBuffer query_buf);
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
! static bool do_connect(const char *new_dbname, const char *new_user);
static bool do_shell(const char *command);
--- 55,61 ----
PsqlScanState scan_state,
PQExpBuffer query_buf);
static bool do_edit(const char *filename_arg, PQExpBuffer query_buf);
! static bool do_connect(const char *new_dbname, const char *new_user, const char *new_host, const char *new_port);
static bool do_shell(const char *command);
***************
*** 189,208 ****
}
/*----------
! * \c or \connect -- connect to new database or as different user
*
! * \c foo bar connect to db "foo" as user "bar"
! * \c foo [-] connect to db "foo" as current user
! * \c - bar connect to current db as user "bar"
* \c connect to default db as default user
*----------
*/
else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
{
char *opt1,
! *opt2;
char opt1q,
! opt2q;
/*
* Ideally we should treat the arguments as SQL identifiers. But for
--- 189,215 ----
}
/*----------
! * \c or \connect -- connect to new database or as different user,
! * and/or new host and/or port
*
! * \c foo bar [-] [-] connect to db "foo" as user "bar" on current host and port
! * \c foo [-] [-] [-] connect to db "foo" as current user on current host and port
! * \c - bar [-] [-] connect to current db as user "bar" on current host and port
! * \c - - host.domain.tld [-] connect to default db as default user on host.domain.tld on default port
! * \c - - - 5555 connect to default db as default user on default host at port 5555
* \c connect to default db as default user
*----------
*/
else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
{
char *opt1,
! *opt2,
! *opt3,
! *opt4;
char opt1q,
! opt2q,
! opt3q,
! opt4q;
/*
* Ideally we should treat the arguments as SQL identifiers. But for
***************
*** 217,236 ****
OT_SQLIDHACK, &opt1q, true);
opt2 = psql_scan_slash_option(scan_state,
OT_SQLIDHACK, &opt2q, true);
if (opt2)
/* gave username */
success = do_connect(!opt1q && (strcmp(opt1, "-") == 0 || strcmp(opt1, "") == 0) ? "" : opt1,
! !opt2q && (strcmp(opt2, "-") == 0 || strcmp(opt2, "") == 0) ? "" : opt2);
else if (opt1)
/* gave database name */
! success = do_connect(!opt1q && (strcmp(opt1, "-") == 0 || strcmp(opt1, "") == 0) ? "" : opt1, "");
else
/* connect to default db as default user */
! success = do_connect(NULL, NULL);
free(opt1);
free(opt2);
}
/* \cd */
--- 224,266 ----
OT_SQLIDHACK, &opt1q, true);
opt2 = psql_scan_slash_option(scan_state,
OT_SQLIDHACK, &opt2q, true);
+ opt3 = psql_scan_slash_option(scan_state,
+ OT_SQLIDHACK, &opt3q, true);
+ opt4 = psql_scan_slash_option(scan_state,
+ OT_SQLIDHACK, &opt4q, true);
+ if (opt4)
+ /* gave port */
+ success = do_connect(!opt1q && (strcmp(opt1, "-") == 0 || strcmp(opt1, "") == 0) ? "" : opt1,
+ !opt2q && (strcmp(opt2, "-") == 0 || strcmp(opt2, "") == 0) ? "" : opt2,
+ !opt3q && (strcmp(opt3, "-") == 0 || strcmp(opt3, "") == 0) ? "" : opt3,
+ !opt3q && (strcmp(opt3, "-") == 0 || strcmp(opt3, "") == 0) ? "" : opt3);
+ if (opt3)
+ /* gave host */
+ success = do_connect(!opt1q && (strcmp(opt1, "-") == 0 || strcmp(opt1, "") == 0) ? "" : opt1,
+ !opt2q && (strcmp(opt2, "-") == 0 || strcmp(opt2, "") == 0) ? "" : opt2,
+ !opt3q && (strcmp(opt3, "-") == 0 || strcmp(opt3, "") == 0) ? "" : opt3,
+ NULL);
if (opt2)
/* gave username */
success = do_connect(!opt1q && (strcmp(opt1, "-") == 0 || strcmp(opt1, "") == 0) ? "" : opt1,
! !opt2q && (strcmp(opt2, "-") == 0 || strcmp(opt2, "") == 0) ? "" : opt2,
! NULL,
! NULL);
else if (opt1)
/* gave database name */
! success = do_connect(!opt1q && (strcmp(opt1, "-") == 0 || strcmp(opt1, "") == 0) ? "" : opt1,
! "",
! NULL,
! NULL);
else
/* connect to default db as default user */
! success = do_connect(NULL, NULL, NULL, NULL);
free(opt1);
free(opt2);
+ free(opt3);
+ free(opt4);
}
/* \cd */
***************
*** 905,915 ****
* The old connection will be kept if the session is interactive.
*/
static bool
! do_connect(const char *new_dbname, const char *new_user)
{
PGconn *oldconn = pset.db;
const char *dbparam = NULL;
const char *userparam = NULL;
const char *pwparam = NULL;
char *password_prompt = NULL;
char *prompted_password = NULL;
--- 935,947 ----
* The old connection will be kept if the session is interactive.
*/
static bool
! do_connect(const char *new_dbname, const char *new_user, const char *new_host, const char *new_port)
{
PGconn *oldconn = pset.db;
const char *dbparam = NULL;
const char *userparam = NULL;
+ const char *hostparam = NULL;
+ const char *portparam = NULL;
const char *pwparam = NULL;
char *password_prompt = NULL;
char *prompted_password = NULL;
***************
*** 931,936 ****
--- 963,980 ----
else
userparam = new_user;
+ /* If host is "" then use the old one */
+ if (new_host && PQhost(oldconn) && strcmp(new_host, "") == 0)
+ hostparam = PQhost(oldconn);
+ else
+ hostparam = new_host;
+
+ /* If port is "" then use the old one */
+ if (new_port && PQport(oldconn) && strcmp(new_port, "") == 0)
+ portparam = PQport(oldconn);
+ else
+ portparam = new_port;
+
if (userparam == NULL)
password_prompt = strdup("Password: ");
else
***************
*** 955,961 ****
do
{
need_pass = false;
! pset.db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn),
NULL, NULL, dbparam, userparam, pwparam);
if (PQstatus(pset.db) == CONNECTION_BAD &&
--- 999,1005 ----
do
{
need_pass = false;
! pset.db = PQsetdbLogin(hostparam, portparam,
NULL, NULL, dbparam, userparam, pwparam);
if (PQstatus(pset.db) == CONNECTION_BAD &&
***************
*** 1007,1020 ****
{
if (!QUIET())
{
! if (userparam != new_user) /* no new user */
! printf(_("You are now connected to database \"%s\".\n"), dbparam);
! else if (dbparam != new_dbname) /* no new db */
! printf(_("You are now connected as new user \"%s\".\n"), new_user);
! else
! /* both new */
! printf(_("You are now connected to database \"%s\" as user \"%s\".\n"),
! PQdb(pset.db), PQuser(pset.db));
}
if (oldconn)
--- 1051,1077 ----
{
if (!QUIET())
{
! if ((hostparam == new_host) && (portparam == new_port)) /* no new host or port */
! {
! if (userparam != new_user) /* no new user */
! printf(_("You are now connected to database \"%s\".\n"), dbparam);
! else if (dbparam != new_dbname) /* no new db */
! printf(_("You are now connected as new user \"%s\".\n"), new_user);
! else
! /* both new */
! printf(_("You are now connected to database \"%s\" as user \"%s\".\n"),
! PQdb(pset.db), PQuser(pset.db));
! }
! else /* At least one of host and port are new */
! {
! printf(
! _("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port %s.\n"),
! PQdb(pset.db),
! PQuser(pset.db),
! PQhost(pset.db),
! PQport(pset.db)
! );
! }
}
if (oldconn)
Index: src/bin/psql/help.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/bin/psql/help.c,v
retrieving revision 1.106
diff -c -r1.106 help.c
*** src/bin/psql/help.c 15 Oct 2005 02:49:40 -0000 1.106
--- src/bin/psql/help.c 9 Dec 2005 09:04:37 -0000
***************
*** 172,178 ****
* in 80 columns >> "
*/
fprintf(output, _("General\n"));
! fprintf(output, _(" \\c[onnect] [DBNAME|- [USER]]\n"
" connect to new database (currently \"%s\")\n"),
PQdb(pset.db));
fprintf(output, _(" \\cd [DIR] change the current working directory\n"));
--- 172,178 ----
* in 80 columns >> "
*/
fprintf(output, _("General\n"));
! fprintf(output, _(" \\c[onnect] [DBNAME|- USER|- HOST|- PORT|-]\n"
" connect to new database (currently \"%s\")\n"),
PQdb(pset.db));
fprintf(output, _(" \\cd [DIR] change the current working directory\n"));
On Dec 9, 2005, at 18:10 , David Fetter wrote:
Please find enclosed a patch that lets you use \c to connect
(optionally) to a new host and port without exiting psql.
I'm not familiar enough with the psql code to be able to tell, but is
this secure? The pg_hba.conf on the new server is enforced, I assume?
Michael Glaesemann
grzm myrealbox com
Michael Glaesemann wrote:
I'm not familiar enough with the psql code to be able to tell, but is
this secure? The pg_hba.conf on the new server is enforced, I assume?
You don't need to be familiar with the psql code to know that it would
be pretty stupid if client programs could override the server
authentication setup.
--
Peter Eisentraut
http://developer.postgresql.org/~petere/
On Dec 12, 2005, at 20:33 , Peter Eisentraut wrote:
Michael Glaesemann wrote:
I'm not familiar enough with the psql code to be able to tell, but is
this secure? The pg_hba.conf on the new server is enforced, I assume?You don't need to be familiar with the psql code to know that it would
be pretty stupid if client programs could override the server
authentication setup.
I'm sorry if I wasn't clear. My point was I'm not familiar enough
with the code to see if this implementation is secure. I do indeed
realize that clients bypassing server authentication is a Bad Thing.
Michael Glaesemann
grzm myrealbox com
On Dec 12, 2005, at 21:32 , Andrew Dunstan wrote:
The patch is to the client only, not even to libpq, so of course no
auth
bypass is involved.
Cool. Thanks for the explanation, Andrew.
Michael Glaesemann
grzm myrealbox com
Import Notes
Reply to msg id not found: 3120.24.211.165.134.1134390776.squirrel@www.dunslane.net
Michael Glaesemann said:
On Dec 12, 2005, at 20:33 , Peter Eisentraut wrote:
Michael Glaesemann wrote:
I'm not familiar enough with the psql code to be able to tell, but is
this secure? The pg_hba.conf on the new server is enforced, I assume?You don't need to be familiar with the psql code to know that it would
be pretty stupid if client programs could override the server
authentication setup.I'm sorry if I wasn't clear. My point was I'm not familiar enough
with the code to see if this implementation is secure. I do indeed
realize that clients bypassing server authentication is a Bad Thing.
The patch is to the client only, not even to libpq, so of course no auth
bypass is involved.
cheers
andrew
On Mon, Dec 12, 2005 at 09:20:57PM +0900, Michael Glaesmann wrote:
On Dec 12, 2005, at 21:32 , Andrew Dunstan wrote:
The patch is to the client only, not even to libpq, so of course no
auth bypass is involved.Cool. Thanks for the explanation, Andrew.
Is the patch suitable for a re-send to -patches?
Cheers,
D
--
David Fetter david@fetter.org http://fetter.org/
phone: +1 415 235 3778
Remember to vote!
Michael Glaesemann <grzm@myrealbox.com> writes:
On Dec 9, 2005, at 18:10 , David Fetter wrote:
Please find enclosed a patch that lets you use \c to connect
(optionally) to a new host and port without exiting psql.
I'm not familiar enough with the psql code to be able to tell, but is
this secure? The pg_hba.conf on the new server is enforced, I assume?
No, security is the server's problem.
What's not clear to me about this patch is what's the point. It's
certainly not a feature we've heard any requests for.
regards, tom lane
On Mon, Dec 12, 2005 at 10:19:00AM -0500, Tom Lane wrote:
Michael Glaesemann <grzm@myrealbox.com> writes:
On Dec 9, 2005, at 18:10 , David Fetter wrote:
Please find enclosed a patch that lets you use \c to connect
(optionally) to a new host and port without exiting psql.I'm not familiar enough with the psql code to be able to tell, but
is this secure? The pg_hba.conf on the new server is enforced, I
assume?No, security is the server's problem.
What's not clear to me about this patch is what's the point. It's
certainly not a feature we've heard any requests for.
Informally, I've heard some carping about how you can change DBs on
one server, but you have to exit the program if you want to change
servers. The change is low-impact because \c continues to work
exactly as before when supplied with < 3 arguments :)
Cheers,
D
--
David Fetter david@fetter.org http://fetter.org/
phone: +1 415 235 3778
Remember to vote!