1 /*
2 * psql - the PostgreSQL interactive terminal
3 *
4 * Copyright (c) 2000-2021, PostgreSQL Global Development Group
5 *
6 * src/bin/psql/mainloop.c
7 */
8 #include "postgres_fe.h"
9
10 #include "command.h"
11 #include "common.h"
12 #include "common/logging.h"
13 #include "input.h"
14 #include "mainloop.h"
15 #include "mb/pg_wchar.h"
16 #include "prompt.h"
17 #include "settings.h"
18
19 /* callback functions for our flex lexer */
20 const PsqlScanCallbacks psqlscan_callbacks = {
21 psql_get_variable,
22 };
23
24
25 /*
26 * Main processing loop for reading lines of input
27 * and sending them to the backend.
28 *
29 * This loop is re-entrant. May be called by \i command
30 * which reads input from a file.
31 */
32 int
MainLoop(FILE * source)33 MainLoop(FILE *source)
34 {
35 PsqlScanState scan_state; /* lexer working state */
36 ConditionalStack cond_stack; /* \if status stack */
37 volatile PQExpBuffer query_buf; /* buffer for query being accumulated */
38 volatile PQExpBuffer previous_buf; /* if there isn't anything in the new
39 * buffer yet, use this one for \e,
40 * etc. */
41 PQExpBuffer history_buf; /* earlier lines of a multi-line command, not
42 * yet saved to readline history */
43 char *line; /* current line of input */
44 int added_nl_pos;
45 bool success;
46 bool line_saved_in_history;
47 volatile int successResult = EXIT_SUCCESS;
48 volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
49 volatile promptStatus_t prompt_status = PROMPT_READY;
50 volatile bool need_redisplay = false;
51 volatile int count_eof = 0;
52 volatile bool die_on_error = false;
53 FILE *prev_cmd_source;
54 bool prev_cmd_interactive;
55 uint64 prev_lineno;
56
57 /* Save the prior command source */
58 prev_cmd_source = pset.cur_cmd_source;
59 prev_cmd_interactive = pset.cur_cmd_interactive;
60 prev_lineno = pset.lineno;
61 /* pset.stmt_lineno does not need to be saved and restored */
62
63 /* Establish new source */
64 pset.cur_cmd_source = source;
65 pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
66 pset.lineno = 0;
67 pset.stmt_lineno = 1;
68
69 /* Create working state */
70 scan_state = psql_scan_create(&psqlscan_callbacks);
71 cond_stack = conditional_stack_create();
72 psql_scan_set_passthrough(scan_state, (void *) cond_stack);
73
74 query_buf = createPQExpBuffer();
75 previous_buf = createPQExpBuffer();
76 history_buf = createPQExpBuffer();
77 if (PQExpBufferBroken(query_buf) ||
78 PQExpBufferBroken(previous_buf) ||
79 PQExpBufferBroken(history_buf))
80 {
81 pg_log_error("out of memory");
82 exit(EXIT_FAILURE);
83 }
84
85 /* main loop to get queries and execute them */
86 while (successResult == EXIT_SUCCESS)
87 {
88 /*
89 * Clean up after a previous Control-C
90 */
91 if (cancel_pressed)
92 {
93 if (!pset.cur_cmd_interactive)
94 {
95 /*
96 * You get here if you stopped a script with Ctrl-C.
97 */
98 successResult = EXIT_USER;
99 break;
100 }
101
102 cancel_pressed = false;
103 }
104
105 /*
106 * Establish longjmp destination for exiting from wait-for-input. We
107 * must re-do this each time through the loop for safety, since the
108 * jmpbuf might get changed during command execution.
109 */
110 if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
111 {
112 /* got here with longjmp */
113
114 /* reset parsing state */
115 psql_scan_finish(scan_state);
116 psql_scan_reset(scan_state);
117 resetPQExpBuffer(query_buf);
118 resetPQExpBuffer(history_buf);
119 count_eof = 0;
120 slashCmdStatus = PSQL_CMD_UNKNOWN;
121 prompt_status = PROMPT_READY;
122 need_redisplay = false;
123 pset.stmt_lineno = 1;
124 cancel_pressed = false;
125
126 if (pset.cur_cmd_interactive)
127 {
128 putc('\n', stdout);
129
130 /*
131 * if interactive user is in an \if block, then Ctrl-C will
132 * exit from the innermost \if.
133 */
134 if (!conditional_stack_empty(cond_stack))
135 {
136 pg_log_error("\\if: escaped");
137 conditional_stack_pop(cond_stack);
138 }
139 }
140 else
141 {
142 successResult = EXIT_USER;
143 break;
144 }
145 }
146
147 fflush(stdout);
148
149 /*
150 * get another line
151 */
152 if (pset.cur_cmd_interactive)
153 {
154 /* May need to reset prompt, eg after \r command */
155 if (query_buf->len == 0)
156 prompt_status = PROMPT_READY;
157 /* If query buffer came from \e, redisplay it with a prompt */
158 if (need_redisplay)
159 {
160 if (query_buf->len > 0)
161 {
162 fputs(get_prompt(PROMPT_READY, cond_stack), stdout);
163 fputs(query_buf->data, stdout);
164 fflush(stdout);
165 }
166 need_redisplay = false;
167 }
168 /* Now we can fetch a line */
169 line = gets_interactive(get_prompt(prompt_status, cond_stack),
170 query_buf);
171 }
172 else
173 {
174 line = gets_fromFile(source);
175 if (!line && ferror(source))
176 successResult = EXIT_FAILURE;
177 }
178
179 /*
180 * query_buf holds query already accumulated. line is the malloc'd
181 * new line of input (note it must be freed before looping around!)
182 */
183
184 /* No more input. Time to quit, or \i done */
185 if (line == NULL)
186 {
187 if (pset.cur_cmd_interactive)
188 {
189 /* This tries to mimic bash's IGNOREEOF feature. */
190 count_eof++;
191
192 if (count_eof < pset.ignoreeof)
193 {
194 if (!pset.quiet)
195 printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);
196 continue;
197 }
198
199 puts(pset.quiet ? "" : "\\q");
200 }
201 break;
202 }
203
204 count_eof = 0;
205
206 pset.lineno++;
207
208 /* ignore UTF-8 Unicode byte-order mark */
209 if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0)
210 memmove(line, line + 3, strlen(line + 3) + 1);
211
212 /* Detect attempts to run custom-format dumps as SQL scripts */
213 if (pset.lineno == 1 && !pset.cur_cmd_interactive &&
214 strncmp(line, "PGDMP", 5) == 0)
215 {
216 free(line);
217 puts(_("The input is a PostgreSQL custom-format dump.\n"
218 "Use the pg_restore command-line client to restore this dump to a database.\n"));
219 fflush(stdout);
220 successResult = EXIT_FAILURE;
221 break;
222 }
223
224 /* no further processing of empty lines, unless within a literal */
225 if (line[0] == '\0' && !psql_scan_in_quote(scan_state))
226 {
227 free(line);
228 continue;
229 }
230
231 /* Recognize "help", "quit", "exit" only in interactive mode */
232 if (pset.cur_cmd_interactive)
233 {
234 char *first_word = line;
235 char *rest_of_line = NULL;
236 bool found_help = false;
237 bool found_exit_or_quit = false;
238 bool found_q = false;
239
240 /*
241 * The assistance words, help/exit/quit, must have no whitespace
242 * before them, and only whitespace after, with an optional
243 * semicolon. This prevents indented use of these words, perhaps
244 * as identifiers, from invoking the assistance behavior.
245 */
246 if (pg_strncasecmp(first_word, "help", 4) == 0)
247 {
248 rest_of_line = first_word + 4;
249 found_help = true;
250 }
251 else if (pg_strncasecmp(first_word, "exit", 4) == 0 ||
252 pg_strncasecmp(first_word, "quit", 4) == 0)
253 {
254 rest_of_line = first_word + 4;
255 found_exit_or_quit = true;
256 }
257 else if (strncmp(first_word, "\\q", 2) == 0)
258 {
259 rest_of_line = first_word + 2;
260 found_q = true;
261 }
262
263 /*
264 * If we found a command word, check whether the rest of the line
265 * contains only whitespace plus maybe one semicolon. If not,
266 * ignore the command word after all. These commands are only for
267 * compatibility with other SQL clients and are not documented.
268 */
269 if (rest_of_line != NULL)
270 {
271 /*
272 * Ignore unless rest of line is whitespace, plus maybe one
273 * semicolon
274 */
275 while (isspace((unsigned char) *rest_of_line))
276 ++rest_of_line;
277 if (*rest_of_line == ';')
278 ++rest_of_line;
279 while (isspace((unsigned char) *rest_of_line))
280 ++rest_of_line;
281 if (*rest_of_line != '\0')
282 {
283 found_help = false;
284 found_exit_or_quit = false;
285 }
286 }
287
288 /*
289 * "help" is only a command when the query buffer is empty, but we
290 * emit a one-line message even when it isn't to help confused
291 * users. The text is still added to the query buffer in that
292 * case.
293 */
294 if (found_help)
295 {
296 if (query_buf->len != 0)
297 #ifndef WIN32
298 puts(_("Use \\? for help or press control-C to clear the input buffer."));
299 #else
300 puts(_("Use \\? for help."));
301 #endif
302 else
303 {
304 puts(_("You are using psql, the command-line interface to PostgreSQL."));
305 printf(_("Type: \\copyright for distribution terms\n"
306 " \\h for help with SQL commands\n"
307 " \\? for help with psql commands\n"
308 " \\g or terminate with semicolon to execute query\n"
309 " \\q to quit\n"));
310 free(line);
311 fflush(stdout);
312 continue;
313 }
314 }
315
316 /*
317 * "quit" and "exit" are only commands when the query buffer is
318 * empty, but we emit a one-line message even when it isn't to
319 * help confused users. The text is still added to the query
320 * buffer in that case.
321 */
322 if (found_exit_or_quit)
323 {
324 if (query_buf->len != 0)
325 {
326 if (prompt_status == PROMPT_READY ||
327 prompt_status == PROMPT_CONTINUE ||
328 prompt_status == PROMPT_PAREN)
329 puts(_("Use \\q to quit."));
330 else
331 #ifndef WIN32
332 puts(_("Use control-D to quit."));
333 #else
334 puts(_("Use control-C to quit."));
335 #endif
336 }
337 else
338 {
339 /* exit app */
340 free(line);
341 fflush(stdout);
342 successResult = EXIT_SUCCESS;
343 break;
344 }
345 }
346
347 /*
348 * If they typed "\q" in a place where "\q" is not active, supply
349 * a hint. The text is still added to the query buffer.
350 */
351 if (found_q && query_buf->len != 0 &&
352 prompt_status != PROMPT_READY &&
353 prompt_status != PROMPT_CONTINUE &&
354 prompt_status != PROMPT_PAREN)
355 #ifndef WIN32
356 puts(_("Use control-D to quit."));
357 #else
358 puts(_("Use control-C to quit."));
359 #endif
360 }
361
362 /* echo back if flag is set, unless interactive */
363 if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive)
364 {
365 puts(line);
366 fflush(stdout);
367 }
368
369 /* insert newlines into query buffer between source lines */
370 if (query_buf->len > 0)
371 {
372 appendPQExpBufferChar(query_buf, '\n');
373 added_nl_pos = query_buf->len;
374 }
375 else
376 added_nl_pos = -1; /* flag we didn't add one */
377
378 /* Setting this will not have effect until next line. */
379 die_on_error = pset.on_error_stop;
380
381 /*
382 * Parse line, looking for command separators.
383 */
384 psql_scan_setup(scan_state, line, strlen(line),
385 pset.encoding, standard_strings());
386 success = true;
387 line_saved_in_history = false;
388
389 while (success || !die_on_error)
390 {
391 PsqlScanResult scan_result;
392 promptStatus_t prompt_tmp = prompt_status;
393 size_t pos_in_query;
394 char *tmp_line;
395
396 pos_in_query = query_buf->len;
397 scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
398 prompt_status = prompt_tmp;
399
400 if (PQExpBufferBroken(query_buf))
401 {
402 pg_log_error("out of memory");
403 exit(EXIT_FAILURE);
404 }
405
406 /*
407 * Increase statement line number counter for each linebreak added
408 * to the query buffer by the last psql_scan() call. There only
409 * will be ones to add when navigating to a statement in
410 * readline's history containing newlines.
411 */
412 tmp_line = query_buf->data + pos_in_query;
413 while (*tmp_line != '\0')
414 {
415 if (*(tmp_line++) == '\n')
416 pset.stmt_lineno++;
417 }
418
419 if (scan_result == PSCAN_EOL)
420 pset.stmt_lineno++;
421
422 /*
423 * Send command if semicolon found, or if end of line and we're in
424 * single-line mode.
425 */
426 if (scan_result == PSCAN_SEMICOLON ||
427 (scan_result == PSCAN_EOL && pset.singleline))
428 {
429 /*
430 * Save line in history. We use history_buf to accumulate
431 * multi-line queries into a single history entry. Note that
432 * history accumulation works on input lines, so it doesn't
433 * matter whether the query will be ignored due to \if.
434 */
435 if (pset.cur_cmd_interactive && !line_saved_in_history)
436 {
437 pg_append_history(line, history_buf);
438 pg_send_history(history_buf);
439 line_saved_in_history = true;
440 }
441
442 /* execute query unless we're in an inactive \if branch */
443 if (conditional_active(cond_stack))
444 {
445 success = SendQuery(query_buf->data);
446 slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
447 pset.stmt_lineno = 1;
448
449 /* transfer query to previous_buf by pointer-swapping */
450 {
451 PQExpBuffer swap_buf = previous_buf;
452
453 previous_buf = query_buf;
454 query_buf = swap_buf;
455 }
456 resetPQExpBuffer(query_buf);
457
458 added_nl_pos = -1;
459 /* we need not do psql_scan_reset() here */
460 }
461 else
462 {
463 /* if interactive, warn about non-executed query */
464 if (pset.cur_cmd_interactive)
465 pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block");
466 /* fake an OK result for purposes of loop checks */
467 success = true;
468 slashCmdStatus = PSQL_CMD_SEND;
469 pset.stmt_lineno = 1;
470 /* note that query_buf doesn't change state */
471 }
472 }
473 else if (scan_result == PSCAN_BACKSLASH)
474 {
475 /* handle backslash command */
476
477 /*
478 * If we added a newline to query_buf, and nothing else has
479 * been inserted in query_buf by the lexer, then strip off the
480 * newline again. This avoids any change to query_buf when a
481 * line contains only a backslash command. Also, in this
482 * situation we force out any previous lines as a separate
483 * history entry; we don't want SQL and backslash commands
484 * intermixed in history if at all possible.
485 */
486 if (query_buf->len == added_nl_pos)
487 {
488 query_buf->data[--query_buf->len] = '\0';
489 pg_send_history(history_buf);
490 }
491 added_nl_pos = -1;
492
493 /* save backslash command in history */
494 if (pset.cur_cmd_interactive && !line_saved_in_history)
495 {
496 pg_append_history(line, history_buf);
497 pg_send_history(history_buf);
498 line_saved_in_history = true;
499 }
500
501 /* execute backslash command */
502 slashCmdStatus = HandleSlashCmds(scan_state,
503 cond_stack,
504 query_buf,
505 previous_buf);
506
507 success = slashCmdStatus != PSQL_CMD_ERROR;
508
509 /*
510 * Resetting stmt_lineno after a backslash command isn't
511 * always appropriate, but it's what we've done historically
512 * and there have been few complaints.
513 */
514 pset.stmt_lineno = 1;
515
516 if (slashCmdStatus == PSQL_CMD_SEND)
517 {
518 /* should not see this in inactive branch */
519 Assert(conditional_active(cond_stack));
520
521 success = SendQuery(query_buf->data);
522
523 /* transfer query to previous_buf by pointer-swapping */
524 {
525 PQExpBuffer swap_buf = previous_buf;
526
527 previous_buf = query_buf;
528 query_buf = swap_buf;
529 }
530 resetPQExpBuffer(query_buf);
531
532 /* flush any paren nesting info after forced send */
533 psql_scan_reset(scan_state);
534 }
535 else if (slashCmdStatus == PSQL_CMD_NEWEDIT)
536 {
537 /* should not see this in inactive branch */
538 Assert(conditional_active(cond_stack));
539 /* ensure what came back from editing ends in a newline */
540 if (query_buf->len > 0 &&
541 query_buf->data[query_buf->len - 1] != '\n')
542 appendPQExpBufferChar(query_buf, '\n');
543 /* rescan query_buf as new input */
544 psql_scan_finish(scan_state);
545 free(line);
546 line = pg_strdup(query_buf->data);
547 resetPQExpBuffer(query_buf);
548 /* reset parsing state since we are rescanning whole line */
549 psql_scan_reset(scan_state);
550 psql_scan_setup(scan_state, line, strlen(line),
551 pset.encoding, standard_strings());
552 line_saved_in_history = false;
553 prompt_status = PROMPT_READY;
554 /* we'll want to redisplay after parsing what we have */
555 need_redisplay = true;
556 }
557 else if (slashCmdStatus == PSQL_CMD_TERMINATE)
558 break;
559 }
560
561 /* fall out of loop if lexer reached EOL */
562 if (scan_result == PSCAN_INCOMPLETE ||
563 scan_result == PSCAN_EOL)
564 break;
565 }
566
567 /* Add line to pending history if we didn't execute anything yet */
568 if (pset.cur_cmd_interactive && !line_saved_in_history)
569 pg_append_history(line, history_buf);
570
571 psql_scan_finish(scan_state);
572 free(line);
573
574 if (slashCmdStatus == PSQL_CMD_TERMINATE)
575 {
576 successResult = EXIT_SUCCESS;
577 break;
578 }
579
580 if (!pset.cur_cmd_interactive)
581 {
582 if (!success && die_on_error)
583 successResult = EXIT_USER;
584 /* Have we lost the db connection? */
585 else if (!pset.db)
586 successResult = EXIT_BADCONN;
587 }
588 } /* while !endoffile/session */
589
590 /*
591 * If we have a non-semicolon-terminated query at the end of file, we
592 * process it unless the input source is interactive --- in that case it
593 * seems better to go ahead and quit. Also skip if this is an error exit.
594 */
595 if (query_buf->len > 0 && !pset.cur_cmd_interactive &&
596 successResult == EXIT_SUCCESS)
597 {
598 /* save query in history */
599 /* currently unneeded since we don't use this block if interactive */
600 #ifdef NOT_USED
601 if (pset.cur_cmd_interactive)
602 pg_send_history(history_buf);
603 #endif
604
605 /* execute query unless we're in an inactive \if branch */
606 if (conditional_active(cond_stack))
607 {
608 success = SendQuery(query_buf->data);
609 }
610 else
611 {
612 if (pset.cur_cmd_interactive)
613 pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block");
614 success = true;
615 }
616
617 if (!success && die_on_error)
618 successResult = EXIT_USER;
619 else if (pset.db == NULL)
620 successResult = EXIT_BADCONN;
621 }
622
623 /*
624 * Check for unbalanced \if-\endifs unless user explicitly quit, or the
625 * script is erroring out
626 */
627 if (slashCmdStatus != PSQL_CMD_TERMINATE &&
628 successResult != EXIT_USER &&
629 !conditional_stack_empty(cond_stack))
630 {
631 pg_log_error("reached EOF without finding closing \\endif(s)");
632 if (die_on_error && !pset.cur_cmd_interactive)
633 successResult = EXIT_USER;
634 }
635
636 /*
637 * Let's just make real sure the SIGINT handler won't try to use
638 * sigint_interrupt_jmp after we exit this routine. If there is an outer
639 * MainLoop instance, it will reset sigint_interrupt_jmp to point to
640 * itself at the top of its loop, before any further interactive input
641 * happens.
642 */
643 sigint_interrupt_enabled = false;
644
645 destroyPQExpBuffer(query_buf);
646 destroyPQExpBuffer(previous_buf);
647 destroyPQExpBuffer(history_buf);
648
649 psql_scan_destroy(scan_state);
650 conditional_stack_destroy(cond_stack);
651
652 pset.cur_cmd_source = prev_cmd_source;
653 pset.cur_cmd_interactive = prev_cmd_interactive;
654 pset.lineno = prev_lineno;
655
656 return successResult;
657 } /* MainLoop() */
658