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