]> granicus.if.org Git - postgresql/commitdiff
Clean up password prompting logic in streamutil.c.
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 15 Nov 2013 22:27:41 +0000 (17:27 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 15 Nov 2013 22:27:41 +0000 (17:27 -0500)
The previous coding was fairly unreadable and drew double-free warnings
from clang.  I believe the double free was actually not reachable, because
PQconnectionNeedsPassword is coded to not return true if a password was
provided, so that the loop can't iterate more than twice.  Nonetheless
it seems worth rewriting.  No back-patch since this is just cosmetic.

src/bin/pg_basebackup/streamutil.c

index 1dfb80f4a72a5e3d6e2fada9d24e25f8e6f93829..67917512e25cebca0ce26e0101dbb39d9cfea50d 100644 (file)
@@ -40,8 +40,8 @@ GetConnection(void)
        int                     i;
        const char **keywords;
        const char **values;
-       char       *password = NULL;
        const char *tmpparam;
+       bool            need_password;
        PQconninfoOption *conn_opts = NULL;
        PQconninfoOption *conn_opt;
        char       *err_msg = NULL;
@@ -114,27 +114,30 @@ GetConnection(void)
                i++;
        }
 
+       /* If -W was given, force prompt for password, but only the first time */
+       need_password = (dbgetpassword == 1 && dbpassword == NULL);
+
        while (true)
        {
-               if (password)
-                       free(password);
+               /* Get a new password if appropriate */
+               if (need_password)
+               {
+                       if (dbpassword)
+                               free(dbpassword);
+                       dbpassword = simple_prompt(_("Password: "), 100, false);
+                       need_password = false;
+               }
 
+               /* Use (or reuse, on a subsequent connection) password if we have it */
                if (dbpassword)
                {
-                       /*
-                        * We've saved a password when a previous connection succeeded,
-                        * meaning this is the call for a second session to the same
-                        * database, so just forcibly reuse that password.
-                        */
                        keywords[i] = "password";
                        values[i] = dbpassword;
-                       dbgetpassword = -1; /* Don't try again if this fails */
                }
-               else if (dbgetpassword == 1)
+               else
                {
-                       password = simple_prompt(_("Password: "), 100, false);
-                       keywords[i] = "password";
-                       values[i] = password;
+                       keywords[i] = NULL;
+                       values[i] = NULL;
                }
 
                tmpconn = PQconnectdbParams(keywords, values, true);
@@ -150,63 +153,62 @@ GetConnection(void)
                        exit(1);
                }
 
+               /* If we need a password and -w wasn't given, loop back and get one */
                if (PQstatus(tmpconn) == CONNECTION_BAD &&
                        PQconnectionNeedsPassword(tmpconn) &&
                        dbgetpassword != -1)
                {
-                       dbgetpassword = 1;      /* ask for password next time */
-                       PQfinish(tmpconn);
-                       continue;
-               }
-
-               if (PQstatus(tmpconn) != CONNECTION_OK)
-               {
-                       fprintf(stderr, _("%s: could not connect to server: %s\n"),
-                                       progname, PQerrorMessage(tmpconn));
                        PQfinish(tmpconn);
-                       free(values);
-                       free(keywords);
-                       if (conn_opts)
-                               PQconninfoFree(conn_opts);
-                       return NULL;
+                       need_password = true;
                }
+               else
+                       break;
+       }
 
-               /* Connection ok! */
+       if (PQstatus(tmpconn) != CONNECTION_OK)
+       {
+               fprintf(stderr, _("%s: could not connect to server: %s\n"),
+                               progname, PQerrorMessage(tmpconn));
+               PQfinish(tmpconn);
                free(values);
                free(keywords);
                if (conn_opts)
                        PQconninfoFree(conn_opts);
+               return NULL;
+       }
 
-               /*
-                * Ensure we have the same value of integer timestamps as the server
-                * we are connecting to.
-                */
-               tmpparam = PQparameterStatus(tmpconn, "integer_datetimes");
-               if (!tmpparam)
-               {
-                       fprintf(stderr,
-                                       _("%s: could not determine server setting for integer_datetimes\n"),
-                                       progname);
-                       PQfinish(tmpconn);
-                       exit(1);
-               }
+       /* Connection ok! */
+       free(values);
+       free(keywords);
+       if (conn_opts)
+               PQconninfoFree(conn_opts);
+
+       /*
+        * Ensure we have the same value of integer timestamps as the server we
+        * are connecting to.
+        */
+       tmpparam = PQparameterStatus(tmpconn, "integer_datetimes");
+       if (!tmpparam)
+       {
+               fprintf(stderr,
+                _("%s: could not determine server setting for integer_datetimes\n"),
+                               progname);
+               PQfinish(tmpconn);
+               exit(1);
+       }
 
 #ifdef HAVE_INT64_TIMESTAMP
-               if (strcmp(tmpparam, "on") != 0)
+       if (strcmp(tmpparam, "on") != 0)
 #else
-               if (strcmp(tmpparam, "off") != 0)
+       if (strcmp(tmpparam, "off") != 0)
 #endif
-               {
-                       fprintf(stderr,
+       {
+               fprintf(stderr,
                         _("%s: integer_datetimes compile flag does not match server\n"),
-                                       progname);
-                       PQfinish(tmpconn);
-                       exit(1);
-               }
-
-               /* Store the password for next run */
-               if (password)
-                       dbpassword = password;
-               return tmpconn;
+                               progname);
+               PQfinish(tmpconn);
+               exit(1);
        }
+
+       return tmpconn;
 }