aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/libpq/auth.c2
-rw-r--r--src/bin/initdb/initdb.c21
-rw-r--r--src/bin/pg_basebackup/streamutil.c13
-rw-r--r--src/bin/pg_dump/pg_backup_db.c28
-rw-r--r--src/bin/pg_dump/pg_dumpall.c18
-rw-r--r--src/bin/pgbench/pgbench.c11
-rw-r--r--src/bin/psql/command.c22
-rw-r--r--src/bin/psql/startup.c14
-rw-r--r--src/bin/scripts/common.c34
-rw-r--r--src/bin/scripts/createuser.c18
-rw-r--r--src/bin/scripts/dropuser.c6
-rw-r--r--src/common/Makefile4
-rw-r--r--src/common/pg_get_line.c85
-rw-r--r--src/common/saslprep.c18
-rw-r--r--src/common/sprompt.c (renamed from src/port/sprompt.c)45
-rw-r--r--src/include/common/string.h7
-rw-r--r--src/include/port.h4
-rw-r--r--src/port/Makefile3
-rw-r--r--src/tools/msvc/Mkvcbuild.pm6
19 files changed, 209 insertions, 150 deletions
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 02b6c3f127c..36565df4fc1 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -698,7 +698,7 @@ recv_password_packet(Port *port)
}
initStringInfo(&buf);
- if (pq_getmessage(&buf, 1000)) /* receive password */
+ if (pq_getmessage(&buf, 0)) /* receive password */
{
/* EOF - pq_getmessage already logged a suitable message */
pfree(buf.data);
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 786672b1b65..73ddf408654 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -67,6 +67,7 @@
#include "common/file_utils.h"
#include "common/logging.h"
#include "common/restricted_token.h"
+#include "common/string.h"
#include "common/username.h"
#include "fe_utils/string_utils.h"
#include "getaddrinfo.h"
@@ -1481,23 +1482,25 @@ setup_auth(FILE *cmdfd)
static void
get_su_pwd(void)
{
- char pwd1[100];
- char pwd2[100];
+ char *pwd1;
if (pwprompt)
{
/*
* Read password from terminal
*/
+ char *pwd2;
+
printf("\n");
fflush(stdout);
- simple_prompt("Enter new superuser password: ", pwd1, sizeof(pwd1), false);
- simple_prompt("Enter it again: ", pwd2, sizeof(pwd2), false);
+ pwd1 = simple_prompt("Enter new superuser password: ", false);
+ pwd2 = simple_prompt("Enter it again: ", false);
if (strcmp(pwd1, pwd2) != 0)
{
fprintf(stderr, _("Passwords didn't match.\n"));
exit(1);
}
+ free(pwd2);
}
else
{
@@ -1510,7 +1513,6 @@ get_su_pwd(void)
* for now.
*/
FILE *pwf = fopen(pwfilename, "r");
- int i;
if (!pwf)
{
@@ -1518,7 +1520,8 @@ get_su_pwd(void)
pwfilename);
exit(1);
}
- if (!fgets(pwd1, sizeof(pwd1), pwf))
+ pwd1 = pg_get_line(pwf);
+ if (!pwd1)
{
if (ferror(pwf))
pg_log_error("could not read password from file \"%s\": %m",
@@ -1530,12 +1533,10 @@ get_su_pwd(void)
}
fclose(pwf);
- i = strlen(pwd1);
- while (i > 0 && (pwd1[i - 1] == '\r' || pwd1[i - 1] == '\n'))
- pwd1[--i] = '\0';
+ (void) pg_strip_crlf(pwd1);
}
- superuser_password = pg_strdup(pwd1);
+ superuser_password = pwd1;
}
/*
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index c08003e7f2c..be653ebb2d9 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -22,6 +22,7 @@
#include "common/fe_memutils.h"
#include "common/file_perm.h"
#include "common/logging.h"
+#include "common/string.h"
#include "datatype/timestamp.h"
#include "port/pg_bswap.h"
#include "pqexpbuffer.h"
@@ -49,8 +50,7 @@ char *dbuser = NULL;
char *dbport = NULL;
char *dbname = NULL;
int dbgetpassword = 0; /* 0=auto, -1=never, 1=always */
-static bool have_password = false;
-static char password[100];
+static char *password = NULL;
PGconn *conn = NULL;
/*
@@ -150,20 +150,21 @@ GetConnection(void)
}
/* If -W was given, force prompt for password, but only the first time */
- need_password = (dbgetpassword == 1 && !have_password);
+ need_password = (dbgetpassword == 1 && !password);
do
{
/* Get a new password if appropriate */
if (need_password)
{
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
+ if (password)
+ free(password);
+ password = simple_prompt("Password: ", false);
need_password = false;
}
/* Use (or reuse, on a subsequent connection) password if we have it */
- if (have_password)
+ if (password)
{
keywords[i] = "password";
values[i] = password;
diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
index 94af11b80a3..12899e26e29 100644
--- a/src/bin/pg_dump/pg_backup_db.c
+++ b/src/bin/pg_dump/pg_backup_db.c
@@ -18,6 +18,7 @@
#endif
#include "common/connect.h"
+#include "common/string.h"
#include "dumputils.h"
#include "fe_utils/string_utils.h"
#include "parallel.h"
@@ -122,7 +123,6 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
const char *newdb;
const char *newuser;
char *password;
- char passbuf[100];
bool new_pass;
if (!reqdb)
@@ -141,10 +141,7 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
password = AH->savedPassword;
if (AH->promptPassword == TRI_YES && password == NULL)
- {
- simple_prompt("Password: ", passbuf, sizeof(passbuf), false);
- password = passbuf;
- }
+ password = simple_prompt("Password: ", false);
initPQExpBuffer(&connstr);
appendPQExpBufferStr(&connstr, "dbname=");
@@ -191,8 +188,9 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
if (AH->promptPassword != TRI_NO)
{
- simple_prompt("Password: ", passbuf, sizeof(passbuf), false);
- password = passbuf;
+ if (password && password != AH->savedPassword)
+ free(password);
+ password = simple_prompt("Password: ", false);
}
else
fatal("connection needs password");
@@ -201,6 +199,9 @@ _connectDB(ArchiveHandle *AH, const char *reqdb, const char *requser)
}
} while (new_pass);
+ if (password && password != AH->savedPassword)
+ free(password);
+
/*
* We want to remember connection's actual password, whether or not we got
* it by prompting. So we don't just store the password variable.
@@ -242,7 +243,6 @@ ConnectDatabase(Archive *AHX,
{
ArchiveHandle *AH = (ArchiveHandle *) AHX;
char *password;
- char passbuf[100];
bool new_pass;
if (AH->connection)
@@ -251,10 +251,8 @@ ConnectDatabase(Archive *AHX,
password = AH->savedPassword;
if (prompt_password == TRI_YES && password == NULL)
- {
- simple_prompt("Password: ", passbuf, sizeof(passbuf), false);
- password = passbuf;
- }
+ password = simple_prompt("Password: ", false);
+
AH->promptPassword = prompt_password;
/*
@@ -293,8 +291,7 @@ ConnectDatabase(Archive *AHX,
prompt_password != TRI_NO)
{
PQfinish(AH->connection);
- simple_prompt("Password: ", passbuf, sizeof(passbuf), false);
- password = passbuf;
+ password = simple_prompt("Password: ", false);
new_pass = true;
}
} while (new_pass);
@@ -309,6 +306,9 @@ ConnectDatabase(Archive *AHX,
PQclear(ExecuteSqlQueryForSingleRow((Archive *) AH,
ALWAYS_SECURE_SEARCH_PATH_SQL));
+ if (password && password != AH->savedPassword)
+ free(password);
+
/*
* We want to remember connection's actual password, whether or not we got
* it by prompting. So we don't just store the password variable.
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 2c82b39af0d..97d2b8dac1c 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -21,6 +21,7 @@
#include "common/connect.h"
#include "common/file_utils.h"
#include "common/logging.h"
+#include "common/string.h"
#include "dumputils.h"
#include "fe_utils/string_utils.h"
#include "getopt_long.h"
@@ -1643,14 +1644,10 @@ connectDatabase(const char *dbname, const char *connection_string,
const char **keywords = NULL;
const char **values = NULL;
PQconninfoOption *conn_opts = NULL;
- static bool have_password = false;
- static char password[100];
+ static char *password = NULL;
- if (prompt_password == TRI_YES && !have_password)
- {
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
- }
+ if (prompt_password == TRI_YES && !password)
+ password = simple_prompt("Password: ", false);
/*
* Start the connection. Loop until we have a password if requested by
@@ -1730,7 +1727,7 @@ connectDatabase(const char *dbname, const char *connection_string,
values[i] = pguser;
i++;
}
- if (have_password)
+ if (password)
{
keywords[i] = "password";
values[i] = password;
@@ -1757,12 +1754,11 @@ connectDatabase(const char *dbname, const char *connection_string,
if (PQstatus(conn) == CONNECTION_BAD &&
PQconnectionNeedsPassword(conn) &&
- !have_password &&
+ !password &&
prompt_password != TRI_NO)
{
PQfinish(conn);
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
+ password = simple_prompt("Password: ", false);
new_pass = true;
}
} while (new_pass);
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 08a5947a9e6..332eabf6379 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -59,6 +59,7 @@
#include "common/int.h"
#include "common/logging.h"
+#include "common/string.h"
#include "fe_utils/cancel.h"
#include "fe_utils/conditional.h"
#include "getopt_long.h"
@@ -1174,8 +1175,7 @@ doConnect(void)
{
PGconn *conn;
bool new_pass;
- static bool have_password = false;
- static char password[100];
+ static char *password = NULL;
/*
* Start the connection. Loop until we have a password if requested by
@@ -1195,7 +1195,7 @@ doConnect(void)
keywords[2] = "user";
values[2] = login;
keywords[3] = "password";
- values[3] = have_password ? password : NULL;
+ values[3] = password;
keywords[4] = "dbname";
values[4] = dbName;
keywords[5] = "fallback_application_name";
@@ -1215,11 +1215,10 @@ doConnect(void)
if (PQstatus(conn) == CONNECTION_BAD &&
PQconnectionNeedsPassword(conn) &&
- !have_password)
+ !password)
{
PQfinish(conn);
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
+ password = simple_prompt("Password: ", false);
new_pass = true;
}
} while (new_pass);
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 9902a4a2ba8..d4aa0976b5b 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -26,6 +26,7 @@
#include "command.h"
#include "common.h"
#include "common/logging.h"
+#include "common/string.h"
#include "copy.h"
#include "crosstabview.h"
#include "describe.h"
@@ -1964,11 +1965,11 @@ exec_command_password(PsqlScanState scan_state, bool active_branch)
{
char *opt0 = psql_scan_slash_option(scan_state,
OT_SQLID, NULL, true);
- char pw1[100];
- char pw2[100];
+ char *pw1;
+ char *pw2;
- simple_prompt("Enter new password: ", pw1, sizeof(pw1), false);
- simple_prompt("Enter it again: ", pw2, sizeof(pw2), false);
+ pw1 = simple_prompt("Enter new password: ", false);
+ pw2 = simple_prompt("Enter it again: ", false);
if (strcmp(pw1, pw2) != 0)
{
@@ -2013,6 +2014,8 @@ exec_command_password(PsqlScanState scan_state, bool active_branch)
if (opt0)
free(opt0);
+ free(pw1);
+ free(pw2);
}
else
ignore_slash_options(scan_state);
@@ -2058,8 +2061,7 @@ exec_command_prompt(PsqlScanState scan_state, bool active_branch,
if (!pset.inputfile)
{
- result = (char *) pg_malloc(4096);
- simple_prompt(prompt_text, result, 4096, true);
+ result = simple_prompt(prompt_text, true);
}
else
{
@@ -2982,19 +2984,19 @@ copy_previous_query(PQExpBuffer query_buf, PQExpBuffer previous_buf)
static char *
prompt_for_password(const char *username)
{
- char buf[100];
+ char *result;
if (username == NULL || username[0] == '\0')
- simple_prompt("Password: ", buf, sizeof(buf), false);
+ result = simple_prompt("Password: ", false);
else
{
char *prompt_text;
prompt_text = psprintf(_("Password for user %s: "), username);
- simple_prompt(prompt_text, buf, sizeof(buf), false);
+ result = simple_prompt(prompt_text, false);
free(prompt_text);
}
- return pg_strdup(buf);
+ return result;
}
static bool
diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c
index 3302bd4dd32..8232a0143bc 100644
--- a/src/bin/psql/startup.c
+++ b/src/bin/psql/startup.c
@@ -17,6 +17,7 @@
#include "command.h"
#include "common.h"
#include "common/logging.h"
+#include "common/string.h"
#include "describe.h"
#include "fe_utils/print.h"
#include "getopt_long.h"
@@ -119,8 +120,7 @@ main(int argc, char *argv[])
{
struct adhoc_opts options;
int successResult;
- bool have_password = false;
- char password[100];
+ char *password = NULL;
bool new_pass;
pg_logging_init(argv[0]);
@@ -233,8 +233,7 @@ main(int argc, char *argv[])
* offer a potentially wrong one. Typical uses of this option are
* noninteractive anyway.
*/
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
+ password = simple_prompt("Password: ", false);
}
/* loop until we have a password if requested by backend */
@@ -251,7 +250,7 @@ main(int argc, char *argv[])
keywords[2] = "user";
values[2] = options.username;
keywords[3] = "password";
- values[3] = have_password ? password : NULL;
+ values[3] = password;
keywords[4] = "dbname"; /* see do_connect() */
values[4] = (options.list_dbs && options.dbname == NULL) ?
"postgres" : options.dbname;
@@ -269,7 +268,7 @@ main(int argc, char *argv[])
if (PQstatus(pset.db) == CONNECTION_BAD &&
PQconnectionNeedsPassword(pset.db) &&
- !have_password &&
+ !password &&
pset.getPassword != TRI_NO)
{
/*
@@ -287,9 +286,8 @@ main(int argc, char *argv[])
password_prompt = pg_strdup(_("Password: "));
PQfinish(pset.db);
- simple_prompt(password_prompt, password, sizeof(password), false);
+ password = simple_prompt(password_prompt, false);
free(password_prompt);
- have_password = true;
new_pass = true;
}
} while (new_pass);
diff --git a/src/bin/scripts/common.c b/src/bin/scripts/common.c
index 420d0d11a5a..e987eef2343 100644
--- a/src/bin/scripts/common.c
+++ b/src/bin/scripts/common.c
@@ -20,6 +20,7 @@
#include "common.h"
#include "common/connect.h"
#include "common/logging.h"
+#include "common/string.h"
#include "fe_utils/cancel.h"
#include "fe_utils/string_utils.h"
@@ -68,18 +69,17 @@ connectDatabase(const char *dbname, const char *pghost,
{
PGconn *conn;
bool new_pass;
- static bool have_password = false;
- static char password[100];
+ static char *password = NULL;
- if (!allow_password_reuse)
- have_password = false;
-
- if (!have_password && prompt_password == TRI_YES)
+ if (!allow_password_reuse && password)
{
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
+ free(password);
+ password = NULL;
}
+ if (!password && prompt_password == TRI_YES)
+ password = simple_prompt("Password: ", false);
+
/*
* Start the connection. Loop until we have a password if requested by
* backend.
@@ -96,7 +96,7 @@ connectDatabase(const char *dbname, const char *pghost,
keywords[2] = "user";
values[2] = pguser;
keywords[3] = "password";
- values[3] = have_password ? password : NULL;
+ values[3] = password;
keywords[4] = "dbname";
values[4] = dbname;
keywords[5] = "fallback_application_name";
@@ -122,8 +122,9 @@ connectDatabase(const char *dbname, const char *pghost,
prompt_password != TRI_NO)
{
PQfinish(conn);
- simple_prompt("Password: ", password, sizeof(password), false);
- have_password = true;
+ if (password)
+ free(password);
+ password = simple_prompt("Password: ", false);
new_pass = true;
}
} while (new_pass);
@@ -444,14 +445,21 @@ yesno_prompt(const char *question)
for (;;)
{
- char resp[10];
+ char *resp;
- simple_prompt(prompt, resp, sizeof(resp), true);
+ resp = simple_prompt(prompt, true);
if (strcmp(resp, _(PG_YESLETTER)) == 0)
+ {
+ free(resp);
return true;
+ }
if (strcmp(resp, _(PG_NOLETTER)) == 0)
+ {
+ free(resp);
return false;
+ }
+ free(resp);
printf(_("Please answer \"%s\" or \"%s\".\n"),
_(PG_YESLETTER), _(PG_NOLETTER));
diff --git a/src/bin/scripts/createuser.c b/src/bin/scripts/createuser.c
index 9ced079ac75..6179199563c 100644
--- a/src/bin/scripts/createuser.c
+++ b/src/bin/scripts/createuser.c
@@ -13,6 +13,7 @@
#include "postgres_fe.h"
#include "common.h"
#include "common/logging.h"
+#include "common/string.h"
#include "fe_utils/simple_list.h"
#include "fe_utils/string_utils.h"
@@ -63,8 +64,6 @@ main(int argc, char *argv[])
int conn_limit = -2; /* less than minimum valid value */
bool pwprompt = false;
char *newpassword = NULL;
- char newuser_buf[128];
- char newpassword_buf[100];
/* Tri-valued variables. */
enum trivalue createdb = TRI_DEFAULT,
@@ -191,9 +190,7 @@ main(int argc, char *argv[])
{
if (interactive)
{
- simple_prompt("Enter name of role to add: ",
- newuser_buf, sizeof(newuser_buf), true);
- newuser = newuser_buf;
+ newuser = simple_prompt("Enter name of role to add: ", true);
}
else
{
@@ -206,17 +203,16 @@ main(int argc, char *argv[])
if (pwprompt)
{
- char pw2[100];
+ char *pw2;
- simple_prompt("Enter password for new role: ",
- newpassword_buf, sizeof(newpassword_buf), false);
- simple_prompt("Enter it again: ", pw2, sizeof(pw2), false);
- if (strcmp(newpassword_buf, pw2) != 0)
+ newpassword = simple_prompt("Enter password for new role: ", false);
+ pw2 = simple_prompt("Enter it again: ", false);
+ if (strcmp(newpassword, pw2) != 0)
{
fprintf(stderr, _("Passwords didn't match.\n"));
exit(1);
}
- newpassword = newpassword_buf;
+ free(pw2);
}
if (superuser == 0)
diff --git a/src/bin/scripts/dropuser.c b/src/bin/scripts/dropuser.c
index fee270d4f6d..f7ddd1402db 100644
--- a/src/bin/scripts/dropuser.c
+++ b/src/bin/scripts/dropuser.c
@@ -13,6 +13,7 @@
#include "postgres_fe.h"
#include "common.h"
#include "common/logging.h"
+#include "common/string.h"
#include "fe_utils/string_utils.h"
@@ -47,7 +48,6 @@ main(int argc, char *argv[])
enum trivalue prompt_password = TRI_DEFAULT;
bool echo = false;
bool interactive = false;
- char dropuser_buf[128];
PQExpBufferData sql;
@@ -112,9 +112,7 @@ main(int argc, char *argv[])
{
if (interactive)
{
- simple_prompt("Enter name of role to drop: ",
- dropuser_buf, sizeof(dropuser_buf), true);
- dropuser = dropuser_buf;
+ dropuser = simple_prompt("Enter name of role to drop: ", true);
}
else
{
diff --git a/src/common/Makefile b/src/common/Makefile
index 16619e4ba88..ad8fd9e41c4 100644
--- a/src/common/Makefile
+++ b/src/common/Makefile
@@ -63,6 +63,7 @@ OBJS_COMMON = \
kwlookup.o \
link-canary.o \
md5.o \
+ pg_get_line.o \
pg_lzcompress.o \
pgfnames.o \
psprintf.o \
@@ -92,7 +93,8 @@ OBJS_FRONTEND = \
fe_memutils.o \
file_utils.o \
logging.o \
- restricted_token.o
+ restricted_token.o \
+ sprompt.o
# foo.o, foo_shlib.o, and foo_srv.o are all built from foo.c
OBJS_SHLIB = $(OBJS_FRONTEND:%.o=%_shlib.o)
diff --git a/src/common/pg_get_line.c b/src/common/pg_get_line.c
new file mode 100644
index 00000000000..38433675d43
--- /dev/null
+++ b/src/common/pg_get_line.c
@@ -0,0 +1,85 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_get_line.c
+ * fgets() with an expansible result buffer
+ *
+ * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/common/pg_get_line.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef FRONTEND
+#include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
+
+#include "common/string.h"
+#include "lib/stringinfo.h"
+
+
+/*
+ * pg_get_line()
+ *
+ * This is meant to be equivalent to fgets(), except that instead of
+ * reading into a caller-supplied, fixed-size buffer, it reads into
+ * a palloc'd (in frontend, really malloc'd) string, which is resized
+ * as needed to handle indefinitely long input lines. The caller is
+ * responsible for pfree'ing the result string when appropriate.
+ *
+ * As with fgets(), returns NULL if there is a read error or if no
+ * characters are available before EOF. The caller can distinguish
+ * these cases by checking ferror(stream).
+ *
+ * Since this is meant to be equivalent to fgets(), the trailing newline
+ * (if any) is not stripped. Callers may wish to apply pg_strip_crlf().
+ *
+ * Note that while I/O errors are reflected back to the caller to be
+ * dealt with, an OOM condition for the palloc'd buffer will not be;
+ * there'll be an ereport(ERROR) or exit(1) inside stringinfo.c.
+ */
+char *
+pg_get_line(FILE *stream)
+{
+ StringInfoData buf;
+
+ initStringInfo(&buf);
+
+ /* Read some data, appending it to whatever we already have */
+ while (fgets(buf.data + buf.len, buf.maxlen - buf.len, stream) != NULL)
+ {
+ buf.len += strlen(buf.data + buf.len);
+
+ /* Done if we have collected a newline */
+ if (buf.len > 0 && buf.data[buf.len - 1] == '\n')
+ return buf.data;
+
+ /* Make some more room in the buffer, and loop to read more data */
+ enlargeStringInfo(&buf, 128);
+ }
+
+ /* Did fgets() fail because of an I/O error? */
+ if (ferror(stream))
+ {
+ /* ensure that free() doesn't mess up errno */
+ int save_errno = errno;
+
+ pfree(buf.data);
+ errno = save_errno;
+ return NULL;
+ }
+
+ /* If we read no data before reaching EOF, we should return NULL */
+ if (buf.len == 0)
+ {
+ pfree(buf.data);
+ return NULL;
+ }
+
+ /* No newline at EOF ... so return what we have */
+ return buf.data;
+}
diff --git a/src/common/saslprep.c b/src/common/saslprep.c
index 2dedf6b0fb6..d60452f75f2 100644
--- a/src/common/saslprep.c
+++ b/src/common/saslprep.c
@@ -30,12 +30,6 @@
#include "mb/pg_wchar.h"
/*
- * Limit on how large password's we will try to process. A password
- * larger than this will be treated the same as out-of-memory.
- */
-#define MAX_PASSWORD_LENGTH 1024
-
-/*
* In backend, we will use palloc/pfree. In frontend, use malloc, and
* return SASLPREP_OOM on out-of-memory.
*/
@@ -1078,18 +1072,6 @@ pg_saslprep(const char *input, char **output)
/* Ensure we return *output as NULL on failure */
*output = NULL;
- /* Check that the password isn't stupendously long */
- if (strlen(input) > MAX_PASSWORD_LENGTH)
- {
-#ifndef FRONTEND
- ereport(ERROR,
- (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
- errmsg("password too long")));
-#else
- return SASLPREP_OOM;
-#endif
- }
-
/*
* Quick check if the input is pure ASCII. An ASCII string requires no
* further processing.
diff --git a/src/port/sprompt.c b/src/common/sprompt.c
index 6d8a8b2609f..0ec75da5bfe 100644
--- a/src/port/sprompt.c
+++ b/src/common/sprompt.c
@@ -8,12 +8,15 @@
*
*
* IDENTIFICATION
- * src/port/sprompt.c
+ * src/common/sprompt.c
*
*-------------------------------------------------------------------------
*/
#include "c.h"
+#include "common/fe_memutils.h"
+#include "common/string.h"
+
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#endif
@@ -26,20 +29,17 @@
* passwords interactively. Reads from /dev/tty or stdin/stderr.
*
* prompt: The prompt to print, or NULL if none (automatically localized)
- * destination: buffer in which to store result
- * destlen: allocated length of destination
* echo: Set to false if you want to hide what is entered (for passwords)
*
- * The input (without trailing newline) is returned in the destination buffer,
- * with a '\0' appended.
+ * The input (without trailing newline) is returned as a malloc'd string.
+ * Caller is responsible for freeing it when done.
*/
-void
-simple_prompt(const char *prompt, char *destination, size_t destlen, bool echo)
+char *
+simple_prompt(const char *prompt, bool echo)
{
- int length;
+ char *result;
FILE *termin,
*termout;
-
#if defined(HAVE_TERMIOS_H)
struct termios t_orig,
t;
@@ -126,29 +126,14 @@ simple_prompt(const char *prompt, char *destination, size_t destlen, bool echo)
fflush(termout);
}
- if (fgets(destination, destlen, termin) == NULL)
- destination[0] = '\0';
+ result = pg_get_line(termin);
- 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), termin) == NULL)
- break;
- buflen = strlen(buf);
- } while (buflen > 0 && buf[buflen - 1] != '\n');
- }
+ /* If we failed to read anything, just return an empty string */
+ if (result == NULL)
+ result = pg_strdup("");
/* strip trailing newline, including \r in case we're on Windows */
- while (length > 0 &&
- (destination[length - 1] == '\n' ||
- destination[length - 1] == '\r'))
- destination[--length] = '\0';
+ (void) pg_strip_crlf(result);
if (!echo)
{
@@ -169,4 +154,6 @@ simple_prompt(const char *prompt, char *destination, size_t destlen, bool echo)
fclose(termin);
fclose(termout);
}
+
+ return result;
}
diff --git a/src/include/common/string.h b/src/include/common/string.h
index 5113c04434c..18aa1dc5aa5 100644
--- a/src/include/common/string.h
+++ b/src/include/common/string.h
@@ -10,10 +10,17 @@
#ifndef COMMON_STRING_H
#define COMMON_STRING_H
+/* functions in src/common/string.c */
extern bool pg_str_endswith(const char *str, const char *end);
extern int strtoint(const char *pg_restrict str, char **pg_restrict endptr,
int base);
extern void pg_clean_ascii(char *str);
extern int pg_strip_crlf(char *str);
+/* functions in src/common/pg_get_line.c */
+extern char *pg_get_line(FILE *stream);
+
+/* functions in src/common/sprompt.c */
+extern char *simple_prompt(const char *prompt, bool echo);
+
#endif /* COMMON_STRING_H */
diff --git a/src/include/port.h b/src/include/port.h
index 271ff0d00bc..84bf2c363f5 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -213,10 +213,6 @@ extern char *pg_strerror_r(int errnum, char *buf, size_t buflen);
/* Wrap strsignal(), or provide our own version if necessary */
extern const char *pg_strsignal(int signum);
-/* Portable prompt handling */
-extern void simple_prompt(const char *prompt, char *destination, size_t destlen,
- bool echo);
-
extern int pclose_check(FILE *stream);
/* Global variable holding time zone information. */
diff --git a/src/port/Makefile b/src/port/Makefile
index 8defa1257bb..e41b005c4f1 100644
--- a/src/port/Makefile
+++ b/src/port/Makefile
@@ -35,6 +35,8 @@ include $(top_builddir)/src/Makefile.global
override CPPFLAGS := -I$(top_builddir)/src/port -DFRONTEND $(CPPFLAGS)
LIBS += $(PTHREAD_LIBS)
+# If you add objects here, see also src/tools/msvc/Mkvcbuild.pm
+
OBJS = \
$(LIBOBJS) \
$(PG_CRC32C_OBJS) \
@@ -55,7 +57,6 @@ OBJS = \
qsort_arg.o \
quotes.o \
snprintf.o \
- sprompt.o \
strerror.o \
tar.o \
thread.o
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 20da7985c10..536df5a92e7 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -102,7 +102,7 @@ sub mkvcbuild
pread.c pwrite.c pg_bitutils.c
pg_strong_random.c pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c
pqsignal.c mkdtemp.c qsort.c qsort_arg.c quotes.c system.c
- sprompt.c strerror.c tar.c thread.c
+ strerror.c tar.c thread.c
win32env.c win32error.c win32security.c win32setlocale.c);
push(@pgportfiles, 'strtof.c') if ($vsVersion < '14.00');
@@ -123,7 +123,7 @@ sub mkvcbuild
config_info.c controldata_utils.c d2s.c encnames.c exec.c
f2s.c file_perm.c hashfn.c ip.c jsonapi.c
keywords.c kwlookup.c link-canary.c md5.c
- pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c
+ pg_get_line.c pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c
saslprep.c scram-common.c string.c stringinfo.c unicode_norm.c username.c
wait_error.c wchar.c);
@@ -139,7 +139,7 @@ sub mkvcbuild
our @pgcommonfrontendfiles = (
@pgcommonallfiles, qw(fe_memutils.c file_utils.c
- logging.c restricted_token.c));
+ logging.c restricted_token.c sprompt.c));
our @pgcommonbkndfiles = @pgcommonallfiles;