Age Owner TLA Line data Source code
1 : /*
2 : * psql - the PostgreSQL interactive terminal
3 : *
4 : * Copyright (c) 2000-2023, PostgreSQL Global Development Group
5 : *
6 : * src/bin/psql/input.c
7 : */
8 : #include "postgres_fe.h"
9 :
10 : #ifndef WIN32
11 : #include <unistd.h>
12 : #endif
13 : #include <fcntl.h>
14 : #include <limits.h>
15 :
16 : #include "common.h"
17 : #include "common/logging.h"
18 : #include "input.h"
19 : #include "settings.h"
20 : #include "tab-complete.h"
21 :
22 : #ifndef WIN32
23 : #define PSQLHISTORY ".psql_history"
24 : #else
25 : #define PSQLHISTORY "psql_history"
26 : #endif
27 :
28 : /* Runtime options for turning off readline and history */
29 : /* (of course there is no runtime command for doing that :) */
30 : #ifdef USE_READLINE
31 : static bool useReadline;
32 : static bool useHistory;
33 :
34 : static char *psql_history;
35 :
36 : static int history_lines_added;
37 :
38 :
39 : /*
40 : * Preserve newlines in saved queries by mapping '\n' to NL_IN_HISTORY
41 : *
42 : * It is assumed NL_IN_HISTORY will never be entered by the user
43 : * nor appear inside a multi-byte string. 0x00 is not properly
44 : * handled by the readline routines so it can not be used
45 : * for this purpose.
46 : */
47 : #define NL_IN_HISTORY 0x01
48 : #endif
49 :
50 : static void finishInput(void);
51 :
52 :
53 : /*
54 : * gets_interactive()
55 : *
56 : * Gets a line of interactive input, using readline if desired.
57 : *
58 : * prompt: the prompt string to be used
59 : * query_buf: buffer containing lines already read in the current command
60 : * (query_buf is not modified here, but may be consulted for tab completion)
61 : *
62 : * The result is a malloc'd string.
63 : *
64 : * Caller *must* have set up sigint_interrupt_jmp before calling.
65 : */
66 : char *
2667 tgl 67 CBC 53 : gets_interactive(const char *prompt, PQExpBuffer query_buf)
68 : {
69 : #ifdef USE_READLINE
8557 bruce 70 53 : if (useReadline)
71 : {
72 : char *result;
73 :
74 : /*
75 : * Some versions of readline don't notice SIGWINCH signals that arrive
76 : * when not actively reading input. The simplest fix is to always
77 : * re-read the terminal size. This leaves a window for SIGWINCH to be
78 : * missed between here and where readline() enables libreadline's
79 : * signal handler, but that's probably short enough to be ignored.
80 : */
81 : #ifdef HAVE_RL_RESET_SCREEN_SIZE
2671 tgl 82 53 : rl_reset_screen_size();
83 : #endif
84 :
85 : /* Make current query_buf available to tab completion callback */
2667 86 53 : tab_completion_query_buf = query_buf;
87 :
88 : /* Enable SIGINT to longjmp to sigint_interrupt_jmp */
6143 89 53 : sigint_interrupt_enabled = true;
90 :
91 : /* On some platforms, readline is declared as readline(char *) */
92 53 : result = readline((char *) prompt);
93 :
94 : /* Disable SIGINT again */
95 53 : sigint_interrupt_enabled = false;
96 :
97 : /* Pure neatnik-ism */
2667 98 53 : tab_completion_query_buf = NULL;
99 :
6143 100 53 : return result;
101 : }
102 : #endif
103 :
6146 tgl 104 UBC 0 : fputs(prompt, stdout);
105 0 : fflush(stdout);
106 0 : return gets_fromFile(stdin);
107 : }
108 :
109 :
110 : /*
111 : * Append the line to the history buffer, making sure there is a trailing '\n'
112 : */
113 : void
6146 tgl 114 CBC 43 : pg_append_history(const char *s, PQExpBuffer history_buf)
115 : {
116 : #ifdef USE_READLINE
4163 rhaas 117 43 : if (useHistory && s)
118 : {
6146 tgl 119 43 : appendPQExpBufferStr(history_buf, s);
4163 rhaas 120 43 : if (!s[0] || s[strlen(s) - 1] != '\n')
6266 bruce 121 43 : appendPQExpBufferChar(history_buf, '\n');
122 : }
123 : #endif
124 43 : }
125 :
126 :
127 : /*
128 : * Emit accumulated history entry to readline's history mechanism,
129 : * then reset the buffer to empty.
130 : *
131 : * Note: we write nothing if history_buf is empty, so extra calls to this
132 : * function don't hurt. There must have been at least one line added by
133 : * pg_append_history before we'll do anything.
134 : */
135 : void
6146 tgl 136 132 : pg_send_history(PQExpBuffer history_buf)
137 : {
138 : #ifdef USE_READLINE
139 : static char *prev_hist = NULL;
140 :
6031 bruce 141 132 : char *s = history_buf->data;
142 : int i;
143 :
144 : /* Trim any trailing \n's (OK to scribble on history_buf) */
5950 tgl 145 174 : for (i = strlen(s) - 1; i >= 0 && s[i] == '\n'; i--)
146 : ;
147 132 : s[i + 1] = '\0';
148 :
6146 149 132 : if (useHistory && s[0])
150 : {
6067 151 42 : if (((pset.histcontrol & hctl_ignorespace) &&
6067 tgl 152 UBC 0 : s[0] == ' ') ||
6067 tgl 153 CBC 42 : ((pset.histcontrol & hctl_ignoredups) &&
6067 tgl 154 UBC 0 : prev_hist && strcmp(s, prev_hist) == 0))
155 : {
156 : /* Ignore this line as far as history is concerned */
157 : }
158 : else
159 : {
160 : /* Save each previous line for ignoredups processing */
297 peter 161 GNC 42 : free(prev_hist);
7014 neilc 162 GIC 42 : prev_hist = pg_strdup(s);
6146 tgl 163 ECB : /* And send it to readline */
8397 bruce 164 GIC 42 : add_history(s);
4956 tgl 165 ECB : /* Count lines added to history for use later */
4956 tgl 166 GIC 42 : history_lines_added++;
167 : }
168 : }
8557 bruce 169 ECB :
6146 tgl 170 GIC 132 : resetPQExpBuffer(history_buf);
6266 bruce 171 ECB : #endif
6266 bruce 172 GIC 132 : }
173 :
174 :
175 : /*
176 : * gets_fromFile
177 : *
178 : * Gets a line of noninteractive input from a file (which could be stdin).
179 : * The result is a malloc'd string, or NULL on EOF or input error.
180 : *
181 : * Caller *must* have set up sigint_interrupt_jmp before calling.
182 : *
183 : * Note: we re-use a static PQExpBuffer for each call. This is to avoid
184 : * leaking memory if interrupted by SIGINT.
185 : */
8557 bruce 186 ECB : char *
8557 bruce 187 GIC 341678 : gets_fromFile(FILE *source)
188 : {
189 : static PQExpBuffer buffer = NULL;
190 :
191 : char line[1024];
8557 bruce 192 ECB :
6143 tgl 193 CBC 341678 : if (buffer == NULL) /* first time through? */
6143 tgl 194 GIC 5962 : buffer = createPQExpBuffer();
6143 tgl 195 ECB : else
6143 tgl 196 GIC 335716 : resetPQExpBuffer(buffer);
197 :
6143 tgl 198 ECB : for (;;)
8557 bruce 199 GIC 4704 : {
200 : char *result;
201 :
6143 tgl 202 ECB : /* Enable SIGINT to longjmp to sigint_interrupt_jmp */
6143 tgl 203 GIC 346382 : sigint_interrupt_enabled = true;
204 :
6143 tgl 205 ECB : /* Get some data */
6143 tgl 206 GIC 346382 : result = fgets(line, sizeof(line), source);
207 :
6143 tgl 208 ECB : /* Disable SIGINT again */
6143 tgl 209 GIC 346382 : sigint_interrupt_enabled = false;
210 :
5611 peter_e 211 ECB : /* EOF or error? */
6143 tgl 212 GIC 346382 : if (result == NULL)
5611 peter_e 213 ECB : {
5611 peter_e 214 GIC 10557 : if (ferror(source))
5611 peter_e 215 EUB : {
1469 peter 216 UBC 0 : pg_log_error("could not read from input file: %m");
5611 peter_e 217 UIC 0 : return NULL;
5611 peter_e 218 ECB : }
6143 tgl 219 GIC 10557 : break;
220 : }
6143 tgl 221 ECB :
6143 tgl 222 GIC 335825 : appendPQExpBufferStr(buffer, line);
6143 tgl 223 ECB :
5247 tgl 224 GIC 335825 : if (PQExpBufferBroken(buffer))
5247 tgl 225 EUB : {
1469 peter 226 UBC 0 : pg_log_error("out of memory");
5247 tgl 227 UIC 0 : return NULL;
228 : }
229 :
6143 tgl 230 ECB : /* EOL? */
2446 tgl 231 GIC 335825 : if (buffer->len > 0 && buffer->data[buffer->len - 1] == '\n')
8557 bruce 232 ECB : {
6143 tgl 233 CBC 331121 : buffer->data[buffer->len - 1] = '\0';
6143 tgl 234 GIC 331121 : return pg_strdup(buffer->data);
235 : }
236 : }
8557 bruce 237 ECB :
6143 tgl 238 CBC 10557 : if (buffer->len > 0) /* EOF after reading some bufferload(s) */
6143 tgl 239 GIC 4640 : return pg_strdup(buffer->data);
240 :
8557 bruce 241 ECB : /* EOF, so return null */
8557 bruce 242 GIC 5917 : return NULL;
243 : }
244 :
245 :
246 : #ifdef USE_READLINE
247 :
248 : /*
249 : * Macros to iterate over each element of the history list in order
250 : *
251 : * You would think this would be simple enough, but in its inimitable fashion
252 : * libedit has managed to break it: in libreadline we must use next_history()
253 : * to go from oldest to newest, but in libedit we must use previous_history().
254 : * To detect what to do, we make a trial call of previous_history(): if it
255 : * fails, then either next_history() is what to use, or there's zero or one
256 : * history entry so that it doesn't matter which direction we go.
257 : *
258 : * In case that wasn't disgusting enough: the code below is not as obvious as
259 : * it might appear. In some libedit releases history_set_pos(0) fails until
260 : * at least one add_history() call has been done. This is not an issue for
261 : * printHistory() or encode_history(), which cannot be invoked before that has
262 : * happened. In decode_history(), that's not so, and what actually happens is
263 : * that we are sitting on the newest entry to start with, previous_history()
264 : * fails, and we iterate over all the entries using next_history(). So the
265 : * decode_history() loop iterates over the entries in the wrong order when
266 : * using such a libedit release, and if there were another attempt to use
267 : * BEGIN_ITERATE_HISTORY() before some add_history() call had happened, it
268 : * wouldn't work. Fortunately we don't care about either of those things.
269 : *
270 : * Usage pattern is:
271 : *
272 : * BEGIN_ITERATE_HISTORY(varname);
273 : * {
274 : * loop body referencing varname->line;
275 : * }
276 : * END_ITERATE_HISTORY();
277 : */
278 : #define BEGIN_ITERATE_HISTORY(VARNAME) \
279 : do { \
280 : HIST_ENTRY *VARNAME; \
281 : bool use_prev_; \
282 : \
283 : history_set_pos(0); \
284 : use_prev_ = (previous_history() != NULL); \
285 : history_set_pos(0); \
286 : for (VARNAME = current_history(); VARNAME != NULL; \
287 : VARNAME = use_prev_ ? previous_history() : next_history()) \
288 : { \
289 : (void) 0
290 :
291 : #define END_ITERATE_HISTORY() \
292 : } \
293 : } while(0)
294 :
295 :
296 : /*
297 : * Convert newlines to NL_IN_HISTORY for safe saving in readline history file
298 : */
6264 bruce 299 ECB : static void
6264 bruce 300 GIC 2 : encode_history(void)
6266 bruce 301 ECB : {
3135 tgl 302 GIC 544 : BEGIN_ITERATE_HISTORY(cur_hist);
303 : {
304 : char *cur_ptr;
305 :
6139 tgl 306 ECB : /* some platforms declare HIST_ENTRY.line as const char * */
6139 tgl 307 GIC 19355 : for (cur_ptr = (char *) cur_hist->line; *cur_ptr; cur_ptr++)
3135 tgl 308 ECB : {
6266 bruce 309 CBC 18813 : if (*cur_ptr == '\n')
6265 bruce 310 GIC 14 : *cur_ptr = NL_IN_HISTORY;
311 : }
312 : }
3135 tgl 313 ECB : END_ITERATE_HISTORY();
6266 bruce 314 GIC 2 : }
315 :
316 : /*
317 : * Reverse the above encoding
318 : */
6264 bruce 319 ECB : static void
6264 bruce 320 GIC 2 : decode_history(void)
6266 bruce 321 ECB : {
3135 tgl 322 GIC 502 : BEGIN_ITERATE_HISTORY(cur_hist);
323 : {
324 : char *cur_ptr;
325 :
6139 tgl 326 ECB : /* some platforms declare HIST_ENTRY.line as const char * */
6139 tgl 327 GIC 18215 : for (cur_ptr = (char *) cur_hist->line; *cur_ptr; cur_ptr++)
3135 tgl 328 ECB : {
6265 bruce 329 CBC 17715 : if (*cur_ptr == NL_IN_HISTORY)
6266 bruce 330 GIC 13 : *cur_ptr = '\n';
331 : }
332 : }
3135 tgl 333 ECB : END_ITERATE_HISTORY();
6266 bruce 334 GIC 2 : }
335 : #endif /* USE_READLINE */
336 :
337 :
338 : /*
339 : * Put any startup stuff related to input in here. It's good to maintain
340 : * abstraction this way.
341 : *
342 : * The only "flag" right now is 1 for use readline & history.
343 : */
8557 bruce 344 ECB : void
8486 peter_e 345 GIC 2 : initializeInput(int flags)
346 : {
8557 bruce 347 ECB : #ifdef USE_READLINE
7325 bruce 348 GIC 2 : if (flags & 1)
349 : {
350 : const char *histfile;
351 : char home[MAXPGPATH];
7325 bruce 352 ECB :
8557 bruce 353 GIC 2 : useReadline = true;
354 :
494 tgl 355 ECB : /* set appropriate values for Readline's global variables */
8397 bruce 356 GIC 2 : initialize_readline();
357 :
358 : #ifdef HAVE_RL_VARIABLE_BIND
494 tgl 359 ECB : /* set comment-begin to a useful value for SQL */
494 tgl 360 GIC 2 : (void) rl_variable_bind("comment-begin", "-- ");
361 : #endif
362 :
494 tgl 363 ECB : /* this reads ~/.inputrc, so do it after rl_variable_bind */
2670 tgl 364 GIC 2 : rl_initialize();
8557 bruce 365 ECB :
8557 bruce 366 CBC 2 : useHistory = true;
367 2 : using_history();
4956 tgl 368 GIC 2 : history_lines_added = 0;
6512 bruce 369 ECB :
6067 tgl 370 GIC 2 : histfile = GetVariable(pset.vars, "HISTFILE");
4054 andrew 371 ECB :
4054 andrew 372 GIC 2 : if (histfile == NULL)
373 : {
374 : char *envhist;
3955 bruce 375 ECB :
4054 andrew 376 CBC 2 : envhist = getenv("PSQL_HISTORY");
377 2 : if (envhist != NULL && strlen(envhist) > 0)
4054 andrew 378 GIC 1 : histfile = envhist;
379 : }
4054 andrew 380 ECB :
6067 tgl 381 GIC 2 : if (histfile == NULL)
6512 bruce 382 ECB : {
6512 bruce 383 CBC 1 : if (get_home_path(home))
3456 tgl 384 GIC 1 : psql_history = psprintf("%s/%s", home, PSQLHISTORY);
385 : }
386 : else
8557 bruce 387 ECB : {
6067 tgl 388 CBC 1 : psql_history = pg_strdup(histfile);
6512 bruce 389 GIC 1 : expand_tilde(&psql_history);
390 : }
7015 neilc 391 ECB :
6512 bruce 392 GIC 2 : if (psql_history)
6146 tgl 393 ECB : {
7015 neilc 394 CBC 2 : read_history(psql_history);
6146 tgl 395 GIC 2 : decode_history();
396 : }
397 : }
398 : #endif
8449 peter_e 399 ECB :
8397 bruce 400 CBC 2 : atexit(finishInput);
8557 bruce 401 GIC 2 : }
402 :
403 :
404 : /*
405 : * This function saves the readline history when psql exits.
406 : *
407 : * fname: pathname of history file. (Should really be "const char *",
408 : * but some ancient versions of readline omit the const-decoration.)
409 : *
410 : * max_lines: if >= 0, limit history file to that many entries.
411 : */
412 : #ifdef USE_READLINE
3135 tgl 413 ECB : static bool
3135 tgl 414 GIC 2 : saveHistory(char *fname, int max_lines)
415 : {
416 : int errnum;
417 :
418 : /*
419 : * Suppressing the write attempt when HISTFILE is set to /dev/null may
420 : * look like a negligible optimization, but it's necessary on e.g. macOS,
421 : * where write_history will fail because it tries to chmod the target
422 : * file.
6069 tgl 423 ECB : */
3135 tgl 424 GIC 2 : if (strcmp(fname, DEVNULL) != 0)
425 : {
426 : /*
427 : * Encode \n, since otherwise readline will reload multiline history
428 : * entries as separate lines. (libedit doesn't really need this, but
429 : * we do it anyway since it's too hard to tell which implementation we
430 : * are using.)
3135 tgl 431 ECB : */
3135 tgl 432 GIC 2 : encode_history();
433 :
434 : /*
435 : * On newer versions of libreadline, truncate the history file as
436 : * needed and then append what we've added. This avoids overwriting
437 : * history from other concurrent sessions (although there are still
438 : * race conditions when two sessions exit at about the same time). If
439 : * we don't have those functions, fall back to write_history().
440 : */
441 : #if defined(HAVE_HISTORY_TRUNCATE_FILE) && defined(HAVE_APPEND_HISTORY)
442 : {
443 : int nlines;
444 : int fd;
445 :
4956 tgl 446 ECB : /* truncate previous entries if needed */
4956 tgl 447 GIC 2 : if (max_lines >= 0)
4956 tgl 448 ECB : {
4956 tgl 449 CBC 2 : nlines = Max(max_lines - history_lines_added, 0);
4956 tgl 450 GIC 2 : (void) history_truncate_file(fname, nlines);
451 : }
4956 tgl 452 ECB : /* append_history fails if file doesn't already exist :-( */
4956 tgl 453 CBC 2 : fd = open(fname, O_CREAT | O_WRONLY | PG_BINARY, 0600);
454 2 : if (fd >= 0)
4956 tgl 455 GIC 2 : close(fd);
4956 tgl 456 ECB : /* append the appropriate number of lines */
4956 tgl 457 CBC 2 : if (max_lines >= 0)
4956 tgl 458 GIC 2 : nlines = Min(max_lines, history_lines_added);
4956 tgl 459 EUB : else
4956 tgl 460 LBC 0 : nlines = history_lines_added;
2948 tgl 461 CBC 2 : errnum = append_history(nlines, fname);
462 2 : if (errnum == 0)
4956 tgl 463 GIC 2 : return true;
464 : }
465 : #else /* don't have append support */
466 : {
467 : /* truncate what we have ... */
468 : if (max_lines >= 0)
469 : stifle_history(max_lines);
470 : /* ... and overwrite file. Tough luck for concurrent sessions. */
471 : errnum = write_history(fname);
472 : if (errnum == 0)
473 : return true;
474 : }
475 : #endif
7325 bruce 476 EUB :
1469 peter 477 UIC 0 : pg_log_error("could not save history to file \"%s\": %m", fname);
8557 bruce 478 EUB : }
7325 bruce 479 UIC 0 : return false;
480 : }
481 : #endif
482 :
483 :
484 :
485 : /*
486 : * Print history to the specified file, or to the console if fname is NULL
487 : * (psql \s command)
488 : *
489 : * We used to use saveHistory() for this purpose, but that doesn't permit
490 : * use of a pager; moreover libedit's implementation behaves incompatibly
491 : * (preferring to encode its output) and may fail outright when the target
492 : * file is specified as /dev/tty.
493 : */
3135 tgl 494 EUB : bool
3135 tgl 495 UIC 0 : printHistory(const char *fname, unsigned short int pager)
496 : {
497 : #ifdef USE_READLINE
498 : FILE *output;
499 : bool is_pager;
3135 tgl 500 EUB :
3135 tgl 501 UBC 0 : if (!useHistory)
3135 tgl 502 UIC 0 : return false;
3135 tgl 503 EUB :
3135 tgl 504 UIC 0 : if (fname == NULL)
505 : {
3135 tgl 506 EUB : /* use pager, if enabled, when printing to console */
2934 andrew 507 UBC 0 : output = PageOutput(INT_MAX, pager ? &(pset.popt.topt) : NULL);
3135 tgl 508 UIC 0 : is_pager = true;
509 : }
510 : else
3135 tgl 511 EUB : {
3135 tgl 512 UBC 0 : output = fopen(fname, "w");
3135 tgl 513 UIC 0 : if (output == NULL)
3135 tgl 514 EUB : {
1469 peter 515 UBC 0 : pg_log_error("could not save history to file \"%s\": %m", fname);
3135 tgl 516 UIC 0 : return false;
3135 tgl 517 EUB : }
3135 tgl 518 UIC 0 : is_pager = false;
519 : }
3135 tgl 520 EUB :
3135 tgl 521 UIC 0 : BEGIN_ITERATE_HISTORY(cur_hist);
3135 tgl 522 EUB : {
3135 tgl 523 UIC 0 : fprintf(output, "%s\n", cur_hist->line);
524 : }
525 : END_ITERATE_HISTORY();
3135 tgl 526 EUB :
3135 tgl 527 UBC 0 : if (is_pager)
3135 tgl 528 UIC 0 : ClosePager(output);
3135 tgl 529 EUB : else
3135 tgl 530 UIC 0 : fclose(output);
3135 tgl 531 EUB :
3135 tgl 532 UIC 0 : return true;
533 : #else
534 : pg_log_error("history is not supported by this installation");
535 : return false;
536 : #endif
537 : }
538 :
539 :
7880 peter_e 540 ECB : static void
8557 bruce 541 GIC 2 : finishInput(void)
542 : {
7669 peter_e 543 ECB : #ifdef USE_READLINE
6512 bruce 544 GIC 2 : if (useHistory && psql_history)
8557 bruce 545 ECB : {
2257 tgl 546 CBC 2 : (void) saveHistory(psql_history, pset.histsize);
6512 bruce 547 2 : free(psql_history);
6512 bruce 548 GIC 2 : psql_history = NULL;
549 : }
8557 bruce 550 ECB : #endif
8557 bruce 551 GIC 2 : }
|