From be5bfd54f213f0618ae51113da64d28793904301 Mon Sep 17 00:00:00 2001
From: "Marc G. Fournier" <scrappy@hub.org>
Date: Tue, 23 Jul 1996 03:03:43 +0000
Subject: [PATCH] Put in a new FAQ

Merged in Dr. George's src/bin tree (possibly broke monitor/psql in process)
---
 src/bin/Makefile               |  19 +-
 src/bin/initdb/initdb.sh       |  14 +-
 src/bin/monitor/monitor.c      |   4 +-
 src/bin/pg4_dump/common.c      |   2 +-
 src/bin/pg4_dump/pg4_dump.c    |   2 +-
 src/bin/pgtclsh/Makefile       |   6 +-
 src/bin/pgtclsh/pgtclAppInit.c |   5 +
 src/bin/pgtclsh/pgtkAppInit.c  |   5 +
 src/bin/psql/psql.c            | 854 ++++++++++++++-------------------
 9 files changed, 386 insertions(+), 525 deletions(-)

diff --git a/src/bin/Makefile b/src/bin/Makefile
index 67ed0b86ad3..d3cfd5a3abc 100644
--- a/src/bin/Makefile
+++ b/src/bin/Makefile
@@ -7,24 +7,29 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/bin/Makefile,v 1.1.1.1 1996/07/09 06:22:11 scrappy Exp $
+#    $Header: /cvsroot/pgsql/src/bin/Makefile,v 1.2 1996/07/23 03:01:58 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
+MKDIR=../mk
+-include $(MKDIR)/../Makefile.global
+
 #
 # C programs
 #
 SUBDIR=  monitor pg_id pg_version psql pg_dump
 
-ifeq ($(USE_TCL), true)
-SUBDIR += pgtclsh
-endif
-
 #
 # Shell scripts
-#
+# 
 SUBDIR+= cleardbdir createdb createuser destroydb destroyuser initdb 
 
+#
+# TCL/TK programs
+#
+ifeq ($(USE_TCL), true)
+SUBDIR += pgtclsh
+endif
 
-include ../mk/postgres.subdir.mk
+include $(MKDIR)/postgres.subdir.mk
 
diff --git a/src/bin/initdb/initdb.sh b/src/bin/initdb/initdb.sh
index 4c15592608a..dfdcc608626 100644
--- a/src/bin/initdb/initdb.sh
+++ b/src/bin/initdb/initdb.sh
@@ -12,7 +12,7 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.3 1996/07/20 07:33:36 scrappy Exp $
+#    $Header: /cvsroot/pgsql/src/bin/initdb/Attic/initdb.sh,v 1.4 1996/07/23 03:03:19 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -33,10 +33,6 @@ FILESDIR=$PGDATA/files
 PATH=$BINDIR:$PATH
 export PATH
 
-# OPENLINK Added an fsync option to postmaster
-# REQUIRES: pg95 compiled with -DOPENLINK_PATCHES, see README_OPENLINK
-# FSYNC=-F
-
 CMDNAME=`basename $0`
 
 # ----------------
@@ -63,9 +59,9 @@ done
 # ----------------
 if test "$debug" -eq 1
 then
-    BACKENDARGS="-boot -C $FSYNC -d"
+    BACKENDARGS="-boot -C -F -d"
 else
-    BACKENDARGS="-boot -C $FSYNC -Q"
+    BACKENDARGS="-boot -C -F -Q"
 fi
 
 
@@ -220,9 +216,7 @@ then
     echo "vacuuming template1"
 fi
 
-    echo "vacuum" | postgres $FSYNC -Q template1 > /dev/null
+    echo "vacuum" | postgres -F -Q template1 > /dev/null
 fi
 
 rm -f /tmp/create.$$
-
-sync
diff --git a/src/bin/monitor/monitor.c b/src/bin/monitor/monitor.c
index 21812898d9d..7770b00ddc7 100644
--- a/src/bin/monitor/monitor.c
+++ b/src/bin/monitor/monitor.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/bin/monitor/Attic/monitor.c,v 1.4 1996/07/23 02:26:41 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/bin/monitor/Attic/monitor.c,v 1.5 1996/07/23 03:03:24 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,7 +20,7 @@
 #ifndef WIN32
 #include <unistd.h>
 #endif
-#ifdef PORTNAME_sparc_solaris
+#if defined(PORTNAME_sparc_solaris) || defined(PORTNAME_i386_solaris)
 #include <netdb.h>	/* for MAXHOSTNAMELEN on some */
 #endif
 #include <sys/types.h>
diff --git a/src/bin/pg4_dump/common.c b/src/bin/pg4_dump/common.c
index f485c152c67..da66dc69291 100644
--- a/src/bin/pg4_dump/common.c
+++ b/src/bin/pg4_dump/common.c
@@ -16,7 +16,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/param.h>	/* for MAXHOSTNAMELEN on most */
-#ifdef PORTNAME_sparc_solaris
+#if defined(PORTNAME_sparc_solaris) || defined(PORTNAME_i386_solaris)
 #include <netdb.h>	/* for MAXHOSTNAMELEN on some */
 #endif
 
diff --git a/src/bin/pg4_dump/pg4_dump.c b/src/bin/pg4_dump/pg4_dump.c
index 6e6ee6fa573..a7f54004dc1 100644
--- a/src/bin/pg4_dump/pg4_dump.c
+++ b/src/bin/pg4_dump/pg4_dump.c
@@ -28,7 +28,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/param.h>	/* for MAXHOSTNAMELEN on most */
-#ifdef PORTNAME_sparc_solaris
+#if defined(PORTNAME_sparc_solaris) || defined(PORTNAME_i386_solaris)
 #include <netdb.h>	/* for MAXHOSTNAMELEN on some */
 #endif
 
diff --git a/src/bin/pgtclsh/Makefile b/src/bin/pgtclsh/Makefile
index a99ab39f082..0e80d3b8317 100644
--- a/src/bin/pgtclsh/Makefile
+++ b/src/bin/pgtclsh/Makefile
@@ -7,7 +7,7 @@
 #
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/bin/pgtclsh/Attic/Makefile,v 1.1.1.1 1996/07/09 06:22:15 scrappy Exp $
+#    $Header: /cvsroot/pgsql/src/bin/pgtclsh/Attic/Makefile,v 1.2 1996/07/23 03:03:36 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -15,7 +15,7 @@ MKDIR=	../../mk
 include $(MKDIR)/postgres.mk
 include ../Makefile.global
 
-CFLAGS+=  -I$(TCL_INCDIR) -I$(TK_INCDIR)
+CFLAGS+=  -I$(TCL_INCDIR) -I$(TK_INCDIR) -I$(X11_INCDIR) -I$(srcdir)/libpgtcl
 
 # try to find libpgtcl.a in either directory
 LIBPGTCL= -L$(srcdir)/libpgtcl/$(objdir) -L$(LIBDIR) -lpgtcl
@@ -26,7 +26,7 @@ pgtclsh: $(objdir)/pgtclAppInit.o
 
 pgtksh: $(objdir)/pgtkAppInit.o
 	$(CC) $(CDEBUG) -o $(objdir)/$(@F) $(objdir)/pgtkAppInit.o \
-	$(LIBPGTCL) $(LIBPQ) -L$(TCL_LIBDIR) -L$(TK_LIBDIR) \
+	$(LIBPGTCL) $(LIBPQ) -L$(TCL_LIBDIR) -L$(TK_LIBDIR) -L$(X11_LIBDIR) \
 	$(TK_LIB) $(TCL_LIB) -lX11 -lm $(LD_ADD)
 
 install::	localobj pgtclsh pgtksh
diff --git a/src/bin/pgtclsh/pgtclAppInit.c b/src/bin/pgtclsh/pgtclAppInit.c
index cc38ca34a70..a4ee17a0323 100644
--- a/src/bin/pgtclsh/pgtclAppInit.c
+++ b/src/bin/pgtclsh/pgtclAppInit.c
@@ -109,6 +109,11 @@ Tcl_AppInit(interp)
      * then no user-specific startup file will be run under any conditions.
      */
 
+#if (TCL_MAJOR_VERSION <= 7) && (TCL_MINOR_VERSION < 5)
     tcl_RcFileName = "~/.tclshrc";
+#else
+    Tcl_SetVar(interp, "tcl_rcFileName", "~/.tclshrc", TCL_GLOBAL_ONLY);
+#endif
+
     return TCL_OK;
 }
diff --git a/src/bin/pgtclsh/pgtkAppInit.c b/src/bin/pgtclsh/pgtkAppInit.c
index 33763458b51..044b6790dac 100644
--- a/src/bin/pgtclsh/pgtkAppInit.c
+++ b/src/bin/pgtclsh/pgtkAppInit.c
@@ -112,6 +112,11 @@ Tcl_AppInit(interp)
      * then no user-specific startup file will be run under any conditions.
      */
 
+#if (TCL_MAJOR_VERSION <= 7) && (TCL_MINOR_VERSION < 5)
     tcl_RcFileName = "~/.wishrc";
+#else
+    Tcl_SetVar(interp, "tcl_rcFileName", "~/.wishrc", TCL_GLOBAL_ONLY);
+#endif
+
     return TCL_OK;
 }
diff --git a/src/bin/psql/psql.c b/src/bin/psql/psql.c
index 4e33ed79df3..2201c064269 100644
--- a/src/bin/psql/psql.c
+++ b/src/bin/psql/psql.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *    $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.5 1996/07/20 08:44:45 scrappy Exp $
+ *    $Header: /cvsroot/pgsql/src/bin/psql/Attic/psql.c,v 1.6 1996/07/23 03:03:43 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,8 +16,8 @@
 #include <signal.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <unistd.h>
 #include <fcntl.h>
+
 #include "libpq-fe.h"
 #include "stringutils.h"
 
@@ -32,57 +32,52 @@ extern char *readline(char *);	/* in rlstubs.c */
 #include "history.h"
 #else
 #include <readline/readline.h>
-#include <readline/history.h>
+#include <history.h>
 #endif
 #endif
 
 #define MAX_QUERY_BUFFER 20000
+#define MAX_FIELD_SEP_LENGTH 40
 
 #define COPYBUFSIZ	8192
 
-#define DEFAULT_FIELD_SEP "|"
+#define DEFAULT_FIELD_SEP " "
 #define DEFAULT_EDITOR  "vi"
 #define DEFAULT_SHELL  "/bin/sh"
 
 typedef struct _psqlSettings {
-    PGconn *db;		   /* connection to backend */
-    FILE *queryFout;       /* where to send the query results */
-    PQprintOpt opt;        /* options to be passed to PQprint */
-    char *prompt;	   /* prompt to display */
-    char *gfname;	   /* one-shot file output argument for \g */
-    bool notty;		   /* input or output is not a tty */
-    bool pipe;		   /* queryFout is from a popen() */
-    bool echoQuery;        /* echo the query before sending it */
-    bool quiet;            /* run quietly, no messages, no promt */
-    bool singleStep;       /* prompt before for each query */ 
-    bool singleLineMode;   /* query terminated by newline */
-    bool useReadline;      /* use libreadline routines */
+    int echoQuery;        /* if 1, echo the query before sending it */
+    int quiet;            /* run quietly, no messages, no promt */
+    int singleStep;       /* if 1, prompt for each query */ 
+    int singleLineMode;   /* if 1, query terminated by newline */
+    int useReadline;      /* use the readline routines or not */
+    int printHeader;      /* print output field headers or not */
+    int fillAlign;        /* fill align the fields */
+    FILE *queryFout;      /* where to send the query results */
+    char fieldSep[MAX_FIELD_SEP_LENGTH];  /* field separator */
 } PsqlSettings;
 
 /* declarations for functions in this file */
 static void usage(char* progname);
 static void slashUsage();
-static void handleCopyOut(PGresult *res, bool quiet);
-static void handleCopyIn(PGresult *res, bool quiet);
-static int tableList(PsqlSettings *ps, bool deep_tablelist);
-static int tableDesc(PsqlSettings *ps, char *table);
+static void handleCopyOut(PGresult *res, int quiet);
+static void handleCopyIn(PGresult *res, int quiet);
+static int tableList(PGconn* conn, int deep_tablelist);
+static int tableDesc(PGconn* conn, char* table);
 
 char* gets_noreadline(char* prompt, FILE* source);
 char* gets_readline(char* prompt, FILE* source);
 char* gets_fromFile(char* prompt, FILE* source);
-int listAllDbs(PsqlSettings *settings);
-int SendQuery(PsqlSettings *settings, char* query);
-int HandleSlashCmds(PsqlSettings *settings,
+int listAllDbs(PGconn *db, PsqlSettings *settings);
+int SendQuery(PGconn* db, char* query, PsqlSettings *settings);
+int HandleSlashCmds(PGconn** db_ptr,  
 		    char *line,
-		    char *query);
-int MainLoop(PsqlSettings *settings, FILE *source);
-/* probably should move this into libpq */
-void PQprint(FILE *fp,
-                     PGresult *res, 
-		     PQprintOpt *po
-		     );
+		    char** prompt_ptr,
+		    char *query,
+		    PsqlSettings *settings);
+int MainLoop(PGconn** db_ptr, FILE *source, PsqlSettings *settings);
+FILE* setFout(char *fname);
 
-FILE* setFout(PsqlSettings *ps, char *fname);
 
 /*
  * usage 
@@ -94,24 +89,22 @@ usage(char* progname)
 {
   fprintf(stderr,"Usage: %s [options] [dbname]\n",progname);
   fprintf(stderr,"\t -a authsvc              set authentication service\n"); 
-  fprintf(stderr,"\t -A                      turn off alignment when printing out attributes\n");
+  fprintf(stderr,"\t -A                      turn off fill-justification when printing out attributes\n");
   fprintf(stderr,"\t -c query                run single query (slash commands too)\n");
   fprintf(stderr,"\t -d dbName               specify database name\n");
   fprintf(stderr,"\t -e                      echo the query sent to the backend\n");
   fprintf(stderr,"\t -f filename             use file as a source of queries\n");
   fprintf(stderr,"\t -F sep                  set the field separator (default is " ")\n");
-  fprintf(stderr,"\t -h host                 set database server host\n");
-  fprintf(stderr,"\t -H                      turn on html3.0 table output\n");
+  fprintf(stderr,"\t -h                      help information\n");
+  fprintf(stderr,"\t -H host                 set database server host\n");
   fprintf(stderr,"\t -l                      list available databases\n");
   fprintf(stderr,"\t -n                      don't use readline library\n");
-  fprintf(stderr,"\t -o filename             send output to filename or (|pipe)\n");
+  fprintf(stderr,"\t -o filename             send output to filename\n");
   fprintf(stderr,"\t -p port                 set port number\n");
   fprintf(stderr,"\t -q                      run quietly (no messages, no prompts)\n");
   fprintf(stderr,"\t -s                      single step mode (prompts for each query)\n");
   fprintf(stderr,"\t -S                      single line mode (i.e. query terminated by newline)\n");
-  fprintf(stderr,"\t -t                      turn off printing of attribute headers\n");
-  fprintf(stderr,"\t -T html                 set html3.0 table command options (cf. -H)\n");
-  fprintf(stderr,"\t -x                      turn on expanded output (field names on left)");
+  fprintf(stderr,"\t -T                      turn off printing of attribute names\n");
   exit(1);
 }
 
@@ -120,60 +113,29 @@ usage(char* progname)
  *    print out usage for the backslash commands 
  */
 
-char *on(bool f)
-{
-	return f? "on": "off";
-}
-
 static void
-slashUsage(PsqlSettings *ps)
+slashUsage()
 {
-  fprintf(stderr,"\t \\a           -- toggle field-alignment (currenty %s)\n", on(ps->opt.align));
-  fprintf(stderr,"\t \\c [<captn>] -- set html3 caption (currently '%s')\n", ps->opt.caption? ps->opt.caption: "");
-  fprintf(stderr,"\t \\C <dbname>  -- connect to new database (currently '%s')\n", PQdb(ps->db));
+  fprintf(stderr,"\t \\a           -- toggle fill-justification of display of attributes\n");
   fprintf(stderr,"\t \\d [<table>] -- list tables in database or columns in <table>\n");
   fprintf(stderr,"\t \\d *         -- list tables in database and columns in all tables\n");
   fprintf(stderr,"\t \\e [<fname>] -- edit the current query buffer or <fname>\n");
-  fprintf(stderr,"\t \\f [<sep>]   -- change field separater (currently '%s')\n", ps->opt.fieldSep);
-  fprintf(stderr,"\t \\g [<fname>] -- send query to backend [and place results in <fname>]\n");
-  fprintf(stderr,"\t \\g |<cmd>    -- send query to backend and pipe results into <cmd>\n");
-  fprintf(stderr,"\t \\h [<cmd>]   -- help on syntax of sql commands\n");
+  fprintf(stderr,"\t \\f <sep>     -- change field separator\n");
+  fprintf(stderr,"\t \\g           -- query to backend\n");
+  fprintf(stderr,"\t \\h <command> -- help on syntax of sql commands\n");
   fprintf(stderr,"\t \\h *         -- complete description of all sql commands\n");
-  fprintf(stderr,"\t \\H           -- toggle html3 output (currently %s)\n", on(ps->opt.html3));
-  fprintf(stderr,"\t \\i <fname>   -- read and execute queries from filename\n");
+  fprintf(stderr,"\t \\g           -- send query to backend\n");
+  fprintf(stderr,"\t \\i <fname>   -- read queries from filename\n");
   fprintf(stderr,"\t \\l           -- list all databases\n");
-  fprintf(stderr,"\t \\o [<fname>] -- send query results to <fname> or stdout\n");
-  fprintf(stderr,"\t \\o |<cmd>    -- pipe query results through <cmd>\n");
+  fprintf(stderr,"\t \\o [<fname>] -- send query results file named <fname> or stdout\n");
   fprintf(stderr,"\t \\p           -- print the current query buffer\n");
   fprintf(stderr,"\t \\q           -- quit\n");
-  fprintf(stderr,"\t \\r [<fname>] -- edit <fname> then send contents to backend\n");
-  fprintf(stderr,"\t \\s [<fname>] -- print history or save it in <fname>\n");
-  fprintf(stderr,"\t \\S           -- toggle standard sql type-setting (currently %s)\n", on(ps->opt.standard));
-  fprintf(stderr,"\t \\t           -- toggle table output header (currently %s)\n", on(ps->opt.header));
-  fprintf(stderr,"\t \\T [<html>]  -- set html3.0 <table ...> options (currently '%s')\n", ps->opt.tableOpt? ps->opt.tableOpt: "");
-  fprintf(stderr,"\t \\x           -- toggle expanded output (currently %s)\n", on(ps->opt.expanded));
-  fprintf(stderr,"\t \\z           -- zorch current query buffer (i.e clear it)\n");
-  fprintf(stderr,"\t \\! [<cmd>]   -- shell escape or command\n");
+  fprintf(stderr,"\t \\s [<fname>] -- save or print history\n");
+  fprintf(stderr,"\t \\t           -- toggle output field headers (defaults to on)\n");
+  fprintf(stderr,"\t \\! [<cmd>]   -- shell escape\n");
   fprintf(stderr,"\t \\?           -- help\n");
 }
 
-PGresult *
-PSQLexec(PsqlSettings *ps, char *query)
-{
-	PGresult *res = PQexec(ps->db, query);
-	if (!res)
-   		fputs(PQerrorMessage(ps->db), stderr);
-	else
-	{
-		if (PQresultStatus(res)==PGRES_COMMAND_OK ||
-		    PQresultStatus(res)==PGRES_TUPLES_OK)
-			return res;
-		if (!ps->quiet)
-    			fputs(PQerrorMessage(ps->db), stderr);
-		PQclear(res);
-	}
-	return NULL;
-}
 /*
  * listAllDbs
  *
@@ -182,37 +144,50 @@ PSQLexec(PsqlSettings *ps, char *query)
  *    
  *
  */
-
-int
-listAllDbs(PsqlSettings *ps)
+int 
+listAllDbs(PGconn *db, PsqlSettings *settings)
 {
   PGresult *results;
   char* query = "select * from pg_database;";
 
-  if (!(results=PSQLexec(ps, query)))
+  results = PQexec(db, query);
+  if (results == NULL) {
+    fprintf(stderr,"%s", PQerrorMessage(db));
     return 1;
+  }
+
+  if (PQresultStatus(results) != PGRES_TUPLES_OK)
+    {
+      fprintf(stderr,"Unexpected error from executing: %s\n", query);
+      return 2;
+    }
   else
     {
-      PQprint(ps->queryFout,
-                      results,
-		      &ps->opt);
+      PQdisplayTuples(results,
+		      settings->queryFout, 
+		      settings->fillAlign,
+		      settings->fieldSep,
+		      settings->printHeader,
+		      settings->quiet);
       PQclear(results);
       return 0;
     }
 }
 
 /*
+ * tableList (PGconn* conn)
  *
  * List The Database Tables
  *     returns 0 if all went well
  *    
  */
 int
-tableList (PsqlSettings *ps, bool deep_tablelist)
+tableList (PGconn* conn, int deep_tablelist)
 {
   char listbuf[256];
   int nColumns; 
   int i;
+  char* ru;
   char* rk;
   char* rr;
 
@@ -228,8 +203,17 @@ tableList (PsqlSettings *ps, bool deep_tablelist)
    add in the int4oideq function */
   strcat(listbuf,"  and usesysid = relowner");
   strcat(listbuf,"  ORDER BY relname ");
-  if (!(res=PSQLexec(ps, listbuf)))
-	return -1;
+  res = PQexec(conn,listbuf);
+  if (res == NULL) {
+      fprintf(stderr,"%s", PQerrorMessage(conn));
+      return (-1);
+  }
+
+  if ((PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res) <= 0)) {
+      fprintf(stderr,"No tables found in database %s.\n", PQdb(conn));
+      PQclear(res);
+      return (-1);
+  }
 
   /* first, print out the attribute names */
   nColumns = PQntuples(res);
@@ -252,14 +236,14 @@ tableList (PsqlSettings *ps, bool deep_tablelist)
 
  	PQclear(res);
  	for (i=0; i < nColumns; i++) {
- 	   tableDesc(ps, table[i]);
+ 	   tableDesc(conn,table[i]);
  	}
  	free(table);
       }
       else {
  	/* Display the information */
 
- 	printf ("\nDatabase    = %s\n", PQdb(ps->db));
+ 	printf ("\nDatabase    = %s\n", PQdb(conn));
 	printf (" +------------------+----------------------------------+----------+\n");
 	printf (" |  Owner           |             Relation             |   Type   |\n");
 	printf (" +------------------+----------------------------------+----------+\n");
@@ -288,7 +272,7 @@ tableList (PsqlSettings *ps, bool deep_tablelist)
 }
 
 /*
- * Describe a table
+ * Describe a table   (PGconn* conn, char* table)
  *
  * Describe the columns in a database table.
  *     returns 0 if all went well
@@ -296,7 +280,7 @@ tableList (PsqlSettings *ps, bool deep_tablelist)
  *
  */
 int
-tableDesc (PsqlSettings *ps, char *table)
+tableDesc (PGconn* conn, char* table)
 {
   char descbuf[256];
   int nColumns;
@@ -318,8 +302,16 @@ tableDesc (PsqlSettings *ps, char *table)
   strcat(descbuf,"    and a.attrelid = c.oid ");
   strcat(descbuf,"    and a.atttypid = t.oid ");
   strcat(descbuf,"  ORDER BY attnum ");
-  if (!(res = PSQLexec(ps, descbuf)))
-	return -1;
+  res = PQexec(conn,descbuf);
+  if (res == NULL) {
+    fprintf(stderr,"%s", PQerrorMessage(conn));
+    return (-1);
+   }
+ if ((PQresultStatus(res) != PGRES_TUPLES_OK) || (PQntuples(res) <= 0)) {
+   fprintf(stderr,"Couldn't find table %s!\n", table);
+   PQclear(res);
+   return (-1);
+ }
   /* first, print out the attribute names */
   nColumns = PQntuples(res);
   if (nColumns > 0)
@@ -329,9 +321,9 @@ tableDesc (PsqlSettings *ps, char *table)
     */
 
     printf ("\nTable    = %s\n", table);
-    printf ("+----------------------------------+----------------------------------+--------+\n");
-    printf ("|              Field               |              Type                | Length |\n");
-    printf ("+----------------------------------+----------------------------------+--------+\n");
+    printf ("+----------------------------------+----------------------------------+-------+\n");
+    printf ("|              Field               |              Type                | Length|\n");
+    printf ("+----------------------------------+----------------------------------+-------+\n");
 
     /* next, print out the instances */
     for (i=0; i < PQntuples(res); i++) {
@@ -340,15 +332,15 @@ tableDesc (PsqlSettings *ps, char *table)
       rsize = atoi(PQgetvalue(res,i,3));
       if (strcmp(rtype, "text") == 0) {
         printf ("%-32.32s |", rtype);
-        printf ("%6s |",  "var" );
+        printf ("%-6s |",  "var" );
       }
       else if (strcmp(rtype, "bpchar") == 0) {
         printf ("%-32.32s |", "char");
-        printf ("%6i |", rsize > 0 ? rsize - 4 : 0 );
+        printf ("%-6i |", rsize > 0 ? rsize - 4 : 0 );
       }
       else if (strcmp(rtype, "varchar") == 0) {
         printf ("%-32.32s |", rtype);
-        printf ("%6i |", rsize > 0 ? rsize - 4 : 0 );
+        printf ("%-6i |", rsize > 0 ? rsize - 4 : 0 );
       }
       else {
 	  /* array types start with an underscore */
@@ -363,13 +355,13 @@ tableDesc (PsqlSettings *ps, char *table)
 	      free(newname);
 	  }
 	if (rsize > 0) 
-	    printf (" %6i |", rsize);
+	    printf ("%-6i |", rsize);
 	else
-	    printf (" %6s |", "var");
+	    printf ("%-6s |", "var");
       }
       printf("\n");
     }
-    printf ("+----------------------------------+----------------------------------+--------+\n");
+    printf ("+----------------------------------+----------------------------------+-------+\n");
 
     PQclear(res);
     return (0);
@@ -404,6 +396,7 @@ gets_readline(char* prompt, FILE* source)
   return (readline(prompt));
 }
 
+
 /*
  * gets_fromFile  prompt source
  *    
@@ -433,12 +426,14 @@ gets_fromFile(char* prompt, FILE* source)
 }
 
 /*
- *  SendQuery: send the query string to the backend 
+ * SendQuery:
+     SendQuery: send the query string to the backend 
+ *
  *  return 0 if the query executed successfully
  *  returns 1 otherwise
  */
 int
-SendQuery(PsqlSettings *settings, char *query)
+SendQuery(PGconn* db, char* query, PsqlSettings *settings)
 {
   PGresult* results;
   PGnotify* notify;
@@ -459,41 +454,20 @@ SendQuery(PsqlSettings *settings, char *query)
 	gets_fromFile("",stdin);
   }
 
-  results = PQexec(settings->db, query);
+  results = PQexec(db, query);
   if (results == NULL) {
-    fprintf(stderr,"%s",PQerrorMessage(settings->db));
+    fprintf(stderr,"%s",PQerrorMessage(db));
     return 1;
   }
 
   switch (PQresultStatus(results)) {
   case PGRES_TUPLES_OK:
-      if (settings->gfname)
-      {
-      		PsqlSettings ps=*settings;
-		FILE *fp;
-		ps.queryFout=stdout;
-		fp=setFout(&ps, settings->gfname);
-		if (!fp || fp==stdout)
-		{
-			status = 1;
-			break;
-		}
-		PQprint(fp,
-			results,
-			&(settings->opt));
-		if (ps.pipe)
-			pclose(fp);
-		else
-			fclose(fp);
-		settings->gfname=NULL;
-		break;
-	} else 
-	{
-	      PQprint(settings->queryFout,
-			      results,
-			      &(settings->opt));
-	      fflush(settings->queryFout);
-	}
+      PQdisplayTuples(results,
+		      settings->queryFout,
+		      settings->fillAlign,
+		      settings->fieldSep,
+		      settings->printHeader,
+		      settings->quiet);
       PQclear(results);
       break;
   case PGRES_EMPTY_QUERY:
@@ -501,7 +475,7 @@ SendQuery(PsqlSettings *settings, char *query)
     break;
   case PGRES_COMMAND_OK:
     if (!settings->quiet)
-      fprintf(stdout,"%s\n", PQcmdStatus(results));
+      fprintf(stdout,"%s\n",PQcmdStatus(results));
     break;
   case PGRES_COPY_OUT:
     handleCopyOut(results, settings->quiet);
@@ -513,12 +487,13 @@ SendQuery(PsqlSettings *settings, char *query)
   case PGRES_FATAL_ERROR:
   case PGRES_BAD_RESPONSE:
     status = 1;
-    fprintf(stderr,"%s",PQerrorMessage(settings->db));
+    fprintf(stderr,"%s",PQerrorMessage(db));
     break;
+
   } 
 
   /* check for asynchronous returns */
-  notify = PQnotifies(settings->db);
+  notify = PQnotifies(db);
   if (notify) {
       fprintf(stderr,"ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
 	      notify->relname, notify->be_pid);
@@ -529,71 +504,6 @@ SendQuery(PsqlSettings *settings, char *query)
 
 }
 
-void
-editFile(char *fname)
-{
-    char *editorName;
-    char *sys;
-    editorName = getenv("EDITOR");
-    if (!editorName)
-	editorName = DEFAULT_EDITOR;
-    sys=malloc(strlen(editorName)+strlen(fname)+32+1);
-    if (!sys)
-    {
-	perror("malloc");
-	exit(1);
-    }
-    sprintf(sys, "exec '%s' '%s'", editorName, fname);
-    system(sys);
-    free(sys);
-}
-
-bool
-toggle(PsqlSettings *settings, bool *sw, char *msg)
-{
-	*sw= !*sw;
-	if (!settings->quiet)
-	    fprintf(stderr, "turned %s %s\n", on(*sw), msg);
-	return *sw;
-}
-
-char *
-decode(char *s)
-{
-	char *p, *d;
-	bool esc=0;
-	for (d=p=s; *p; p++)
-	{
-		char c=*p;
-		if (esc)
-		{
-			switch(*p)
-			{
-			case 'n':
-				c='\n';
-				break;
-			case 'r':
-				c='\r';
-				break;
-			case 't':
-				c='\t';
-				break;
-			case 'f':
-				c='\f';
-				break;
-			}
-			esc=0;
-		} else
-			if (c=='\\')
-			{
-				esc=1;
-				continue;
-			}
-		*d++=c;
-	}
-	*d='\0';
-}
-
 /*
   HandleSlashCmds:
 
@@ -609,161 +519,189 @@ decode(char *s)
        2 - terminate processing of this query entirely
 */
 int
-HandleSlashCmds(PsqlSettings *settings,
+HandleSlashCmds(PGconn** db_ptr, 
 		char* line, 
-		char *query)
+		char** prompt_ptr, 
+		char *query,
+		PsqlSettings *settings)
 {
-  int status = 1;
+  int status = 0;
+  PGconn* db = *db_ptr;
+  char* dbname = PQdb(db);
   char *optarg = NULL;
   int len;
 
   len = strlen(line);
   if (len > 2)
-  {
       optarg = leftTrim(line+2);
-      decode(optarg);
-  }
   switch (line[1])
     {
-    case 'a': /* toggles to align fields on output */
-        toggle(settings, &settings->opt.align, "field alignment");
-	break;
-    case 'c': /* define new caption */
-    	if (settings->opt.caption)
-		free(settings->opt.caption);
-	if (!optarg)
-		settings->opt.caption=NULL;
-	else
-		if (!(settings->opt.caption=dupstr(optarg)))
-		{
-			perror("malloc");
-			exit(1);
-		}
+    case 'a': /* toggles to fill fields on output */
+	if (settings->fillAlign)
+	    settings->fillAlign = 0;
+	else 
+	    settings->fillAlign = 1;
+	if (!settings->quiet)
+	    fprintf(stderr,"turning %s fill-justification\n",
+		    (settings->fillAlign) ? "on" : "off" );
 	break;
-    case 'C':  /* \C means connect to new database */
+    case 'c':  /* \c means connect to new database */
       {
-	  char *dbname=PQdb(settings->db);
 	  if (!optarg) {
 	      fprintf(stderr,"\\c must be followed by a database name\n");
+	      status = 1;
 	      break;
 	  }
-	  {
-	      PGconn *olddb=settings->db;
+	  if (strcmp(optarg, dbname) == 0)  {
+	      fprintf(stderr,"already connected to %s\n", dbname);
+	      status = 1;
+	      break;
+	  }
+	  else {
+	      PGconn *olddb;
 	      
-	      printf("closing connection to database: %s\n", dbname);
-	      settings->db = PQsetdb(PQhost(olddb), PQport(olddb), NULL, NULL, optarg);
+	      printf("closing connection to database:%s\n", dbname);
+	      olddb = db;
+	      db = PQsetdb(PQhost(olddb), PQport(olddb), NULL, NULL, optarg);
+	      *db_ptr = db;
 	      printf("connecting to new database: %s\n", optarg);
-	      if (PQstatus(settings->db) == CONNECTION_BAD) {
-		  fprintf(stderr,"%s\n", PQerrorMessage(settings->db));
+	      if (PQstatus(db) == CONNECTION_BAD) {
+		  fprintf(stderr,"%s\n", PQerrorMessage(db));
 		  printf("reconnecting to %s\n", dbname);
-		  settings->db = PQsetdb(PQhost(olddb), PQport(olddb), 
+		  db = PQsetdb(PQhost(olddb), PQport(olddb), 
 			       NULL, NULL, dbname);
-		  if (PQstatus(settings->db) == CONNECTION_BAD) {
+		  *db_ptr = db;
+		  if (PQstatus(db) == CONNECTION_BAD) {
 		      fprintf(stderr, 
-			      "could not reconnect to %s. exiting\n", dbname);
+			      "could not reconnect to %s.  exiting\n", dbname);
 		      exit(2);
 		  }
+		  status = 1;
 		  break;
 	      }
 	      PQfinish(olddb);
-	      free(settings->prompt);
-	      settings->prompt = malloc(strlen(PQdb(settings->db)) + 10);
-	      sprintf(settings->prompt,"%s=> ", PQdb(settings->db));
+	      free(*prompt_ptr);
+	      *prompt_ptr = malloc(strlen(optarg) + 10);
+	      sprintf(*prompt_ptr,"%s=> ", optarg);
+	      status = 1;
 	    break;
 	  }
       }
       break;
     case 'd':     /* \d describe tables or columns in a table */
+      {
 	if (!optarg) {
-          tableList(settings, 0);
+          tableList(db,0);
+	  status = 1;
 	  break;
-	} 
- 	if (strcmp(optarg, "*") == 0 ) {
- 	   tableList(settings, 0);
- 	   tableList(settings, 1);
+	}
+ 	if ( strcmp(optarg,"*") == 0 ) {
+ 	   tableList(db, 0);
+ 	   tableList(db, 1);
  	}
  	else {
- 	   tableDesc(settings, optarg);
+ 	   tableDesc(db,optarg);
  	}
+ 	status = 1;
  	break;
+      }
     case 'e':
       {
+	char s[256];
 	int fd;
-	char tmp[64];
-	char *fname;
-	int cc;
 	int ql = strlen(query);
+	int f_arg = 0;
+	int cc;
         if (optarg)
-        	fname=optarg;
+        {
+        	f_arg = 1;
+        	strcpy(s, optarg);
+        }
         else
-	{
-		sprintf(tmp, "/tmp/psql.%d.%d", getuid(), getpid());
-		fname=tmp;
-		unlink(tmp);
+        {
+		sprintf(s, "/tmp/psql.%d.%d", geteuid(), getpid());
+		unlink(s);
 		if (ql)
 		{
-			if ((fd=open(tmp, O_EXCL|O_CREAT|O_WRONLY, 0600))==-1)
+			if ((fd=open(s, O_EXCL|O_CREAT|O_WRONLY, 0600))==-1)
 			{
-				perror(tmp);
+				perror(s);
 				break;
 			}
 			if (query[ql-1]!='\n')
 				strcat(query, "\n");
 			if (write(fd, query, ql)!=ql)
 			{
-				perror(tmp);
+				perror(s);
 				close(fd);
-				unlink(tmp);
+				unlink(s);
 				break;
 			}
 			close(fd);
 		}
 	}
-	editFile(fname);
-	if ((fd=open(fname, O_RDONLY))==-1)
 	{
-		perror(fname);
-		if (!optarg)
-			unlink(fname);
+	    char sys[256];
+	    char *editorName;
+	    editorName = getenv("EDITOR");
+	    if (editorName == NULL)
+		editorName = DEFAULT_EDITOR;
+	    sprintf(sys, "exec %s %s", editorName, s);
+	    system(sys);
+        }
+	if ((fd=open(s, O_RDONLY))==-1)
+	{
+		if (!f_arg)
+			unlink(s);
 		break;
 	}
 	if ((cc=read(fd, query, MAX_QUERY_BUFFER))==-1)
         {
-		perror(fname);
+		perror(s);
 		close(fd);
-		if (!optarg)
-			unlink(fname);
+		if (!f_arg)
+			unlink(s);
 		break;
 	}	
 	query[cc]='\0';
 	close(fd);
-	if (!optarg)
-		unlink(fname);
+	if (!f_arg)
+		unlink(s);
 	rightTrim(query);
 	if (query[strlen(query)-1]==';')
 		return 0;
 	break;
       }
-    case 'f':
-    {
-        char *fs=DEFAULT_FIELD_SEP;
-    	if (optarg)
-		fs=optarg;
-        if (settings->opt.fieldSep);
-		free(settings->opt.fieldSep);
-	if (!(settings->opt.fieldSep=dupstr(fs)))
-	{
-		perror("malloc");
-		exit(1);
-	}
-	if (!settings->quiet)
-		fprintf(stderr, "field separater changed to '%s'\n", settings->opt.fieldSep);
-	break;
-    }
+  case 'f':
+      if (optarg)
+	  strcpy(settings->fieldSep,optarg);
+      else
+          strcpy(settings->fieldSep,DEFAULT_FIELD_SEP);
+      break;
   case 'g':  /* \g means send query */
-      settings->gfname = optarg;
       status = 0;     
-      break;
+	break;
+    case 'i':     /* \i is include file */
+      {
+	FILE* fd;
+
+	if (!optarg) {
+	  fprintf(stderr,"\\i must be followed by a file name\n");
+	  status = 1;
+	  break;
+	}
+
+	if ( (fd = fopen(optarg, "r")) == NULL)
+	  {
+	    fprintf(stderr,"file named %s could not be opened\n",optarg);
+	    status = 1;
+	    break;
+	  }
+	MainLoop(&db, fd, settings);
+	fclose(fd);
+	status = 1;
+	break;
+      }
     case 'h':
       {
 	char* cmd;
@@ -789,7 +727,7 @@ HandleSlashCmds(PsqlSettings *settings,
 
 	  numCmds = numCmds - 1;
 
- 	  if (strcmp(cmd, "*") == 0 ) {
+ 	  if ( strcmp(cmd,"*") == 0 ) {
  	     all_help=1;
  	  }
 
@@ -810,143 +748,74 @@ HandleSlashCmds(PsqlSettings *settings,
 	  if (i == numCmds && ! all_help)
 	    printf("command not found,  try \\h with no arguments to see available help\n");
 	}
+	status = 1;
 	break;
       }
-    case 'i':     /* \i is include file */
-        {
-        FILE* fd;
- 
-        if (!optarg) {
-          fprintf(stderr,"\\i must be followed by a file name\n");
-          break;
-        }
- 
-        if ((fd = fopen(optarg, "r")) == NULL)
-          {
-            fprintf(stderr,"file named %s could not be opened\n",optarg);
-            break;
-          }
-        MainLoop(settings, fd);
-        fclose(fd);
-        break;
-        }
     case 'l':     /* \l is list database */
-       listAllDbs(settings);
-       break;
-    case 'H':
-       if (toggle(settings, &settings->opt.html3, "HTML3.0 tablular output"))
-           settings->opt.standard = 0;
+      listAllDbs(db,settings);
+      status = 1;
       break;
     case 'o':
-      setFout(settings, optarg);
+      settings->queryFout = setFout(optarg);
       break;
     case 'p':
 	if (query) {
 	    fputs(query, stdout);
 	    fputc('\n', stdout);
+            status = 1;
 	}
 	break;
     case 'q': /* \q is quit */
       status = 2;
       break;
     case 'r':
-    {
-      FILE* fd;
-      static char *lastfile;
-      struct stat st, st2;
-      if (optarg) { 
-	if (lastfile) free(lastfile);
-	lastfile=malloc(strlen(optarg+1));
-	if (!lastfile) {
-	   perror("malloc");
-	   exit(1);
-	}  
-	strcpy(lastfile, optarg);
-      } else 
-	if (!lastfile) {
-	   fprintf(stderr, "\\r must be followed by a file name initially\n"); 
-  	   break;
+        query[0] = '\0';
+        status = 1;
+        break;
+    case 's': /* \s is save history to a file */
+      {
+	char* fname;
+
+	if (!optarg) {
+	  fprintf(stderr,"\\s must be followed by a file name\n");
+	  status = 1;
+	  break;
 	}
-      stat(lastfile, &st); 
-      editFile(lastfile);
-      if ((stat(lastfile, &st2) == -1) || 
-	 ((fd = fopen(lastfile, "r")) == NULL)) {
-	   perror(lastfile);
-	   break;
-      }
-      if (st2.st_mtime==st.st_mtime) { 
-	if (!settings->quiet)
-	   fprintf(stderr, "warning: %s not modified. query not executed\n", 
-		   lastfile);  
-	fclose(fd);
+
+	fname = optarg;
+	if (write_history(fname) != 0)
+	  {
+	    fprintf(stderr,"cannot write history to %s\n",fname);
+	  }
+	status = 1;
 	break;
-      } 
-      MainLoop(settings, fd);
-      fclose(fd);
-      break;
       }
-    case 's': /* \s is save history to a file */
-      if (!optarg) optarg="/dev/tty";
-      if (write_history(optarg) != 0)
-          fprintf(stderr,"cannot write history to %s\n",optarg);
-      break;
-    case 'S': /* standard SQL output */
-      if (toggle(settings, &settings->opt.standard, 
-	         "standard SQL separaters and padding")) {
-	settings->opt.html3 = settings->opt.expanded = 0;
-	settings->opt.align = settings->opt.header = 1;
-	free(settings->opt.fieldSep);
-	settings->opt.fieldSep=dupstr("|");
-	if (!settings->quiet)
-	   fprintf(stderr, "field separater changed to '%s'\n", 
-		   settings->opt.fieldSep);
-      } else {
-	free(settings->opt.fieldSep);
-	settings->opt.fieldSep=dupstr(DEFAULT_FIELD_SEP);
+    case 't':
+	if ( settings->printHeader )
+	     settings->printHeader = 0;
+	else
+	     settings->printHeader = 1;
 	if (!settings->quiet)
-	   fprintf(stderr, "field separater changed to '%s'\n", 
-		   settings->opt.fieldSep); 
-      }
-      break;
-    case 't': /* toggle headers */
-      toggle(settings, &settings->opt.header, "output headers");
-      break; 
-    case 'T': /* define html <table ...> option */
-      if (settings->opt.tableOpt) free(settings->opt.tableOpt);
-      if (!optarg) settings->opt.tableOpt=NULL;
-      else
-	if (!(settings->opt.tableOpt=dupstr(optarg))) {
-	   perror("malloc");
-	   exit(1);
-	}
-      break;
-    case 'x':
-      toggle(settings, &settings->opt.expanded, 
-	     "expanded table representation");     
-      break;
-    case 'z': /* zorch buffer */
-      query[0]='\0';
-      if (!settings->quiet) fprintf(stderr, "zorched current query buffer\n");
-      break;  
+	    fprintf(stderr,"turning %s printing of field headers\n",
+		    (settings->printHeader) ? "on" : "off" );
+	break;
     case '!':
       if (!optarg) {
-	char *sys;
-	char *shellName;
-	shellName = getenv("SHELL");
-	if (shellName == NULL) shellName = DEFAULT_SHELL;
-	sys = malloc(strlen(shellName)+16);
-	if (!sys) {
-	   perror("malloc");
-	   exit(1);
-	}
-	sprintf(sys,"exec %s", shellName);
-	system(sys);
-	free(sys);
-      } else system(optarg);
+	  char sys[256];
+	  char *shellName;
+	  shellName = getenv("SHELL");
+	  if (shellName == NULL) 
+	      shellName = DEFAULT_SHELL;
+	  sprintf(sys,"exec %s", shellName);
+	  system(sys);
+      }
+      else
+	  system(optarg);
       break;
     default:
     case '?':     /* \? is help */
-      slashUsage(settings);
+      slashUsage();
+      status = 1;
       break;
     }
   return status;
@@ -961,14 +830,19 @@ HandleSlashCmds(PsqlSettings *settings,
 
  *db_ptr must be initialized and set
 */
-
 int
-MainLoop(PsqlSettings *settings, FILE* source)
+MainLoop(PGconn** db_ptr, 
+	 FILE* source,
+	 PsqlSettings *settings)
 {
+  char* prompt;                 /* readline prompt */
   char* line;                   /* line of input*/
   int len;                      /* length of the line */
   char query[MAX_QUERY_BUFFER]; /* multi-line query storage */
+  PGconn* db = *db_ptr;
+  char* dbname = PQdb(db);
   int exitStatus = 0;
+
   int slashCmdStatus = 0;
  /* slashCmdStatus can be:
        0 - send currently constructed query to backend (i.e. we got a \g)
@@ -976,21 +850,18 @@ MainLoop(PsqlSettings *settings, FILE* source)
        2 - terminate processing of this query entirely
   */
 
-  bool sendQuery = 0;
-  bool querySent = 0;
-  bool interactive;
+  int send_query = 0;
+  int interactive;
   READ_ROUTINE GetNextLine;
 
-  interactive = ((source == stdin) && !settings->notty);
-#define PROMPT "=> "
+  interactive = (source == stdin);
+
   if (interactive) {
-    if (settings->prompt)
-	free(settings->prompt);
-    settings->prompt = malloc(strlen(PQdb(settings->db)) + strlen(PROMPT) + 1);
+    prompt = malloc(strlen(dbname) + 10);
     if (settings->quiet)
-      settings->prompt[0] = '\0';
+      prompt[0] = '\0';
     else
-      sprintf(settings->prompt,"%s%s", PQdb(settings->db), PROMPT);
+      sprintf(prompt,"%s=> ", dbname);
     if (settings->useReadline) {
 	using_history();
 	GetNextLine = gets_readline;
@@ -1004,7 +875,7 @@ MainLoop(PsqlSettings *settings, FILE* source)
   query[0] = '\0';
   
   /* main loop for getting queries and executing them */
-  while ((line = GetNextLine(settings->prompt, source)) != NULL)
+  while ((line = GetNextLine(prompt, source)) != NULL)
     {
 	exitStatus = 0;
       line = rightTrim(line); /* remove whitespaces on the right, incl. \n's */
@@ -1024,11 +895,6 @@ MainLoop(PsqlSettings *settings, FILE* source)
 	  free(line);
 	  continue;
       }
-      if (line[0] != '\\' && querySent)
-      {
-	  query[0]='\0';
-          querySent = 0;
-      }
 
       len = strlen(line);
 
@@ -1037,31 +903,34 @@ MainLoop(PsqlSettings *settings, FILE* source)
       
       /* do the query immediately if we are doing single line queries 
        or if the last character is a semicolon */
-      sendQuery = settings->singleLineMode || (line[len-1] == ';') ;
+      send_query = settings->singleLineMode || (line[len-1] == ';') ;
 
       /* normally, \ commands have to be start the line,
 	 but for backwards compatibility with monitor,
 	 check for \g at the end of line */
-      if (len > 2 && !sendQuery) 
+      if (len > 2 && !send_query) 
 	{
 	  if (line[len-1]=='g' && line[len-2]=='\\')
 	    {
-	    sendQuery = 1;
+	    send_query = 1;
 	    line[len-2]='\0';
 	  }
 	}
       
       /* slash commands have to be on their own line */
       if (line[0] == '\\') {
-	  slashCmdStatus = HandleSlashCmds(settings,
+	  slashCmdStatus = HandleSlashCmds(db_ptr, 
 					   line, 
-					   query);
+					   &prompt, 
+					   query,
+					   settings);
+	db = *db_ptr; /* in case \c changed the database */
 	if (slashCmdStatus == 1)
 	  continue;
 	if (slashCmdStatus == 2)
 	  break;
 	if (slashCmdStatus == 0)
-	  sendQuery = 1;
+	  send_query = 1;
       }
       else
 	if (strlen(query) + len > MAX_QUERY_BUFFER)
@@ -1077,29 +946,30 @@ MainLoop(PsqlSettings *settings, FILE* source)
       else
 	strcpy(query,line);
       
-      if (sendQuery && query[0] != '\0')
+      if (send_query && query[0] != '\0')
 	{
 	    /* echo the line read from the file,
 	     unless we are in single_step mode, because single_step mode
 	     will echo anyway */
-	  if (!interactive && !settings->singleStep && !settings->quiet) 
-	    fprintf(stderr,"%s\n", query);
+	  if (!interactive && !settings->singleStep) 
+	    fprintf(stderr,"%s\n",query);
 
-	  exitStatus = SendQuery(settings, query);
-          querySent = 1;
+	  exitStatus = SendQuery(db, query, settings);
+	  query[0] = '\0';
 	}
       
        free(line); /* free storage malloc'd by GetNextLine */
     } /* while */
-    return exitStatus;
+  return exitStatus;
 } 
 
 int
 main(int argc, char** argv)
 {
   extern char* optarg;
-  extern int optind;
+  extern int optind, opterr;
   
+  PGconn *db;
   char* dbname = NULL;
   char* host = NULL;
   char* port = NULL;
@@ -1110,27 +980,31 @@ main(int argc, char** argv)
 
   char* singleQuery = NULL;
 
-  bool listDatabases = 0 ;
+  int listDatabases = 0 ;
   int exitStatus = 0;
-  bool singleSlashCmd = 0;
+  int singleSlashCmd = 0;
   int c;
 
-  memset(&settings, 0, sizeof settings);
-  settings.opt.align = 1;
-  settings.opt.header = 1;
-  settings.queryFout = stdout;
-  settings.opt.fieldSep=dupstr(DEFAULT_FIELD_SEP);
-  if (!isatty(0) || !isatty(1))
-  	settings.quiet = settings.notty = 1;
-  else
-#ifndef NOREADLINE
-	settings.useReadline = 1;
+
+#ifdef NOREADLINE
+  settings.useReadline = 0;
+#else
+  settings.useReadline = 1;
 #endif
 
-  while ((c = getopt(argc, argv, "Aa:c:d:ef:F:lhH:nso:p:qStTx")) != EOF) {
+  settings.quiet = 0;
+  settings.fillAlign = 1;
+  settings.printHeader = 1;
+  settings.echoQuery = 0;
+  settings.singleStep = 0;
+  settings.singleLineMode = 0;
+  settings.queryFout = stdout;
+  strcpy(settings.fieldSep, DEFAULT_FIELD_SEP);
+
+  while ((c = getopt(argc, argv, "Aa:c:d:ef:F:lhH:nso:p:qST")) != EOF) {
     switch (c) {
     case 'A':
-	settings.opt.align = 0;
+	settings.fillAlign = 0;
 	break;
     case 'a':
 	fe_setauthsvc(optarg, errbuf);
@@ -1151,23 +1025,20 @@ main(int argc, char** argv)
       qfilename = optarg;
       break;
     case 'F':
-      settings.opt.fieldSep=dupstr(optarg);
-      break;
+	strncpy(settings.fieldSep,optarg,MAX_FIELD_SEP_LENGTH); 
+	break;
     case 'l':
       listDatabases = 1;
       break;
-    case 'h':
-      host = optarg;
-      break;
     case 'H':
-      settings.opt.html3 = 1;
+      host = optarg;
       break;
     case 'n':
-      settings.useReadline = 0;
-      break;
+	settings.useReadline = 0;
+	break;
     case 'o':
-      setFout(&settings, optarg);
-      break;
+	settings.queryFout = setFout(optarg);
+	break;
     case 'p':
       port = optarg;
       break;
@@ -1180,15 +1051,10 @@ main(int argc, char** argv)
     case 'S':
       settings.singleLineMode = 1;
       break;
-    case 't':
-      settings.opt.header = 0;
-      break;
     case 'T':
-      settings.opt.tableOpt = dupstr(optarg);
-      break;
-    case 'x':
-      settings.opt.expanded = 0;
-      break;
+	settings.printHeader = 0;
+	break;
+    case 'h':
     default:
       usage(argv[0]);
       break;
@@ -1201,16 +1067,16 @@ main(int argc, char** argv)
   if (listDatabases)
     dbname = "template1";
   
-  settings.db = PQsetdb(host, port, NULL, NULL, dbname);
-  dbname = PQdb(settings.db);
+  db = PQsetdb(host, port, NULL, NULL, dbname);
+  dbname = PQdb(db);
 
-  if (PQstatus(settings.db) == CONNECTION_BAD) {
+  if (PQstatus(db) == CONNECTION_BAD) {
     fprintf(stderr,"Connection to database '%s' failed.\n", dbname);
-    fprintf(stderr,"%s",PQerrorMessage(settings.db));
+    fprintf(stderr,"%s",PQerrorMessage(db));
     exit(1);
   }
   if (listDatabases) {
-      exit(listAllDbs(&settings));
+      exit(listAllDbs(db,&settings));
     }
 
   if (!settings.quiet && !singleQuery && !qfilename) {
@@ -1226,6 +1092,7 @@ main(int argc, char** argv)
       /* read in a file full of queries instead of reading in queries
 	 interactively */
       char *line;
+      char prompt[100];
 
       if ( singleSlashCmd ) {
  	/* Not really a query, but "Do what I mean, not what I say." */
@@ -1235,25 +1102,24 @@ main(int argc, char** argv)
  	line = malloc(strlen(qfilename) + 5);
  	sprintf(line,"\\i %s", qfilename);
       }
-      HandleSlashCmds(&settings, line, "");
+      HandleSlashCmds(&db, line, (char**)prompt, "", &settings);
       
    } else {
        if (singleQuery) {
-	   exitStatus = SendQuery(&settings, singleQuery);
+	   exitStatus = SendQuery(db, singleQuery, &settings);
        }
        else 
-	   exitStatus = MainLoop(&settings, stdin);
+	   exitStatus = MainLoop(&db, stdin, &settings);
    }
 
-  PQfinish(settings.db);
+  PQfinish(db);
 
   return exitStatus;
 }
 
-#define COPYBUFSIZ	8192
 
 static void
-handleCopyOut(PGresult *res, bool quiet)
+handleCopyOut(PGresult *res, int quiet)
 {
     bool copydone = false;
     char copybuf[COPYBUFSIZ];
@@ -1287,7 +1153,7 @@ handleCopyOut(PGresult *res, bool quiet)
 
 
 static void
-handleCopyIn(PGresult *res, bool quiet)
+handleCopyIn(PGresult *res, int quiet)
 {
     bool copydone = false;
     bool firstload;
@@ -1346,38 +1212,24 @@ handleCopyIn(PGresult *res, bool quiet)
     PQendcopy(res->conn);
 }
 
+
 /* try to open fname and return a FILE*,
    if it fails, use stdout, instead */
-
 FILE* 
-setFout(PsqlSettings *ps, char *fname)
+setFout(char *fname)
 {
-        if (ps->queryFout && ps->queryFout != stdout)
-	{
-		if (ps->pipe)
-			pclose(ps->queryFout);
-		else
-			fclose(ps->queryFout);
+    FILE *queryFout;
+
+    if (!fname)
+	queryFout = stdout;
+    else {
+	queryFout = fopen(fname, "w");
+	if (!queryFout) {
+	    perror(fname);
+	    queryFout = stdout;
 	}
-	if (!fname)
-		ps->queryFout = stdout;
-	else
-	{
-		if (*fname == '|')
-		{
-	                signal(SIGPIPE, SIG_IGN);
-			ps->queryFout = popen(fname+1, "w");
-			ps->pipe = 1;
-		}
-		else
-		{
-			ps->queryFout = fopen(fname, "w");
-			ps->pipe = 0;
-		}
-		if (!ps->queryFout) {
-		    perror(fname);
-		    ps->queryFout = stdout;
-		}
-	}
-    return ps->queryFout;
+    }
+
+    return queryFout;
 }
+ 
-- 
GitLab