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