mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-10-01 00:31:14 +02:00
9df48371c2
psql4win32.patch - changes in the psql source code psql-ref.patch - changes in the documentation psql-ref.sgml (for new builtin variable WIN32_CONSOLE) To apply them use "patch -p 1" in the root directory of the postgres source directory. These patches fix the following problems of psql on Win32 (all changes only have effect #ifdef WIN32): a) Problem: Static library libpq.a did not work Solution: Added WSAStartup() in fe-connect.c b) Problem: Secret Password was echoed by psql Solution: Password echoing disabled in sprompt.c c) Problem: 8bit characters were displayed/interpreted wrong in psql This is due to the fact that the Win32 "console" uses a different encoding than the rest of the Windows system Solution: Introduced a new psql variable WIN32_CONSOLE When set with "\set WIN32_console", the function OemToChar() is applied after reading input and CharToOem() before displaying Output Christoph Dalitz
264 lines
4.6 KiB
C
264 lines
4.6 KiB
C
/*
|
|
* psql - the PostgreSQL interactive terminal
|
|
*
|
|
* Copyright 2000 by PostgreSQL Global Development Group
|
|
*
|
|
* $Header: /cvsroot/pgsql/src/bin/psql/input.c,v 1.26 2003/07/27 03:32:26 momjian Exp $
|
|
*/
|
|
#include "postgres_fe.h"
|
|
#include "input.h"
|
|
|
|
#include <errno.h>
|
|
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#include "pqexpbuffer.h"
|
|
#include "settings.h"
|
|
#include "tab-complete.h"
|
|
#include "common.h"
|
|
|
|
/* Runtime options for turning off readline and history */
|
|
/* (of course there is no runtime command for doing that :) */
|
|
#ifdef USE_READLINE
|
|
static bool useReadline;
|
|
static bool useHistory;
|
|
|
|
enum histcontrol
|
|
{
|
|
hctl_none = 0,
|
|
hctl_ignorespace = 1,
|
|
hctl_ignoredups = 2,
|
|
hctl_ignoreboth = hctl_ignorespace | hctl_ignoredups
|
|
};
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_ATEXIT
|
|
static void finishInput(void);
|
|
|
|
#else
|
|
/* designed for use with on_exit() */
|
|
static void finishInput(int, void *);
|
|
#endif
|
|
|
|
#define PSQLHISTORY ".psql_history"
|
|
|
|
|
|
#ifdef WIN32
|
|
/*
|
|
* translate DOS console character set into ANSI, needed e.g. for
|
|
* German umlauts
|
|
*/
|
|
if (GetVariableBool(pset.vars, "WIN32_CONSOLE"))
|
|
OemToChar(s, s);
|
|
#endif
|
|
|
|
#ifdef USE_READLINE
|
|
static enum histcontrol
|
|
GetHistControlConfig(void)
|
|
{
|
|
enum histcontrol HC;
|
|
const char *var;
|
|
|
|
var = GetVariable(pset.vars, "HISTCONTROL");
|
|
|
|
if (!var) HC = hctl_none;
|
|
else if (strcmp(var, "ignorespace") == 0) HC = hctl_ignorespace;
|
|
else if (strcmp(var, "ignoredups") == 0) HC = hctl_ignoredups;
|
|
else if (strcmp(var, "ignoreboth") == 0) HC = hctl_ignoreboth;
|
|
else HC = hctl_none;
|
|
|
|
return HC;
|
|
}
|
|
#endif
|
|
|
|
|
|
static char *
|
|
gets_basic(const char prompt[])
|
|
{
|
|
fputs(prompt, stdout);
|
|
fflush(stdout);
|
|
return gets_fromFile(stdin);
|
|
}
|
|
|
|
|
|
/*
|
|
* gets_interactive()
|
|
*
|
|
* Gets a line of interactive input, using readline of desired.
|
|
* The result is malloced.
|
|
*/
|
|
char *
|
|
gets_interactive(const char *prompt)
|
|
{
|
|
#ifdef USE_READLINE
|
|
char *s;
|
|
|
|
static char *prev_hist = NULL;
|
|
|
|
if (useReadline)
|
|
/* On some platforms, readline is declared as readline(char *) */
|
|
s = readline((char *) prompt);
|
|
else
|
|
s = gets_basic(prompt);
|
|
|
|
if (useHistory && s && s[0])
|
|
{
|
|
enum histcontrol HC;
|
|
|
|
HC = GetHistControlConfig();
|
|
|
|
if (((HC & hctl_ignorespace) && s[0] == ' ') ||
|
|
((HC & hctl_ignoredups) && prev_hist && strcmp(s, prev_hist) == 0))
|
|
{
|
|
/* Ignore this line as far as history is concerned */
|
|
}
|
|
else
|
|
{
|
|
free(prev_hist);
|
|
prev_hist = strdup(s);
|
|
add_history(s);
|
|
}
|
|
}
|
|
|
|
return s;
|
|
#else
|
|
return gets_basic(prompt);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* gets_fromFile
|
|
*
|
|
* Gets a line of noninteractive input from a file (which could be stdin).
|
|
*/
|
|
char *
|
|
gets_fromFile(FILE *source)
|
|
{
|
|
PQExpBufferData buffer;
|
|
char line[1024];
|
|
|
|
initPQExpBuffer(&buffer);
|
|
|
|
while (fgets(line, sizeof(line), source) != NULL)
|
|
{
|
|
appendPQExpBufferStr(&buffer, line);
|
|
if (buffer.data[buffer.len - 1] == '\n')
|
|
{
|
|
buffer.data[buffer.len - 1] = '\0';
|
|
return buffer.data;
|
|
}
|
|
}
|
|
|
|
if (buffer.len > 0)
|
|
return buffer.data; /* EOF after reading some bufferload(s) */
|
|
|
|
/* EOF, so return null */
|
|
termPQExpBuffer(&buffer);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Put any startup stuff related to input in here. It's good to maintain
|
|
* abstraction this way.
|
|
*
|
|
* The only "flag" right now is 1 for use readline & history.
|
|
*/
|
|
void
|
|
initializeInput(int flags)
|
|
{
|
|
#ifdef USE_READLINE
|
|
if (flags & 1)
|
|
{
|
|
const char *home;
|
|
|
|
useReadline = true;
|
|
initialize_readline();
|
|
|
|
useHistory = true;
|
|
SetVariable(pset.vars, "HISTSIZE", "500");
|
|
using_history();
|
|
home = getenv("HOME");
|
|
if (home)
|
|
{
|
|
char *psql_history = (char *) malloc(strlen(home) + 1 +
|
|
strlen(PSQLHISTORY) + 1);
|
|
|
|
if (psql_history)
|
|
{
|
|
sprintf(psql_history, "%s/%s", home, PSQLHISTORY);
|
|
read_history(psql_history);
|
|
free(psql_history);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef HAVE_ATEXIT
|
|
atexit(finishInput);
|
|
#else
|
|
on_exit(finishInput, NULL);
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
saveHistory(char *fname)
|
|
{
|
|
#ifdef USE_READLINE
|
|
if (useHistory && fname)
|
|
{
|
|
if (write_history(fname) == 0)
|
|
return true;
|
|
|
|
psql_error("could not save history to file \"%s\": %s\n", fname, strerror(errno));
|
|
}
|
|
#endif
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
#ifdef HAVE_ATEXIT
|
|
finishInput(void)
|
|
#else
|
|
finishInput(int exitstatus, void *arg)
|
|
#endif
|
|
{
|
|
#ifdef USE_READLINE
|
|
if (useHistory)
|
|
{
|
|
char *home;
|
|
char *psql_history;
|
|
|
|
home = getenv("HOME");
|
|
if (home)
|
|
{
|
|
psql_history = (char *) malloc(strlen(home) + 1 +
|
|
strlen(PSQLHISTORY) + 1);
|
|
if (psql_history)
|
|
{
|
|
int hist_size;
|
|
hist_size = GetVariableNum(pset.vars,"HISTSIZE",-1,-1,true);
|
|
|
|
if (hist_size >= 0)
|
|
stifle_history(hist_size);
|
|
|
|
sprintf(psql_history, "%s/%s", home, PSQLHISTORY);
|
|
write_history(psql_history);
|
|
free(psql_history);
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|