2003-11-12 00:52:45 +01:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* sprompt.c
|
|
|
|
* simple_prompt() routine
|
|
|
|
*
|
2016-01-02 19:33:40 +01:00
|
|
|
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
2003-11-12 00:52:45 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
2002-07-06 22:12:30 +02:00
|
|
|
*
|
2003-11-12 00:52:45 +01:00
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/port/sprompt.c
|
2002-07-06 22:12:30 +02:00
|
|
|
*
|
2003-11-12 00:52:45 +01:00
|
|
|
*-------------------------------------------------------------------------
|
2002-07-06 22:12:30 +02:00
|
|
|
*/
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
#include "c.h"
|
|
|
|
|
|
|
|
#ifdef HAVE_TERMIOS_H
|
|
|
|
#include <termios.h>
|
|
|
|
#endif
|
2002-07-06 22:12:30 +02:00
|
|
|
|
2002-07-06 22:14:58 +02:00
|
|
|
|
2002-07-06 22:12:30 +02:00
|
|
|
/*
|
|
|
|
* simple_prompt
|
|
|
|
*
|
|
|
|
* Generalized function especially intended for reading in usernames and
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
* passwords interactively. Reads from /dev/tty or stdin/stderr.
|
2002-07-06 22:12:30 +02:00
|
|
|
*
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
* prompt: The prompt to print, or NULL if none (automatically localized)
|
|
|
|
* destination: buffer in which to store result
|
|
|
|
* destlen: allocated length of destination
|
2002-07-06 22:12:30 +02:00
|
|
|
* echo: Set to false if you want to hide what is entered (for passwords)
|
|
|
|
*
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
* The input (without trailing newline) is returned in the destination buffer,
|
|
|
|
* with a '\0' appended.
|
2002-07-06 22:12:30 +02:00
|
|
|
*/
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
void
|
|
|
|
simple_prompt(const char *prompt, char *destination, size_t destlen, bool echo)
|
2002-07-06 22:12:30 +02:00
|
|
|
{
|
|
|
|
int length;
|
2006-03-04 05:30:41 +01:00
|
|
|
FILE *termin,
|
|
|
|
*termout;
|
2002-07-06 22:12:30 +02:00
|
|
|
|
|
|
|
#ifdef HAVE_TERMIOS_H
|
|
|
|
struct termios t_orig,
|
|
|
|
t;
|
2003-07-27 05:32:26 +02:00
|
|
|
#else
|
|
|
|
#ifdef WIN32
|
2004-04-19 19:42:59 +02:00
|
|
|
HANDLE t = NULL;
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
DWORD t_orig = 0;
|
2003-07-27 05:32:26 +02:00
|
|
|
#endif
|
2002-07-06 22:12:30 +02:00
|
|
|
#endif
|
|
|
|
|
2013-01-24 22:01:31 +01:00
|
|
|
#ifdef WIN32
|
2014-05-06 18:12:18 +02:00
|
|
|
|
2013-01-24 22:01:31 +01:00
|
|
|
/*
|
|
|
|
* A Windows console has an "input code page" and an "output code page";
|
|
|
|
* these usually match each other, but they rarely match the "Windows ANSI
|
|
|
|
* code page" defined at system boot and expected of "char *" arguments to
|
|
|
|
* Windows API functions. The Microsoft CRT write() implementation
|
|
|
|
* automatically converts text between these code pages when writing to a
|
|
|
|
* console. To identify such file descriptors, it calls GetConsoleMode()
|
|
|
|
* on the underlying HANDLE, which in turn requires GENERIC_READ access on
|
2014-05-06 18:12:18 +02:00
|
|
|
* the HANDLE. Opening termout in mode "w+" allows that detection to
|
2013-01-24 22:01:31 +01:00
|
|
|
* succeed. Otherwise, write() would not recognize the descriptor as a
|
|
|
|
* console, and non-ASCII characters would display incorrectly.
|
|
|
|
*
|
|
|
|
* XXX fgets() still receives text in the console's input code page. This
|
|
|
|
* makes non-ASCII credentials unportable.
|
|
|
|
*/
|
|
|
|
termin = fopen("CONIN$", "r");
|
|
|
|
termout = fopen("CONOUT$", "w+");
|
|
|
|
#else
|
|
|
|
|
2002-07-06 22:12:30 +02:00
|
|
|
/*
|
2005-10-15 04:49:52 +02:00
|
|
|
* Do not try to collapse these into one "w+" mode file. Doesn't work on
|
|
|
|
* some platforms (eg, HPUX 10.20).
|
2002-07-06 22:12:30 +02:00
|
|
|
*/
|
2013-01-24 22:01:31 +01:00
|
|
|
termin = fopen("/dev/tty", "r");
|
|
|
|
termout = fopen("/dev/tty", "w");
|
|
|
|
#endif
|
2006-03-05 06:33:12 +01:00
|
|
|
if (!termin || !termout
|
|
|
|
#ifdef WIN32
|
2014-05-06 18:12:18 +02:00
|
|
|
|
2013-01-24 22:01:31 +01:00
|
|
|
/*
|
|
|
|
* Direct console I/O does not work from the MSYS 1.0.10 console. Writes
|
|
|
|
* reach nowhere user-visible; reads block indefinitely. XXX This affects
|
|
|
|
* most Windows terminal environments, including rxvt, mintty, Cygwin
|
2014-05-06 18:12:18 +02:00
|
|
|
* xterm, Cygwin sshd, and PowerShell ISE. Switch to a more-generic test.
|
2013-01-24 22:01:31 +01:00
|
|
|
*/
|
2006-03-05 06:33:12 +01:00
|
|
|
|| (getenv("OSTYPE") && strcmp(getenv("OSTYPE"), "msys") == 0)
|
|
|
|
#endif
|
|
|
|
)
|
2002-07-06 22:12:30 +02:00
|
|
|
{
|
|
|
|
if (termin)
|
|
|
|
fclose(termin);
|
|
|
|
if (termout)
|
|
|
|
fclose(termout);
|
|
|
|
termin = stdin;
|
|
|
|
termout = stderr;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_TERMIOS_H
|
|
|
|
if (!echo)
|
|
|
|
{
|
|
|
|
tcgetattr(fileno(termin), &t);
|
|
|
|
t_orig = t;
|
|
|
|
t.c_lflag &= ~ECHO;
|
|
|
|
tcsetattr(fileno(termin), TCSAFLUSH, &t);
|
|
|
|
}
|
2003-07-27 05:32:26 +02:00
|
|
|
#else
|
|
|
|
#ifdef WIN32
|
|
|
|
if (!echo)
|
|
|
|
{
|
|
|
|
/* get a new handle to turn echo off */
|
2003-08-04 02:43:34 +02:00
|
|
|
t = GetStdHandle(STD_INPUT_HANDLE);
|
2003-07-27 05:32:26 +02:00
|
|
|
|
|
|
|
/* save the old configuration first */
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
GetConsoleMode(t, &t_orig);
|
2003-07-27 05:32:26 +02:00
|
|
|
|
|
|
|
/* set to the new mode */
|
2003-08-04 02:43:34 +02:00
|
|
|
SetConsoleMode(t, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT);
|
2003-07-27 05:32:26 +02:00
|
|
|
}
|
|
|
|
#endif
|
2002-07-06 22:12:30 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (prompt)
|
|
|
|
{
|
2005-02-22 05:43:23 +01:00
|
|
|
fputs(_(prompt), termout);
|
2002-07-06 22:12:30 +02:00
|
|
|
fflush(termout);
|
|
|
|
}
|
|
|
|
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
if (fgets(destination, destlen, termin) == NULL)
|
2002-07-06 22:12:30 +02:00
|
|
|
destination[0] = '\0';
|
|
|
|
|
|
|
|
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 (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);
|
|
|
|
}
|
2003-07-27 05:32:26 +02:00
|
|
|
#else
|
|
|
|
#ifdef WIN32
|
|
|
|
if (!echo)
|
|
|
|
{
|
|
|
|
/* reset to the original console mode */
|
Simplify correct use of simple_prompt().
The previous API for this function had it returning a malloc'd string.
That meant that callers had to check for NULL return, which few of them
were doing, and it also meant that callers had to remember to free()
the string later, which required extra logic in most cases.
Instead, make simple_prompt() write into a buffer supplied by the caller.
Anywhere that the maximum required input length is reasonably small,
which is almost all of the callers, we can just use a local or static
array as the buffer instead of dealing with malloc/free.
A fair number of callers used "pointer == NULL" as a proxy for "haven't
requested the password yet". Maintaining the same behavior requires
adding a separate boolean flag for that, which adds back some of the
complexity we save by removing free()s. Nonetheless, this nets out
at a small reduction in overall code size, and considerably less code
than we would have had if we'd added the missing NULL-return checks
everywhere they were needed.
In passing, clean up the API comment for simple_prompt() and get rid
of a very-unnecessary malloc/free in its Windows code path.
This is nominally a bug fix, but it does not seem worth back-patching,
because the actual risk of an OOM failure in any of these places seems
pretty tiny, and all of them are client-side not server-side anyway.
This patch is by me, but it owes a great deal to Michael Paquier
who identified the problem and drafted a patch for fixing it the
other way.
Discussion: <CAB7nPqRu07Ot6iht9i9KRfYLpDaF2ZuUv5y_+72uP23ZAGysRg@mail.gmail.com>
2016-08-30 23:02:02 +02:00
|
|
|
SetConsoleMode(t, t_orig);
|
2003-07-27 05:32:26 +02:00
|
|
|
fputs("\n", termout);
|
|
|
|
fflush(termout);
|
|
|
|
}
|
|
|
|
#endif
|
2002-07-06 22:12:30 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (termin != stdin)
|
|
|
|
{
|
|
|
|
fclose(termin);
|
|
|
|
fclose(termout);
|
|
|
|
}
|
|
|
|
}
|