Fix several problems with simple_prompt() --- the nastiest being that
authorTom Lane
Thu, 18 Oct 2001 21:57:11 +0000 (21:57 +0000)
committerTom Lane
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 c87c743e09670058bb89899cf617f0231fb8548a..839bb7211f4bebea96259f780e7892822e2c4eee 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 3acf191b0b048f57f36f1ecc98f2aedd18c2a826..0749c24bb523a2e7cf98faacefb51fd1ea126dba 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 b0572186d8bc25244e04f59e743f3e1fb57348db..336d8138783c951226251930b27fcda3e6345044 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;
 }