1 /*-------------------------------------------------------------------------
4 * functions related to setting up a connection to the backend
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.59 1998/01/26 01:42:28 scrappy Exp $
12 *-------------------------------------------------------------------------
16 #include <sys/types.h>
17 #include <sys/socket.h>
25 #include <netinet/in.h>
26 #include <netinet/tcp.h>
29 #include <ctype.h> /* for isspace() */
33 #include "fe-connect.h"
44 /* use a local version instead of the one found in pqpacket.c */
45 static ConnStatusType connectDB(PGconn *conn);
47 static void freePGconn(PGconn *conn);
48 static void closePGconn(PGconn *conn);
49 static int conninfo_parse(const char *conninfo, char *errorMessage);
50 static char *conninfo_getval(char *keyword);
51 static void conninfo_free(void);
52 void PQsetenv(PGconn *conn);
54 #define NOTIFYLIST_INITIAL_SIZE 10
55 #define NOTIFYLIST_GROWBY 10
59 * Definition of the conninfo parameters and their fallback resources.
60 * If Environment-Var and Compiled-in are specified as NULL, no
61 * fallback is available. If after all no value can be determined
62 * for an option, an error is returned.
64 * The values for dbname and user are treated special in conninfo_parse.
65 * If the Compiled-in resource is specified as a NULL value, the
66 * user is determined by fe_getauthname() and for dbname the user
69 * The Label and Disp-Char entries are provided for applications that
70 * want to use PQconndefaults() to create a generic database connection
71 * dialog. Disp-Char is defined as follows:
72 * "" Normal input field
75 static PQconninfoOption PQconninfoOptions[] = {
76 /* ----------------------------------------------------------------- */
77 /* Option-name Environment-Var Compiled-in Current value */
79 /* ----------------- --------------- --------------- --------------- */
80 /* "authtype" is ignored as it is no longer used. */
81 {"authtype", "PGAUTHTYPE", DefaultAuthtype, NULL,
82 "Database-Authtype", "", 20},
84 {"user", "PGUSER", NULL, NULL,
85 "Database-User", "", 20},
87 {"password", "PGPASSWORD", DefaultPassword, NULL,
88 "Database-Password", "", 20},
90 {"dbname", "PGDATABASE", NULL, NULL,
91 "Database-Name", "", 20},
93 {"host", "PGHOST", NULL, NULL,
94 "Database-Host", "", 40},
96 {"port", "PGPORT", DEF_PGPORT, NULL,
97 "Database-Port", "", 6},
99 {"tty", "PGTTY", DefaultTty, NULL,
100 "Backend-Debug-TTY", "D", 40},
102 {"options", "PGOPTIONS", DefaultOption, NULL,
103 "Backend-Debug-Options", "D", 40},
104 /* ----------------- --------------- --------------- --------------- */
105 {NULL, NULL, NULL, NULL,
109 struct EnvironmentOptions
113 } EnvironmentOptions[] =
116 /* common user-interface settings */
117 { "PGDATESTYLE", "datestyle" },
118 { "PGTZ", "timezone" },
120 /* internal performance-related settings */
121 { "PGCOSTHEAP", "cost_heap" },
122 { "PGCOSTINDEX", "cost_index" },
123 { "PGRPLANS", "r_plans" },
124 { "PGGEQO", "geqo" },
131 * establishes a connection to a postgres backend through the postmaster
132 * using connection information in a string.
134 * The conninfo string is a list of
138 * definitions. Value might be a single value containing no whitespaces
139 * or a single quoted string. If a single quote should appear everywhere
140 * in the value, it must be escaped with a backslash like \'
142 * Returns a PGconn* which is needed for all subsequent libpq calls
143 * if the status field of the connection returned is CONNECTION_BAD,
144 * then some fields may be null'ed out instead of having valid values
148 PQconnectdb(const char *conninfo)
151 char errorMessage[ERROR_MSG_LENGTH];
154 * Allocate memory for the conn structure
157 conn = (PGconn *) malloc(sizeof(PGconn));
161 "FATAL: PQsetdb() -- unable to allocate memory for a PGconn");
162 return (PGconn *) NULL;
164 MemSet((char *) conn, 0, sizeof(PGconn));
167 * Parse the conninfo string and get the fallback resources
170 if (conninfo_parse(conninfo, errorMessage) < 0)
172 conn->status = CONNECTION_BAD;
173 strcpy(conn->errorMessage, errorMessage);
179 * Setup the conn structure
182 conn->lobjfuncs = (PGlobjfuncs *) NULL;
185 conn->Pfdebug = NULL;
186 conn->notifyList = DLNewList();
188 tmp = conninfo_getval("host");
189 conn->pghost = tmp ? strdup(tmp) : NULL;
190 tmp = conninfo_getval("port");
191 conn->pgport = tmp ? strdup(tmp) : NULL;
192 tmp = conninfo_getval("tty");
193 conn->pgtty = tmp ? strdup(tmp) : NULL;
194 tmp = conninfo_getval("options");
195 conn->pgoptions = tmp ? strdup(tmp) : NULL;
196 tmp = conninfo_getval("user");
197 conn->pguser = tmp ? strdup(tmp) : NULL;
198 tmp = conninfo_getval("password");
199 conn->pgpass = tmp ? strdup(tmp) : NULL;
200 tmp = conninfo_getval("dbname");
201 conn->dbName = tmp ? strdup(tmp) : NULL;
204 * Free the connection info - all is in conn now
210 * Connect to the database
213 conn->status = connectDB(conn);
214 if (conn->status == CONNECTION_OK)
219 * Send a blank query to make sure everything works; in
220 * particular, that the database exists.
222 res = PQexec(conn, " ");
223 if (res == NULL || res->resultStatus != PGRES_EMPTY_QUERY)
225 /* PQexec has put error message in conn->errorMessage */
239 * Parse an empty string like PQconnectdb() would do and return the
240 * address of the connection options structure. Using this function
241 * an application might determine all possible options and their
242 * current default values.
248 char errorMessage[ERROR_MSG_LENGTH];
250 conninfo_parse("", errorMessage);
251 return PQconninfoOptions;
257 * establishes a connection to a postgres backend through the postmaster
258 * at the specified host and port.
260 * returns a PGconn* which is needed for all subsequent libpq calls
261 * if the status field of the connection returned is CONNECTION_BAD,
262 * then some fields may be null'ed out instead of having valid values
264 * Uses these environment variables:
266 * PGHOST identifies host to which to connect if <pghost> argument
267 * is NULL or a null string.
269 * PGPORT identifies TCP port to which to connect if <pgport> argument
270 * is NULL or a null string.
272 * PGTTY identifies tty to which to send messages if <pgtty> argument
273 * is NULL or a null string.
275 * PGOPTIONS identifies connection options if <pgoptions> argument is
276 * NULL or a null string.
278 * PGUSER Postgres username to associate with the connection.
280 * PGPASSWORD The user's password.
282 * PGDATABASE name of database to which to connect if <pgdatabase>
283 * argument is NULL or a null string
285 * None of the above need be defined. There are defaults for all of them.
287 * To support "delimited identifiers" for database names, only convert
288 * the database name to lower case if it is not surrounded by double quotes.
289 * Otherwise, strip the double quotes but leave the reset of the string intact.
290 * - thomas 1997-11-08
295 PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd)
299 char errorMessage[ERROR_MSG_LENGTH];
301 /* An error message from some service we call. */
304 /* We encountered an error that prevents successful completion */
307 conn = (PGconn *) malloc(sizeof(PGconn));
311 "FATAL: PQsetdb() -- unable to allocate memory for a PGconn");
314 conn->lobjfuncs = (PGlobjfuncs *) NULL;
317 conn->Pfdebug = NULL;
318 conn->notifyList = DLNewList();
320 if ((pghost == NULL) || pghost[0] == '\0')
323 if ((tmp = getenv("PGHOST")) != NULL)
324 conn->pghost = strdup(tmp);
327 conn->pghost = strdup(pghost);
329 if ((pgport == NULL) || pgport[0] == '\0')
331 if ((tmp = getenv("PGPORT")) == NULL)
333 conn->pgport = strdup(tmp);
336 conn->pgport = strdup(pgport);
338 if ((pgtty == NULL) || pgtty[0] == '\0')
340 if ((tmp = getenv("PGTTY")) == NULL)
342 conn->pgtty = strdup(tmp);
345 conn->pgtty = strdup(pgtty);
347 if ((pgoptions == NULL) || pgoptions[0] == '\0')
349 if ((tmp = getenv("PGOPTIONS")) == NULL)
351 conn->pgoptions = strdup(tmp);
354 conn->pgoptions = strdup(pgoptions);
359 conn->pguser = strdup(login);
361 else if ((tmp = getenv("PGUSER")) != NULL)
364 conn->pguser = strdup(tmp);
368 tmp = fe_getauthname(errorMessage);
372 sprintf(conn->errorMessage,
373 "FATAL: PQsetdb: Unable to determine a Postgres username!\n");
384 conn->pgpass = strdup(pwd);
386 else if ((tmp = getenv("PGPASSWORD")) != NULL)
388 conn->pgpass = strdup(tmp);
391 conn->pgpass = strdup(DefaultPassword);
395 if ((((tmp = (char *) dbName) != NULL) && (dbName[0] != '\0'))
396 || ((tmp = getenv("PGDATABASE"))))
397 conn->dbName = strdup(tmp);
399 conn->dbName = strdup(conn->pguser);
402 * if the database name is surrounded by double-quotes,
403 * then don't convert case
405 if (*conn->dbName == '"')
407 strcpy(conn->dbName, conn->dbName + 1);
408 *(conn->dbName + strlen(conn->dbName) - 1) = '\0';
411 for (i = 0; conn->dbName[i]; i++)
412 if (isupper(conn->dbName[i]))
413 conn->dbName[i] = tolower(conn->dbName[i]);
419 conn->status = CONNECTION_BAD;
422 conn->status = connectDB(conn);
423 /* Puts message in conn->errorMessage */
424 if (conn->status == CONNECTION_OK)
429 * Send a blank query to make sure everything works; in
430 * particular, that the database exists.
432 res = PQexec(conn, " ");
433 if (res == NULL || res->resultStatus != PGRES_EMPTY_QUERY)
435 /* PQexec has put error message in conn->errorMessage */
449 * make a connection to the backend so it is ready to receive queries.
450 * return CONNECTION_OK if successful, CONNECTION_BAD if not.
453 static ConnStatusType
454 connectDB(PGconn *conn)
460 int laddrlen = sizeof(SockAddr);
466 * Initialize the startup packet.
469 MemSet((char *)&sp, 0, sizeof (StartupPacket));
471 sp.protoVersion = (ProtocolVersion)htonl(PG_PROTOCOL_LATEST);
473 strncpy(sp.user, conn->pguser, SM_USER);
474 strncpy(sp.database, conn->dbName, SM_DATABASE);
475 strncpy(sp.tty, conn->pgtty, SM_TTY);
478 strncpy(sp.options, conn->pgoptions, SM_OPTIONS);
481 * Open a connection to postmaster/backend.
484 if (conn->pghost != NULL)
486 hp = gethostbyname(conn->pghost);
487 if ((hp == NULL) || (hp->h_addrtype != AF_INET))
489 (void) sprintf(conn->errorMessage,
490 "connectDB() -- unknown hostname: %s\n",
492 goto connect_errReturn;
498 MemSet((char *) &port->raddr, 0, sizeof(port->raddr));
500 portno = atoi(conn->pgport);
501 family = (conn->pghost != NULL) ? AF_INET : AF_UNIX;
502 conn->raddr.sa.sa_family = family;
503 if (family == AF_INET)
505 memmove((char *) &(conn->raddr.in.sin_addr),
508 conn->raddr.in.sin_port = htons((unsigned short) (portno));
509 len = sizeof(struct sockaddr_in);
513 len = UNIXSOCK_PATH(conn->raddr.un, portno);
515 /* connect to the server */
516 if ((conn->sock = socket(family, SOCK_STREAM, 0)) < 0)
518 (void) sprintf(conn->errorMessage,
519 "connectDB() -- socket() failed: errno=%d\n%s\n",
520 errno, strerror(errno));
521 goto connect_errReturn;
523 if (connect(conn->sock, &conn->raddr.sa, len) < 0)
525 (void) sprintf(conn->errorMessage,
526 "connectDB() failed: Is the postmaster running and accepting%s connections at '%s' on port '%s'?\n",
527 conn->pghost ? " TCP/IP(with -i)" : "",
528 conn->pghost ? conn->pghost : "UNIX Socket",
530 goto connect_errReturn;
532 if (family == AF_INET)
537 pe = getprotobyname("TCP");
540 (void) sprintf(conn->errorMessage,
541 "connectDB(): getprotobyname failed\n");
542 goto connect_errReturn;
544 if (setsockopt(conn->sock, pe->p_proto, TCP_NODELAY,
545 &on, sizeof(on)) < 0)
547 (void) sprintf(conn->errorMessage,
548 "connectDB(): setsockopt failed\n");
549 goto connect_errReturn;
553 /* fill in the client address */
554 if (getsockname(conn->sock, &conn->laddr.sa, &laddrlen) < 0)
556 (void) sprintf(conn->errorMessage,
557 "connectDB() -- getsockname() failed: errno=%d\n%s\n",
558 errno, strerror(errno));
559 goto connect_errReturn;
562 /* set up the socket file descriptors */
563 conn->Pfout = fdopen(conn->sock, "w");
564 conn->Pfin = fdopen(dup(conn->sock), "r");
565 if ((conn->Pfout == NULL) || (conn->Pfin == NULL))
567 (void) sprintf(conn->errorMessage,
568 "connectDB() -- fdopen() failed: errno=%d\n%s\n",
569 errno, strerror(errno));
570 goto connect_errReturn;
573 /* Send the startup packet. */
575 if (packetSend(conn, (char *)&sp, sizeof(StartupPacket)) != STATUS_OK)
577 sprintf(conn->errorMessage,
578 "connectDB() -- couldn't send complete packet: errno=%d\n%s\n", errno, strerror(errno));
579 goto connect_errReturn;
583 * Get the response from the backend, either an error message or an
584 * authentication request.
591 if ((beresp = pqGetc(conn->Pfin, conn->Pfdebug)) == EOF)
593 (void)sprintf(conn->errorMessage,
594 "connectDB() -- error getting authentication request\n");
596 goto connect_errReturn;
603 pqGets(conn->errorMessage, sizeof (conn->errorMessage),
604 conn->Pfin, conn->Pfdebug);
606 goto connect_errReturn;
609 /* Check it was an authentication request. */
613 (void)sprintf(conn->errorMessage,
614 "connectDB() -- expected authentication request\n");
616 goto connect_errReturn;
619 /* Get the type of request. */
621 if (pqGetInt((int *)&areq, 4, conn->Pfin, conn->Pfdebug))
623 (void)sprintf(conn->errorMessage,
624 "connectDB() -- error getting authentication request type\n");
626 goto connect_errReturn;
629 /* Get the password salt if there is one. */
631 if (areq == AUTH_REQ_CRYPT &&
632 pqGetnchar(conn->salt, sizeof (conn->salt),
633 conn->Pfin, conn->Pfdebug))
635 (void)sprintf(conn->errorMessage,
636 "connectDB() -- error getting password salt\n");
638 goto connect_errReturn;
642 /* Respond to the request. */
644 if (fe_sendauth(areq, conn, conn->pghost, conn->pgpass,
645 conn->errorMessage) != STATUS_OK)
646 goto connect_errReturn;
648 while (areq != AUTH_REQ_OK);
650 /* free the password so it's not hanging out in memory forever */
651 if (conn->pgpass != NULL)
656 return CONNECTION_OK;
659 return CONNECTION_BAD;
664 PQsetenv(PGconn *conn)
666 struct EnvironmentOptions *eo;
667 char setQuery[80]; /* mjl: size okay? XXX */
669 for (eo = EnvironmentOptions; eo->envName; eo++)
673 if ((val = getenv(eo->envName)))
677 if (strcasecmp(val, "default") == 0)
678 sprintf(setQuery, "SET %s = %.60s", eo->pgName, val);
680 sprintf(setQuery, "SET %s = '%.60s'", eo->pgName, val);
682 printf("Use environment variable %s to send %s\n", eo->envName, setQuery);
684 res = PQexec(conn, setQuery);
685 PQclear(res); /* Don't care? */
692 * - free the PGconn data structure
696 freePGconn(PGconn *conn)
705 free(conn->pgoptions);
712 if (conn->notifyList)
713 DLFreeList(conn->notifyList);
719 - properly close a connection to the backend
722 closePGconn(PGconn *conn)
724 /* GH: What to do for !USE_POSIX_SIGNALS ? */
725 #if defined(USE_POSIX_SIGNALS)
726 struct sigaction ignore_action;
729 * This is used as a constant, but not declared as such because the
730 * sigaction structure is defined differently on different systems
732 struct sigaction oldaction;
735 * If connection is already gone, that's cool. No reason for kernel
736 * to kill us when we try to write to it. So ignore SIGPIPE signals.
738 ignore_action.sa_handler = SIG_IGN;
739 sigemptyset(&ignore_action.sa_mask);
740 ignore_action.sa_flags = 0;
741 sigaction(SIGPIPE, (struct sigaction *) & ignore_action, &oldaction);
743 fputs("X\0", conn->Pfout);
745 sigaction(SIGPIPE, &oldaction, NULL);
747 signal(SIGPIPE, SIG_IGN);
748 fputs("X\0", conn->Pfout);
750 signal(SIGPIPE, SIG_DFL);
757 fclose(conn->Pfdebug);
758 conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just
764 properly close a connection to the backend
765 also frees the PGconn data structure so it shouldn't be re-used
769 PQfinish(PGconn *conn)
773 fprintf(stderr, "PQfinish() -- pointer to PGconn is null\n");
777 if (conn->status == CONNECTION_OK)
784 resets the connection to the backend
785 closes the existing connection and makes a new one
788 PQreset(PGconn *conn)
792 fprintf(stderr, "PQreset() -- pointer to PGconn is null\n");
797 conn->status = connectDB(conn);
804 this is just like PacketSend(), defined in backend/libpq/pqpacket.c
805 but we define it here to avoid linking in all of libpq.a
807 * packetSend -- send a single-packet message.
809 * RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise.
810 * SIDE_EFFECTS: may block.
813 packetSend(PGconn *conn,
817 /* Send the total packet size. */
819 if (pqPutInt(4 + len, 4, conn->Pfout, conn->Pfdebug))
822 /* Send the packet itself. */
824 if (pqPutnchar(buf, len, conn->Pfout, conn->Pfdebug))
827 pqFlush(conn->Pfout, conn->Pfdebug);
834 * Conninfo parser routine
838 conninfo_parse(const char *conninfo, char *errorMessage)
846 PQconninfoOption *option;
847 char errortmp[ERROR_MSG_LENGTH];
851 if ((buf = strdup(conninfo)) == NULL)
854 "FATAL: cannot allocate memory for copy of conninfo string\n");
861 /* Skip blanks before the parameter name */
868 /* Get the parameter name */
892 /* Check that there is a following '=' */
895 sprintf(errorMessage,
896 "ERROR: PQconnectdb() - Missing '=' after '%s' in conninfo\n",
903 /* Skip blanks after the '=' */
948 sprintf(errorMessage,
949 "ERROR: PQconnectdb() - unterminated quoted string in conninfo\n");
973 * Now we have the name and the value. Search
974 * for the param record.
977 for (option = PQconninfoOptions; option->keyword != NULL; option++)
979 if (!strcmp(option->keyword, pname))
984 if (option->keyword == NULL)
986 sprintf(errorMessage,
987 "ERROR: PQconnectdb() - unknown option '%s'\n",
997 option->val = strdup(pval);
1003 * Get the fallback resources for parameters not specified
1004 * in the conninfo string.
1007 for (option = PQconninfoOptions; option->keyword != NULL; option++)
1009 if (option->val != NULL)
1010 continue; /* Value was in conninfo */
1013 * Try to get the environment variable fallback
1016 if (option->environ != NULL)
1018 if ((tmp = getenv(option->environ)) != NULL)
1020 option->val = strdup(tmp);
1026 * No environment variable specified or this one isn't set -
1030 if (option->compiled != NULL)
1032 option->val = strdup(option->compiled);
1037 * Special handling for user
1040 if (!strcmp(option->keyword, "user"))
1042 tmp = fe_getauthname(errortmp);
1045 option->val = strdup(tmp);
1050 * Special handling for dbname
1053 if (!strcmp(option->keyword, "dbname"))
1055 tmp = conninfo_getval("user");
1058 option->val = strdup(tmp);
1068 conninfo_getval(char *keyword)
1070 PQconninfoOption *option;
1072 for (option = PQconninfoOptions; option->keyword != NULL; option++)
1074 if (!strcmp(option->keyword, keyword))
1087 PQconninfoOption *option;
1089 for (option = PQconninfoOptions; option->keyword != NULL; option++)
1091 if (option->val != NULL)
1099 /* =========== accessor functions for PGconn ========= */
1105 fprintf(stderr, "PQdb() -- pointer to PGconn is null\n");
1106 return (char *) NULL;
1108 return conn->dbName;
1112 PQuser(PGconn *conn)
1116 fprintf(stderr, "PQuser() -- pointer to PGconn is null\n");
1117 return (char *) NULL;
1119 return conn->pguser;
1123 PQhost(PGconn *conn)
1127 fprintf(stderr, "PQhost() -- pointer to PGconn is null\n");
1128 return (char *) NULL;
1131 return conn->pghost;
1135 PQoptions(PGconn *conn)
1139 fprintf(stderr, "PQoptions() -- pointer to PGconn is null\n");
1140 return (char *) NULL;
1142 return conn->pgoptions;
1150 fprintf(stderr, "PQtty() -- pointer to PGconn is null\n");
1151 return (char *) NULL;
1157 PQport(PGconn *conn)
1161 fprintf(stderr, "PQport() -- pointer to PGconn is null\n");
1162 return (char *) NULL;
1164 return conn->pgport;
1168 PQstatus(PGconn *conn)
1172 fprintf(stderr, "PQstatus() -- pointer to PGconn is null\n");
1173 return CONNECTION_BAD;
1175 return conn->status;
1179 PQerrorMessage(PGconn *conn)
1183 fprintf(stderr, "PQerrorMessage() -- pointer to PGconn is null\n");
1184 return (char *) NULL;
1186 return conn->errorMessage;
1190 PQtrace(PGconn *conn, FILE *debug_port)
1193 conn->status == CONNECTION_BAD)
1198 conn->Pfdebug = debug_port;
1202 PQuntrace(PGconn *conn)
1205 conn->status == CONNECTION_BAD)
1211 fflush(conn->Pfdebug);
1212 conn->Pfdebug = NULL;