1 /*
2 * psql - the PostgreSQL interactive terminal
3 *
4 * Copyright (c) 2000-2017, 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 "mb/pg_wchar.h"
18
19
20 /* callback functions for our flex lexer */
21 const PsqlScanCallbacks psqlscan_callbacks = {
22 psql_get_variable,
23 psql_error
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 */
34 int
MainLoop(FILE * source)35 MainLoop(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 psql_error("out of memory\n");
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 psql_error("\\if: escaped\n");
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 /* A request for help? Be friendly and give them some guidance */
220 if (pset.cur_cmd_interactive && query_buf->len == 0 &&
221 pg_strncasecmp(line, "help", 4) == 0 &&
222 (line[4] == '\0' || line[4] == ';' || isspace((unsigned char) line[4])))
223 {
224 free(line);
225 puts(_("You are using psql, the command-line interface to PostgreSQL."));
226 printf(_("Type: \\copyright for distribution terms\n"
227 " \\h for help with SQL commands\n"
228 " \\? for help with psql commands\n"
229 " \\g or terminate with semicolon to execute query\n"
230 " \\q to quit\n"));
231
232 fflush(stdout);
233 continue;
234 }
235
236 /* echo back if flag is set, unless interactive */
237 if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive)
238 {
239 puts(line);
240 fflush(stdout);
241 }
242
243 /* insert newlines into query buffer between source lines */
244 if (query_buf->len > 0)
245 {
246 appendPQExpBufferChar(query_buf, '\n');
247 added_nl_pos = query_buf->len;
248 }
249 else
250 added_nl_pos = -1; /* flag we didn't add one */
251
252 /* Setting this will not have effect until next line. */
253 die_on_error = pset.on_error_stop;
254
255 /*
256 * Parse line, looking for command separators.
257 */
258 psql_scan_setup(scan_state, line, strlen(line),
259 pset.encoding, standard_strings());
260 success = true;
261 line_saved_in_history = false;
262
263 while (success || !die_on_error)
264 {
265 PsqlScanResult scan_result;
266 promptStatus_t prompt_tmp = prompt_status;
267 size_t pos_in_query;
268 char *tmp_line;
269
270 pos_in_query = query_buf->len;
271 scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
272 prompt_status = prompt_tmp;
273
274 if (PQExpBufferBroken(query_buf))
275 {
276 psql_error("out of memory\n");
277 exit(EXIT_FAILURE);
278 }
279
280 /*
281 * Increase statement line number counter for each linebreak added
282 * to the query buffer by the last psql_scan() call. There only
283 * will be ones to add when navigating to a statement in
284 * readline's history containing newlines.
285 */
286 tmp_line = query_buf->data + pos_in_query;
287 while (*tmp_line != '\0')
288 {
289 if (*(tmp_line++) == '\n')
290 pset.stmt_lineno++;
291 }
292
293 if (scan_result == PSCAN_EOL)
294 pset.stmt_lineno++;
295
296 /*
297 * Send command if semicolon found, or if end of line and we're in
298 * single-line mode.
299 */
300 if (scan_result == PSCAN_SEMICOLON ||
301 (scan_result == PSCAN_EOL && pset.singleline))
302 {
303 /*
304 * Save line in history. We use history_buf to accumulate
305 * multi-line queries into a single history entry. Note that
306 * history accumulation works on input lines, so it doesn't
307 * matter whether the query will be ignored due to \if.
308 */
309 if (pset.cur_cmd_interactive && !line_saved_in_history)
310 {
311 pg_append_history(line, history_buf);
312 pg_send_history(history_buf);
313 line_saved_in_history = true;
314 }
315
316 /* execute query unless we're in an inactive \if branch */
317 if (conditional_active(cond_stack))
318 {
319 success = SendQuery(query_buf->data);
320 slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
321 pset.stmt_lineno = 1;
322
323 /* transfer query to previous_buf by pointer-swapping */
324 {
325 PQExpBuffer swap_buf = previous_buf;
326
327 previous_buf = query_buf;
328 query_buf = swap_buf;
329 }
330 resetPQExpBuffer(query_buf);
331
332 added_nl_pos = -1;
333 /* we need not do psql_scan_reset() here */
334 }
335 else
336 {
337 /* if interactive, warn about non-executed query */
338 if (pset.cur_cmd_interactive)
339 psql_error("query ignored; use \\endif or Ctrl-C to exit current \\if block\n");
340 /* fake an OK result for purposes of loop checks */
341 success = true;
342 slashCmdStatus = PSQL_CMD_SEND;
343 pset.stmt_lineno = 1;
344 /* note that query_buf doesn't change state */
345 }
346 }
347 else if (scan_result == PSCAN_BACKSLASH)
348 {
349 /* handle backslash command */
350
351 /*
352 * If we added a newline to query_buf, and nothing else has
353 * been inserted in query_buf by the lexer, then strip off the
354 * newline again. This avoids any change to query_buf when a
355 * line contains only a backslash command. Also, in this
356 * situation we force out any previous lines as a separate
357 * history entry; we don't want SQL and backslash commands
358 * intermixed in history if at all possible.
359 */
360 if (query_buf->len == added_nl_pos)
361 {
362 query_buf->data[--query_buf->len] = '\0';
363 pg_send_history(history_buf);
364 }
365 added_nl_pos = -1;
366
367 /* save backslash command in history */
368 if (pset.cur_cmd_interactive && !line_saved_in_history)
369 {
370 pg_append_history(line, history_buf);
371 pg_send_history(history_buf);
372 line_saved_in_history = true;
373 }
374
375 /* execute backslash command */
376 slashCmdStatus = HandleSlashCmds(scan_state,
377 cond_stack,
378 query_buf,
379 previous_buf);
380
381 success = slashCmdStatus != PSQL_CMD_ERROR;
382
383 /*
384 * Resetting stmt_lineno after a backslash command isn't
385 * always appropriate, but it's what we've done historically
386 * and there have been few complaints.
387 */
388 pset.stmt_lineno = 1;
389
390 if (slashCmdStatus == PSQL_CMD_SEND)
391 {
392 /* should not see this in inactive branch */
393 Assert(conditional_active(cond_stack));
394
395 success = SendQuery(query_buf->data);
396
397 /* transfer query to previous_buf by pointer-swapping */
398 {
399 PQExpBuffer swap_buf = previous_buf;
400
401 previous_buf = query_buf;
402 query_buf = swap_buf;
403 }
404 resetPQExpBuffer(query_buf);
405
406 /* flush any paren nesting info after forced send */
407 psql_scan_reset(scan_state);
408 }
409 else if (slashCmdStatus == PSQL_CMD_NEWEDIT)
410 {
411 /* should not see this in inactive branch */
412 Assert(conditional_active(cond_stack));
413 /* rescan query_buf as new input */
414 psql_scan_finish(scan_state);
415 free(line);
416 line = pg_strdup(query_buf->data);
417 resetPQExpBuffer(query_buf);
418 /* reset parsing state since we are rescanning whole line */
419 psql_scan_reset(scan_state);
420 psql_scan_setup(scan_state, line, strlen(line),
421 pset.encoding, standard_strings());
422 line_saved_in_history = false;
423 prompt_status = PROMPT_READY;
424 }
425 else if (slashCmdStatus == PSQL_CMD_TERMINATE)
426 break;
427 }
428
429 /* fall out of loop if lexer reached EOL */
430 if (scan_result == PSCAN_INCOMPLETE ||
431 scan_result == PSCAN_EOL)
432 break;
433 }
434
435 /* Add line to pending history if we didn't execute anything yet */
436 if (pset.cur_cmd_interactive && !line_saved_in_history)
437 pg_append_history(line, history_buf);
438
439 psql_scan_finish(scan_state);
440 free(line);
441
442 if (slashCmdStatus == PSQL_CMD_TERMINATE)
443 {
444 successResult = EXIT_SUCCESS;
445 break;
446 }
447
448 if (!pset.cur_cmd_interactive)
449 {
450 if (!success && die_on_error)
451 successResult = EXIT_USER;
452 /* Have we lost the db connection? */
453 else if (!pset.db)
454 successResult = EXIT_BADCONN;
455 }
456 } /* while !endoffile/session */
457
458 /*
459 * Process query at the end of file without a semicolon
460 */
461 if (query_buf->len > 0 && !pset.cur_cmd_interactive &&
462 successResult == EXIT_SUCCESS)
463 {
464 /* save query in history */
465 if (pset.cur_cmd_interactive)
466 pg_send_history(history_buf);
467
468 /* execute query unless we're in an inactive \if branch */
469 if (conditional_active(cond_stack))
470 {
471 success = SendQuery(query_buf->data);
472 }
473 else
474 {
475 if (pset.cur_cmd_interactive)
476 psql_error("query ignored; use \\endif or Ctrl-C to exit current \\if block\n");
477 success = true;
478 }
479
480 if (!success && die_on_error)
481 successResult = EXIT_USER;
482 else if (pset.db == NULL)
483 successResult = EXIT_BADCONN;
484 }
485
486 /*
487 * Check for unbalanced \if-\endifs unless user explicitly quit, or the
488 * script is erroring out
489 */
490 if (slashCmdStatus != PSQL_CMD_TERMINATE &&
491 successResult != EXIT_USER &&
492 !conditional_stack_empty(cond_stack))
493 {
494 psql_error("reached EOF without finding closing \\endif(s)\n");
495 if (die_on_error && !pset.cur_cmd_interactive)
496 successResult = EXIT_USER;
497 }
498
499 /*
500 * Let's just make real sure the SIGINT handler won't try to use
501 * sigint_interrupt_jmp after we exit this routine. If there is an outer
502 * MainLoop instance, it will reset sigint_interrupt_jmp to point to
503 * itself at the top of its loop, before any further interactive input
504 * happens.
505 */
506 sigint_interrupt_enabled = false;
507
508 destroyPQExpBuffer(query_buf);
509 destroyPQExpBuffer(previous_buf);
510 destroyPQExpBuffer(history_buf);
511
512 psql_scan_destroy(scan_state);
513 conditional_stack_destroy(cond_stack);
514
515 pset.cur_cmd_source = prev_cmd_source;
516 pset.cur_cmd_interactive = prev_cmd_interactive;
517 pset.lineno = prev_lineno;
518
519 return successResult;
520 } /* MainLoop() */
521