#include "postgres_fe.h"#include <unistd.h>#include <fcntl.h>#include "input.h"#include "settings.h"#include "tab-complete.h"#include "common.h"
Go to the source code of this file.
Defines | |
| #define | PSQLHISTORY ".psql_history" |
Functions | |
| static void | finishInput (void) |
| char * | gets_interactive (const char *prompt) |
| void | pg_append_history (const char *s, PQExpBuffer history_buf) |
| void | pg_send_history (PQExpBuffer history_buf) |
| char * | gets_fromFile (FILE *source) |
| void | initializeInput (int flags) |
| bool | saveHistory (char *fname, int max_lines, bool appendFlag, bool encodeFlag) |
| #define PSQLHISTORY ".psql_history" |
Definition at line 21 of file input.c.
Referenced by initializeInput().
| static void finishInput | ( | void | ) | [static] |
Definition at line 420 of file input.c.
References free, GetVariableNum(), pset, saveHistory(), and _psqlSettings::vars.
Referenced by initializeInput().
{
#ifdef USE_READLINE
if (useHistory && psql_history)
{
int hist_size;
hist_size = GetVariableNum(pset.vars, "HISTSIZE", 500, -1, true);
saveHistory(psql_history, hist_size, true, true);
free(psql_history);
psql_history = NULL;
}
#endif
}
| char* gets_fromFile | ( | FILE * | source | ) |
Definition at line 164 of file input.c.
References appendPQExpBufferStr(), createPQExpBuffer(), PQExpBufferData::data, PQExpBufferData::len, NULL, pg_strdup(), PQExpBufferBroken, psql_error(), resetPQExpBuffer(), sigint_interrupt_enabled, and strerror().
Referenced by exec_command(), gets_interactive(), and MainLoop().
{
static PQExpBuffer buffer = NULL;
char line[1024];
if (buffer == NULL) /* first time through? */
buffer = createPQExpBuffer();
else
resetPQExpBuffer(buffer);
for (;;)
{
char *result;
/* Enable SIGINT to longjmp to sigint_interrupt_jmp */
sigint_interrupt_enabled = true;
/* Get some data */
result = fgets(line, sizeof(line), source);
/* Disable SIGINT again */
sigint_interrupt_enabled = false;
/* EOF or error? */
if (result == NULL)
{
if (ferror(source))
{
psql_error("could not read from input file: %s\n",
strerror(errno));
return NULL;
}
break;
}
appendPQExpBufferStr(buffer, line);
if (PQExpBufferBroken(buffer))
{
psql_error("out of memory\n");
return NULL;
}
/* EOL? */
if (buffer->data[buffer->len - 1] == '\n')
{
buffer->data[buffer->len - 1] = '\0';
return pg_strdup(buffer->data);
}
}
if (buffer->len > 0) /* EOF after reading some bufferload(s) */
return pg_strdup(buffer->data);
/* EOF, so return null */
return NULL;
}
| char* gets_interactive | ( | const char * | prompt | ) |
Definition at line 60 of file input.c.
References gets_fromFile(), and sigint_interrupt_enabled.
Referenced by MainLoop().
{
#ifdef USE_READLINE
if (useReadline)
{
char *result;
/* Enable SIGINT to longjmp to sigint_interrupt_jmp */
sigint_interrupt_enabled = true;
/* On some platforms, readline is declared as readline(char *) */
result = readline((char *) prompt);
/* Disable SIGINT again */
sigint_interrupt_enabled = false;
return result;
}
#endif
fputs(prompt, stdout);
fflush(stdout);
return gets_fromFile(stdin);
}
| void initializeInput | ( | int | flags | ) |
Definition at line 272 of file input.c.
References expand_tilde(), finishInput(), get_home_path(), GetVariable(), initialize_readline(), MAXPGPATH, NULL, pg_malloc(), pg_strdup(), pset, PSQLHISTORY, snprintf(), and _psqlSettings::vars.
Referenced by main().
{
#ifdef USE_READLINE
if (flags & 1)
{
const char *histfile;
char home[MAXPGPATH];
useReadline = true;
initialize_readline();
useHistory = true;
using_history();
history_lines_added = 0;
histfile = GetVariable(pset.vars, "HISTFILE");
if (histfile == NULL)
{
char *envhist;
envhist = getenv("PSQL_HISTORY");
if (envhist != NULL && strlen(envhist) > 0)
histfile = envhist;
}
if (histfile == NULL)
{
if (get_home_path(home))
{
psql_history = pg_malloc(strlen(home) + 1 +
strlen(PSQLHISTORY) + 1);
snprintf(psql_history, MAXPGPATH, "%s/%s", home, PSQLHISTORY);
}
}
else
{
psql_history = pg_strdup(histfile);
expand_tilde(&psql_history);
}
if (psql_history)
{
read_history(psql_history);
decode_history();
}
}
#endif
atexit(finishInput);
}
| void pg_append_history | ( | const char * | s, | |
| PQExpBuffer | history_buf | |||
| ) |
Definition at line 90 of file input.c.
References appendPQExpBufferChar(), and appendPQExpBufferStr().
Referenced by MainLoop().
{
#ifdef USE_READLINE
if (useHistory && s)
{
appendPQExpBufferStr(history_buf, s);
if (!s[0] || s[strlen(s) - 1] != '\n')
appendPQExpBufferChar(history_buf, '\n');
}
#endif
}
| void pg_send_history | ( | PQExpBuffer | history_buf | ) |
Definition at line 112 of file input.c.
References PQExpBufferData::data, free, hctl_ignoredups, hctl_ignorespace, _psqlSettings::histcontrol, i, pg_strdup(), pset, and resetPQExpBuffer().
Referenced by MainLoop().
{
#ifdef USE_READLINE
static char *prev_hist = NULL;
char *s = history_buf->data;
int i;
/* Trim any trailing \n's (OK to scribble on history_buf) */
for (i = strlen(s) - 1; i >= 0 && s[i] == '\n'; i--)
;
s[i + 1] = '\0';
if (useHistory && s[0])
{
if (((pset.histcontrol & hctl_ignorespace) &&
s[0] == ' ') ||
((pset.histcontrol & hctl_ignoredups) &&
prev_hist && strcmp(s, prev_hist) == 0))
{
/* Ignore this line as far as history is concerned */
}
else
{
/* Save each previous line for ignoredups processing */
if (prev_hist)
free(prev_hist);
prev_hist = pg_strdup(s);
/* And send it to readline */
add_history(s);
/* Count lines added to history for use later */
history_lines_added++;
}
}
resetPQExpBuffer(history_buf);
#endif
}
Definition at line 341 of file input.c.
References close, DEVNULL, Max, Min, PG_BINARY, psql_error(), and strerror().
Referenced by exec_command(), and finishInput().
{
#ifdef USE_READLINE
/*
* Suppressing the write attempt when HISTFILE is set to /dev/null may
* look like a negligible optimization, but it's necessary on e.g. Darwin,
* where write_history will fail because it tries to chmod the target
* file.
*/
if (useHistory && fname &&
strcmp(fname, DEVNULL) != 0)
{
if (encodeFlag)
encode_history();
/*
* On newer versions of libreadline, truncate the history file as
* needed and then append what we've added. This avoids overwriting
* history from other concurrent sessions (although there are still
* race conditions when two sessions exit at about the same time). If
* we don't have those functions, fall back to write_history().
*
* Note: return value of write_history is not standardized across GNU
* readline and libedit. Therefore, check for errno becoming set to
* see if the write failed. Similarly for append_history.
*/
#if defined(HAVE_HISTORY_TRUNCATE_FILE) && defined(HAVE_APPEND_HISTORY)
if (appendFlag)
{
int nlines;
int fd;
/* truncate previous entries if needed */
if (max_lines >= 0)
{
nlines = Max(max_lines - history_lines_added, 0);
(void) history_truncate_file(fname, nlines);
}
/* append_history fails if file doesn't already exist :-( */
fd = open(fname, O_CREAT | O_WRONLY | PG_BINARY, 0600);
if (fd >= 0)
close(fd);
/* append the appropriate number of lines */
if (max_lines >= 0)
nlines = Min(max_lines, history_lines_added);
else
nlines = history_lines_added;
errno = 0;
(void) append_history(nlines, fname);
if (errno == 0)
return true;
}
else
#endif
{
/* truncate what we have ... */
if (max_lines >= 0)
stifle_history(max_lines);
/* ... and overwrite file. Tough luck for concurrent sessions. */
errno = 0;
(void) write_history(fname);
if (errno == 0)
return true;
}
psql_error("could not save history to file \"%s\": %s\n",
fname, strerror(errno));
}
#else
/* only get here in \s case, so complain */
psql_error("history is not supported by this installation\n");
#endif
return false;
}
1.7.1