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