2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2008, 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);