diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml index 160cb0bba1..ba1b6c9b21 100644 --- a/doc/src/sgml/backup.sgml +++ b/doc/src/sgml/backup.sgml @@ -1,4 +1,4 @@ - + Backup and Restore @@ -61,11 +61,10 @@ pg_dump dbname > 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 -U option or set the + environment variable PGUSER. Remember that + pg_dump connections are subject to the normal + client authentication mechanisms (which are described in ). @@ -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. - diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml index ddcf5db63f..be2afefc8f 100644 --- a/doc/src/sgml/ref/pg_dump.sgml +++ b/doc/src/sgml/ref/pg_dump.sgml @@ -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 + -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. diff --git a/doc/src/sgml/ref/pg_dumpall.sgml b/doc/src/sgml/ref/pg_dumpall.sgml index aa2c2a8827..bf35106c67 100644 --- a/doc/src/sgml/ref/pg_dumpall.sgml +++ b/doc/src/sgml/ref/pg_dumpall.sgml @@ -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 + -U 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 + + Examples To dump all databases: diff --git a/doc/src/sgml/ref/pg_restore.sgml b/doc/src/sgml/ref/pg_restore.sgml index 246154a8df..5ab98fc0b3 100644 --- a/doc/src/sgml/ref/pg_restore.sgml +++ b/doc/src/sgml/ref/pg_restore.sgml @@ -1,4 +1,4 @@ - + @@ -46,7 +46,8 @@ -x -h host -p port - -u + -U username + -W archive-file @@ -448,10 +449,20 @@ - -u + -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. diff --git a/src/bin/pg_dump/pg_backup.h b/src/bin/pg_dump/pg_backup.h index bf453c73ab..1aedab8773 100644 --- a/src/bin/pg_dump/pg_backup.h +++ b/src/bin/pg_dump/pg_backup.h @@ -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 - pjw@rhyme.com.au * @@ -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); diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 8af0133de1..647005f359 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -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 - pjw@rhyme.com.au * @@ -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); /* diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h index fd36acba9f..a5357dacd8 100644 --- a/src/bin/pg_dump/pg_backup_archiver.h +++ b/src/bin/pg_dump/pg_backup_archiver.h @@ -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 - pjw@rhyme.com.au * - 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 */ diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c index a0d9a2dc5f..bc9cf723b9 100644 --- a/src/bin/pg_dump/pg_backup_db.c +++ b/src/bin/pg_dump/pg_backup_db.c @@ -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 * @@ -40,18 +40,28 @@ 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) + destination = (char *) malloc(maxlen + 2); + if (!destination) + return NULL; + if (prompt) + fputs(prompt, stderr); + +#ifdef HAVE_TERMIOS_H + if (!echo) { - 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'; + tcgetattr(0, &t); + t_orig = t; + t.c_lflag &= ~ECHO; + tcsetattr(0, TCSADRAIN, &t); } - -#ifdef HAVE_TERMIOS_H - 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'; -#ifdef HAVE_TERMIOS_H - tcsetattr(0, TCSADRAIN, &t_orig); #endif - length = strlen(password); - if (length > 0 && password[length - 1] != '\n') + if (fgets(destination, maxlen, stdin) == NULL) + destination[0] = '\0'; + +#ifdef HAVE_TERMIOS_H + if (!echo) + { + tcsetattr(0, TCSADRAIN, &t_orig); + fputs("\n", stderr); + } +#endif + + 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) diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index e7792549ca..f18d0972ed 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -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 - dave@bensoft.com - 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 diff --git a/src/bin/pg_dump/pg_dumpall.sh b/src/bin/pg_dump/pg_dumpall.sh index 708e165bfe..7af04a71c3 100644 --- a/src/bin/pg_dump/pg_dumpall.sh +++ b/src/bin/pg_dump/pg_dumpall.sh @@ -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 diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c index 7b4ec4c1f1..7e6ee4f8dd 100644 --- a/src/bin/pg_dump/pg_restore.c +++ b/src/bin/pg_dump/pg_restore.c @@ -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 - pjw@rhyme.com.au * @@ -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");