OSDN Git Service

Fix several problems with simple_prompt() --- the nastiest being that
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 18 Oct 2001 21:57:11 +0000 (21:57 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 18 Oct 2001 21:57:11 +0000 (21:57 +0000)
the entered password would get echoed on some platforms, eg HPUX.
We have enough copies of this code that I'm thinking it ought to be
moved into libpq, but that's a task for another day.

contrib/dbase/dbf2pg.c
src/bin/pg_dump/pg_backup_db.c
src/bin/psql/common.c

index c87c743..839bb72 100644 (file)
@@ -57,7 +57,7 @@ char *convert_charset(char *string);
 void usage(void);
 unsigned int isinteger(char *);
 
-char *simple_prompt(const char *prompt, int maxlen, int echo);
+char *simple_prompt(const char *prompt, int maxlen, bool echo);
 
 
 unsigned int isinteger(char *buff) {
@@ -472,13 +472,12 @@ void do_inserts(PGconn *conn, char *table, dbhead *dbh) {
        free(query);
 }
 
+
 /*
- * This is from Postgres 7.0.3 source tarball, utility program PSQL.
- *
- * simple_prompt
+ * simple_prompt  --- borrowed from psql
  *
  * Generalized function especially intended for reading in usernames and
- * password interactively. Reads from stdin.
+ * password interactively. Reads from /dev/tty or stdin/stderr.
  *
  * prompt:             The prompt to print
  * maxlen:             How many characters to accept
@@ -486,66 +485,96 @@ void do_inserts(PGconn *conn, char *table, dbhead *dbh) {
  *
  * Returns a malloc()'ed string with the input (w/o trailing newline).
  */
-static int prompt_state;
+static bool prompt_state = false;
 
 char *
-simple_prompt(const char *prompt, int maxlen, int echo)
+simple_prompt(const char *prompt, int maxlen, bool echo)
 {
        int                     length;
        char       *destination;
-
+       FILE *termin, *termout;
 #ifdef HAVE_TERMIOS_H
        struct termios t_orig,
                                t;
-
 #endif
 
        destination = (char *) malloc(maxlen + 2);
        if (!destination)
                return NULL;
-       if (prompt)
-               fputs(prompt, stderr);
 
-       prompt_state = 1;
+       prompt_state = true;            /* disable SIGINT */
+
+       /*
+        * Do not try to collapse these into one "w+" mode file.
+        * Doesn't work on some platforms (eg, HPUX 10.20).
+        */
+       termin = fopen("/dev/tty", "r");
+       termout = fopen("/dev/tty", "w");
+       if (!termin || !termout)
+       {
+               if (termin)
+                       fclose(termin);
+               if (termout)
+                       fclose(termout);
+               termin = stdin;
+               termout = stderr;
+       }
 
 #ifdef HAVE_TERMIOS_H
        if (!echo)
        {
-               tcgetattr(0, &t);
+               tcgetattr(fileno(termin), &t);
                t_orig = t;
                t.c_lflag &= ~ECHO;
-               tcsetattr(0, TCSADRAIN, &t);
+               tcsetattr(fileno(termin), TCSAFLUSH, &t);
        }
 #endif
-
-       fgets(destination, maxlen, stdin);
-
-#ifdef HAVE_TERMIOS_H
-       if (!echo)
+       
+       if (prompt)
        {
-               tcsetattr(0, TCSADRAIN, &t_orig);
-               puts("");
+               fputs(gettext(prompt), termout);
+               fflush(termout);
        }
-#endif
 
-       prompt_state = 0;
+       if (fgets(destination, maxlen, termin) == NULL)
+               destination[0] = '\0';
 
        length = strlen(destination);
        if (length > 0 && destination[length - 1] != '\n')
        {
                /* eat rest of the line */
-               char            buf[512];
+               char            buf[128];
+               int                     buflen;
 
                do
                {
-                       fgets(buf, 512, stdin);
-               } while (buf[strlen(buf) - 1] != '\n');
+                       if (fgets(buf, sizeof(buf), termin) == NULL)
+                               break;
+                       buflen = strlen(buf);
+               } while (buflen > 0 && buf[buflen - 1] != '\n');
        }
 
        if (length > 0 && destination[length - 1] == '\n')
                /* remove trailing newline */
                destination[length - 1] = '\0';
 
+#ifdef HAVE_TERMIOS_H
+       if (!echo)
+       {
+               tcsetattr(fileno(termin), TCSAFLUSH, &t_orig);
+               fputs("\n", termout);
+               fflush(termout);
+       }
+#endif
+
+       if (termin != stdin)
+       {
+               fclose(termin);
+               fclose(termout);
+       }
+
+       prompt_state = false;           /* SIGINT okay again */
+
        return destination;
 }
 
index 3acf191..0749c24 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.27 2001/10/15 16:40:27 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.28 2001/10/18 21:57:11 tgl Exp $
  *
  * NOTES
  *
@@ -46,7 +46,7 @@ static void notice_processor(void *arg, const char *message);
 
 
 /*
- * simple_prompt
+ * simple_prompt  --- borrowed from psql
  *
  * Generalized function especially intended for reading in usernames and
  * password interactively. Reads from /dev/tty or stdin/stderr.
@@ -57,15 +57,14 @@ static void notice_processor(void *arg, const char *message);
  *
  * Returns a malloc()'ed string with the input (w/o trailing newline).
  */
-static bool prompt_state;
+static bool prompt_state = false;
 
 char *
 simple_prompt(const char *prompt, int maxlen, bool echo)
 {
        int                     length;
        char       *destination;
-       static FILE *termin = NULL, *termout;
-
+       FILE *termin, *termout;
 #ifdef HAVE_TERMIOS_H
        struct termios t_orig,
                                t;
@@ -75,22 +74,22 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
        if (!destination)
                return NULL;
 
-       prompt_state = true;
+       prompt_state = true;            /* disable SIGINT */
 
-       /* initialize the streams */
-       if (!termin)
-       {
-               if ((termin = termout = fopen("/dev/tty", "w+")) == NULL)
-               {
-                       termin = stdin;
-                       termout = stderr;
-               }
-       }
-       
-       if (prompt)
+       /*
+        * Do not try to collapse these into one "w+" mode file.
+        * Doesn't work on some platforms (eg, HPUX 10.20).
+        */
+       termin = fopen("/dev/tty", "r");
+       termout = fopen("/dev/tty", "w");
+       if (!termin || !termout)
        {
-               fputs(gettext(prompt), termout);
-               rewind(termout); /* does flush too */
+               if (termin)
+                       fclose(termin);
+               if (termout)
+                       fclose(termout);
+               termin = stdin;
+               termout = stderr;
        }
 
 #ifdef HAVE_TERMIOS_H
@@ -99,22 +98,18 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
                tcgetattr(fileno(termin), &t);
                t_orig = t;
                t.c_lflag &= ~ECHO;
-               tcsetattr(fileno(termin), TCSADRAIN, &t);
+               tcsetattr(fileno(termin), TCSAFLUSH, &t);
        }
 #endif
-
-       if (fgets(destination, maxlen, termin) == NULL)
-               destination[0] = '\0';
-
-#ifdef HAVE_TERMIOS_H
-       if (!echo)
+       
+       if (prompt)
        {
-               tcsetattr(fileno(termin), TCSADRAIN, &t_orig);
-               fputs("\n", termout);
+               fputs(gettext(prompt), termout);
+               fflush(termout);
        }
-#endif
 
-       prompt_state = false;
+       if (fgets(destination, maxlen, termin) == NULL)
+               destination[0] = '\0';
 
        length = strlen(destination);
        if (length > 0 && destination[length - 1] != '\n')
@@ -135,11 +130,27 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
                /* remove trailing newline */
                destination[length - 1] = '\0';
 
+#ifdef HAVE_TERMIOS_H
+       if (!echo)
+       {
+               tcsetattr(fileno(termin), TCSAFLUSH, &t_orig);
+               fputs("\n", termout);
+               fflush(termout);
+       }
+#endif
+
+       if (termin != stdin)
+       {
+               fclose(termin);
+               fclose(termout);
+       }
+
+       prompt_state = false;           /* SIGINT okay again */
+
        return destination;
 }
 
 
-
 static int
 _parse_version(ArchiveHandle *AH, const char* versionString)
 {
index b057218..336d813 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.35 2001/10/15 16:40:27 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.36 2001/10/18 21:57:11 tgl Exp $
  */
 #include "postgres_fe.h"
 
@@ -169,15 +169,14 @@ NoticeProcessor(void *arg, const char *message)
  *
  * Returns a malloc()'ed string with the input (w/o trailing newline).
  */
-static bool prompt_state;
+static bool prompt_state = false;
 
 char *
 simple_prompt(const char *prompt, int maxlen, bool echo)
 {
        int                     length;
        char       *destination;
-       static FILE *termin = NULL, *termout;
-
+       FILE *termin, *termout;
 #ifdef HAVE_TERMIOS_H
        struct termios t_orig,
                                t;
@@ -187,22 +186,22 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
        if (!destination)
                return NULL;
 
-       prompt_state = true;
+       prompt_state = true;            /* disable SIGINT */
 
-       /* initialize the streams */
-       if (!termin)
-       {
-               if ((termin = termout = fopen("/dev/tty", "w+")) == NULL)
-               {
-                       termin = stdin;
-                       termout = stderr;
-               }
-       }
-       
-       if (prompt)
+       /*
+        * Do not try to collapse these into one "w+" mode file.
+        * Doesn't work on some platforms (eg, HPUX 10.20).
+        */
+       termin = fopen("/dev/tty", "r");
+       termout = fopen("/dev/tty", "w");
+       if (!termin || !termout)
        {
-               fputs(gettext(prompt), termout);
-               rewind(termout); /* does flush too */
+               if (termin)
+                       fclose(termin);
+               if (termout)
+                       fclose(termout);
+               termin = stdin;
+               termout = stderr;
        }
 
 #ifdef HAVE_TERMIOS_H
@@ -211,22 +210,18 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
                tcgetattr(fileno(termin), &t);
                t_orig = t;
                t.c_lflag &= ~ECHO;
-               tcsetattr(fileno(termin), TCSADRAIN, &t);
+               tcsetattr(fileno(termin), TCSAFLUSH, &t);
        }
 #endif
-
-       if (fgets(destination, maxlen, termin) == NULL)
-               destination[0] = '\0';
-
-#ifdef HAVE_TERMIOS_H
-       if (!echo)
+       
+       if (prompt)
        {
-               tcsetattr(fileno(termin), TCSADRAIN, &t_orig);
-               fputs("\n", termout);
+               fputs(gettext(prompt), termout);
+               fflush(termout);
        }
-#endif
 
-       prompt_state = false;
+       if (fgets(destination, maxlen, termin) == NULL)
+               destination[0] = '\0';
 
        length = strlen(destination);
        if (length > 0 && destination[length - 1] != '\n')
@@ -247,6 +242,23 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
                /* remove trailing newline */
                destination[length - 1] = '\0';
 
+#ifdef HAVE_TERMIOS_H
+       if (!echo)
+       {
+               tcsetattr(fileno(termin), TCSAFLUSH, &t_orig);
+               fputs("\n", termout);
+               fflush(termout);
+       }
+#endif
+
+       if (termin != stdin)
+       {
+               fclose(termin);
+               fclose(termout);
+       }
+
+       prompt_state = false;           /* SIGINT okay again */
+
        return destination;
 }