diff options
Diffstat (limited to 'src/interfaces')
-rw-r--r-- | src/interfaces/libpgtcl/libpgtcl.h | 12 | ||||
-rw-r--r-- | src/interfaces/libpgtcl/pgtcl.c | 277 | ||||
-rw-r--r-- | src/interfaces/libpgtcl/pgtclCmds.c | 2054 | ||||
-rw-r--r-- | src/interfaces/libpgtcl/pgtclCmds.h | 134 | ||||
-rw-r--r-- | src/interfaces/libpgtcl/pgtclId.c | 260 | ||||
-rw-r--r-- | src/interfaces/libpgtcl/pgtclId.h | 24 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-auth.c | 763 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-auth.h | 34 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-connect.c | 1686 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-connect.h | 12 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-exec.c | 3014 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-lobj.c | 939 | ||||
-rw-r--r-- | src/interfaces/libpq/fe-misc.c | 227 | ||||
-rw-r--r-- | src/interfaces/libpq/libpq-fe.h | 503 | ||||
-rw-r--r-- | src/interfaces/libpq/pqsignal.c | 38 | ||||
-rw-r--r-- | src/interfaces/libpq/pqsignal.h | 12 |
16 files changed, 5353 insertions, 4636 deletions
diff --git a/src/interfaces/libpgtcl/libpgtcl.h b/src/interfaces/libpgtcl/libpgtcl.h index 7a5fa0364c1..4ee2848c991 100644 --- a/src/interfaces/libpgtcl/libpgtcl.h +++ b/src/interfaces/libpgtcl/libpgtcl.h @@ -1,12 +1,12 @@ /*------------------------------------------------------------------------- * * libpgtcl.h-- - * libpgtcl is a tcl package for front-ends to interface with pglite - * It's the tcl equivalent of the old libpq C interface. + * libpgtcl is a tcl package for front-ends to interface with pglite + * It's the tcl equivalent of the old libpq C interface. * * Copyright (c) 1994, Regents of the University of California * - * $Id: libpgtcl.h,v 1.2 1996/10/30 06:18:37 scrappy Exp $ + * $Id: libpgtcl.h,v 1.3 1997/09/07 05:03:06 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -16,7 +16,7 @@ #include "tcl.h" -extern int Pgtcl_Init (Tcl_Interp *interp); -extern int Pgtcl_SafeInit (Tcl_Interp *interp); +extern int Pgtcl_Init(Tcl_Interp * interp); +extern int Pgtcl_SafeInit(Tcl_Interp * interp); -#endif /* LIBPGTCL_H */ +#endif /* LIBPGTCL_H */ diff --git a/src/interfaces/libpgtcl/pgtcl.c b/src/interfaces/libpgtcl/pgtcl.c index 8df0c42105c..75c8ec5ddad 100644 --- a/src/interfaces/libpgtcl/pgtcl.c +++ b/src/interfaces/libpgtcl/pgtcl.c @@ -1,15 +1,15 @@ /*------------------------------------------------------------------------- * * pgtcl.c-- - * - * libpgtcl is a tcl package for front-ends to interface with pglite - * It's the tcl equivalent of the old libpq C interface. + * + * libpgtcl is a tcl package for front-ends to interface with pglite + * It's the tcl equivalent of the old libpq C interface. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtcl.c,v 1.7 1997/01/03 18:48:28 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtcl.c,v 1.8 1997/09/07 05:03:09 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -23,8 +23,8 @@ #include "pgtclId.h" /* - * Pgtcl_Init - * initialization package for the PGLITE Tcl package + * Pgtcl_Init + * initialization package for the PGLITE Tcl package * */ @@ -32,153 +32,154 @@ * Tidy up forgotten postgres connection at Tcl_Exit */ static void -Pgtcl_AtExit (ClientData cData) +Pgtcl_AtExit(ClientData cData) { - Pg_clientData *cd = (Pg_clientData *)cData; - Tcl_HashEntry *hent; - Tcl_HashSearch hsearch; - Pg_ConnectionId *connid; - PGconn *conn; - - while((hent = Tcl_FirstHashEntry(&(cd->dbh_hash), &hsearch)) != NULL) { - connid = (Pg_ConnectionId *)Tcl_GetHashValue(hent); - conn = connid->conn; - PgDelConnectionId(cd, connid->id); - PQfinish(conn); - } - - Tcl_DeleteHashTable(&(cd->dbh_hash)); - Tcl_DeleteHashTable(&(cd->res_hash)); - Tcl_DeleteHashTable(&(cd->notify_hash)); - - Tcl_DeleteExitHandler(Pgtcl_AtExit, cData); + Pg_clientData *cd = (Pg_clientData *) cData; + Tcl_HashEntry *hent; + Tcl_HashSearch hsearch; + Pg_ConnectionId *connid; + PGconn *conn; + + while ((hent = Tcl_FirstHashEntry(&(cd->dbh_hash), &hsearch)) != NULL) + { + connid = (Pg_ConnectionId *) Tcl_GetHashValue(hent); + conn = connid->conn; + PgDelConnectionId(cd, connid->id); + PQfinish(conn); + } + + Tcl_DeleteHashTable(&(cd->dbh_hash)); + Tcl_DeleteHashTable(&(cd->res_hash)); + Tcl_DeleteHashTable(&(cd->notify_hash)); + + Tcl_DeleteExitHandler(Pgtcl_AtExit, cData); } /* * Tidy up forgotten postgres connections on Interpreter deletion */ static void -Pgtcl_Shutdown (ClientData cData, Tcl_Interp *interp) +Pgtcl_Shutdown(ClientData cData, Tcl_Interp * interp) { - Pgtcl_AtExit(cData); + Pgtcl_AtExit(cData); } int -Pgtcl_Init (Tcl_Interp *interp) +Pgtcl_Init(Tcl_Interp * interp) { - Pg_clientData *cd; - - /* Create and initialize the client data area */ - cd = (Pg_clientData *)ckalloc(sizeof(Pg_clientData)); - Tcl_InitHashTable(&(cd->dbh_hash), TCL_STRING_KEYS); - Tcl_InitHashTable(&(cd->res_hash), TCL_STRING_KEYS); - Tcl_InitHashTable(&(cd->notify_hash), TCL_STRING_KEYS); - cd->dbh_count = 0L; - cd->res_count = 0L; - - /* Arrange for tidy up when interpreter is deleted or Tcl exits */ - Tcl_CallWhenDeleted(interp, Pgtcl_Shutdown, (ClientData)cd); - Tcl_CreateExitHandler(Pgtcl_AtExit, (ClientData)cd); - - /* register all pgtcl commands */ - Tcl_CreateCommand(interp, - "pg_conndefaults", - Pg_conndefaults, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_connect", - Pg_connect, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_disconnect", - Pg_disconnect, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_exec", - Pg_exec, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_select", - Pg_select, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_result", - Pg_result, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_lo_open", - Pg_lo_open, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_lo_close", - Pg_lo_close, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_lo_read", - Pg_lo_read, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_lo_write", - Pg_lo_write, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_lo_lseek", - Pg_lo_lseek, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_lo_creat", - Pg_lo_creat, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_lo_tell", - Pg_lo_tell, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_lo_unlink", - Pg_lo_unlink, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_lo_import", - Pg_lo_import, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_lo_export", - Pg_lo_export, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_listen", - Pg_listen, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_CreateCommand(interp, - "pg_notifies", - Pg_notifies, - (ClientData)cd, (Tcl_CmdDeleteProc*)NULL); - - Tcl_PkgProvide(interp, "Pgtcl", "1.0"); - - return TCL_OK; + Pg_clientData *cd; + + /* Create and initialize the client data area */ + cd = (Pg_clientData *) ckalloc(sizeof(Pg_clientData)); + Tcl_InitHashTable(&(cd->dbh_hash), TCL_STRING_KEYS); + Tcl_InitHashTable(&(cd->res_hash), TCL_STRING_KEYS); + Tcl_InitHashTable(&(cd->notify_hash), TCL_STRING_KEYS); + cd->dbh_count = 0L; + cd->res_count = 0L; + + /* Arrange for tidy up when interpreter is deleted or Tcl exits */ + Tcl_CallWhenDeleted(interp, Pgtcl_Shutdown, (ClientData) cd); + Tcl_CreateExitHandler(Pgtcl_AtExit, (ClientData) cd); + + /* register all pgtcl commands */ + Tcl_CreateCommand(interp, + "pg_conndefaults", + Pg_conndefaults, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_connect", + Pg_connect, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_disconnect", + Pg_disconnect, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_exec", + Pg_exec, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_select", + Pg_select, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_result", + Pg_result, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_lo_open", + Pg_lo_open, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_lo_close", + Pg_lo_close, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_lo_read", + Pg_lo_read, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_lo_write", + Pg_lo_write, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_lo_lseek", + Pg_lo_lseek, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_lo_creat", + Pg_lo_creat, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_lo_tell", + Pg_lo_tell, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_lo_unlink", + Pg_lo_unlink, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_lo_import", + Pg_lo_import, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_lo_export", + Pg_lo_export, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_listen", + Pg_listen, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_CreateCommand(interp, + "pg_notifies", + Pg_notifies, + (ClientData) cd, (Tcl_CmdDeleteProc *) NULL); + + Tcl_PkgProvide(interp, "Pgtcl", "1.0"); + + return TCL_OK; } int -Pgtcl_SafeInit (Tcl_Interp *interp) +Pgtcl_SafeInit(Tcl_Interp * interp) { - return Pgtcl_Init(interp); + return Pgtcl_Init(interp); } diff --git a/src/interfaces/libpgtcl/pgtclCmds.c b/src/interfaces/libpgtcl/pgtclCmds.c index 6ad9ca17673..834938487d4 100644 --- a/src/interfaces/libpgtcl/pgtclCmds.c +++ b/src/interfaces/libpgtcl/pgtclCmds.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * pgtclCmds.c-- - * C functions which implement pg_* tcl commands + * C functions which implement pg_* tcl commands * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.13 1997/04/02 18:16:49 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclCmds.c,v 1.14 1997/09/07 05:03:10 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -25,8 +25,8 @@ #include "pgtclId.h" #ifdef TCL_ARRAYS -#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7')) -#define DIGIT(c) ((c) - '0') +#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7')) +#define DIGIT(c) ((c) - '0') /* * translate_escape() -- @@ -38,97 +38,107 @@ * just before the rest of the buffer). */ -static inline char* +static inline char * translate_escape(char *p, int isArray) { - register char c, *q, *s; + register char c, + *q, + *s; #ifdef TCL_ARRAYS_DEBUG_ESCAPE - printf(" escape = '%s'\n", p); + printf(" escape = '%s'\n", p); #endif - /* Address of the first character after the escape sequence */ - s = p+2; - switch (c = *(p+1)) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - c = DIGIT(c); - if (ISOCTAL(*s)) { - c = (c<<3) + DIGIT(*s++); - } - if (ISOCTAL(*s)) { - c = (c<<3) + DIGIT(*s++); - } - *p = c; - break; - case 'b': - *p = '\b'; - break; - case 'f': - *p = '\f'; - break; - case 'n': - *p = '\n'; - break; - case 'r': - *p = '\r'; - break; - case 't': - *p = '\t'; - break; - case 'v': - *p = '\v'; - break; - case '\\': - case '{': - case '}': - case '"': - /* - * Backslahes, curly braces and double-quotes are left - * escaped if they appear inside an array. They will be - * unescaped by Tcl in Tcl_AppendElement. - * The buffer position is advanced by 1 so that the this - * character is not processed again by the caller. - */ - if (isArray) { - return p+1; - } else { - *p = c; + /* Address of the first character after the escape sequence */ + s = p + 2; + switch (c = *(p + 1)) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + c = DIGIT(c); + if (ISOCTAL(*s)) + { + c = (c << 3) + DIGIT(*s++); + } + if (ISOCTAL(*s)) + { + c = (c << 3) + DIGIT(*s++); + } + *p = c; + break; + case 'b': + *p = '\b'; + break; + case 'f': + *p = '\f'; + break; + case 'n': + *p = '\n'; + break; + case 'r': + *p = '\r'; + break; + case 't': + *p = '\t'; + break; + case 'v': + *p = '\v'; + break; + case '\\': + case '{': + case '}': + case '"': + + /* + * Backslahes, curly braces and double-quotes are left escaped if + * they appear inside an array. They will be unescaped by Tcl in + * Tcl_AppendElement. The buffer position is advanced by 1 so that + * the this character is not processed again by the caller. + */ + if (isArray) + { + return p + 1; + } + else + { + *p = c; + } + break; + case '\0': + + /* + * This means a backslash at the end of the string. It should + * never happen but in that case replace the \ with a \0 but don't + * shift the rest of the buffer so that the caller can see the end + * of the string and terminate. + */ + *p = c; + return p; + break; + default: + + /* + * Default case, store the escaped character over the backslash + * and shift the buffer over itself. + */ + *p = c; } - break; - case '\0': - /* - * This means a backslash at the end of the string. - * It should never happen but in that case replace - * the \ with a \0 but don't shift the rest of the - * buffer so that the caller can see the end of the - * string and terminate. - */ - *p = c; - return p; - break; - default: - /* - * Default case, store the escaped character over the backslash - * and shift the buffer over itself. - */ - *p = c; - } - /* Shift the rest of the buffer over itself after the current char */ - q = p+1; - for ( ; *s ; ) { - *q++ = *s++; - } - *q = '\0'; + /* Shift the rest of the buffer over itself after the current char */ + q = p + 1; + for (; *s;) + { + *q++ = *s++; + } + *q = '\0'; #ifdef TCL_ARRAYS_DEBUG_ESCAPE - printf(" after = '%s'\n", p); + printf(" after = '%s'\n", p); #endif - return p; + return p; } /* @@ -139,299 +149,339 @@ translate_escape(char *p, int isArray) * representation of a postgres array. */ -static char * -tcl_value (char *value) +static char * +tcl_value(char *value) { - int literal, last; - register char *p; + int literal, + last; + register char *p; - if (!value) { - return ((char *) NULL); - } + if (!value) + { + return ((char *) NULL); + } #ifdef TCL_ARRAYS_DEBUG - printf("pq_value = '%s'\n", value); + printf("pq_value = '%s'\n", value); #endif - last = strlen(value)-1; - if ((last >= 1) && (value[0] == '{') && (value[last] == '}')) { - /* Looks like an array, replace ',' with spaces */ - /* Remove the outer pair of { }, the last first! */ - value[last] = '\0'; - value++; - literal = 0; - for (p=value; *p; p++) { - if (!literal) { - /* We are at the list level, look for ',' and '"' */ - switch (*p) { - case '"': /* beginning of literal */ - literal = 1; - break; - case ',': /* replace the ',' with space */ - *p = ' '; - break; - } - } else { - /* We are inside a C string */ - switch (*p) { - case '"': /* end of literal */ - literal = 0; - break; - case '\\': - /* - * escape sequence, translate it - */ - p = translate_escape(p,1); - break; + last = strlen(value) - 1; + if ((last >= 1) && (value[0] == '{') && (value[last] == '}')) + { + /* Looks like an array, replace ',' with spaces */ + /* Remove the outer pair of { }, the last first! */ + value[last] = '\0'; + value++; + literal = 0; + for (p = value; *p; p++) + { + if (!literal) + { + /* We are at the list level, look for ',' and '"' */ + switch (*p) + { + case '"': /* beginning of literal */ + literal = 1; + break; + case ',': /* replace the ',' with space */ + *p = ' '; + break; + } + } + else + { + /* We are inside a C string */ + switch (*p) + { + case '"': /* end of literal */ + literal = 0; + break; + case '\\': + + /* + * escape sequence, translate it + */ + p = translate_escape(p, 1); + break; + } + } + if (!*p) + { + break; + } } - } - if (!*p) { - break; - } } - } else { - /* Looks like a normal scalar value */ - for (p=value; *p; p++) { - if (*p == '\\') { - /* - * escape sequence, translate it - */ - p = translate_escape(p,0); - } - if (!*p) { - break; - } + else + { + /* Looks like a normal scalar value */ + for (p = value; *p; p++) + { + if (*p == '\\') + { + + /* + * escape sequence, translate it + */ + p = translate_escape(p, 0); + } + if (!*p) + { + break; + } + } } - } #ifdef TCL_ARRAYS_DEBUG - printf("tcl_value = '%s'\n\n", value); + printf("tcl_value = '%s'\n\n", value); #endif - return (value); + return (value); } #endif /********************************** * pg_conndefaults - + syntax: pg_conndefaults - + the return result is a list describing the possible options and their current default values for a call to pg_connect with the new -conninfo syntax. Each entry in the list is a sublist of the format: - {optname label dispchar dispsize value} - + {optname label dispchar dispsize value} + **********************************/ int -Pg_conndefaults(ClientData cData, Tcl_Interp *interp, int argc, char **argv) +Pg_conndefaults(ClientData cData, Tcl_Interp * interp, int argc, char **argv) { - PQconninfoOption *option; - char buf[8192]; - - Tcl_ResetResult(interp); - for(option = PQconndefaults(); option->keyword != NULL; option++) { - if(option->val == NULL) { - option->val = ""; - } - sprintf(buf, "{%s} {%s} {%s} %d {%s}", - option->keyword, - option->label, - option->dispchar, - option->dispsize, - option->val); - Tcl_AppendElement(interp, buf); - } - - return TCL_OK; + PQconninfoOption *option; + char buf[8192]; + + Tcl_ResetResult(interp); + for (option = PQconndefaults(); option->keyword != NULL; option++) + { + if (option->val == NULL) + { + option->val = ""; + } + sprintf(buf, "{%s} {%s} {%s} %d {%s}", + option->keyword, + option->label, + option->dispchar, + option->dispsize, + option->val); + Tcl_AppendElement(interp, buf); + } + + return TCL_OK; } /********************************** * pg_connect - make a connection to a backend. - + make a connection to a backend. + syntax: pg_connect dbName [-host hostName] [-port portNumber] [-tty pqtty]] - + the return result is either an error message or a handle for a database connection. Handles start with the prefix "pgp" - + **********************************/ int -Pg_connect(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_connect(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - char *pghost = NULL; - char *pgtty = NULL; - char *pgport = NULL; - char *pgoptions = NULL; - char *dbName; - int i; - PGconn *conn; - - if (argc == 1) { - Tcl_AppendResult(interp, "pg_connect: database name missing\n", 0); - Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]\n", 0); - Tcl_AppendResult(interp, "pg_connect -conninfo <conninfo-string>", 0); - return TCL_ERROR; - - } + Pg_clientData *cd = (Pg_clientData *) cData; + char *pghost = NULL; + char *pgtty = NULL; + char *pgport = NULL; + char *pgoptions = NULL; + char *dbName; + int i; + PGconn *conn; + + if (argc == 1) + { + Tcl_AppendResult(interp, "pg_connect: database name missing\n", 0); + Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]\n", 0); + Tcl_AppendResult(interp, "pg_connect -conninfo <conninfo-string>", 0); + return TCL_ERROR; - if (!strcmp("-conninfo", argv[1])) { - /* - * Establish a connection using the new PQconnectdb() interface - */ - if (argc != 3) { - Tcl_AppendResult(interp, "pg_connect: syntax error\n", 0); - Tcl_AppendResult(interp, "pg_connect -conninfo <conninfo-string>", 0); - return TCL_ERROR; } - conn = PQconnectdb(argv[2]); - } else { - /* - * Establish a connection using the old PQsetdb() interface - */ - if (argc > 2) { - /* parse for pg environment settings */ - i = 2; - while (i+1 < argc) { - if (strcmp(argv[i], "-host") == 0) { - pghost = argv[i+1]; - i += 2; + + if (!strcmp("-conninfo", argv[1])) + { + + /* + * Establish a connection using the new PQconnectdb() interface + */ + if (argc != 3) + { + Tcl_AppendResult(interp, "pg_connect: syntax error\n", 0); + Tcl_AppendResult(interp, "pg_connect -conninfo <conninfo-string>", 0); + return TCL_ERROR; } - else - if (strcmp(argv[i], "-port") == 0) { - pgport = argv[i+1]; - i += 2; - } - else - if (strcmp(argv[i], "-tty") == 0) { - pgtty = argv[i+1]; - i += 2; - } - else if (strcmp(argv[i], "-options") == 0) { - pgoptions = argv[i+1]; - i += 2; - } - else { - Tcl_AppendResult(interp, "Bad option to pg_connect : \n", - argv[i], 0); - Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]",0); - return TCL_ERROR; + conn = PQconnectdb(argv[2]); + } + else + { + + /* + * Establish a connection using the old PQsetdb() interface + */ + if (argc > 2) + { + /* parse for pg environment settings */ + i = 2; + while (i + 1 < argc) + { + if (strcmp(argv[i], "-host") == 0) + { + pghost = argv[i + 1]; + i += 2; + } + else if (strcmp(argv[i], "-port") == 0) + { + pgport = argv[i + 1]; + i += 2; + } + else if (strcmp(argv[i], "-tty") == 0) + { + pgtty = argv[i + 1]; + i += 2; + } + else if (strcmp(argv[i], "-options") == 0) + { + pgoptions = argv[i + 1]; + i += 2; + } + else + { + Tcl_AppendResult(interp, "Bad option to pg_connect : \n", + argv[i], 0); + Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]", 0); + return TCL_ERROR; + } + } /* while */ + if ((i % 2 != 0) || i != argc) + { + Tcl_AppendResult(interp, "wrong # of arguments to pg_connect\n", argv[i], 0); + Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]", 0); + return TCL_ERROR; } - } /* while */ - if ((i % 2 != 0) || i != argc) { - Tcl_AppendResult(interp, "wrong # of arguments to pg_connect\n", argv[i],0); - Tcl_AppendResult(interp, "pg_connect databaseName [-host hostName] [-port portNumber] [-tty pgtty]]",0); - return TCL_ERROR; - } + } + dbName = argv[1]; + conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName); } - dbName = argv[1]; - conn = PQsetdb(pghost, pgport, pgoptions, pgtty, dbName); - } - if (conn->status == CONNECTION_OK) { - PgSetConnectionId(cd, interp->result, conn); - return TCL_OK; - } - else { - Tcl_AppendResult(interp, "Connection to database failed\n", 0); - Tcl_AppendResult(interp, conn->errorMessage, 0); - PQfinish(conn); - return TCL_ERROR; - } + if (conn->status == CONNECTION_OK) + { + PgSetConnectionId(cd, interp->result, conn); + return TCL_OK; + } + else + { + Tcl_AppendResult(interp, "Connection to database failed\n", 0); + Tcl_AppendResult(interp, conn->errorMessage, 0); + PQfinish(conn); + return TCL_ERROR; + } } /********************************** * pg_disconnect close a backend connection - + syntax: pg_disconnect connection - + The argument passed in must be a connection pointer. - + **********************************/ int -Pg_disconnect(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_disconnect(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGconn *conn; + Pg_clientData *cd = (Pg_clientData *) cData; + PGconn *conn; - if (argc != 2) { - Tcl_AppendResult(interp, "Wrong # of arguments\n", "pg_disconnect connection", 0); - return TCL_ERROR; - } + if (argc != 2) + { + Tcl_AppendResult(interp, "Wrong # of arguments\n", "pg_disconnect connection", 0); + return TCL_ERROR; + } - conn = PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - - PgDelConnectionId(cd, argv[1]); - PQfinish(conn); - return TCL_OK; + conn = PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); + return TCL_ERROR; + } + + PgDelConnectionId(cd, argv[1]); + PQfinish(conn); + return TCL_OK; } /********************************** * pg_exec send a query string to the backend connection - + syntax: pg_exec connection query - + the return result is either an error message or a handle for a query result. Handles start with the prefix "pgp" **********************************/ int -Pg_exec(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_exec(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGconn *conn; - PGresult *result; + Pg_clientData *cd = (Pg_clientData *) cData; + PGconn *conn; + PGresult *result; - if (argc != 3) { - Tcl_AppendResult(interp, "Wrong # of arguments\n", - "pg_exec connection queryString", 0); - return TCL_ERROR; - } + if (argc != 3) + { + Tcl_AppendResult(interp, "Wrong # of arguments\n", + "pg_exec connection queryString", 0); + return TCL_ERROR; + } - conn = PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - - result = PQexec(conn, argv[2]); - if (result) { - PgSetResultId(cd, interp->result, argv[1], result); + conn = PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); + return TCL_ERROR; + } + + result = PQexec(conn, argv[2]); + if (result) + { + PgSetResultId(cd, interp->result, argv[1], result); + return TCL_OK; + } + else + { + /* error occurred during the query */ + Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC); + return TCL_ERROR; + } + /* check return status of result */ return TCL_OK; - } - else { - /* error occurred during the query */ - Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC); - return TCL_ERROR; - } - /* check return status of result */ - return TCL_OK; } /********************************** * pg_result get information about the results of a query - + syntax: - pg_result result ?option? - + pg_result result ?option? + the options are: - -status + -status the status of the result -conn the connection that produced the result @@ -451,291 +501,333 @@ Pg_exec(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) returns the number of attributes returned by the query -getTuple tupleNumber returns the values of the tuple in a list - -clear + -clear clear the result buffer. Do not reuse after this **********************************/ int -Pg_result(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_result(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGresult *result; - char *opt; - int i; - int tupno; - char prearrayInd[MAX_MESSAGE_LEN]; - char arrayInd[MAX_MESSAGE_LEN]; - char *appendstr; - char *arrVar; - - if (argc != 3 && argc != 4 && argc != 5) { - Tcl_AppendResult(interp, "Wrong # of arguments\n",0); - goto Pg_result_errReturn; - } - - result = PgGetResultId(cd, argv[1]); - if (result == (PGresult *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid query result\n", 0); - return TCL_ERROR; - } + Pg_clientData *cd = (Pg_clientData *) cData; + PGresult *result; + char *opt; + int i; + int tupno; + char prearrayInd[MAX_MESSAGE_LEN]; + char arrayInd[MAX_MESSAGE_LEN]; + char *appendstr; + char *arrVar; + + if (argc != 3 && argc != 4 && argc != 5) + { + Tcl_AppendResult(interp, "Wrong # of arguments\n", 0); + goto Pg_result_errReturn; + } + + result = PgGetResultId(cd, argv[1]); + if (result == (PGresult *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid query result\n", 0); + return TCL_ERROR; + } - opt = argv[2]; + opt = argv[2]; - if (strcmp(opt, "-status") == 0) { - Tcl_AppendResult(interp, pgresStatus[PQresultStatus(result)], 0); - return TCL_OK; - } - else if (strcmp(opt, "-oid") == 0) { - Tcl_AppendResult(interp, PQoidStatus(result), 0); - return TCL_OK; - } - else if (strcmp(opt, "-conn") == 0) { - PgGetConnByResultId(cd, interp->result, argv[1]); - return TCL_OK; - } - else if (strcmp(opt, "-clear") == 0) { - PgDelResultId(cd, argv[1]); - PQclear(result); - return TCL_OK; - } - else if (strcmp(opt, "-numTuples") == 0) { - sprintf(interp->result, "%d", PQntuples(result)); - return TCL_OK; - } - else if (strcmp(opt, "-assign") == 0) { - if (argc != 4) { - Tcl_AppendResult(interp, "-assign option must be followed by a variable name",0); - return TCL_ERROR; - } - arrVar = argv[3]; - /* this assignment assigns the table of result tuples into a giant - array with the name given in the argument, - the indices of the array or (tupno,attrName)*/ - for (tupno = 0; tupno<PQntuples(result); tupno++) { - for (i=0;i<PQnfields(result);i++) { - sprintf(arrayInd, "%d,%s", tupno, PQfname(result,i)); - Tcl_SetVar2(interp, arrVar, arrayInd, + if (strcmp(opt, "-status") == 0) + { + Tcl_AppendResult(interp, pgresStatus[PQresultStatus(result)], 0); + return TCL_OK; + } + else if (strcmp(opt, "-oid") == 0) + { + Tcl_AppendResult(interp, PQoidStatus(result), 0); + return TCL_OK; + } + else if (strcmp(opt, "-conn") == 0) + { + PgGetConnByResultId(cd, interp->result, argv[1]); + return TCL_OK; + } + else if (strcmp(opt, "-clear") == 0) + { + PgDelResultId(cd, argv[1]); + PQclear(result); + return TCL_OK; + } + else if (strcmp(opt, "-numTuples") == 0) + { + sprintf(interp->result, "%d", PQntuples(result)); + return TCL_OK; + } + else if (strcmp(opt, "-assign") == 0) + { + if (argc != 4) + { + Tcl_AppendResult(interp, "-assign option must be followed by a variable name", 0); + return TCL_ERROR; + } + arrVar = argv[3]; + + /* + * this assignment assigns the table of result tuples into a giant + * array with the name given in the argument, the indices of the + * array or (tupno,attrName) + */ + for (tupno = 0; tupno < PQntuples(result); tupno++) + { + for (i = 0; i < PQnfields(result); i++) + { + sprintf(arrayInd, "%d,%s", tupno, PQfname(result, i)); + Tcl_SetVar2(interp, arrVar, arrayInd, #ifdef TCL_ARRAYS - tcl_value(PQgetvalue(result,tupno,i)), + tcl_value(PQgetvalue(result, tupno, i)), #else - PQgetvalue(result,tupno,i), + PQgetvalue(result, tupno, i), #endif - TCL_LEAVE_ERR_MSG); - } + TCL_LEAVE_ERR_MSG); + } + } + Tcl_AppendResult(interp, arrVar, 0); + return TCL_OK; } - Tcl_AppendResult(interp, arrVar, 0); - return TCL_OK; - } - else if (strcmp(opt, "-assignbyidx") == 0) { - if (argc !=4 && argc != 5) { - Tcl_AppendResult(interp, "-assignbyidx requires the array name and takes one optional argument as an append string",0); - return TCL_ERROR; - } - arrVar = argv[3]; - /* this assignment assigns the table of result tuples into a giant - array with the name given in the argument, - the indices of the array or (tupno,attrName)*/ - if (argc == 5) { - appendstr = argv[4]; - } else { - appendstr = ""; - } - for (tupno = 0; tupno<PQntuples(result); tupno++) { - sprintf(prearrayInd,"%s",PQgetvalue(result,tupno,0)); - for (i=1;i<PQnfields(result);i++) { - sprintf(arrayInd, "%s,%s%s", prearrayInd, PQfname(result,i), - appendstr); - Tcl_SetVar2(interp, arrVar, arrayInd, - PQgetvalue(result,tupno,i), - TCL_LEAVE_ERR_MSG); - } - } - Tcl_AppendResult(interp, arrVar, 0); - return TCL_OK; - } - else if (strcmp(opt, "-getTuple") == 0) { - if (argc != 4) { - Tcl_AppendResult(interp, "-getTuple option must be followed by a tuple number",0); - return TCL_ERROR; - } - tupno = atoi(argv[3]); - - if (tupno >= PQntuples(result)) { - Tcl_AppendResult(interp, "argument to getTuple cannot exceed number of tuples - 1",0); - return TCL_ERROR; + else if (strcmp(opt, "-assignbyidx") == 0) + { + if (argc != 4 && argc != 5) + { + Tcl_AppendResult(interp, "-assignbyidx requires the array name and takes one optional argument as an append string", 0); + return TCL_ERROR; + } + arrVar = argv[3]; + + /* + * this assignment assigns the table of result tuples into a giant + * array with the name given in the argument, the indices of the + * array or (tupno,attrName) + */ + if (argc == 5) + { + appendstr = argv[4]; + } + else + { + appendstr = ""; + } + for (tupno = 0; tupno < PQntuples(result); tupno++) + { + sprintf(prearrayInd, "%s", PQgetvalue(result, tupno, 0)); + for (i = 1; i < PQnfields(result); i++) + { + sprintf(arrayInd, "%s,%s%s", prearrayInd, PQfname(result, i), + appendstr); + Tcl_SetVar2(interp, arrVar, arrayInd, + PQgetvalue(result, tupno, i), + TCL_LEAVE_ERR_MSG); + } + } + Tcl_AppendResult(interp, arrVar, 0); + return TCL_OK; } + else if (strcmp(opt, "-getTuple") == 0) + { + if (argc != 4) + { + Tcl_AppendResult(interp, "-getTuple option must be followed by a tuple number", 0); + return TCL_ERROR; + } + tupno = atoi(argv[3]); + + if (tupno >= PQntuples(result)) + { + Tcl_AppendResult(interp, "argument to getTuple cannot exceed number of tuples - 1", 0); + return TCL_ERROR; + } #ifdef TCL_ARRAYS - for (i=0; i<PQnfields(result); i++) { - Tcl_AppendElement(interp, tcl_value(PQgetvalue(result,tupno,i))); - } + for (i = 0; i < PQnfields(result); i++) + { + Tcl_AppendElement(interp, tcl_value(PQgetvalue(result, tupno, i))); + } #else -/* Tcl_AppendResult(interp, PQgetvalue(result,tupno,0),NULL); */ - Tcl_AppendElement(interp, PQgetvalue(result,tupno,0)); - for (i=1;i<PQnfields(result);i++) { -/* Tcl_AppendResult(interp, " ", PQgetvalue(result,tupno,i),NULL);*/ - Tcl_AppendElement(interp, PQgetvalue(result,tupno,i)); - } +/* Tcl_AppendResult(interp, PQgetvalue(result,tupno,0),NULL); */ + Tcl_AppendElement(interp, PQgetvalue(result, tupno, 0)); + for (i = 1; i < PQnfields(result); i++) + { +/* Tcl_AppendResult(interp, " ", PQgetvalue(result,tupno,i),NULL);*/ + Tcl_AppendElement(interp, PQgetvalue(result, tupno, i)); + } #endif - return TCL_OK; - } - else if (strcmp(opt, "-attributes") == 0) { - Tcl_AppendResult(interp, PQfname(result,0),NULL); - for (i=1;i<PQnfields(result);i++) { - Tcl_AppendResult(interp, " ", PQfname(result,i), NULL); - } - return TCL_OK; - } - else if (strcmp(opt, "-lAttributes") == 0) { - char buf[512]; - Tcl_ResetResult(interp); - for (i = 0; i < PQnfields(result); i++) { - sprintf(buf, "{%s} %ld %d", PQfname(result, i), - (long) PQftype(result, i), - PQfsize(result, i)); - Tcl_AppendElement(interp, buf); - } - return TCL_OK; - } - else if (strcmp(opt, "-numAttrs") == 0) { - sprintf(interp->result, "%d", PQnfields(result)); - return TCL_OK; - } - else { - Tcl_AppendResult(interp, "Invalid option",0); - goto Pg_result_errReturn; - } - - - Pg_result_errReturn: - Tcl_AppendResult(interp, - "pg_result result ?option? where ?option is\n", - "\t-status\n", - "\t-conn\n", - "\t-assign arrayVarName\n", - "\t-assignbyidx arrayVarName ?appendstr?\n", - "\t-numTuples\n", - "\t-attributes\n" - "\t-lAttributes\n" - "\t-numAttrs\n" - "\t-getTuple tupleNumber\n", - "\t-clear\n", - "\t-oid\n", - 0); - return TCL_ERROR; - + return TCL_OK; + } + else if (strcmp(opt, "-attributes") == 0) + { + Tcl_AppendResult(interp, PQfname(result, 0), NULL); + for (i = 1; i < PQnfields(result); i++) + { + Tcl_AppendResult(interp, " ", PQfname(result, i), NULL); + } + return TCL_OK; + } + else if (strcmp(opt, "-lAttributes") == 0) + { + char buf[512]; + + Tcl_ResetResult(interp); + for (i = 0; i < PQnfields(result); i++) + { + sprintf(buf, "{%s} %ld %d", PQfname(result, i), + (long) PQftype(result, i), + PQfsize(result, i)); + Tcl_AppendElement(interp, buf); + } + return TCL_OK; + } + else if (strcmp(opt, "-numAttrs") == 0) + { + sprintf(interp->result, "%d", PQnfields(result)); + return TCL_OK; + } + else + { + Tcl_AppendResult(interp, "Invalid option", 0); + goto Pg_result_errReturn; + } + + +Pg_result_errReturn: + Tcl_AppendResult(interp, + "pg_result result ?option? where ?option is\n", + "\t-status\n", + "\t-conn\n", + "\t-assign arrayVarName\n", + "\t-assignbyidx arrayVarName ?appendstr?\n", + "\t-numTuples\n", + "\t-attributes\n" + "\t-lAttributes\n" + "\t-numAttrs\n" + "\t-getTuple tupleNumber\n", + "\t-clear\n", + "\t-oid\n", + 0); + return TCL_ERROR; + } /********************************** * pg_lo_open - open a large object - + open a large object + syntax: - pg_lo_open conn objOid mode + pg_lo_open conn objOid mode where mode can be either 'r', 'w', or 'rw' **********************/ int -Pg_lo_open(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_lo_open(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGconn *conn; - int lobjId; - int mode; - int fd; - - if (argc != 4) { - Tcl_AppendResult(interp, "Wrong # of arguments\n", - "pg_lo_open connection lobjOid mode", 0); - return TCL_ERROR; - } - - conn = PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - - lobjId = atoi(argv[2]); - if (strlen(argv[3]) < 1 || - strlen(argv[3]) > 2) - { - Tcl_AppendResult(interp,"mode argument must be 'r', 'w', or 'rw'",0); - return TCL_ERROR; - } - switch (argv[3][0]) { - case 'r': - case 'R': - mode = INV_READ; - break; - case 'w': - case 'W': - mode = INV_WRITE; - break; - default: - Tcl_AppendResult(interp,"mode argument must be 'r', 'w', or 'rw'",0); - return TCL_ERROR; - } - switch (argv[3][1]) { - case '\0': - break; - case 'r': - case 'R': - mode = mode & INV_READ; - break; - case 'w': - case 'W': - mode = mode & INV_WRITE; - break; - default: - Tcl_AppendResult(interp,"mode argument must be 'r', 'w', or 'rw'",0); - return TCL_ERROR; - } - - fd = lo_open(conn,lobjId,mode); - sprintf(interp->result,"%d",fd); - return TCL_OK; + Pg_clientData *cd = (Pg_clientData *) cData; + PGconn *conn; + int lobjId; + int mode; + int fd; + + if (argc != 4) + { + Tcl_AppendResult(interp, "Wrong # of arguments\n", + "pg_lo_open connection lobjOid mode", 0); + return TCL_ERROR; + } + + conn = PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); + return TCL_ERROR; + } + + lobjId = atoi(argv[2]); + if (strlen(argv[3]) < 1 || + strlen(argv[3]) > 2) + { + Tcl_AppendResult(interp, "mode argument must be 'r', 'w', or 'rw'", 0); + return TCL_ERROR; + } + switch (argv[3][0]) + { + case 'r': + case 'R': + mode = INV_READ; + break; + case 'w': + case 'W': + mode = INV_WRITE; + break; + default: + Tcl_AppendResult(interp, "mode argument must be 'r', 'w', or 'rw'", 0); + return TCL_ERROR; + } + switch (argv[3][1]) + { + case '\0': + break; + case 'r': + case 'R': + mode = mode & INV_READ; + break; + case 'w': + case 'W': + mode = mode & INV_WRITE; + break; + default: + Tcl_AppendResult(interp, "mode argument must be 'r', 'w', or 'rw'", 0); + return TCL_ERROR; + } + + fd = lo_open(conn, lobjId, mode); + sprintf(interp->result, "%d", fd); + return TCL_OK; } /********************************** * pg_lo_close - close a large object - + close a large object + syntax: - pg_lo_close conn fd + pg_lo_close conn fd **********************/ int -Pg_lo_close(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_lo_close(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGconn *conn; - int fd; + Pg_clientData *cd = (Pg_clientData *) cData; + PGconn *conn; + int fd; - if (argc != 3) { - Tcl_AppendResult(interp, "Wrong # of arguments\n", - "pg_lo_close connection fd", 0); - return TCL_ERROR; - } + if (argc != 3) + { + Tcl_AppendResult(interp, "Wrong # of arguments\n", + "pg_lo_close connection fd", 0); + return TCL_ERROR; + } - conn = PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - - fd = atoi(argv[2]); - sprintf(interp->result,"%d",lo_close(conn,fd)); - return TCL_OK; + conn = PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); + return TCL_ERROR; + } + + fd = atoi(argv[2]); + sprintf(interp->result, "%d", lo_close(conn, fd)); + return TCL_OK; } /********************************** * pg_lo_read - reads at most len bytes from a large object into a variable named + reads at most len bytes from a large object into a variable named bufVar - + syntax: pg_lo_read conn fd bufVar len @@ -743,98 +835,104 @@ Pg_lo_close(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) **********************/ int -Pg_lo_read(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_lo_read(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGconn *conn; - int fd; - int nbytes = 0; - char *buf; - char *bufVar; - int len; - - if (argc != 5) { - Tcl_AppendResult(interp, "Wrong # of arguments\n", - " pg_lo_read conn fd bufVar len", 0); - return TCL_ERROR; - } + Pg_clientData *cd = (Pg_clientData *) cData; + PGconn *conn; + int fd; + int nbytes = 0; + char *buf; + char *bufVar; + int len; - conn = PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - - fd = atoi(argv[2]); + if (argc != 5) + { + Tcl_AppendResult(interp, "Wrong # of arguments\n", + " pg_lo_read conn fd bufVar len", 0); + return TCL_ERROR; + } + + conn = PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); + return TCL_ERROR; + } - bufVar = argv[3]; + fd = atoi(argv[2]); - len = atoi(argv[4]); + bufVar = argv[3]; - if (len <= 0) { - sprintf(interp->result,"%d",nbytes); - return TCL_OK; - } - buf = malloc(sizeof(len+1)); + len = atoi(argv[4]); + + if (len <= 0) + { + sprintf(interp->result, "%d", nbytes); + return TCL_OK; + } + buf = malloc(sizeof(len + 1)); - nbytes = lo_read(conn,fd,buf,len); + nbytes = lo_read(conn, fd, buf, len); + + Tcl_SetVar(interp, bufVar, buf, TCL_LEAVE_ERR_MSG); + sprintf(interp->result, "%d", nbytes); + free(buf); + return TCL_OK; - Tcl_SetVar(interp,bufVar,buf,TCL_LEAVE_ERR_MSG); - sprintf(interp->result,"%d",nbytes); - free(buf); - return TCL_OK; - } /*********************************** Pg_lo_write - write at most len bytes to a large object + write at most len bytes to a large object syntax: pg_lo_write conn fd buf len ***********************************/ int -Pg_lo_write(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_lo_write(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGconn *conn; - char *buf; - int fd; - int nbytes = 0; - int len; - - if (argc != 5) { - Tcl_AppendResult(interp, "Wrong # of arguments\n", - "pg_lo_write conn fd buf len", 0); - return TCL_ERROR; - } + Pg_clientData *cd = (Pg_clientData *) cData; + PGconn *conn; + char *buf; + int fd; + int nbytes = 0; + int len; - conn = PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - - fd = atoi(argv[2]); + if (argc != 5) + { + Tcl_AppendResult(interp, "Wrong # of arguments\n", + "pg_lo_write conn fd buf len", 0); + return TCL_ERROR; + } + + conn = PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); + return TCL_ERROR; + } - buf = argv[3]; + fd = atoi(argv[2]); - len = atoi(argv[4]); + buf = argv[3]; - if (len <= 0) { - sprintf(interp->result,"%d",nbytes); - return TCL_OK; - } + len = atoi(argv[4]); - nbytes = lo_write(conn,fd,buf,len); - sprintf(interp->result,"%d",nbytes); - return TCL_OK; + if (len <= 0) + { + sprintf(interp->result, "%d", nbytes); + return TCL_OK; + } + + nbytes = lo_write(conn, fd, buf, len); + sprintf(interp->result, "%d", nbytes); + return TCL_OK; } /*********************************** Pg_lo_lseek - seek to a certain position in a large object + seek to a certain position in a large object syntax pg_lo_lseek conn fd offset whence @@ -843,44 +941,54 @@ whence can be either "SEEK_CUR", "SEEK_END", or "SEEK_SET" ***********************************/ int -Pg_lo_lseek(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_lo_lseek(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGconn *conn; - int fd; - char *whenceStr; - int offset, whence; - - if (argc != 5) { - Tcl_AppendResult(interp, "Wrong # of arguments\n", - "pg_lo_lseek conn fd offset whence", 0); - return TCL_ERROR; - } + Pg_clientData *cd = (Pg_clientData *) cData; + PGconn *conn; + int fd; + char *whenceStr; + int offset, + whence; - conn = PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - - fd = atoi(argv[2]); - - offset = atoi(argv[3]); - - whenceStr = argv[4]; - if (strcmp(whenceStr,"SEEK_SET") == 0) { - whence = SEEK_SET; - } else if (strcmp(whenceStr,"SEEK_CUR") == 0) { - whence = SEEK_CUR; - } else if (strcmp(whenceStr,"SEEK_END") == 0) { - whence = SEEK_END; - } else { - Tcl_AppendResult(interp, "the whence argument to Pg_lo_lseek must be SEEK_SET, SEEK_CUR or SEEK_END",0); - return TCL_ERROR; - } - - sprintf(interp->result,"%d",lo_lseek(conn,fd,offset,whence)); - return TCL_OK; + if (argc != 5) + { + Tcl_AppendResult(interp, "Wrong # of arguments\n", + "pg_lo_lseek conn fd offset whence", 0); + return TCL_ERROR; + } + + conn = PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); + return TCL_ERROR; + } + + fd = atoi(argv[2]); + + offset = atoi(argv[3]); + + whenceStr = argv[4]; + if (strcmp(whenceStr, "SEEK_SET") == 0) + { + whence = SEEK_SET; + } + else if (strcmp(whenceStr, "SEEK_CUR") == 0) + { + whence = SEEK_CUR; + } + else if (strcmp(whenceStr, "SEEK_END") == 0) + { + whence = SEEK_END; + } + else + { + Tcl_AppendResult(interp, "the whence argument to Pg_lo_lseek must be SEEK_SET, SEEK_CUR or SEEK_END", 0); + return TCL_ERROR; + } + + sprintf(interp->result, "%d", lo_lseek(conn, fd, offset, whence)); + return TCL_OK; } @@ -896,97 +1004,116 @@ for now, we don't support any additional storage managers. ***********************************/ int -Pg_lo_creat(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_lo_creat(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGconn *conn; - char *modeStr; - char *modeWord; - int mode; - - if (argc != 3) { - Tcl_AppendResult(interp, "Wrong # of arguments\n", - "pg_lo_creat conn mode", 0); - return TCL_ERROR; - } + Pg_clientData *cd = (Pg_clientData *) cData; + PGconn *conn; + char *modeStr; + char *modeWord; + int mode; - conn = PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - - modeStr = argv[2]; - - modeWord = strtok(modeStr,"|"); - if (strcmp(modeWord,"INV_READ") == 0) { - mode = INV_READ; - } else if (strcmp(modeWord,"INV_WRITE") == 0) { - mode = INV_WRITE; - } else if (strcmp(modeWord,"INV_ARCHIVE") == 0) { - mode = INV_ARCHIVE; - } else { - Tcl_AppendResult(interp, - "invalid mode argument to Pg_lo_creat\nmode argument must be some OR'd combination of INV_READ, INV_WRITE, and INV_ARCHIVE", - 0); - return TCL_ERROR; - } - - while ( (modeWord = strtok((char*)NULL, "|")) != NULL) { - if (strcmp(modeWord,"INV_READ") == 0) { - mode |= INV_READ; - } else if (strcmp(modeWord,"INV_WRITE") == 0) { - mode |= INV_WRITE; - } else if (strcmp(modeWord,"INV_ARCHIVE") == 0) { - mode |= INV_ARCHIVE; - } else { - Tcl_AppendResult(interp, - "invalid mode argument to Pg_lo_creat\nmode argument must be some OR'd combination of INV_READ, INV_WRITE, and INV_ARCHIVE", - 0); - return TCL_ERROR; - } - } - sprintf(interp->result,"%d",lo_creat(conn,mode)); - return TCL_OK; + if (argc != 3) + { + Tcl_AppendResult(interp, "Wrong # of arguments\n", + "pg_lo_creat conn mode", 0); + return TCL_ERROR; + } + + conn = PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); + return TCL_ERROR; + } + + modeStr = argv[2]; + + modeWord = strtok(modeStr, "|"); + if (strcmp(modeWord, "INV_READ") == 0) + { + mode = INV_READ; + } + else if (strcmp(modeWord, "INV_WRITE") == 0) + { + mode = INV_WRITE; + } + else if (strcmp(modeWord, "INV_ARCHIVE") == 0) + { + mode = INV_ARCHIVE; + } + else + { + Tcl_AppendResult(interp, + "invalid mode argument to Pg_lo_creat\nmode argument must be some OR'd combination of INV_READ, INV_WRITE, and INV_ARCHIVE", + 0); + return TCL_ERROR; + } + + while ((modeWord = strtok((char *) NULL, "|")) != NULL) + { + if (strcmp(modeWord, "INV_READ") == 0) + { + mode |= INV_READ; + } + else if (strcmp(modeWord, "INV_WRITE") == 0) + { + mode |= INV_WRITE; + } + else if (strcmp(modeWord, "INV_ARCHIVE") == 0) + { + mode |= INV_ARCHIVE; + } + else + { + Tcl_AppendResult(interp, + "invalid mode argument to Pg_lo_creat\nmode argument must be some OR'd combination of INV_READ, INV_WRITE, and INV_ARCHIVE", + 0); + return TCL_ERROR; + } + } + sprintf(interp->result, "%d", lo_creat(conn, mode)); + return TCL_OK; } /*********************************** Pg_lo_tell - returns the current seek location of the large object + returns the current seek location of the large object syntax: pg_lo_tell conn fd ***********************************/ int -Pg_lo_tell(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_lo_tell(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGconn *conn; - int fd; + Pg_clientData *cd = (Pg_clientData *) cData; + PGconn *conn; + int fd; - if (argc != 3) { - Tcl_AppendResult(interp, "Wrong # of arguments\n", - "pg_lo_tell conn fd", 0); - return TCL_ERROR; - } + if (argc != 3) + { + Tcl_AppendResult(interp, "Wrong # of arguments\n", + "pg_lo_tell conn fd", 0); + return TCL_ERROR; + } - conn = PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - - fd = atoi(argv[2]); + conn = PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); + return TCL_ERROR; + } - sprintf(interp->result,"%d",lo_tell(conn,fd)); - return TCL_OK; + fd = atoi(argv[2]); + + sprintf(interp->result, "%d", lo_tell(conn, fd)); + return TCL_OK; } /*********************************** Pg_lo_unlink - unlink a file based on lobject id + unlink a file based on lobject id syntax: pg_lo_unlink conn lobjId @@ -994,40 +1121,43 @@ Pg_lo_unlink ***********************************/ int -Pg_lo_unlink(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_lo_unlink(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGconn *conn; - int lobjId; - int retval; - - if (argc != 3) { - Tcl_AppendResult(interp, "Wrong # of arguments\n", - "pg_lo_tell conn fd", 0); - return TCL_ERROR; - } + Pg_clientData *cd = (Pg_clientData *) cData; + PGconn *conn; + int lobjId; + int retval; - conn = PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - - lobjId = atoi(argv[2]); + if (argc != 3) + { + Tcl_AppendResult(interp, "Wrong # of arguments\n", + "pg_lo_tell conn fd", 0); + return TCL_ERROR; + } - retval = lo_unlink(conn,lobjId); - if (retval == -1) { - sprintf(interp->result,"Pg_lo_unlink of '%d' failed",lobjId); - return TCL_ERROR; - } - - sprintf(interp->result,"%d",retval); - return TCL_OK; + conn = PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); + return TCL_ERROR; + } + + lobjId = atoi(argv[2]); + + retval = lo_unlink(conn, lobjId); + if (retval == -1) + { + sprintf(interp->result, "Pg_lo_unlink of '%d' failed", lobjId); + return TCL_ERROR; + } + + sprintf(interp->result, "%d", retval); + return TCL_OK; } /*********************************** Pg_lo_import - import a Unix file into an (inversion) large objct + import a Unix file into an (inversion) large objct returns the oid of that object upon success returns InvalidOid upon failure @@ -1037,81 +1167,87 @@ Pg_lo_import ***********************************/ int -Pg_lo_import(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_lo_import(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGconn *conn; - char* filename; - Oid lobjId; - - if (argc != 3) { - Tcl_AppendResult(interp, "Wrong # of arguments\n", - "pg_lo_import conn filename", 0); - return TCL_ERROR; - } + Pg_clientData *cd = (Pg_clientData *) cData; + PGconn *conn; + char *filename; + Oid lobjId; - conn = PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - - filename = argv[2]; + if (argc != 3) + { + Tcl_AppendResult(interp, "Wrong # of arguments\n", + "pg_lo_import conn filename", 0); + return TCL_ERROR; + } - lobjId = lo_import(conn,filename); - if (lobjId == InvalidOid) { - sprintf(interp->result, "Pg_lo_import of '%s' failed",filename); - return TCL_ERROR; - } - sprintf(interp->result,"%d",lobjId); - return TCL_OK; + conn = PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); + return TCL_ERROR; + } + + filename = argv[2]; + + lobjId = lo_import(conn, filename); + if (lobjId == InvalidOid) + { + sprintf(interp->result, "Pg_lo_import of '%s' failed", filename); + return TCL_ERROR; + } + sprintf(interp->result, "%d", lobjId); + return TCL_OK; } /*********************************** Pg_lo_export - export an Inversion large object to a Unix file - + export an Inversion large object to a Unix file + syntax: pg_lo_export conn lobjId filename ***********************************/ int -Pg_lo_export(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_lo_export(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGconn *conn; - char* filename; - Oid lobjId; - int retval; - - if (argc != 4) { - Tcl_AppendResult(interp, "Wrong # of arguments\n", - "pg_lo_export conn lobjId filename", 0); - return TCL_ERROR; - } + Pg_clientData *cd = (Pg_clientData *) cData; + PGconn *conn; + char *filename; + Oid lobjId; + int retval; - conn = PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - - lobjId = atoi(argv[2]); - filename = argv[3]; - - retval = lo_export(conn,lobjId,filename); - if (retval == -1) { - sprintf(interp->result, "Pg_lo_export %d %s failed",lobjId, filename); - return TCL_ERROR; - } - return TCL_OK; + if (argc != 4) + { + Tcl_AppendResult(interp, "Wrong # of arguments\n", + "pg_lo_export conn lobjId filename", 0); + return TCL_ERROR; + } + + conn = PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); + return TCL_ERROR; + } + + lobjId = atoi(argv[2]); + filename = argv[3]; + + retval = lo_export(conn, lobjId, filename); + if (retval == -1) + { + sprintf(interp->result, "Pg_lo_export %d %s failed", lobjId, filename); + return TCL_ERROR; + } + return TCL_OK; } /********************************** * pg_select send a select query string to the backend connection - + syntax: pg_select connection query var proc @@ -1121,7 +1257,7 @@ Pg_lo_export(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) Originally I was also going to update changes but that has turned out to be not so simple. Instead, the caller should get the OID of any - table they want to update and update it themself in the loop. I may + table they want to update and update it themself in the loop. I may try to write a simplified table lookup and update function to make that task a little easier. @@ -1130,41 +1266,45 @@ Pg_lo_export(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) **********************************/ int -Pg_select(ClientData cData, Tcl_Interp *interp, int argc, char **argv) +Pg_select(ClientData cData, Tcl_Interp * interp, int argc, char **argv) { - Pg_clientData *cd = (Pg_clientData *)cData; - PGconn *conn; - PGresult *result; - int r; - size_t tupno, column, ncols; - Tcl_DString headers; - char buffer[2048]; - struct { - char *cname; - int change; - } *info; + Pg_clientData *cd = (Pg_clientData *) cData; + PGconn *conn; + PGresult *result; + int r; + size_t tupno, + column, + ncols; + Tcl_DString headers; + char buffer[2048]; + struct + { + char *cname; + int change; + } *info; if (argc != 5) { Tcl_AppendResult(interp, "Wrong # of arguments\n", - "pg_select connection queryString var proc", 0); + "pg_select connection queryString var proc", 0); + return TCL_ERROR; + } + + conn = PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); return TCL_ERROR; } - conn = PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - if ((result = PQexec(conn, argv[2])) == 0) - { + { /* error occurred during the query */ Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC); return TCL_ERROR; - } + } - if ((info = malloc(sizeof(*info) * (ncols = PQnfields(result)))) == NULL) + if ((info = malloc(sizeof(*info) * (ncols = PQnfields(result)))) == NULL) { Tcl_AppendResult(interp, "Not enough memory", 0); return TCL_ERROR; @@ -1203,10 +1343,10 @@ Pg_select(ClientData cData, Tcl_Interp *interp, int argc, char **argv) if (r == TCL_ERROR) { - char msg[60]; + char msg[60]; sprintf(msg, "\n (\"pg_select\" body line %d)", - interp->errorLine); + interp->errorLine); Tcl_AddErrorInfo(interp, msg); } @@ -1221,142 +1361,160 @@ Pg_select(ClientData cData, Tcl_Interp *interp, int argc, char **argv) } int -Pg_listen(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_listen(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - int new; - char *relname; - char *callback = NULL; - Tcl_HashEntry *entry; - PGconn *conn; - PGresult *result; - - if ((argc < 3) || (argc > 4)) { - Tcl_AppendResult(interp, "wrong # args, should be \"", - argv[0], " connection relname ?callback?\"", 0); - return TCL_ERROR; - } - - /* - * Get the command arguments. Note that relname will copied by - * Tcl_CreateHashEntry while callback must be allocated. - */ - conn = (PGconn*)PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - relname = argv[2]; - if ((argc > 3) && *argv[3]) { - callback = (char *) ckalloc((unsigned) (strlen(argv[3])+1)); - strcpy(callback, argv[3]); - } - - /* - * Set or update a callback for a relation; - */ - if (callback) { - entry = Tcl_CreateHashEntry(&(cd->notify_hash), relname, &new); - if (new) { - /* New callback, execute a listen command on the relation */ - char *cmd = (char *) ckalloc((unsigned) (strlen(argv[2])+8)); - sprintf(cmd, "LISTEN %s", relname); - result = PQexec(conn, cmd); - ckfree(cmd); - if (!result || (result->resultStatus != PGRES_COMMAND_OK)) { - /* Error occurred during the execution of command */ - if (result) PQclear(result); - ckfree(callback); - Tcl_DeleteHashEntry(entry); - Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC); + Pg_clientData *cd = (Pg_clientData *) cData; + int new; + char *relname; + char *callback = NULL; + Tcl_HashEntry *entry; + PGconn *conn; + PGresult *result; + + if ((argc < 3) || (argc > 4)) + { + Tcl_AppendResult(interp, "wrong # args, should be \"", + argv[0], " connection relname ?callback?\"", 0); + return TCL_ERROR; + } + + /* + * Get the command arguments. Note that relname will copied by + * Tcl_CreateHashEntry while callback must be allocated. + */ + conn = (PGconn *) PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); return TCL_ERROR; - } - PQclear(result); - } else { - /* Free the old callback string */ - ckfree((char *) Tcl_GetHashValue(entry)); - } - /* Store the new callback command */ - Tcl_SetHashValue(entry, callback); - } - - /* - * Remove a callback for a relation. There is no way to - * un-listen a relation, simply remove the callback from - * the notify hash table. - */ - if (callback == NULL) { - entry = Tcl_FindHashEntry(&(cd->notify_hash), relname); - if (entry == NULL) { - Tcl_AppendResult(interp, "not listening on ", relname, 0); - return TCL_ERROR; - } - ckfree((char *) Tcl_GetHashValue(entry)); - Tcl_DeleteHashEntry(entry); - } - - return TCL_OK; + } + relname = argv[2]; + if ((argc > 3) && *argv[3]) + { + callback = (char *) ckalloc((unsigned) (strlen(argv[3]) + 1)); + strcpy(callback, argv[3]); + } + + /* + * Set or update a callback for a relation; + */ + if (callback) + { + entry = Tcl_CreateHashEntry(&(cd->notify_hash), relname, &new); + if (new) + { + /* New callback, execute a listen command on the relation */ + char *cmd = (char *) ckalloc((unsigned) (strlen(argv[2]) + 8)); + + sprintf(cmd, "LISTEN %s", relname); + result = PQexec(conn, cmd); + ckfree(cmd); + if (!result || (result->resultStatus != PGRES_COMMAND_OK)) + { + /* Error occurred during the execution of command */ + if (result) + PQclear(result); + ckfree(callback); + Tcl_DeleteHashEntry(entry); + Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC); + return TCL_ERROR; + } + PQclear(result); + } + else + { + /* Free the old callback string */ + ckfree((char *) Tcl_GetHashValue(entry)); + } + /* Store the new callback command */ + Tcl_SetHashValue(entry, callback); + } + + /* + * Remove a callback for a relation. There is no way to un-listen a + * relation, simply remove the callback from the notify hash table. + */ + if (callback == NULL) + { + entry = Tcl_FindHashEntry(&(cd->notify_hash), relname); + if (entry == NULL) + { + Tcl_AppendResult(interp, "not listening on ", relname, 0); + return TCL_ERROR; + } + ckfree((char *) Tcl_GetHashValue(entry)); + Tcl_DeleteHashEntry(entry); + } + + return TCL_OK; } int -Pg_notifies(ClientData cData, Tcl_Interp *interp, int argc, char* argv[]) +Pg_notifies(ClientData cData, Tcl_Interp * interp, int argc, char *argv[]) { - Pg_clientData *cd = (Pg_clientData *)cData; - int count; - char buff[12]; - char *callback; - Tcl_HashEntry *entry; - PGconn *conn; - PGresult *result; - PGnotify *notify; - - if (argc != 2) { - Tcl_AppendResult(interp, "wrong # args, should be \"", - argv[0], " connection\"", 0); - return TCL_ERROR; - } - - /* - * Get the connection argument. - */ - conn = (PGconn*)PgGetConnectionId(cd, argv[1]); - if (conn == (PGconn *)NULL) { - Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); - return TCL_ERROR; - } - - /* Execute an empty command to retrieve asynchronous notifications */ - result = PQexec(conn, " "); - if (result == NULL) { - /* Error occurred during the execution of command */ - Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC); - return TCL_ERROR; - } - PQclear(result); - - /* - * Loop while there are pending notifies. - */ - for (count=0; count < 999; count++) { - /* See if there is a pending notification */ - notify = PQnotifies(conn); - if (notify == NULL) { - break; - } - entry = Tcl_FindHashEntry(&(cd->notify_hash), notify->relname); - if (entry != NULL) { - callback = Tcl_GetHashValue(entry); - if (callback) { - Tcl_Eval(interp, callback); - } - } - free(notify); - } - - /* - * Return the number of notifications processed. - */ - sprintf(buff, "%d", count); - Tcl_SetResult(interp, buff, TCL_VOLATILE); - return TCL_OK; + Pg_clientData *cd = (Pg_clientData *) cData; + int count; + char buff[12]; + char *callback; + Tcl_HashEntry *entry; + PGconn *conn; + PGresult *result; + PGnotify *notify; + + if (argc != 2) + { + Tcl_AppendResult(interp, "wrong # args, should be \"", + argv[0], " connection\"", 0); + return TCL_ERROR; + } + + /* + * Get the connection argument. + */ + conn = (PGconn *) PgGetConnectionId(cd, argv[1]); + if (conn == (PGconn *) NULL) + { + Tcl_AppendResult(interp, "First argument is not a valid connection\n", 0); + return TCL_ERROR; + } + + /* Execute an empty command to retrieve asynchronous notifications */ + result = PQexec(conn, " "); + if (result == NULL) + { + /* Error occurred during the execution of command */ + Tcl_SetResult(interp, conn->errorMessage, TCL_STATIC); + return TCL_ERROR; + } + PQclear(result); + + /* + * Loop while there are pending notifies. + */ + for (count = 0; count < 999; count++) + { + /* See if there is a pending notification */ + notify = PQnotifies(conn); + if (notify == NULL) + { + break; + } + entry = Tcl_FindHashEntry(&(cd->notify_hash), notify->relname); + if (entry != NULL) + { + callback = Tcl_GetHashValue(entry); + if (callback) + { + Tcl_Eval(interp, callback); + } + } + free(notify); + } + + /* + * Return the number of notifications processed. + */ + sprintf(buff, "%d", count); + Tcl_SetResult(interp, buff, TCL_VOLATILE); + return TCL_OK; } diff --git a/src/interfaces/libpgtcl/pgtclCmds.h b/src/interfaces/libpgtcl/pgtclCmds.h index de69ad2e14c..f1e5755641f 100644 --- a/src/interfaces/libpgtcl/pgtclCmds.h +++ b/src/interfaces/libpgtcl/pgtclCmds.h @@ -1,11 +1,11 @@ /*------------------------------------------------------------------------- * * pgtclCmds.h-- - * declarations for the C functions which implement pg_* tcl commands + * declarations for the C functions which implement pg_* tcl commands * * Copyright (c) 1994, Regents of the University of California * - * $Id: pgtclCmds.h,v 1.6 1997/01/03 18:48:31 scrappy Exp $ + * $Id: pgtclCmds.h,v 1.7 1997/09/07 05:03:12 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -18,69 +18,89 @@ #include "libpq-fe.h" #include "libpq/libpq-fs.h" -typedef struct Pg_clientData_s { - Tcl_HashTable dbh_hash; - Tcl_HashTable res_hash; - Tcl_HashTable notify_hash; - long dbh_count; - long res_count; -} Pg_clientData; +typedef struct Pg_clientData_s +{ + Tcl_HashTable dbh_hash; + Tcl_HashTable res_hash; + Tcl_HashTable notify_hash; + long dbh_count; + long res_count; +} Pg_clientData; -typedef struct Pg_ConnectionId_s { - char id[32]; - PGconn *conn; - Tcl_HashTable res_hash; -} Pg_ConnectionId; +typedef struct Pg_ConnectionId_s +{ + char id[32]; + PGconn *conn; + Tcl_HashTable res_hash; +} Pg_ConnectionId; -typedef struct Pg_ResultId_s { - char id[32]; - PGresult *result; - Pg_ConnectionId *connection; -} Pg_ResultId; +typedef struct Pg_ResultId_s +{ + char id[32]; + PGresult *result; + Pg_ConnectionId *connection; +} Pg_ResultId; /* **************************/ /* registered Tcl functions */ /* **************************/ -extern int Pg_conndefaults( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_connect( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_disconnect( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_exec( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_select( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_result( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_lo_open( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_lo_close( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_lo_read( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_lo_write( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_lo_lseek( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_lo_creat( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_lo_tell( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_lo_unlink( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_lo_import( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_lo_export( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_listen( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); -extern int Pg_notifies( - ClientData cData, Tcl_Interp *interp, int argc, char* argv[]); +extern int +Pg_conndefaults( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_connect( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_disconnect( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_exec( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_select( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_result( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_lo_open( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_lo_close( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_lo_read( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_lo_write( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_lo_lseek( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_lo_creat( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_lo_tell( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_lo_unlink( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_lo_import( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_lo_export( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_listen( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); +extern int +Pg_notifies( + ClientData cData, Tcl_Interp * interp, int argc, char *argv[]); -#endif /*PGTCLCMDS_H*/ - +#endif /* PGTCLCMDS_H */ diff --git a/src/interfaces/libpgtcl/pgtclId.c b/src/interfaces/libpgtcl/pgtclId.c index f39342c002e..d6265974b43 100644 --- a/src/interfaces/libpgtcl/pgtclId.c +++ b/src/interfaces/libpgtcl/pgtclId.c @@ -1,18 +1,18 @@ /*------------------------------------------------------------------------- * * pgtclId.c-- - * useful routines to convert between strings and pointers - * Needed because everything in tcl is a string, but we want pointers - * to data structures + * useful routines to convert between strings and pointers + * Needed because everything in tcl is a string, but we want pointers + * to data structures * - * ASSUMPTION: sizeof(long) >= sizeof(void*) + * ASSUMPTION: sizeof(long) >= sizeof(void*) * * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.3 1996/11/11 12:14:45 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpgtcl/Attic/pgtclId.c,v 1.4 1997/09/07 05:03:13 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -29,39 +29,40 @@ * Create the Id for a new connection and hash it */ void -PgSetConnectionId(Pg_clientData *cd, char *id, PGconn *conn) +PgSetConnectionId(Pg_clientData * cd, char *id, PGconn * conn) { - Tcl_HashEntry *hent; - Pg_ConnectionId *connid; - int hnew; - - connid = (Pg_ConnectionId *)ckalloc(sizeof(Pg_ConnectionId)); - connid->conn = conn; - Tcl_InitHashTable(&(connid->res_hash), TCL_STRING_KEYS); - sprintf(connid->id, "pgc%ld", cd->dbh_count++); - strcpy(id, connid->id); - - hent = Tcl_CreateHashEntry(&(cd->dbh_hash), connid->id, &hnew); - Tcl_SetHashValue(hent, (ClientData)connid); + Tcl_HashEntry *hent; + Pg_ConnectionId *connid; + int hnew; + + connid = (Pg_ConnectionId *) ckalloc(sizeof(Pg_ConnectionId)); + connid->conn = conn; + Tcl_InitHashTable(&(connid->res_hash), TCL_STRING_KEYS); + sprintf(connid->id, "pgc%ld", cd->dbh_count++); + strcpy(id, connid->id); + + hent = Tcl_CreateHashEntry(&(cd->dbh_hash), connid->id, &hnew); + Tcl_SetHashValue(hent, (ClientData) connid); } /* * Get back the connection from the Id */ -PGconn * -PgGetConnectionId(Pg_clientData *cd, char *id) +PGconn * +PgGetConnectionId(Pg_clientData * cd, char *id) { - Tcl_HashEntry *hent; - Pg_ConnectionId *connid; + Tcl_HashEntry *hent; + Pg_ConnectionId *connid; - hent = Tcl_FindHashEntry(&(cd->dbh_hash), id); - if(hent == NULL) { - return (PGconn *)NULL; - } + hent = Tcl_FindHashEntry(&(cd->dbh_hash), id); + if (hent == NULL) + { + return (PGconn *) NULL; + } - connid = (Pg_ConnectionId *)Tcl_GetHashValue(hent); - return connid->conn; + connid = (Pg_ConnectionId *) Tcl_GetHashValue(hent); + return connid->conn; } @@ -70,36 +71,39 @@ PgGetConnectionId(Pg_clientData *cd, char *id) * close all portals the user forgot. */ void -PgDelConnectionId(Pg_clientData *cd, char *id) +PgDelConnectionId(Pg_clientData * cd, char *id) { - Tcl_HashEntry *hent; - Tcl_HashEntry *hent2; - Tcl_HashEntry *hent3; - Tcl_HashSearch hsearch; - Pg_ConnectionId *connid; - Pg_ResultId *resid; - - hent = Tcl_FindHashEntry(&(cd->dbh_hash), id); - if(hent == NULL) { - return; - } - - connid = (Pg_ConnectionId *)Tcl_GetHashValue(hent); - - hent2 = Tcl_FirstHashEntry(&(connid->res_hash), &hsearch); - while(hent2 != NULL) { - resid = (Pg_ResultId *)Tcl_GetHashValue(hent2); - PQclear(resid->result); - hent3 = Tcl_FindHashEntry(&(cd->res_hash), resid->id); - if(hent3 != NULL) { - Tcl_DeleteHashEntry(hent3); + Tcl_HashEntry *hent; + Tcl_HashEntry *hent2; + Tcl_HashEntry *hent3; + Tcl_HashSearch hsearch; + Pg_ConnectionId *connid; + Pg_ResultId *resid; + + hent = Tcl_FindHashEntry(&(cd->dbh_hash), id); + if (hent == NULL) + { + return; } - ckfree(resid); - hent2 = Tcl_NextHashEntry(&hsearch); - } - Tcl_DeleteHashTable(&(connid->res_hash)); - Tcl_DeleteHashEntry(hent); - ckfree(connid); + + connid = (Pg_ConnectionId *) Tcl_GetHashValue(hent); + + hent2 = Tcl_FirstHashEntry(&(connid->res_hash), &hsearch); + while (hent2 != NULL) + { + resid = (Pg_ResultId *) Tcl_GetHashValue(hent2); + PQclear(resid->result); + hent3 = Tcl_FindHashEntry(&(cd->res_hash), resid->id); + if (hent3 != NULL) + { + Tcl_DeleteHashEntry(hent3); + } + ckfree(resid); + hent2 = Tcl_NextHashEntry(&hsearch); + } + Tcl_DeleteHashTable(&(connid->res_hash)); + Tcl_DeleteHashEntry(hent); + ckfree(connid); } @@ -107,52 +111,57 @@ PgDelConnectionId(Pg_clientData *cd, char *id) * Create a new result Id and hash it */ void -PgSetResultId(Pg_clientData *cd, char *id, char *connid_c, PGresult *res) +PgSetResultId(Pg_clientData * cd, char *id, char *connid_c, PGresult * res) { - Tcl_HashEntry *hent; - Pg_ConnectionId *connid; - Pg_ResultId *resid; - int hnew; - - hent = Tcl_FindHashEntry(&(cd->dbh_hash), connid_c); - if(hent == NULL) { - connid = NULL; - } else { - connid = (Pg_ConnectionId *)Tcl_GetHashValue(hent); - } - - resid = (Pg_ResultId *)ckalloc(sizeof(Pg_ResultId)); - resid->result = res; - resid->connection = connid; - sprintf(resid->id, "pgr%ld", cd->res_count++); - strcpy(id, resid->id); - - hent = Tcl_CreateHashEntry(&(cd->res_hash), resid->id, &hnew); - Tcl_SetHashValue(hent, (ClientData)resid); - - if(connid != NULL) { - hent = Tcl_CreateHashEntry(&(connid->res_hash), resid->id, &hnew); - Tcl_SetHashValue(hent, (ClientData)resid); - } + Tcl_HashEntry *hent; + Pg_ConnectionId *connid; + Pg_ResultId *resid; + int hnew; + + hent = Tcl_FindHashEntry(&(cd->dbh_hash), connid_c); + if (hent == NULL) + { + connid = NULL; + } + else + { + connid = (Pg_ConnectionId *) Tcl_GetHashValue(hent); + } + + resid = (Pg_ResultId *) ckalloc(sizeof(Pg_ResultId)); + resid->result = res; + resid->connection = connid; + sprintf(resid->id, "pgr%ld", cd->res_count++); + strcpy(id, resid->id); + + hent = Tcl_CreateHashEntry(&(cd->res_hash), resid->id, &hnew); + Tcl_SetHashValue(hent, (ClientData) resid); + + if (connid != NULL) + { + hent = Tcl_CreateHashEntry(&(connid->res_hash), resid->id, &hnew); + Tcl_SetHashValue(hent, (ClientData) resid); + } } /* * Get back the result pointer from the Id */ -PGresult * -PgGetResultId(Pg_clientData *cd, char *id) +PGresult * +PgGetResultId(Pg_clientData * cd, char *id) { - Tcl_HashEntry *hent; - Pg_ResultId *resid; + Tcl_HashEntry *hent; + Pg_ResultId *resid; - hent = Tcl_FindHashEntry(&(cd->res_hash), id); - if(hent == NULL) { - return (PGresult *)NULL; - } + hent = Tcl_FindHashEntry(&(cd->res_hash), id); + if (hent == NULL) + { + return (PGresult *) NULL; + } - resid = (Pg_ResultId *)Tcl_GetHashValue(hent); - return resid->result; + resid = (Pg_ResultId *) Tcl_GetHashValue(hent); + return resid->result; } @@ -160,27 +169,30 @@ PgGetResultId(Pg_clientData *cd, char *id) * Remove a result Id from the hash tables */ void -PgDelResultId(Pg_clientData *cd, char *id) +PgDelResultId(Pg_clientData * cd, char *id) { - Tcl_HashEntry *hent; - Tcl_HashEntry *hent2; - Pg_ResultId *resid; - - hent = Tcl_FindHashEntry(&(cd->res_hash), id); - if(hent == NULL) { - return; - } - - resid = (Pg_ResultId *)Tcl_GetHashValue(hent); - if (resid->connection != NULL) { - hent2 = Tcl_FindHashEntry(&(resid->connection->res_hash), id); - if(hent2 != NULL) { - Tcl_DeleteHashEntry(hent2); + Tcl_HashEntry *hent; + Tcl_HashEntry *hent2; + Pg_ResultId *resid; + + hent = Tcl_FindHashEntry(&(cd->res_hash), id); + if (hent == NULL) + { + return; } - } - Tcl_DeleteHashEntry(hent); - ckfree(resid); + resid = (Pg_ResultId *) Tcl_GetHashValue(hent); + if (resid->connection != NULL) + { + hent2 = Tcl_FindHashEntry(&(resid->connection->res_hash), id); + if (hent2 != NULL) + { + Tcl_DeleteHashEntry(hent2); + } + } + + Tcl_DeleteHashEntry(hent); + ckfree(resid); } @@ -188,20 +200,20 @@ PgDelResultId(Pg_clientData *cd, char *id) * Get the connection Id from the result Id */ void -PgGetConnByResultId(Pg_clientData *cd, char *id, char *resid_c) +PgGetConnByResultId(Pg_clientData * cd, char *id, char *resid_c) { - Tcl_HashEntry *hent; - Pg_ResultId *resid; - - hent = Tcl_FindHashEntry(&(cd->res_hash), id); - if(hent == NULL) { - return; - } - - resid = (Pg_ResultId *)Tcl_GetHashValue(hent); - if (resid->connection != NULL) { - strcpy(id, resid->connection->id); - } -} + Tcl_HashEntry *hent; + Pg_ResultId *resid; + hent = Tcl_FindHashEntry(&(cd->res_hash), id); + if (hent == NULL) + { + return; + } + resid = (Pg_ResultId *) Tcl_GetHashValue(hent); + if (resid->connection != NULL) + { + strcpy(id, resid->connection->id); + } +} diff --git a/src/interfaces/libpgtcl/pgtclId.h b/src/interfaces/libpgtcl/pgtclId.h index 9cb431918aa..03856434d6b 100644 --- a/src/interfaces/libpgtcl/pgtclId.h +++ b/src/interfaces/libpgtcl/pgtclId.h @@ -1,22 +1,22 @@ /*------------------------------------------------------------------------- * * pgtclId.h-- - * useful routines to convert between strings and pointers - * Needed because everything in tcl is a string, but often, pointers - * to data structures are needed. - * + * useful routines to convert between strings and pointers + * Needed because everything in tcl is a string, but often, pointers + * to data structures are needed. + * * * Copyright (c) 1994, Regents of the University of California * - * $Id: pgtclId.h,v 1.2 1996/10/30 06:18:42 scrappy Exp $ + * $Id: pgtclId.h,v 1.3 1997/09/07 05:03:14 momjian Exp $ * *------------------------------------------------------------------------- */ -extern void PgSetConnectionId(Pg_clientData *cd, char *id, PGconn *conn); -extern PGconn *PgGetConnectionId(Pg_clientData *cd, char *id); -extern void PgDelConnectionId(Pg_clientData *cd, char *id); -extern void PgSetResultId(Pg_clientData *cd, char *id, char *connid, PGresult *res); -extern PGresult *PgGetResultId(Pg_clientData *cd, char *id); -extern void PgDelResultId(Pg_clientData *cd, char *id); -extern void PgGetConnByResultId(Pg_clientData *cd, char *id, char *resid); +extern void PgSetConnectionId(Pg_clientData * cd, char *id, PGconn * conn); +extern PGconn *PgGetConnectionId(Pg_clientData * cd, char *id); +extern void PgDelConnectionId(Pg_clientData * cd, char *id); +extern void PgSetResultId(Pg_clientData * cd, char *id, char *connid, PGresult * res); +extern PGresult *PgGetResultId(Pg_clientData * cd, char *id); +extern void PgDelResultId(Pg_clientData * cd, char *id); +extern void PgGetConnByResultId(Pg_clientData * cd, char *id, char *resid); diff --git a/src/interfaces/libpq/fe-auth.c b/src/interfaces/libpq/fe-auth.c index d058ec8ab78..433cc65ded7 100644 --- a/src/interfaces/libpq/fe-auth.c +++ b/src/interfaces/libpq/fe-auth.c @@ -1,34 +1,34 @@ /*------------------------------------------------------------------------- * * fe-auth.c-- - * The front-end (client) authorization routines + * The front-end (client) authorization routines * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.8 1997/08/12 20:16:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.9 1997/09/07 05:03:17 momjian Exp $ * *------------------------------------------------------------------------- */ /* * INTERFACE ROUTINES - * frontend (client) routines: - * fe_sendauth send authentication information - * fe_getauthname get user's name according to the client side - * of the authentication system - * fe_setauthsvc set frontend authentication service - * fe_getauthsvc get current frontend authentication service + * frontend (client) routines: + * fe_sendauth send authentication information + * fe_getauthname get user's name according to the client side + * of the authentication system + * fe_setauthsvc set frontend authentication service + * fe_getauthsvc get current frontend authentication service * * * */ #include <stdio.h> #include <string.h> -#include <sys/param.h> /* for MAXHOSTNAMELEN on most */ +#include <sys/param.h> /* for MAXHOSTNAMELEN on most */ #ifndef MAXHOSTNAMELEN -#include <netdb.h> /* for MAXHOSTNAMELEN on some */ +#include <netdb.h> /* for MAXHOSTNAMELEN on some */ #endif #include <unistd.h> #include <sys/types.h> @@ -47,12 +47,12 @@ *---------------------------------------------------------------- */ -struct authsvc { - char name[16]; /* service nickname (for command line) */ - MsgType msgtype; /* startup packet header type */ - int allowed; /* initially allowed (before command line - * option parsing)? - */ +struct authsvc +{ + char name[16]; /* service nickname (for command line) */ + MsgType msgtype; /* startup packet header type */ + int allowed; /* initially allowed (before command line + * option parsing)? */ }; /* @@ -67,24 +67,24 @@ struct authsvc { */ static struct authsvc authsvcs[] = { #ifdef KRB4 - { "krb4", STARTUP_KRB4_MSG, 1 }, - { "kerberos", STARTUP_KRB4_MSG, 1 }, -#endif /* KRB4 */ + {"krb4", STARTUP_KRB4_MSG, 1}, + {"kerberos", STARTUP_KRB4_MSG, 1}, +#endif /* KRB4 */ #ifdef KRB5 - { "krb5", STARTUP_KRB5_MSG, 1 }, - { "kerberos", STARTUP_KRB5_MSG, 1 }, -#endif /* KRB5 */ - { UNAUTHNAME, STARTUP_MSG, + {"krb5", STARTUP_KRB5_MSG, 1}, + {"kerberos", STARTUP_KRB5_MSG, 1}, +#endif /* KRB5 */ + {UNAUTHNAME, STARTUP_MSG, #if defined(KRB4) || defined(KRB5) - 0 -#else /* !(KRB4 || KRB5) */ - 1 -#endif /* !(KRB4 || KRB5) */ - }, - { "password", STARTUP_PASSWORD_MSG, 0 } + 0 +#else /* !(KRB4 || KRB5) */ + 1 +#endif /* !(KRB4 || KRB5) */ + }, + {"password", STARTUP_PASSWORD_MSG, 0} }; -static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc); +static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc); #ifdef KRB4 /*---------------------------------------------------------------- @@ -95,8 +95,8 @@ static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc); #include "krb.h" /* for some reason, this is not defined in krb.h ... */ -extern char *tkt_string(void); - +extern char *tkt_string(void); + /* * pg_krb4_init -- initialization performed before any Kerberos calls are made * @@ -104,60 +104,63 @@ extern char *tkt_string(void); * ticket file if we want them to see a special one. (They will open the file * themselves.) */ -static void pg_krb4_init() +static void +pg_krb4_init() { - char *realm; - static init_done = 0; - - if (init_done) - return; - init_done = 1; - - /* - * If the user set PGREALM, then we use a ticket file with a special - * name: <usual-ticket-file-name>@<PGREALM-value> - */ - if (realm = getenv("PGREALM")) { - char tktbuf[MAXPATHLEN]; - - (void) sprintf(tktbuf, "%s@%s", tkt_string(), realm); - krb_set_tkt_string(tktbuf); - } + char *realm; + static init_done = 0; + + if (init_done) + return; + init_done = 1; + + /* + * If the user set PGREALM, then we use a ticket file with a special + * name: <usual-ticket-file-name>@<PGREALM-value> + */ + if (realm = getenv("PGREALM")) + { + char tktbuf[MAXPATHLEN]; + + (void) sprintf(tktbuf, "%s@%s", tkt_string(), realm); + krb_set_tkt_string(tktbuf); + } } /* * pg_krb4_authname -- returns a pointer to static space containing whatever - * name the user has authenticated to the system + * name the user has authenticated to the system * * We obtain this information by digging around in the ticket file. */ -static char * -pg_krb4_authname(char* PQerrormsg) +static char * +pg_krb4_authname(char *PQerrormsg) { - char instance[INST_SZ]; - char realm[REALM_SZ]; - int status; - static char name[SNAME_SZ+1] = ""; - - if (name[0]) - return(name); - - pg_krb4_init(); - - name[SNAME_SZ] = '\0'; - status = krb_get_tf_fullname(tkt_string(), name, instance, realm); - if (status != KSUCCESS) { - (void) sprintf(PQerrormsg, - "pg_krb4_authname: krb_get_tf_fullname: %s\n", - krb_err_txt[status]); - return((char *) NULL); - } - return(name); + char instance[INST_SZ]; + char realm[REALM_SZ]; + int status; + static char name[SNAME_SZ + 1] = ""; + + if (name[0]) + return (name); + + pg_krb4_init(); + + name[SNAME_SZ] = '\0'; + status = krb_get_tf_fullname(tkt_string(), name, instance, realm); + if (status != KSUCCESS) + { + (void) sprintf(PQerrormsg, + "pg_krb4_authname: krb_get_tf_fullname: %s\n", + krb_err_txt[status]); + return ((char *) NULL); + } + return (name); } /* * pg_krb4_sendauth -- client routine to send authentication information to - * the server + * the server * * This routine does not do mutual authentication, nor does it return enough * information to do encrypted connections. But then, if we want to do @@ -170,48 +173,50 @@ pg_krb4_authname(char* PQerrormsg) * (canonicalized to omit all domain suffixes). */ static int -pg_krb4_sendauth(const char* PQerrormsg, int sock, - struct sockaddr_in *laddr, - struct sockaddr_in *raddr, - const char *hostname) +pg_krb4_sendauth(const char *PQerrormsg, int sock, + struct sockaddr_in * laddr, + struct sockaddr_in * raddr, + const char *hostname) { - long krbopts = 0; /* one-way authentication */ - KTEXT_ST clttkt; - int status; - char hostbuf[MAXHOSTNAMELEN]; - const char *realm = getenv("PGREALM"); /* NULL == current realm */ - - if (!hostname || !(*hostname)) { - if (gethostname(hostbuf, MAXHOSTNAMELEN) < 0) - strcpy(hostbuf, "localhost"); - hostname = hostbuf; - } - - pg_krb4_init(); - - status = krb_sendauth(krbopts, - sock, - &clttkt, - PG_KRB_SRVNAM, - hostname, - realm, - (u_long) 0, - (MSG_DAT *) NULL, - (CREDENTIALS *) NULL, - (Key_schedule *) NULL, - laddr, - raddr, - PG_KRB4_VERSION); - if (status != KSUCCESS) { - (void) sprintf(PQerrormsg, - "pg_krb4_sendauth: kerberos error: %s\n", - krb_err_txt[status]); - return(STATUS_ERROR); - } - return(STATUS_OK); + long krbopts = 0;/* one-way authentication */ + KTEXT_ST clttkt; + int status; + char hostbuf[MAXHOSTNAMELEN]; + const char *realm = getenv("PGREALM"); /* NULL == current realm */ + + if (!hostname || !(*hostname)) + { + if (gethostname(hostbuf, MAXHOSTNAMELEN) < 0) + strcpy(hostbuf, "localhost"); + hostname = hostbuf; + } + + pg_krb4_init(); + + status = krb_sendauth(krbopts, + sock, + &clttkt, + PG_KRB_SRVNAM, + hostname, + realm, + (u_long) 0, + (MSG_DAT *) NULL, + (CREDENTIALS *) NULL, + (Key_schedule *) NULL, + laddr, + raddr, + PG_KRB4_VERSION); + if (status != KSUCCESS) + { + (void) sprintf(PQerrormsg, + "pg_krb4_sendauth: kerberos error: %s\n", + krb_err_txt[status]); + return (STATUS_ERROR); + } + return (STATUS_OK); } -#endif /* KRB4 */ +#endif /* KRB4 */ #ifdef KRB5 /*---------------------------------------------------------------- @@ -223,25 +228,25 @@ pg_krb4_sendauth(const char* PQerrormsg, int sock, /* * pg_an_to_ln -- return the local name corresponding to an authentication - * name + * name * * XXX Assumes that the first aname component is the user name. This is NOT - * necessarily so, since an aname can actually be something out of your - * worst X.400 nightmare, like - * ORGANIZATION=U. C. Berkeley/NAME=Paul M. [email protected] - * Note that the MIT an_to_ln code does the same thing if you don't - * provide an aname mapping database...it may be a better idea to use - * krb5_an_to_ln, except that it punts if multiple components are found, - * and we can't afford to punt. + * necessarily so, since an aname can actually be something out of your + * worst X.400 nightmare, like + * ORGANIZATION=U. C. Berkeley/NAME=Paul M. [email protected] + * Note that the MIT an_to_ln code does the same thing if you don't + * provide an aname mapping database...it may be a better idea to use + * krb5_an_to_ln, except that it punts if multiple components are found, + * and we can't afford to punt. */ -static char * +static char * pg_an_to_ln(const char *aname) { - char *p; - - if ((p = strchr(aname, '/')) || (p = strchr(aname, '@'))) - *p = '\0'; - return(aname); + char *p; + + if ((p = strchr(aname, '/')) || (p = strchr(aname, '@'))) + *p = '\0'; + return (aname); } @@ -251,85 +256,92 @@ pg_an_to_ln(const char *aname) * With v5, we can no longer set the ticket (credential cache) file name; * we now have to provide a file handle for the open (well, "resolved") * ticket file everywhere. - * + * */ static int -krb5_ccache pg_krb5_init(void) +krb5_ccache +pg_krb5_init(void) { - krb5_error_code code; - char *realm, *defname; - char tktbuf[MAXPATHLEN]; - static krb5_ccache ccache = (krb5_ccache) NULL; - - if (ccache) - return(ccache); - - /* - * If the user set PGREALM, then we use a ticket file with a special - * name: <usual-ticket-file-name>@<PGREALM-value> - */ - if (!(defname = krb5_cc_default_name())) { - (void) sprintf(PQerrormsg, - "pg_krb5_init: krb5_cc_default_name failed\n"); - return((krb5_ccache) NULL); - } - strcpy(tktbuf, defname); - if (realm = getenv("PGREALM")) { - strcat(tktbuf, "@"); - strcat(tktbuf, realm); - } - - if (code = krb5_cc_resolve(tktbuf, &ccache)) { - (void) sprintf(PQerrormsg, - "pg_krb5_init: Kerberos error %d in krb5_cc_resolve\n", - code); - com_err("pg_krb5_init", code, "in krb5_cc_resolve"); - return((krb5_ccache) NULL); - } - return(ccache); + krb5_error_code code; + char *realm, + *defname; + char tktbuf[MAXPATHLEN]; + static krb5_ccache ccache = (krb5_ccache) NULL; + + if (ccache) + return (ccache); + + /* + * If the user set PGREALM, then we use a ticket file with a special + * name: <usual-ticket-file-name>@<PGREALM-value> + */ + if (!(defname = krb5_cc_default_name())) + { + (void) sprintf(PQerrormsg, + "pg_krb5_init: krb5_cc_default_name failed\n"); + return ((krb5_ccache) NULL); + } + strcpy(tktbuf, defname); + if (realm = getenv("PGREALM")) + { + strcat(tktbuf, "@"); + strcat(tktbuf, realm); + } + + if (code = krb5_cc_resolve(tktbuf, &ccache)) + { + (void) sprintf(PQerrormsg, + "pg_krb5_init: Kerberos error %d in krb5_cc_resolve\n", + code); + com_err("pg_krb5_init", code, "in krb5_cc_resolve"); + return ((krb5_ccache) NULL); + } + return (ccache); } /* * pg_krb5_authname -- returns a pointer to static space containing whatever - * name the user has authenticated to the system + * name the user has authenticated to the system * * We obtain this information by digging around in the ticket file. */ static const char * -pg_krb5_authname(const char* PQerrormsg) +pg_krb5_authname(const char *PQerrormsg) { - krb5_ccache ccache; - krb5_principal principal; - krb5_error_code code; - static char *authname = (char *) NULL; - - if (authname) - return(authname); - - ccache = pg_krb5_init(); /* don't free this */ - - if (code = krb5_cc_get_principal(ccache, &principal)) { - (void) sprintf(PQerrormsg, - "pg_krb5_authname: Kerberos error %d in krb5_cc_get_principal\n", - code); - com_err("pg_krb5_authname", code, "in krb5_cc_get_principal"); - return((char *) NULL); - } - if (code = krb5_unparse_name(principal, &authname)) { - (void) sprintf(PQerrormsg, - "pg_krb5_authname: Kerberos error %d in krb5_unparse_name\n", - code); - com_err("pg_krb5_authname", code, "in krb5_unparse_name"); + krb5_ccache ccache; + krb5_principal principal; + krb5_error_code code; + static char *authname = (char *) NULL; + + if (authname) + return (authname); + + ccache = pg_krb5_init(); /* don't free this */ + + if (code = krb5_cc_get_principal(ccache, &principal)) + { + (void) sprintf(PQerrormsg, + "pg_krb5_authname: Kerberos error %d in krb5_cc_get_principal\n", + code); + com_err("pg_krb5_authname", code, "in krb5_cc_get_principal"); + return ((char *) NULL); + } + if (code = krb5_unparse_name(principal, &authname)) + { + (void) sprintf(PQerrormsg, + "pg_krb5_authname: Kerberos error %d in krb5_unparse_name\n", + code); + com_err("pg_krb5_authname", code, "in krb5_unparse_name"); + krb5_free_principal(principal); + return ((char *) NULL); + } krb5_free_principal(principal); - return((char *) NULL); - } - krb5_free_principal(principal); - return(pg_an_to_ln(authname)); + return (pg_an_to_ln(authname)); } /* * pg_krb5_sendauth -- client routine to send authentication information to - * the server + * the server * * This routine does not do mutual authentication, nor does it return enough * information to do encrypted connections. But then, if we want to do @@ -337,159 +349,173 @@ pg_krb5_authname(const char* PQerrormsg) * anyway. * * Server hostnames are canonicalized v4-style, i.e., all domain suffixes - * are simply chopped off. Hence, we are assuming that you've entered your + * are simply chopped off. Hence, we are assuming that you've entered your * server instances as - * <value-of-PG_KRB_SRVNAM>/<canonicalized-hostname> - * in the PGREALM (or local) database. This is probably a bad assumption. + * <value-of-PG_KRB_SRVNAM>/<canonicalized-hostname> + * in the PGREALM (or local) database. This is probably a bad assumption. */ static int -pg_krb5_sendauth(const char* PQerrormsg,int sock, - struct sockaddr_in *laddr, - struct sockaddr_in *raddr, - const char *hostname) +pg_krb5_sendauth(const char *PQerrormsg, int sock, + struct sockaddr_in * laddr, + struct sockaddr_in * raddr, + const char *hostname) { - char servbuf[MAXHOSTNAMELEN + 1 + - sizeof(PG_KRB_SRVNAM)]; - const char *hostp; - const char *realm; - krb5_error_code code; - krb5_principal client, server; - krb5_ccache ccache; - krb5_error *error = (krb5_error *) NULL; - - ccache = pg_krb5_init(); /* don't free this */ - - /* - * set up client -- this is easy, we can get it out of the ticket - * file. - */ - if (code = krb5_cc_get_principal(ccache, &client)) { - (void) sprintf(PQerrormsg, - "pg_krb5_sendauth: Kerberos error %d in krb5_cc_get_principal\n", - code); - com_err("pg_krb5_sendauth", code, "in krb5_cc_get_principal"); - return(STATUS_ERROR); - } - - /* - * set up server -- canonicalize as described above - */ - strcpy(servbuf, PG_KRB_SRVNAM); - *(hostp = servbuf + (sizeof(PG_KRB_SRVNAM) - 1)) = '/'; - if (hostname || *hostname) { - strncpy(++hostp, hostname, MAXHOSTNAMELEN); - } else { - if (gethostname(++hostp, MAXHOSTNAMELEN) < 0) - strcpy(hostp, "localhost"); - } - if (hostp = strchr(hostp, '.')) - *hostp = '\0'; - if (realm = getenv("PGREALM")) { - strcat(servbuf, "@"); - strcat(servbuf, realm); - } - if (code = krb5_parse_name(servbuf, &server)) { - (void) sprintf(PQerrormsg, - "pg_krb5_sendauth: Kerberos error %d in krb5_parse_name\n", - code); - com_err("pg_krb5_sendauth", code, "in krb5_parse_name"); - krb5_free_principal(client); - return(STATUS_ERROR); - } - - /* - * The only thing we want back from krb5_sendauth is an error status - * and any error messages. - */ - if (code = krb5_sendauth((krb5_pointer) &sock, - PG_KRB5_VERSION, - client, - server, - (krb5_flags) 0, - (krb5_checksum *) NULL, - (krb5_creds *) NULL, - ccache, - (krb5_int32 *) NULL, - (krb5_keyblock **) NULL, - &error, - (krb5_ap_rep_enc_part **) NULL)) { - if ((code == KRB5_SENDAUTH_REJECTED) && error) { - (void) sprintf(PQerrormsg, - "pg_krb5_sendauth: authentication rejected: \"%*s\"\n", - error->text.length, error->text.data); - fputs(PQerrormsg, stderr); - pqdebug("%s", PQerrormsg); - } else { - (void) sprintf(PQerrormsg, - "pg_krb5_sendauth: Kerberos error %d in krb5_sendauth\n", - code); - com_err("pg_krb5_sendauth", code, "in krb5_sendauth"); + char servbuf[MAXHOSTNAMELEN + 1 + + sizeof(PG_KRB_SRVNAM)]; + const char *hostp; + const char *realm; + krb5_error_code code; + krb5_principal client, + server; + krb5_ccache ccache; + krb5_error *error = (krb5_error *) NULL; + + ccache = pg_krb5_init(); /* don't free this */ + + /* + * set up client -- this is easy, we can get it out of the ticket + * file. + */ + if (code = krb5_cc_get_principal(ccache, &client)) + { + (void) sprintf(PQerrormsg, + "pg_krb5_sendauth: Kerberos error %d in krb5_cc_get_principal\n", + code); + com_err("pg_krb5_sendauth", code, "in krb5_cc_get_principal"); + return (STATUS_ERROR); + } + + /* + * set up server -- canonicalize as described above + */ + strcpy(servbuf, PG_KRB_SRVNAM); + *(hostp = servbuf + (sizeof(PG_KRB_SRVNAM) - 1)) = '/'; + if (hostname || *hostname) + { + strncpy(++hostp, hostname, MAXHOSTNAMELEN); + } + else + { + if (gethostname(++hostp, MAXHOSTNAMELEN) < 0) + strcpy(hostp, "localhost"); + } + if (hostp = strchr(hostp, '.')) + *hostp = '\0'; + if (realm = getenv("PGREALM")) + { + strcat(servbuf, "@"); + strcat(servbuf, realm); + } + if (code = krb5_parse_name(servbuf, &server)) + { + (void) sprintf(PQerrormsg, + "pg_krb5_sendauth: Kerberos error %d in krb5_parse_name\n", + code); + com_err("pg_krb5_sendauth", code, "in krb5_parse_name"); + krb5_free_principal(client); + return (STATUS_ERROR); + } + + /* + * The only thing we want back from krb5_sendauth is an error status + * and any error messages. + */ + if (code = krb5_sendauth((krb5_pointer) & sock, + PG_KRB5_VERSION, + client, + server, + (krb5_flags) 0, + (krb5_checksum *) NULL, + (krb5_creds *) NULL, + ccache, + (krb5_int32 *) NULL, + (krb5_keyblock **) NULL, + &error, + (krb5_ap_rep_enc_part **) NULL)) + { + if ((code == KRB5_SENDAUTH_REJECTED) && error) + { + (void) sprintf(PQerrormsg, + "pg_krb5_sendauth: authentication rejected: \"%*s\"\n", + error->text.length, error->text.data); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + } + else + { + (void) sprintf(PQerrormsg, + "pg_krb5_sendauth: Kerberos error %d in krb5_sendauth\n", + code); + com_err("pg_krb5_sendauth", code, "in krb5_sendauth"); + } } - } - krb5_free_principal(client); - krb5_free_principal(server); - return(code ? STATUS_ERROR : STATUS_OK); + krb5_free_principal(client); + krb5_free_principal(server); + return (code ? STATUS_ERROR : STATUS_OK); } -#endif /* KRB5 */ +#endif /* KRB5 */ static int -pg_password_sendauth(Port *port, const char *user, const char *password) +pg_password_sendauth(Port * port, const char *user, const char *password) { - PacketBuf buf; - char *tmp; + PacketBuf buf; + char *tmp; - buf.len = htonl(sizeof(PacketBuf)); - buf.msgtype = STARTUP_PASSWORD_MSG; - buf.data[0] = '\0'; + buf.len = htonl(sizeof(PacketBuf)); + buf.msgtype = STARTUP_PASSWORD_MSG; + buf.data[0] = '\0'; - tmp = buf.data; - strncpy(tmp, user, strlen(user)+1); - tmp += strlen(user)+1; - strncpy(tmp, password, strlen(password)+1); + tmp = buf.data; + strncpy(tmp, user, strlen(user) + 1); + tmp += strlen(user) + 1; + strncpy(tmp, password, strlen(password) + 1); - return packetSend(port, &buf, sizeof(PacketBuf), BLOCKING); + return packetSend(port, &buf, sizeof(PacketBuf), BLOCKING); } /* * fe_sendauth -- client demux routine for outgoing authentication information */ int -fe_sendauth(MsgType msgtype, Port *port, const char *hostname, - const char *user, const char *password, const char* PQerrormsg) +fe_sendauth(MsgType msgtype, Port * port, const char *hostname, + const char *user, const char *password, const char *PQerrormsg) { - switch (msgtype) { + switch (msgtype) + { #ifdef KRB4 - case STARTUP_KRB4_MSG: - if (pg_krb4_sendauth(PQerrormsg, port->sock, &port->laddr, - &port->raddr, - hostname) != STATUS_OK) { - (void) sprintf(PQerrormsg, - "fe_sendauth: krb4 authentication failed\n"); -/* fputs(PQerrormsg, stderr); */ - return(STATUS_ERROR); - } - break; + case STARTUP_KRB4_MSG: + if (pg_krb4_sendauth(PQerrormsg, port->sock, &port->laddr, + &port->raddr, + hostname) != STATUS_OK) + { + (void) sprintf(PQerrormsg, + "fe_sendauth: krb4 authentication failed\n"); +/* fputs(PQerrormsg, stderr); */ + return (STATUS_ERROR); + } + break; #endif #ifdef KRB5 - case STARTUP_KRB5_MSG: - if (pg_krb5_sendauth(PQerrormsg,port->sock, &port->laddr, - &port->raddr, - hostname) != STATUS_OK) { - (void) sprintf(PQerrormsg, - "fe_sendauth: krb5 authentication failed\n"); - return(STATUS_ERROR); - } - break; + case STARTUP_KRB5_MSG: + if (pg_krb5_sendauth(PQerrormsg, port->sock, &port->laddr, + &port->raddr, + hostname) != STATUS_OK) + { + (void) sprintf(PQerrormsg, + "fe_sendauth: krb5 authentication failed\n"); + return (STATUS_ERROR); + } + break; #endif - case STARTUP_MSG: - break; - case STARTUP_PASSWORD_MSG: - pg_password_sendauth(port, user, password); - default: - break; - } - return(STATUS_OK); + case STARTUP_MSG: + break; + case STARTUP_PASSWORD_MSG: + pg_password_sendauth(port, user, password); + default: + break; + } + return (STATUS_OK); } /* @@ -499,74 +525,77 @@ fe_sendauth(MsgType msgtype, Port *port, const char *hostname, * Set/return the authentication service currently selected for use by the * frontend. (You can only use one in the frontend, obviously.) */ -static pg_authsvc = -1; +static pg_authsvc = -1; void -fe_setauthsvc(const char *name, char* PQerrormsg) +fe_setauthsvc(const char *name, char *PQerrormsg) { - int i; - - for (i = 0; i < n_authsvcs; ++i) - if (!strcmp(name, authsvcs[i].name)) { - pg_authsvc = i; - break; + int i; + + for (i = 0; i < n_authsvcs; ++i) + if (!strcmp(name, authsvcs[i].name)) + { + pg_authsvc = i; + break; + } + if (i == n_authsvcs) + { + (void) sprintf(PQerrormsg, + "fe_setauthsvc: invalid name: %s, ignoring...\n", + name); } - if (i == n_authsvcs) { - (void) sprintf(PQerrormsg, - "fe_setauthsvc: invalid name: %s, ignoring...\n", - name); - } - return; + return; } MsgType -fe_getauthsvc(char* PQerrormsg) +fe_getauthsvc(char *PQerrormsg) { - if (pg_authsvc < 0 || pg_authsvc >= n_authsvcs) - fe_setauthsvc(DEFAULT_CLIENT_AUTHSVC,PQerrormsg); - return(authsvcs[pg_authsvc].msgtype); + if (pg_authsvc < 0 || pg_authsvc >= n_authsvcs) + fe_setauthsvc(DEFAULT_CLIENT_AUTHSVC, PQerrormsg); + return (authsvcs[pg_authsvc].msgtype); } /* * fe_getauthname -- returns a pointer to dynamic space containing whatever - * name the user has authenticated to the system + * name the user has authenticated to the system * if there is an error, return the error message in PQerrormsg */ -char* -fe_getauthname(char* PQerrormsg) +char * +fe_getauthname(char *PQerrormsg) { - char *name = (char *) NULL; - char *authn = (char *) NULL; - MsgType authsvc; - - authsvc = fe_getauthsvc(PQerrormsg); - switch ((int) authsvc) { + char *name = (char *) NULL; + char *authn = (char *) NULL; + MsgType authsvc; + + authsvc = fe_getauthsvc(PQerrormsg); + switch ((int) authsvc) + { #ifdef KRB4 - case STARTUP_KRB4_MSG: - name = pg_krb4_authname(PQerrormsg); - break; + case STARTUP_KRB4_MSG: + name = pg_krb4_authname(PQerrormsg); + break; #endif #ifdef KRB5 - case STARTUP_KRB5_MSG: - name = pg_krb5_authname(PQerrormsg); - break; + case STARTUP_KRB5_MSG: + name = pg_krb5_authname(PQerrormsg); + break; #endif - case STARTUP_MSG: - { - struct passwd *pw = getpwuid(geteuid()); - if (pw) name = pw->pw_name; + case STARTUP_MSG: + { + struct passwd *pw = getpwuid(geteuid()); + + if (pw) + name = pw->pw_name; + } + break; + default: + (void) sprintf(PQerrormsg, + "fe_getauthname: invalid authentication system: %d\n", + authsvc); + break; } - break; - default: - (void) sprintf(PQerrormsg, - "fe_getauthname: invalid authentication system: %d\n", - authsvc); - break; - } - - if(name && (authn = (char *) malloc(strlen(name) + 1))) - strcpy(authn, name); - return(authn); -} - + if (name && (authn = (char *) malloc(strlen(name) + 1))) + strcpy(authn, name); + return (authn); +} diff --git a/src/interfaces/libpq/fe-auth.h b/src/interfaces/libpq/fe-auth.h index 646f93df37a..6ca83fe4e89 100644 --- a/src/interfaces/libpq/fe-auth.h +++ b/src/interfaces/libpq/fe-auth.h @@ -1,17 +1,17 @@ /*------------------------------------------------------------------------- * * fe-auth.h - * - * Definitions for network authentication routines + * + * Definitions for network authentication routines * * Copyright (c) 1994, Regents of the University of California * - * $Id: fe-auth.h,v 1.3 1997/03/12 21:23:04 scrappy Exp $ + * $Id: fe-auth.h,v 1.4 1997/09/07 05:03:21 momjian Exp $ * *------------------------------------------------------------------------- */ #ifndef FE_AUTH_H -#define FE_AUTH_H +#define FE_AUTH_H /*---------------------------------------------------------------- * Common routines and definitions @@ -19,22 +19,22 @@ */ /* what we call "no authentication system" */ -#define UNAUTHNAME "unauth" +#define UNAUTHNAME "unauth" /* what a frontend uses by default */ #if !defined(KRB4) && !defined(KRB5) -#define DEFAULT_CLIENT_AUTHSVC UNAUTHNAME -#else /* KRB4 || KRB5 */ -#define DEFAULT_CLIENT_AUTHSVC "kerberos" -#endif /* KRB4 || KRB5 */ - -extern int fe_sendauth(MsgType msgtype, Port *port, const char *hostname, - const char *user, const char *password, - const char* PQerromsg); -extern void fe_setauthsvc(const char *name, char* PQerrormsg); +#define DEFAULT_CLIENT_AUTHSVC UNAUTHNAME +#else /* KRB4 || KRB5 */ +#define DEFAULT_CLIENT_AUTHSVC "kerberos" +#endif /* KRB4 || KRB5 */ -#define PG_KRB4_VERSION "PGVER4.1" /* at most KRB_SENDAUTH_VLEN chars */ -#define PG_KRB5_VERSION "PGVER5.1" +extern int +fe_sendauth(MsgType msgtype, Port * port, const char *hostname, + const char *user, const char *password, + const char *PQerromsg); +extern void fe_setauthsvc(const char *name, char *PQerrormsg); -#endif /* FE_AUTH_H */ +#define PG_KRB4_VERSION "PGVER4.1" /* at most KRB_SENDAUTH_VLEN chars */ +#define PG_KRB5_VERSION "PGVER5.1" +#endif /* FE_AUTH_H */ diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index cb9b10d8704..1b6a1c1243d 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * fe-connect.c-- - * functions related to setting up a connection to the backend + * functions related to setting up a connection to the backend * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.38 1997/09/05 00:09:43 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.39 1997/09/07 05:03:24 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -24,10 +24,11 @@ #include <netinet/tcp.h> #include <errno.h> #include <signal.h> -#include <ctype.h> /* for isspace() */ +#include <ctype.h> /* for isspace() */ #include "postgres.h" -#include "libpq/pqcomm.h" /* for decls of MsgType, PacketBuf, StartupInfo */ +#include "libpq/pqcomm.h" /* for decls of MsgType, PacketBuf, + * StartupInfo */ #include "fe-auth.h" #include "fe-connect.h" #include "libpq-fe.h" @@ -38,14 +39,14 @@ /* use a local version instead of the one found in pqpacket.c */ -static ConnStatusType connectDB(PGconn *conn); +static ConnStatusType connectDB(PGconn * conn); -static void startup2PacketBuf(StartupInfo* s, PacketBuf* res); -static void freePGconn(PGconn *conn); -static void closePGconn(PGconn *conn); -static int conninfo_parse(const char *conninfo, char *errorMessage); -static char *conninfo_getval(char *keyword); -static void conninfo_free(void); +static void startup2PacketBuf(StartupInfo * s, PacketBuf * res); +static void freePGconn(PGconn * conn); +static void closePGconn(PGconn * conn); +static int conninfo_parse(const char *conninfo, char *errorMessage); +static char *conninfo_getval(char *keyword); +static void conninfo_free(void); #define NOTIFYLIST_INITIAL_SIZE 10 #define NOTIFYLIST_GROWBY 10 @@ -65,60 +66,66 @@ static void conninfo_free(void); * The Label and Disp-Char entries are provided for applications that * want to use PQconndefaults() to create a generic database connection * dialog. Disp-Char is defined as follows: - * "" Normal input field + * "" Normal input field * ---------- */ static PQconninfoOption PQconninfoOptions[] = { -/* ----------------------------------------------------------------- */ -/* Option-name Environment-Var Compiled-in Current value */ -/* Label Disp-Char */ -/* ----------------- --------------- --------------- --------------- */ - { "authtype", "PGAUTHTYPE", DefaultAuthtype, NULL, - "Database-Authtype", "", 20 }, +/* ----------------------------------------------------------------- */ +/* Option-name Environment-Var Compiled-in Current value */ +/* Label Disp-Char */ +/* ----------------- --------------- --------------- --------------- */ + {"authtype", "PGAUTHTYPE", DefaultAuthtype, NULL, + "Database-Authtype", "", 20}, - { "user", "PGUSER", NULL, NULL, - "Database-User", "", 20 }, + {"user", "PGUSER", NULL, NULL, + "Database-User", "", 20}, - { "password", "PGPASSWORD", DefaultPassword, NULL, - "Database-Password", "", 20 }, + {"password", "PGPASSWORD", DefaultPassword, NULL, + "Database-Password", "", 20}, - { "dbname", "PGDATABASE", NULL, NULL, - "Database-Name", "", 20 }, + {"dbname", "PGDATABASE", NULL, NULL, + "Database-Name", "", 20}, - { "host", "PGHOST", DefaultHost, NULL, - "Database-Host", "", 40 }, + {"host", "PGHOST", DefaultHost, NULL, + "Database-Host", "", 40}, - { "port", "PGPORT", DEF_PGPORT, NULL, - "Database-Port", "", 6 }, + {"port", "PGPORT", DEF_PGPORT, NULL, + "Database-Port", "", 6}, - { "tty", "PGTTY", DefaultTty, NULL, - "Backend-Debug-TTY", "D", 40 }, + {"tty", "PGTTY", DefaultTty, NULL, + "Backend-Debug-TTY", "D", 40}, - { "options", "PGOPTIONS", DefaultOption, NULL, - "Backend-Debug-Options", "D", 40 }, -/* ----------------- --------------- --------------- --------------- */ - { NULL, NULL, NULL, NULL, - NULL, NULL, 0 } + {"options", "PGOPTIONS", DefaultOption, NULL, + "Backend-Debug-Options", "D", 40}, +/* ----------------- --------------- --------------- --------------- */ + {NULL, NULL, NULL, NULL, + NULL, NULL, 0} }; struct EnvironmentOptions +{ + const char *envName, + *pgName; +} EnvironmentOptions[] = + +{ { - const char *envName, *pgName; - } EnvironmentOptions[] = + "PG_DATESTYLE", "datestyle" + }, { - { "PG_DATESTYLE", "datestyle" }, - { NULL } - }; - + NULL + } +}; + /* ---------------- - * PQconnectdb - * + * PQconnectdb + * * establishes a connectin to a postgres backend through the postmaster * using connection information in a string. * * The conninfo string is a list of * - * option = value + * option = value * * definitions. Value might be a single value containing no whitespaces * or a single quoted string. If a single quote should appear everywhere @@ -126,547 +133,624 @@ struct EnvironmentOptions * * Returns a PGconn* which is needed for all subsequent libpq calls * if the status field of the connection returned is CONNECTION_BAD, - * then some fields may be null'ed out instead of having valid values + * then some fields may be null'ed out instead of having valid values * ---------------- */ -PGconn* +PGconn * PQconnectdb(const char *conninfo) { - PGconn *conn; - PQconninfoOption *option; - char errorMessage[ERROR_MSG_LENGTH]; - - /* ---------- - * Allocate memory for the conn structure - * ---------- - */ - conn = (PGconn*)malloc(sizeof(PGconn)); - if (conn == NULL) { - fprintf(stderr, - "FATAL: PQsetdb() -- unable to allocate memory for a PGconn"); - return (PGconn*)NULL; - } - memset((char *)conn, 0, sizeof(PGconn)); - - /* ---------- - * Parse the conninfo string and get the fallback resources - * ---------- - */ - if(conninfo_parse(conninfo, errorMessage) < 0) { - conn->status = CONNECTION_BAD; - strcpy(conn->errorMessage, errorMessage); - conninfo_free(); - return conn; - } + PGconn *conn; + PQconninfoOption *option; + char errorMessage[ERROR_MSG_LENGTH]; - /* ---------- - * Check that we have all connection parameters - * ---------- - */ - for(option = PQconninfoOptions; option->keyword != NULL; option++) { - if(option->val != NULL) continue; /* Value was in conninfo */ + /* ---------- + * Allocate memory for the conn structure + * ---------- + */ + conn = (PGconn *) malloc(sizeof(PGconn)); + if (conn == NULL) + { + fprintf(stderr, + "FATAL: PQsetdb() -- unable to allocate memory for a PGconn"); + return (PGconn *) NULL; + } + memset((char *) conn, 0, sizeof(PGconn)); /* ---------- - * No value was found for this option. Return an error. + * Parse the conninfo string and get the fallback resources * ---------- */ - conn->status = CONNECTION_BAD; - sprintf(conn->errorMessage, - "ERROR: PQconnectdb(): Cannot determine a value for option '%s'.\n", - option->keyword); - strcat(conn->errorMessage, - "Option not specified in conninfo string"); - if(option->environ) { - strcat(conn->errorMessage, - ", environment variable "); - strcat(conn->errorMessage, option->environ); - strcat(conn->errorMessage, "\nnot set"); + if (conninfo_parse(conninfo, errorMessage) < 0) + { + conn->status = CONNECTION_BAD; + strcpy(conn->errorMessage, errorMessage); + conninfo_free(); + return conn; } - strcat(conn->errorMessage, " and no compiled in default value.\n"); + + /* ---------- + * Check that we have all connection parameters + * ---------- + */ + for (option = PQconninfoOptions; option->keyword != NULL; option++) + { + if (option->val != NULL) + continue; /* Value was in conninfo */ + + /* ---------- + * No value was found for this option. Return an error. + * ---------- + */ + conn->status = CONNECTION_BAD; + sprintf(conn->errorMessage, + "ERROR: PQconnectdb(): Cannot determine a value for option '%s'.\n", + option->keyword); + strcat(conn->errorMessage, + "Option not specified in conninfo string"); + if (option->environ) + { + strcat(conn->errorMessage, + ", environment variable "); + strcat(conn->errorMessage, option->environ); + strcat(conn->errorMessage, "\nnot set"); + } + strcat(conn->errorMessage, " and no compiled in default value.\n"); + conninfo_free(); + return conn; + } + + /* ---------- + * Setup the conn structure + * ---------- + */ + conn->lobjfuncs = (PGlobjfuncs *) NULL; + conn->Pfout = NULL; + conn->Pfin = NULL; + conn->Pfdebug = NULL; + conn->port = NULL; + conn->notifyList = DLNewList(); + + conn->pghost = strdup(conninfo_getval("host")); + conn->pgport = strdup(conninfo_getval("port")); + conn->pgtty = strdup(conninfo_getval("tty")); + conn->pgoptions = strdup(conninfo_getval("options")); + conn->pguser = strdup(conninfo_getval("user")); + conn->pgpass = strdup(conninfo_getval("password")); + conn->pgauth = strdup(conninfo_getval("authtype")); + conn->dbName = strdup(conninfo_getval("dbname")); + + /* ---------- + * Free the connection info - all is in conn now + * ---------- + */ conninfo_free(); + + /* + * try to set the auth service if one was specified + */ + if (conn->pgauth) + { + fe_setauthsvc(conn->pgauth, conn->errorMessage); + } + + /* ---------- + * Connect to the database + * ---------- + */ + conn->status = connectDB(conn); + if (conn->status == CONNECTION_OK) + { + PGresult *res; + + /* + * Send a blank query to make sure everything works; in + * particular, that the database exists. + */ + res = PQexec(conn, " "); + if (res == NULL || res->resultStatus != PGRES_EMPTY_QUERY) + { + /* PQexec has put error message in conn->errorMessage */ + closePGconn(conn); + } + PQclear(res); + } + return conn; - } - - /* ---------- - * Setup the conn structure - * ---------- - */ - conn->lobjfuncs = (PGlobjfuncs *) NULL; - conn->Pfout = NULL; - conn->Pfin = NULL; - conn->Pfdebug = NULL; - conn->port = NULL; - conn->notifyList = DLNewList(); - - conn->pghost = strdup(conninfo_getval("host")); - conn->pgport = strdup(conninfo_getval("port")); - conn->pgtty = strdup(conninfo_getval("tty")); - conn->pgoptions = strdup(conninfo_getval("options")); - conn->pguser = strdup(conninfo_getval("user")); - conn->pgpass = strdup(conninfo_getval("password")); - conn->pgauth = strdup(conninfo_getval("authtype")); - conn->dbName = strdup(conninfo_getval("dbname")); - - /* ---------- - * Free the connection info - all is in conn now - * ---------- - */ - conninfo_free(); - - /* - * try to set the auth service if one was specified - */ - if(conn->pgauth) { - fe_setauthsvc(conn->pgauth, conn->errorMessage); - } - - /* ---------- - * Connect to the database - * ---------- - */ - conn->status = connectDB(conn); - if (conn->status == CONNECTION_OK) { - PGresult *res; - /* Send a blank query to make sure everything works; in particular, that - the database exists. - */ - res = PQexec(conn," "); - if (res == NULL || res->resultStatus != PGRES_EMPTY_QUERY) { - /* PQexec has put error message in conn->errorMessage */ - closePGconn(conn); - } - PQclear(res); - } - - return conn; } /* ---------------- - * PQconndefaults - * + * PQconndefaults + * * Parse an empty string like PQconnectdb() would do and return the * address of the connection options structure. Using this function * an application might determine all possible options and their * current default values. * ---------------- */ -PQconninfoOption* +PQconninfoOption * PQconndefaults(void) { - char errorMessage[ERROR_MSG_LENGTH]; + char errorMessage[ERROR_MSG_LENGTH]; - conninfo_parse("", errorMessage); - return PQconninfoOptions; + conninfo_parse("", errorMessage); + return PQconninfoOptions; } /* ---------------- - * PQsetdb - * + * PQsetdb + * * establishes a connection to a postgres backend through the postmaster * at the specified host and port. * * returns a PGconn* which is needed for all subsequent libpq calls * if the status field of the connection returned is CONNECTION_BAD, - * then some fields may be null'ed out instead of having valid values + * then some fields may be null'ed out instead of having valid values * - * Uses these environment variables: + * Uses these environment variables: * - * PGHOST identifies host to which to connect if <pghost> argument - * is NULL or a null string. + * PGHOST identifies host to which to connect if <pghost> argument + * is NULL or a null string. * - * PGPORT identifies TCP port to which to connect if <pgport> argument - * is NULL or a null string. + * PGPORT identifies TCP port to which to connect if <pgport> argument + * is NULL or a null string. * - * PGTTY identifies tty to which to send messages if <pgtty> argument - * is NULL or a null string. + * PGTTY identifies tty to which to send messages if <pgtty> argument + * is NULL or a null string. * - * PGOPTIONS identifies connection options if <pgoptions> argument is - * NULL or a null string. + * PGOPTIONS identifies connection options if <pgoptions> argument is + * NULL or a null string. * - * PGUSER Postgres username to associate with the connection. + * PGUSER Postgres username to associate with the connection. * - * PGPASSWORD The user's password. + * PGPASSWORD The user's password. * - * PGDATABASE name of database to which to connect if <pgdatabase> - * argument is NULL or a null string + * PGDATABASE name of database to which to connect if <pgdatabase> + * argument is NULL or a null string * - * None of the above need be defined. There are defaults for all of them. + * None of the above need be defined. There are defaults for all of them. * * ---------------- */ -PGconn* -PQsetdb(const char *pghost, const char* pgport, const char* pgoptions, const char* pgtty, const char* dbName) +PGconn * +PQsetdb(const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName) { - PGconn *conn; - char *tmp; - char errorMessage[ERROR_MSG_LENGTH]; - /* An error message from some service we call. */ - bool error; - /* We encountered an error that prevents successful completion */ - int i; - - conn = (PGconn*)malloc(sizeof(PGconn)); - - if (conn == NULL) - fprintf(stderr, - "FATAL: PQsetdb() -- unable to allocate memory for a PGconn"); - else { - conn->lobjfuncs = (PGlobjfuncs *) NULL; - conn->Pfout = NULL; - conn->Pfin = NULL; - conn->Pfdebug = NULL; - conn->port = NULL; - conn->notifyList = DLNewList(); - - if (!pghost || pghost[0] == '\0') { - if (!(tmp = getenv("PGHOST"))) { - tmp = DefaultHost; - } - conn->pghost = strdup(tmp); - } else - conn->pghost = strdup(pghost); - - if (!pgport || pgport[0] == '\0') { - if (!(tmp = getenv("PGPORT"))) { - tmp = DEF_PGPORT; - } - conn->pgport = strdup(tmp); - } else - conn->pgport = strdup(pgport); - - if (!pgtty || pgtty[0] == '\0') { - if (!(tmp = getenv("PGTTY"))) { - tmp = DefaultTty; - } - conn->pgtty = strdup(tmp); - } else - conn->pgtty = strdup(pgtty); - - if (!pgoptions || pgoptions[0] == '\0') { - if (!(tmp = getenv("PGOPTIONS"))) { - tmp = DefaultOption; - } - conn->pgoptions = strdup(tmp); - } else - conn->pgoptions = strdup(pgoptions); - - if ((tmp = getenv("PGUSER"))) { - error = FALSE; - conn->pguser = strdup(tmp); - } else { - tmp = fe_getauthname(errorMessage); - if (tmp == 0) { - error = TRUE; - sprintf(conn->errorMessage, - "FATAL: PQsetdb: Unable to determine a Postgres username!\n"); - } else { - error = FALSE; - conn->pguser = tmp; - } - } - - if((tmp = getenv("PGPASSWORD"))) { - conn->pgpass = strdup(tmp); - } else { - conn->pgpass = 0; - } - - if (!error) { - if (((tmp = (char *)dbName) && (dbName[0] != '\0')) || - ((tmp = getenv("PGDATABASE")))) { - conn->dbName = strdup(tmp); - } else conn->dbName = strdup(conn->pguser); - for(i = 0; conn->dbName[i]; i++) - if (isupper(conn->dbName[i])) - conn->dbName[i] = tolower(conn->dbName[i]); - } else conn->dbName = NULL; - - if (error) conn->status = CONNECTION_BAD; - else { - conn->status = connectDB(conn); - /* Puts message in conn->errorMessage */ - if (conn->status == CONNECTION_OK) { - PGresult *res; - /* Send a blank query to make sure everything works; - in particular, that the database exists. - */ - res = PQexec(conn," "); - if (res == NULL || res->resultStatus != PGRES_EMPTY_QUERY) { - /* PQexec has put error message in conn->errorMessage */ - closePGconn(conn); - } - PQclear(res); - } - } - } - return conn; + PGconn *conn; + char *tmp; + char errorMessage[ERROR_MSG_LENGTH]; + + /* An error message from some service we call. */ + bool error; + + /* We encountered an error that prevents successful completion */ + int i; + + conn = (PGconn *) malloc(sizeof(PGconn)); + + if (conn == NULL) + fprintf(stderr, + "FATAL: PQsetdb() -- unable to allocate memory for a PGconn"); + else + { + conn->lobjfuncs = (PGlobjfuncs *) NULL; + conn->Pfout = NULL; + conn->Pfin = NULL; + conn->Pfdebug = NULL; + conn->port = NULL; + conn->notifyList = DLNewList(); + + if (!pghost || pghost[0] == '\0') + { + if (!(tmp = getenv("PGHOST"))) + { + tmp = DefaultHost; + } + conn->pghost = strdup(tmp); + } + else + conn->pghost = strdup(pghost); + + if (!pgport || pgport[0] == '\0') + { + if (!(tmp = getenv("PGPORT"))) + { + tmp = DEF_PGPORT; + } + conn->pgport = strdup(tmp); + } + else + conn->pgport = strdup(pgport); + + if (!pgtty || pgtty[0] == '\0') + { + if (!(tmp = getenv("PGTTY"))) + { + tmp = DefaultTty; + } + conn->pgtty = strdup(tmp); + } + else + conn->pgtty = strdup(pgtty); + + if (!pgoptions || pgoptions[0] == '\0') + { + if (!(tmp = getenv("PGOPTIONS"))) + { + tmp = DefaultOption; + } + conn->pgoptions = strdup(tmp); + } + else + conn->pgoptions = strdup(pgoptions); + + if ((tmp = getenv("PGUSER"))) + { + error = FALSE; + conn->pguser = strdup(tmp); + } + else + { + tmp = fe_getauthname(errorMessage); + if (tmp == 0) + { + error = TRUE; + sprintf(conn->errorMessage, + "FATAL: PQsetdb: Unable to determine a Postgres username!\n"); + } + else + { + error = FALSE; + conn->pguser = tmp; + } + } + + if ((tmp = getenv("PGPASSWORD"))) + { + conn->pgpass = strdup(tmp); + } + else + { + conn->pgpass = 0; + } + + if (!error) + { + if (((tmp = (char *) dbName) && (dbName[0] != '\0')) || + ((tmp = getenv("PGDATABASE")))) + { + conn->dbName = strdup(tmp); + } + else + conn->dbName = strdup(conn->pguser); + for (i = 0; conn->dbName[i]; i++) + if (isupper(conn->dbName[i])) + conn->dbName[i] = tolower(conn->dbName[i]); + } + else + conn->dbName = NULL; + + if (error) + conn->status = CONNECTION_BAD; + else + { + conn->status = connectDB(conn); + /* Puts message in conn->errorMessage */ + if (conn->status == CONNECTION_OK) + { + PGresult *res; + + /* + * Send a blank query to make sure everything works; in + * particular, that the database exists. + */ + res = PQexec(conn, " "); + if (res == NULL || res->resultStatus != PGRES_EMPTY_QUERY) + { + /* PQexec has put error message in conn->errorMessage */ + closePGconn(conn); + } + PQclear(res); + } + } + } + return conn; } - + /* * connectDB - - * make a connection to the backend so it is ready to receive queries. + * make a connection to the backend so it is ready to receive queries. * return CONNECTION_OK if successful, CONNECTION_BAD if not. * */ -static ConnStatusType -connectDB(PGconn *conn) +static ConnStatusType +connectDB(PGconn * conn) { - struct hostent *hp; - - StartupInfo startup; - PacketBuf pacBuf; - int status; - MsgType msgtype; - int laddrlen = sizeof(struct sockaddr); - Port *port = conn->port; - int portno; - - /* - * - * Initialize the startup packet. - * - * This data structure is used for the seq-packet protocol. It - * describes the frontend-backend connection. - * - * - */ - strncpy(startup.user,conn->pguser,sizeof(startup.user)); - strncpy(startup.database,conn->dbName,sizeof(startup.database)); - strncpy(startup.tty,conn->pgtty,sizeof(startup.tty)); - if (conn->pgoptions) { - strncpy(startup.options,conn->pgoptions, sizeof(startup.options)); - } - else - startup.options[0]='\0'; - startup.execFile[0]='\0'; /* not used */ - - /* - * - * Open a connection to postmaster/backend. - * - */ - port = (Port *) malloc(sizeof(Port)); - memset((char *) port, 0, sizeof(Port)); - - if (!(hp = gethostbyname(conn->pghost)) || hp->h_addrtype != AF_INET) { - (void) sprintf(conn->errorMessage, - "connectDB() -- unknown hostname: %s\n", - conn->pghost); - goto connect_errReturn; - } - memset((char *) &port->raddr, 0, sizeof(port->raddr)); - memmove((char *) &(port->raddr.sin_addr), - (char *) hp->h_addr, - hp->h_length); - port->raddr.sin_family = AF_INET; - portno = atoi(conn->pgport); - port->raddr.sin_port = htons((unsigned short)(portno)); - - /* connect to the server */ - if ((port->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - (void) sprintf(conn->errorMessage, - "connectDB() -- socket() failed: errno=%d\n%s\n", - errno, strerror(errno)); - goto connect_errReturn; - } - if (connect(port->sock, (struct sockaddr *)&port->raddr, - sizeof(port->raddr)) < 0) { - (void) sprintf(conn->errorMessage, - "connectDB() failed: Is the postmaster running at '%s' on port '%s'?\n", - conn->pghost,conn->pgport); - goto connect_errReturn; - } - { - struct protoent *pe; - int on=1; - - pe = getprotobyname ("TCP"); - if ( pe == NULL ) - { - (void) sprintf(conn->errorMessage, - "connectDB(): getprotobyname failed\n"); - goto connect_errReturn; + struct hostent *hp; + + StartupInfo startup; + PacketBuf pacBuf; + int status; + MsgType msgtype; + int laddrlen = sizeof(struct sockaddr); + Port *port = conn->port; + int portno; + + /* + * Initialize the startup packet. + * + * This data structure is used for the seq-packet protocol. It describes + * the frontend-backend connection. + * + * + */ + strncpy(startup.user, conn->pguser, sizeof(startup.user)); + strncpy(startup.database, conn->dbName, sizeof(startup.database)); + strncpy(startup.tty, conn->pgtty, sizeof(startup.tty)); + if (conn->pgoptions) + { + strncpy(startup.options, conn->pgoptions, sizeof(startup.options)); + } + else + startup.options[0] = '\0'; + startup.execFile[0] = '\0'; /* not used */ + + /* + * Open a connection to postmaster/backend. + * + */ + port = (Port *) malloc(sizeof(Port)); + memset((char *) port, 0, sizeof(Port)); + + if (!(hp = gethostbyname(conn->pghost)) || hp->h_addrtype != AF_INET) + { + (void) sprintf(conn->errorMessage, + "connectDB() -- unknown hostname: %s\n", + conn->pghost); + goto connect_errReturn; + } + memset((char *) &port->raddr, 0, sizeof(port->raddr)); + memmove((char *) &(port->raddr.sin_addr), + (char *) hp->h_addr, + hp->h_length); + port->raddr.sin_family = AF_INET; + portno = atoi(conn->pgport); + port->raddr.sin_port = htons((unsigned short) (portno)); + + /* connect to the server */ + if ((port->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + (void) sprintf(conn->errorMessage, + "connectDB() -- socket() failed: errno=%d\n%s\n", + errno, strerror(errno)); + goto connect_errReturn; + } + if (connect(port->sock, (struct sockaddr *) & port->raddr, + sizeof(port->raddr)) < 0) + { + (void) sprintf(conn->errorMessage, + "connectDB() failed: Is the postmaster running at '%s' on port '%s'?\n", + conn->pghost, conn->pgport); + goto connect_errReturn; + } + { + struct protoent *pe; + int on = 1; + + pe = getprotobyname("TCP"); + if (pe == NULL) + { + (void) sprintf(conn->errorMessage, + "connectDB(): getprotobyname failed\n"); + goto connect_errReturn; + } + if (setsockopt(port->sock, pe->p_proto, TCP_NODELAY, + &on, sizeof(on)) < 0) + { + (void) sprintf(conn->errorMessage, + "connectDB(): setsockopt failed\n"); + goto connect_errReturn; + } + } + + /* fill in the client address */ + if (getsockname(port->sock, (struct sockaddr *) & port->laddr, + &laddrlen) < 0) + { + (void) sprintf(conn->errorMessage, + "connectDB() -- getsockname() failed: errno=%d\n%s\n", + errno, strerror(errno)); + goto connect_errReturn; + } + + /* by this point, connection has been opened */ + msgtype = fe_getauthsvc(conn->errorMessage); + +/* pacBuf = startup2PacketBuf(&startup);*/ + startup2PacketBuf(&startup, &pacBuf); + pacBuf.msgtype = (MsgType) htonl(msgtype); + status = packetSend(port, &pacBuf, sizeof(PacketBuf), BLOCKING); + + if (status == STATUS_ERROR) + { + sprintf(conn->errorMessage, + "connectDB() -- couldn't send complete packet: errno=%d\n%s\n", errno, strerror(errno)); + goto connect_errReturn; } - if ( setsockopt (port->sock, pe->p_proto, TCP_NODELAY, - &on, sizeof (on)) < 0 ) - { - (void) sprintf(conn->errorMessage, - "connectDB(): setsockopt failed\n"); - goto connect_errReturn; + + /* authenticate as required */ + if (fe_sendauth(msgtype, port, conn->pghost, + conn->pguser, conn->pgpass, + conn->errorMessage) != STATUS_OK) + { + (void) sprintf(conn->errorMessage, + "connectDB() -- authentication failed with %s\n", + conn->pghost); + goto connect_errReturn; } - } - - /* fill in the client address */ - if (getsockname(port->sock, (struct sockaddr *) &port->laddr, - &laddrlen) < 0) { - (void) sprintf(conn->errorMessage, - "connectDB() -- getsockname() failed: errno=%d\n%s\n", - errno, strerror(errno)); - goto connect_errReturn; - } - - /* by this point, connection has been opened */ - msgtype = fe_getauthsvc(conn->errorMessage); - -/* pacBuf = startup2PacketBuf(&startup);*/ - startup2PacketBuf(&startup, &pacBuf); - pacBuf.msgtype = (MsgType) htonl(msgtype); - status = packetSend(port, &pacBuf, sizeof(PacketBuf), BLOCKING); - - if (status == STATUS_ERROR) + + /* free the password so it's not hanging out in memory forever */ + if (conn->pgpass) { - sprintf(conn->errorMessage, - "connectDB() -- couldn't send complete packet: errno=%d\n%s\n", errno,strerror(errno)); - goto connect_errReturn; + free(conn->pgpass); } - /* authenticate as required*/ - if (fe_sendauth(msgtype, port, conn->pghost, - conn->pguser, conn->pgpass, - conn->errorMessage) != STATUS_OK) { - (void) sprintf(conn->errorMessage, - "connectDB() -- authentication failed with %s\n", - conn->pghost); - goto connect_errReturn; - } - - /* free the password so it's not hanging out in memory forever */ - if(conn->pgpass) { - free(conn->pgpass); - } - - /* set up the socket file descriptors */ - conn->Pfout = fdopen(port->sock, "w"); - conn->Pfin = fdopen(dup(port->sock), "r"); - if (!conn->Pfout || !conn->Pfin) { - (void) sprintf(conn->errorMessage, - "connectDB() -- fdopen() failed: errno=%d\n%s\n", - errno, strerror(errno)); - goto connect_errReturn; - } - - conn->port = port; - - { + /* set up the socket file descriptors */ + conn->Pfout = fdopen(port->sock, "w"); + conn->Pfin = fdopen(dup(port->sock), "r"); + if (!conn->Pfout || !conn->Pfin) + { + (void) sprintf(conn->errorMessage, + "connectDB() -- fdopen() failed: errno=%d\n%s\n", + errno, strerror(errno)); + goto connect_errReturn; + } + + conn->port = port; + + { struct EnvironmentOptions *eo; - char setQuery[80]; /* mjl: size okay? XXX */ - - for(eo = EnvironmentOptions; eo->envName; eo++) + char setQuery[80]; /* mjl: size okay? XXX */ + + for (eo = EnvironmentOptions; eo->envName; eo++) + { + const char *val; + + if ((val = getenv(eo->envName))) { - const char *val; - - if((val = getenv(eo->envName))) - { - PGresult *res; - + PGresult *res; + sprintf(setQuery, "SET %s TO '%.60s'", eo->pgName, val); res = PQexec(conn, setQuery); PQclear(res); /* Don't care? */ - } } } - return CONNECTION_OK; + } + return CONNECTION_OK; connect_errReturn: - /* Igor/6/3/97 - We need to free it here...otherwise the function - returns without setting conn->port to port. Because of that - any way of referencing this variable will be lost and it's allocated - memory will not be freed. */ - free(port); /* PURIFY */ - return CONNECTION_BAD; + /* + * Igor/6/3/97 - We need to free it here...otherwise the function + * returns without setting conn->port to port. Because of that any way + * of referencing this variable will be lost and it's allocated memory + * will not be freed. + */ + free(port); /* PURIFY */ + return CONNECTION_BAD; } /* * freePGconn - * - free the PGconn data structure + * - free the PGconn data structure * */ -static void -freePGconn(PGconn *conn) +static void +freePGconn(PGconn * conn) { - if (!conn) return; - if (conn->pghost) free(conn->pghost); - if (conn->pgtty) free(conn->pgtty); - if (conn->pgoptions) free(conn->pgoptions); - if (conn->pgport) free(conn->pgport); - if (conn->dbName) free(conn->dbName); - if (conn->pguser) free(conn->pguser); - if (conn->notifyList) DLFreeList(conn->notifyList); - if (conn->port) free(conn->port); - free(conn); + if (!conn) + return; + if (conn->pghost) + free(conn->pghost); + if (conn->pgtty) + free(conn->pgtty); + if (conn->pgoptions) + free(conn->pgoptions); + if (conn->pgport) + free(conn->pgport); + if (conn->dbName) + free(conn->dbName); + if (conn->pguser) + free(conn->pguser); + if (conn->notifyList) + DLFreeList(conn->notifyList); + if (conn->port) + free(conn->port); + free(conn); } /* closePGconn - - properly close a connection to the backend + - properly close a connection to the backend */ static void -closePGconn(PGconn *conn) +closePGconn(PGconn * conn) { /* GH: What to do for !USE_POSIX_SIGNALS ? */ #if defined(USE_POSIX_SIGNALS) - struct sigaction ignore_action; - /* This is used as a constant, but not declared as such because the - sigaction structure is defined differently on different systems */ - struct sigaction oldaction; - - /* If connection is already gone, that's cool. No reason for kernel - to kill us when we try to write to it. So ignore SIGPIPE signals. - */ - ignore_action.sa_handler = SIG_IGN; - sigemptyset(&ignore_action.sa_mask); - ignore_action.sa_flags = 0; - sigaction(SIGPIPE, (struct sigaction *) &ignore_action, &oldaction); - - fputs("X\0", conn->Pfout); - fflush(conn->Pfout); - sigaction(SIGPIPE, &oldaction, NULL); + struct sigaction ignore_action; + + /* + * This is used as a constant, but not declared as such because the + * sigaction structure is defined differently on different systems + */ + struct sigaction oldaction; + + /* + * If connection is already gone, that's cool. No reason for kernel + * to kill us when we try to write to it. So ignore SIGPIPE signals. + */ + ignore_action.sa_handler = SIG_IGN; + sigemptyset(&ignore_action.sa_mask); + ignore_action.sa_flags = 0; + sigaction(SIGPIPE, (struct sigaction *) & ignore_action, &oldaction); + + fputs("X\0", conn->Pfout); + fflush(conn->Pfout); + sigaction(SIGPIPE, &oldaction, NULL); #else - signal(SIGPIPE, SIG_IGN); - fputs("X\0", conn->Pfout); - fflush(conn->Pfout); - signal(SIGPIPE, SIG_DFL); + signal(SIGPIPE, SIG_IGN); + fputs("X\0", conn->Pfout); + fflush(conn->Pfout); + signal(SIGPIPE, SIG_DFL); #endif - if (conn->Pfout) fclose(conn->Pfout); - if (conn->Pfin) fclose(conn->Pfin); - if (conn->Pfdebug) fclose(conn->Pfdebug); - conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */ + if (conn->Pfout) + fclose(conn->Pfout); + if (conn->Pfin) + fclose(conn->Pfin); + if (conn->Pfdebug) + fclose(conn->Pfdebug); + conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just + * absent */ } /* PQfinish: - properly close a connection to the backend - also frees the PGconn data structure so it shouldn't be re-used - after this + properly close a connection to the backend + also frees the PGconn data structure so it shouldn't be re-used + after this */ void -PQfinish(PGconn *conn) +PQfinish(PGconn * conn) { - if (!conn) { - fprintf(stderr,"PQfinish() -- pointer to PGconn is null\n"); - } else { - if (conn->status == CONNECTION_OK) - closePGconn(conn); - freePGconn(conn); - } + if (!conn) + { + fprintf(stderr, "PQfinish() -- pointer to PGconn is null\n"); + } + else + { + if (conn->status == CONNECTION_OK) + closePGconn(conn); + freePGconn(conn); + } } /* PQreset : resets the connection to the backend - closes the existing connection and makes a new one + closes the existing connection and makes a new one */ void -PQreset(PGconn *conn) +PQreset(PGconn * conn) { - if (!conn) { - fprintf(stderr,"PQreset() -- pointer to PGconn is null\n"); - } else { - closePGconn(conn); - conn->status = connectDB(conn); - } + if (!conn) + { + fprintf(stderr, "PQreset() -- pointer to PGconn is null\n"); + } + else + { + closePGconn(conn); + conn->status = connectDB(conn); + } } /* @@ -679,29 +763,30 @@ PQreset(PGconn *conn) * * RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise. * SIDE_EFFECTS: may block. - * NOTES: Non-blocking writes would significantly complicate - * buffer management. For now, we're not going to do it. + * NOTES: Non-blocking writes would significantly complicate + * buffer management. For now, we're not going to do it. * */ int -packetSend(Port *port, - PacketBuf *buf, - PacketLen len, - bool nonBlocking) +packetSend(Port * port, + PacketBuf * buf, + PacketLen len, + bool nonBlocking) { - PacketLen totalLen; - int addrLen = sizeof(struct sockaddr_in); - - totalLen = len; - - len = sendto(port->sock, (Addr) buf, totalLen, /* flags */ 0, - (struct sockaddr *)&(port->raddr), addrLen); - - if (len < totalLen) { - return(STATUS_ERROR); - } - - return(STATUS_OK); + PacketLen totalLen; + int addrLen = sizeof(struct sockaddr_in); + + totalLen = len; + + len = sendto(port->sock, (Addr) buf, totalLen, /* flags */ 0, + (struct sockaddr *) & (port->raddr), addrLen); + + if (len < totalLen) + { + return (STATUS_ERROR); + } + + return (STATUS_OK); } /* @@ -709,359 +794,412 @@ packetSend(Port *port, * * this is just like StartupInfo2Packet(), defined in backend/libpq/pqpacket.c * but we repeat it here so we don't have to link in libpq.a - * + * * converts a StartupInfo structure to a PacketBuf */ static void -startup2PacketBuf(StartupInfo* s, PacketBuf* res) +startup2PacketBuf(StartupInfo * s, PacketBuf * res) { - char* tmp; - -/* res = (PacketBuf*)malloc(sizeof(PacketBuf)); */ - res->len = htonl(sizeof(PacketBuf)); - /* use \n to delimit the strings */ - res->data[0] = '\0'; - - tmp= res->data; - - strncpy(tmp, s->database, sizeof(s->database)); - tmp += sizeof(s->database); - strncpy(tmp, s->user, sizeof(s->user)); - tmp += sizeof(s->user); - strncpy(tmp, s->options, sizeof(s->options)); - tmp += sizeof(s->options); - strncpy(tmp, s->execFile, sizeof(s->execFile)); - tmp += sizeof(s->execFile); - strncpy(tmp, s->tty, sizeof(s->tty)); + char *tmp; + +/* res = (PacketBuf*)malloc(sizeof(PacketBuf)); */ + res->len = htonl(sizeof(PacketBuf)); + /* use \n to delimit the strings */ + res->data[0] = '\0'; + + tmp = res->data; + + strncpy(tmp, s->database, sizeof(s->database)); + tmp += sizeof(s->database); + strncpy(tmp, s->user, sizeof(s->user)); + tmp += sizeof(s->user); + strncpy(tmp, s->options, sizeof(s->options)); + tmp += sizeof(s->options); + strncpy(tmp, s->execFile, sizeof(s->execFile)); + tmp += sizeof(s->execFile); + strncpy(tmp, s->tty, sizeof(s->tty)); } /* ---------------- * Conninfo parser routine * ---------------- */ -static int conninfo_parse(const char *conninfo, char *errorMessage) +static int +conninfo_parse(const char *conninfo, char *errorMessage) { - char *pname; - char *pval; - char *buf; - char *tmp; - char *cp; - char *cp2; - PQconninfoOption *option; - char errortmp[ERROR_MSG_LENGTH]; - - conninfo_free(); - - if((buf = strdup(conninfo)) == NULL) { - strcpy(errorMessage, - "FATAL: cannot allocate memory for copy of conninfo string\n"); - return -1; - } - cp = buf; - - while(*cp) { - /* Skip blanks before the parameter name */ - if(isspace(*cp)) { - cp++; - continue; + char *pname; + char *pval; + char *buf; + char *tmp; + char *cp; + char *cp2; + PQconninfoOption *option; + char errortmp[ERROR_MSG_LENGTH]; + + conninfo_free(); + + if ((buf = strdup(conninfo)) == NULL) + { + strcpy(errorMessage, + "FATAL: cannot allocate memory for copy of conninfo string\n"); + return -1; } + cp = buf; - /* Get the parameter name */ - pname = cp; - while(*cp) { - if(*cp == '=') { - break; - } - if(isspace(*cp)) { - *cp++ = '\0'; - while(*cp) { - if(!isspace(*cp)) { - break; - } - cp++; + while (*cp) + { + /* Skip blanks before the parameter name */ + if (isspace(*cp)) + { + cp++; + continue; } - break; - } - cp++; - } - /* Check that there is a following '=' */ - if(*cp != '=') { - sprintf(errorMessage, - "ERROR: PQconnectdb() - Missing '=' after '%s' in conninfo\n", - pname); - free(buf); - return -1; - } - *cp++ = '\0'; - - /* Skip blanks after the '=' */ - while(*cp) { - if(!isspace(*cp)) { - break; - } - cp++; - } + /* Get the parameter name */ + pname = cp; + while (*cp) + { + if (*cp == '=') + { + break; + } + if (isspace(*cp)) + { + *cp++ = '\0'; + while (*cp) + { + if (!isspace(*cp)) + { + break; + } + cp++; + } + break; + } + cp++; + } - pval = cp; + /* Check that there is a following '=' */ + if (*cp != '=') + { + sprintf(errorMessage, + "ERROR: PQconnectdb() - Missing '=' after '%s' in conninfo\n", + pname); + free(buf); + return -1; + } + *cp++ = '\0'; - if(*cp != '\'') { - cp2 = pval; - while(*cp) { - if(isspace(*cp)) { - *cp++ = '\0'; - break; + /* Skip blanks after the '=' */ + while (*cp) + { + if (!isspace(*cp)) + { + break; + } + cp++; } - if(*cp == '\\') { - cp++; - if(*cp != '\0') { - *cp2++ = *cp++; - } - } else { - *cp2++ = *cp++; + + pval = cp; + + if (*cp != '\'') + { + cp2 = pval; + while (*cp) + { + if (isspace(*cp)) + { + *cp++ = '\0'; + break; + } + if (*cp == '\\') + { + cp++; + if (*cp != '\0') + { + *cp2++ = *cp++; + } + } + else + { + *cp2++ = *cp++; + } + } + *cp2 = '\0'; } - } - *cp2 = '\0'; - } else { - cp2 = pval; - cp++; - for(;;) { - if(*cp == '\0') { - sprintf(errorMessage, - "ERROR: PQconnectdb() - unterminated quoted string in conninfo\n"); - free(buf); - return -1; + else + { + cp2 = pval; + cp++; + for (;;) + { + if (*cp == '\0') + { + sprintf(errorMessage, + "ERROR: PQconnectdb() - unterminated quoted string in conninfo\n"); + free(buf); + return -1; + } + if (*cp == '\\') + { + cp++; + if (*cp != '\0') + { + *cp2++ = *cp++; + } + continue; + } + if (*cp == '\'') + { + *cp2 = '\0'; + cp++; + break; + } + *cp2++ = *cp++; + } } - if(*cp == '\\') { - cp++; - if(*cp != '\0') { - *cp2++ = *cp++; - } - continue; + + /* ---------- + * Now we have the name and the value. Search + * for the param record. + * ---------- + */ + for (option = PQconninfoOptions; option->keyword != NULL; option++) + { + if (!strcmp(option->keyword, pname)) + { + break; + } } - if(*cp == '\'') { - *cp2 = '\0'; - cp++; - break; + if (option->keyword == NULL) + { + sprintf(errorMessage, + "ERROR: PQconnectdb() - unknown option '%s'\n", + pname); + free(buf); + return -1; } - *cp2++ = *cp++; - } - } - /* ---------- - * Now we have the name and the value. Search - * for the param record. - * ---------- - */ - for(option = PQconninfoOptions; option->keyword != NULL; option++) { - if(!strcmp(option->keyword, pname)) { - break; - } - } - if(option->keyword == NULL) { - sprintf(errorMessage, - "ERROR: PQconnectdb() - unknown option '%s'\n", - pname); - free(buf); - return -1; + /* ---------- + * Store the value + * ---------- + */ + option->val = strdup(pval); } - /* ---------- - * Store the value - * ---------- - */ - option->val = strdup(pval); - } - - free(buf); - - /* ---------- - * Get the fallback resources for parameters not specified - * in the conninfo string. - * ---------- - */ - for(option = PQconninfoOptions; option->keyword != NULL; option++) { - if(option->val != NULL) continue; /* Value was in conninfo */ + free(buf); /* ---------- - * Try to get the environment variable fallback + * Get the fallback resources for parameters not specified + * in the conninfo string. * ---------- */ - if(option->environ != NULL) { - if((tmp = getenv(option->environ)) != NULL) { - option->val = strdup(tmp); - continue; - } - } + for (option = PQconninfoOptions; option->keyword != NULL; option++) + { + if (option->val != NULL) + continue; /* Value was in conninfo */ + + /* ---------- + * Try to get the environment variable fallback + * ---------- + */ + if (option->environ != NULL) + { + if ((tmp = getenv(option->environ)) != NULL) + { + option->val = strdup(tmp); + continue; + } + } - /* ---------- - * No environment variable specified or this one isn't set - - * try compiled in - * ---------- - */ - if(option->compiled != NULL) { - option->val = strdup(option->compiled); - continue; - } + /* ---------- + * No environment variable specified or this one isn't set - + * try compiled in + * ---------- + */ + if (option->compiled != NULL) + { + option->val = strdup(option->compiled); + continue; + } - /* ---------- - * Special handling for user - * ---------- - */ - if(!strcmp(option->keyword, "user")) { - tmp = fe_getauthname(errortmp); - if (tmp) { - option->val = strdup(tmp); - } - } + /* ---------- + * Special handling for user + * ---------- + */ + if (!strcmp(option->keyword, "user")) + { + tmp = fe_getauthname(errortmp); + if (tmp) + { + option->val = strdup(tmp); + } + } - /* ---------- - * Special handling for dbname - * ---------- - */ - if(!strcmp(option->keyword, "dbname")) { - tmp = conninfo_getval("user"); - if (tmp) { - option->val = strdup(tmp); - } + /* ---------- + * Special handling for dbname + * ---------- + */ + if (!strcmp(option->keyword, "dbname")) + { + tmp = conninfo_getval("user"); + if (tmp) + { + option->val = strdup(tmp); + } + } } - } - return 0; + return 0; } -static char* +static char * conninfo_getval(char *keyword) { - PQconninfoOption *option; + PQconninfoOption *option; - for(option = PQconninfoOptions; option->keyword != NULL; option++) { - if (!strcmp(option->keyword, keyword)) { - return option->val; + for (option = PQconninfoOptions; option->keyword != NULL; option++) + { + if (!strcmp(option->keyword, keyword)) + { + return option->val; + } } - } - return NULL; + return NULL; } static void conninfo_free() { - PQconninfoOption *option; + PQconninfoOption *option; - for(option = PQconninfoOptions; option->keyword != NULL; option++) { - if(option->val != NULL) { - free(option->val); - option->val = NULL; + for (option = PQconninfoOptions; option->keyword != NULL; option++) + { + if (option->val != NULL) + { + free(option->val); + option->val = NULL; + } } - } } /* =========== accessor functions for PGconn ========= */ -char* -PQdb(PGconn* conn) +char * +PQdb(PGconn * conn) { - if (!conn) { - fprintf(stderr,"PQdb() -- pointer to PGconn is null\n"); - return (char *)NULL; - } - return conn->dbName; + if (!conn) + { + fprintf(stderr, "PQdb() -- pointer to PGconn is null\n"); + return (char *) NULL; + } + return conn->dbName; } -char* -PQuser(PGconn* conn) +char * +PQuser(PGconn * conn) { - if (!conn) { - fprintf(stderr,"PQuser() -- pointer to PGconn is null\n"); - return (char *)NULL; - } - return conn->pguser; + if (!conn) + { + fprintf(stderr, "PQuser() -- pointer to PGconn is null\n"); + return (char *) NULL; + } + return conn->pguser; } -char* -PQhost(PGconn* conn) +char * +PQhost(PGconn * conn) { - if (!conn) { - fprintf(stderr,"PQhost() -- pointer to PGconn is null\n"); - return (char *)NULL; - } + if (!conn) + { + fprintf(stderr, "PQhost() -- pointer to PGconn is null\n"); + return (char *) NULL; + } - return conn->pghost; + return conn->pghost; } -char* -PQoptions(PGconn* conn) +char * +PQoptions(PGconn * conn) { - if (!conn) { - fprintf(stderr,"PQoptions() -- pointer to PGconn is null\n"); - return (char *)NULL; - } - return conn->pgoptions; + if (!conn) + { + fprintf(stderr, "PQoptions() -- pointer to PGconn is null\n"); + return (char *) NULL; + } + return conn->pgoptions; } -char* -PQtty(PGconn* conn) +char * +PQtty(PGconn * conn) { - if (!conn) { - fprintf(stderr,"PQtty() -- pointer to PGconn is null\n"); - return (char *)NULL; - } - return conn->pgtty; + if (!conn) + { + fprintf(stderr, "PQtty() -- pointer to PGconn is null\n"); + return (char *) NULL; + } + return conn->pgtty; } -char* -PQport(PGconn* conn) +char * +PQport(PGconn * conn) { - if (!conn) { - fprintf(stderr,"PQport() -- pointer to PGconn is null\n"); - return (char *)NULL; - } - return conn->pgport; + if (!conn) + { + fprintf(stderr, "PQport() -- pointer to PGconn is null\n"); + return (char *) NULL; + } + return conn->pgport; } ConnStatusType -PQstatus(PGconn* conn) +PQstatus(PGconn * conn) { - if (!conn) { - fprintf(stderr,"PQstatus() -- pointer to PGconn is null\n"); - return CONNECTION_BAD; - } - return conn->status; + if (!conn) + { + fprintf(stderr, "PQstatus() -- pointer to PGconn is null\n"); + return CONNECTION_BAD; + } + return conn->status; } -char* -PQerrorMessage(PGconn* conn) +char * +PQerrorMessage(PGconn * conn) { - if (!conn) { - fprintf(stderr,"PQerrorMessage() -- pointer to PGconn is null\n"); - return (char *)NULL; - } - return conn->errorMessage; + if (!conn) + { + fprintf(stderr, "PQerrorMessage() -- pointer to PGconn is null\n"); + return (char *) NULL; + } + return conn->errorMessage; } void -PQtrace(PGconn *conn, FILE* debug_port) +PQtrace(PGconn * conn, FILE * debug_port) { - if (conn == NULL || - conn->status == CONNECTION_BAD) { - return; - } - PQuntrace(conn); - conn->Pfdebug = debug_port; + if (conn == NULL || + conn->status == CONNECTION_BAD) + { + return; + } + PQuntrace(conn); + conn->Pfdebug = debug_port; } -void -PQuntrace(PGconn *conn) +void +PQuntrace(PGconn * conn) { - if (conn == NULL || - conn->status == CONNECTION_BAD) { - return; - } - if (conn->Pfdebug) { - fflush(conn->Pfdebug); - fclose(conn->Pfdebug); - conn->Pfdebug = NULL; - } + if (conn == NULL || + conn->status == CONNECTION_BAD) + { + return; + } + if (conn->Pfdebug) + { + fflush(conn->Pfdebug); + fclose(conn->Pfdebug); + conn->Pfdebug = NULL; + } } diff --git a/src/interfaces/libpq/fe-connect.h b/src/interfaces/libpq/fe-connect.h index ffa746473d3..5bd38084488 100644 --- a/src/interfaces/libpq/fe-connect.h +++ b/src/interfaces/libpq/fe-connect.h @@ -2,28 +2,28 @@ * * fe-connect.h * - * Definitions related to setting up a connection to the backend + * Definitions related to setting up a connection to the backend * * Copyright (c) 1994, Regents of the University of California * - * $Id: fe-connect.h,v 1.1 1997/03/16 19:06:04 scrappy Exp $ + * $Id: fe-connect.h,v 1.2 1997/09/07 05:03:26 momjian Exp $ * *------------------------------------------------------------------------- */ #ifndef FE_CONNECT_H -#define FE_CONNECT_H +#define FE_CONNECT_H /*---------------------------------------------------------------- * Common routines and definitions *---------------------------------------------------------------- */ -extern int packetSend(Port *port, PacketBuf *buf, PacketLen len, bool nonBlocking); +extern int packetSend(Port * port, PacketBuf * buf, PacketLen len, bool nonBlocking); -#endif /* FE_CONNECT_H */ +#endif /* FE_CONNECT_H */ #ifndef FE_CONNECT_H #define FE_CONNECT_H -int packetSend(Port *port, PacketBuf *buf, PacketLen len, bool nonBlocking); +int packetSend(Port * port, PacketBuf * buf, PacketLen len, bool nonBlocking); #endif diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index 771e8c66e2b..be8913e7bf7 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * fe-exec.c-- - * functions related to sending a query down to the backend + * functions related to sending a query down to the backend * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.35 1997/09/05 00:09:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.36 1997/09/07 05:03:28 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -23,19 +23,22 @@ #include "libpq-fe.h" #include <sys/ioctl.h> #ifndef HAVE_TERMIOS_H -# include <sys/termios.h> +#include <sys/termios.h> #else -# include <termios.h> +#include <termios.h> #endif #ifdef TIOCGWINSZ -struct winsize screen_size; +struct winsize screen_size; + #else -struct winsize { - int ws_row; - int ws_col; -} screen_size; +struct winsize +{ + int ws_row; + int ws_col; +} screen_size; + #endif /* the rows array in a PGresGroup has to grow to accommodate the rows */ @@ -43,325 +46,358 @@ struct winsize { #define TUPARR_GROW_BY 100 /* keep this in same order as ExecStatusType in pgtclCmds.h */ -const char* pgresStatus[] = { - "PGRES_EMPTY_QUERY", - "PGRES_COMMAND_OK", - "PGRES_TUPLES_OK", - "PGRES_BAD_RESPONSE", - "PGRES_NONFATAL_ERROR", - "PGRES_FATAL_ERROR" +const char *pgresStatus[] = { + "PGRES_EMPTY_QUERY", + "PGRES_COMMAND_OK", + "PGRES_TUPLES_OK", + "PGRES_BAD_RESPONSE", + "PGRES_NONFATAL_ERROR", + "PGRES_FATAL_ERROR" }; -static PGresult* makePGresult(PGconn *conn, char *pname); -static void addTuple(PGresult *res, PGresAttValue *tup); -static PGresAttValue* getTuple(PGconn *conn, PGresult *res, int binary); -static PGresult* makeEmptyPGresult(PGconn *conn, ExecStatusType status); -static void fill(int length, int max, char filler, FILE *fp); -static char* do_header(FILE *fout, PQprintOpt *po, const int nFields, - int fieldMax[], char *fieldNames[], unsigned char fieldNotNum[], - const int fs_len, PGresult *res); +static PGresult *makePGresult(PGconn * conn, char *pname); +static void addTuple(PGresult * res, PGresAttValue * tup); +static PGresAttValue *getTuple(PGconn * conn, PGresult * res, int binary); +static PGresult *makeEmptyPGresult(PGconn * conn, ExecStatusType status); +static void fill(int length, int max, char filler, FILE * fp); +static char * +do_header(FILE * fout, PQprintOpt * po, const int nFields, + int fieldMax[], char *fieldNames[], unsigned char fieldNotNum[], + const int fs_len, PGresult * res); /* * PQclear - - * free's the memory associated with a PGresult + * free's the memory associated with a PGresult * */ void -PQclear(PGresult* res) +PQclear(PGresult * res) { - int i,j; - - if (!res) - return; - - /* free all the rows */ - for (i=0;i<res->ntups;i++) { - for (j=0;j<res->numAttributes;j++) { - if (res->tuples[i][j].value) - free(res->tuples[i][j].value); - } - if (res->tuples[i]) free(res->tuples[i]); - } - if (res->tuples) free(res->tuples); - - /* free all the attributes */ - for (i=0;i<res->numAttributes;i++) { - if (res->attDescs[i].name) - free(res->attDescs[i].name); - } - if (res->attDescs) free(res->attDescs); - - /* free the structure itself */ - free(res); + int i, + j; + + if (!res) + return; + + /* free all the rows */ + for (i = 0; i < res->ntups; i++) + { + for (j = 0; j < res->numAttributes; j++) + { + if (res->tuples[i][j].value) + free(res->tuples[i][j].value); + } + if (res->tuples[i]) + free(res->tuples[i]); + } + if (res->tuples) + free(res->tuples); + + /* free all the attributes */ + for (i = 0; i < res->numAttributes; i++) + { + if (res->attDescs[i].name) + free(res->attDescs[i].name); + } + if (res->attDescs) + free(res->attDescs); + + /* free the structure itself */ + free(res); } /* * PGresult - - * returns a newly allocated, initialized PGresult + * returns a newly allocated, initialized PGresult * */ -static PGresult* -makeEmptyPGresult(PGconn *conn, ExecStatusType status) +static PGresult * +makeEmptyPGresult(PGconn * conn, ExecStatusType status) { - PGresult *result; - - result = (PGresult*)malloc(sizeof(PGresult)); - - result->conn = conn; - result->ntups = 0; - result->numAttributes = 0; - result->attDescs = NULL; - result->tuples = NULL; - result->tupArrSize = 0; - result->resultStatus = status; - result->cmdStatus[0] = '\0'; - result->binary = 0; - return result; + PGresult *result; + + result = (PGresult *) malloc(sizeof(PGresult)); + + result->conn = conn; + result->ntups = 0; + result->numAttributes = 0; + result->attDescs = NULL; + result->tuples = NULL; + result->tupArrSize = 0; + result->resultStatus = status; + result->cmdStatus[0] = '\0'; + result->binary = 0; + return result; } /* * getTuple - - * get the next row from the stream + * get the next row from the stream * - * the CALLER is responsible from freeing the PGresAttValue returned + * the CALLER is responsible from freeing the PGresAttValue returned */ -static PGresAttValue* -getTuple(PGconn *conn, PGresult* result, int binary) +static PGresAttValue * +getTuple(PGconn * conn, PGresult * result, int binary) { - char bitmap[MAX_FIELDS]; /* the backend sends us a bitmap of */ - /* which attributes are null */ - int bitmap_index = 0; - int i; - int nbytes; /* the number of bytes in bitmap */ - char bmap; /* One byte of the bitmap */ - int bitcnt = 0; /* number of bits examined in current byte */ - int vlen; /* length of the current field value */ - FILE *pfin = conn->Pfin; - FILE *pfdebug = conn->Pfdebug; - - PGresAttValue* tup; - - int nfields = result->numAttributes; - - result->binary = binary; - - tup = (PGresAttValue*) malloc(nfields * sizeof(PGresAttValue)); - - nbytes = nfields / BYTELEN; - if ( (nfields % BYTELEN) > 0) - nbytes++; - - if (pqGetnchar(bitmap, nbytes, pfin, pfdebug) == 1){ - sprintf(conn->errorMessage, - "Error reading null-values bitmap from row data stream\n"); - return NULL; - } - - bmap = bitmap[bitmap_index]; - - for (i=0;i<nfields;i++) { - if (!(bmap & 0200)) { - /* if the field value is absent, make it '\0' */ - tup[i].value = (char*)malloc(1); - tup[i].value[0] = '\0'; - tup[i].len = NULL_LEN; - } - else { - /* get the value length (the first four bytes are for length) */ - pqGetInt(&vlen, VARHDRSZ, pfin, pfdebug); - if (binary == 0) { - vlen = vlen - VARHDRSZ; - } - if (vlen < 0) - vlen = 0; - tup[i].len = vlen; - tup[i].value = (char*) malloc(vlen + 1); - /* read in the value; */ - if (vlen > 0) - pqGetnchar((char*)(tup[i].value), vlen, pfin, pfdebug); - tup[i].value[vlen] = '\0'; - } - /* get the appropriate bitmap */ - bitcnt++; - if (bitcnt == BYTELEN) { - bitmap_index++; - bmap = bitmap[bitmap_index]; - bitcnt = 0; - } else - bmap <<= 1; - } - - return tup; + char bitmap[MAX_FIELDS]; /* the backend sends us a bitmap + * of */ + + /* which attributes are null */ + int bitmap_index = 0; + int i; + int nbytes; /* the number of bytes in bitmap */ + char bmap; /* One byte of the bitmap */ + int bitcnt = 0; /* number of bits examined in current byte */ + int vlen; /* length of the current field value */ + FILE *pfin = conn->Pfin; + FILE *pfdebug = conn->Pfdebug; + + PGresAttValue *tup; + + int nfields = result->numAttributes; + + result->binary = binary; + + tup = (PGresAttValue *) malloc(nfields * sizeof(PGresAttValue)); + + nbytes = nfields / BYTELEN; + if ((nfields % BYTELEN) > 0) + nbytes++; + + if (pqGetnchar(bitmap, nbytes, pfin, pfdebug) == 1) + { + sprintf(conn->errorMessage, + "Error reading null-values bitmap from row data stream\n"); + return NULL; + } + + bmap = bitmap[bitmap_index]; + + for (i = 0; i < nfields; i++) + { + if (!(bmap & 0200)) + { + /* if the field value is absent, make it '\0' */ + tup[i].value = (char *) malloc(1); + tup[i].value[0] = '\0'; + tup[i].len = NULL_LEN; + } + else + { + /* get the value length (the first four bytes are for length) */ + pqGetInt(&vlen, VARHDRSZ, pfin, pfdebug); + if (binary == 0) + { + vlen = vlen - VARHDRSZ; + } + if (vlen < 0) + vlen = 0; + tup[i].len = vlen; + tup[i].value = (char *) malloc(vlen + 1); + /* read in the value; */ + if (vlen > 0) + pqGetnchar((char *) (tup[i].value), vlen, pfin, pfdebug); + tup[i].value[vlen] = '\0'; + } + /* get the appropriate bitmap */ + bitcnt++; + if (bitcnt == BYTELEN) + { + bitmap_index++; + bmap = bitmap[bitmap_index]; + bitcnt = 0; + } + else + bmap <<= 1; + } + + return tup; } /* * addTuple - * add a row to the PGresult structure, growing it if necessary - * to accommodate + * add a row to the PGresult structure, growing it if necessary + * to accommodate * */ -static void -addTuple(PGresult* res, PGresAttValue* tup) +static void +addTuple(PGresult * res, PGresAttValue * tup) { - if (res->ntups == res->tupArrSize) { - /* grow the array */ - res->tupArrSize += TUPARR_GROW_BY; - - if (res->ntups == 0) - res->tuples = (PGresAttValue**) - malloc(res->tupArrSize * sizeof(PGresAttValue*)); - else - /* we can use realloc because shallow copying of the structure is okay */ - res->tuples = (PGresAttValue**) - realloc(res->tuples, res->tupArrSize * sizeof(PGresAttValue*)); - } - - res->tuples[res->ntups] = tup; - res->ntups++; + if (res->ntups == res->tupArrSize) + { + /* grow the array */ + res->tupArrSize += TUPARR_GROW_BY; + + if (res->ntups == 0) + res->tuples = (PGresAttValue **) + malloc(res->tupArrSize * sizeof(PGresAttValue *)); + else + + /* + * we can use realloc because shallow copying of the structure + * is okay + */ + res->tuples = (PGresAttValue **) + realloc(res->tuples, res->tupArrSize * sizeof(PGresAttValue *)); + } + + res->tuples[res->ntups] = tup; + res->ntups++; } /* * PGresult - * fill out the PGresult structure with result rows from the backend - * this is called after query has been successfully run and we have - * a portal name + * fill out the PGresult structure with result rows from the backend + * this is called after query has been successfully run and we have + * a portal name * - * ASSUMPTION: we assume only *1* row group is returned from the backend + * ASSUMPTION: we assume only *1* row group is returned from the backend * - * the CALLER is reponsible for free'ing the new PGresult allocated here + * the CALLER is reponsible for free'ing the new PGresult allocated here * */ -static PGresult* -makePGresult(PGconn* conn, char* pname) +static PGresult * +makePGresult(PGconn * conn, char *pname) { - PGresult* result; - int id; - int nfields; - int i; - int done = 0; - - PGresAttValue* newTup; - - FILE* pfin = conn->Pfin; - FILE* pfdebug = conn->Pfdebug; - - result = makeEmptyPGresult(conn, PGRES_TUPLES_OK); - - /* makePGresult() should only be called when the */ - /* id of the stream is 'T' to start with */ - - /* the next two bytes are the number of fields */ - if (pqGetInt(&nfields, 2, pfin, pfdebug) == 1) { - sprintf(conn->errorMessage, - "could not get the number of fields from the 'T' message\n"); - goto makePGresult_badResponse_return; - } - else - result->numAttributes = nfields; - - /* allocate space for the attribute descriptors */ - if (nfields > 0) { - result->attDescs = (PGresAttDesc*) malloc(nfields * sizeof(PGresAttDesc)); - } - - /* get type info */ - for (i=0;i<nfields;i++) { - char typName[MAX_MESSAGE_LEN]; - int adtid; - int adtsize; - - if ( pqGets(typName, MAX_MESSAGE_LEN, pfin, pfdebug) || - pqGetInt(&adtid, 4, pfin, pfdebug) || - pqGetInt(&adtsize, 2, pfin, pfdebug)) { - sprintf(conn->errorMessage, - "error reading type information from the 'T' message\n"); - goto makePGresult_badResponse_return; - } - result->attDescs[i].name = malloc(strlen(typName)+1); - strcpy(result->attDescs[i].name,typName); - result->attDescs[i].adtid = adtid; - result->attDescs[i].adtsize = adtsize; /* casting from int to int2 here */ - } - - id = pqGetc(pfin,pfdebug); - - /* process the data stream until we're finished */ - while(!done) { - switch (id) { - case 'T': /* a new row group */ - sprintf(conn->errorMessage, - "makePGresult() -- " - "is not equipped to handle multiple row groups.\n"); - goto makePGresult_badResponse_return; - case 'B': /* a row in binary format */ - case 'D': /* a row in ASCII format */ - newTup = getTuple(conn, result, (id == 'B')); - if (newTup == NULL) - goto makePGresult_badResponse_return; - addTuple(result,newTup); - break; - case 'C': /* end of portal row stream */ - { - char command[MAX_MESSAGE_LEN]; - pqGets(command,MAX_MESSAGE_LEN, pfin, pfdebug); /* read command tag */ - done = 1; - } - break; - case 'E': /* errors */ - if (pqGets(conn->errorMessage, ERROR_MSG_LENGTH, pfin, pfdebug) == 1) { - sprintf(conn->errorMessage, - "Error return detected from backend, " - "but error message cannot be read"); - } - result->resultStatus = PGRES_FATAL_ERROR; - return result; - break; - case 'N': /* notices from the backend */ - if (pqGets(conn->errorMessage, ERROR_MSG_LENGTH, pfin, pfdebug) == 1) { - sprintf(conn->errorMessage, - "Notice return detected from backend, " - "but error message cannot be read"); - } else - /* XXXX send Notices to stderr for now */ - fprintf(stderr, "%s\n", conn->errorMessage); - break; - default: /* uh-oh - this should never happen but frequently does when the - backend dumps core */ - sprintf(conn->errorMessage, - "FATAL: unrecognized data from the backend. " - "It probably dumped core.\n"); - fprintf(stderr, conn->errorMessage); - result->resultStatus = PGRES_FATAL_ERROR; - return result; - break; - } - if (!done) - id = getc(pfin); - } /* while (1) */ - - result->resultStatus = PGRES_TUPLES_OK; - return result; + PGresult *result; + int id; + int nfields; + int i; + int done = 0; + + PGresAttValue *newTup; + + FILE *pfin = conn->Pfin; + FILE *pfdebug = conn->Pfdebug; + + result = makeEmptyPGresult(conn, PGRES_TUPLES_OK); + + /* makePGresult() should only be called when the */ + /* id of the stream is 'T' to start with */ + + /* the next two bytes are the number of fields */ + if (pqGetInt(&nfields, 2, pfin, pfdebug) == 1) + { + sprintf(conn->errorMessage, + "could not get the number of fields from the 'T' message\n"); + goto makePGresult_badResponse_return; + } + else + result->numAttributes = nfields; + + /* allocate space for the attribute descriptors */ + if (nfields > 0) + { + result->attDescs = (PGresAttDesc *) malloc(nfields * sizeof(PGresAttDesc)); + } + + /* get type info */ + for (i = 0; i < nfields; i++) + { + char typName[MAX_MESSAGE_LEN]; + int adtid; + int adtsize; + + if (pqGets(typName, MAX_MESSAGE_LEN, pfin, pfdebug) || + pqGetInt(&adtid, 4, pfin, pfdebug) || + pqGetInt(&adtsize, 2, pfin, pfdebug)) + { + sprintf(conn->errorMessage, + "error reading type information from the 'T' message\n"); + goto makePGresult_badResponse_return; + } + result->attDescs[i].name = malloc(strlen(typName) + 1); + strcpy(result->attDescs[i].name, typName); + result->attDescs[i].adtid = adtid; + result->attDescs[i].adtsize = adtsize; /* casting from int to + * int2 here */ + } + + id = pqGetc(pfin, pfdebug); + + /* process the data stream until we're finished */ + while (!done) + { + switch (id) + { + case 'T': /* a new row group */ + sprintf(conn->errorMessage, + "makePGresult() -- " + "is not equipped to handle multiple row groups.\n"); + goto makePGresult_badResponse_return; + case 'B': /* a row in binary format */ + case 'D': /* a row in ASCII format */ + newTup = getTuple(conn, result, (id == 'B')); + if (newTup == NULL) + goto makePGresult_badResponse_return; + addTuple(result, newTup); + break; + case 'C': /* end of portal row stream */ + { + char command[MAX_MESSAGE_LEN]; + + pqGets(command, MAX_MESSAGE_LEN, pfin, pfdebug); /* read command tag */ + done = 1; + } + break; + case 'E': /* errors */ + if (pqGets(conn->errorMessage, ERROR_MSG_LENGTH, pfin, pfdebug) == 1) + { + sprintf(conn->errorMessage, + "Error return detected from backend, " + "but error message cannot be read"); + } + result->resultStatus = PGRES_FATAL_ERROR; + return result; + break; + case 'N': /* notices from the backend */ + if (pqGets(conn->errorMessage, ERROR_MSG_LENGTH, pfin, pfdebug) == 1) + { + sprintf(conn->errorMessage, + "Notice return detected from backend, " + "but error message cannot be read"); + } + else + /* XXXX send Notices to stderr for now */ + fprintf(stderr, "%s\n", conn->errorMessage); + break; + default: /* uh-oh this should never happen but + * frequently does when the backend dumps + * core */ + sprintf(conn->errorMessage, + "FATAL: unrecognized data from the backend. " + "It probably dumped core.\n"); + fprintf(stderr, conn->errorMessage); + result->resultStatus = PGRES_FATAL_ERROR; + return result; + break; + } + if (!done) + id = getc(pfin); + } /* while (1) */ + + result->resultStatus = PGRES_TUPLES_OK; + return result; makePGresult_badResponse_return: - result->resultStatus = PGRES_BAD_RESPONSE; - return result; + result->resultStatus = PGRES_BAD_RESPONSE; + return result; } /* - * Assuming that we just sent a query to the backend, read the backend's + * Assuming that we just sent a query to the backend, read the backend's * response from stream <pfin> and respond accordingly. * * If <pfdebug> is non-null, write to that stream whatever we receive * (it's a debugging trace). - * + * * Return as <result> a pointer to a proper final PGresult structure, * newly allocated, for the query based on the response we get. If the * response we get indicates that the query didn't execute, return a @@ -370,450 +406,522 @@ makePGresult_badResponse_return: */ static void -process_response_from_backend(FILE *pfin, FILE *pfout, FILE *pfdebug, - PGconn *conn, - PGresult **result_p, char * const reason) { - - int id; - /* The protocol character received from the backend. The protocol - character is the first character in the backend's response to our - query. It defines the nature of the response. - */ - PGnotify *newNotify; - bool done; - /* We're all done with the query and ready to return the result. */ - int emptiesSent; - /* Number of empty queries we have sent in order to flush out multiple - responses, less the number of corresponding responses we have - received. - */ - int errors; - /* If an error is received, we must still drain out the empty - queries sent. So we need another flag. - */ - char cmdStatus[MAX_MESSAGE_LEN]; - char pname[MAX_MESSAGE_LEN]; /* portal name */ - - /* loop because multiple messages, especially NOTICES, - can come back from the backend. NOTICES are output directly to stderr - */ - - emptiesSent = 0; /* No empty queries sent yet */ - errors = 0; /* No errors received yet */ - pname[0] = '\0'; - - done = false; /* initial value */ - while (!done) { - /* read the result id */ - id = pqGetc(pfin, pfdebug); - if (id == EOF) { - /* hmm, no response from the backend-end, that's bad */ - (void) sprintf(reason, - "PQexec() -- Request was sent to backend, but backend " - "closed the channel before " - "responding. This probably means the backend " - "terminated abnormally before or while processing " - "the request.\n"); - conn->status = CONNECTION_BAD; /* No more connection to backend */ - *result_p = (PGresult*)NULL; - done = true; - } else { - switch (id) { - case 'A': - newNotify = (PGnotify*)malloc(sizeof(PGnotify)); - pqGetInt(&(newNotify->be_pid), 4, pfin, pfdebug); - pqGets(newNotify->relname, NAMEDATALEN, pfin, pfdebug); - DLAddTail(conn->notifyList, DLNewElem(newNotify)); - /* async messages are piggy'ed back on other messages, - so we stay in the while loop for other messages */ - break; - case 'C': /* portal query command, no rows returned */ - if (pqGets(cmdStatus, MAX_MESSAGE_LEN, pfin, pfdebug) == 1) { - sprintf(reason, - "PQexec() -- query command completed, " - "but return message from backend cannot be read."); - *result_p = (PGresult*)NULL; - done = true; - } else { - /* - * since backend may produce more than one result for some - * commands need to poll until clear - * send an empty query down, and keep reading out of the pipe - * until an 'I' is received. - */ - pqPuts("Q ", pfout, pfdebug); /* send an empty query */ - /* - * Increment a flag and process messages in the usual way because - * there may be async notifications pending. DZ - 31-8-1996 - */ - emptiesSent++; - } - break; - case 'E': /* error return */ - if (pqGets(conn->errorMessage, ERROR_MSG_LENGTH, pfin, pfdebug) == 1) { - (void) sprintf(reason, - "PQexec() -- error return detected from backend, " - "but attempt to read the error message failed."); - } - *result_p = (PGresult*)NULL; - errors++; - if (emptiesSent == 0) { - done = true; - } - break; - case 'I': { /* empty query */ - /* read and throw away the closing '\0' */ - int c; - if ((c = pqGetc(pfin,pfdebug)) != '\0') { - fprintf(stderr,"error!, unexpected character %c following 'I'\n", c); - } - if (emptiesSent) { - if (--emptiesSent == 0) { /* is this the last one? */ - /* - * If this is the result of a portal query command set the - * command status and message accordingly. DZ - 31-8-1996 - */ - if (!errors) { - *result_p = makeEmptyPGresult(conn,PGRES_COMMAND_OK); - strncpy((*result_p)->cmdStatus, cmdStatus, CMDSTATUS_LEN-1); - } else { - *result_p = (PGresult*)NULL; - } - done = true; - } - } - else { - if (!errors) { - *result_p = makeEmptyPGresult(conn, PGRES_EMPTY_QUERY); - } else { - *result_p = (PGresult*)NULL; - } - done = true; - } - } - break; - case 'N': /* notices from the backend */ - if (pqGets(reason, ERROR_MSG_LENGTH, pfin, pfdebug) == 1) { - sprintf(reason, - "PQexec() -- Notice detected from backend, " - "but attempt to read the notice failed."); - *result_p = (PGresult*)NULL; - done = true; - } else - /* Should we really be doing this? These notices are not important - enough for us to presume to put them on stderr. Maybe the caller - should decide whether to put them on stderr or not. BJH 96.12.27 - */ - fprintf(stderr,"%s", reason); - break; - case 'P': /* synchronous (normal) portal */ - pqGets(pname, MAX_MESSAGE_LEN, pfin, pfdebug); /* read in portal name*/ - break; - case 'T': /* actual row results: */ - *result_p = makePGresult(conn, pname); - done = true; - break; - case 'D': /* copy command began successfully */ - *result_p = makeEmptyPGresult(conn, PGRES_COPY_IN); - done = true; - break; - case 'B': /* copy command began successfully */ - *result_p = makeEmptyPGresult(conn, PGRES_COPY_OUT); - done = true; - break; - default: - sprintf(reason, - "unknown protocol character '%c' read from backend. " - "(The protocol character is the first character the " - "backend sends in response to a query it receives).\n", - id); - *result_p = (PGresult*)NULL; - done = true; - } /* switch on protocol character */ - } /* if character was received */ - } /* while not done */ +process_response_from_backend(FILE * pfin, FILE * pfout, FILE * pfdebug, + PGconn * conn, + PGresult ** result_p, char *const reason) +{ + + int id; + + /* + * The protocol character received from the backend. The protocol + * character is the first character in the backend's response to our + * query. It defines the nature of the response. + */ + PGnotify *newNotify; + bool done; + + /* We're all done with the query and ready to return the result. */ + int emptiesSent; + + /* + * Number of empty queries we have sent in order to flush out multiple + * responses, less the number of corresponding responses we have + * received. + */ + int errors; + + /* + * If an error is received, we must still drain out the empty queries + * sent. So we need another flag. + */ + char cmdStatus[MAX_MESSAGE_LEN]; + char pname[MAX_MESSAGE_LEN]; /* portal name */ + + /* + * loop because multiple messages, especially NOTICES, can come back + * from the backend. NOTICES are output directly to stderr + */ + + emptiesSent = 0; /* No empty queries sent yet */ + errors = 0; /* No errors received yet */ + pname[0] = '\0'; + + done = false; /* initial value */ + while (!done) + { + /* read the result id */ + id = pqGetc(pfin, pfdebug); + if (id == EOF) + { + /* hmm, no response from the backend-end, that's bad */ + (void) sprintf(reason, + "PQexec() -- Request was sent to backend, but backend " + "closed the channel before " + "responding. This probably means the backend " + "terminated abnormally before or while processing " + "the request.\n"); + conn->status = CONNECTION_BAD; /* No more connection to + * backend */ + *result_p = (PGresult *) NULL; + done = true; + } + else + { + switch (id) + { + case 'A': + newNotify = (PGnotify *) malloc(sizeof(PGnotify)); + pqGetInt(&(newNotify->be_pid), 4, pfin, pfdebug); + pqGets(newNotify->relname, NAMEDATALEN, pfin, pfdebug); + DLAddTail(conn->notifyList, DLNewElem(newNotify)); + + /* + * async messages are piggy'ed back on other messages, so + * we stay in the while loop for other messages + */ + break; + case 'C': /* portal query command, no rows returned */ + if (pqGets(cmdStatus, MAX_MESSAGE_LEN, pfin, pfdebug) == 1) + { + sprintf(reason, + "PQexec() -- query command completed, " + "but return message from backend cannot be read."); + *result_p = (PGresult *) NULL; + done = true; + } + else + { + + /* + * since backend may produce more than one result for + * some commands need to poll until clear send an + * empty query down, and keep reading out of the pipe + * until an 'I' is received. + */ + pqPuts("Q ", pfout, pfdebug); /* send an empty query */ + + /* + * Increment a flag and process messages in the usual + * way because there may be async notifications + * pending. DZ - 31-8-1996 + */ + emptiesSent++; + } + break; + case 'E': /* error return */ + if (pqGets(conn->errorMessage, ERROR_MSG_LENGTH, pfin, pfdebug) == 1) + { + (void) sprintf(reason, + "PQexec() -- error return detected from backend, " + "but attempt to read the error message failed."); + } + *result_p = (PGresult *) NULL; + errors++; + if (emptiesSent == 0) + { + done = true; + } + break; + case 'I': + { /* empty query */ + /* read and throw away the closing '\0' */ + int c; + + if ((c = pqGetc(pfin, pfdebug)) != '\0') + { + fprintf(stderr, "error!, unexpected character %c following 'I'\n", c); + } + if (emptiesSent) + { + if (--emptiesSent == 0) + { /* is this the last one? */ + + /* + * If this is the result of a portal query + * command set the command status and message + * accordingly. DZ - 31-8-1996 + */ + if (!errors) + { + *result_p = makeEmptyPGresult(conn, PGRES_COMMAND_OK); + strncpy((*result_p)->cmdStatus, cmdStatus, CMDSTATUS_LEN - 1); + } + else + { + *result_p = (PGresult *) NULL; + } + done = true; + } + } + else + { + if (!errors) + { + *result_p = makeEmptyPGresult(conn, PGRES_EMPTY_QUERY); + } + else + { + *result_p = (PGresult *) NULL; + } + done = true; + } + } + break; + case 'N': /* notices from the backend */ + if (pqGets(reason, ERROR_MSG_LENGTH, pfin, pfdebug) == 1) + { + sprintf(reason, + "PQexec() -- Notice detected from backend, " + "but attempt to read the notice failed."); + *result_p = (PGresult *) NULL; + done = true; + } + else + + /* + * Should we really be doing this? These notices are + * not important enough for us to presume to put them + * on stderr. Maybe the caller should decide whether + * to put them on stderr or not. BJH 96.12.27 + */ + fprintf(stderr, "%s", reason); + break; + case 'P': /* synchronous (normal) portal */ + pqGets(pname, MAX_MESSAGE_LEN, pfin, pfdebug); /* read in portal name */ + break; + case 'T': /* actual row results: */ + *result_p = makePGresult(conn, pname); + done = true; + break; + case 'D': /* copy command began successfully */ + *result_p = makeEmptyPGresult(conn, PGRES_COPY_IN); + done = true; + break; + case 'B': /* copy command began successfully */ + *result_p = makeEmptyPGresult(conn, PGRES_COPY_OUT); + done = true; + break; + default: + sprintf(reason, + "unknown protocol character '%c' read from backend. " + "(The protocol character is the first character the " + "backend sends in response to a query it receives).\n", + id); + *result_p = (PGresult *) NULL; + done = true; + } /* switch on protocol character */ + } /* if character was received */ + } /* while not done */ } /* * PQexec - * send a query to the backend and package up the result in a Pgresult + * send a query to the backend and package up the result in a Pgresult * - * if the query failed, return NULL, conn->errorMessage is set to + * if the query failed, return NULL, conn->errorMessage is set to * a relevant message - * if query is successful, a new PGresult is returned + * if query is successful, a new PGresult is returned * the use is responsible for freeing that structure when done with it * */ -PGresult* -PQexec(PGconn* conn, const char* query) +PGresult * +PQexec(PGconn * conn, const char *query) { - PGresult *result; - char buffer[MAX_MESSAGE_LEN]; - - if (!conn) return NULL; - if (!query) { - sprintf(conn->errorMessage, "PQexec() -- query pointer is null."); - return NULL; - } - - /*clear the error string */ - conn->errorMessage[0] = '\0'; - - /* check to see if the query string is too long */ - if (strlen(query) > MAX_MESSAGE_LEN) { - sprintf(conn->errorMessage, "PQexec() -- query is too long. " - "Maximum length is %d\n", MAX_MESSAGE_LEN -2 ); - return NULL; - } - - /* Don't try to send if we know there's no live connection. */ - if (conn->status != CONNECTION_OK) { - sprintf(conn->errorMessage, "PQexec() -- There is no connection " - "to the backend.\n"); - return NULL; - } - - /* the frontend-backend protocol uses 'Q' to designate queries */ - sprintf(buffer,"Q%s",query); - - /* send the query to the backend; */ - if (pqPuts(buffer, conn->Pfout, conn->Pfdebug) == 1) { - (void) sprintf(conn->errorMessage, - "PQexec() -- while sending query: %s\n" - "-- fprintf to Pfout failed: errno=%d\n%s\n", - query, errno, strerror(errno)); - return NULL; - } - - process_response_from_backend(conn->Pfin, conn->Pfout, conn->Pfdebug, conn, - &result, conn->errorMessage); - return(result); + PGresult *result; + char buffer[MAX_MESSAGE_LEN]; + + if (!conn) + return NULL; + if (!query) + { + sprintf(conn->errorMessage, "PQexec() -- query pointer is null."); + return NULL; + } + + /* clear the error string */ + conn->errorMessage[0] = '\0'; + + /* check to see if the query string is too long */ + if (strlen(query) > MAX_MESSAGE_LEN) + { + sprintf(conn->errorMessage, "PQexec() -- query is too long. " + "Maximum length is %d\n", MAX_MESSAGE_LEN - 2); + return NULL; + } + + /* Don't try to send if we know there's no live connection. */ + if (conn->status != CONNECTION_OK) + { + sprintf(conn->errorMessage, "PQexec() -- There is no connection " + "to the backend.\n"); + return NULL; + } + + /* the frontend-backend protocol uses 'Q' to designate queries */ + sprintf(buffer, "Q%s", query); + + /* send the query to the backend; */ + if (pqPuts(buffer, conn->Pfout, conn->Pfdebug) == 1) + { + (void) sprintf(conn->errorMessage, + "PQexec() -- while sending query: %s\n" + "-- fprintf to Pfout failed: errno=%d\n%s\n", + query, errno, strerror(errno)); + return NULL; + } + + process_response_from_backend(conn->Pfin, conn->Pfout, conn->Pfdebug, conn, + &result, conn->errorMessage); + return (result); } /* * PQnotifies - * returns a PGnotify* structure of the latest async notification + * returns a PGnotify* structure of the latest async notification * that has not yet been handled * - * returns NULL, if there is currently + * returns NULL, if there is currently * no unhandled async notification from the backend * * the CALLER is responsible for FREE'ing the structure returned */ -PGnotify* -PQnotifies(PGconn *conn) +PGnotify * +PQnotifies(PGconn * conn) { - Dlelem *e; - - if (!conn) return NULL; - - if (conn->status != CONNECTION_OK) - return NULL; - /* RemHead returns NULL if list is empy */ - e = DLRemHead(conn->notifyList); - if (e) - return (PGnotify*)DLE_VAL(e); - else - return NULL; + Dlelem *e; + + if (!conn) + return NULL; + + if (conn->status != CONNECTION_OK) + return NULL; + /* RemHead returns NULL if list is empy */ + e = DLRemHead(conn->notifyList); + if (e) + return (PGnotify *) DLE_VAL(e); + else + return NULL; } /* * PQgetline - gets a newline-terminated string from the backend. - * + * * Chiefly here so that applications can use "COPY <rel> to stdout" - * and read the output string. Returns a null-terminated string in s. + * and read the output string. Returns a null-terminated string in s. * * PQgetline reads up to maxlen-1 characters (like fgets(3)) but strips * the terminating \n (like gets(3)). * * RETURNS: - * EOF if it is detected or invalid arguments are given - * 0 if EOL is reached (i.e., \n has been read) - * (this is required for backward-compatibility -- this - * routine used to always return EOF or 0, assuming that - * the line ended within maxlen bytes.) - * 1 in other cases + * EOF if it is detected or invalid arguments are given + * 0 if EOL is reached (i.e., \n has been read) + * (this is required for backward-compatibility -- this + * routine used to always return EOF or 0, assuming that + * the line ended within maxlen bytes.) + * 1 in other cases */ int -PQgetline(PGconn *conn, char *s, int maxlen) +PQgetline(PGconn * conn, char *s, int maxlen) { - int c = '\0'; - - if (!conn) return EOF; - - if (!conn->Pfin || !s || maxlen <= 1) - return(EOF); - - for (; maxlen > 1 && - (c = pqGetc(conn->Pfin, conn->Pfdebug)) != '\n' && - c != EOF; - --maxlen) { - *s++ = c; - } - *s = '\0'; - - if (c == EOF) { - return(EOF); /* error -- reached EOF before \n */ - } else if (c == '\n') { - return(0); /* done with this line */ - } - return(1); /* returning a full buffer */ + int c = '\0'; + + if (!conn) + return EOF; + + if (!conn->Pfin || !s || maxlen <= 1) + return (EOF); + + for (; maxlen > 1 && + (c = pqGetc(conn->Pfin, conn->Pfdebug)) != '\n' && + c != EOF; + --maxlen) + { + *s++ = c; + } + *s = '\0'; + + if (c == EOF) + { + return (EOF); /* error -- reached EOF before \n */ + } + else if (c == '\n') + { + return (0); /* done with this line */ + } + return (1); /* returning a full buffer */ } /* * PQputline -- sends a string to the backend. - * + * * Chiefly here so that applications can use "COPY <rel> from stdin". * */ void -PQputline(PGconn *conn, const char *s) +PQputline(PGconn * conn, const char *s) { - if (conn && (conn->Pfout)) { - (void) fputs(s, conn->Pfout); - fflush(conn->Pfout); - } + if (conn && (conn->Pfout)) + { + (void) fputs(s, conn->Pfout); + fflush(conn->Pfout); + } } /* * PQendcopy - * called while waiting for the backend to respond with success/failure - * to a "copy". + * called while waiting for the backend to respond with success/failure + * to a "copy". * * RETURNS: - * 0 on success - * 1 on failure + * 0 on success + * 1 on failure */ int -PQendcopy(PGconn *conn) +PQendcopy(PGconn * conn) { - FILE *pfin, *pfdebug; - bool valid = true; - - if (!conn) return (int)NULL; - - pfin = conn->Pfin; - pfdebug = conn->Pfdebug; - - if ( pqGetc(pfin,pfdebug) == 'C') - { - char command[MAX_MESSAGE_LEN]; - pqGets(command,MAX_MESSAGE_LEN, pfin, pfdebug); /* read command tag */ - } - else valid = false; - - if ( valid ) - return (0); - else { - sprintf(conn->errorMessage, - "Error return detected from backend, " - "but attempt to read the message failed."); - fprintf(stderr,"resetting connection\n"); - PQreset(conn); - return(1); - } + FILE *pfin, + *pfdebug; + bool valid = true; + + if (!conn) + return (int) NULL; + + pfin = conn->Pfin; + pfdebug = conn->Pfdebug; + + if (pqGetc(pfin, pfdebug) == 'C') + { + char command[MAX_MESSAGE_LEN]; + + pqGets(command, MAX_MESSAGE_LEN, pfin, pfdebug); /* read command tag */ + } + else + valid = false; + + if (valid) + return (0); + else + { + sprintf(conn->errorMessage, + "Error return detected from backend, " + "but attempt to read the message failed."); + fprintf(stderr, "resetting connection\n"); + PQreset(conn); + return (1); + } } /* simply send out max-length number of filler characters to fp */ static void -fill (int length, int max, char filler, FILE *fp) +fill(int length, int max, char filler, FILE * fp) { - int count; - char filltmp[2]; - - filltmp[0] = filler; - filltmp[1] = 0; - count = max - length; - while (count-- >= 0) - { - fprintf(fp, "%s", filltmp); - } - } + int count; + char filltmp[2]; + + filltmp[0] = filler; + filltmp[1] = 0; + count = max - length; + while (count-- >= 0) + { + fprintf(fp, "%s", filltmp); + } +} /* * PQdisplayTuples() * kept for backward compatibility */ void -PQdisplayTuples(PGresult *res, - FILE *fp, /* where to send the output */ - int fillAlign, /* pad the fields with spaces */ - const char *fieldSep, /* field separator */ - int printHeader, /* display headers? */ - int quiet - ) +PQdisplayTuples(PGresult * res, + FILE * fp, /* where to send the output */ + int fillAlign, /* pad the fields with spaces */ + const char *fieldSep, /* field separator */ + int printHeader,/* display headers? */ + int quiet +) { #define DEFAULT_FIELD_SEP " " - int i, j; - int nFields; - int nTuples; - int fLength[MAX_FIELDS]; - - if (fieldSep == NULL) - fieldSep = DEFAULT_FIELD_SEP; - - /* Get some useful info about the results */ - nFields = PQnfields(res); - nTuples = PQntuples(res); - - if (fp == NULL) - fp = stdout; - - /* Zero the initial field lengths */ - for (j=0 ; j < nFields; j++) { - fLength[j] = strlen(PQfname(res,j)); - } - /* Find the max length of each field in the result */ - /* will be somewhat time consuming for very large results */ - if (fillAlign) { - for (i=0; i < nTuples; i++) { - for (j=0 ; j < nFields; j++) { - if (PQgetlength(res,i,j) > fLength[j]) - fLength[j] = PQgetlength(res,i,j); - } - } - } - - if (printHeader) { - /* first, print out the attribute names */ - for (i=0; i < nFields; i++) { - fputs(PQfname(res,i), fp); - if (fillAlign) - fill (strlen (PQfname(res,i)), fLength[i], ' ', fp); - fputs(fieldSep,fp); - } - fprintf(fp, "\n"); - - /* Underline the attribute names */ - for (i=0; i < nFields; i++) { - if (fillAlign) - fill (0, fLength[i], '-', fp); - fputs(fieldSep,fp); - } - fprintf(fp, "\n"); - } - - /* next, print out the instances */ - for (i=0; i < nTuples; i++) { - for (j=0 ; j < nFields; j++) { - fprintf(fp, "%s", PQgetvalue(res,i,j)); - if (fillAlign) - fill (strlen (PQgetvalue(res,i,j)), fLength[j], ' ', fp); - fputs(fieldSep,fp); - } - fprintf(fp, "\n"); - } - - if (!quiet) - fprintf (fp, "\nQuery returned %d row%s.\n",PQntuples(res), - (PQntuples(res) == 1) ? "" : "s"); - - fflush(fp); + int i, + j; + int nFields; + int nTuples; + int fLength[MAX_FIELDS]; + + if (fieldSep == NULL) + fieldSep = DEFAULT_FIELD_SEP; + + /* Get some useful info about the results */ + nFields = PQnfields(res); + nTuples = PQntuples(res); + + if (fp == NULL) + fp = stdout; + + /* Zero the initial field lengths */ + for (j = 0; j < nFields; j++) + { + fLength[j] = strlen(PQfname(res, j)); + } + /* Find the max length of each field in the result */ + /* will be somewhat time consuming for very large results */ + if (fillAlign) + { + for (i = 0; i < nTuples; i++) + { + for (j = 0; j < nFields; j++) + { + if (PQgetlength(res, i, j) > fLength[j]) + fLength[j] = PQgetlength(res, i, j); + } + } + } + + if (printHeader) + { + /* first, print out the attribute names */ + for (i = 0; i < nFields; i++) + { + fputs(PQfname(res, i), fp); + if (fillAlign) + fill(strlen(PQfname(res, i)), fLength[i], ' ', fp); + fputs(fieldSep, fp); + } + fprintf(fp, "\n"); + + /* Underline the attribute names */ + for (i = 0; i < nFields; i++) + { + if (fillAlign) + fill(0, fLength[i], '-', fp); + fputs(fieldSep, fp); + } + fprintf(fp, "\n"); + } + + /* next, print out the instances */ + for (i = 0; i < nTuples; i++) + { + for (j = 0; j < nFields; j++) + { + fprintf(fp, "%s", PQgetvalue(res, i, j)); + if (fillAlign) + fill(strlen(PQgetvalue(res, i, j)), fLength[j], ' ', fp); + fputs(fieldSep, fp); + } + fprintf(fp, "\n"); + } + + if (!quiet) + fprintf(fp, "\nQuery returned %d row%s.\n", PQntuples(res), + (PQntuples(res) == 1) ? "" : "s"); + + fflush(fp); } @@ -825,260 +933,311 @@ PQdisplayTuples(PGresult *res, * */ void -PQprintTuples(PGresult *res, - FILE* fout, /* output stream */ - int PrintAttNames,/* print attribute names or not*/ - int TerseOutput, /* delimiter bars or not?*/ - int colWidth /* width of column, if 0, use variable width */ - ) +PQprintTuples(PGresult * res, + FILE * fout, /* output stream */ + int PrintAttNames,/* print attribute names or not */ + int TerseOutput, /* delimiter bars or not? */ + int colWidth /* width of column, if 0, use variable + * width */ +) { - int nFields; - int nTups; - int i,j; - char formatString[80]; - - char *tborder = NULL; - - nFields = PQnfields(res); - nTups = PQntuples(res); - - if (colWidth > 0) { - sprintf(formatString,"%%s %%-%ds",colWidth); - } else - sprintf(formatString,"%%s %%s"); - - if ( nFields > 0 ) { /* only print rows with at least 1 field. */ - - if (!TerseOutput) - { - int width; - width = nFields * 14; - tborder = malloc (width+1); - for (i = 0; i <= width; i++) - tborder[i] = '-'; - tborder[i] = '\0'; - fprintf(fout,"%s\n",tborder); - } - - for (i=0; i < nFields; i++) { - if (PrintAttNames) { - fprintf(fout,formatString, - TerseOutput ? "" : "|", - PQfname(res, i)); - } - } - - if (PrintAttNames) { - if (TerseOutput) - fprintf(fout,"\n"); - else - fprintf(fout, "|\n%s\n",tborder); - } - - for (i = 0; i < nTups; i++) { - for (j = 0; j < nFields; j++) { - char *pval = PQgetvalue(res,i,j); - fprintf(fout, formatString, - TerseOutput ? "" : "|", - pval ? pval : ""); - } - if (TerseOutput) - fprintf(fout,"\n"); - else - fprintf(fout, "|\n%s\n",tborder); - } - } + int nFields; + int nTups; + int i, + j; + char formatString[80]; + + char *tborder = NULL; + + nFields = PQnfields(res); + nTups = PQntuples(res); + + if (colWidth > 0) + { + sprintf(formatString, "%%s %%-%ds", colWidth); + } + else + sprintf(formatString, "%%s %%s"); + + if (nFields > 0) + { /* only print rows with at least 1 field. */ + + if (!TerseOutput) + { + int width; + + width = nFields * 14; + tborder = malloc(width + 1); + for (i = 0; i <= width; i++) + tborder[i] = '-'; + tborder[i] = '\0'; + fprintf(fout, "%s\n", tborder); + } + + for (i = 0; i < nFields; i++) + { + if (PrintAttNames) + { + fprintf(fout, formatString, + TerseOutput ? "" : "|", + PQfname(res, i)); + } + } + + if (PrintAttNames) + { + if (TerseOutput) + fprintf(fout, "\n"); + else + fprintf(fout, "|\n%s\n", tborder); + } + + for (i = 0; i < nTups; i++) + { + for (j = 0; j < nFields; j++) + { + char *pval = PQgetvalue(res, i, j); + + fprintf(fout, formatString, + TerseOutput ? "" : "|", + pval ? pval : ""); + } + if (TerseOutput) + fprintf(fout, "\n"); + else + fprintf(fout, "|\n%s\n", tborder); + } + } } static void -do_field(PQprintOpt *po, PGresult *res, - const int i, const int j, char *buf, const int fs_len, - char *fields[], - const int nFields, char *fieldNames[], - unsigned char fieldNotNum[], int fieldMax[], - const int fieldMaxLen, FILE *fout - ) { - - char *pval, *p, *o; - int plen; - bool skipit; - - plen=PQgetlength(res,i,j); - pval=PQgetvalue(res,i,j); - - if (plen < 1 || !pval || !*pval) { - if (po->align || po->expanded) skipit = true; - else { - skipit = false; - goto efield; - } - } else skipit = false; - - if (!skipit) { - for (p=pval, o=buf; *p; *(o++)=*(p++)) { - if ((fs_len==1 && (*p==*(po->fieldSep))) || *p=='\\' || *p=='\n') - *(o++)='\\'; - if (po->align && (*pval=='E' || *pval=='e' || - !((*p>='0' && *p<='9') || - *p=='.' || - *p=='E' || - *p=='e' || - *p==' ' || - *p=='-'))) - fieldNotNum[j]=1; - } - *o='\0'; - if (!po->expanded && (po->align || po->html3)) { - int n=strlen(buf); - if (n>fieldMax[j]) - fieldMax[j]=n; - if (!(fields[i*nFields+j]=(char *)malloc(n+1))) { - perror("malloc"); - exit(1); - } - strcpy(fields[i*nFields+j], buf); - } else { - if (po->expanded) { - if (po->html3) - fprintf(fout, - "<tr><td align=left><b>%s</b></td>" - "<td align=%s>%s</td></tr>\n", - fieldNames[j], - fieldNotNum[j] ? "left": "right", - buf); - else { - if (po->align) - fprintf(fout, - "%-*s%s %s\n", - fieldMaxLen-fs_len, fieldNames[j], po->fieldSep, - buf); - else - fprintf(fout, "%s%s%s\n", fieldNames[j], po->fieldSep, buf); - } - } else { - if (!po->html3) { - fputs(buf, fout); - efield: - if ((j+1)<nFields) - fputs(po->fieldSep, fout); - else - fputc('\n', fout); - } - } - } - } +do_field(PQprintOpt * po, PGresult * res, + const int i, const int j, char *buf, const int fs_len, + char *fields[], + const int nFields, char *fieldNames[], + unsigned char fieldNotNum[], int fieldMax[], + const int fieldMaxLen, FILE * fout +) +{ + + char *pval, + *p, + *o; + int plen; + bool skipit; + + plen = PQgetlength(res, i, j); + pval = PQgetvalue(res, i, j); + + if (plen < 1 || !pval || !*pval) + { + if (po->align || po->expanded) + skipit = true; + else + { + skipit = false; + goto efield; + } + } + else + skipit = false; + + if (!skipit) + { + for (p = pval, o = buf; *p; *(o++) = *(p++)) + { + if ((fs_len == 1 && (*p == *(po->fieldSep))) || *p == '\\' || *p == '\n') + *(o++) = '\\'; + if (po->align && (*pval == 'E' || *pval == 'e' || + !((*p >= '0' && *p <= '9') || + *p == '.' || + *p == 'E' || + *p == 'e' || + *p == ' ' || + *p == '-'))) + fieldNotNum[j] = 1; + } + *o = '\0'; + if (!po->expanded && (po->align || po->html3)) + { + int n = strlen(buf); + + if (n > fieldMax[j]) + fieldMax[j] = n; + if (!(fields[i * nFields + j] = (char *) malloc(n + 1))) + { + perror("malloc"); + exit(1); + } + strcpy(fields[i * nFields + j], buf); + } + else + { + if (po->expanded) + { + if (po->html3) + fprintf(fout, + "<tr><td align=left><b>%s</b></td>" + "<td align=%s>%s</td></tr>\n", + fieldNames[j], + fieldNotNum[j] ? "left" : "right", + buf); + else + { + if (po->align) + fprintf(fout, + "%-*s%s %s\n", + fieldMaxLen - fs_len, fieldNames[j], po->fieldSep, + buf); + else + fprintf(fout, "%s%s%s\n", fieldNames[j], po->fieldSep, buf); + } + } + else + { + if (!po->html3) + { + fputs(buf, fout); + efield: + if ((j + 1) < nFields) + fputs(po->fieldSep, fout); + else + fputc('\n', fout); + } + } + } + } } -static char* -do_header(FILE *fout, PQprintOpt *po, const int nFields, int fieldMax[], - char *fieldNames[], unsigned char fieldNotNum[], - const int fs_len, PGresult *res) { - - int j; /* for loop index */ - char *border=NULL; - - if (po->html3) - fputs("<tr>", fout); - else { - int j; /* for loop index */ - int tot=0; - int n=0; - char *p=NULL; - for (; n < nFields; n++) - tot+=fieldMax[n]+fs_len+(po->standard? 2: 0); - if (po->standard) - tot+=fs_len*2+2; - border=malloc(tot+1); - if (!border) { - perror("malloc"); - exit(1); - } - p=border; - if (po->standard) { - char *fs=po->fieldSep; - while (*fs++) - *p++='+'; - } - for (j=0; j < nFields; j++) { - int len; - for (len=fieldMax[j] + (po->standard? 2:0) ; len--; *p++='-'); - if (po->standard || (j+1)<nFields) { - char *fs=po->fieldSep; - while (*fs++) - *p++='+'; - } - } - *p='\0'; - if (po->standard) - fprintf(fout, "%s\n", border); - } - if (po->standard) - fputs(po->fieldSep, fout); - for (j=0; j < nFields; j++) { - char *s=PQfname(res, j); - if (po->html3) { - fprintf(fout, "<th align=%s>%s</th>", - fieldNotNum[j]? "left": "right", fieldNames[j]); - } else { - int n=strlen(s); - if (n>fieldMax[j]) - fieldMax[j]=n; - if (po->standard) - fprintf(fout, - fieldNotNum[j] ? " %-*s ": " %*s ", - fieldMax[j], s); - else - fprintf(fout, fieldNotNum[j] ? "%-*s": "%*s", fieldMax[j], s); - if (po->standard || (j+1)<nFields) - fputs(po->fieldSep, fout); - } - } - if (po->html3) - fputs("</tr>\n", fout); - else - fprintf(fout, "\n%s\n", border); - return border; +static char * +do_header(FILE * fout, PQprintOpt * po, const int nFields, int fieldMax[], + char *fieldNames[], unsigned char fieldNotNum[], + const int fs_len, PGresult * res) +{ + + int j; /* for loop index */ + char *border = NULL; + + if (po->html3) + fputs("<tr>", fout); + else + { + int j; /* for loop index */ + int tot = 0; + int n = 0; + char *p = NULL; + + for (; n < nFields; n++) + tot += fieldMax[n] + fs_len + (po->standard ? 2 : 0); + if (po->standard) + tot += fs_len * 2 + 2; + border = malloc(tot + 1); + if (!border) + { + perror("malloc"); + exit(1); + } + p = border; + if (po->standard) + { + char *fs = po->fieldSep; + + while (*fs++) + *p++ = '+'; + } + for (j = 0; j < nFields; j++) + { + int len; + + for (len = fieldMax[j] + (po->standard ? 2 : 0); len--; *p++ = '-'); + if (po->standard || (j + 1) < nFields) + { + char *fs = po->fieldSep; + + while (*fs++) + *p++ = '+'; + } + } + *p = '\0'; + if (po->standard) + fprintf(fout, "%s\n", border); + } + if (po->standard) + fputs(po->fieldSep, fout); + for (j = 0; j < nFields; j++) + { + char *s = PQfname(res, j); + + if (po->html3) + { + fprintf(fout, "<th align=%s>%s</th>", + fieldNotNum[j] ? "left" : "right", fieldNames[j]); + } + else + { + int n = strlen(s); + + if (n > fieldMax[j]) + fieldMax[j] = n; + if (po->standard) + fprintf(fout, + fieldNotNum[j] ? " %-*s " : " %*s ", + fieldMax[j], s); + else + fprintf(fout, fieldNotNum[j] ? "%-*s" : "%*s", fieldMax[j], s); + if (po->standard || (j + 1) < nFields) + fputs(po->fieldSep, fout); + } + } + if (po->html3) + fputs("</tr>\n", fout); + else + fprintf(fout, "\n%s\n", border); + return border; } static void -output_row(FILE *fout, PQprintOpt *po, const int nFields, char *fields[], - unsigned char fieldNotNum[], int fieldMax[], char *border, - const int row_index) { - - int field_index; /* for loop index */ - - if (po->html3) - fputs("<tr>", fout); - else if (po->standard) - fputs(po->fieldSep, fout); - for (field_index = 0; field_index < nFields; field_index++) { - char *p=fields[row_index*nFields+field_index]; - if (po->html3) - fprintf(fout, "<td align=%s>%s</td>", - fieldNotNum[field_index]? "left": "right", p? p: ""); - else { - fprintf(fout, - fieldNotNum[field_index] ? - (po->standard ? " %-*s ": "%-*s") : - (po->standard ? " %*s ": "%*s"), - fieldMax[field_index], - p ? p: ""); - if (po->standard || field_index+1 < nFields) - fputs(po->fieldSep, fout); - } - if (p) - free(p); - } - if (po->html3) - fputs("</tr>", fout); - else - if (po->standard) - fprintf(fout, "\n%s", border); - fputc('\n', fout); +output_row(FILE * fout, PQprintOpt * po, const int nFields, char *fields[], + unsigned char fieldNotNum[], int fieldMax[], char *border, + const int row_index) +{ + + int field_index;/* for loop index */ + + if (po->html3) + fputs("<tr>", fout); + else if (po->standard) + fputs(po->fieldSep, fout); + for (field_index = 0; field_index < nFields; field_index++) + { + char *p = fields[row_index * nFields + field_index]; + + if (po->html3) + fprintf(fout, "<td align=%s>%s</td>", + fieldNotNum[field_index] ? "left" : "right", p ? p : ""); + else + { + fprintf(fout, + fieldNotNum[field_index] ? + (po->standard ? " %-*s " : "%-*s") : + (po->standard ? " %*s " : "%*s"), + fieldMax[field_index], + p ? p : ""); + if (po->standard || field_index + 1 < nFields) + fputs(po->fieldSep, fout); + } + if (p) + free(p); + } + if (po->html3) + fputs("</tr>", fout); + else if (po->standard) + fprintf(fout, "\n%s", border); + fputc('\n', fout); } @@ -1097,591 +1256,672 @@ output_row(FILE *fout, PQprintOpt *po, const int nFields, char *fields[], */ void -PQprint(FILE *fout, - PGresult *res, - PQprintOpt *po - ) +PQprint(FILE * fout, + PGresult * res, + PQprintOpt * po +) { - int nFields; - - nFields = PQnfields(res); - - if ( nFields > 0 ) { /* only print rows with at least 1 field. */ - int i,j; - int nTups; - int *fieldMax=NULL; /* in case we don't use them */ - unsigned char *fieldNotNum=NULL; - char *border=NULL; - char **fields=NULL; - char **fieldNames; - int fieldMaxLen=0; - int numFieldName; - int fs_len=strlen(po->fieldSep); - int total_line_length = 0; - int usePipe = 0; - char *pagerenv; - char buf[8192*2+1]; - - nTups = PQntuples(res); - if (!(fieldNames=(char **)calloc(nFields, sizeof (char *)))) { - perror("calloc"); - exit(1); - } - if (!(fieldNotNum=(unsigned char *)calloc(nFields, 1))) { - perror("calloc"); - exit(1); - } - if (!(fieldMax=(int *)calloc(nFields, sizeof(int)))) { - perror("calloc"); - exit(1); - } - for (numFieldName=0; - po->fieldName && po->fieldName[numFieldName]; - numFieldName++) - ; - for (j=0; j < nFields; j++) { - int len; - char *s = - (j<numFieldName && po->fieldName[j][0])? - po->fieldName[j]: PQfname(res, j); - fieldNames[j]=s; - len=s ? strlen(s): 0; - fieldMax[j] = len; - len+=fs_len; - if (len>fieldMaxLen) - fieldMaxLen=len; - total_line_length += len; - } - - total_line_length += nFields * strlen(po->fieldSep) + 1; - - if (fout == NULL) - fout = stdout; - if (po->pager && fout == stdout && - isatty(fileno(stdin)) && - isatty(fileno(stdout))) { - /* try to pipe to the pager program if possible */ + int nFields; + + nFields = PQnfields(res); + + if (nFields > 0) + { /* only print rows with at least 1 field. */ + int i, + j; + int nTups; + int *fieldMax = NULL; /* in case we don't use + * them */ + unsigned char *fieldNotNum = NULL; + char *border = NULL; + char **fields = NULL; + char **fieldNames; + int fieldMaxLen = 0; + int numFieldName; + int fs_len = strlen(po->fieldSep); + int total_line_length = 0; + int usePipe = 0; + char *pagerenv; + char buf[8192 * 2 + 1]; + + nTups = PQntuples(res); + if (!(fieldNames = (char **) calloc(nFields, sizeof(char *)))) + { + perror("calloc"); + exit(1); + } + if (!(fieldNotNum = (unsigned char *) calloc(nFields, 1))) + { + perror("calloc"); + exit(1); + } + if (!(fieldMax = (int *) calloc(nFields, sizeof(int)))) + { + perror("calloc"); + exit(1); + } + for (numFieldName = 0; + po->fieldName && po->fieldName[numFieldName]; + numFieldName++) + ; + for (j = 0; j < nFields; j++) + { + int len; + char *s = + (j < numFieldName && po->fieldName[j][0]) ? + po->fieldName[j] : PQfname(res, j); + + fieldNames[j] = s; + len = s ? strlen(s) : 0; + fieldMax[j] = len; + len += fs_len; + if (len > fieldMaxLen) + fieldMaxLen = len; + total_line_length += len; + } + + total_line_length += nFields * strlen(po->fieldSep) + 1; + + if (fout == NULL) + fout = stdout; + if (po->pager && fout == stdout && + isatty(fileno(stdin)) && + isatty(fileno(stdout))) + { + /* try to pipe to the pager program if possible */ #ifdef TIOCGWINSZ - if (ioctl(fileno(stdout),TIOCGWINSZ,&screen_size) == -1 || - screen_size.ws_col == 0 || - screen_size.ws_row == 0) { + if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1 || + screen_size.ws_col == 0 || + screen_size.ws_row == 0) + { #endif - screen_size.ws_row = 24; - screen_size.ws_col = 80; + screen_size.ws_row = 24; + screen_size.ws_col = 80; #ifdef TIOCGWINSZ - } + } #endif - pagerenv=getenv("PAGER"); - if (pagerenv != NULL && - pagerenv[0] != '\0' && - !po->html3 && - ((po->expanded && - nTups * (nFields+1) >= screen_size.ws_row) || - (!po->expanded && - nTups * (total_line_length / screen_size.ws_col + 1) * - ( 1 + (po->standard != 0)) >= - screen_size.ws_row - - (po->header != 0) * - (total_line_length / screen_size.ws_col + 1) * 2 - - (po->header != 0) *2 /* row count and newline */ - ))) { - fout = popen(pagerenv, "w"); - if (fout) { - usePipe = 1; - pqsignal(SIGPIPE, SIG_IGN); - } else - fout = stdout; - } - } - - if (!po->expanded && (po->align || po->html3)) { - if (!(fields=(char **)calloc(nFields*(nTups+1), sizeof(char *)))) { - perror("calloc"); - exit(1); - } - } else - if (po->header && !po->html3) { - if (po->expanded) { - if (po->align) - fprintf(fout, "%-*s%s Value\n", - fieldMaxLen-fs_len, "Field", po->fieldSep); - else - fprintf(fout, "%s%sValue\n", "Field", po->fieldSep); - } else { - int len=0; - for (j=0; j < nFields; j++) { - char *s=fieldNames[j]; - fputs(s, fout); - len+=strlen(s)+fs_len; - if ((j+1)<nFields) - fputs(po->fieldSep, fout); - } - fputc('\n', fout); - for (len-=fs_len; len--; fputc('-', fout)); - fputc('\n', fout); - } - } - if (po->expanded && po->html3) { - if (po->caption) - fprintf(fout, "<centre><h2>%s</h2></centre>\n", po->caption); - else - fprintf(fout, - "<centre><h2>" - "Query retrieved %d rows * %d fields" - "</h2></centre>\n", - nTups, nFields); - } - for (i = 0; i < nTups; i++) { - if (po->expanded) { - if (po->html3) - fprintf(fout, - "<table %s><caption align=high>%d</caption>\n", - po->tableOpt? po->tableOpt: "", i); - else - fprintf(fout, "-- RECORD %d --\n", i); - } - for (j = 0; j < nFields; j++) - do_field(po, res, i, j, buf, fs_len, fields, nFields, - fieldNames, fieldNotNum, - fieldMax, fieldMaxLen, fout); - if (po->html3 && po->expanded) - fputs("</table>\n", fout); - } - if (!po->expanded && (po->align || po->html3)) { - if (po->html3) { - if (po->header) { - if (po->caption) - fprintf(fout, - "<table %s><caption align=high>%s</caption>\n", - po->tableOpt? po->tableOpt: "", - po->caption); - else - fprintf(fout, - "<table %s><caption align=high>" - "Retrieved %d rows * %d fields" - "</caption>\n", - po->tableOpt? po->tableOpt: "", nTups, nFields); - } else - fprintf(fout, "<table %s>", po->tableOpt? po->tableOpt: ""); - } - if (po->header) - border = do_header(fout, po, nFields, fieldMax, fieldNames, - fieldNotNum, fs_len, res); - for (i = 0; i < nTups; i++) - output_row(fout, po, nFields, fields, - fieldNotNum, fieldMax, border, i); - free(fields); - if (border) - free(border); - } - if (po->header && !po->html3) - fprintf (fout, "(%d row%s)\n\n",PQntuples(res), - (PQntuples(res) == 1) ? "" : "s"); - free(fieldMax); - free(fieldNotNum); - free(fieldNames); - if (usePipe) { - pclose(fout); - pqsignal(SIGPIPE, SIG_DFL); - } - if (po->html3 && !po->expanded) - fputs("</table>\n", fout); - } + pagerenv = getenv("PAGER"); + if (pagerenv != NULL && + pagerenv[0] != '\0' && + !po->html3 && + ((po->expanded && + nTups * (nFields + 1) >= screen_size.ws_row) || + (!po->expanded && + nTups * (total_line_length / screen_size.ws_col + 1) * + (1 + (po->standard != 0)) >= + screen_size.ws_row - + (po->header != 0) * + (total_line_length / screen_size.ws_col + 1) * 2 + - (po->header != 0) * 2 /* row count and newline */ + ))) + { + fout = popen(pagerenv, "w"); + if (fout) + { + usePipe = 1; + pqsignal(SIGPIPE, SIG_IGN); + } + else + fout = stdout; + } + } + + if (!po->expanded && (po->align || po->html3)) + { + if (!(fields = (char **) calloc(nFields * (nTups + 1), sizeof(char *)))) + { + perror("calloc"); + exit(1); + } + } + else if (po->header && !po->html3) + { + if (po->expanded) + { + if (po->align) + fprintf(fout, "%-*s%s Value\n", + fieldMaxLen - fs_len, "Field", po->fieldSep); + else + fprintf(fout, "%s%sValue\n", "Field", po->fieldSep); + } + else + { + int len = 0; + + for (j = 0; j < nFields; j++) + { + char *s = fieldNames[j]; + + fputs(s, fout); + len += strlen(s) + fs_len; + if ((j + 1) < nFields) + fputs(po->fieldSep, fout); + } + fputc('\n', fout); + for (len -= fs_len; len--; fputc('-', fout)); + fputc('\n', fout); + } + } + if (po->expanded && po->html3) + { + if (po->caption) + fprintf(fout, "<centre><h2>%s</h2></centre>\n", po->caption); + else + fprintf(fout, + "<centre><h2>" + "Query retrieved %d rows * %d fields" + "</h2></centre>\n", + nTups, nFields); + } + for (i = 0; i < nTups; i++) + { + if (po->expanded) + { + if (po->html3) + fprintf(fout, + "<table %s><caption align=high>%d</caption>\n", + po->tableOpt ? po->tableOpt : "", i); + else + fprintf(fout, "-- RECORD %d --\n", i); + } + for (j = 0; j < nFields; j++) + do_field(po, res, i, j, buf, fs_len, fields, nFields, + fieldNames, fieldNotNum, + fieldMax, fieldMaxLen, fout); + if (po->html3 && po->expanded) + fputs("</table>\n", fout); + } + if (!po->expanded && (po->align || po->html3)) + { + if (po->html3) + { + if (po->header) + { + if (po->caption) + fprintf(fout, + "<table %s><caption align=high>%s</caption>\n", + po->tableOpt ? po->tableOpt : "", + po->caption); + else + fprintf(fout, + "<table %s><caption align=high>" + "Retrieved %d rows * %d fields" + "</caption>\n", + po->tableOpt ? po->tableOpt : "", nTups, nFields); + } + else + fprintf(fout, "<table %s>", po->tableOpt ? po->tableOpt : ""); + } + if (po->header) + border = do_header(fout, po, nFields, fieldMax, fieldNames, + fieldNotNum, fs_len, res); + for (i = 0; i < nTups; i++) + output_row(fout, po, nFields, fields, + fieldNotNum, fieldMax, border, i); + free(fields); + if (border) + free(border); + } + if (po->header && !po->html3) + fprintf(fout, "(%d row%s)\n\n", PQntuples(res), + (PQntuples(res) == 1) ? "" : "s"); + free(fieldMax); + free(fieldNotNum); + free(fieldNames); + if (usePipe) + { + pclose(fout); + pqsignal(SIGPIPE, SIG_DFL); + } + if (po->html3 && !po->expanded) + fputs("</table>\n", fout); + } } /* ---------------- - * PQfn - Send a function call to the POSTGRES backend. + * PQfn - Send a function call to the POSTGRES backend. * - * conn : backend connection - * fnid : function id - * result_buf : pointer to result buffer (&int if integer) - * result_len : length of return value. - * actual_result_len: actual length returned. (differs from result_len - * for varlena structures.) - * result_type : If the result is an integer, this must be 1, - * otherwise this should be 0 - * args : pointer to a NULL terminated arg array. - * (length, if integer, and result-pointer) - * nargs : # of arguments in args array. + * conn : backend connection + * fnid : function id + * result_buf : pointer to result buffer (&int if integer) + * result_len : length of return value. + * actual_result_len: actual length returned. (differs from result_len + * for varlena structures.) + * result_type : If the result is an integer, this must be 1, + * otherwise this should be 0 + * args : pointer to a NULL terminated arg array. + * (length, if integer, and result-pointer) + * nargs : # of arguments in args array. * * RETURNS - * NULL on failure. PQerrormsg will be set. - * "G" if there is a return value. - * "V" if there is no return value. + * NULL on failure. PQerrormsg will be set. + * "G" if there is a return value. + * "V" if there is no return value. * ---------------- */ -PGresult* -PQfn(PGconn *conn, - int fnid, - int *result_buf, - int *actual_result_len, - int result_is_int, - PQArgBlock *args, - int nargs) +PGresult * +PQfn(PGconn * conn, + int fnid, + int *result_buf, + int *actual_result_len, + int result_is_int, + PQArgBlock * args, + int nargs) { - FILE *pfin, *pfout, *pfdebug; - int id; - int i; - - if (!conn) return NULL; - - pfin = conn->Pfin; - pfout = conn->Pfout; - pfdebug = conn->Pfdebug; - - /* clear the error string */ - conn->errorMessage[0] = '\0'; - - pqPuts("F ",pfout,pfdebug); /* function */ - pqPutInt(fnid, 4, pfout, pfdebug); /* function id */ - pqPutInt(nargs, 4, pfout, pfdebug); /* # of args */ - - for (i = 0; i < nargs; ++i) { /* len.int4 + contents */ - pqPutInt(args[i].len, 4, pfout, pfdebug); - if (args[i].isint) { - pqPutInt(args[i].u.integer, 4, pfout, pfdebug); - } else { - pqPutnchar((char *)args[i].u.ptr, args[i].len, pfout, pfdebug); - } - } - pqFlush(pfout, pfdebug); - - id = pqGetc(pfin, pfdebug); - if (id != 'V') { - if (id == 'E') { - pqGets(conn->errorMessage,ERROR_MSG_LENGTH,pfin,pfdebug); - } else - sprintf(conn->errorMessage, - "PQfn: expected a 'V' from the backend. Got '%c' instead", - id); - return makeEmptyPGresult(conn,PGRES_FATAL_ERROR); - } - - id = pqGetc(pfin, pfdebug); - for (;;) { - int c; - switch (id) { - case 'G': /* function returned properly */ - pqGetInt(actual_result_len,4,pfin,pfdebug); - if (result_is_int) { - pqGetInt(result_buf,4,pfin,pfdebug); - } else { - pqGetnchar((char *) result_buf, *actual_result_len, - pfin, pfdebug); - } - c = pqGetc(pfin, pfdebug); /* get the last '0'*/ - return makeEmptyPGresult(conn,PGRES_COMMAND_OK); - case 'E': - sprintf(conn->errorMessage, - "PQfn: returned an error"); - return makeEmptyPGresult(conn,PGRES_FATAL_ERROR); - case 'N': - /* print notice and go back to processing return values */ - if (pqGets(conn->errorMessage, ERROR_MSG_LENGTH, pfin, pfdebug) - == 1) { - sprintf(conn->errorMessage, - "Notice return detected from backend, but message " - "cannot be read"); - } else - fprintf(stderr, "%s\n", conn->errorMessage); - /* keep iterating */ - break; - case '0': /* no return value */ - return makeEmptyPGresult(conn,PGRES_COMMAND_OK); - default: - /* The backend violates the protocol. */ - sprintf(conn->errorMessage, - "FATAL: PQfn: protocol error: id=%x\n", id); - return makeEmptyPGresult(conn,PGRES_FATAL_ERROR); - } - } + FILE *pfin, + *pfout, + *pfdebug; + int id; + int i; + + if (!conn) + return NULL; + + pfin = conn->Pfin; + pfout = conn->Pfout; + pfdebug = conn->Pfdebug; + + /* clear the error string */ + conn->errorMessage[0] = '\0'; + + pqPuts("F ", pfout, pfdebug); /* function */ + pqPutInt(fnid, 4, pfout, pfdebug); /* function id */ + pqPutInt(nargs, 4, pfout, pfdebug); /* # of args */ + + for (i = 0; i < nargs; ++i) + { /* len.int4 + contents */ + pqPutInt(args[i].len, 4, pfout, pfdebug); + if (args[i].isint) + { + pqPutInt(args[i].u.integer, 4, pfout, pfdebug); + } + else + { + pqPutnchar((char *) args[i].u.ptr, args[i].len, pfout, pfdebug); + } + } + pqFlush(pfout, pfdebug); + + id = pqGetc(pfin, pfdebug); + if (id != 'V') + { + if (id == 'E') + { + pqGets(conn->errorMessage, ERROR_MSG_LENGTH, pfin, pfdebug); + } + else + sprintf(conn->errorMessage, + "PQfn: expected a 'V' from the backend. Got '%c' instead", + id); + return makeEmptyPGresult(conn, PGRES_FATAL_ERROR); + } + + id = pqGetc(pfin, pfdebug); + for (;;) + { + int c; + + switch (id) + { + case 'G': /* function returned properly */ + pqGetInt(actual_result_len, 4, pfin, pfdebug); + if (result_is_int) + { + pqGetInt(result_buf, 4, pfin, pfdebug); + } + else + { + pqGetnchar((char *) result_buf, *actual_result_len, + pfin, pfdebug); + } + c = pqGetc(pfin, pfdebug); /* get the last '0' */ + return makeEmptyPGresult(conn, PGRES_COMMAND_OK); + case 'E': + sprintf(conn->errorMessage, + "PQfn: returned an error"); + return makeEmptyPGresult(conn, PGRES_FATAL_ERROR); + case 'N': + /* print notice and go back to processing return values */ + if (pqGets(conn->errorMessage, ERROR_MSG_LENGTH, pfin, pfdebug) + == 1) + { + sprintf(conn->errorMessage, + "Notice return detected from backend, but message " + "cannot be read"); + } + else + fprintf(stderr, "%s\n", conn->errorMessage); + /* keep iterating */ + break; + case '0': /* no return value */ + return makeEmptyPGresult(conn, PGRES_COMMAND_OK); + default: + /* The backend violates the protocol. */ + sprintf(conn->errorMessage, + "FATAL: PQfn: protocol error: id=%x\n", id); + return makeEmptyPGresult(conn, PGRES_FATAL_ERROR); + } + } } /* ====== accessor funcs for PGresult ======== */ -ExecStatusType -PQresultStatus(PGresult* res) -{ - if (!res) { - fprintf(stderr, "PQresultStatus() -- pointer to PQresult is null"); - return PGRES_NONFATAL_ERROR; - } +ExecStatusType +PQresultStatus(PGresult * res) +{ + if (!res) + { + fprintf(stderr, "PQresultStatus() -- pointer to PQresult is null"); + return PGRES_NONFATAL_ERROR; + } - return res->resultStatus; + return res->resultStatus; } -int -PQntuples(PGresult *res) +int +PQntuples(PGresult * res) { - if (!res) { - fprintf(stderr, "PQntuples() -- pointer to PQresult is null"); - return (int)NULL; - } - return res->ntups; + if (!res) + { + fprintf(stderr, "PQntuples() -- pointer to PQresult is null"); + return (int) NULL; + } + return res->ntups; } int -PQnfields(PGresult *res) +PQnfields(PGresult * res) { - if (!res) { - fprintf(stderr, "PQnfields() -- pointer to PQresult is null"); - return (int)NULL; - } - return res->numAttributes; + if (!res) + { + fprintf(stderr, "PQnfields() -- pointer to PQresult is null"); + return (int) NULL; + } + return res->numAttributes; } /* returns NULL if the field_num is invalid */ -char* -PQfname(PGresult *res, int field_num) +char * +PQfname(PGresult * res, int field_num) { - if (!res) { - fprintf(stderr, "PQfname() -- pointer to PQresult is null"); - return NULL; - } - - if (field_num > (res->numAttributes - 1)) { - fprintf(stderr, - "PQfname: ERROR! name of field %d(of %d) is not available", - field_num, res->numAttributes -1); - return NULL; - } - if (res->attDescs) { - return res->attDescs[field_num].name; - } else - return NULL; + if (!res) + { + fprintf(stderr, "PQfname() -- pointer to PQresult is null"); + return NULL; + } + + if (field_num > (res->numAttributes - 1)) + { + fprintf(stderr, + "PQfname: ERROR! name of field %d(of %d) is not available", + field_num, res->numAttributes - 1); + return NULL; + } + if (res->attDescs) + { + return res->attDescs[field_num].name; + } + else + return NULL; } /* returns -1 on a bad field name */ int -PQfnumber(PGresult *res, const char* field_name) +PQfnumber(PGresult * res, const char *field_name) { - int i; + int i; - if (!res) { - fprintf(stderr, "PQfnumber() -- pointer to PQresult is null"); - return -1; - } + if (!res) + { + fprintf(stderr, "PQfnumber() -- pointer to PQresult is null"); + return -1; + } - if (field_name == NULL || - field_name[0] == '\0' || - res->attDescs == NULL) - return -1; + if (field_name == NULL || + field_name[0] == '\0' || + res->attDescs == NULL) + return -1; - for (i=0;i<res->numAttributes;i++) { - if ( strcasecmp(field_name, res->attDescs[i].name) == 0 ) - return i; - } - return -1; + for (i = 0; i < res->numAttributes; i++) + { + if (strcasecmp(field_name, res->attDescs[i].name) == 0) + return i; + } + return -1; } Oid -PQftype(PGresult *res, int field_num) +PQftype(PGresult * res, int field_num) { - if (!res) { - fprintf(stderr, "PQftype() -- pointer to PQresult is null"); - return InvalidOid; - } - - if (field_num > (res->numAttributes - 1)) { - fprintf(stderr, - "PQftype: ERROR! type of field %d(of %d) is not available", - field_num, res->numAttributes -1); - } - if (res->attDescs) { - return res->attDescs[field_num].adtid; - } else - return InvalidOid; + if (!res) + { + fprintf(stderr, "PQftype() -- pointer to PQresult is null"); + return InvalidOid; + } + + if (field_num > (res->numAttributes - 1)) + { + fprintf(stderr, + "PQftype: ERROR! type of field %d(of %d) is not available", + field_num, res->numAttributes - 1); + } + if (res->attDescs) + { + return res->attDescs[field_num].adtid; + } + else + return InvalidOid; } int2 -PQfsize(PGresult *res, int field_num) +PQfsize(PGresult * res, int field_num) { - if (!res) { - fprintf(stderr, "PQfsize() -- pointer to PQresult is null"); - return (int2)NULL; - } - - if (field_num > (res->numAttributes - 1)) { - fprintf(stderr, - "PQfsize: ERROR! size of field %d(of %d) is not available", - field_num, res->numAttributes -1); - } - if (res->attDescs) { - return res->attDescs[field_num].adtsize; - } else - return 0; + if (!res) + { + fprintf(stderr, "PQfsize() -- pointer to PQresult is null"); + return (int2) NULL; + } + + if (field_num > (res->numAttributes - 1)) + { + fprintf(stderr, + "PQfsize: ERROR! size of field %d(of %d) is not available", + field_num, res->numAttributes - 1); + } + if (res->attDescs) + { + return res->attDescs[field_num].adtsize; + } + else + return 0; } -char* PQcmdStatus(PGresult *res) { - if (!res) { - fprintf(stderr, "PQcmdStatus() -- pointer to PQresult is null"); - return NULL; - } - return res->cmdStatus; +char * +PQcmdStatus(PGresult * res) +{ + if (!res) + { + fprintf(stderr, "PQcmdStatus() -- pointer to PQresult is null"); + return NULL; + } + return res->cmdStatus; } /* PQoidStatus - - if the last command was an INSERT, return the oid string - if not, return "" + if the last command was an INSERT, return the oid string + if not, return "" */ -static char oidStatus[32] = {0}; -const char* PQoidStatus (PGresult *res) +static char oidStatus[32] = {0}; +const char * +PQoidStatus(PGresult * res) { - if (!res) - { - fprintf (stderr, "PQoidStatus () -- pointer to PQresult is null"); - return NULL; - } - - oidStatus[0] = 0; - if ( !res->cmdStatus ) - return oidStatus; - - if ( strncmp (res->cmdStatus, "INSERT", 6) == 0 ) - { - char *p = res->cmdStatus + 7; - char *e; - - for (e = p; *e != ' ' && *e; ) e++; - sprintf (oidStatus, "%.*s", e - p, p); - } - return oidStatus; + if (!res) + { + fprintf(stderr, "PQoidStatus () -- pointer to PQresult is null"); + return NULL; + } + + oidStatus[0] = 0; + if (!res->cmdStatus) + return oidStatus; + + if (strncmp(res->cmdStatus, "INSERT", 6) == 0) + { + char *p = res->cmdStatus + 7; + char *e; + + for (e = p; *e != ' ' && *e;) + e++; + sprintf(oidStatus, "%.*s", e - p, p); + } + return oidStatus; } /* PQcmdTuples - - if the last command was an INSERT/UPDATE/DELETE, return number - of inserted/affected tuples, if not, return "" + if the last command was an INSERT/UPDATE/DELETE, return number + of inserted/affected tuples, if not, return "" */ -const char* PQcmdTuples (PGresult *res) +const char * +PQcmdTuples(PGresult * res) { - if (!res) - { - fprintf (stderr, "PQcmdTuples () -- pointer to PQresult is null"); - return NULL; - } - - if ( !res->cmdStatus ) - return ""; - - if ( strncmp (res->cmdStatus, "INSERT", 6) == 0 || - strncmp (res->cmdStatus, "DELETE", 6) == 0 || - strncmp (res->cmdStatus, "UPDATE", 6) == 0 ) - { - char *p = res->cmdStatus + 6; - - if ( *p == 0 ) - { - fprintf (stderr, "PQcmdTuples (%s) -- short input from server", - res->cmdStatus); - return NULL; - } - p++; - if ( *(res->cmdStatus) != 'I' ) /* UPDATE/DELETE */ - return (p); - while ( *p != ' ' && *p ) p++; /* INSERT: skip oid */ - if ( *p == 0 ) - { - fprintf (stderr, "PQcmdTuples (INSERT) -- there's no # of tuples"); - return NULL; - } - p++; - return (p); - } - return ""; + if (!res) + { + fprintf(stderr, "PQcmdTuples () -- pointer to PQresult is null"); + return NULL; + } + + if (!res->cmdStatus) + return ""; + + if (strncmp(res->cmdStatus, "INSERT", 6) == 0 || + strncmp(res->cmdStatus, "DELETE", 6) == 0 || + strncmp(res->cmdStatus, "UPDATE", 6) == 0) + { + char *p = res->cmdStatus + 6; + + if (*p == 0) + { + fprintf(stderr, "PQcmdTuples (%s) -- short input from server", + res->cmdStatus); + return NULL; + } + p++; + if (*(res->cmdStatus) != 'I') /* UPDATE/DELETE */ + return (p); + while (*p != ' ' && *p) + p++; /* INSERT: skip oid */ + if (*p == 0) + { + fprintf(stderr, "PQcmdTuples (INSERT) -- there's no # of tuples"); + return NULL; + } + p++; + return (p); + } + return ""; } /* PQgetvalue: - return the value of field 'field_num' of row 'tup_num' + return the value of field 'field_num' of row 'tup_num' - If res is binary, then the value returned is NOT a null-terminated - ASCII string, but the binary representation in the server's native - format. + If res is binary, then the value returned is NOT a null-terminated + ASCII string, but the binary representation in the server's native + format. - if res is not binary, a null-terminated ASCII string is returned. + if res is not binary, a null-terminated ASCII string is returned. */ -char* -PQgetvalue(PGresult *res, int tup_num, int field_num) +char * +PQgetvalue(PGresult * res, int tup_num, int field_num) { - if (!res) { - fprintf(stderr, "PQgetvalue: pointer to PQresult is null\n"); - return NULL; - } else if (tup_num > (res->ntups - 1)) { - fprintf(stderr, - "PQgetvalue: There is no row %d in the query results. " - "The highest numbered row is %d.\n", - tup_num, res->ntups - 1); - return NULL; - } else if (field_num > (res->numAttributes - 1)) { - fprintf(stderr, - "PQgetvalue: There is no field %d in the query results. " - "The highest numbered field is %d.\n", - field_num, res->numAttributes - 1); - return NULL; - } - - return res->tuples[tup_num][field_num].value; + if (!res) + { + fprintf(stderr, "PQgetvalue: pointer to PQresult is null\n"); + return NULL; + } + else if (tup_num > (res->ntups - 1)) + { + fprintf(stderr, + "PQgetvalue: There is no row %d in the query results. " + "The highest numbered row is %d.\n", + tup_num, res->ntups - 1); + return NULL; + } + else if (field_num > (res->numAttributes - 1)) + { + fprintf(stderr, + "PQgetvalue: There is no field %d in the query results. " + "The highest numbered field is %d.\n", + field_num, res->numAttributes - 1); + return NULL; + } + + return res->tuples[tup_num][field_num].value; } /* PQgetlength: - returns the length of a field value in bytes. If res is binary, - i.e. a result of a binary portal, then the length returned does - NOT include the size field of the varlena. + returns the length of a field value in bytes. If res is binary, + i.e. a result of a binary portal, then the length returned does + NOT include the size field of the varlena. */ int -PQgetlength(PGresult *res, int tup_num, int field_num) +PQgetlength(PGresult * res, int tup_num, int field_num) { - if (!res) { - fprintf(stderr, "PQgetlength() -- pointer to PQresult is null"); - return (int)NULL; - } - - if (tup_num > (res->ntups - 1 )|| - field_num > (res->numAttributes - 1)) { - fprintf(stderr, - "PQgetlength: ERROR! field %d(of %d) of row %d(of %d) " - "is not available", - field_num, res->numAttributes - 1, tup_num, res->ntups); - } - - if (res->tuples[tup_num][field_num].len != NULL_LEN) - return res->tuples[tup_num][field_num].len; - else - return 0; - } + if (!res) + { + fprintf(stderr, "PQgetlength() -- pointer to PQresult is null"); + return (int) NULL; + } + + if (tup_num > (res->ntups - 1) || + field_num > (res->numAttributes - 1)) + { + fprintf(stderr, + "PQgetlength: ERROR! field %d(of %d) of row %d(of %d) " + "is not available", + field_num, res->numAttributes - 1, tup_num, res->ntups); + } + + if (res->tuples[tup_num][field_num].len != NULL_LEN) + return res->tuples[tup_num][field_num].len; + else + return 0; +} /* PQgetisnull: - returns the null status of a field value. + returns the null status of a field value. */ int -PQgetisnull(PGresult *res, int tup_num, int field_num) +PQgetisnull(PGresult * res, int tup_num, int field_num) { - if (!res) { - fprintf(stderr, "PQgetisnull() -- pointer to PQresult is null"); - return (int)NULL; - } - - if (tup_num > (res->ntups - 1 )|| - field_num > (res->numAttributes - 1)) { - fprintf(stderr, - "PQgetisnull: ERROR! field %d(of %d) of row %d(of %d) " - "is not available", - field_num, res->numAttributes - 1, tup_num, res->ntups); - } - - if (res->tuples[tup_num][field_num].len == NULL_LEN) - return 1; - else - return 0; + if (!res) + { + fprintf(stderr, "PQgetisnull() -- pointer to PQresult is null"); + return (int) NULL; + } + + if (tup_num > (res->ntups - 1) || + field_num > (res->numAttributes - 1)) + { + fprintf(stderr, + "PQgetisnull: ERROR! field %d(of %d) of row %d(of %d) " + "is not available", + field_num, res->numAttributes - 1, tup_num, res->ntups); + } + + if (res->tuples[tup_num][field_num].len == NULL_LEN) + return 1; + else + return 0; } diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c index 9b566cea339..1636edc7f42 100644 --- a/src/interfaces/libpq/fe-lobj.c +++ b/src/interfaces/libpq/fe-lobj.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------- * * fe-lobj.c-- - * Front-end large object interface + * Front-end large object interface * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.7 1997/05/06 07:19:04 thomas Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-lobj.c,v 1.8 1997/09/07 05:03:34 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -21,207 +21,227 @@ #include "libpq-fe.h" #include "libpq/libpq-fs.h" -#define LO_BUFSIZE 1024 +#define LO_BUFSIZE 1024 -static int lo_initialize(PGconn *conn); +static int lo_initialize(PGconn * conn); /* * lo_open - * opens an existing large object + * opens an existing large object * * returns the file descriptor for use in later lo_* calls * return -1 upon failure. */ int -lo_open(PGconn* conn, Oid lobjId, int mode) +lo_open(PGconn * conn, Oid lobjId, int mode) { - int fd; - int result_len; - PQArgBlock argv[2]; - PGresult *res; - - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = lobjId; - - argv[1].isint = 1; - argv[1].len = 4; - argv[1].u.integer = mode; - - if(conn->lobjfuncs == (PGlobjfuncs *)NULL) { - if(lo_initialize(conn) < 0) { - return -1; - } - } - - res = PQfn(conn, conn->lobjfuncs->fn_lo_open,&fd,&result_len,1,argv,2); - if (PQresultStatus(res) == PGRES_COMMAND_OK) { - PQclear(res); + int fd; + int result_len; + PQArgBlock argv[2]; + PGresult *res; + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = lobjId; + + argv[1].isint = 1; + argv[1].len = 4; + argv[1].u.integer = mode; + + if (conn->lobjfuncs == (PGlobjfuncs *) NULL) + { + if (lo_initialize(conn) < 0) + { + return -1; + } + } + + res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); - /* have to do this to reset offset in shared fd cache */ - /* but only if fd is valid */ - if (fd >= 0 && lo_lseek(conn, fd, 0L, SEEK_SET) < 0) - return -1; - return fd; - } else - return -1; + /* have to do this to reset offset in shared fd cache */ + /* but only if fd is valid */ + if (fd >= 0 && lo_lseek(conn, fd, 0L, SEEK_SET) < 0) + return -1; + return fd; + } + else + return -1; } /* * lo_close - * closes an existing large object + * closes an existing large object * * returns 0 upon success * returns -1 upon failure. */ int -lo_close(PGconn *conn, int fd) +lo_close(PGconn * conn, int fd) { - PQArgBlock argv[1]; - PGresult *res; - int retval; - int result_len; - - if(conn->lobjfuncs == (PGlobjfuncs *)NULL) { - if(lo_initialize(conn) < 0) { - return -1; - } - } - - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; - res = PQfn(conn, conn->lobjfuncs->fn_lo_close, - &retval,&result_len,1,argv,1); - if (PQresultStatus(res) == PGRES_COMMAND_OK) { - PQclear(res); - return retval; - } else - return -1; + PQArgBlock argv[1]; + PGresult *res; + int retval; + int result_len; + + if (conn->lobjfuncs == (PGlobjfuncs *) NULL) + { + if (lo_initialize(conn) < 0) + { + return -1; + } + } + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; + res = PQfn(conn, conn->lobjfuncs->fn_lo_close, + &retval, &result_len, 1, argv, 1); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return retval; + } + else + return -1; } /* * lo_read - * read len bytes of the large object into buf + * read len bytes of the large object into buf * * returns the length of bytes read. * the CALLER must have allocated enough space to hold the result returned */ int -lo_read(PGconn *conn, int fd, char *buf, int len) +lo_read(PGconn * conn, int fd, char *buf, int len) { - PQArgBlock argv[2]; - PGresult *res; - int result_len; - - if(conn->lobjfuncs == (PGlobjfuncs *)NULL) { - if(lo_initialize(conn) < 0) { - return -1; - } - } - - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; - - argv[1].isint = 1; - argv[1].len = 4; - argv[1].u.integer = len; - - res = PQfn(conn, conn->lobjfuncs->fn_lo_read, - (int*)buf,&result_len,0,argv,2); - if (PQresultStatus(res) == PGRES_COMMAND_OK) { - PQclear(res); - return result_len; - } else - return -1; + PQArgBlock argv[2]; + PGresult *res; + int result_len; + + if (conn->lobjfuncs == (PGlobjfuncs *) NULL) + { + if (lo_initialize(conn) < 0) + { + return -1; + } + } + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; + + argv[1].isint = 1; + argv[1].len = 4; + argv[1].u.integer = len; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_read, + (int *) buf, &result_len, 0, argv, 2); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return result_len; + } + else + return -1; } /* * lo_write - * write len bytes of buf into the large object fd + * write len bytes of buf into the large object fd * */ int -lo_write(PGconn *conn, int fd, char *buf, int len) +lo_write(PGconn * conn, int fd, char *buf, int len) { - PQArgBlock argv[2]; - PGresult *res; - int result_len; - int retval; - - if(conn->lobjfuncs == (PGlobjfuncs *)NULL) { - if(lo_initialize(conn) < 0) { - return -1; - } - } - - if (len <= 0) - return 0; + PQArgBlock argv[2]; + PGresult *res; + int result_len; + int retval; + + if (conn->lobjfuncs == (PGlobjfuncs *) NULL) + { + if (lo_initialize(conn) < 0) + { + return -1; + } + } - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; + if (len <= 0) + return 0; - argv[1].isint = 0; - argv[1].len = len; - argv[1].u.ptr = (int*)buf; + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; - res = PQfn(conn, conn->lobjfuncs->fn_lo_write, - &retval,&result_len,1,argv,2); - if (PQresultStatus(res) == PGRES_COMMAND_OK) { - PQclear(res); - return retval; - } else - return -1; + argv[1].isint = 0; + argv[1].len = len; + argv[1].u.ptr = (int *) buf; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_write, + &retval, &result_len, 1, argv, 2); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return retval; + } + else + return -1; } /* * lo_lseek - * change the current read or write location on a large object + * change the current read or write location on a large object * currently, only L_SET is a legal value for whence * */ int -lo_lseek(PGconn *conn, int fd, int offset, int whence) +lo_lseek(PGconn * conn, int fd, int offset, int whence) { - PQArgBlock argv[3]; - PGresult *res; - int retval; - int result_len; - - if(conn->lobjfuncs == (PGlobjfuncs *)NULL) { - if(lo_initialize(conn) < 0) { - return -1; - } - } - - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; - - argv[1].isint = 1; - argv[1].len = 4; - argv[1].u.integer = offset; - - argv[2].isint = 1; - argv[2].len = 4; - argv[2].u.integer = whence; - - res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek, - &retval,&result_len,1,argv,3); - if (PQresultStatus(res) == PGRES_COMMAND_OK) { - PQclear(res); - return retval; - } else - return -1; + PQArgBlock argv[3]; + PGresult *res; + int retval; + int result_len; + + if (conn->lobjfuncs == (PGlobjfuncs *) NULL) + { + if (lo_initialize(conn) < 0) + { + return -1; + } + } + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; + + argv[1].isint = 1; + argv[1].len = 4; + argv[1].u.integer = offset; + + argv[2].isint = 1; + argv[2].len = 4; + argv[2].u.integer = whence; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek, + &retval, &result_len, 1, argv, 3); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return retval; + } + else + return -1; } /* * lo_creat - * create a new large object + * create a new large object * the mode is a bitmask describing different attributes of the new object * * returns the oid of the large object created or @@ -229,209 +249,233 @@ lo_lseek(PGconn *conn, int fd, int offset, int whence) */ Oid -lo_creat(PGconn *conn, int mode) +lo_creat(PGconn * conn, int mode) { - PQArgBlock argv[1]; - PGresult *res; - int retval; - int result_len; - - if(conn->lobjfuncs == (PGlobjfuncs *)NULL) { - if(lo_initialize(conn) < 0) { - return -1; - } - } - - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = mode; - res = PQfn(conn, conn->lobjfuncs->fn_lo_creat, - &retval,&result_len,1,argv,1); - if (PQresultStatus(res) == PGRES_COMMAND_OK) { - PQclear(res); - return (Oid)retval; - } else - return InvalidOid; + PQArgBlock argv[1]; + PGresult *res; + int retval; + int result_len; + + if (conn->lobjfuncs == (PGlobjfuncs *) NULL) + { + if (lo_initialize(conn) < 0) + { + return -1; + } + } + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = mode; + res = PQfn(conn, conn->lobjfuncs->fn_lo_creat, + &retval, &result_len, 1, argv, 1); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return (Oid) retval; + } + else + return InvalidOid; } /* * lo_tell - * returns the current seek location of the large object + * returns the current seek location of the large object * */ int -lo_tell(PGconn *conn, int fd) +lo_tell(PGconn * conn, int fd) { - int retval; - PQArgBlock argv[1]; - PGresult *res; - int result_len; - - if(conn->lobjfuncs == (PGlobjfuncs *)NULL) { - if(lo_initialize(conn) < 0) { - return -1; - } - } - - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; - - res = PQfn(conn, conn->lobjfuncs->fn_lo_tell, - &retval,&result_len,1,argv,1); - if (PQresultStatus(res) == PGRES_COMMAND_OK) { - PQclear(res); - return retval; - } else - return -1; + int retval; + PQArgBlock argv[1]; + PGresult *res; + int result_len; + + if (conn->lobjfuncs == (PGlobjfuncs *) NULL) + { + if (lo_initialize(conn) < 0) + { + return -1; + } + } + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = fd; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_tell, + &retval, &result_len, 1, argv, 1); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return retval; + } + else + return -1; } /* * lo_unlink - * delete a file + * delete a file * */ int -lo_unlink(PGconn *conn, Oid lobjId) +lo_unlink(PGconn * conn, Oid lobjId) { - PQArgBlock argv[1]; - PGresult *res; - int result_len; - int retval; - - if(conn->lobjfuncs == (PGlobjfuncs *)NULL) { - if(lo_initialize(conn) < 0) { - return -1; - } - } - - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = lobjId; - - res = PQfn(conn, conn->lobjfuncs->fn_lo_unlink, - &retval,&result_len,1,argv,1); - if (PQresultStatus(res) == PGRES_COMMAND_OK) { - PQclear(res); - return retval; - } else - return -1; + PQArgBlock argv[1]; + PGresult *res; + int result_len; + int retval; + + if (conn->lobjfuncs == (PGlobjfuncs *) NULL) + { + if (lo_initialize(conn) < 0) + { + return -1; + } + } + + argv[0].isint = 1; + argv[0].len = 4; + argv[0].u.integer = lobjId; + + res = PQfn(conn, conn->lobjfuncs->fn_lo_unlink, + &retval, &result_len, 1, argv, 1); + if (PQresultStatus(res) == PGRES_COMMAND_OK) + { + PQclear(res); + return retval; + } + else + return -1; } /* * lo_import - - * imports a file as an (inversion) large object. - * returns the oid of that object upon success, + * imports a file as an (inversion) large object. + * returns the oid of that object upon success, * returns InvalidOid upon failure * */ Oid -lo_import(PGconn *conn, char* filename) +lo_import(PGconn * conn, char *filename) { - int fd; - int nbytes, tmp; - char buf[LO_BUFSIZE]; - Oid lobjOid; - int lobj; - - /* - * open the file to be read in - */ - fd = open(filename, O_RDONLY, 0666); - if (fd < 0) { /* error */ - sprintf(conn->errorMessage, - "lo_import: can't open unix file\"%s\"\n", filename); - return InvalidOid; - } - - /* - * create an inversion "object" - */ - lobjOid = lo_creat(conn, INV_READ|INV_WRITE); - if (lobjOid == InvalidOid) { - sprintf(conn->errorMessage, - "lo_import: can't create inv object for \"%s\"", filename); - return InvalidOid; - } - - lobj = lo_open(conn, lobjOid, INV_WRITE); - if (lobj == -1) { - sprintf(conn->errorMessage, - "lo_import: could not open inv object oid %d",lobjOid); - return InvalidOid; - } - /* - * read in from the Unix file and write to the inversion file - */ - while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0) { - tmp = lo_write(conn,lobj, buf, nbytes); - if (tmp < nbytes) { - sprintf(conn->errorMessage, - "lo_import: error while reading \"%s\"",filename); - return InvalidOid; - } - } - - (void) close(fd); - (void) lo_close(conn, lobj); - - return lobjOid; + int fd; + int nbytes, + tmp; + char buf[LO_BUFSIZE]; + Oid lobjOid; + int lobj; + + /* + * open the file to be read in + */ + fd = open(filename, O_RDONLY, 0666); + if (fd < 0) + { /* error */ + sprintf(conn->errorMessage, + "lo_import: can't open unix file\"%s\"\n", filename); + return InvalidOid; + } + + /* + * create an inversion "object" + */ + lobjOid = lo_creat(conn, INV_READ | INV_WRITE); + if (lobjOid == InvalidOid) + { + sprintf(conn->errorMessage, + "lo_import: can't create inv object for \"%s\"", filename); + return InvalidOid; + } + + lobj = lo_open(conn, lobjOid, INV_WRITE); + if (lobj == -1) + { + sprintf(conn->errorMessage, + "lo_import: could not open inv object oid %d", lobjOid); + return InvalidOid; + } + + /* + * read in from the Unix file and write to the inversion file + */ + while ((nbytes = read(fd, buf, LO_BUFSIZE)) > 0) + { + tmp = lo_write(conn, lobj, buf, nbytes); + if (tmp < nbytes) + { + sprintf(conn->errorMessage, + "lo_import: error while reading \"%s\"", filename); + return InvalidOid; + } + } + + (void) close(fd); + (void) lo_close(conn, lobj); + + return lobjOid; } /* * lo_export - - * exports an (inversion) large object. + * exports an (inversion) large object. * returns -1 upon failure, 1 otherwise */ int -lo_export(PGconn *conn, Oid lobjId, char *filename) +lo_export(PGconn * conn, Oid lobjId, char *filename) { - int fd; - int nbytes, tmp; - char buf[LO_BUFSIZE]; - int lobj; - - /* - * create an inversion "object" - */ - lobj = lo_open(conn, lobjId, INV_READ); - if (lobj == -1) { - sprintf(conn->errorMessage, - "lo_export: can't open inv object %d",lobjId); - return -1; - } - - /* - * open the file to be written to - */ - fd = open(filename, O_CREAT|O_WRONLY, 0666); - if (fd < 0) { /* error */ - sprintf(conn->errorMessage, - "lo_export: can't open unix file\"%s\"",filename); - return 0; - } + int fd; + int nbytes, + tmp; + char buf[LO_BUFSIZE]; + int lobj; + + /* + * create an inversion "object" + */ + lobj = lo_open(conn, lobjId, INV_READ); + if (lobj == -1) + { + sprintf(conn->errorMessage, + "lo_export: can't open inv object %d", lobjId); + return -1; + } + + /* + * open the file to be written to + */ + fd = open(filename, O_CREAT | O_WRONLY, 0666); + if (fd < 0) + { /* error */ + sprintf(conn->errorMessage, + "lo_export: can't open unix file\"%s\"", filename); + return 0; + } - /* - * read in from the Unix file and write to the inversion file - */ - while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0) { - tmp = write(fd, buf, nbytes); - if (tmp < nbytes) { - sprintf(conn->errorMessage, - "lo_export: error while writing \"%s\"", - filename); - return -1; + /* + * read in from the Unix file and write to the inversion file + */ + while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0) + { + tmp = write(fd, buf, nbytes); + if (tmp < nbytes) + { + sprintf(conn->errorMessage, + "lo_export: error while writing \"%s\"", + filename); + return -1; + } } - } - (void) lo_close(conn,lobj); - (void) close(fd); + (void) lo_close(conn, lobj); + (void) close(fd); - return 1; + return 1; } @@ -443,31 +487,33 @@ lo_export(PGconn *conn, Oid lobjId, char *filename) * functions that are required for large object operations. * ---------------- */ -static int lo_initialize(PGconn *conn) +static int +lo_initialize(PGconn * conn) { - PGresult *res; - PGlobjfuncs *lobjfuncs; - int n; - char *fname; - Oid foid; - - /* ---------------- - * Allocate the structure to hold the functions OID's - * ---------------- - */ - lobjfuncs = (PGlobjfuncs *)malloc(sizeof(PGlobjfuncs)); - if (lobjfuncs == (PGlobjfuncs *)NULL) { - strcpy(conn->errorMessage, - "FATAL: malloc() failed in lo_initialize()\n"); - return -1; - } - memset((char *)lobjfuncs, 0, sizeof(PGlobjfuncs)); - - /* ---------------- - * Execute the query to get all the functions at once - * ---------------- - */ - res = PQexec(conn, "select proname, oid from pg_proc \ + PGresult *res; + PGlobjfuncs *lobjfuncs; + int n; + char *fname; + Oid foid; + + /* ---------------- + * Allocate the structure to hold the functions OID's + * ---------------- + */ + lobjfuncs = (PGlobjfuncs *) malloc(sizeof(PGlobjfuncs)); + if (lobjfuncs == (PGlobjfuncs *) NULL) + { + strcpy(conn->errorMessage, + "FATAL: malloc() failed in lo_initialize()\n"); + return -1; + } + memset((char *) lobjfuncs, 0, sizeof(PGlobjfuncs)); + + /* ---------------- + * Execute the query to get all the functions at once + * ---------------- + */ + res = PQexec(conn, "select proname, oid from pg_proc \ where proname = 'lo_open' \ or proname = 'lo_close' \ or proname = 'lo_creat' \ @@ -476,114 +522,131 @@ static int lo_initialize(PGconn *conn) or proname = 'lo_tell' \ or proname = 'loread' \ or proname = 'lowrite'"); - if (res == (PGresult *)NULL) { - free(lobjfuncs); - return -1; - } + if (res == (PGresult *) NULL) + { + free(lobjfuncs); + return -1; + } + + if (res->resultStatus != PGRES_TUPLES_OK) + { + free(lobjfuncs); + PQclear(res); + strcpy(conn->errorMessage, + "ERROR: SELECT didn't return data in lo_initialize()\n"); + return -1; + } + + /* ---------------- + * Examine the result and put the OID's into the struct + * ---------------- + */ + for (n = 0; n < PQntuples(res); n++) + { + fname = PQgetvalue(res, n, 0); + foid = (Oid) atoi(PQgetvalue(res, n, 1)); + if (!strcmp(fname, "lo_open")) + { + lobjfuncs->fn_lo_open = foid; + } + else if (!strcmp(fname, "lo_close")) + { + lobjfuncs->fn_lo_close = foid; + } + else if (!strcmp(fname, "lo_creat")) + { + lobjfuncs->fn_lo_creat = foid; + } + else if (!strcmp(fname, "lo_unlink")) + { + lobjfuncs->fn_lo_unlink = foid; + } + else if (!strcmp(fname, "lo_lseek")) + { + lobjfuncs->fn_lo_lseek = foid; + } + else if (!strcmp(fname, "lo_tell")) + { + lobjfuncs->fn_lo_tell = foid; + } + else if (!strcmp(fname, "loread")) + { + lobjfuncs->fn_lo_read = foid; + } + else if (!strcmp(fname, "lowrite")) + { + lobjfuncs->fn_lo_write = foid; + } + } - if (res->resultStatus != PGRES_TUPLES_OK) { - free(lobjfuncs); PQclear(res); - strcpy(conn->errorMessage, - "ERROR: SELECT didn't return data in lo_initialize()\n"); - return -1; - } - - /* ---------------- - * Examine the result and put the OID's into the struct - * ---------------- - */ - for(n = 0; n < PQntuples(res); n++) { - fname = PQgetvalue(res, n, 0); - foid = (Oid)atoi(PQgetvalue(res, n, 1)); - if(!strcmp(fname, "lo_open")) { - lobjfuncs->fn_lo_open = foid; - } else - if(!strcmp(fname, "lo_close")) { - lobjfuncs->fn_lo_close = foid; - } else - if(!strcmp(fname, "lo_creat")) { - lobjfuncs->fn_lo_creat = foid; - } else - if(!strcmp(fname, "lo_unlink")) { - lobjfuncs->fn_lo_unlink = foid; - } else - if(!strcmp(fname, "lo_lseek")) { - lobjfuncs->fn_lo_lseek = foid; - } else - if(!strcmp(fname, "lo_tell")) { - lobjfuncs->fn_lo_tell = foid; - } else - if(!strcmp(fname, "loread")) { - lobjfuncs->fn_lo_read = foid; - } else - if(!strcmp(fname, "lowrite")) { - lobjfuncs->fn_lo_write = foid; - } - } - - PQclear(res); - - /* ---------------- - * Finally check that we really got all large object - * interface functions. - * ---------------- - */ - if(lobjfuncs->fn_lo_open == 0) { - strcpy(conn->errorMessage, - "ERROR: Cannot determine OID for function lo_open\n"); - free(lobjfuncs); - return -1; - } - if(lobjfuncs->fn_lo_close == 0) { - strcpy(conn->errorMessage, - "ERROR: Cannot determine OID for function lo_close\n"); - free(lobjfuncs); - return -1; - } - if(lobjfuncs->fn_lo_creat == 0) { - strcpy(conn->errorMessage, - "ERROR: Cannot determine OID for function lo_creat\n"); - free(lobjfuncs); - return -1; - } - if(lobjfuncs->fn_lo_unlink == 0) { - strcpy(conn->errorMessage, - "ERROR: Cannot determine OID for function lo_unlink\n"); - free(lobjfuncs); - return -1; - } - if(lobjfuncs->fn_lo_lseek == 0) { - strcpy(conn->errorMessage, - "ERROR: Cannot determine OID for function lo_lseek\n"); - free(lobjfuncs); - return -1; - } - if(lobjfuncs->fn_lo_tell == 0) { - strcpy(conn->errorMessage, - "ERROR: Cannot determine OID for function lo_tell\n"); - free(lobjfuncs); - return -1; - } - if(lobjfuncs->fn_lo_read == 0) { - strcpy(conn->errorMessage, - "ERROR: Cannot determine OID for function loread\n"); - free(lobjfuncs); - return -1; - } - if(lobjfuncs->fn_lo_write == 0) { - strcpy(conn->errorMessage, - "ERROR: Cannot determine OID for function lowrite\n"); - free(lobjfuncs); - return -1; - } - - /* ---------------- - * Put the structure into the connection control - * ---------------- - */ - conn->lobjfuncs = lobjfuncs; - return 0; -} + /* ---------------- + * Finally check that we really got all large object + * interface functions. + * ---------------- + */ + if (lobjfuncs->fn_lo_open == 0) + { + strcpy(conn->errorMessage, + "ERROR: Cannot determine OID for function lo_open\n"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_close == 0) + { + strcpy(conn->errorMessage, + "ERROR: Cannot determine OID for function lo_close\n"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_creat == 0) + { + strcpy(conn->errorMessage, + "ERROR: Cannot determine OID for function lo_creat\n"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_unlink == 0) + { + strcpy(conn->errorMessage, + "ERROR: Cannot determine OID for function lo_unlink\n"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_lseek == 0) + { + strcpy(conn->errorMessage, + "ERROR: Cannot determine OID for function lo_lseek\n"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_tell == 0) + { + strcpy(conn->errorMessage, + "ERROR: Cannot determine OID for function lo_tell\n"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_read == 0) + { + strcpy(conn->errorMessage, + "ERROR: Cannot determine OID for function loread\n"); + free(lobjfuncs); + return -1; + } + if (lobjfuncs->fn_lo_write == 0) + { + strcpy(conn->errorMessage, + "ERROR: Cannot determine OID for function lowrite\n"); + free(lobjfuncs); + return -1; + } + /* ---------------- + * Put the structure into the connection control + * ---------------- + */ + conn->lobjfuncs = lobjfuncs; + return 0; +} diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c index 62062184ca8..b7e8a1b1c69 100644 --- a/src/interfaces/libpq/fe-misc.c +++ b/src/interfaces/libpq/fe-misc.c @@ -1,17 +1,17 @@ /*------------------------------------------------------------------------- * - * FILE - * fe-misc.c + * FILE + * fe-misc.c * - * DESCRIPTION - * miscellaneous useful functions - * these routines are analogous to the ones in libpq/pqcomm.c + * DESCRIPTION + * miscellaneous useful functions + * these routines are analogous to the ones in libpq/pqcomm.c * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.5 1997/03/16 18:51:29 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.6 1997/09/07 05:03:35 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -29,80 +29,84 @@ if debug is set, also echo the character fetched */ -int pqGetc(FILE* fin, FILE* debug) +int +pqGetc(FILE * fin, FILE * debug) { - int c; + int c; - c = getc(fin); + c = getc(fin); - if (debug && c != EOF) - fprintf(debug, "From backend> %c\n", c); - - return c; + if (debug && c != EOF) + fprintf(debug, "From backend> %c\n", c); + + return c; } /* --------------------------------------------------------------------- */ /* pqPutnchar: - send a string of exactly len length into stream f + send a string of exactly len length into stream f returns 1 if there was an error, 0 otherwise. */ -int pqPutnchar(const char* s, int len, FILE *f, FILE *debug) +int +pqPutnchar(const char *s, int len, FILE * f, FILE * debug) { - if (f == NULL) - return 1; + if (f == NULL) + return 1; - if(debug) - fprintf(debug, "To backend> %s\n", s); + if (debug) + fprintf(debug, "To backend> %s\n", s); - if(fwrite(s, 1, len, f) != len) - return 1; + if (fwrite(s, 1, len, f) != len) + return 1; - return 0; + return 0; } /* --------------------------------------------------------------------- */ /* pqGetnchar: - get a string of exactly len length from stream f + get a string of exactly len length from stream f */ -int pqGetnchar(char* s, int len, FILE *f, FILE *debug) +int +pqGetnchar(char *s, int len, FILE * f, FILE * debug) { - int cnt; + int cnt; + + if (f == NULL) + return 1; - if (f == NULL) - return 1; - - cnt = fread(s, 1, len, f); - s[cnt] = '\0'; - /* mjl: actually needs up to len+1 bytes, is this okay? XXX */ + cnt = fread(s, 1, len, f); + s[cnt] = '\0'; + /* mjl: actually needs up to len+1 bytes, is this okay? XXX */ - if (debug) - fprintf(debug, "From backend (%d)> %s\n", len, s); + if (debug) + fprintf(debug, "From backend (%d)> %s\n", len, s); - return 0; + return 0; } /* --------------------------------------------------------------------- */ /* pqGets: get a string of up to length len from stream f */ -int pqGets(char* s, int len, FILE *f, FILE *debug) +int +pqGets(char *s, int len, FILE * f, FILE * debug) { - int c; - const char *str = s; + int c; + const char *str = s; + + if (f == NULL) + return 1; - if (f == NULL) - return 1; - - while (len-- && (c = getc(f)) != EOF && c) - *s++ = c; - *s = '\0'; - /* mjl: actually needs up to len+1 bytes, is this okay? XXX */ + while (len-- && (c = getc(f)) != EOF && c) + *s++ = c; + *s = '\0'; + /* mjl: actually needs up to len+1 bytes, is this okay? XXX */ - if (debug) - fprintf(debug, "From backend> \"%s\"\n", str); + if (debug) + fprintf(debug, "From backend> \"%s\"\n", str); - return 0; + return 0; } /* --------------------------------------------------------------------- */ @@ -111,84 +115,91 @@ int pqGets(char* s, int len, FILE *f, FILE *debug) for host endianness. returns 0 if successful, 1 otherwise */ -int pqPutInt(const int integer, int bytes, FILE* f, FILE *debug) +int +pqPutInt(const int integer, int bytes, FILE * f, FILE * debug) { - int retval = 0; - - switch(bytes) - { - case 2: - retval = pqPutShort(integer, f); - break; - case 4: - retval = pqPutLong(integer, f); - break; - default: - fprintf(stderr, "** int size %d not supported\n", bytes); - retval = 1; - } - - if (debug) fprintf(debug, "To backend (%d#)> %d\n", bytes, integer); - - return retval; + int retval = 0; + + switch (bytes) + { + case 2: + retval = pqPutShort(integer, f); + break; + case 4: + retval = pqPutLong(integer, f); + break; + default: + fprintf(stderr, "** int size %d not supported\n", bytes); + retval = 1; + } + + if (debug) + fprintf(debug, "To backend (%d#)> %d\n", bytes, integer); + + return retval; } /* --------------------------------------------------------------------- */ -/* pgGetInt +/* pgGetInt read a 2 or 4 byte integer from the stream and swab it around to compensate for different endianness - returns 0 if successful + returns 0 if successful */ -int pqGetInt(int* result, int bytes, FILE* f, FILE *debug) +int +pqGetInt(int *result, int bytes, FILE * f, FILE * debug) { - int retval = 0; - - switch(bytes) - { - case 2: - retval = pqGetShort(result, f); - break; - case 4: - retval = pqGetLong(result, f); - break; - default: - fprintf(stderr, "** int size %d not supported\n", bytes); - retval = 1; - } - - if (debug) - fprintf(debug,"From backend (#%d)> %d\n", bytes, *result); - - return retval; + int retval = 0; + + switch (bytes) + { + case 2: + retval = pqGetShort(result, f); + break; + case 4: + retval = pqGetLong(result, f); + break; + default: + fprintf(stderr, "** int size %d not supported\n", bytes); + retval = 1; + } + + if (debug) + fprintf(debug, "From backend (#%d)> %d\n", bytes, *result); + + return retval; } /* --------------------------------------------------------------------- */ -int pqPuts(const char* s, FILE *f, FILE *debug) +int +pqPuts(const char *s, FILE * f, FILE * debug) { - if (f == NULL) - return 1; - - if (fputs(s, f) == EOF) - return 1; - - fputc('\0', f); /* important to send an ending \0 since backend expects it */ - fflush(f); - - if (debug) { - fprintf(debug, "To backend> %s\n", s); - } - - return 0; + if (f == NULL) + return 1; + + if (fputs(s, f) == EOF) + return 1; + + fputc('\0', f); /* important to send an ending \0 since + * backend expects it */ + fflush(f); + + if (debug) + { + fprintf(debug, "To backend> %s\n", s); + } + + return 0; } /* --------------------------------------------------------------------- */ -void pqFlush(FILE *f, FILE *debug) +void +pqFlush(FILE * f, FILE * debug) { - if (f) - fflush(f); + if (f) + fflush(f); - if (debug) - fflush(debug); + if (debug) + fflush(debug); } /* --------------------------------------------------------------------- */ diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h index fdd29fe42d2..3013d5a2bfc 100644 --- a/src/interfaces/libpq/libpq-fe.h +++ b/src/interfaces/libpq/libpq-fe.h @@ -1,12 +1,12 @@ /*------------------------------------------------------------------------- * * libpq-fe.h-- - * This file contains definitions for structures and - * externs for functions used by frontend postgres applications. + * This file contains definitions for structures and + * externs for functions used by frontend postgres applications. * * Copyright (c) 1994, Regents of the University of California * - * $Id: libpq-fe.h,v 1.20 1997/08/27 09:05:24 vadim Exp $ + * $Id: libpq-fe.h,v 1.21 1997/09/07 05:03:36 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -15,41 +15,47 @@ #define LIBPQ_FE_H #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #include <stdio.h> /* ---------------- - * include stuff common to fe and be + * include stuff common to fe and be * ---------------- */ #include "postgres_ext.h" #include "libpq/pqcomm.h" #include "lib/dllist.h" -typedef enum {CONNECTION_OK, - CONNECTION_BAD} ConnStatusType; - -typedef enum { - PGRES_EMPTY_QUERY = 0, - PGRES_COMMAND_OK, /* a query command that doesn't return */ - /* anything was executed properly by the backend */ - PGRES_TUPLES_OK, /* a query command that returns tuples */ - /* was executed properly by the backend, PGresult */ - /* contains the resulttuples */ - PGRES_COPY_OUT, - PGRES_COPY_IN, - PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from the backend */ - PGRES_NONFATAL_ERROR, - PGRES_FATAL_ERROR - -} ExecStatusType; + typedef enum + { + CONNECTION_OK, + CONNECTION_BAD + } ConnStatusType; + + typedef enum + { + PGRES_EMPTY_QUERY = 0, + PGRES_COMMAND_OK, /* a query command that doesn't return */ + /* anything was executed properly by the backend */ + PGRES_TUPLES_OK, /* a query command that returns tuples */ + /* was executed properly by the backend, PGresult */ + /* contains the resulttuples */ + PGRES_COPY_OUT, + PGRES_COPY_IN, + PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from + * the backend */ + PGRES_NONFATAL_ERROR, + PGRES_FATAL_ERROR + + } ExecStatusType; /* string descriptions of the ExecStatusTypes */ -extern const char* pgresStatus[]; + extern const char *pgresStatus[]; -/* - * POSTGRES backend dependent Constants. +/* + * POSTGRES backend dependent Constants. */ /* ERROR_MSG_LENGTH should really be the same as ELOG_MAXLEN in utils/elog.h*/ @@ -60,236 +66,273 @@ extern const char* pgresStatus[]; /* ---------------- * PQArgBlock -- - * Information (pointer to array of this structure) required - * for the PQfn() call. + * Information (pointer to array of this structure) required + * for the PQfn() call. * ---------------- */ -typedef struct { - int len; - int isint; - union { - int *ptr; /* can't use void (dec compiler barfs) */ - int integer; - } u; -} PQArgBlock; - -typedef struct pgresAttDesc { - char* name; /* type name */ - Oid adtid; /* type id */ - short adtsize; /* type size */ -} PGresAttDesc; + typedef struct + { + int len; + int isint; + union + { + int *ptr;/* can't use void (dec compiler barfs) */ + int integer; + } u; + } PQArgBlock; + + typedef struct pgresAttDesc + { + char *name; /* type name */ + Oid adtid; /* type id */ + short adtsize;/* type size */ + } PGresAttDesc; /* use char* for Attribute values, ASCII tuples are guaranteed to be null-terminated For binary tuples, the first four bytes of the value is the size, - and the bytes afterwards are the value. The binary value is + and the bytes afterwards are the value. The binary value is not guaranteed to be null-terminated. In fact, it can have embedded nulls*/ -#define NULL_LEN (-1) /* pg_result len for NULL value */ - -typedef struct pgresAttValue { - int len; /* length in bytes of the value */ - char *value; /* actual value */ -} PGresAttValue; - -typedef struct pgNotify { - char relname[NAMEDATALEN]; /* name of relation containing data */ - int be_pid; /* process id of backend */ -} PGnotify; - -typedef struct pgLobjfuncs { - Oid fn_lo_open; /* OID of backend function lo_open */ - Oid fn_lo_close; /* OID of backend function lo_close */ - Oid fn_lo_creat; /* OID of backend function lo_creat */ - Oid fn_lo_unlink; /* OID of backend function lo_unlink */ - Oid fn_lo_lseek; /* OID of backend function lo_lseek */ - Oid fn_lo_tell; /* OID of backend function lo_tell */ - Oid fn_lo_read; /* OID of backend function LOread */ - Oid fn_lo_write; /* OID of backend function LOwrite */ -} PGlobjfuncs; +#define NULL_LEN (-1) /* pg_result len for NULL value */ + + typedef struct pgresAttValue + { + int len; /* length in bytes of the value */ + char *value; /* actual value */ + } PGresAttValue; + + typedef struct pgNotify + { + char relname[NAMEDATALEN]; /* name of relation + * containing data */ + int be_pid; /* process id of backend */ + } PGnotify; + + typedef struct pgLobjfuncs + { + Oid fn_lo_open; /* OID of backend function lo_open */ + Oid fn_lo_close; /* OID of backend function + * lo_close */ + Oid fn_lo_creat; /* OID of backend function + * lo_creat */ + Oid fn_lo_unlink; /* OID of backend function + * lo_unlink */ + Oid fn_lo_lseek; /* OID of backend function + * lo_lseek */ + Oid fn_lo_tell; /* OID of backend function lo_tell */ + Oid fn_lo_read; /* OID of backend function LOread */ + Oid fn_lo_write; /* OID of backend function LOwrite */ + } PGlobjfuncs; /* PGconn encapsulates a connection to the backend */ -typedef struct pg_conn{ - char *pghost; /* the machine on which the server is running */ - char *pgtty; /* tty on which the backend messages is displayed */ - char *pgport; /* the communication port with the backend */ - char *pgoptions; /* options to start the backend with */ - char *dbName; /* database name */ - ConnStatusType status; - char errorMessage[ERROR_MSG_LENGTH]; - /* pipes for be/fe communication */ - FILE *Pfin; - FILE *Pfout; - FILE *Pfdebug; - void *port; /* really a Port* */ - int asyncNotifyWaiting; - Dllist* notifyList; - char *pguser; /* Postgres username of user who is connected */ - char *pgpass; - char *pgauth; - PGlobjfuncs *lobjfuncs; /* Backend function OID's for large object access */ -} PGconn; + typedef struct pg_conn + { + char *pghost; /* the machine on which the server is + * running */ + char *pgtty; /* tty on which the backend messages is + * displayed */ + char *pgport; /* the communication port with the backend */ + char *pgoptions; /* options to start the backend + * with */ + char *dbName; /* database name */ + ConnStatusType status; + char errorMessage[ERROR_MSG_LENGTH]; + /* pipes for be/fe communication */ + FILE *Pfin; + FILE *Pfout; + FILE *Pfdebug; + void *port; /* really a Port* */ + int asyncNotifyWaiting; + Dllist *notifyList; + char *pguser; /* Postgres username of user who is + * connected */ + char *pgpass; + char *pgauth; + PGlobjfuncs *lobjfuncs; /* Backend function OID's for + * large object access */ + } PGconn; #define CMDSTATUS_LEN 40 /* PGresult encapsulates the result of a query */ /* unlike the old libpq, we assume that queries only return in one group */ -typedef struct pg_result{ - int ntups; - int numAttributes; - PGresAttDesc *attDescs; - PGresAttValue* *tuples; /* each PGresTuple is an array of PGresAttValue's */ - int tupArrSize; /* size of tuples array allocated */ - ExecStatusType resultStatus; - char cmdStatus[CMDSTATUS_LEN]; /* cmd status from the last insert query*/ - int binary; /* binary tuple values if binary == 1, otherwise ASCII */ - PGconn* conn; -} PGresult; - -typedef char pqbool; - /* We can't use the conventional "bool", because we are designed to be - included in a user's program, and user may already have that type - defined. Pqbool, on the other hand, is unlikely to be used. - */ - -struct _PQprintOpt { - pqbool header; /* print output field headings and row count */ - pqbool align; /* fill align the fields */ - pqbool standard; /* old brain dead format */ - pqbool html3; /* output html tables */ - pqbool expanded; /* expand tables */ - pqbool pager; /* use pager for output if needed */ - char *fieldSep; /* field separator */ - char *tableOpt; /* insert to HTML <table ...> */ - char *caption; /* HTML <caption> */ - char **fieldName; /* null terminated array of repalcement field names */ -}; - -typedef struct _PQprintOpt PQprintOpt; + typedef struct pg_result + { + int ntups; + int numAttributes; + PGresAttDesc *attDescs; + PGresAttValue **tuples;/* each PGresTuple is an array of + * PGresAttValue's */ + int tupArrSize; /* size of tuples array allocated */ + ExecStatusType resultStatus; + char cmdStatus[CMDSTATUS_LEN]; /* cmd status from the + * last insert query */ + int binary; /* binary tuple values if binary == 1, + * otherwise ASCII */ + PGconn *conn; + } PGresult; + + typedef char pqbool; + + /* + * We can't use the conventional "bool", because we are designed to be + * included in a user's program, and user may already have that type + * defined. Pqbool, on the other hand, is unlikely to be used. + */ + + struct _PQprintOpt + { + pqbool header; /* print output field headings and row + * count */ + pqbool align; /* fill align the fields */ + pqbool standard; /* old brain dead format */ + pqbool html3; /* output html tables */ + pqbool expanded; /* expand tables */ + pqbool pager; /* use pager for output if needed */ + char *fieldSep; /* field separator */ + char *tableOpt; /* insert to HTML <table ...> */ + char *caption;/* HTML <caption> */ + char **fieldName; /* null terminated array of + * repalcement field names */ + }; + + typedef struct _PQprintOpt PQprintOpt; /* ---------------- * Structure for the conninfo parameter definitions of PQconnectdb() * ---------------- */ -struct _PQconninfoOption { - char *keyword; /* The keyword of the option */ - char *environ; /* Fallback environment variable name */ - char *compiled; /* Fallback compiled in default value */ - char *val; /* Options value */ - char *label; /* Label for field in connect dialog */ - char *dispchar; /* Character to display for this field */ - /* in a connect dialog. Values are: */ - /* "" Display entered value as is */ - /* "*" Password field - hide value */ - /* "D" Debug options - don't */ - /* create a field by default */ - int dispsize; /* Field size in characters for dialog */ -}; - -typedef struct _PQconninfoOption PQconninfoOption; - -/* === in fe-connect.c === */ - /* make a new client connection to the backend */ -extern PGconn* PQconnectdb(const char* conninfo); -extern PQconninfoOption *PQconndefaults(void); -extern PGconn* PQsetdb(const char* pghost, const char* pgport, const char* pgoptions, - const char* pgtty, const char* dbName); - /* close the current connection and free the PGconn data structure */ -extern void PQfinish(PGconn* conn); - /* close the current connection and restablish a new one with the same - parameters */ -extern void PQreset(PGconn* conn); - -extern char* PQdb(PGconn* conn); -extern char* PQuser(PGconn* conn); -extern char* PQhost(PGconn* conn); -extern char* PQoptions(PGconn* conn); -extern char* PQport(PGconn* conn); -extern char* PQtty(PGconn* conn); -extern ConnStatusType PQstatus(PGconn* conn); -extern char* PQerrorMessage(PGconn* conn); -extern void PQtrace(PGconn *conn, FILE* debug_port); -extern void PQuntrace(PGconn *conn); + struct _PQconninfoOption + { + char *keyword;/* The keyword of the option */ + char *environ;/* Fallback environment variable name */ + char *compiled; /* Fallback compiled in default + * value */ + char *val; /* Options value */ + char *label; /* Label for field in connect dialog */ + char *dispchar; /* Character to display for this + * field */ + /* in a connect dialog. Values are: */ + /* "" Display entered value as is */ + /* "*" Password field - hide value */ + /* "D" Debug options - don't */ + /* create a field by default */ + int dispsize; /* Field size in characters for + * dialog */ + }; + + typedef struct _PQconninfoOption PQconninfoOption; + +/* === in fe-connect.c === */ + /* make a new client connection to the backend */ + extern PGconn *PQconnectdb(const char *conninfo); + extern PQconninfoOption *PQconndefaults(void); + extern PGconn *PQsetdb(const char *pghost, const char *pgport, const char *pgoptions, + const char *pgtty, const char *dbName); + /* close the current connection and free the PGconn data structure */ + extern void PQfinish(PGconn * conn); + + /* + * close the current connection and restablish a new one with the same + * parameters + */ + extern void PQreset(PGconn * conn); + + extern char *PQdb(PGconn * conn); + extern char *PQuser(PGconn * conn); + extern char *PQhost(PGconn * conn); + extern char *PQoptions(PGconn * conn); + extern char *PQport(PGconn * conn); + extern char *PQtty(PGconn * conn); + extern ConnStatusType PQstatus(PGconn * conn); + extern char *PQerrorMessage(PGconn * conn); + extern void PQtrace(PGconn * conn, FILE * debug_port); + extern void PQuntrace(PGconn * conn); /* === in fe-exec.c === */ -extern PGresult* PQexec(PGconn* conn, const char* query); -extern int PQgetline(PGconn *conn, char* string, int length); -extern int PQendcopy(PGconn *conn); -extern void PQputline(PGconn *conn, const char* string); -extern ExecStatusType PQresultStatus(PGresult* res); -extern int PQntuples(PGresult *res); -extern int PQnfields(PGresult *res); -extern char* PQfname(PGresult *res, int field_num); -extern int PQfnumber(PGresult *res, const char* field_name); -extern Oid PQftype(PGresult *res, int field_num); -extern short PQfsize(PGresult *res, int field_num); -extern char* PQcmdStatus(PGresult *res); -extern const char* PQoidStatus(PGresult *res); -extern const char* PQcmdTuples(PGresult *res); -extern char* PQgetvalue(PGresult *res, int tup_num, int field_num); -extern int PQgetlength(PGresult *res, int tup_num, int field_num); -extern int PQgetisnull(PGresult *res, int tup_num, int field_num); -extern void PQclear(PGresult* res); + extern PGresult *PQexec(PGconn * conn, const char *query); + extern int PQgetline(PGconn * conn, char *string, int length); + extern int PQendcopy(PGconn * conn); + extern void PQputline(PGconn * conn, const char *string); + extern ExecStatusType PQresultStatus(PGresult * res); + extern int PQntuples(PGresult * res); + extern int PQnfields(PGresult * res); + extern char *PQfname(PGresult * res, int field_num); + extern int PQfnumber(PGresult * res, const char *field_name); + extern Oid PQftype(PGresult * res, int field_num); + extern short PQfsize(PGresult * res, int field_num); + extern char *PQcmdStatus(PGresult * res); + extern const char *PQoidStatus(PGresult * res); + extern const char *PQcmdTuples(PGresult * res); + extern char *PQgetvalue(PGresult * res, int tup_num, int field_num); + extern int PQgetlength(PGresult * res, int tup_num, int field_num); + extern int PQgetisnull(PGresult * res, int tup_num, int field_num); + extern void PQclear(PGresult * res); /* PQdisplayTuples() is a better version of PQprintTuples() */ -extern void PQdisplayTuples(PGresult *res, - FILE *fp, /* where to send the output */ - int fillAlign, /* pad the fields with spaces */ - const char *fieldSep, /* field separator */ - int printHeader, /* display headers? */ - int quiet); -extern void PQprintTuples(PGresult* res, - FILE* fout, /* output stream */ - int printAttName,/* print attribute names or not*/ - int terseOutput, /* delimiter bars or not?*/ - int width /* width of column, - if 0, use variable width */ - ); -extern void PQprint(FILE* fout, /* output stream */ - PGresult* res, - PQprintOpt *ps /* option structure */ - ); -extern PGnotify* PQnotifies(PGconn *conn); -extern PGresult* PQfn(PGconn* conn, - int fnid, - int *result_buf, - int *result_len, - int result_is_int, - PQArgBlock *args, - int nargs); + extern void PQdisplayTuples(PGresult * res, + FILE * fp, /* where to send the + * output */ + int fillAlign, /* pad the fields with + * spaces */ + const char *fieldSep, /* field separator */ + int printHeader, /* display headers? */ + int quiet); + extern void PQprintTuples(PGresult * res, + FILE * fout, /* output stream */ + int printAttName, /* print attribute names + * or not */ + int terseOutput, /* delimiter bars or + * not? */ + int width /* width of column, if + * 0, use variable width */ + ); + extern void PQprint(FILE * fout, /* output stream */ + PGresult * res, + PQprintOpt * ps /* option structure */ + ); + extern PGnotify *PQnotifies(PGconn * conn); + extern PGresult *PQfn(PGconn * conn, + int fnid, + int *result_buf, + int *result_len, + int result_is_int, + PQArgBlock * args, + int nargs); /* === in fe-auth.c === */ -extern MsgType fe_getauthsvc(char* PQerrormsg); -extern void fe_setauthsvc(const char *name, char* PQerrormsg); -extern char *fe_getauthname(char* PQerrormsg); + extern MsgType fe_getauthsvc(char *PQerrormsg); + extern void fe_setauthsvc(const char *name, char *PQerrormsg); + extern char *fe_getauthname(char *PQerrormsg); /* === in fe-misc.c === */ /* pqGets and pqPuts gets and sends strings to the file stream - returns 0 if successful - if debug is non-null, debugging output is sent to that stream + returns 0 if successful + if debug is non-null, debugging output is sent to that stream */ -extern int pqGets(char* s, int maxlen, FILE* stream, FILE* debug); -extern int pqGetnchar(char* s, int maxlen, FILE* stream, FILE* debug); -extern int pqPutnchar(const char* s, int maxlen, FILE* stream, FILE* debug); -extern int pqPuts(const char* s, FILE* stream, FILE* debug ); -extern int pqGetc(FILE* stream, FILE *debug); + extern int pqGets(char *s, int maxlen, FILE * stream, FILE * debug); + extern int pqGetnchar(char *s, int maxlen, FILE * stream, FILE * debug); + extern int pqPutnchar(const char *s, int maxlen, FILE * stream, FILE * debug); + extern int pqPuts(const char *s, FILE * stream, FILE * debug); + extern int pqGetc(FILE * stream, FILE * debug); /* get a n-byte integer from the stream into result */ /* returns 0 if successful */ -extern int pqGetInt(int* result, int bytes, FILE* stream, FILE *debug ); + extern int pqGetInt(int *result, int bytes, FILE * stream, FILE * debug); /* put a n-byte integer into the stream */ /* returns 0 if successful */ -extern int pqPutInt(const int n, int bytes, FILE* stream, FILE *debug ); -extern void pqFlush(FILE* stream, FILE* debug); + extern int pqPutInt(const int n, int bytes, FILE * stream, FILE * debug); + extern void pqFlush(FILE * stream, FILE * debug); /* === in fe-lobj.c === */ -int lo_open(PGconn* conn, Oid lobjId, int mode); -int lo_close(PGconn *conn, int fd); -int lo_read(PGconn *conn, int fd, char *buf, int len); -int lo_write(PGconn *conn, int fd, char *buf, int len); -int lo_lseek(PGconn *conn, int fd, int offset, int whence); -Oid lo_creat(PGconn *conn, int mode); -int lo_tell(PGconn *conn, int fd); -int lo_unlink(PGconn *conn, Oid lobjId); -Oid lo_import(PGconn *conn, char *filename); -int lo_export(PGconn *conn, Oid lobjId, char *filename); + int lo_open(PGconn * conn, Oid lobjId, int mode); + int lo_close(PGconn * conn, int fd); + int lo_read(PGconn * conn, int fd, char *buf, int len); + int lo_write(PGconn * conn, int fd, char *buf, int len); + int lo_lseek(PGconn * conn, int fd, int offset, int whence); + Oid lo_creat(PGconn * conn, int mode); + int lo_tell(PGconn * conn, int fd); + int lo_unlink(PGconn * conn, Oid lobjId); + Oid lo_import(PGconn * conn, char *filename); + int lo_export(PGconn * conn, Oid lobjId, char *filename); /* max length of message to send */ #define MAX_MESSAGE_LEN 8193 @@ -299,25 +342,25 @@ int lo_export(PGconn *conn, Oid lobjId, char *filename); /* fall back options if they are not specified by arguments or defined by environment variables */ -#define DefaultHost "localhost" -#define DefaultTty "" +#define DefaultHost "localhost" +#define DefaultTty "" #define DefaultOption "" -#define DefaultAuthtype "" -#define DefaultPassword "" +#define DefaultAuthtype "" +#define DefaultPassword "" -typedef void *TUPLE; + typedef void *TUPLE; #define palloc malloc #define pfree free #if defined(sunos4) -extern char *sys_errlist[]; + extern char *sys_errlist[]; #define strerror(A) (sys_errlist[(A)]) -#endif /* sunos4 */ +#endif /* sunos4 */ #ifdef __cplusplus }; -#endif -#endif /* LIBPQ_FE_H */ +#endif +#endif /* LIBPQ_FE_H */ diff --git a/src/interfaces/libpq/pqsignal.c b/src/interfaces/libpq/pqsignal.c index a177012051a..c004704ba45 100644 --- a/src/interfaces/libpq/pqsignal.c +++ b/src/interfaces/libpq/pqsignal.c @@ -1,18 +1,18 @@ /*------------------------------------------------------------------------- * * pqsignal.c-- - * reliable BSD-style signal(2) routine stolen from RWW who stole it - * from Stevens... + * reliable BSD-style signal(2) routine stolen from RWW who stole it + * from Stevens... * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqsignal.c,v 1.3 1996/12/26 22:08:30 momjian Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/libpq/pqsignal.c,v 1.4 1997/09/07 05:03:37 momjian Exp $ * * NOTES - * This shouldn't be in libpq, but the monitor and some other - * things need it... + * This shouldn't be in libpq, but the monitor and some other + * things need it... * *------------------------------------------------------------------------- */ @@ -26,18 +26,20 @@ pqsigfunc pqsignal(int signo, pqsigfunc func) { #if !defined(USE_POSIX_SIGNALS) - return signal(signo, func); + return signal(signo, func); #else - struct sigaction act, oact; - - act.sa_handler = func; - sigemptyset(&act.sa_mask); - act.sa_flags = 0; - if (signo != SIGALRM) { - act.sa_flags |= SA_RESTART; - } - if (sigaction(signo, &act, &oact) < 0) - return(SIG_ERR); - return(oact.sa_handler); -#endif /* !USE_POSIX_SIGNALS */ + struct sigaction act, + oact; + + act.sa_handler = func; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + if (signo != SIGALRM) + { + act.sa_flags |= SA_RESTART; + } + if (sigaction(signo, &act, &oact) < 0) + return (SIG_ERR); + return (oact.sa_handler); +#endif /* !USE_POSIX_SIGNALS */ } diff --git a/src/interfaces/libpq/pqsignal.h b/src/interfaces/libpq/pqsignal.h index 4d57549443f..e2f6d7a973b 100644 --- a/src/interfaces/libpq/pqsignal.h +++ b/src/interfaces/libpq/pqsignal.h @@ -1,16 +1,16 @@ /*------------------------------------------------------------------------- * * pqsignal.h-- - * prototypes for the reliable BSD-style signal(2) routine. + * prototypes for the reliable BSD-style signal(2) routine. * * * Copyright (c) 1994, Regents of the University of California * - * $Id: pqsignal.h,v 1.2 1996/12/26 22:08:34 momjian Exp $ + * $Id: pqsignal.h,v 1.3 1997/09/07 05:03:39 momjian Exp $ * * NOTES - * This shouldn't be in libpq, but the monitor and some other - * things need it... + * This shouldn't be in libpq, but the monitor and some other + * things need it... * *------------------------------------------------------------------------- */ @@ -19,8 +19,8 @@ #include "c.h" -typedef void (*pqsigfunc)(int); +typedef void (*pqsigfunc) (int); extern pqsigfunc pqsignal(int signo, pqsigfunc func); -#endif /* PQSIGNAL_H */ +#endif /* PQSIGNAL_H */ |