Skip to content

Commit 4fec55a

Browse files
committed
Fix several problems with simple_prompt() --- the nastiest being that
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.
1 parent f5a5b44 commit 4fec55a

File tree

3 files changed

+138
-86
lines changed

3 files changed

+138
-86
lines changed

contrib/dbase/dbf2pg.c

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ char *convert_charset(char *string);
5757
void usage(void);
5858
unsigned int isinteger(char *);
5959

60-
char *simple_prompt(const char *prompt, int maxlen, int echo);
60+
char *simple_prompt(const char *prompt, int maxlen, bool echo);
6161

6262

6363
unsigned int isinteger(char *buff) {
@@ -472,80 +472,109 @@ void do_inserts(PGconn *conn, char *table, dbhead *dbh) {
472472
free(query);
473473
}
474474

475+
475476
/*
476-
* This is from Postgres 7.0.3 source tarball, utility program PSQL.
477-
*
478-
* simple_prompt
477+
* simple_prompt --- borrowed from psql
479478
*
480479
* Generalized function especially intended for reading in usernames and
481-
* password interactively. Reads from stdin.
480+
* password interactively. Reads from /dev/tty or stdin/stderr.
482481
*
483482
* prompt: The prompt to print
484483
* maxlen: How many characters to accept
485484
* echo: Set to false if you want to hide what is entered (for passwords)
486485
*
487486
* Returns a malloc()'ed string with the input (w/o trailing newline).
488487
*/
489-
static int prompt_state;
488+
static bool prompt_state = false;
490489

491490
char *
492-
simple_prompt(const char *prompt, int maxlen, int echo)
491+
simple_prompt(const char *prompt, int maxlen, bool echo)
493492
{
494493
int length;
495494
char *destination;
496-
495+
FILE *termin, *termout;
497496
#ifdef HAVE_TERMIOS_H
498497
struct termios t_orig,
499498
t;
500-
501499
#endif
502500

503501
destination = (char *) malloc(maxlen + 2);
504502
if (!destination)
505503
return NULL;
506-
if (prompt)
507-
fputs(prompt, stderr);
508504

509-
prompt_state = 1;
505+
prompt_state = true; /* disable SIGINT */
506+
507+
/*
508+
* Do not try to collapse these into one "w+" mode file.
509+
* Doesn't work on some platforms (eg, HPUX 10.20).
510+
*/
511+
termin = fopen("/dev/tty", "r");
512+
termout = fopen("/dev/tty", "w");
513+
if (!termin || !termout)
514+
{
515+
if (termin)
516+
fclose(termin);
517+
if (termout)
518+
fclose(termout);
519+
termin = stdin;
520+
termout = stderr;
521+
}
510522

511523
#ifdef HAVE_TERMIOS_H
512524
if (!echo)
513525
{
514-
tcgetattr(0, &t);
526+
tcgetattr(fileno(termin), &t);
515527
t_orig = t;
516528
t.c_lflag &= ~ECHO;
517-
tcsetattr(0, TCSADRAIN, &t);
529+
tcsetattr(fileno(termin), TCSAFLUSH, &t);
518530
}
519531
#endif
520-
521-
fgets(destination, maxlen, stdin);
522-
523-
#ifdef HAVE_TERMIOS_H
524-
if (!echo)
532+
533+
if (prompt)
525534
{
526-
tcsetattr(0, TCSADRAIN, &t_orig);
527-
puts("");
535+
fputs(gettext(prompt), termout);
536+
fflush(termout);
528537
}
529-
#endif
530538

531-
prompt_state = 0;
539+
if (fgets(destination, maxlen, termin) == NULL)
540+
destination[0] = '\0';
532541

533542
length = strlen(destination);
534543
if (length > 0 && destination[length - 1] != '\n')
535544
{
536545
/* eat rest of the line */
537-
char buf[512];
546+
char buf[128];
547+
int buflen;
538548

539549
do
540550
{
541-
fgets(buf, 512, stdin);
542-
} while (buf[strlen(buf) - 1] != '\n');
551+
if (fgets(buf, sizeof(buf), termin) == NULL)
552+
break;
553+
buflen = strlen(buf);
554+
} while (buflen > 0 && buf[buflen - 1] != '\n');
543555
}
544556

545557
if (length > 0 && destination[length - 1] == '\n')
546558
/* remove trailing newline */
547559
destination[length - 1] = '\0';
548560

561+
#ifdef HAVE_TERMIOS_H
562+
if (!echo)
563+
{
564+
tcsetattr(fileno(termin), TCSAFLUSH, &t_orig);
565+
fputs("\n", termout);
566+
fflush(termout);
567+
}
568+
#endif
569+
570+
if (termin != stdin)
571+
{
572+
fclose(termin);
573+
fclose(termout);
574+
}
575+
576+
prompt_state = false; /* SIGINT okay again */
577+
549578
return destination;
550579
}
551580

src/bin/pg_dump/pg_backup_db.c

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Implements the basic DB functions used by the archiver.
66
*
77
* IDENTIFICATION
8-
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.27 2001/10/15 16:40:27 momjian Exp $
8+
* $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_db.c,v 1.28 2001/10/18 21:57:11 tgl Exp $
99
*
1010
* NOTES
1111
*
@@ -46,7 +46,7 @@ static void notice_processor(void *arg, const char *message);
4646

4747

4848
/*
49-
* simple_prompt
49+
* simple_prompt --- borrowed from psql
5050
*
5151
* Generalized function especially intended for reading in usernames and
5252
* password interactively. Reads from /dev/tty or stdin/stderr.
@@ -57,15 +57,14 @@ static void notice_processor(void *arg, const char *message);
5757
*
5858
* Returns a malloc()'ed string with the input (w/o trailing newline).
5959
*/
60-
static bool prompt_state;
60+
static bool prompt_state = false;
6161

6262
char *
6363
simple_prompt(const char *prompt, int maxlen, bool echo)
6464
{
6565
int length;
6666
char *destination;
67-
static FILE *termin = NULL, *termout;
68-
67+
FILE *termin, *termout;
6968
#ifdef HAVE_TERMIOS_H
7069
struct termios t_orig,
7170
t;
@@ -75,22 +74,22 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
7574
if (!destination)
7675
return NULL;
7776

78-
prompt_state = true;
77+
prompt_state = true; /* disable SIGINT */
7978

80-
/* initialize the streams */
81-
if (!termin)
82-
{
83-
if ((termin = termout = fopen("/dev/tty", "w+")) == NULL)
84-
{
85-
termin = stdin;
86-
termout = stderr;
87-
}
88-
}
89-
90-
if (prompt)
79+
/*
80+
* Do not try to collapse these into one "w+" mode file.
81+
* Doesn't work on some platforms (eg, HPUX 10.20).
82+
*/
83+
termin = fopen("/dev/tty", "r");
84+
termout = fopen("/dev/tty", "w");
85+
if (!termin || !termout)
9186
{
92-
fputs(gettext(prompt), termout);
93-
rewind(termout); /* does flush too */
87+
if (termin)
88+
fclose(termin);
89+
if (termout)
90+
fclose(termout);
91+
termin = stdin;
92+
termout = stderr;
9493
}
9594

9695
#ifdef HAVE_TERMIOS_H
@@ -99,22 +98,18 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
9998
tcgetattr(fileno(termin), &t);
10099
t_orig = t;
101100
t.c_lflag &= ~ECHO;
102-
tcsetattr(fileno(termin), TCSADRAIN, &t);
101+
tcsetattr(fileno(termin), TCSAFLUSH, &t);
103102
}
104103
#endif
105-
106-
if (fgets(destination, maxlen, termin) == NULL)
107-
destination[0] = '\0';
108-
109-
#ifdef HAVE_TERMIOS_H
110-
if (!echo)
104+
105+
if (prompt)
111106
{
112-
tcsetattr(fileno(termin), TCSADRAIN, &t_orig);
113-
fputs("\n", termout);
107+
fputs(gettext(prompt), termout);
108+
fflush(termout);
114109
}
115-
#endif
116110

117-
prompt_state = false;
111+
if (fgets(destination, maxlen, termin) == NULL)
112+
destination[0] = '\0';
118113

119114
length = strlen(destination);
120115
if (length > 0 && destination[length - 1] != '\n')
@@ -135,11 +130,27 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
135130
/* remove trailing newline */
136131
destination[length - 1] = '\0';
137132

133+
#ifdef HAVE_TERMIOS_H
134+
if (!echo)
135+
{
136+
tcsetattr(fileno(termin), TCSAFLUSH, &t_orig);
137+
fputs("\n", termout);
138+
fflush(termout);
139+
}
140+
#endif
141+
142+
if (termin != stdin)
143+
{
144+
fclose(termin);
145+
fclose(termout);
146+
}
147+
148+
prompt_state = false; /* SIGINT okay again */
149+
138150
return destination;
139151
}
140152

141153

142-
143154
static int
144155
_parse_version(ArchiveHandle *AH, const char* versionString)
145156
{

src/bin/psql/common.c

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright 2000 by PostgreSQL Global Development Group
55
*
6-
* $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.35 2001/10/15 16:40:27 momjian Exp $
6+
* $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.36 2001/10/18 21:57:11 tgl Exp $
77
*/
88
#include "postgres_fe.h"
99

@@ -169,15 +169,14 @@ NoticeProcessor(void *arg, const char *message)
169169
*
170170
* Returns a malloc()'ed string with the input (w/o trailing newline).
171171
*/
172-
static bool prompt_state;
172+
static bool prompt_state = false;
173173

174174
char *
175175
simple_prompt(const char *prompt, int maxlen, bool echo)
176176
{
177177
int length;
178178
char *destination;
179-
static FILE *termin = NULL, *termout;
180-
179+
FILE *termin, *termout;
181180
#ifdef HAVE_TERMIOS_H
182181
struct termios t_orig,
183182
t;
@@ -187,22 +186,22 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
187186
if (!destination)
188187
return NULL;
189188

190-
prompt_state = true;
189+
prompt_state = true; /* disable SIGINT */
191190

192-
/* initialize the streams */
193-
if (!termin)
194-
{
195-
if ((termin = termout = fopen("/dev/tty", "w+")) == NULL)
196-
{
197-
termin = stdin;
198-
termout = stderr;
199-
}
200-
}
201-
202-
if (prompt)
191+
/*
192+
* Do not try to collapse these into one "w+" mode file.
193+
* Doesn't work on some platforms (eg, HPUX 10.20).
194+
*/
195+
termin = fopen("/dev/tty", "r");
196+
termout = fopen("/dev/tty", "w");
197+
if (!termin || !termout)
203198
{
204-
fputs(gettext(prompt), termout);
205-
rewind(termout); /* does flush too */
199+
if (termin)
200+
fclose(termin);
201+
if (termout)
202+
fclose(termout);
203+
termin = stdin;
204+
termout = stderr;
206205
}
207206

208207
#ifdef HAVE_TERMIOS_H
@@ -211,22 +210,18 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
211210
tcgetattr(fileno(termin), &t);
212211
t_orig = t;
213212
t.c_lflag &= ~ECHO;
214-
tcsetattr(fileno(termin), TCSADRAIN, &t);
213+
tcsetattr(fileno(termin), TCSAFLUSH, &t);
215214
}
216215
#endif
217-
218-
if (fgets(destination, maxlen, termin) == NULL)
219-
destination[0] = '\0';
220-
221-
#ifdef HAVE_TERMIOS_H
222-
if (!echo)
216+
217+
if (prompt)
223218
{
224-
tcsetattr(fileno(termin), TCSADRAIN, &t_orig);
225-
fputs("\n", termout);
219+
fputs(gettext(prompt), termout);
220+
fflush(termout);
226221
}
227-
#endif
228222

229-
prompt_state = false;
223+
if (fgets(destination, maxlen, termin) == NULL)
224+
destination[0] = '\0';
230225

231226
length = strlen(destination);
232227
if (length > 0 && destination[length - 1] != '\n')
@@ -247,6 +242,23 @@ simple_prompt(const char *prompt, int maxlen, bool echo)
247242
/* remove trailing newline */
248243
destination[length - 1] = '\0';
249244

245+
#ifdef HAVE_TERMIOS_H
246+
if (!echo)
247+
{
248+
tcsetattr(fileno(termin), TCSAFLUSH, &t_orig);
249+
fputs("\n", termout);
250+
fflush(termout);
251+
}
252+
#endif
253+
254+
if (termin != stdin)
255+
{
256+
fclose(termin);
257+
fclose(termout);
258+
}
259+
260+
prompt_state = false; /* SIGINT okay again */
261+
250262
return destination;
251263
}
252264

0 commit comments

Comments
 (0)