2
* psql - the PostgreSQL interactive terminal
4
* Copyright (c) 2000-2009, PostgreSQL Global Development Group
8
#include "postgres_fe.h"
12
#include "tab-complete.h"
16
#define PSQLHISTORY ".psql_history"
18
#define PSQLHISTORY "psql_history"
21
/* Runtime options for turning off readline and history */
22
/* (of course there is no runtime command for doing that :) */
24
static bool useReadline;
25
static bool useHistory;
29
* Preserve newlines in saved queries by mapping '\n' to NL_IN_HISTORY
31
* It is assumed NL_IN_HISTORY will never be entered by the user
32
* nor appear inside a multi-byte string. 0x00 is not properly
33
* handled by the readline routines so it can not be used
36
#define NL_IN_HISTORY 0x01
40
static void finishInput(void);
42
/* designed for use with on_exit() */
43
static void finishInput(int, void *);
50
* Gets a line of interactive input, using readline if desired.
51
* The result is a malloc'd string.
53
* Caller *must* have set up sigint_interrupt_jmp before calling.
56
gets_interactive(const char *prompt)
63
/* Enable SIGINT to longjmp to sigint_interrupt_jmp */
64
sigint_interrupt_enabled = true;
66
/* On some platforms, readline is declared as readline(char *) */
67
result = readline((char *) prompt);
69
/* Disable SIGINT again */
70
sigint_interrupt_enabled = false;
76
fputs(prompt, stdout);
78
return gets_fromFile(stdin);
83
* Append the line to the history buffer, making sure there is a trailing '\n'
86
pg_append_history(const char *s, PQExpBuffer history_buf)
89
if (useHistory && s && s[0])
91
appendPQExpBufferStr(history_buf, s);
92
if (s[strlen(s) - 1] != '\n')
93
appendPQExpBufferChar(history_buf, '\n');
100
* Emit accumulated history entry to readline's history mechanism,
101
* then reset the buffer to empty.
103
* Note: we write nothing if history_buf is empty, so extra calls to this
104
* function don't hurt. There must have been at least one line added by
105
* pg_append_history before we'll do anything.
108
pg_send_history(PQExpBuffer history_buf)
111
static char *prev_hist = NULL;
113
char *s = history_buf->data;
116
/* Trim any trailing \n's (OK to scribble on history_buf) */
117
for (i = strlen(s) - 1; i >= 0 && s[i] == '\n'; i--)
121
if (useHistory && s[0])
123
if (((pset.histcontrol & hctl_ignorespace) &&
125
((pset.histcontrol & hctl_ignoredups) &&
126
prev_hist && strcmp(s, prev_hist) == 0))
128
/* Ignore this line as far as history is concerned */
132
/* Save each previous line for ignoredups processing */
135
prev_hist = pg_strdup(s);
136
/* And send it to readline */
141
resetPQExpBuffer(history_buf);
149
* Gets a line of noninteractive input from a file (which could be stdin).
150
* The result is a malloc'd string, or NULL on EOF or input error.
152
* Caller *must* have set up sigint_interrupt_jmp before calling.
154
* Note: we re-use a static PQExpBuffer for each call. This is to avoid
155
* leaking memory if interrupted by SIGINT.
158
gets_fromFile(FILE *source)
160
static PQExpBuffer buffer = NULL;
164
if (buffer == NULL) /* first time through? */
165
buffer = createPQExpBuffer();
167
resetPQExpBuffer(buffer);
173
/* Enable SIGINT to longjmp to sigint_interrupt_jmp */
174
sigint_interrupt_enabled = true;
177
result = fgets(line, sizeof(line), source);
179
/* Disable SIGINT again */
180
sigint_interrupt_enabled = false;
187
psql_error("could not read from input file: %s\n",
194
appendPQExpBufferStr(buffer, line);
196
if (PQExpBufferBroken(buffer))
198
psql_error("out of memory\n");
203
if (buffer->data[buffer->len - 1] == '\n')
205
buffer->data[buffer->len - 1] = '\0';
206
return pg_strdup(buffer->data);
210
if (buffer->len > 0) /* EOF after reading some bufferload(s) */
211
return pg_strdup(buffer->data);
213
/* EOF, so return null */
220
* Convert newlines to NL_IN_HISTORY for safe saving in readline history file
225
HIST_ENTRY *cur_hist;
229
for (cur_hist = current_history(); cur_hist; cur_hist = next_history())
231
/* some platforms declare HIST_ENTRY.line as const char * */
232
for (cur_ptr = (char *) cur_hist->line; *cur_ptr; cur_ptr++)
233
if (*cur_ptr == '\n')
234
*cur_ptr = NL_IN_HISTORY;
239
* Reverse the above encoding
244
HIST_ENTRY *cur_hist;
248
for (cur_hist = current_history(); cur_hist; cur_hist = next_history())
250
/* some platforms declare HIST_ENTRY.line as const char * */
251
for (cur_ptr = (char *) cur_hist->line; *cur_ptr; cur_ptr++)
252
if (*cur_ptr == NL_IN_HISTORY)
256
#endif /* USE_READLINE */
260
* Put any startup stuff related to input in here. It's good to maintain
261
* abstraction this way.
263
* The only "flag" right now is 1 for use readline & history.
266
initializeInput(int flags)
271
const char *histfile;
272
char home[MAXPGPATH];
275
initialize_readline();
280
histfile = GetVariable(pset.vars, "HISTFILE");
281
if (histfile == NULL)
283
if (get_home_path(home))
285
psql_history = pg_malloc(strlen(home) + 1 +
286
strlen(PSQLHISTORY) + 1);
287
snprintf(psql_history, MAXPGPATH, "%s/%s", home, PSQLHISTORY);
292
psql_history = pg_strdup(histfile);
293
expand_tilde(&psql_history);
298
read_history(psql_history);
307
on_exit(finishInput, NULL);
313
* This function is for saving the readline history when user
314
* runs \s command or when psql finishes.
316
* We have an argument named encodeFlag to handle the cases differently.
317
* In case of call via \s we don't really need to encode \n as \x01,
318
* but when we save history for Readline we must do that conversion.
321
saveHistory(char *fname, bool encodeFlag)
326
* Suppressing the write attempt when HISTFILE is set to /dev/null may
327
* look like a negligible optimization, but it's necessary on e.g. Darwin,
328
* where write_history will fail because it tries to chmod the target
331
if (useHistory && fname &&
332
strcmp(fname, DEVNULL) != 0)
338
* return value of write_history is not standardized across GNU
339
* readline and libedit. Therefore, check for errno becoming set to
340
* see if the write failed.
343
(void) write_history(fname);
347
psql_error("could not save history to file \"%s\": %s\n",
348
fname, strerror(errno));
351
/* only get here in \s case, so complain */
352
psql_error("history is not supported by this installation\n");
363
finishInput(int exitstatus, void *arg)
367
if (useHistory && psql_history)
371
hist_size = GetVariableNum(pset.vars, "HISTSIZE", 500, -1, true);
373
stifle_history(hist_size);
375
saveHistory(psql_history, true);