From 2150c2edf184f4e1a136b235e36b96c1e7fdfd60 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Mon, 13 Nov 2000 15:18:15 +0000 Subject: [PATCH] UUNET is looking into offering PostgreSQL as a part of a managed web hosting product, on both shared and dedicated machines. We currently offer Oracle and MySQL, and it would be a nice middle-ground. However, as shipped, PostgreSQL lacks the following features we need that MySQL has: 1. The ability to listen only on a particular IP address. Each hosting customer has their own IP address, on which all of their servers (http, ftp, real media, etc.) run. 2. The ability to place the Unix-domain socket in a mode 700 directory. This allows us to automatically create an empty database, with an empty DBA password, for new or upgrading customers without having to interactively set a DBA password and communicate it to (or from) the customer. This in turn cuts down our install and upgrade times. 3. The ability to connect to the Unix-domain socket from within a change-rooted environment. We run CGI programs chrooted to the user's home directory, which is another reason why we need to be able to specify where the Unix-domain socket is, instead of /tmp. 4. The ability to, if run as root, open a pid file in /var/run as root, and then setuid to the desired user. (mysqld -u can almost do this; I had to patch it, too). The patch below fixes problem 1-3. I plan to address #4, also, but haven't done so yet. These diffs are big enough that they should give the PG development team something to think about in the meantime :-) Also, I'm about to leave for 2 weeks' vacation, so I thought I'd get out what I have, which works (for the problems it tackles), now. With these changes, we can set up and run PostgreSQL with scripts the same way we can with apache or proftpd or mysql. In summary, this patch makes the following enhancements: 1. Adds an environment variable PGUNIXSOCKET, analogous to MYSQL_UNIX_PORT, and command line options -k --unix-socket to the relevant programs. 2. Adds a -h option to postmaster to set the hostname or IP address to listen on instead of the default INADDR_ANY. 3. Extends some library interfaces to support the above. 4. Fixes a few memory leaks in PQconnectdb(). The default behavior is unchanged from stock 7.0.2; if you don't use any of these new features, they don't change the operation. David J. MacKenzie --- doc/src/sgml/environ.sgml | 23 +++---- doc/src/sgml/libpq++.sgml | 9 ++- doc/src/sgml/libpq.sgml | 28 +++++++- doc/src/sgml/ref/createdb.sgml | 14 +++- doc/src/sgml/ref/createlang.sgml | 14 +++- doc/src/sgml/ref/createuser.sgml | 14 +++- doc/src/sgml/ref/dropdb.sgml | 14 +++- doc/src/sgml/ref/droplang.sgml | 14 +++- doc/src/sgml/ref/dropuser.sgml | 14 +++- doc/src/sgml/ref/pg_dump.sgml | 21 +++++- doc/src/sgml/ref/pg_dumpall.sgml | 19 +++++- doc/src/sgml/ref/postmaster.sgml | 65 ++++++++++++++++++- doc/src/sgml/ref/psql-ref.sgml | 15 ++++- doc/src/sgml/ref/vacuumdb.sgml | 14 +++- doc/src/sgml/start.sgml | 6 +- src/backend/libpq/pqcomm.c | 32 ++++++++-- src/backend/postmaster/postmaster.c | 95 ++++++++++++++++++++++++--- src/backend/utils/misc/guc.c | 8 ++- src/bin/pg_dump/pg_backup.h | 4 +- src/bin/pg_dump/pg_backup_archiver.c | 5 +- src/bin/pg_dump/pg_backup_archiver.h | 1 + src/bin/pg_dump/pg_backup_db.c | 12 +++- src/bin/pg_dump/pg_dump.c | 13 +++- src/bin/pg_dump/pg_restore.c | 9 ++- src/bin/psql/command.c | 5 +- src/bin/psql/common.c | 4 +- src/bin/psql/help.c | 12 +++- src/bin/psql/prompt.c | 7 +- src/bin/psql/startup.c | 13 +++- src/bin/scripts/createdb | 12 +++- src/bin/scripts/createlang.sh | 12 +++- src/bin/scripts/createuser | 12 +++- src/bin/scripts/dropdb | 12 +++- src/bin/scripts/droplang | 12 +++- src/bin/scripts/dropuser | 12 +++- src/bin/scripts/vacuumdb | 12 +++- src/include/libpq/libpq.h | 5 +- src/include/libpq/pqcomm.h | 17 +++-- src/interfaces/libpq/fe-connect.c | 96 +++++++++++++++++++++++++--- src/interfaces/libpq/libpq-fe.h | 3 +- src/interfaces/libpq/libpq-int.h | 4 +- src/interfaces/libpq/libpqdll.def | 1 + 42 files changed, 627 insertions(+), 87 deletions(-) diff --git a/doc/src/sgml/environ.sgml b/doc/src/sgml/environ.sgml index dc5741a95d..830502a696 100644 --- a/doc/src/sgml/environ.sgml +++ b/doc/src/sgml/environ.sgml @@ -47,16 +47,17 @@ $ export PATH -If your site administrator has not set things up in the -default way, you may have some more work to do. For example, if the database - server machine is a remote machine, you -will need to set the PGHOST environment variable to the name -of the database server machine. The environment variable -PGPORT may also have to be set. The bottom line is this: if -you try to start an application program and it complains -that it cannot connect to the postmaster, - you should immediately consult your site administrator to make sure that your -environment is properly set up. - + +If your site administrator has not set things up in the default way, +you may have some more work to do. For example, if the database server +machine is a remote machine, you will need to set the +PGHOST environment variable to the name of the +database server machine. The environment variable +PGPORT or PGUNIXSOCKET may also have +to be set. The bottom line is this: if you try to start an application +program and it complains that it cannot connect to the +postmaster, you should immediately consult +your site administrator to make sure that your environment is properly +set up. diff --git a/doc/src/sgml/libpq++.sgml b/doc/src/sgml/libpq++.sgml index 44f7f97dcd..a3b045e219 100644 --- a/doc/src/sgml/libpq++.sgml +++ b/doc/src/sgml/libpq++.sgml @@ -1,5 +1,5 @@ @@ -91,6 +91,13 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/libpq++.sgml,v 1.17 2000/09/29 20:21: backend. + + + PGUNIXSOCKET sets the full Unix domain socket + file name for communicating with the Postgres + backend. + + PGDATABASE sets the default diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index a23ef89546..d9b96b8620 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1,5 +1,5 @@ @@ -133,6 +133,15 @@ PGconn *PQconnectdb(const char *conninfo) + + unixsocket + + + Full path to Unix-domain socket file to connect to at the server host. + + + + dbname @@ -554,6 +563,16 @@ char *PQport(const PGconn *conn) + + +PQunixsocket + Returns the name of the Unix-domain socket of the connection. + +char *PQunixsocket(const PGconn *conn) + + + + PQtty @@ -1832,6 +1851,13 @@ backend. +PGPORT sets the default port or local Unix domain socket +file extension for communicating with the Postgres +backend. + + + + PGDATABASE sets the default Postgres database name. diff --git a/doc/src/sgml/ref/createdb.sgml b/doc/src/sgml/ref/createdb.sgml index 3d1aca17bb..d5199e307a 100644 --- a/doc/src/sgml/ref/createdb.sgml +++ b/doc/src/sgml/ref/createdb.sgml @@ -1,5 +1,5 @@ @@ -56,6 +56,18 @@ Postgres documentation + + -k, --unixsocket path + + + Specifies the Unix-domain socket on which the + postmaster is running. + Without this option, the socket is created in /tmp + based on the port number. + + + + -U, --username username diff --git a/doc/src/sgml/ref/createlang.sgml b/doc/src/sgml/ref/createlang.sgml index f7c0540eac..0258646ad7 100644 --- a/doc/src/sgml/ref/createlang.sgml +++ b/doc/src/sgml/ref/createlang.sgml @@ -1,5 +1,5 @@ @@ -101,6 +101,18 @@ Postgres documentation + + -k, --unixsocket path + + + Specifies the Unix-domain socket on which the + postmaster is running. + Without this option, the socket is created in /tmp + based on the port number. + + + + -U, --username username diff --git a/doc/src/sgml/ref/createuser.sgml b/doc/src/sgml/ref/createuser.sgml index 5f3db58159..9845fcba1e 100644 --- a/doc/src/sgml/ref/createuser.sgml +++ b/doc/src/sgml/ref/createuser.sgml @@ -1,5 +1,5 @@ @@ -55,6 +55,18 @@ Postgres documentation + + -k, --unixsocket path + + + Specifies the Unix-domain socket on which the + postmaster is running. + Without this option, the socket is created in /tmp + based on the port number. + + + + -e, --echo diff --git a/doc/src/sgml/ref/dropdb.sgml b/doc/src/sgml/ref/dropdb.sgml index 5e28c4d528..c265c016e9 100644 --- a/doc/src/sgml/ref/dropdb.sgml +++ b/doc/src/sgml/ref/dropdb.sgml @@ -1,5 +1,5 @@ @@ -55,6 +55,18 @@ Postgres documentation + + -k, --unixsocket path + + + Specifies the Unix-domain socket on which the + postmaster is running. + Without this option, the socket is created in /tmp + based on the port number. + + + + -U, --username username diff --git a/doc/src/sgml/ref/droplang.sgml b/doc/src/sgml/ref/droplang.sgml index 48645d78a5..5d75a89fde 100644 --- a/doc/src/sgml/ref/droplang.sgml +++ b/doc/src/sgml/ref/droplang.sgml @@ -1,5 +1,5 @@ @@ -101,6 +101,18 @@ Postgres documentation + + -k, --unixsocket path + + + Specifies the Unix-domain socket on which the + postmaster is running. + Without this option, the socket is created in /tmp + based on the port number. + + + + -U, --username username diff --git a/doc/src/sgml/ref/dropuser.sgml b/doc/src/sgml/ref/dropuser.sgml index b72c5d865f..a2b1e537e5 100644 --- a/doc/src/sgml/ref/dropuser.sgml +++ b/doc/src/sgml/ref/dropuser.sgml @@ -1,5 +1,5 @@ @@ -55,6 +55,18 @@ Postgres documentation + + -k, --unixsocket path + + + Specifies the Unix-domain socket on which the + postmaster is running. + Without this option, the socket is created in /tmp + based on the port number. + + + + -e, --echo diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml index f0d1facfca..b0ad3e49cf 100644 --- a/doc/src/sgml/ref/pg_dump.sgml +++ b/doc/src/sgml/ref/pg_dump.sgml @@ -1,5 +1,5 @@ @@ -24,7 +24,9 @@ Postgres documentation pg_dump [ dbname ] -pg_dump [ -h host ] [ -p port ] +pg_dump [ -h host ] + [ -k path ] + [ -p port ] [ -t table ] [ -a ] [ -c ] [ -d ] [ -D ] [ -i ] [ -n ] [ -N ] [ -o ] [ -s ] [ -u ] [ -v ] [ -x ] @@ -204,6 +206,21 @@ pg_dump [ -h host ] [ -p + + -k path + + + Specifies the local Unix domain socket file path + on which the postmaster + is listening for connections. + Without this option, the socket path name defaults to + the value of the PGUNIXSOCKET environment + variable (if set), otherwise it is constructed + from the port number. + + + + -p port diff --git a/doc/src/sgml/ref/pg_dumpall.sgml b/doc/src/sgml/ref/pg_dumpall.sgml index a4d5c8d45a..1d78b9008c 100644 --- a/doc/src/sgml/ref/pg_dumpall.sgml +++ b/doc/src/sgml/ref/pg_dumpall.sgml @@ -1,5 +1,5 @@ @@ -23,7 +23,7 @@ Postgres documentation 1999-07-20 -pg_dumpall [ -h host ] [ -p port ] [ -a ] [ -d ] [ -D ] [ -O ] [ -s ] [ -u ] [ -v ] [ -x ] [ --accounts-only ] +pg_dumpall [ -h host ] [ -k path ] [ -p port ] [ -a ] [ -d ] [ -D ] [ -O ] [ -s ] [ -u ] [ -v ] [ -x ] [ --accounts-only ] @@ -149,6 +149,21 @@ pg_dumpall [ -h host ] [ -p + + -k path + + + Specifies the local Unix domain socket file path + on which the postmaster + is listening for connections. + Without this option, the socket path name defaults to + the value of the PGUNIXSOCKET environment + variable (if set), otherwise it is constructed + from the port number. + + + + -p port diff --git a/doc/src/sgml/ref/postmaster.sgml b/doc/src/sgml/ref/postmaster.sgml index eba01b30d4..e8e34c739f 100644 --- a/doc/src/sgml/ref/postmaster.sgml +++ b/doc/src/sgml/ref/postmaster.sgml @@ -1,5 +1,5 @@ @@ -24,7 +24,9 @@ Postgres documentation postmaster [ -B nBuffers ] [ -D DataDir ] [ -N maxBackends ] [ -S ] - [ -d DebugLevel ] [ -i ] [ -l ] + [ -d DebugLevel ] + [ -h hostname ] [ -i ] + [ -k path ] [ -l ] [ -o BackendOptions ] [ -p port ] [ -n | -s ] @@ -123,6 +125,36 @@ postmaster [ -B nBuffers ] [ -D + + -h hostName + + + Specifies the TCP/IP hostname or address + on which the postmaster + is to listen for connections from frontend applications. Defaults to + the value of the + PGHOST + environment variable, or if PGHOST + is not set, then defaults to "all", meaning listen on all configured addresses + (including localhost). + + + If you use a hostname or address other than "all", do not try to run + multiple instances of postmaster on the + same IP address but different ports. Doing so will result in them + attempting (incorrectly) to use the same shared memory segments. + Also, if you use a hostname other than "all", all of the host's IP addresses + on which postmaster instances are + listening must be distinct in the two last octets. + + + If you do use "all" (the default), then each instance must listen on a + different port (via -p or PGPORT). And, of course, do + not try to use both approaches on one host. + + + + -i @@ -134,6 +166,35 @@ postmaster [ -B nBuffers ] [ -D + + -k path + + + Specifies the local Unix domain socket path name + on which the postmaster + is to listen for connections from frontend applications. Defaults to + the value of the + PGUNIXSOCKET + environment variable, or if PGUNIXSOCKET + is not set, then defaults to a file in /tmp + constructed from the port number. + + + You can use this option to put the Unix-domain socket in a + directory that is private to one or more users using Unix + directory permissions. This is necessary for securely + creating databases automatically on shared machines. + In that situation, also disallow all TCP/IP connections + initially in pg_hba.conf. + If you specify a socket path other than the + default then all frontend applications (including + psql) must specify the same + socket path using either command-line options or + PGUNIXSOCKET. + + + + -l diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index 446449d95e..ca8d14f6de 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -1,5 +1,5 @@ @@ -1329,6 +1329,19 @@ Access permissions for database "test" + + -k, --unixsocket path + + + Specifies the Unix-domain socket on which the + postmaster is running. + Without this option, the socket is created in /tmp + based on the port number. + + + + + -H, --html diff --git a/doc/src/sgml/ref/vacuumdb.sgml b/doc/src/sgml/ref/vacuumdb.sgml index 1417ac55f9..7a701f216d 100644 --- a/doc/src/sgml/ref/vacuumdb.sgml +++ b/doc/src/sgml/ref/vacuumdb.sgml @@ -1,5 +1,5 @@ @@ -136,6 +136,18 @@ Postgres documentation + + -k, --unixsocket path + + + Specifies the Unix-domain socket on which the + postmaster is running. + Without this option, the socket is created in /tmp + based on the port number. + + + + -U username --username username diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml index b5093ffed1..3b484f50f9 100644 --- a/doc/src/sgml/start.sgml +++ b/doc/src/sgml/start.sgml @@ -1,5 +1,5 @@ @@ -110,8 +110,8 @@ $Header: /cvsroot/pgsql/doc/src/sgml/start.sgml,v 1.13 2000/09/29 20:21:34 peter will need to set the PGHOST environment variable to the name of the database server machine. The environment variable - PGPORT may also have to be set. The bottom - line is this: if + PGPORT or PGUNIXSOCKET may also have to be set. + The bottom line is this: if you try to start an application program and it complains that it cannot connect to the postmaster, you should immediately consult your site administrator to make diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 355144937a..2434d6ff16 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -29,7 +29,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pqcomm.c,v 1.109 2000/11/01 21:14:01 petere Exp $ + * $Id: pqcomm.c,v 1.110 2000/11/13 15:18:09 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -169,13 +169,14 @@ StreamDoUnlink(void) /* * StreamServerPort -- open a sock stream "listening" port. * - * This initializes the Postmaster's connection-accepting port. + * This initializes the Postmaster's connection-accepting port fdP. * * RETURNS: STATUS_OK or STATUS_ERROR */ int -StreamServerPort(int family, unsigned short portName, int *fdP) +StreamServerPort(int family, char *hostName, unsigned short portName, + char *unixSocketName, int *fdP) { SockAddr saddr; int fd, @@ -218,7 +219,8 @@ StreamServerPort(int family, unsigned short portName, int *fdP) #ifdef HAVE_UNIX_SOCKETS if (family == AF_UNIX) { - len = UNIXSOCK_PATH(saddr.un, portName); + UNIXSOCK_PATH(saddr.un, portName, unixSocketName); + len = UNIXSOCK_LEN(saddr.un); strcpy(sock_path, saddr.un.sun_path); /* * If the socket exists but nobody has an advisory lock on it we @@ -242,7 +244,27 @@ StreamServerPort(int family, unsigned short portName, int *fdP) if (family == AF_INET) { - saddr.in.sin_addr.s_addr = htonl(INADDR_ANY); + /* TCP/IP socket */ + if (hostName[0] == '\0') + saddr.in.sin_addr.s_addr = htonl(INADDR_ANY); + else + { + struct hostent *hp; + + hp = gethostbyname(hostName); + if ((hp == NULL) || (hp->h_addrtype != AF_INET)) + { + snprintf(PQerrormsg, PQERRORMSG_LENGTH, + "FATAL: StreamServerPort: gethostbyname(%s) failed: %s\n", + hostName, hstrerror(h_errno)); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return STATUS_ERROR; + } + memmove((char *) &(saddr.in.sin_addr), (char *) hp->h_addr, + hp->h_length); + } + saddr.in.sin_port = htons(portName); len = sizeof(struct sockaddr_in); } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index e50c0ee4d0..c6b645b15b 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.182 2000/11/12 20:51:51 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.183 2000/11/13 15:18:11 momjian Exp $ * * NOTES * @@ -114,6 +114,8 @@ static Dllist *PortList; /* The socket number we are listening for connections on */ int PostPortName; +char * UnixSocketName; +char * HostName; /* * This is a sequence number that indicates how many times we've had to @@ -224,7 +226,7 @@ extern void SetThisStartUpID(void); static void pmdaemonize(int argc, char *argv[]); static Port *ConnCreate(int serverFd); static void ConnFree(Port *port); -static void reset_shared(int port); +static void reset_shared(unsigned short port); static void SIGHUP_handler(SIGNAL_ARGS); static void pmdie(SIGNAL_ARGS); static void reaper(SIGNAL_ARGS); @@ -366,7 +368,7 @@ PostmasterMain(int argc, char *argv[]) * will occur. */ opterr = 1; - while ((opt = getopt(argc, argv, "A:a:B:b:c:D:d:Film:MN:no:p:SsV-:?")) != EOF) + while ((opt = getopt(argc, argv, "A:a:B:b:c:D:d:Fh:ik:lm:MN:no:p:SsV-:?")) != EOF) { switch(opt) { @@ -422,7 +424,7 @@ PostmasterMain(int argc, char *argv[]) #ifdef HAVE_INT_OPTRESET optreset = 1; #endif - while ((opt = getopt(argc, argv, "A:a:B:b:c:D:d:Film:MN:no:p:SsV-:?")) != EOF) + while ((opt = getopt(argc, argv, "A:a:B:b:c:D:d:Fh:ik:lm:MN:no:p:SsV-:?")) != EOF) { switch (opt) { @@ -456,9 +458,16 @@ PostmasterMain(int argc, char *argv[]) case 'F': enableFsync = false; break; + case 'h': + HostName = optarg; + break; case 'i': NetServer = true; break; + case 'k': + /* Set PGUNIXSOCKET by hand. */ + UnixSocketName = optarg; + break; #ifdef USE_SSL case 'l': EnableSSL = true; @@ -606,8 +615,9 @@ PostmasterMain(int argc, char *argv[]) if (NetServer) { - status = StreamServerPort(AF_INET, (unsigned short) PostPortName, - &ServerSock_INET); + status = StreamServerPort(AF_INET, HostName, + (unsigned short) PostPortName, UnixSocketName, + &ServerSock_INET); if (status != STATUS_OK) { fprintf(stderr, "%s: cannot create INET stream port\n", @@ -617,8 +627,9 @@ PostmasterMain(int argc, char *argv[]) } #ifdef HAVE_UNIX_SOCKETS - status = StreamServerPort(AF_UNIX, (unsigned short) PostPortName, - &ServerSock_UNIX); + status = StreamServerPort(AF_UNIX, HostName, + (unsigned short) PostPortName, UnixSocketName, + &ServerSock_UNIX); if (status != STATUS_OK) { fprintf(stderr, "%s: cannot create UNIX stream port\n", @@ -789,7 +800,9 @@ usage(const char *progname) printf(" -d 1-5 debugging level\n"); printf(" -D database directory\n"); printf(" -F turn fsync off\n"); + printf(" -h hostname specify hostname or IP address\n"); printf(" -i enable TCP/IP connections\n"); + printf(" -k path specify Unix-domain socket name\n"); #ifdef USE_SSL printf(" -l enable SSL connections\n"); #endif @@ -1302,12 +1315,76 @@ ConnFree(Port *conn) free(conn); } +/* + * get_host_port -- return a pseudo port number (16 bits) + * derived from the primary IP address of HostName. + */ +static unsigned short +get_host_port(void) +{ + static unsigned short hostPort = 0; + + if (hostPort == 0) + { + SockAddr saddr; + struct hostent *hp; + + hp = gethostbyname(HostName); + if ((hp == NULL) || (hp->h_addrtype != AF_INET)) + { + char msg[1024]; + snprintf(msg, sizeof(msg), + "FATAL: get_host_port: gethostbyname(%s) failed: %s\n", + HostName, hstrerror(h_errno)); + fputs(msg, stderr); + pqdebug("%s", msg); + exit(1); + } + memmove((char *) &(saddr.in.sin_addr), + (char *) hp->h_addr, + hp->h_length); + hostPort = ntohl(saddr.in.sin_addr.s_addr) & 0xFFFF; + } + + return hostPort; +} + /* * reset_shared -- reset shared memory and semaphores */ static void -reset_shared(int port) +reset_shared(unsigned short port) { + /* + * A typical ipc_key is 5432001, which is port 5432, sequence + * number 0, and 01 as the index in IPCKeyGetBufferMemoryKey(). + * The 32-bit INT_MAX is 2147483 6 47. + * + * The default algorithm for calculating the IPC keys assumes that all + * instances of postmaster on a given host are listening on different + * ports. In order to work (prevent shared memory collisions) if you + * run multiple PostgreSQL instances on the same port and different IP + * addresses on a host, we change the algorithm if you give postmaster + * the -h option, or set PGHOST, to a value other than the internal + * default. + * + * If HostName is set, then we generate the IPC keys using the + * last two octets of the IP address instead of the port number. + * This algorithm assumes that no one will run multiple PostgreSQL + * instances on one host using two IP addresses that have the same two + * last octets in different class C networks. If anyone does, it + * would be rare. + * + * So, if you use -h or PGHOST, don't try to run two instances of + * PostgreSQL on the same IP address but different ports. If you + * don't use them, then you must use different ports (via -p or + * PGPORT). And, of course, don't try to use both approaches on one + * host. + */ + + if (HostName[0] != '\0') + port = get_host_port(); + ipc_key = port * 1000 + shmem_seq * 100; CreateSharedMemoryAndSemaphores(ipc_key, MaxBackends); shmem_seq += 1; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 8fe7bd36fa..ecdc1d1a75 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -4,7 +4,7 @@ * Support for grand unified configuration scheme, including SET * command, configuration file, and command line options. * - * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.16 2000/11/09 11:25:59 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.17 2000/11/13 15:18:12 momjian Exp $ * * Copyright 2000 by PostgreSQL Global Development Group * Written by Peter Eisentraut . @@ -304,6 +304,12 @@ ConfigureNamesString[] = {"unix_socket_group", PGC_POSTMASTER, &Unix_socket_group, "", NULL}, + {"unixsocket", PGC_POSTMASTER, &UnixSocketName, + "", NULL}, + + {"hostname", PGC_POSTMASTER, &HostName, + "", NULL}, + {NULL, 0, NULL, NULL, NULL} }; diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index 8fceb26c8e..ffe071a665 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -99,8 +99,9 @@ typedef struct _restoreOptions { int useDB; char *dbname; - char *pgport; char *pghost; + char *pgport; + char *pgunixsocket; int ignoreVersion; int requirePassword; @@ -122,6 +123,7 @@ PGconn* ConnectDatabase(Archive *AH, const char* dbname, const char* pghost, const char* pgport, + const char* pgunixsocket, const int reqPwd, const int ignoreVersion); diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index d8a969b41e..085a2eb329 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -131,8 +131,9 @@ void RestoreArchive(Archive* AHX, RestoreOptions *ropt) if (AH->version < K_VERS_1_3) die_horribly(AH, "Direct database connections are not supported in pre-1.3 archives"); - ConnectDatabase(AHX, ropt->dbname, ropt->pghost, ropt->pgport, - ropt->requirePassword, ropt->ignoreVersion); + ConnectDatabase(AHX, ropt->dbname, ropt->pghost, ropt->pgport, + ropt->pgunixsocket, ropt->requirePassword, + ropt->ignoreVersion); /* * If no superuser was specified then see if the current user will do... diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h index 2c7291e6c6..a938f5e339 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -187,6 +187,7 @@ typedef struct _archiveHandle { char *archdbname; /* DB name *read* from archive */ char *pghost; char *pgport; + char *pgunixsocket; PGconn *connection; PGconn *blobConnection; /* Connection for BLOB xref */ int txActive; /* Flag set if TX active on connection */ diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c index 4b8873c3a2..082edd5824 100644 --- a/src/bin/pg_dump/pg_backup_db.c +++ b/src/bin/pg_dump/pg_backup_db.c @@ -1,7 +1,7 @@ /*------------------------------------------------------------------------- * * -*------------------------------------------------------------------------- + *------------------------------------------------------------------------- */ #include /* for getopt() */ @@ -273,6 +273,7 @@ PGconn* ConnectDatabase(Archive *AHX, const char* dbname, const char* pghost, const char* pgport, + const char* pgunixsocket, const int reqPwd, const int ignoreVersion) { @@ -307,6 +308,15 @@ PGconn* ConnectDatabase(Archive *AHX, else AH->pgport = NULL; + if (pgunixsocket != NULL) + { + AH->pgport = strdup(pgunixsocket); + sprintf(tmp_string, "unixsocket=%s ", AH->pgunixsocket); + strcat(connect_string, tmp_string); + } + else + AH->pgunixsocket = NULL; + sprintf(tmp_string, "dbname=%s ", AH->dbname); strcat(connect_string, tmp_string); diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 4b765f5288..738425a3eb 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -22,7 +22,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.177 2000/10/31 14:20:30 pjw Exp $ + * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.178 2000/11/13 15:18:13 momjian Exp $ * * Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb * @@ -200,6 +200,7 @@ help(const char *progname) " -F, --format {c|f|p} output file format (custom, files, plain text)\n" " -h, --host server host name\n" " -i, --ignore-version proceed when database version != pg_dump version\n" + " -k, --unixsocket server Unix-domain socket name\n" " -n, --no-quotes suppress most quotes around identifiers\n" " -N, --quotes enable most quotes around identifiers\n" " -o, --oids dump object ids (oids)\n" @@ -226,6 +227,7 @@ help(const char *progname) " -F {c|f|p} output file format (custom, files, plain text)\n" " -h server host name\n" " -i proceed when database version != pg_dump version\n" + " -k server Unix-domain socket name\n" " -n suppress most quotes around identifiers\n" " -N enable most quotes around identifiers\n" " -o dump object ids (oids)\n" @@ -629,6 +631,7 @@ main(int argc, char **argv) const char *dbname = NULL; const char *pghost = NULL; const char *pgport = NULL; + const char *pgunixsocket = NULL; char *tablename = NULL; bool oids = false; TableInfo *tblinfo; @@ -658,6 +661,7 @@ main(int argc, char **argv) {"attribute-inserts", no_argument, NULL, 'D'}, {"host", required_argument, NULL, 'h'}, {"ignore-version", no_argument, NULL, 'i'}, + {"unixsocket", required_argument, NULL, 'k'}, {"no-reconnect", no_argument, NULL, 'R'}, {"no-quotes", no_argument, NULL, 'n'}, {"quotes", no_argument, NULL, 'N'}, @@ -752,6 +756,10 @@ main(int argc, char **argv) ignore_version = true; break; + case 'k': /* server Unix-domain socket */ + pgunixsocket = optarg; + break; + case 'n': /* Do not force double-quotes on * identifiers */ force_quotes = false; @@ -948,7 +956,8 @@ main(int argc, char **argv) dbname = argv[optind]; /* Open the database using the Archiver, so it knows about it. Errors mean death */ - g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport, use_password, ignore_version); + g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport, pgunixsocket, + use_password, ignore_version); /* * Start serializable transaction to dump consistent data diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c index 458482ed51..cafb7e9df6 100644 --- a/src/bin/pg_dump/pg_restore.c +++ b/src/bin/pg_dump/pg_restore.c @@ -101,6 +101,7 @@ struct option cmdopts[] = { { "ignore-version", 0, NULL, 'i'}, { "index", 2, NULL, 'I'}, { "list", 0, NULL, 'l'}, + { "unixsocket", 1, NULL, 'k' }, { "no-acl", 0, NULL, 'x' }, { "no-owner", 0, NULL, 'O'}, { "no-reconnect", 0, NULL, 'R' }, @@ -132,9 +133,9 @@ int main(int argc, char **argv) progname = *argv; #ifdef HAVE_GETOPT_LONG - while ((c = getopt_long(argc, argv, "acCd:f:F:h:i:lNoOp:P:rRsS:t:T:uU:vx", cmdopts, NULL)) != EOF) + while ((c = getopt_long(argc, argv, "acCd:f:F:h:i:k:lNoOp:P:rRsS:t:T:uU:vx", cmdopts, NULL)) != EOF) #else - while ((c = getopt(argc, argv, "acCd:f:F:h:i:lNoOp:P:rRsS:t:T:uU:vx")) != -1) + while ((c = getopt(argc, argv, "acCd:f:F:h:i:k:lNoOp:P:rRsS:t:T:uU:vx")) != -1) #endif { switch (c) @@ -170,6 +171,10 @@ int main(int argc, char **argv) case 'i': opts->ignoreVersion = 1; break; + case 'k': + if (strlen(optarg) != 0) + opts->pgunixsocket = strdup(optarg); + break; case 'N': opts->origOrder = 1; break; diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index d563070ae6..65c05a4ac9 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.36 2000/09/17 20:33:45 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.37 2000/11/13 15:18:14 momjian Exp $ */ #include "postgres.h" #include "command.h" @@ -1202,6 +1202,7 @@ do_connect(const char *new_dbname, const char *new_user) SetVariable(pset.vars, "USER", NULL); SetVariable(pset.vars, "HOST", NULL); SetVariable(pset.vars, "PORT", NULL); + SetVariable(pset.vars, "UNIXSOCKET", NULL); SetVariable(pset.vars, "ENCODING", NULL); /* If dbname is "" then use old name, else new one (even if NULL) */ @@ -1231,6 +1232,7 @@ do_connect(const char *new_dbname, const char *new_user) do { need_pass = false; + /* FIXME use PQconnectdb to support passing the Unix socket */ pset.db = PQsetdbLogin(PQhost(oldconn), PQport(oldconn), NULL, NULL, dbparam, userparam, pwparam); @@ -1307,6 +1309,7 @@ do_connect(const char *new_dbname, const char *new_user) SetVariable(pset.vars, "USER", PQuser(pset.db)); SetVariable(pset.vars, "HOST", PQhost(pset.db)); SetVariable(pset.vars, "PORT", PQport(pset.db)); + SetVariable(pset.vars, "UNIXSOCKET", PQunixsocket(pset.db)); SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding)); pset.issuper = test_superuser(PQuser(pset.db)); diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index ddc2be3c4f..da0542df59 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.23 2000/08/29 09:36:48 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.24 2000/11/13 15:18:14 momjian Exp $ */ #include "postgres.h" #include "common.h" @@ -329,6 +329,7 @@ PSQLexec(const char *query) SetVariable(pset.vars, "DBNAME", NULL); SetVariable(pset.vars, "HOST", NULL); SetVariable(pset.vars, "PORT", NULL); + SetVariable(pset.vars, "UNIXSOCKET", NULL); SetVariable(pset.vars, "USER", NULL); SetVariable(pset.vars, "ENCODING", NULL); return NULL; @@ -508,6 +509,7 @@ SendQuery(const char *query) SetVariable(pset.vars, "DBNAME", NULL); SetVariable(pset.vars, "HOST", NULL); SetVariable(pset.vars, "PORT", NULL); + SetVariable(pset.vars, "UNIXSOCKET", NULL); SetVariable(pset.vars, "USER", NULL); SetVariable(pset.vars, "ENCODING", NULL); return false; diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index 3dfd7d8e8d..b9ee9caa67 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/help.c,v 1.32 2000/09/22 23:02:00 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/help.c,v 1.33 2000/11/13 15:18:14 momjian Exp $ */ #include "postgres.h" #include "help.h" @@ -103,6 +103,16 @@ usage(void) puts(")"); puts(" -H HTML table output mode (-P format=html)"); + + /* Display default Unix-domain socket */ + env = getenv("PGUNIXSOCKET"); + printf(" -k Specify Unix domain socket name (default: "); + if (env) + fputs(env, stdout); + else + fputs("computed from the port", stdout); + puts(")"); + puts(" -l List available databases, then exit"); puts(" -n Disable readline"); puts(" -o Send query output to filename (or |pipe)"); diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c index 1177c6f3f3..d29bc12ddb 100644 --- a/src/bin/psql/prompt.c +++ b/src/bin/psql/prompt.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/prompt.c,v 1.13 2000/08/20 10:55:34 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/prompt.c,v 1.14 2000/11/13 15:18:14 momjian Exp $ */ #include "postgres.h" #include "prompt.h" @@ -190,6 +190,11 @@ get_prompt(promptStatus_t status) if (pset.db && PQport(pset.db)) strncpy(buf, PQport(pset.db), MAX_PROMPT_SIZE); break; + /* DB server Unix-domain socket */ + case '<': + if (pset.db && PQunixsocket(pset.db)) + strncpy(buf, PQunixsocket(pset.db), MAX_PROMPT_SIZE); + break; /* DB server user name */ case 'n': if (pset.db) diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c index f96cc7980b..9b0e60f0a3 100644 --- a/src/bin/psql/startup.c +++ b/src/bin/psql/startup.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.37 2000/09/17 20:33:45 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.38 2000/11/13 15:18:14 momjian Exp $ */ #include "postgres.h" @@ -65,6 +65,7 @@ struct adhoc_opts char *dbname; char *host; char *port; + char *unixsocket; char *username; enum _actions action; char *action_string; @@ -161,6 +162,7 @@ main(int argc, char *argv[]) do { need_pass = false; + /* FIXME use PQconnectdb to allow setting the unix socket */ pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.action == ACT_LIST_DB ? "template1" : options.dbname, username, password); @@ -206,6 +208,7 @@ main(int argc, char *argv[]) SetVariable(pset.vars, "USER", PQuser(pset.db)); SetVariable(pset.vars, "HOST", PQhost(pset.db)); SetVariable(pset.vars, "PORT", PQport(pset.db)); + SetVariable(pset.vars, "UNIXSOCKET", PQunixsocket(pset.db)); SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding)); #ifndef WIN32 @@ -320,6 +323,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) {"field-separator", required_argument, NULL, 'F'}, {"host", required_argument, NULL, 'h'}, {"html", no_argument, NULL, 'H'}, + {"unixsocket", required_argument, NULL, 'k'}, {"list", no_argument, NULL, 'l'}, {"no-readline", no_argument, NULL, 'n'}, {"output", required_argument, NULL, 'o'}, @@ -353,14 +357,14 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) memset(options, 0, sizeof *options); #ifdef HAVE_GETOPT_LONG - while ((c = getopt_long(argc, argv, "aAc:d:eEf:F:lh:Hno:p:P:qRsStT:uU:v:VWxX?", long_options, &optindex)) != -1) + while ((c = getopt_long(argc, argv, "aAc:d:eEf:F:lh:Hk:no:p:P:qRsStT:uU:v:VWxX?", long_options, &optindex)) != -1) #else /* not HAVE_GETOPT_LONG */ /* * Be sure to leave the '-' in here, so we can catch accidental long * options. */ - while ((c = getopt(argc, argv, "aAc:d:eEf:F:lh:Hno:p:P:qRsStT:uU:v:VWxX?-")) != -1) + while ((c = getopt(argc, argv, "aAc:d:eEf:F:lh:Hk:no:p:P:qRsStT:uU:v:VWxX?-")) != -1) #endif /* not HAVE_GETOPT_LONG */ { switch (c) @@ -406,6 +410,9 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) case 'l': options->action = ACT_LIST_DB; break; + case 'k': + options->unixsocket = optarg; + break; case 'n': options->no_readline = true; break; diff --git a/src/bin/scripts/createdb b/src/bin/scripts/createdb index 3601811b24..213913ba89 100644 --- a/src/bin/scripts/createdb +++ b/src/bin/scripts/createdb @@ -11,7 +11,7 @@ # # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/createdb,v 1.9 2000/11/11 22:59:48 petere Exp $ +# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/createdb,v 1.10 2000/11/13 15:18:14 momjian Exp $ # #------------------------------------------------------------------------- @@ -50,6 +50,15 @@ do --port=*) PSQLOPT="$PSQLOPT -p "`echo $1 | sed 's/^--port=//'` ;; + --unixsocket|-k) + PSQLOPT="$PSQLOPT -k $2" + shift;; + -k*) + PSQLOPT="$PSQLOPT $1" + ;; + --unixsocket=*) + PSQLOPT="$PSQLOPT -k "`echo $1 | sed 's/^--unixsocket=//'` + ;; --username|-U) PSQLOPT="$PSQLOPT -U $2" shift;; @@ -114,6 +123,7 @@ if [ "$usage" ]; then echo " -E, --encoding=ENCODING Multibyte encoding for the database" echo " -h, --host=HOSTNAME Database server host" echo " -p, --port=PORT Database server port" + echo " -k, --unixsocket=PATH Database server Unix-domain socket name" echo " -U, --username=USERNAME Username to connect as" echo " -W, --password Prompt for password" echo " -e, --echo Show the query being sent to the backend" diff --git a/src/bin/scripts/createlang.sh b/src/bin/scripts/createlang.sh index 4275dc6e93..c22dcba652 100644 --- a/src/bin/scripts/createlang.sh +++ b/src/bin/scripts/createlang.sh @@ -8,7 +8,7 @@ # # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/createlang.sh,v 1.17 2000/11/11 22:59:48 petere Exp $ +# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/createlang.sh,v 1.18 2000/11/13 15:18:14 momjian Exp $ # #------------------------------------------------------------------------- @@ -65,6 +65,15 @@ do --port=*) PSQLOPT="$PSQLOPT -p "`echo $1 | sed 's/^--port=//'` ;; + --unixsocket|-k) + PSQLOPT="$PSQLOPT -k $2" + shift;; + -k*) + PSQLOPT="$PSQLOPT $1" + ;; + --unixsocket=*) + PSQLOPT="$PSQLOPT -k "`echo $1 | sed 's/^--unixsocket=//'` + ;; --username|-U) PSQLOPT="$PSQLOPT -U $2" shift;; @@ -126,6 +135,7 @@ if [ "$usage" ]; then echo "Options:" echo " -h, --host=HOSTNAME Database server host" echo " -p, --port=PORT Database server port" + echo " -k, --unixsocket=PATH Database server Unix-domain socket name" echo " -U, --username=USERNAME Username to connect as" echo " -W, --password Prompt for password" echo " -d, --dbname=DBNAME Database to install language in" diff --git a/src/bin/scripts/createuser b/src/bin/scripts/createuser index 62c674d99e..198e4b81cf 100644 --- a/src/bin/scripts/createuser +++ b/src/bin/scripts/createuser @@ -8,7 +8,7 @@ # # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/createuser,v 1.12 2000/11/11 22:59:48 petere Exp $ +# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/createuser,v 1.13 2000/11/13 15:18:14 momjian Exp $ # # Note - this should NOT be setuid. # @@ -63,6 +63,15 @@ do --port=*) PSQLOPT="$PSQLOPT -p "`echo $1 | sed 's/^--port=//'` ;; + --unixsocket|-k) + PSQLOPT="$PSQLOPT -k $2" + shift;; + -k*) + PSQLOPT="$PSQLOPT $1" + ;; + --unixsocket=*) + PSQLOPT="$PSQLOPT -k "`echo $1 | sed 's/^--unixsocket=//'` + ;; # Note: These two specify the user to connect as (like in psql), # not the user you're creating. --username|-U) @@ -135,6 +144,7 @@ if [ "$usage" ]; then echo " -P, --pwprompt Assign a password to new user" echo " -h, --host=HOSTNAME Database server host" echo " -p, --port=PORT Database server port" + echo " -k, --unixsocket=PATH Database server Unix-domain socket name" echo " -U, --username=USERNAME Username to connect as (not the one to create)" echo " -W, --password Prompt for password to connect" echo " -e, --echo Show the query being sent to the backend" diff --git a/src/bin/scripts/dropdb b/src/bin/scripts/dropdb index 1bb6f10f25..586b62ac7f 100644 --- a/src/bin/scripts/dropdb +++ b/src/bin/scripts/dropdb @@ -10,7 +10,7 @@ # # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/dropdb,v 1.7 2000/11/11 22:59:48 petere Exp $ +# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/dropdb,v 1.8 2000/11/13 15:18:14 momjian Exp $ # #------------------------------------------------------------------------- @@ -59,6 +59,15 @@ do --port=*) PSQLOPT="$PSQLOPT -p "`echo $1 | sed 's/^--port=//'` ;; + --unixsocket|-k) + PSQLOPT="$PSQLOPT -k $2" + shift;; + -k*) + PSQLOPT="$PSQLOPT $1" + ;; + --unixsocket=*) + PSQLOPT="$PSQLOPT -k "`echo $1 | sed 's/^--unixsocket=//'` + ;; --username|-U) PSQLOPT="$PSQLOPT -U $2" shift;; @@ -103,6 +112,7 @@ if [ "$usage" ]; then echo "Options:" echo " -h, --host=HOSTNAME Database server host" echo " -p, --port=PORT Database server port" + echo " -k, --unixsocket=PATH Database server Unix-domain socket name" echo " -U, --username=USERNAME Username to connect as" echo " -W, --password Prompt for password" echo " -i, --interactive Prompt before deleting anything" diff --git a/src/bin/scripts/droplang b/src/bin/scripts/droplang index 3205ad3577..46856e4241 100644 --- a/src/bin/scripts/droplang +++ b/src/bin/scripts/droplang @@ -8,7 +8,7 @@ # # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/droplang,v 1.8 2000/11/11 22:59:48 petere Exp $ +# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/droplang,v 1.9 2000/11/13 15:18:14 momjian Exp $ # #------------------------------------------------------------------------- @@ -65,6 +65,15 @@ do --port=*) PSQLOPT="$PSQLOPT -p "`echo $1 | sed 's/^--port=//'` ;; + --unixsocket|-k) + PSQLOPT="$PSQLOPT -k $2" + shift;; + -k*) + PSQLOPT="$PSQLOPT $1" + ;; + --unixsocket=*) + PSQLOPT="$PSQLOPT -k "`echo $1 | sed 's/^--unixsocket=//'` + ;; --username|-U) PSQLOPT="$PSQLOPT -U $2" shift;; @@ -113,6 +122,7 @@ if [ "$usage" ]; then echo "Options:" echo " -h, --host=HOSTNAME Database server host" echo " -p, --port=PORT Database server port" + echo " -k, --unixsocket=PATH Database server Unix-domain socket name" echo " -U, --username=USERNAME Username to connect as" echo " -W, --password Prompt for password" echo " -d, --dbname=DBNAME Database to remove language from" diff --git a/src/bin/scripts/dropuser b/src/bin/scripts/dropuser index 81a00f9c1c..4aa858124b 100644 --- a/src/bin/scripts/dropuser +++ b/src/bin/scripts/dropuser @@ -8,7 +8,7 @@ # # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/dropuser,v 1.7 2000/11/11 22:59:48 petere Exp $ +# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/dropuser,v 1.8 2000/11/13 15:18:14 momjian Exp $ # # Note - this should NOT be setuid. # @@ -59,6 +59,15 @@ do --port=*) PSQLOPT="$PSQLOPT -p "`echo $1 | sed 's/^--port=//'` ;; + --unixsocket|-k) + PSQLOPT="$PSQLOPT -k $2" + shift;; + -k*) + PSQLOPT="$PSQLOPT $1" + ;; + --unixsocket=*) + PSQLOPT="$PSQLOPT -k "`echo $1 | sed 's/^--unixsocket=//'` + ;; # Note: These two specify the user to connect as (like in psql), # not the user you're dropping. --username|-U) @@ -105,6 +114,7 @@ if [ "$usage" ]; then echo "Options:" echo " -h, --host=HOSTNAME Database server host" echo " -p, --port=PORT Database server port" + echo " -k, --unixsocket=PATH Database server Unix-domain socket name" echo " -U, --username=USERNAME Username to connect as (not the one to drop)" echo " -W, --password Prompt for password to connect" echo " -i, --interactive Prompt before deleting anything" diff --git a/src/bin/scripts/vacuumdb b/src/bin/scripts/vacuumdb index af038add8a..fb1db8bfe6 100644 --- a/src/bin/scripts/vacuumdb +++ b/src/bin/scripts/vacuumdb @@ -11,7 +11,7 @@ # # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/vacuumdb,v 1.10 2000/11/11 22:59:48 petere Exp $ +# $Header: /cvsroot/pgsql/src/bin/scripts/Attic/vacuumdb,v 1.11 2000/11/13 15:18:14 momjian Exp $ # #------------------------------------------------------------------------- @@ -52,6 +52,15 @@ do --port=*) PSQLOPT="$PSQLOPT -p "`echo $1 | sed 's/^--port=//'` ;; + --unixsocket|-k) + PSQLOPT="$PSQLOPT -k $2" + shift;; + -k*) + PSQLOPT="$PSQLOPT $1" + ;; + --unixsocket=*) + PSQLOPT="$PSQLOPT -k "`echo $1 | sed 's/^--unixsocket=//'` + ;; --username|-U) PSQLOPT="$PSQLOPT -U $2" shift;; @@ -121,6 +130,7 @@ if [ "$usage" ]; then echo "Options:" echo " -h, --host=HOSTNAME Database server host" echo " -p, --port=PORT Database server port" + echo " -k, --unixsocket=PATH Database server Unix-domain socket name" echo " -U, --username=USERNAME Username to connect as" echo " -W, --password Prompt for password" echo " -d, --dbname=DBNAME Database to vacuum" diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h index 3632012f67..21cae47d97 100644 --- a/src/include/libpq/libpq.h +++ b/src/include/libpq/libpq.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: libpq.h,v 1.39 2000/07/08 03:04:30 tgl Exp $ + * $Id: libpq.h,v 1.40 2000/11/13 15:18:14 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -55,7 +55,8 @@ extern char PQerrormsg[PQERRORMSG_LENGTH]; /* in libpq/util.c */ /* * prototypes for functions in pqcomm.c */ -extern int StreamServerPort(int family, unsigned short portName, int *fdP); +extern int StreamServerPort(int family, char *hostName, + unsigned short portName, char *unixSocketName, int *fdP); extern int StreamConnection(int server_fd, Port *port); extern void StreamClose(int sock); extern void pq_init(void); diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h index bb64862922..10a798d6a6 100644 --- a/src/include/libpq/pqcomm.h +++ b/src/include/libpq/pqcomm.h @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pqcomm.h,v 1.43 2000/11/01 21:14:03 petere Exp $ + * $Id: pqcomm.h,v 1.44 2000/11/13 15:18:14 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -51,12 +51,15 @@ typedef union SockAddr /* Configure the UNIX socket address for the well known port. */ #if defined(SUN_LEN) -#define UNIXSOCK_PATH(sun,port) \ - (sprintf((sun).sun_path, "/tmp/.s.PGSQL.%d", (port)), SUN_LEN(&(sun))) +#define UNIXSOCK_PATH(sun,port,defpath) \ + ((defpath && defpath[0] != '\0') ? (strncpy((sun).sun_path, defpath, sizeof((sun).sun_path)), (sun).sun_path[sizeof((sun).sun_path)-1] = '\0') : sprintf((sun).sun_path, "/tmp/.s.PGSQL.%d", (port))) +#define UNIXSOCK_LEN(sun) \ + (SUN_LEN(&(sun))) #else -#define UNIXSOCK_PATH(sun,port) \ - (sprintf((sun).sun_path, "/tmp/.s.PGSQL.%d", (port)), \ - strlen((sun).sun_path)+ offsetof(struct sockaddr_un, sun_path)) +#define UNIXSOCK_PATH(sun,port,defpath) \ + ((defpath && defpath[0] != '\0') ? (strncpy((sun).sun_path, defpath, sizeof((sun).sun_path)), (sun).sun_path[sizeof((sun).sun_path)-1] = '\0') : sprintf((sun).sun_path, "/tmp/.s.PGSQL.%d", (port))) +#define UNIXSOCK_LEN(sun) \ + (strlen((sun).sun_path)+ offsetof(struct sockaddr_un, sun_path)) #endif /* @@ -176,5 +179,7 @@ typedef struct CancelRequestPacket extern int Unix_socket_permissions; extern char * Unix_socket_group; +extern char * UnixSocketName; +extern char * HostName; #endif /* PQCOMM_H */ diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 4d37a8c611..b0447285d4 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.144 2000/11/04 02:27:56 ishii Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.145 2000/11/13 15:18:15 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -130,6 +130,9 @@ static const PQconninfoOption PQconninfoOptions[] = { {"port", "PGPORT", DEF_PGPORT_STR, NULL, "Database-Port", "", 6}, + {"unixsocket", "PGUNIXSOCKET", NULL, NULL, + "Unix-Socket", "", 80}, + {"tty", "PGTTY", DefaultTty, NULL, "Backend-Debug-TTY", "D", 40}, @@ -305,6 +308,8 @@ PQconnectStart(const char *conninfo) conn->pghost = tmp ? strdup(tmp) : NULL; tmp = conninfo_getval(connOptions, "port"); conn->pgport = tmp ? strdup(tmp) : NULL; + tmp = conninfo_getval(connOptions, "unixsocket"); + conn->pgunixsocket = tmp ? strdup(tmp) : NULL; tmp = conninfo_getval(connOptions, "tty"); conn->pgtty = tmp ? strdup(tmp) : NULL; tmp = conninfo_getval(connOptions, "options"); @@ -385,6 +390,9 @@ PQconndefaults(void) * PGPORT identifies TCP port to which to connect if argument * is NULL or a null string. * + * PGUNIXSOCKET identifies Unix-domain socket to which to connect; default + * is computed from the TCP port. + * * PGTTY identifies tty to which to send messages if argument * is NULL or a null string. * @@ -435,6 +443,14 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions, else conn->pgport = strdup(pgport); +#if FIX_ME + /* we need to modify the function to accept a unix socket path */ + if (pgunixsocket) + conn->pgunixsocket = strdup(pgunixsocket); + else if ((tmp = getenv("PGUNIXSOCKET")) != NULL) + conn->pgunixsocket = strdup(tmp); +#endif + if (pgtty == NULL) { if ((tmp = getenv("PGTTY")) == NULL) @@ -510,13 +526,13 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions, /* * update_db_info - - * get all additional infos out of dbName + * get all additional info out of dbName * */ static int update_db_info(PGconn *conn) { - char *tmp, + char *tmp, *tmp2, *old = conn->dbName; if (strchr(conn->dbName, '@') != NULL) @@ -525,6 +541,8 @@ update_db_info(PGconn *conn) tmp = strrchr(conn->dbName, ':'); if (tmp != NULL) /* port number given */ { + if (conn->pgport) + free(conn->pgport); conn->pgport = strdup(tmp + 1); *tmp = '\0'; } @@ -532,6 +550,8 @@ update_db_info(PGconn *conn) tmp = strrchr(conn->dbName, '@'); if (tmp != NULL) /* host name given */ { + if (conn->pghost) + free(conn->pghost); conn->pghost = strdup(tmp + 1); *tmp = '\0'; } @@ -558,13 +578,15 @@ update_db_info(PGconn *conn) /* * new style: - * :postgresql://server[:port][/dbname][?options] + * :postgresql://server[:port|:/unixsocket/path:][/dbname][?options] */ offset += strlen("postgresql://"); tmp = strrchr(conn->dbName + offset, '?'); if (tmp != NULL) /* options given */ { + if (conn->pgoptions) + free(conn->pgoptions); conn->pgoptions = strdup(tmp + 1); *tmp = '\0'; } @@ -572,26 +594,62 @@ update_db_info(PGconn *conn) tmp = strrchr(conn->dbName + offset, '/'); if (tmp != NULL) /* database name given */ { + if (conn->dbName) + free(conn->dbName); conn->dbName = strdup(tmp + 1); *tmp = '\0'; } else { + /* Why do we default only this value from the environment again? */ if ((tmp = getenv("PGDATABASE")) != NULL) + { + if (conn->dbName) + free(conn->dbName); conn->dbName = strdup(tmp); + } else if (conn->pguser) + { + if (conn->dbName) + free(conn->dbName); conn->dbName = strdup(conn->pguser); + } } tmp = strrchr(old + offset, ':'); - if (tmp != NULL) /* port number given */ + if (tmp != NULL) /* port number or Unix socket path given */ { - conn->pgport = strdup(tmp + 1); *tmp = '\0'; + if ((tmp2 = strchr(tmp + 1, ':')) != NULL) + { + if (strncmp(old, "unix:", 5) != 0) + { + printfPQExpBuffer(&conn->errorMessage, + "connectDBStart() -- " + "socket name can only be specified with " + "non-TCP\n"); + return 1; + } + *tmp2 = '\0'; + if (conn->pgunixsocket) + free(conn->pgunixsocket); + conn->pgunixsocket = strdup(tmp + 1); + } + else + { + if (conn->pgport) + free(conn->pgport); + conn->pgport = strdup(tmp + 1); + if (conn->pgunixsocket) + free(conn->pgunixsocket); + conn->pgunixsocket = NULL; + } } if (strncmp(old, "unix:", 5) == 0) { + if (conn->pghost) + free(conn->pghost); conn->pghost = NULL; if (strcmp(old + offset, "localhost") != 0) { @@ -603,8 +661,11 @@ update_db_info(PGconn *conn) } } else + { + if (conn->pghost) + free(conn->pghost); conn->pghost = strdup(old + offset); - + } free(old); } } @@ -763,7 +824,10 @@ connectDBStart(PGconn *conn) } #ifdef HAVE_UNIX_SOCKETS else - conn->raddr_len = UNIXSOCK_PATH(conn->raddr.un, portno); + { + UNIXSOCK_PATH(conn->raddr.un, portno, conn->pgunixsocket); + conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un); + } #endif @@ -842,7 +906,8 @@ connectDBStart(PGconn *conn) conn->pghost ? conn->pghost : "localhost", (family == AF_INET) ? "TCP/IP port" : "Unix socket", - conn->pgport); + (family == AF_UNIX && conn->pgunixsocket) ? + conn->pgunixsocket : conn->pgport); goto connect_errReturn; } } @@ -1143,7 +1208,8 @@ keep_going: /* We will come back to here until there conn->pghost ? conn->pghost : "localhost", (conn->raddr.sa.sa_family == AF_INET) ? "TCP/IP port" : "Unix socket", - conn->pgport); + (conn->raddr.sa.sa_family == AF_UNIX && conn->pgunixsocket) ? + conn->pgunixsocket : conn->pgport); goto error_return; } @@ -1819,6 +1885,8 @@ freePGconn(PGconn *conn) free(conn->pghostaddr); if (conn->pgport) free(conn->pgport); + if (conn->pgunixsocket) + free(conn->pgunixsocket); if (conn->pgtty) free(conn->pgtty); if (conn->pgoptions) @@ -2528,6 +2596,14 @@ PQport(const PGconn *conn) return conn->pgport; } +char * +PQunixsocket(const PGconn *conn) +{ + if (!conn) + return (char *) NULL; + return conn->pgunixsocket; +} + char * PQtty(const PGconn *conn) { diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h index cfca198460..0d064e1a67 100644 --- a/src/interfaces/libpq/libpq-fe.h +++ b/src/interfaces/libpq/libpq-fe.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: libpq-fe.h,v 1.67 2000/08/30 14:54:23 momjian Exp $ + * $Id: libpq-fe.h,v 1.68 2000/11/13 15:18:15 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -217,6 +217,7 @@ extern "C" extern char *PQpass(const PGconn *conn); extern char *PQhost(const PGconn *conn); extern char *PQport(const PGconn *conn); + extern char *PQunixsocket(const PGconn *conn); extern char *PQtty(const PGconn *conn); extern char *PQoptions(const PGconn *conn); extern ConnStatusType PQstatus(const PGconn *conn); diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index c640b6df9f..a7c6acb952 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: libpq-int.h,v 1.27 2000/08/30 14:54:24 momjian Exp $ + * $Id: libpq-int.h,v 1.28 2000/11/13 15:18:15 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -203,6 +203,8 @@ struct pg_conn * numbers-and-dots notation. Takes * precedence over above. */ char *pgport; /* the server's communication port */ + char *pgunixsocket; /* the Unix-domain socket that the server is listening on; + * if NULL, uses a default constructed from pgport */ char *pgtty; /* tty on which the backend messages is * displayed (NOT ACTUALLY USED???) */ char *pgoptions; /* options to start the backend with */ diff --git a/src/interfaces/libpq/libpqdll.def b/src/interfaces/libpq/libpqdll.def index 32b0fa6ec3..7cf3bbc0a4 100644 --- a/src/interfaces/libpq/libpqdll.def +++ b/src/interfaces/libpq/libpqdll.def @@ -79,3 +79,4 @@ EXPORTS destroyPQExpBuffer @ 76 createPQExpBuffer @ 77 PQconninfoFree @ 78 + PQunixsocket @ 79 -- GitLab