Add -U and -W options to pg_dump and friends to support non-interactive
authorPeter Eisentraut
Thu, 17 May 2001 21:12:49 +0000 (21:12 +0000)
committerPeter Eisentraut
Thu, 17 May 2001 21:12:49 +0000 (21:12 +0000)
specification of username (like in psql).  pg_dumpall now works with
password authentication.

doc/src/sgml/backup.sgml
doc/src/sgml/ref/pg_dump.sgml
doc/src/sgml/ref/pg_dumpall.sgml
doc/src/sgml/ref/pg_restore.sgml
src/bin/pg_dump/pg_backup.h
src/bin/pg_dump/pg_backup_archiver.c
src/bin/pg_dump/pg_backup_archiver.h
src/bin/pg_dump/pg_backup_db.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dumpall.sh
src/bin/pg_dump/pg_restore.c

index 160cb0bba1b40f72559b6e97c3f2c8b9e54dfe9e..ba1b6c9b21c6254dcf954cb03b09875fe5c4e692 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
  Backup and Restore
 
@@ -61,11 +61,10 @@ pg_dump dbname > 
    As any other Postgres client application,
    pg_dump will by default connect with the database
    user name that is equal to the current Unix user name. To override
-   this, either specify the  option to force a prompt for
-   the user name, or set the environment variable
-   PGUSER. Remember that pg_dump
-   connections are subject to the normal client authentication
-   mechanisms (which are described in 
+   this, either specify the  option or set the
+   environment variable PGUSER. Remember that
+   pg_dump connections are subject to the normal
+   client authentication mechanisms (which are described in 
    linkend="client-authentication">).
   
 
@@ -163,20 +162,6 @@ pg_dumpall > outfile
     you have database superuser access, as that is required to restore
     the user and group information.
    
-
-   
-    pg_dumpall has one little flaw: It is
-    not prepared for interactively authenticating to each database it
-    dumps. If you are using password authentication then you need to
-    set it the environment variable PGPASSWORD to
-    communicate the password the the underlying calls to
-    pg_dump. More severely, if you have different
-    passwords set up for each database, then
-    pg_dumpall will fail. You can either choose a
-    different authentication mechanism for the purposes of backup or
-    adjust the pg_dumpall shell script to your
-    needs.
-   
   
 
   
index ddcf5db63f8b76be72a2529008b6a6e1ae39493c..be2afefc8f25f051b56861e3dbcd0580f3e514bb 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -46,7 +46,8 @@ Postgres documentation
    -Z 0...9
    -h host
    -p port
-   -u
+   -U username
+   -W
    dbname
   
  
@@ -412,13 +413,20 @@ Postgres documentation
      
 
      
-      -u
+      -username
       
        
-   Use password authentication. 
-   Prompts for
-   username
-   and password.
+        Connect as the given user.
+       
+      
+     
+
+     
+      -W
+      
+       
+        Force a password prompt.  This should happen automatically if
+        the server requires password authentication.
        
       
      
index aa2c2a8827659df6be7a0994d83f50462d042799..bf35106c67a06869585bf2a02752ce91d9b2d82e 100644 (file)
@@ -1,5 +1,5 @@
 
 
@@ -23,9 +23,11 @@ Postgres documentation
   
    pg_dumpall
    -c--clean
+   -g--globals-only
    -h host
    -p port
-   -g--globals-only
+   -U username
+   -W
   
  
 
@@ -81,6 +83,15 @@ Postgres documentation
       
      
 
+     
+      -g, --globals-only
+      
+       
+   Only dump global objects (users and groups), no databases.
+       
+      
+     
+
      
       -h host
       
@@ -106,14 +117,23 @@ Postgres documentation
      
 
      
-      -g, --globals-only
+      -username
       
        
-   Only dump global objects (users and groups), no databases.
+        Connect as the given user.
        
       
      
 
+     
+      -W
+      
+       
+        Force a password prompt.  This should happen automatically if
+        the server requires password authentication.
+       
+      
+     
     
    
 
@@ -128,8 +148,8 @@ Postgres documentation
   
  
 
usage">
-  <span class="marked">Usage</span>
ex">
+  <span class="marked">Examples</span>
   
    To dump all databases:
 
index 246154a8df2d70179978bf56eb6a2ae87bc3bcee..5ab98fc0b3aa3760904d5622d08e3ec730110eb0 100644 (file)
@@ -1,4 +1,4 @@
-
+
 
 
  
@@ -46,7 +46,8 @@
     -x 
     -h  host 
     -p  port 
-    -u 
+    -U username 
+    -W 
     archive-file 
   
  
      
 
      
-      -u
+      -username
       
        
-   Use password authentication. Prompts for user name and password.
+        Connect as the given user.
+       
+      
+     
+
+     
+      -W
+      
+       
+        Force a password prompt.  This should happen automatically if
+        the server requires password authentication.
        
       
      
index bf453c73ab0fdc01e6403e04ea0a101fe0d792fa..1aedab8773dd39211dd8b9282db78f89a0970c5c 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *     $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.11 2001/04/25 07:03:19 pjw Exp $
+ *     $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup.h,v 1.12 2001/05/17 21:12:48 petere Exp $
  *
  * Modifications - 28-Jun-2000 - [email protected]
  *
@@ -114,6 +114,7 @@ typedef struct _restoreOptions
    char       *dbname;
    char       *pgport;
    char       *pghost;
+   char       *username;
    int         ignoreVersion;
    int         requirePassword;
 
@@ -130,12 +131,16 @@ typedef struct _restoreOptions
 
 extern void exit_horribly(Archive *AH, const char *fmt,...);
 
+extern char *
+simple_prompt(const char *prompt, int maxlen, bool echo);
+
 /* Lets the archibe know we have a DB connection to shutdown if it dies */
 
 PGconn *ConnectDatabase(Archive *AH,
                const char *dbname,
                const char *pghost,
                const char *pgport,
+               const char *username,
                const int reqPwd,
                const int ignoreVersion);
 
index 8af0133de19d4c9e55ac35927239465d13ae312a..647005f359cbb036c44ea1a0bd2d06a09d1b2b52 100644 (file)
@@ -15,7 +15,7 @@
  *
  *
  * IDENTIFICATION
- *     $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.26 2001/05/12 01:03:59 pjw Exp $
+ *     $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.27 2001/05/17 21:12:48 petere Exp $
  *
  * Modifications - 28-Jun-2000 - [email protected]
  *
@@ -180,7 +180,7 @@ RestoreArchive(Archive *AHX, RestoreOptions *ropt)
        AHX->minRemoteVersion = 070100;
        AHX->maxRemoteVersion = 999999;
 
-       ConnectDatabase(AHX, ropt->dbname, ropt->pghost, ropt->pgport,
+       ConnectDatabase(AHX, ropt->dbname, ropt->pghost, ropt->pgport, ropt->username,
                        ropt->requirePassword, ropt->ignoreVersion);
 
        /*
index fd36acba9fb57f2dfc4ac0249757584b4d1e82e7..a5357dacd858e90eb70aca812d5942bb5d38a937 100644 (file)
@@ -17,7 +17,7 @@
  *
  *
  * IDENTIFICATION
- *     $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.33 2001/05/12 01:03:59 pjw Exp $
+ *     $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.h,v 1.34 2001/05/17 21:12:48 petere Exp $
  *
  * Modifications - 28-Jun-2000 - [email protected]
  * -   Initial version.
@@ -203,11 +203,12 @@ typedef struct _archiveHandle
    CustomOutPtr CustomOutPtr;  /* Alternate script output routine */
 
    /* Stuff for direct DB connection */
-   char        username[100];
+   char       *username;
    char       *dbname;         /* Name of db for connection */
    char       *archdbname;     /* DB name *read* from archive */
    char       *pghost;
    char       *pgport;
+   bool        requirePassword;
    PGconn     *connection;
    PGconn     *blobConnection; /* Connection for BLOB xref */
    int         txActive;       /* Flag set if TX active on connection */
index a0d9a2dc5f4a0aba36f4ad7ab75a9a8de51d6e9d..bc9cf723b9148f43ab5fa728714f4856037ca517 100644 (file)
@@ -5,7 +5,7 @@
  * Implements the basic DB functions used by the archiver.
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.18 2001/04/25 07:03:19 pjw Exp $
+ *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.19 2001/05/17 21:12:48 petere Exp $
  *
  * NOTES
  *
 
 static const char *progname = "Archiver(db)";
 
-static void _prompt_for_password(char *username, char *password);
 static void _check_database_version(ArchiveHandle *AH, bool ignoreVersion);
 static PGconn *_connectDB(ArchiveHandle *AH, const char *newdbname, char *newUser);
 static int _executeSqlCommand(ArchiveHandle *AH, PGconn *conn, PQExpBuffer qry, char *desc);
 
 
-static void
-_prompt_for_password(char *username, char *password)
+/*
+ * simple_prompt
+ *
+ * Generalized function especially intended for reading in usernames and
+ * password interactively. Reads from stdin.
+ *
+ * prompt:     The prompt to print
+ * maxlen:     How many characters to accept
+ * echo:       Set to false if you want to hide what is entered (for passwords)
+ *
+ * Returns a malloc()'ed string with the input (w/o trailing newline).
+ */
+char *
+simple_prompt(const char *prompt, int maxlen, bool echo)
 {
-   char        buf[512];
    int         length;
-   int         buflen;
+   char       *destination;
 
 #ifdef HAVE_TERMIOS_H
    struct termios t_orig,
@@ -59,48 +69,40 @@ _prompt_for_password(char *username, char *password)
 
 #endif
 
-   /*
-    * Allow for forcing a specific username
-    */
-   if (strlen(username) == 0)
-   {
-       fprintf(stderr, "Username: ");
-       fflush(stderr);
-       if (fgets(username, 100, stdin) == NULL)
-           username[0] = '\0';
-       length = strlen(username);
-       if (length > 0 && username[length - 1] != '\n')
-       {
-           /* eat rest of the line */
-           do
-           {
-               if (fgets(buf, sizeof(buf), stdin) == NULL)
-                   break;
-               buflen = strlen(buf);
-           } while (buflen > 0 && buf[buflen - 1] != '\n');
-       }
-       if (length > 0 && username[length - 1] == '\n')
-           username[length - 1] = '\0';
-   }
+   destination = (char *) malloc(maxlen + 2);
+   if (!destination)
+       return NULL;
+   if (prompt)
+       fputs(prompt, stderr);
 
 #ifdef HAVE_TERMIOS_H
-   tcgetattr(0, &t);
-   t_orig = t;
-   t.c_lflag &= ~ECHO;
-   tcsetattr(0, TCSADRAIN, &t);
+   if (!echo)
+   {
+       tcgetattr(0, &t);
+       t_orig = t;
+       t.c_lflag &= ~ECHO;
+       tcsetattr(0, TCSADRAIN, &t);
+   }
 #endif
-   fprintf(stderr, "Password: ");
-   fflush(stderr);
-   if (fgets(password, 100, stdin) == NULL)
-       password[0] = '\0';
+
+   if (fgets(destination, maxlen, stdin) == NULL)
+       destination[0] = '\0';
+
 #ifdef HAVE_TERMIOS_H
-   tcsetattr(0, TCSADRAIN, &t_orig);
+   if (!echo)
+   {
+       tcsetattr(0, TCSADRAIN, &t_orig);
+       fputs("\n", stderr);
+   }
 #endif
 
-   length = strlen(password);
-   if (length > 0 && password[length - 1] != '\n')
+   length = strlen(destination);
+   if (length > 0 && destination[length - 1] != '\n')
    {
        /* eat rest of the line */
+       char        buf[128];
+       int         buflen;
+
        do
        {
            if (fgets(buf, sizeof(buf), stdin) == NULL)
@@ -108,12 +110,14 @@ _prompt_for_password(char *username, char *password)
            buflen = strlen(buf);
        } while (buflen > 0 && buf[buflen - 1] != '\n');
    }
-   if (length > 0 && password[length - 1] == '\n')
-       password[length - 1] = '\0';
+   if (length > 0 && destination[length - 1] == '\n')
+       /* remove trailing newline */
+       destination[length - 1] = '\0';
 
-   fprintf(stderr, "\n\n");
+   return destination;
 }
 
+
 static int
 _parse_version(ArchiveHandle *AH, const char* versionString)
 {
@@ -244,7 +248,8 @@ ReconnectDatabase(ArchiveHandle *AH, const char *newdbname, char *newUser)
 
    PQfinish(AH->connection);
    AH->connection = newConn;
-   strcpy(AH->username, newUser);
+   free(AH->username);
+   AH->username = strdup(newUser);
 
    return 1;
 }
@@ -257,8 +262,7 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, char *requser)
 {
    int         need_pass;
    PGconn     *newConn;
-   char        password[100];
-   char       *pwparam = NULL;
+   char       *password = NULL;
    int         badPwd = 0;
    int         noPwd = 0;
    char       *newdb;
@@ -276,20 +280,28 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, char *requser)
 
    ahlog(AH, 1, "Connecting to %s as %s\n", newdb, newuser);
 
+   if (AH->requirePassword)
+   {
+       password = simple_prompt("Password: ", 100, false);
+       if (password == NULL)
+           die_horribly(AH, "out of memory");
+   }
+
    do
    {
        need_pass = false;
        newConn = PQsetdbLogin(PQhost(AH->connection), PQport(AH->connection),
                               NULL, NULL, newdb,
-                              newuser, pwparam);
+                              newuser, password);
        if (!newConn)
            die_horribly(AH, "%s: Failed to reconnect (PQsetdbLogin failed).\n", progname);
 
        if (PQstatus(newConn) == CONNECTION_BAD)
        {
-           noPwd = (strcmp(PQerrorMessage(newConn), "fe_sendauth: no password supplied\n") == 0);
-           badPwd = (strncmp(PQerrorMessage(newConn), "Password authentication failed for user", 39)
-                     == 0);
+           noPwd = (strcmp(PQerrorMessage(newConn),
+                           "fe_sendauth: no password supplied\n") == 0);
+           badPwd = (strncmp(PQerrorMessage(newConn),
+                             "Password authentication failed for user", 39) == 0);
 
            if (noPwd || badPwd)
            {
@@ -297,34 +309,45 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, char *requser)
                if (badPwd)
                    fprintf(stderr, "Password incorrect\n");
 
-               fprintf(stderr, "Connecting to %s as %s\n", PQdb(AH->connection), newuser);
+               fprintf(stderr, "Connecting to %s as %s\n",
+                       PQdb(AH->connection), newuser);
 
                need_pass = true;
-               _prompt_for_password(newuser, password);
-               pwparam = password;
+               if (password)
+                   free(password);
+               password = simple_prompt("Password: ", 100, false);
            }
            else
-               die_horribly(AH, "%s: Could not reconnect. %s\n", progname, PQerrorMessage(newConn));
+               die_horribly(AH, "%s: Could not reconnect. %s\n",
+                            progname, PQerrorMessage(newConn));
        }
 
    } while (need_pass);
 
+   if (password)
+       free(password);
+
    return newConn;
 }
 
 
+/*
+ * Make a database connection with the given parameters.  The
+ * connection handle is returned, the parameters are stored in AHX.
+ * An interactive password prompt is automatically issued if required.
+ */
 PGconn *
 ConnectDatabase(Archive *AHX,
                const char *dbname,
                const char *pghost,
                const char *pgport,
+               const char *username,
                const int reqPwd,
                const int ignoreVersion)
 {
    ArchiveHandle *AH = (ArchiveHandle *) AHX;
-   char        connect_string[512] = "";
-   char        tmp_string[128];
-   char        password[100];
+   char       *password = NULL;
+   bool        need_pass = false;
 
    if (AH->connection)
        die_horribly(AH, "%s: already connected to database\n", progname);
@@ -335,40 +358,58 @@ ConnectDatabase(Archive *AHX,
    AH->dbname = strdup(dbname);
 
    if (pghost != NULL)
-   {
        AH->pghost = strdup(pghost);
-       sprintf(tmp_string, "host=%s ", AH->pghost);
-       strcat(connect_string, tmp_string);
-   }
    else
        AH->pghost = NULL;
 
    if (pgport != NULL)
-   {
        AH->pgport = strdup(pgport);
-       sprintf(tmp_string, "port=%s ", AH->pgport);
-       strcat(connect_string, tmp_string);
-   }
    else
        AH->pgport = NULL;
 
-   sprintf(tmp_string, "dbname=%s ", AH->dbname);
-   strcat(connect_string, tmp_string);
+   if (username != NULL)
+       AH->username = strdup(username);
+   else
+       AH->username = NULL;
 
    if (reqPwd)
    {
-       AH->username[0] = '\0';
-       _prompt_for_password(AH->username, password);
-       strcat(connect_string, "authtype=password ");
-       sprintf(tmp_string, "user=%s ", AH->username);
-       strcat(connect_string, tmp_string);
-       sprintf(tmp_string, "password=%s ", password);
-       strcat(connect_string, tmp_string);
-       MemSet(tmp_string, 0, sizeof(tmp_string));
-       MemSet(password, 0, sizeof(password));
+       password = simple_prompt("Password: ", 100, false);
+       if (password == NULL)
+           die_horribly(AH, "out of memory");
+       AH->requirePassword = true;
    }
-   AH->connection = PQconnectdb(connect_string);
-   MemSet(connect_string, 0, sizeof(connect_string));
+   else
+       AH->requirePassword = false;
+
+   /*
+    * Start the connection.  Loop until we have a password if
+    * requested by backend.
+    */
+   do
+   {
+       need_pass = false;
+       AH->connection = PQsetdbLogin(AH->pghost, AH->pgport, NULL, NULL,
+                                     AH->dbname, AH->username, password);
+
+       if (!AH->connection)
+           die_horribly(AH, "%s: Failed to connect (PQsetdbLogin failed).\n",
+                        progname);
+
+       if (PQstatus(AH->connection) == CONNECTION_BAD &&
+           strcmp(PQerrorMessage(AH->connection), "fe_sendauth: no password supplied\n") == 0 &&
+           !feof(stdin))
+       {
+           PQfinish(AH->connection);
+           need_pass = true;
+           free(password);
+           password = NULL;
+           password = simple_prompt("Password: ", 100, false);
+       }
+   } while (need_pass);
+
+   if (password)
+       free(password);
 
    /* check to see that the backend connection was successfully made */
    if (PQstatus(AH->connection) == CONNECTION_BAD)
index e7792549ca1dfcd9ecde197a7ba8f3c635f46570..f18d0972ed762070d6b4b0481e5d8c8150ac0bd2 100644 (file)
@@ -22,7 +22,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.207 2001/05/12 23:36:03 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.208 2001/05/17 21:12:48 petere Exp $
  *
  * Modifications - 6/10/96 - [email protected] - version 1.13.dhb
  *
@@ -267,8 +267,9 @@ help(const char *progname)
         "  -S, --superuser=NAME     specify the superuser user name to use in plain\n"
         "                           text format\n"
      "  -t, --table=TABLE        dump for this table only (* for all)\n"
-        "  -u, --password           use password authentication\n"
+        "  -U, --username=NAME      connect as specified database user\n"
         "  -v, --verbose            verbose\n"
+        "  -W, --password           force password prompt (should happen automatically)\n"
         "  -x, --no-acl             do not dump ACL's (grant/revoke)\n"
         "  -Z, --compress {0-9}     compression level for compressed formats\n"
        );
@@ -296,8 +297,9 @@ help(const char *progname)
         "  -S NAME                  specify the superuser user name to use in plain\n"
         "                           text format\n"
      "  -t TABLE                 dump for this table only (* for all)\n"
-        "  -u                       use password authentication\n"
+        "  -U NAME                  connect as specified database user\n"
         "  -v                       verbose\n"
+        "  -W                       force password prompt (should happen automatically)\n"
         "  -x                       do not dump ACL's (grant/revoke)\n"
         "  -Z {0-9}                 compression level for compressed formats\n"
        );
@@ -711,11 +713,12 @@ main(int argc, char **argv)
    const char *dbname = NULL;
    const char *pghost = NULL;
    const char *pgport = NULL;
+   const char *username = NULL;
    char       *tablename = NULL;
    bool        oids = false;
    TableInfo  *tblinfo;
    int         numTables;
-   bool        use_password = false;
+   bool        force_password = false;
    int         compressLevel = -1;
    bool        ignore_version = false;
    int         plainText = 0;
@@ -749,7 +752,8 @@ main(int argc, char **argv)
        {"schema-only", no_argument, NULL, 's'},
        {"superuser", required_argument, NULL, 'S'},
        {"table", required_argument, NULL, 't'},
-       {"password", no_argument, NULL, 'u'},
+       {"password", no_argument, NULL, 'W'},
+       {"username", required_argument, NULL, 'U'},
        {"verbose", no_argument, NULL, 'v'},
        {"no-acl", no_argument, NULL, 'x'},
        {"compress", required_argument, NULL, 'Z'},
@@ -796,9 +800,9 @@ main(int argc, char **argv)
    }
 
 #ifdef HAVE_GETOPT_LONG
-   while ((c = getopt_long(argc, argv, "abcCdDf:F:h:inNoOp:RsS:t:uvxzZ:V?", long_options, &optindex)) != -1)
+   while ((c = getopt_long(argc, argv, "abcCdDf:F:h:inNoOp:RsS:t:uU:vWxzZ:V?", long_options, &optindex)) != -1)
 #else
-   while ((c = getopt(argc, argv, "abcCdDf:F:h:inNoOp:RsS:t:uvxzZ:V?-")) != -1)
+   while ((c = getopt(argc, argv, "abcCdDf:F:h:inNoOp:RsS:t:uU:vWxzZ:V?-")) != -1)
 #endif
 
    {
@@ -918,13 +922,22 @@ main(int argc, char **argv)
                break;
 
            case 'u':
-               use_password = true;
+               force_password = true;
+               username = simple_prompt("Username: ", 100, true);
+               break;
+
+           case 'U':
+               username = optarg;
                break;
 
            case 'v':           /* verbose */
                g_verbose = true;
                break;
 
+           case 'W':
+               force_password = true;
+               break;
+
            case 'x':           /* skip ACL dump */
                aclsSkip = true;
                break;
@@ -1053,7 +1066,7 @@ main(int argc, char **argv)
     */
    g_fout->minRemoteVersion = 70000;
    g_fout->maxRemoteVersion = 70199;
-   g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport, use_password, ignore_version);
+   g_conn = ConnectDatabase(g_fout, dbname, pghost, pgport, username, force_password, ignore_version);
 
    /*
     * Start serializable transaction to dump consistent data
index 708e165bfeaf39eccaa87e822052d20360963310..7af04a71c360a11f320de80c6452ef2d20c2b786 100644 (file)
@@ -6,7 +6,7 @@
 # and "pg_group" tables, which belong to the whole installation rather
 # than any one individual database.
 #
-# $Header: /cvsroot/pgsql/src/bin/pg_dump/Attic/pg_dumpall.sh,v 1.11 2001/02/09 17:16:57 momjian Exp $
+# $Header: /cvsroot/pgsql/src/bin/pg_dump/Attic/pg_dumpall.sh,v 1.12 2001/05/17 21:12:49 petere Exp $
 
 CMDNAME=`basename $0`
 
@@ -47,12 +47,14 @@ fi
 #
 for prog in pg_dump psql ; do
     if [ ! -x "$PGPATH/$prog" ] ; then
+      (
         echo "The program $prog needed by $CMDNAME could not be found. It was"
         echo "expected at:"
         echo "    $PGPATH/$prog"
         echo "If this is not the correct directory, please start $CMDNAME"
         echo "with a full search path. Otherwise make sure that the program"
         echo "was installed successfully."
+      ) 1>&2
         exit 1
     fi
 done
@@ -74,11 +76,7 @@ usage=
 cleanschema=
 globals_only=
 
-#
-# Scan options. We're interested in the -h (host), -p (port),
-# -c (clean), and -g (global) options.
-# The rest we pass to pg_dump, which may or may not be useful.
-#
+
 while [ $# -gt 0 ] ; do
     case $1 in
         --help)
@@ -107,6 +105,19 @@ while [ $# -gt 0 ] ; do
         --port=*)
                 connectopts="$connectopts -p "`echo $1 | sed 's/^--port=//'`
                 ;;
+   --user|--username|-U)
+       connectopts="$connectopts -U $2"
+       shift;;
+   -U*)
+       connectopts="$connectopts $1"
+       ;;
+   --user=*|--username=*)
+       connectopts="$connectopts -U "`echo $1 | sed 's/^--user[^=]*=//'`
+       ;;
+   -W|--password)
+       connectopts="$connectopts -W"
+       ;;
+
         -c|--clean)
                 cleanschema=yes
                 pgdumpextraopts="$pgdumpextraopts -c"
@@ -126,14 +137,17 @@ if [ "$usage" ] ; then
     echo "$CMDNAME extracts a PostgreSQL database cluster into an SQL script file."
     echo
     echo "Usage:"
-    echo "  $CMDNAME [ -c ] [ -h HOSTNAME ] [ -p PORT ] [ -g ]"
+    echo "  $CMDNAME [ options... ]"
     echo
     echo "Options:"
     echo "  -c, --clean            Clean (drop) schema prior to create"
+    echo "  -g, --globals-only     Only dump global objects, no databases"
     echo "  -h, --host=HOSTNAME    Server host name"
     echo "  -p, --port=PORT        Server port number"
-    echo "  -g, --globals-only     Only dump global objects, no databases"
-    echo "Any extra options will be passed to pg_dump."
+    echo "  -U, --username=NAME    Connect as specified database user"
+    echo "  -W, --password         Force password prompts (should happen automatically)"
+    echo "Any extra options will be passed to pg_dump.  The dump will be written"
+    echo "to the standard output."
     echo
     echo "Report bugs to ."
     exit 0
@@ -155,17 +169,18 @@ echo "${BS}connect template1"
 echo "DELETE FROM pg_shadow WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');"
 echo
 
-$PSQL -d template1 -At <<__END__
+echo "connected to template1..." 1>&2
+$PSQL -d template1 -At -c "\
 SELECT
-  'CREATE USER "' || usename || '" WITH SYSID ' || usesysid
+  'CREATE USER \"' || usename || '\" WITH SYSID ' || usesysid
   || CASE WHEN passwd IS NOT NULL THEN ' PASSWORD ''' || passwd || '''' else '' end
   || CASE WHEN usecreatedb THEN ' CREATEDB'::text ELSE ' NOCREATEDB' END
   || CASE WHEN usesuper THEN ' CREATEUSER'::text ELSE ' NOCREATEUSER' END
   || CASE WHEN valuntil IS NOT NULL THEN ' VALID UNTIL '''::text
     || CAST(valuntil AS TIMESTAMP) || '''' ELSE '' END || ';'
 FROM pg_shadow
-WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');
-__END__
+WHERE usesysid <> (SELECT datdba FROM pg_database WHERE datname = 'template0');" \
+|| exit 1
 echo
 
 #
@@ -188,12 +203,15 @@ done
 test "$globals_only" = yes && exit 0
 
 
+# Save stdin for pg_dump password prompts.
+exec 4<&0
+
 # For each database, run pg_dump to dump the contents of that database.
 # We skip databases marked not datallowconn, since we'd be unable to
 # connect to them anyway (and besides, we don't want to dump template0).
 
 $PSQL -d template1 -At -F ' ' \
-  -c "SELECT datname, coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), pg_encoding_to_char(d.encoding), datistemplate, datpath FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) WHERE datallowconn;" | \
+  -c "SELECT datname, coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), pg_encoding_to_char(d.encoding), datistemplate, datpath FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) WHERE datallowconn ORDER BY 1;" | \
 while read DATABASE DBOWNER ENCODING ISTEMPLATE DBPATH; do
     echo
     echo "--"
@@ -217,7 +235,8 @@ while read DATABASE DBOWNER ENCODING ISTEMPLATE DBPATH; do
     fi
 
     echo "${BS}connect $DATABASE $DBOWNER"
-    $PGDUMP "$DATABASE"
+    echo "dumping database \"$DATABASE\"..." 1>&2
+    $PGDUMP "$DATABASE" <&4
     if [ "$?" -ne 0 ] ; then
         echo "pg_dump failed on $DATABASE, exiting" 1>&2
         exit 1
index 7b4ec4c1f1a4655f8a8b13f5375ecda7537201be..7e6ee4f8dd6128b5e753872e5c9c1fbc401efd6d 100644 (file)
@@ -34,7 +34,7 @@
  *
  *
  * IDENTIFICATION
- *     $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.19 2001/03/22 04:00:15 momjian Exp $
+ *     $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_restore.c,v 1.20 2001/05/17 21:12:49 petere Exp $
  *
  * Modifications - 28-Jun-2000 - [email protected]
  *
@@ -98,13 +98,14 @@ struct option cmdopts[] = {
    {"port", 1, NULL, 'p'},
    {"oid-order", 0, NULL, 'o'},
    {"orig-order", 0, NULL, 'N'},
-   {"password", 0, NULL, 'u'},
+   {"password", 0, NULL, 'W'},
    {"rearrange", 0, NULL, 'r'},
    {"schema-only", 0, NULL, 's'},
    {"superuser", 1, NULL, 'S'},
    {"table", 2, NULL, 't'},
    {"trigger", 2, NULL, 'T'},
    {"use-list", 1, NULL, 'L'},
+   {"username", 1, NULL, 'U'},
    {"verbose", 0, NULL, 'v'},
    {NULL, 0, NULL, 0}
 };
@@ -141,9 +142,9 @@ main(int argc, char **argv)
    }
 
 #ifdef HAVE_GETOPT_LONG
-   while ((c = getopt_long(argc, argv, "acCd:f:F:h:i:lL:NoOp:P:rRsS:t:T:uvx", cmdopts, NULL)) != EOF)
+   while ((c = getopt_long(argc, argv, "acCd:f:F:h:i:lL:NoOp:P:rRsS:t:T:uU:vWx", cmdopts, NULL)) != EOF)
 #else
-   while ((c = getopt(argc, argv, "acCd:f:F:h:i:lL:NoOp:P:rRsS:t:T:uvx")) != -1)
+   while ((c = getopt(argc, argv, "acCd:f:F:h:i:lL:NoOp:P:rRsS:t:T:uU:vWx")) != -1)
 #endif
    {
        switch (c)
@@ -236,12 +237,22 @@ main(int argc, char **argv)
                break;
 
            case 'u':
-               opts->requirePassword = 1;
+               opts->requirePassword = true;
+               opts->username = simple_prompt("Username: ", 100, true);
+               break;
+
+           case 'U':
+               opts->username = optarg;
                break;
 
            case 'v':           /* verbose */
                opts->verbose = 1;
                break;
+
+           case 'W':
+               opts->requirePassword = true;
+               break;
+
            case 'x':           /* skip ACL dump */
                opts->aclsSkip = 1;
                break;
@@ -354,8 +365,9 @@ usage(const char *progname)
         "                           disabling triggers\n"
         "  -t, --table[=TABLE]      restore this table only\n"
         "  -T, --trigger[=NAME]     restore triggers or named trigger\n"
-        "  -u, --password           use password authentication\n"
+        "  -U, --username=NAME      connect as specified database user\n"
         "  -v, --verbose            verbose\n"
+        "  -W, --password           force password prompt (should happen automatically)\n"
     "  -x, --no-acl             skip dumping of ACLs (grant/revoke)\n");
 
 #else                          /* not HAVE_GETOPT_LONG */
@@ -385,8 +397,9 @@ usage(const char *progname)
         "                           disabling triggers\n"
         "  -t NAME                  restore this table only\n"
         "  -T NAME                  restore triggers or named trigger\n"
-        "  -u                       use password authentication\n"
+        "  -U NAME                  connect as specified database user\n"
         "  -v                       verbose\n"
+        "  -W                       force password prompt (should happen automatically)\n"
     "  -x                       skip dumping of ACLs (grant/revoke)\n");
 #endif
    puts("If [file] is not supplied, then standard input is used.\n");