1 /*
2  * psql - the PostgreSQL interactive terminal
3  *
4  * Copyright (c) 2000-2016, 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 	volatile PQExpBuffer query_buf;		/* buffer for query being accumulated */
39 	volatile PQExpBuffer previous_buf;	/* if there isn't anything in the new
40 										 * buffer yet, use this one for \e,
41 										 * etc. */
42 	PQExpBuffer history_buf;	/* earlier lines of a multi-line command, not
43 								 * yet saved to readline history */
44 	char	   *line;			/* current line of input */
45 	int			added_nl_pos;
46 	bool		success;
47 	bool		line_saved_in_history;
48 	volatile int successResult = EXIT_SUCCESS;
49 	volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
50 	volatile promptStatus_t prompt_status = PROMPT_READY;
51 	volatile int count_eof = 0;
52 	volatile bool die_on_error = false;
53 
54 	/* Save the prior command source */
55 	FILE	   *prev_cmd_source;
56 	bool		prev_cmd_interactive;
57 	uint64		prev_lineno;
58 
59 	/* Save old settings */
60 	prev_cmd_source = pset.cur_cmd_source;
61 	prev_cmd_interactive = pset.cur_cmd_interactive;
62 	prev_lineno = pset.lineno;
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 
73 	query_buf = createPQExpBuffer();
74 	previous_buf = createPQExpBuffer();
75 	history_buf = createPQExpBuffer();
76 	if (PQExpBufferBroken(query_buf) ||
77 		PQExpBufferBroken(previous_buf) ||
78 		PQExpBufferBroken(history_buf))
79 	{
80 		psql_error("out of memory\n");
81 		exit(EXIT_FAILURE);
82 	}
83 
84 	/* main loop to get queries and execute them */
85 	while (successResult == EXIT_SUCCESS)
86 	{
87 		/*
88 		 * Clean up after a previous Control-C
89 		 */
90 		if (cancel_pressed)
91 		{
92 			if (!pset.cur_cmd_interactive)
93 			{
94 				/*
95 				 * You get here if you stopped a script with Ctrl-C.
96 				 */
97 				successResult = EXIT_USER;
98 				break;
99 			}
100 
101 			cancel_pressed = false;
102 		}
103 
104 		/*
105 		 * Establish longjmp destination for exiting from wait-for-input. We
106 		 * must re-do this each time through the loop for safety, since the
107 		 * jmpbuf might get changed during command execution.
108 		 */
109 		if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
110 		{
111 			/* got here with longjmp */
112 
113 			/* reset parsing state */
114 			psql_scan_finish(scan_state);
115 			psql_scan_reset(scan_state);
116 			resetPQExpBuffer(query_buf);
117 			resetPQExpBuffer(history_buf);
118 			count_eof = 0;
119 			slashCmdStatus = PSQL_CMD_UNKNOWN;
120 			prompt_status = PROMPT_READY;
121 			pset.stmt_lineno = 1;
122 			cancel_pressed = false;
123 
124 			if (pset.cur_cmd_interactive)
125 				putc('\n', stdout);
126 			else
127 			{
128 				successResult = EXIT_USER;
129 				break;
130 			}
131 		}
132 
133 		fflush(stdout);
134 
135 		/*
136 		 * get another line
137 		 */
138 		if (pset.cur_cmd_interactive)
139 		{
140 			/* May need to reset prompt, eg after \r command */
141 			if (query_buf->len == 0)
142 				prompt_status = PROMPT_READY;
143 			line = gets_interactive(get_prompt(prompt_status), query_buf);
144 		}
145 		else
146 		{
147 			line = gets_fromFile(source);
148 			if (!line && ferror(source))
149 				successResult = EXIT_FAILURE;
150 		}
151 
152 		/*
153 		 * query_buf holds query already accumulated.  line is the malloc'd
154 		 * new line of input (note it must be freed before looping around!)
155 		 */
156 
157 		/* No more input.  Time to quit, or \i done */
158 		if (line == NULL)
159 		{
160 			if (pset.cur_cmd_interactive)
161 			{
162 				/* This tries to mimic bash's IGNOREEOF feature. */
163 				count_eof++;
164 
165 				if (count_eof < GetVariableNum(pset.vars, "IGNOREEOF", 0, 10, false))
166 				{
167 					if (!pset.quiet)
168 						printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);
169 					continue;
170 				}
171 
172 				puts(pset.quiet ? "" : "\\q");
173 			}
174 			break;
175 		}
176 
177 		count_eof = 0;
178 
179 		pset.lineno++;
180 
181 		/* ignore UTF-8 Unicode byte-order mark */
182 		if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0)
183 			memmove(line, line + 3, strlen(line + 3) + 1);
184 
185 		/* Detect attempts to run custom-format dumps as SQL scripts */
186 		if (pset.lineno == 1 && !pset.cur_cmd_interactive &&
187 			strncmp(line, "PGDMP", 5) == 0)
188 		{
189 			free(line);
190 			puts(_("The input is a PostgreSQL custom-format dump.\n"
191 				   "Use the pg_restore command-line client to restore this dump to a database.\n"));
192 			fflush(stdout);
193 			successResult = EXIT_FAILURE;
194 			break;
195 		}
196 
197 		/* no further processing of empty lines, unless within a literal */
198 		if (line[0] == '\0' && !psql_scan_in_quote(scan_state))
199 		{
200 			free(line);
201 			continue;
202 		}
203 
204 		/* A request for help? Be friendly and give them some guidance */
205 		if (pset.cur_cmd_interactive && query_buf->len == 0 &&
206 			pg_strncasecmp(line, "help", 4) == 0 &&
207 			(line[4] == '\0' || line[4] == ';' || isspace((unsigned char) line[4])))
208 		{
209 			free(line);
210 			puts(_("You are using psql, the command-line interface to PostgreSQL."));
211 			printf(_("Type:  \\copyright for distribution terms\n"
212 					 "       \\h for help with SQL commands\n"
213 					 "       \\? for help with psql commands\n"
214 				  "       \\g or terminate with semicolon to execute query\n"
215 					 "       \\q to quit\n"));
216 
217 			fflush(stdout);
218 			continue;
219 		}
220 
221 		/* echo back if flag is set, unless interactive */
222 		if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive)
223 		{
224 			puts(line);
225 			fflush(stdout);
226 		}
227 
228 		/* insert newlines into query buffer between source lines */
229 		if (query_buf->len > 0)
230 		{
231 			appendPQExpBufferChar(query_buf, '\n');
232 			added_nl_pos = query_buf->len;
233 		}
234 		else
235 			added_nl_pos = -1;	/* flag we didn't add one */
236 
237 		/* Setting this will not have effect until next line. */
238 		die_on_error = pset.on_error_stop;
239 
240 		/*
241 		 * Parse line, looking for command separators.
242 		 */
243 		psql_scan_setup(scan_state, line, strlen(line),
244 						pset.encoding, standard_strings());
245 		success = true;
246 		line_saved_in_history = false;
247 
248 		while (success || !die_on_error)
249 		{
250 			PsqlScanResult scan_result;
251 			promptStatus_t prompt_tmp = prompt_status;
252 			size_t		pos_in_query;
253 			char	   *tmp_line;
254 
255 			pos_in_query = query_buf->len;
256 			scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
257 			prompt_status = prompt_tmp;
258 
259 			if (PQExpBufferBroken(query_buf))
260 			{
261 				psql_error("out of memory\n");
262 				exit(EXIT_FAILURE);
263 			}
264 
265 			/*
266 			 * Increase statement line number counter for each linebreak added
267 			 * to the query buffer by the last psql_scan() call. There only
268 			 * will be ones to add when navigating to a statement in
269 			 * readline's history containing newlines.
270 			 */
271 			tmp_line = query_buf->data + pos_in_query;
272 			while (*tmp_line != '\0')
273 			{
274 				if (*(tmp_line++) == '\n')
275 					pset.stmt_lineno++;
276 			}
277 
278 			if (scan_result == PSCAN_EOL)
279 				pset.stmt_lineno++;
280 
281 			/*
282 			 * Send command if semicolon found, or if end of line and we're in
283 			 * single-line mode.
284 			 */
285 			if (scan_result == PSCAN_SEMICOLON ||
286 				(scan_result == PSCAN_EOL && pset.singleline))
287 			{
288 				/*
289 				 * Save query in history.  We use history_buf to accumulate
290 				 * multi-line queries into a single history entry.
291 				 */
292 				if (pset.cur_cmd_interactive && !line_saved_in_history)
293 				{
294 					pg_append_history(line, history_buf);
295 					pg_send_history(history_buf);
296 					line_saved_in_history = true;
297 				}
298 
299 				/* execute query */
300 				success = SendQuery(query_buf->data);
301 				slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
302 				pset.stmt_lineno = 1;
303 
304 				/* transfer query to previous_buf by pointer-swapping */
305 				{
306 					PQExpBuffer swap_buf = previous_buf;
307 
308 					previous_buf = query_buf;
309 					query_buf = swap_buf;
310 				}
311 				resetPQExpBuffer(query_buf);
312 
313 				added_nl_pos = -1;
314 				/* we need not do psql_scan_reset() here */
315 			}
316 			else if (scan_result == PSCAN_BACKSLASH)
317 			{
318 				/* handle backslash command */
319 
320 				/*
321 				 * If we added a newline to query_buf, and nothing else has
322 				 * been inserted in query_buf by the lexer, then strip off the
323 				 * newline again.  This avoids any change to query_buf when a
324 				 * line contains only a backslash command.  Also, in this
325 				 * situation we force out any previous lines as a separate
326 				 * history entry; we don't want SQL and backslash commands
327 				 * intermixed in history if at all possible.
328 				 */
329 				if (query_buf->len == added_nl_pos)
330 				{
331 					query_buf->data[--query_buf->len] = '\0';
332 					pg_send_history(history_buf);
333 				}
334 				added_nl_pos = -1;
335 
336 				/* save backslash command in history */
337 				if (pset.cur_cmd_interactive && !line_saved_in_history)
338 				{
339 					pg_append_history(line, history_buf);
340 					pg_send_history(history_buf);
341 					line_saved_in_history = true;
342 				}
343 
344 				/* execute backslash command */
345 				slashCmdStatus = HandleSlashCmds(scan_state,
346 												 query_buf->len > 0 ?
347 												 query_buf : previous_buf);
348 
349 				success = slashCmdStatus != PSQL_CMD_ERROR;
350 				pset.stmt_lineno = 1;
351 
352 				if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_NEWEDIT) &&
353 					query_buf->len == 0)
354 				{
355 					/* copy previous buffer to current for handling */
356 					appendPQExpBufferStr(query_buf, previous_buf->data);
357 				}
358 
359 				if (slashCmdStatus == PSQL_CMD_SEND)
360 				{
361 					success = SendQuery(query_buf->data);
362 
363 					/* transfer query to previous_buf by pointer-swapping */
364 					{
365 						PQExpBuffer swap_buf = previous_buf;
366 
367 						previous_buf = query_buf;
368 						query_buf = swap_buf;
369 					}
370 					resetPQExpBuffer(query_buf);
371 
372 					/* flush any paren nesting info after forced send */
373 					psql_scan_reset(scan_state);
374 				}
375 				else if (slashCmdStatus == PSQL_CMD_NEWEDIT)
376 				{
377 					/* rescan query_buf as new input */
378 					psql_scan_finish(scan_state);
379 					free(line);
380 					line = pg_strdup(query_buf->data);
381 					resetPQExpBuffer(query_buf);
382 					/* reset parsing state since we are rescanning whole line */
383 					psql_scan_reset(scan_state);
384 					psql_scan_setup(scan_state, line, strlen(line),
385 									pset.encoding, standard_strings());
386 					line_saved_in_history = false;
387 					prompt_status = PROMPT_READY;
388 				}
389 				else if (slashCmdStatus == PSQL_CMD_TERMINATE)
390 					break;
391 			}
392 
393 			/* fall out of loop if lexer reached EOL */
394 			if (scan_result == PSCAN_INCOMPLETE ||
395 				scan_result == PSCAN_EOL)
396 				break;
397 		}
398 
399 		/* Add line to pending history if we didn't execute anything yet */
400 		if (pset.cur_cmd_interactive && !line_saved_in_history)
401 			pg_append_history(line, history_buf);
402 
403 		psql_scan_finish(scan_state);
404 		free(line);
405 
406 		if (slashCmdStatus == PSQL_CMD_TERMINATE)
407 		{
408 			successResult = EXIT_SUCCESS;
409 			break;
410 		}
411 
412 		if (!pset.cur_cmd_interactive)
413 		{
414 			if (!success && die_on_error)
415 				successResult = EXIT_USER;
416 			/* Have we lost the db connection? */
417 			else if (!pset.db)
418 				successResult = EXIT_BADCONN;
419 		}
420 	}							/* while !endoffile/session */
421 
422 	/*
423 	 * Process query at the end of file without a semicolon
424 	 */
425 	if (query_buf->len > 0 && !pset.cur_cmd_interactive &&
426 		successResult == EXIT_SUCCESS)
427 	{
428 		/* save query in history */
429 		if (pset.cur_cmd_interactive)
430 			pg_send_history(history_buf);
431 
432 		/* execute query */
433 		success = SendQuery(query_buf->data);
434 
435 		if (!success && die_on_error)
436 			successResult = EXIT_USER;
437 		else if (pset.db == NULL)
438 			successResult = EXIT_BADCONN;
439 	}
440 
441 	/*
442 	 * Let's just make real sure the SIGINT handler won't try to use
443 	 * sigint_interrupt_jmp after we exit this routine.  If there is an outer
444 	 * MainLoop instance, it will reset sigint_interrupt_jmp to point to
445 	 * itself at the top of its loop, before any further interactive input
446 	 * happens.
447 	 */
448 	sigint_interrupt_enabled = false;
449 
450 	destroyPQExpBuffer(query_buf);
451 	destroyPQExpBuffer(previous_buf);
452 	destroyPQExpBuffer(history_buf);
453 
454 	psql_scan_destroy(scan_state);
455 
456 	pset.cur_cmd_source = prev_cmd_source;
457 	pset.cur_cmd_interactive = prev_cmd_interactive;
458 	pset.lineno = prev_lineno;
459 
460 	return successResult;
461 }	/* MainLoop() */
462