Re: [PATCHES] PostgreSQL virtual hosting support - Mailing list pgsql-hackers
From | Bruce Momjian |
---|---|
Subject | Re: [PATCHES] PostgreSQL virtual hosting support |
Date | |
Msg-id | 200010110121.VAA21524@candle.pha.pa.us Whole thread Raw |
Responses |
Re: Re: [PATCHES] PostgreSQL virtual hosting support
Re: Re: [PATCHES] PostgreSQL virtual hosting support Re: Re: [PATCHES] PostgreSQL virtual hosting support |
List | pgsql-hackers |
I am tempted to apply this. This is the second person who asked for binding to a single port. The patch looks quite complete, with doc changes. It appears to be a thorough job. Any objections? > Your name : David MacKenzie > Your email address : djm@web.us.uu.net > > > System Configuration > --------------------- > Architecture (example: Intel Pentium) : Intel x86 > > Operating System (example: Linux 2.0.26 ELF) : BSD/OS 4.0.1 > > PostgreSQL version (example: PostgreSQL-7.0): PostgreSQL-7.0.2 > > Compiler used (example: gcc 2.8.0) : gcc version 2.7.2.1 > > > Please enter a FULL description of your problem: > ------------------------------------------------ > > 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. > > Index: doc/src/sgml/layout.sgml > *** doc/src/sgml/layout.sgml 2000/06/30 21:15:36 1.1 > --- doc/src/sgml/layout.sgml 2000/07/02 03:56:05 1.2 > *************** > *** 55,61 **** > For example, if the database server machine is a remote machine, you > will need to set the <envar>PGHOST</envar> environment variable to the name > of the database server machine. The environment variable > ! <envar>PGPORT</envar> 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 <Application>postmaster</Application>, > you must go back and make sure that your > --- 55,62 ---- > For example, if the database server machine is a remote machine, you > will need to set the <envar>PGHOST</envar> environment variable to the name > of the database server machine. The environment variable > ! <envar>PGPORT</envar> or <envar>PGUNIXSOCKET</envar> 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 <Application>postmaster</Application>, > you must go back and make sure that your > Index: doc/src/sgml/libpq++.sgml > *** doc/src/sgml/libpq++.sgml 2000/06/30 21:15:36 1.1 > --- doc/src/sgml/libpq++.sgml 2000/07/02 03:56:05 1.2 > *************** > *** 93,98 **** > --- 93,105 ---- > </listitem> > <listitem> > <para> > + <envar>PGUNIXSOCKET</envar> sets the full Unix domain socket > + file name for communicating with the <productname>Postgres</productname> > + backend. > + </para> > + </listitem> > + <listitem> > + <para> > <envar>PGDATABASE</envar> sets the default > <productname>Postgres</productname> database name. > </para> > Index: doc/src/sgml/libpq.sgml > *** doc/src/sgml/libpq.sgml 2000/06/30 21:15:36 1.1 > --- doc/src/sgml/libpq.sgml 2000/07/02 03:56:05 1.2 > *************** > *** 134,139 **** > --- 134,148 ---- > </varlistentry> > > <varlistentry> > + <term><literal>unixsocket</literal></term> > + <listitem> > + <para> > + Full path to Unix-domain socket file to connect to at the server host. > + </para> > + </listitem> > + </varlistentry> > + > + <varlistentry> > <term><literal>dbname</literal></term> > <listitem> > <para> > *************** > *** 545,550 **** > --- 554,569 ---- > > <listitem> > <para> > + <function>PQunixsocket</function> > + Returns the name of the Unix-domain socket of the connection. > + <synopsis> > + char *PQunixsocket(const PGconn *conn) > + </synopsis> > + </para> > + </listitem> > + > + <listitem> > + <para> > <function>PQtty</function> > Returns the debug tty of the connection. > <synopsis> > *************** > *** 1772,1777 **** > --- 1791,1803 ---- > <envar>PGHOST</envar> sets the default server name. > If a non-zero-length string is specified, TCP/IP communication is used. > Without a host name, libpq will connect using a local Unix domain socket. > + </para> > + </listitem> > + <listitem> > + <para> > + <envar>PGPORT</envar> sets the default port or local Unix domain socket > + file extension for communicating with the <productname>Postgres</productname> > + backend. > </para> > </listitem> > <listitem> > Index: doc/src/sgml/start.sgml > *** doc/src/sgml/start.sgml 2000/06/30 21:15:37 1.1 > --- doc/src/sgml/start.sgml 2000/07/02 03:56:05 1.2 > *************** > *** 110,117 **** > will need to set the <acronym>PGHOST</acronym> environment > variable to the name > of the database server machine. The environment variable > ! <acronym>PGPORT</acronym> 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 <application>postmaster</application>, > you should immediately consult your site administrator to make > --- 110,117 ---- > will need to set the <acronym>PGHOST</acronym> environment > variable to the name > of the database server machine. The environment variable > ! <acronym>PGPORT</acronym> or <acronym>PGUNIXSOCKET</acronym> 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 <application>postmaster</application>, > you should immediately consult your site administrator to make > Index: doc/src/sgml/ref/createdb.sgml > *** doc/src/sgml/ref/createdb.sgml 2000/06/30 21:15:37 1.1 > --- doc/src/sgml/ref/createdb.sgml 2000/07/04 04:46:45 1.2 > *************** > *** 58,63 **** > --- 58,75 ---- > </listitem> > </varlistentry> > > + <varlistentry> > + <term>-k, --unixsocket <replaceable class="parameter">path</replaceable></term> > + <listitem> > + <para> > + Specifies the Unix-domain socket on which the > + <application>postmaster</application> is running. > + Without this option, the socket is created in <filename>/tmp</filename> > + based on the port number. > + </para> > + </listitem> > + </varlistentry> > + > <varlistentry> > <term>-U, --username <replaceable class="parameter">username</replaceable></term> > <listitem> > Index: doc/src/sgml/ref/createlang.sgml > *** doc/src/sgml/ref/createlang.sgml 2000/06/30 21:15:37 1.1 > --- doc/src/sgml/ref/createlang.sgml 2000/07/04 04:46:45 1.2 > *************** > *** 96,101 **** > --- 96,113 ---- > </listitem> > </varlistentry> > > + <varlistentry> > + <term>-k, --unixsocket <replaceable class="parameter">path</replaceable></term> > + <listitem> > + <para> > + Specifies the Unix-domain socket on which the > + <application>postmaster</application> is running. > + Without this option, the socket is created in <filename>/tmp</filename> > + based on the port number. > + </para> > + </listitem> > + </varlistentry> > + > <varlistentry> > <term>-U, --username <replaceable class="parameter">username</replaceable></term> > <listitem> > Index: doc/src/sgml/ref/createuser.sgml > *** doc/src/sgml/ref/createuser.sgml 2000/06/30 21:15:37 1.1 > --- doc/src/sgml/ref/createuser.sgml 2000/07/04 04:46:45 1.2 > *************** > *** 59,64 **** > --- 59,76 ---- > </listitem> > </varlistentry> > > + <varlistentry> > + <term>-k, --unixsocket <replaceable class="parameter">path</replaceable></term> > + <listitem> > + <para> > + Specifies the Unix-domain socket on which the > + <application>postmaster</application> is running. > + Without this option, the socket is created in <filename>/tmp</filename> > + based on the port number. > + </para> > + </listitem> > + </varlistentry> > + > <varlistentry> > <term>-e, --echo</term> > <listitem> > Index: doc/src/sgml/ref/dropdb.sgml > *** doc/src/sgml/ref/dropdb.sgml 2000/06/30 21:15:38 1.1 > --- doc/src/sgml/ref/dropdb.sgml 2000/07/04 04:46:45 1.2 > *************** > *** 58,63 **** > --- 58,75 ---- > </listitem> > </varlistentry> > > + <varlistentry> > + <term>-k, --unixsocket <replaceable class="parameter">path</replaceable></term> > + <listitem> > + <para> > + Specifies the Unix-domain socket on which the > + <application>postmaster</application> is running. > + Without this option, the socket is created in <filename>/tmp</filename> > + based on the port number. > + </para> > + </listitem> > + </varlistentry> > + > <varlistentry> > <term>-U, --username <replaceable class="parameter">username</replaceable></term> > <listitem> > Index: doc/src/sgml/ref/droplang.sgml > *** doc/src/sgml/ref/droplang.sgml 2000/06/30 21:15:38 1.1 > --- doc/src/sgml/ref/droplang.sgml 2000/07/04 04:46:45 1.2 > *************** > *** 96,101 **** > --- 96,113 ---- > </listitem> > </varlistentry> > > + <varlistentry> > + <term>-k, --unixsocket <replaceable class="parameter">path</replaceable></term> > + <listitem> > + <para> > + Specifies the Unix-domain socket on which the > + <application>postmaster</application> is running. > + Without this option, the socket is created in <filename>/tmp</filename> > + based on the port number. > + </para> > + </listitem> > + </varlistentry> > + > <varlistentry> > <term>-U, --username <replaceable class="parameter">username</replaceable></term> > <listitem> > Index: doc/src/sgml/ref/dropuser.sgml > *** doc/src/sgml/ref/dropuser.sgml 2000/06/30 21:15:38 1.1 > --- doc/src/sgml/ref/dropuser.sgml 2000/07/04 04:46:45 1.2 > *************** > *** 58,63 **** > --- 58,75 ---- > </listitem> > </varlistentry> > > + <varlistentry> > + <term>-k, --unixsocket <replaceable class="parameter">path</replaceable></term> > + <listitem> > + <para> > + Specifies the Unix-domain socket on which the > + <application>postmaster</application> is running. > + Without this option, the socket is created in <filename>/tmp</filename> > + based on the port number. > + </para> > + </listitem> > + </varlistentry> > + > <varlistentry> > <term>-e, --echo</term> > <listitem> > Index: doc/src/sgml/ref/pg_dump.sgml > *** doc/src/sgml/ref/pg_dump.sgml 2000/06/30 21:15:38 1.1 > --- doc/src/sgml/ref/pg_dump.sgml 2000/07/01 18:41:22 1.2 > *************** > *** 24,30 **** > </refsynopsisdivinfo> > <synopsis> > pg_dump [ <replaceable class="parameter">dbname</replaceable> ] > ! pg_dump [ -h <replaceable class="parameter">host</replaceable> ] [ -p <replaceable class="parameter">port</replaceable>] > [ -t <replaceable class="parameter">table</replaceable> ] > [ -a ] [ -c ] [ -d ] [ -D ] [ -i ] [ -n ] [ -N ] > [ -o ] [ -s ] [ -u ] [ -v ] [ -x ] > --- 24,32 ---- > </refsynopsisdivinfo> > <synopsis> > pg_dump [ <replaceable class="parameter">dbname</replaceable> ] > ! pg_dump [ -h <replaceable class="parameter">host</replaceable> ] > ! [ -k <replaceable class="parameter">path</replaceable> ] > ! [ -p <replaceable class="parameter">port</replaceable> ] > [ -t <replaceable class="parameter">table</replaceable> ] > [ -a ] [ -c ] [ -d ] [ -D ] [ -i ] [ -n ] [ -N ] > [ -o ] [ -s ] [ -u ] [ -v ] [ -x ] > *************** > *** 200,205 **** > --- 202,222 ---- > <application>postmaster</application> > is running. Defaults to using a local Unix domain socket > rather than an IP connection.. > + </para> > + </listitem> > + </varlistentry> > + > + <varlistentry> > + <term>-k <replaceable class="parameter">path</replaceable></term> > + <listitem> > + <para> > + Specifies the local Unix domain socket file path > + on which the <application>postmaster</application> > + is listening for connections. > + Without this option, the socket path name defaults to > + the value of the <envar>PGUNIXSOCKET</envar> environment > + variable (if set), otherwise it is constructed > + from the port number. > </para> > </listitem> > </varlistentry> > Index: doc/src/sgml/ref/pg_dumpall.sgml > *** doc/src/sgml/ref/pg_dumpall.sgml 2000/06/30 21:15:38 1.1 > --- doc/src/sgml/ref/pg_dumpall.sgml 2000/07/01 18:41:22 1.2 > *************** > *** 24,30 **** > </refsynopsisdivinfo> > <synopsis> > pg_dumpall > ! pg_dumpall [ -h <replaceable class="parameter">host</replaceable> ] [ -p <replaceable class="parameter">port</replaceable>] [ -a ] [ -d ] [ -D ] [ -O ] [ -s ] [ -u ] [ -v ] [ -x ] > </synopsis> > > <refsect2 id="R2-APP-PG-DUMPALL-1"> > --- 24,33 ---- > </refsynopsisdivinfo> > <synopsis> > pg_dumpall > ! pg_dumpall [ -h <replaceable class="parameter">host</replaceable> ] > ! [ -k <replaceable class="parameter">path</replaceable> ] > ! [ -p <replaceable class="parameter">port</replaceable> ] > ! [ -a ] [ -d ] [ -D ] [ -O ] [ -s ] [ -u ] [ -v ] [ -x ] > </synopsis> > > <refsect2 id="R2-APP-PG-DUMPALL-1"> > *************** > *** 137,142 **** > --- 140,160 ---- > <application>postmaster</application> > is running. Defaults to using a local Unix domain socket > rather than an IP connection.. > + </para> > + </listitem> > + </varlistentry> > + > + <varlistentry> > + <term>-k <replaceable class="parameter">path</replaceable></term> > + <listitem> > + <para> > + Specifies the local Unix domain socket file path > + on which the <application>postmaster</application> > + is listening for connections. > + Without this option, the socket path name defaults to > + the value of the <envar>PGUNIXSOCKET</envar> environment > + variable (if set), otherwise it is constructed > + from the port number. > </para> > </listitem> > </varlistentry> > Index: doc/src/sgml/ref/postmaster.sgml > *** doc/src/sgml/ref/postmaster.sgml 2000/06/30 21:15:38 1.1 > --- doc/src/sgml/ref/postmaster.sgml 2000/07/06 07:48:31 1.7 > *************** > *** 24,30 **** > </refsynopsisdivinfo> > <synopsis> > postmaster [ -B <replaceable class="parameter">nBuffers</replaceable> ] [ -D <replaceable class="parameter">DataDir</replaceable>] [ -N <replaceable class="parameter">maxBackends</replaceable> ] [ -S ] > ! [ -d <replaceable class="parameter">DebugLevel</replaceable> ] [ -i ] [ -l ] > [ -o <replaceable class="parameter">BackendOptions</replaceable> ] [ -p <replaceable class="parameter">port</replaceable>] [ -n | -s ] > </synopsis> > > --- 24,32 ---- > </refsynopsisdivinfo> > <synopsis> > postmaster [ -B <replaceable class="parameter">nBuffers</replaceable> ] [ -D <replaceable class="parameter">DataDir</replaceable>] [ -N <replaceable class="parameter">maxBackends</replaceable> ] [ -S ] > ! [ -d <replaceable class="parameter">DebugLevel</replaceable> ] > ! [ -h <replaceable class="parameter">hostname</replaceable> ] [ -i ] > ! [ -k <replaceable class="parameter">path</replaceable> ] [ -l ] > [ -o <replaceable class="parameter">BackendOptions</replaceable> ] [ -p <replaceable class="parameter">port</replaceable>] [ -n | -s ] > </synopsis> > > *************** > *** 124,129 **** > --- 126,161 ---- > </varlistentry> > > <varlistentry> > + <term>-h <replaceable class="parameter">hostName</replaceable></term> > + <listitem> > + <para> > + Specifies the TCP/IP hostname or address > + on which the <application>postmaster</application> > + is to listen for connections from frontend applications. Defaults to > + the value of the > + <envar>PGHOST</envar> > + environment variable, or if <envar>PGHOST</envar> > + is not set, then defaults to "all", meaning listen on all configured addresses > + (including localhost). > + </para> > + <para> > + If you use a hostname or address other than "all", do not try to run > + multiple instances of <application>postmaster</application> 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 <application>postmaster</application> instances are > + listening must be distinct in the two last octets. > + </para> > + <para> > + If you do use "all" (the default), then each instance must listen on a > + different port (via -p or <envar>PGPORT</envar>). And, of course, do > + not try to use both approaches on one host. > + </para> > + </listitem> > + </varlistentry> > + > + <varlistentry> > <term>-i</term> > <listitem> > <para> > *************** > *** 135,140 **** > --- 167,201 ---- > </varlistentry> > > <varlistentry> > + <term>-k <replaceable class="parameter">path</replaceable></term> > + <listitem> > + <para> > + Specifies the local Unix domain socket path name > + on which the <application>postmaster</application> > + is to listen for connections from frontend applications. Defaults to > + the value of the > + <envar>PGUNIXSOCKET</envar> > + environment variable, or if <envar>PGUNIXSOCKET</envar> > + is not set, then defaults to a file in <filename>/tmp</filename> > + constructed from the port number. > + </para> > + <para> > + 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 <filename>pg_hba.conf</filename>. > + If you specify a socket path other than the > + default then all frontend applications (including > + <application>psql</application>) must specify the same > + socket path using either command-line options or > + <envar>PGUNIXSOCKET</envar>. > + </para> > + </listitem> > + </varlistentry> > + > + <varlistentry> > <term>-l</term> > <listitem> > <para> > Index: doc/src/sgml/ref/psql-ref.sgml > *** doc/src/sgml/ref/psql-ref.sgml 2000/06/30 21:15:38 1.1 > --- doc/src/sgml/ref/psql-ref.sgml 2000/07/02 03:56:05 1.3 > *************** > *** 1329,1334 **** > --- 1329,1347 ---- > > > <varlistentry> > + <term>-k, --unixsocket <replaceable class="parameter">path</replaceable></term> > + <listitem> > + <para> > + Specifies the Unix-domain socket on which the > + <application>postmaster</application> is running. > + Without this option, the socket is created in <filename>/tmp</filename> > + based on the port number. > + </para> > + </listitem> > + </varlistentry> > + > + > + <varlistentry> > <term>-H, --html</term> > <listitem> > <para> > Index: doc/src/sgml/ref/vacuumdb.sgml > *** doc/src/sgml/ref/vacuumdb.sgml 2000/06/30 21:15:38 1.1 > --- doc/src/sgml/ref/vacuumdb.sgml 2000/07/04 04:46:45 1.2 > *************** > *** 24,30 **** > </refsynopsisdivinfo> > <synopsis> > vacuumdb [ <replaceable class="parameter">options</replaceable> ] [ --analyze | -z ] > ! [ --alldb | -a ] [ --verbose | -v ] > [ --table '<replaceable class="parameter">table</replaceable> [ ( <replaceable class="parameter">column</replaceable>[,...] ) ]' ] [ [-d] <replaceable class="parameter">dbname</replaceable> ] > </synopsis> > > --- 24,30 ---- > </refsynopsisdivinfo> > <synopsis> > vacuumdb [ <replaceable class="parameter">options</replaceable> ] [ --analyze | -z ] > ! [ --all | -a ] [ --verbose | -v ] > [ --table '<replaceable class="parameter">table</replaceable> [ ( <replaceable class="parameter">column</replaceable>[,...] ) ]' ] [ [-d] <replaceable class="parameter">dbname</replaceable> ] > </synopsis> > > *************** > *** 128,133 **** > --- 128,145 ---- > </para> > </listitem> > </varlistentry> > + > + <varlistentry> > + <term>-k, --unixsocket <replaceable class="parameter">path</replaceable></term> > + <listitem> > + <para> > + Specifies the Unix-domain socket on which the > + <application>postmaster</application> is running. > + Without this option, the socket is created in <filename>/tmp</filename> > + based on the port number. > + </para> > + </listitem> > + </varlistentry> > > <varlistentry> > <term>-U <replaceable class="parameter">username</replaceable></term> > Index: src/backend/libpq/pqcomm.c > *** src/backend/libpq/pqcomm.c 2000/06/30 21:15:40 1.1 > --- src/backend/libpq/pqcomm.c 2000/07/01 18:50:46 1.3 > *************** > *** 42,47 **** > --- 42,48 ---- > * StreamConnection - Create new connection with client > * StreamClose - Close a client/backend connection > * pq_getport - return the PGPORT setting > + * pq_getunixsocket - return the PGUNIXSOCKET setting > * pq_init - initialize libpq at backend startup > * pq_close - shutdown libpq at backend exit > * > *************** > *** 134,139 **** > --- 135,151 ---- > } > > /* -------------------------------- > + * pq_getunixsocket - return the PGUNIXSOCKET setting. > + * If NULL, default to computing it based on the port. > + * -------------------------------- > + */ > + char * > + pq_getunixsocket(void) > + { > + return getenv("PGUNIXSOCKET"); > + } > + > + /* -------------------------------- > * pq_close - shutdown libpq at backend exit > * > * Note: in a standalone backend MyProcPort will be null, > *************** > *** 177,189 **** > /* > * StreamServerPort -- open a sock stream "listening" port. > * > ! * This initializes the Postmaster's connection-accepting port. > * > * RETURNS: STATUS_OK or STATUS_ERROR > */ > > int > ! StreamServerPort(char *hostName, unsigned short portName, int *fdP) > { > SockAddr saddr; > int fd, > --- 189,205 ---- > /* > * StreamServerPort -- open a sock stream "listening" port. > * > ! * This initializes the Postmaster's connection-accepting port fdP. > ! * If hostName is "any", listen on all configured IP addresses. > ! * If hostName is NULL, listen on a Unix-domain socket instead of TCP; > ! * if unixSocketName is NULL, a default path (constructed in UNIX_SOCK_PATH > ! * in include/libpq/pqcomm.h) based on portName is used. > * > * RETURNS: STATUS_OK or STATUS_ERROR > */ > > int > ! StreamServerPort(char *hostName, unsigned short portNumber, char *unixSocketName, int *fdP) > { > SockAddr saddr; > int fd, > *************** > *** 227,233 **** > saddr.sa.sa_family = family; > if (family == AF_UNIX) > { > ! len = UNIXSOCK_PATH(saddr.un, portName); > strcpy(sock_path, saddr.un.sun_path); > > /* > --- 243,250 ---- > saddr.sa.sa_family = family; > if (family == AF_UNIX) > { > ! UNIXSOCK_PATH(saddr.un, portNumber, unixSocketName); > ! len = UNIXSOCK_LEN(saddr.un); > strcpy(sock_path, saddr.un.sun_path); > > /* > *************** > *** 259,267 **** > } > else > { > ! saddr.in.sin_addr.s_addr = htonl(INADDR_ANY); > ! saddr.in.sin_port = htons(portName); > ! len = sizeof(struct sockaddr_in); > } > err = bind(fd, &saddr.sa, len); > if (err < 0) > --- 276,305 ---- > } > else > { > ! /* TCP/IP socket */ > ! if (!strcmp(hostName, "all")) /* like for databases in pg_hba.conf. */ > ! 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(portNumber); > ! len = sizeof(struct sockaddr_in); > } > err = bind(fd, &saddr.sa, len); > if (err < 0) > Index: src/backend/postmaster/postmaster.c > *** src/backend/postmaster/postmaster.c 2000/06/30 21:15:42 1.1 > --- src/backend/postmaster/postmaster.c 2000/07/06 07:38:21 1.5 > *************** > *** 136,143 **** > /* list of ports associated with still open, but incomplete connections */ > static Dllist *PortList; > > ! static unsigned short PostPortName = 0; > > /* > * This is a boolean indicating that there is at least one backend that > * is accessing the current shared memory and semaphores. Between the > --- 136,150 ---- > /* list of ports associated with still open, but incomplete connections */ > static Dllist *PortList; > > ! /* Hostname of interface to listen on, or 'any'. */ > ! static char *HostName = NULL; > > + /* TCP/IP port number to listen on. Also used to default the Unix-domain socket name. */ > + static unsigned short PostPortNumber = 0; > + > + /* Override of the default Unix-domain socket name to listen on, if non-NULL. */ > + static char *UnixSocketName = NULL; > + > /* > * This is a boolean indicating that there is at least one backend that > * is accessing the current shared memory and semaphores. Between the > *************** > *** 274,280 **** > static void SignalChildren(SIGNAL_ARGS); > static int CountChildren(void); > static int > ! SetOptsFile(char *progname, int port, char *datadir, > int assert, int nbuf, char *execfile, > int debuglvl, int netserver, > #ifdef USE_SSL > --- 281,287 ---- > static void SignalChildren(SIGNAL_ARGS); > static int CountChildren(void); > static int > ! SetOptsFile(char *progname, char *hostname, int port, char *unixsocket, char *datadir, > int assert, int nbuf, char *execfile, > int debuglvl, int netserver, > #ifdef USE_SSL > *************** > *** 370,380 **** > { > extern int NBuffers; /* from buffer/bufmgr.c */ > int opt; > - char *hostName; > int status; > int silentflag = 0; > bool DataDirOK; /* We have a usable PGDATA value */ > - char hostbuf[MAXHOSTNAMELEN]; > int nonblank_argc; > char original_extraoptions[MAXPGPATH]; > > --- 377,385 ---- > *************** > *** 431,449 **** > */ > umask((mode_t) 0077); > > - if (!(hostName = getenv("PGHOST"))) > - { > - if (gethostname(hostbuf, MAXHOSTNAMELEN) < 0) > - strcpy(hostbuf, "localhost"); > - hostName = hostbuf; > - } > - > MyProcPid = getpid(); > DataDir = getenv("PGDATA"); /* default value */ > > opterr = 0; > IgnoreSystemIndexes(false); > ! while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:d:ilm:MN:no:p:Ss")) != EOF) > { > switch (opt) > { > --- 436,447 ---- > */ > umask((mode_t) 0077); > > MyProcPid = getpid(); > DataDir = getenv("PGDATA"); /* default value */ > > opterr = 0; > IgnoreSystemIndexes(false); > ! while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:d:h:ik:lm:MN:no:p:Ss")) != EOF) > { > switch (opt) > { > *************** > *** 498,506 **** > --- 496,511 ---- > DebugLvl = atoi(optarg); > pg_options[TRACE_VERBOSE] = DebugLvl; > 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': > SecureNetServer = true; > *************** > *** 545,551 **** > break; > case 'p': > /* Set PGPORT by hand. */ > ! PostPortName = (unsigned short) atoi(optarg); > break; > case 'S': > > --- 550,556 ---- > break; > case 'p': > /* Set PGPORT by hand. */ > ! PostPortNumber = (unsigned short) atoi(optarg); > break; > case 'S': > > *************** > *** 577,584 **** > /* > * Select default values for switches where needed > */ > ! if (PostPortName == 0) > ! PostPortName = (unsigned short) pq_getport(); > > /* > * Check for invalid combinations of switches > --- 582,603 ---- > /* > * Select default values for switches where needed > */ > ! if (HostName == NULL) > ! { > ! if (!(HostName = getenv("PGHOST"))) > ! { > ! HostName = "any"; > ! } > ! } > ! else if (!NetServer) > ! { > ! fprintf(stderr, "%s: -h requires -i.\n", progname); > ! exit(1); > ! } > ! if (PostPortNumber == 0) > ! PostPortNumber = (unsigned short) pq_getport(); > ! if (UnixSocketName == NULL) > ! UnixSocketName = pq_getunixsocket(); > > /* > * Check for invalid combinations of switches > *************** > *** 622,628 **** > > if (NetServer) > { > ! status = StreamServerPort(hostName, PostPortName, &ServerSock_INET); > if (status != STATUS_OK) > { > fprintf(stderr, "%s: cannot create INET stream port\n", > --- 641,647 ---- > > if (NetServer) > { > ! status = StreamServerPort(HostName, PostPortNumber, NULL, &ServerSock_INET); > if (status != STATUS_OK) > { > fprintf(stderr, "%s: cannot create INET stream port\n", > *************** > *** 632,638 **** > } > > #if !defined(__CYGWIN32__) && !defined(__QNX__) > ! status = StreamServerPort(NULL, PostPortName, &ServerSock_UNIX); > if (status != STATUS_OK) > { > fprintf(stderr, "%s: cannot create UNIX stream port\n", > --- 651,657 ---- > } > > #if !defined(__CYGWIN32__) && !defined(__QNX__) > ! status = StreamServerPort(NULL, PostPortNumber, UnixSocketName, &ServerSock_UNIX); > if (status != STATUS_OK) > { > fprintf(stderr, "%s: cannot create UNIX stream port\n", > *************** > *** 642,648 **** > #endif > /* set up shared memory and semaphores */ > EnableMemoryContext(TRUE); > ! reset_shared(PostPortName); > > /* > * Initialize the list of active backends. This list is only used for > --- 661,667 ---- > #endif > /* set up shared memory and semaphores */ > EnableMemoryContext(TRUE); > ! reset_shared(PostPortNumber); > > /* > * Initialize the list of active backends. This list is only used for > *************** > *** 664,670 **** > { > if (SetOptsFile( > progname, /* postmaster executable file */ > ! PostPortName, /* port number */ > DataDir, /* PGDATA */ > assert_enabled, /* whether -A is specified > * or not */ > --- 683,691 ---- > { > if (SetOptsFile( > progname, /* postmaster executable file */ > ! HostName, /* IP address to bind to */ > ! PostPortNumber, /* port number */ > ! UnixSocketName, /* PGUNIXSOCKET */ > DataDir, /* PGDATA */ > assert_enabled, /* whether -A is specified > * or not */ > *************** > *** 753,759 **** > { > if (SetOptsFile( > progname, /* postmaster executable file */ > ! PostPortName, /* port number */ > DataDir, /* PGDATA */ > assert_enabled, /* whether -A is specified > * or not */ > --- 774,782 ---- > { > if (SetOptsFile( > progname, /* postmaster executable file */ > ! HostName, /* IP address to bind to */ > ! PostPortNumber, /* port number */ > ! UnixSocketName, /* PGUNIXSOCKET */ > DataDir, /* PGDATA */ > assert_enabled, /* whether -A is specified > * or not */ > *************** > *** 837,843 **** > --- 860,868 ---- > fprintf(stderr, "\t-a system\tuse this authentication system\n"); > fprintf(stderr, "\t-b backend\tuse a specific backend server executable\n"); > fprintf(stderr, "\t-d [1-5]\tset debugging level\n"); > + fprintf(stderr, "\t-h hostname\tspecify hostname or IP address or 'any' for postmaster to listen on (also use -i)\n"); > fprintf(stderr, "\t-i \t\tlisten on TCP/IP sockets as well as Unix domain socket\n"); > + fprintf(stderr, "\t-k path\tspecify Unix-domain socket name for postmaster to listen on\n"); > #ifdef USE_SSL > fprintf(stderr, " \t-l \t\tfor TCP/IP sockets, listen only on SSL connections\n"); > #endif > *************** > *** 1318,1328 **** > --- 1343,1417 ---- > } > > /* > + * 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(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 of "any". > + * > + * If HostName is not "any", 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 (strcmp(HostName, "any")) > + port = get_host_port(); > + > ipc_key = port * 1000 + shmem_seq * 100; > CreateSharedMemoryAndSemaphores(ipc_key, MaxBackends); > shmem_seq += 1; > *************** > *** 1540,1546 **** > ctime(&tnow)); > fflush(stderr); > shmem_exit(0); > ! reset_shared(PostPortName); > StartupPID = StartupDataBase(); > return; > } > --- 1629,1635 ---- > ctime(&tnow)); > fflush(stderr); > shmem_exit(0); > ! reset_shared(PostPortNumber); > StartupPID = StartupDataBase(); > return; > } > *************** > *** 1720,1726 **** > * Set up the necessary environment variables for the backend This > * should really be some sort of message.... > */ > ! sprintf(envEntry[0], "POSTPORT=%d", PostPortName); > putenv(envEntry[0]); > sprintf(envEntry[1], "POSTID=%d", NextBackendTag); > putenv(envEntry[1]); > --- 1809,1815 ---- > * Set up the necessary environment variables for the backend This > * should really be some sort of message.... > */ > ! sprintf(envEntry[0], "POSTPORT=%d", PostPortNumber); > putenv(envEntry[0]); > sprintf(envEntry[1], "POSTID=%d", NextBackendTag); > putenv(envEntry[1]); > *************** > *** 2174,2180 **** > for (i = 0; i < 4; ++i) > MemSet(ssEntry[i], 0, 2 * ARGV_SIZE); > > ! sprintf(ssEntry[0], "POSTPORT=%d", PostPortName); > putenv(ssEntry[0]); > sprintf(ssEntry[1], "POSTID=%d", NextBackendTag); > putenv(ssEntry[1]); > --- 2263,2269 ---- > for (i = 0; i < 4; ++i) > MemSet(ssEntry[i], 0, 2 * ARGV_SIZE); > > ! sprintf(ssEntry[0], "POSTPORT=%d", PostPortNumber); > putenv(ssEntry[0]); > sprintf(ssEntry[1], "POSTID=%d", NextBackendTag); > putenv(ssEntry[1]); > *************** > *** 2254,2260 **** > * Create the opts file > */ > static int > ! SetOptsFile(char *progname, int port, char *datadir, > int assert, int nbuf, char *execfile, > int debuglvl, int netserver, > #ifdef USE_SSL > --- 2343,2349 ---- > * Create the opts file > */ > static int > ! SetOptsFile(char *progname, char *hostname, int port, char *unixsocket, char *datadir, > int assert, int nbuf, char *execfile, > int debuglvl, int netserver, > #ifdef USE_SSL > *************** > *** 2279,2284 **** > --- 2368,2383 ---- > return (-1); > } > snprintf(opts, sizeof(opts), "%s\n-p %d\n-D %s\n", progname, port, datadir); > + if (netserver) > + { > + sprintf(buf, "-h %s\n", hostname); > + strcat(opts, buf); > + } > + if (unixsocket) > + { > + sprintf(buf, "-k %s\n", unixsocket); > + strcat(opts, buf); > + } > if (assert) > { > sprintf(buf, "-A %d\n", assert); > Index: src/bin/pg_dump/pg_dump.c > *** src/bin/pg_dump/pg_dump.c 2000/06/30 21:15:44 1.1 > --- src/bin/pg_dump/pg_dump.c 2000/07/01 18:41:22 1.2 > *************** > *** 140,145 **** > --- 140,146 ---- > " -D, --attribute-inserts dump data as INSERT commands with attribute names\n" > " -h, --host <hostname> server host name\n" > " -i, --ignore-version proceed when database version != pg_dump version\n" > + " -k, --unixsocket <path> 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" > *************** > *** 158,163 **** > --- 159,165 ---- > " -D dump data as INSERT commands with attribute names\n" > " -h <hostname> server host name\n" > " -i proceed when database version != pg_dump version\n" > + " -k <path> 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" > *************** > *** 579,584 **** > --- 581,587 ---- > const char *dbname = NULL; > const char *pghost = NULL; > const char *pgport = NULL; > + const char *pgunixsocket = NULL; > char *tablename = NULL; > bool oids = false; > TableInfo *tblinfo; > *************** > *** 598,603 **** > --- 601,607 ---- > {"attribute-inserts", no_argument, NULL, 'D'}, > {"host", required_argument, NULL, 'h'}, > {"ignore-version", no_argument, NULL, 'i'}, > + {"unixsocket", required_argument, NULL, 'k'}, > {"no-quotes", no_argument, NULL, 'n'}, > {"quotes", no_argument, NULL, 'N'}, > {"oids", no_argument, NULL, 'o'}, > *************** > *** 662,667 **** > --- 666,674 ---- > case 'i': /* ignore database version mismatch */ > 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; > *************** > *** 782,788 **** > exit(1); > } > > - /* g_conn = PQsetdb(pghost, pgport, NULL, NULL, dbname); */ > if (pghost != NULL) > { > sprintf(tmp_string, "host=%s ", pghost); > --- 789,794 ---- > *************** > *** 791,796 **** > --- 797,807 ---- > if (pgport != NULL) > { > sprintf(tmp_string, "port=%s ", pgport); > + strcat(connect_string, tmp_string); > + } > + if (pgunixsocket != NULL) > + { > + sprintf(tmp_string, "unixsocket=%s ", pgunixsocket); > strcat(connect_string, tmp_string); > } > if (dbname != NULL) > Index: src/bin/psql/command.c > *** src/bin/psql/command.c 2000/06/30 21:15:46 1.1 > --- src/bin/psql/command.c 2000/07/01 18:20:40 1.2 > *************** > *** 1199,1204 **** > --- 1199,1205 ---- > 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) */ > *************** > *** 1228,1233 **** > --- 1229,1235 ---- > 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); > > *************** > *** 1303,1308 **** > --- 1305,1311 ---- > 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)); > Index: src/bin/psql/command.h > Index: src/bin/psql/common.c > *** src/bin/psql/common.c 2000/06/30 21:15:46 1.1 > --- src/bin/psql/common.c 2000/07/01 18:20:40 1.2 > *************** > *** 330,335 **** > --- 330,336 ---- > 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; > *************** > *** 509,514 **** > --- 510,516 ---- > 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; > Index: src/bin/psql/help.c > *** src/bin/psql/help.c 2000/06/30 21:15:46 1.1 > --- src/bin/psql/help.c 2000/07/01 18:20:40 1.2 > *************** > *** 103,108 **** > --- 103,118 ---- > puts(")"); > > puts(" -H HTML table output mode (-P format=html)"); > + > + /* Display default Unix-domain socket */ > + env = getenv("PGUNIXSOCKET"); > + printf(" -k <path> 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 <filename> Send query output to filename (or |pipe)"); > Index: src/bin/psql/prompt.c > *** src/bin/psql/prompt.c 2000/06/30 21:15:46 1.1 > --- src/bin/psql/prompt.c 2000/07/01 18:20:40 1.2 > *************** > *** 189,194 **** > --- 189,199 ---- > 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) > Index: src/bin/psql/prompt.h > Index: src/bin/psql/settings.h > Index: src/bin/psql/startup.c > *** src/bin/psql/startup.c 2000/06/30 21:15:46 1.1 > --- src/bin/psql/startup.c 2000/07/01 18:20:40 1.2 > *************** > *** 66,71 **** > --- 66,72 ---- > char *dbname; > char *host; > char *port; > + char *unixsocket; > char *username; > enum _actions action; > char *action_string; > *************** > *** 158,163 **** > --- 159,165 ---- > 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); > *************** > *** 202,207 **** > --- 204,210 ---- > 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 > *************** > *** 313,318 **** > --- 316,322 ---- > {"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'}, > *************** > *** 346,359 **** > 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) > #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) > #endif /* not HAVE_GETOPT_LONG */ > { > switch (c) > --- 350,363 ---- > memset(options, 0, sizeof *options); > > #ifdef HAVE_GETOPT_LONG > ! 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:Hk:no:p:P:qRsStT:uU:v:VWxX?-")) != -1) > #endif /* not HAVE_GETOPT_LONG */ > { > switch (c) > *************** > *** 398,403 **** > --- 402,410 ---- > break; > case 'l': > options->action = ACT_LIST_DB; > + break; > + case 'k': > + options->unixsocket = optarg; > break; > case 'n': > options->no_readline = true; > Index: src/bin/scripts/createdb > *** src/bin/scripts/createdb 2000/06/30 21:15:46 1.1 > --- src/bin/scripts/createdb 2000/07/04 04:46:45 1.2 > *************** > *** 50,55 **** > --- 50,64 ---- > --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,119 **** > --- 123,129 ---- > 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" > Index: src/bin/scripts/createlang.sh > *** src/bin/scripts/createlang.sh 2000/06/30 21:15:46 1.1 > --- src/bin/scripts/createlang.sh 2000/07/04 04:46:45 1.2 > *************** > *** 65,70 **** > --- 65,79 ---- > --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,131 **** > --- 135,141 ---- > 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" > Index: src/bin/scripts/createuser > *** src/bin/scripts/createuser 2000/06/30 21:15:46 1.1 > --- src/bin/scripts/createuser 2000/07/04 04:46:45 1.2 > *************** > *** 63,68 **** > --- 63,77 ---- > --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,140 **** > --- 144,150 ---- > 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" > Index: src/bin/scripts/dropdb > *** src/bin/scripts/dropdb 2000/06/30 21:15:46 1.1 > --- src/bin/scripts/dropdb 2000/07/04 04:46:45 1.2 > *************** > *** 59,64 **** > --- 59,73 ---- > --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,108 **** > --- 112,118 ---- > 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" > Index: src/bin/scripts/droplang > *** src/bin/scripts/droplang 2000/06/30 21:15:46 1.1 > --- src/bin/scripts/droplang 2000/07/04 04:46:45 1.2 > *************** > *** 65,70 **** > --- 65,79 ---- > --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,118 **** > --- 122,128 ---- > 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" > Index: src/bin/scripts/dropuser > *** src/bin/scripts/dropuser 2000/06/30 21:15:46 1.1 > --- src/bin/scripts/dropuser 2000/07/04 04:46:45 1.2 > *************** > *** 59,64 **** > --- 59,73 ---- > --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,110 **** > --- 114,120 ---- > 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" > Index: src/bin/scripts/vacuumdb > *** src/bin/scripts/vacuumdb 2000/06/30 21:15:46 1.1 > --- src/bin/scripts/vacuumdb 2000/07/04 04:46:45 1.2 > *************** > *** 52,57 **** > --- 52,66 ---- > --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,126 **** > --- 130,136 ---- > 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" > Index: src/include/libpq/libpq.h > *** src/include/libpq/libpq.h 2000/06/30 21:15:47 1.1 > --- src/include/libpq/libpq.h 2000/07/01 18:20:40 1.2 > *************** > *** 236,246 **** > /* > * prototypes for functions in pqcomm.c > */ > ! extern int StreamServerPort(char *hostName, unsigned short portName, int *fdP); > extern int StreamConnection(int server_fd, Port *port); > extern void StreamClose(int sock); > extern void pq_init(void); > extern int pq_getport(void); > extern void pq_close(void); > extern int pq_getbytes(char *s, size_t len); > extern int pq_getstring(StringInfo s); > --- 236,247 ---- > /* > * prototypes for functions in pqcomm.c > */ > ! extern int StreamServerPort(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); > extern int pq_getport(void); > + extern char *pq_getunixsocket(void); > extern void pq_close(void); > extern int pq_getbytes(char *s, size_t len); > extern int pq_getstring(StringInfo s); > Index: src/include/libpq/password.h > Index: src/include/libpq/pqcomm.h > *** src/include/libpq/pqcomm.h 2000/06/30 21:15:47 1.1 > --- src/include/libpq/pqcomm.h 2000/07/01 18:59:33 1.6 > *************** > *** 42,53 **** > /* 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))) > #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)) > #endif > > /* > --- 42,56 ---- > /* Configure the UNIX socket address for the well known port. */ > > #if defined(SUN_LEN) > ! #define UNIXSOCK_PATH(sun,port,defpath) \ > ! (defpath ? (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,defpath) \ > ! (defpath ? (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 > > /* > Index: src/interfaces/libpq/fe-connect.c > *** src/interfaces/libpq/fe-connect.c 2000/06/30 21:15:51 1.1 > --- src/interfaces/libpq/fe-connect.c 2000/07/01 18:50:47 1.3 > *************** > *** 125,130 **** > --- 125,133 ---- > {"port", "PGPORT", DEF_PGPORT, NULL, > "Database-Port", "", 6}, > > + {"unixsocket", "PGUNIXSOCKET", NULL, NULL, > + "Unix-Socket", "", 80}, > + > {"tty", "PGTTY", DefaultTty, NULL, > "Backend-Debug-TTY", "D", 40}, > > *************** > *** 293,298 **** > --- 296,303 ---- > 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"); > *************** > *** 369,374 **** > --- 374,382 ---- > * PGPORT identifies TCP port to which to connect if <pgport> 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 <pgtty> argument > * is NULL or a null string. > * > *************** > *** 422,427 **** > --- 430,439 ---- > else > conn->pgport = strdup(pgport); > > + conn->pgunixsocket = getenv("PGUNIXSOCKET"); > + if (conn->pgunixsocket) > + conn->pgunixsocket = strdup(conn->pgunixsocket); > + > if ((pgtty == NULL) || pgtty[0] == '\0') > { > if ((tmp = getenv("PGTTY")) == NULL) > *************** > *** 489,501 **** > > /* > * update_db_info - > ! * get all additional infos out of dbName > * > */ > static int > update_db_info(PGconn *conn) > { > ! char *tmp, > *old = conn->dbName; > > if (strchr(conn->dbName, '@') != NULL) > --- 501,513 ---- > > /* > * update_db_info - > ! * get all additional info out of dbName > * > */ > static int > update_db_info(PGconn *conn) > { > ! char *tmp, *tmp2, > *old = conn->dbName; > > if (strchr(conn->dbName, '@') != NULL) > *************** > *** 504,509 **** > --- 516,523 ---- > tmp = strrchr(conn->dbName, ':'); > if (tmp != NULL) /* port number given */ > { > + if (conn->pgport) > + free(conn->pgport); > conn->pgport = strdup(tmp + 1); > *tmp = '\0'; > } > *************** > *** 511,516 **** > --- 525,532 ---- > tmp = strrchr(conn->dbName, '@'); > if (tmp != NULL) /* host name given */ > { > + if (conn->pghost) > + free(conn->pghost); > conn->pghost = strdup(tmp + 1); > *tmp = '\0'; > } > *************** > *** 537,549 **** > > /* > * new style: > ! * <tcp|unix>:postgresql://server[:port][/dbname][?options] > */ > offset += strlen("postgresql://"); > > tmp = strrchr(conn->dbName + offset, '?'); > if (tmp != NULL) /* options given */ > { > conn->pgoptions = strdup(tmp + 1); > *tmp = '\0'; > } > --- 553,567 ---- > > /* > * new style: > ! * <tcp|unix>: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'; > } > *************** > *** 551,576 **** > tmp = strrchr(conn->dbName + offset, '/'); > if (tmp != NULL) /* database name given */ > { > conn->dbName = strdup(tmp + 1); > *tmp = '\0'; > } > else > { > if ((tmp = getenv("PGDATABASE")) != NULL) > conn->dbName = strdup(tmp); > else if (conn->pguser) > conn->dbName = strdup(conn->pguser); > } > > tmp = strrchr(old + offset, ':'); > ! if (tmp != NULL) /* port number given */ > { > - conn->pgport = strdup(tmp + 1); > *tmp = '\0'; > } > > if (strncmp(old, "unix:", 5) == 0) > { > conn->pghost = NULL; > if (strcmp(old + offset, "localhost") != 0) > { > --- 569,630 ---- > 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 or Unix socket path given */ > { > *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) > { > *************** > *** 582,589 **** > } > } > else > conn->pghost = strdup(old + offset); > ! > free(old); > } > } > --- 636,646 ---- > } > } > else > + { > + if (conn->pghost) > + free(conn->pghost); > conn->pghost = strdup(old + offset); > ! } > free(old); > } > } > *************** > *** 743,749 **** > } > #if !defined(WIN32) && !defined(__CYGWIN32__) > else > ! conn->raddr_len = UNIXSOCK_PATH(conn->raddr.un, portno); > #endif > > > --- 800,809 ---- > } > #if !defined(WIN32) && !defined(__CYGWIN32__) > else > ! { > ! UNIXSOCK_PATH(conn->raddr.un, portno, conn->pgunixsocket); > ! conn->raddr_len = UNIXSOCK_LEN(conn->raddr.un); > ! } > #endif > > > *************** > *** 892,898 **** > conn->pghost ? conn->pghost : "localhost", > (family == AF_INET) ? > "TCP/IP port" : "Unix socket", > ! conn->pgport); > goto connect_errReturn; > } > } > --- 952,959 ---- > conn->pghost ? conn->pghost : "localhost", > (family == AF_INET) ? > "TCP/IP port" : "Unix socket", > ! (family == AF_UNIX && conn->pgunixsocket) ? > ! conn->pgunixsocket : conn->pgport); > goto connect_errReturn; > } > } > *************** > *** 1123,1129 **** > conn->pghost ? conn->pghost : "localhost", > (conn->raddr.sa.sa_family == AF_INET) ? > "TCP/IP port" : "Unix socket", > ! conn->pgport); > goto error_return; > } > > --- 1184,1191 ---- > conn->pghost ? conn->pghost : "localhost", > (conn->raddr.sa.sa_family == AF_INET) ? > "TCP/IP port" : "Unix socket", > ! (conn->raddr.sa.sa_family == AF_UNIX && conn->pgunixsocket) ? > ! conn->pgunixsocket : conn->pgport); > goto error_return; > } > > *************** > *** 1799,1804 **** > --- 1861,1868 ---- > free(conn->pghostaddr); > if (conn->pgport) > free(conn->pgport); > + if (conn->pgunixsocket) > + free(conn->pgunixsocket); > if (conn->pgtty) > free(conn->pgtty); > if (conn->pgoptions) > *************** > *** 2383,2388 **** > --- 2447,2460 ---- > if (!conn) > return (char *) NULL; > return conn->pgport; > + } > + > + char * > + PQunixsocket(const PGconn *conn) > + { > + if (!conn) > + return (char *) NULL; > + return conn->pgunixsocket; > } > > char * > Index: src/interfaces/libpq/libpq-fe.h > *** src/interfaces/libpq/libpq-fe.h 2000/06/30 21:15:51 1.1 > --- src/interfaces/libpq/libpq-fe.h 2000/07/01 18:20:40 1.2 > *************** > *** 214,219 **** > --- 214,220 ---- > 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); > Index: src/interfaces/libpq/libpq-int.h > *** src/interfaces/libpq/libpq-int.h 2000/06/30 21:15:51 1.1 > --- src/interfaces/libpq/libpq-int.h 2000/07/01 18:20:40 1.2 > *************** > *** 202,207 **** > --- 202,209 ---- > * 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 */ > Index: src/interfaces/libpq/libpqdll.def > *** src/interfaces/libpq/libpqdll.def 2000/06/30 21:15:51 1.1 > --- src/interfaces/libpq/libpqdll.def 2000/07/01 18:20:40 1.2 > *************** > *** 79,81 **** > --- 79,82 ---- > destroyPQExpBuffer @ 76 > createPQExpBuffer @ 77 > PQconninfoFree @ 78 > + PQunixsocket @ 79 > -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 853-3000+ If your life is a hard drive, | 830 Blythe Avenue + Christ can be your backup. | Drexel Hill, Pennsylvania19026
pgsql-hackers by date: