1 /* -*-pgsql-c-*- */
2 /*
3  * Scanner for the configuration file
4  *
5  * Copyright (c) 2000-2021, PostgreSQL Global Development Group
6  *
7  * src/backend/utils/misc/guc-file.l
8  */
9 
10 %{
11 
12 #include "postgres.h"
13 
14 #include <ctype.h>
15 #include <unistd.h>
16 
17 #include "mb/pg_wchar.h"
18 #include "miscadmin.h"
19 #include "storage/fd.h"
20 #include "utils/guc.h"
21 
22 
23 /*
24  * flex emits a yy_fatal_error() function that it calls in response to
25  * critical errors like malloc failure, file I/O errors, and detection of
26  * internal inconsistency.  That function prints a message and calls exit().
27  * Mutate it to instead call our handler, which jumps out of the parser.
28  */
29 #undef fprintf
30 #define fprintf(file, fmt, msg) GUC_flex_fatal(msg)
31 
32 enum
33 {
34 	GUC_ID = 1,
35 	GUC_STRING = 2,
36 	GUC_INTEGER = 3,
37 	GUC_REAL = 4,
38 	GUC_EQUALS = 5,
39 	GUC_UNQUOTED_STRING = 6,
40 	GUC_QUALIFIED_ID = 7,
41 	GUC_EOL = 99,
42 	GUC_ERROR = 100
43 };
44 
45 static unsigned int ConfigFileLineno;
46 static const char *GUC_flex_fatal_errmsg;
47 static sigjmp_buf *GUC_flex_fatal_jmp;
48 
49 static void FreeConfigVariable(ConfigVariable *item);
50 
51 static void record_config_file_error(const char *errmsg,
52 						 const char *config_file,
53 						 int lineno,
54 						 ConfigVariable **head_p,
55 						 ConfigVariable **tail_p);
56 
57 static int	GUC_flex_fatal(const char *msg);
58 
59 /* LCOV_EXCL_START */
60 
61 %}
62 
63 %option 8bit
64 %option never-interactive
65 %option nodefault
66 %option noinput
67 %option nounput
68 %option noyywrap
69 %option warn
70 %option prefix="GUC_yy"
71 
72 
73 SIGN			("-"|"+")
74 DIGIT			[0-9]
75 HEXDIGIT		[0-9a-fA-F]
76 
77 UNIT_LETTER		[a-zA-Z]
78 
79 INTEGER			{SIGN}?({DIGIT}+|0x{HEXDIGIT}+){UNIT_LETTER}*
80 
81 EXPONENT		[Ee]{SIGN}?{DIGIT}+
82 REAL			{SIGN}?{DIGIT}*"."{DIGIT}*{EXPONENT}?
83 
84 LETTER			[A-Za-z_\200-\377]
85 LETTER_OR_DIGIT [A-Za-z_0-9\200-\377]
86 
87 ID				{LETTER}{LETTER_OR_DIGIT}*
88 QUALIFIED_ID	{ID}"."{ID}
89 
90 UNQUOTED_STRING {LETTER}({LETTER_OR_DIGIT}|[-._:/])*
91 STRING			\'([^'\\\n]|\\.|\'\')*\'
92 
93 %%
94 
95 \n				ConfigFileLineno++; return GUC_EOL;
96 [ \t\r]+		/* eat whitespace */
97 #.*				/* eat comment (.* matches anything until newline) */
98 
99 {ID}			return GUC_ID;
100 {QUALIFIED_ID}	return GUC_QUALIFIED_ID;
101 {STRING}		return GUC_STRING;
102 {UNQUOTED_STRING} return GUC_UNQUOTED_STRING;
103 {INTEGER}		return GUC_INTEGER;
104 {REAL}			return GUC_REAL;
105 =				return GUC_EQUALS;
106 
107 .				return GUC_ERROR;
108 
109 %%
110 
111 /* LCOV_EXCL_STOP */
112 
113 /*
114  * Exported function to read and process the configuration file. The
115  * parameter indicates in what context the file is being read --- either
116  * postmaster startup (including standalone-backend startup) or SIGHUP.
117  * All options mentioned in the configuration file are set to new values.
118  * If a hard error occurs, no values will be changed.  (There can also be
119  * errors that prevent just one value from being changed.)
120  */
121 void
122 ProcessConfigFile(GucContext context)
123 {
124 	int			elevel;
125 	MemoryContext config_cxt;
126 	MemoryContext caller_cxt;
127 
128 	/*
129 	 * Config files are processed on startup (by the postmaster only) and on
130 	 * SIGHUP (by the postmaster and its children)
131 	 */
132 	Assert((context == PGC_POSTMASTER && !IsUnderPostmaster) ||
133 		   context == PGC_SIGHUP);
134 
135 	/*
136 	 * To avoid cluttering the log, only the postmaster bleats loudly about
137 	 * problems with the config file.
138 	 */
139 	elevel = IsUnderPostmaster ? DEBUG2 : LOG;
140 
141 	/*
142 	 * This function is usually called within a process-lifespan memory
143 	 * context.  To ensure that any memory leaked during GUC processing does
144 	 * not accumulate across repeated SIGHUP cycles, do the work in a private
145 	 * context that we can free at exit.
146 	 */
147 	config_cxt = AllocSetContextCreate(CurrentMemoryContext,
148 									   "config file processing",
149 									   ALLOCSET_DEFAULT_SIZES);
150 	caller_cxt = MemoryContextSwitchTo(config_cxt);
151 
152 	/*
153 	 * Read and apply the config file.  We don't need to examine the result.
154 	 */
155 	(void) ProcessConfigFileInternal(context, true, elevel);
156 
157 	/* Clean up */
158 	MemoryContextSwitchTo(caller_cxt);
159 	MemoryContextDelete(config_cxt);
160 }
161 
162 /*
163  * This function handles both actual config file (re)loads and execution of
164  * show_all_file_settings() (i.e., the pg_file_settings view).  In the latter
165  * case we don't apply any of the settings, but we make all the usual validity
166  * checks, and we return the ConfigVariable list so that it can be printed out
167  * by show_all_file_settings().
168  */
169 static ConfigVariable *
ProcessConfigFileInternal(GucContext context,bool applySettings,int elevel)170 ProcessConfigFileInternal(GucContext context, bool applySettings, int elevel)
171 {
172 	bool		error = false;
173 	bool		applying = false;
174 	const char *ConfFileWithError;
175 	ConfigVariable *item,
176 			   *head,
177 			   *tail;
178 	int			i;
179 
180 	/* Parse the main config file into a list of option names and values */
181 	ConfFileWithError = ConfigFileName;
182 	head = tail = NULL;
183 
184 	if (!ParseConfigFile(ConfigFileName, true,
185 						 NULL, 0, 0, elevel,
186 						 &head, &tail))
187 	{
188 		/* Syntax error(s) detected in the file, so bail out */
189 		error = true;
190 		goto bail_out;
191 	}
192 
193 	/*
194 	 * Parse the PG_AUTOCONF_FILENAME file, if present, after the main file to
195 	 * replace any parameters set by ALTER SYSTEM command.  Because this file
196 	 * is in the data directory, we can't read it until the DataDir has been
197 	 * set.
198 	 */
199 	if (DataDir)
200 	{
201 		if (!ParseConfigFile(PG_AUTOCONF_FILENAME, false,
202 							 NULL, 0, 0, elevel,
203 							 &head, &tail))
204 		{
205 			/* Syntax error(s) detected in the file, so bail out */
206 			error = true;
207 			ConfFileWithError = PG_AUTOCONF_FILENAME;
208 			goto bail_out;
209 		}
210 	}
211 	else
212 	{
213 		/*
214 		 * If DataDir is not set, the PG_AUTOCONF_FILENAME file cannot be
215 		 * read.  In this case, we don't want to accept any settings but
216 		 * data_directory from postgresql.conf, because they might be
217 		 * overwritten with settings in the PG_AUTOCONF_FILENAME file which
218 		 * will be read later. OTOH, since data_directory isn't allowed in the
219 		 * PG_AUTOCONF_FILENAME file, it will never be overwritten later.
220 		 */
221 		ConfigVariable *newlist = NULL;
222 
223 		/*
224 		 * Prune all items except the last "data_directory" from the list.
225 		 */
226 		for (item = head; item; item = item->next)
227 		{
228 			if (!item->ignore &&
229 				strcmp(item->name, "data_directory") == 0)
230 				newlist = item;
231 		}
232 
233 		if (newlist)
234 			newlist->next = NULL;
235 		head = tail = newlist;
236 
237 		/*
238 		 * Quick exit if data_directory is not present in file.
239 		 *
240 		 * We need not do any further processing, in particular we don't set
241 		 * PgReloadTime; that will be set soon by subsequent full loading of
242 		 * the config file.
243 		 */
244 		if (head == NULL)
245 			goto bail_out;
246 	}
247 
248 	/*
249 	 * Mark all extant GUC variables as not present in the config file. We
250 	 * need this so that we can tell below which ones have been removed from
251 	 * the file since we last processed it.
252 	 */
253 	for (i = 0; i < num_guc_variables; i++)
254 	{
255 		struct config_generic *gconf = guc_variables[i];
256 
257 		gconf->status &= ~GUC_IS_IN_FILE;
258 	}
259 
260 	/*
261 	 * Check if all the supplied option names are valid, as an additional
262 	 * quasi-syntactic check on the validity of the config file.  It is
263 	 * important that the postmaster and all backends agree on the results of
264 	 * this phase, else we will have strange inconsistencies about which
265 	 * processes accept a config file update and which don't.  Hence, unknown
266 	 * custom variable names have to be accepted without complaint.  For the
267 	 * same reason, we don't attempt to validate the options' values here.
268 	 *
269 	 * In addition, the GUC_IS_IN_FILE flag is set on each existing GUC
270 	 * variable mentioned in the file; and we detect duplicate entries in the
271 	 * file and mark the earlier occurrences as ignorable.
272 	 */
273 	for (item = head; item; item = item->next)
274 	{
275 		struct config_generic *record;
276 
277 		/* Ignore anything already marked as ignorable */
278 		if (item->ignore)
279 			continue;
280 
281 		/*
282 		 * Try to find the variable; but do not create a custom placeholder if
283 		 * it's not there already.
284 		 */
285 		record = find_option(item->name, false, true, elevel);
286 
287 		if (record)
288 		{
289 			/* If it's already marked, then this is a duplicate entry */
290 			if (record->status & GUC_IS_IN_FILE)
291 			{
292 				/*
293 				 * Mark the earlier occurrence(s) as dead/ignorable.  We could
294 				 * avoid the O(N^2) behavior here with some additional state,
295 				 * but it seems unlikely to be worth the trouble.
296 				 */
297 				ConfigVariable *pitem;
298 
299 				for (pitem = head; pitem != item; pitem = pitem->next)
300 				{
301 					if (!pitem->ignore &&
302 						strcmp(pitem->name, item->name) == 0)
303 						pitem->ignore = true;
304 				}
305 			}
306 			/* Now mark it as present in file */
307 			record->status |= GUC_IS_IN_FILE;
308 		}
309 		else if (!valid_custom_variable_name(item->name))
310 		{
311 			/* Invalid non-custom variable, so complain */
312 			ereport(elevel,
313 					(errcode(ERRCODE_UNDEFINED_OBJECT),
314 					 errmsg("unrecognized configuration parameter \"%s\" in file \"%s\" line %d",
315 							item->name,
316 							item->filename, item->sourceline)));
317 			item->errmsg = pstrdup("unrecognized configuration parameter");
318 			error = true;
319 			ConfFileWithError = item->filename;
320 		}
321 	}
322 
323 	/*
324 	 * If we've detected any errors so far, we don't want to risk applying any
325 	 * changes.
326 	 */
327 	if (error)
328 		goto bail_out;
329 
330 	/* Otherwise, set flag that we're beginning to apply changes */
331 	applying = true;
332 
333 	/*
334 	 * Check for variables having been removed from the config file, and
335 	 * revert their reset values (and perhaps also effective values) to the
336 	 * boot-time defaults.  If such a variable can't be changed after startup,
337 	 * report that and continue.
338 	 */
339 	for (i = 0; i < num_guc_variables; i++)
340 	{
341 		struct config_generic *gconf = guc_variables[i];
342 		GucStack   *stack;
343 
344 		if (gconf->reset_source != PGC_S_FILE ||
345 			(gconf->status & GUC_IS_IN_FILE))
346 			continue;
347 		if (gconf->context < PGC_SIGHUP)
348 		{
349 			/* The removal can't be effective without a restart */
350 			gconf->status |= GUC_PENDING_RESTART;
351 			ereport(elevel,
352 					(errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
353 					 errmsg("parameter \"%s\" cannot be changed without restarting the server",
354 							gconf->name)));
355 			record_config_file_error(psprintf("parameter \"%s\" cannot be changed without restarting the server",
356 											  gconf->name),
357 									 NULL, 0,
358 									 &head, &tail);
359 			error = true;
360 			continue;
361 		}
362 
363 		/* No more to do if we're just doing show_all_file_settings() */
364 		if (!applySettings)
365 			continue;
366 
367 		/*
368 		 * Reset any "file" sources to "default", else set_config_option will
369 		 * not override those settings.
370 		 */
371 		if (gconf->reset_source == PGC_S_FILE)
372 			gconf->reset_source = PGC_S_DEFAULT;
373 		if (gconf->source == PGC_S_FILE)
374 			gconf->source = PGC_S_DEFAULT;
375 		for (stack = gconf->stack; stack; stack = stack->prev)
376 		{
377 			if (stack->source == PGC_S_FILE)
378 				stack->source = PGC_S_DEFAULT;
379 		}
380 
381 		/* Now we can re-apply the wired-in default (i.e., the boot_val) */
382 		if (set_config_option(gconf->name, NULL,
383 							  context, PGC_S_DEFAULT,
384 							  GUC_ACTION_SET, true, 0, false) > 0)
385 		{
386 			/* Log the change if appropriate */
387 			if (context == PGC_SIGHUP)
388 				ereport(elevel,
389 						(errmsg("parameter \"%s\" removed from configuration file, reset to default",
390 								gconf->name)));
391 		}
392 	}
393 
394 	/*
395 	 * Restore any variables determined by environment variables or
396 	 * dynamically-computed defaults.  This is a no-op except in the case
397 	 * where one of these had been in the config file and is now removed.
398 	 *
399 	 * In particular, we *must not* do this during the postmaster's initial
400 	 * loading of the file, since the timezone functions in particular should
401 	 * be run only after initialization is complete.
402 	 *
403 	 * XXX this is an unmaintainable crock, because we have to know how to set
404 	 * (or at least what to call to set) every variable that could potentially
405 	 * have PGC_S_DYNAMIC_DEFAULT or PGC_S_ENV_VAR source. However, there's no
406 	 * time to redesign it for 9.1.
407 	 */
408 	if (context == PGC_SIGHUP && applySettings)
409 	{
410 		InitializeGUCOptionsFromEnvironment();
411 		pg_timezone_abbrev_initialize();
412 		/* this selects SQL_ASCII in processes not connected to a database */
413 		SetConfigOption("client_encoding", GetDatabaseEncodingName(),
414 						PGC_BACKEND, PGC_S_DYNAMIC_DEFAULT);
415 	}
416 
417 	/*
418 	 * Now apply the values from the config file.
419 	 */
420 	for (item = head; item; item = item->next)
421 	{
422 		char	   *pre_value = NULL;
423 		int			scres;
424 
425 		/* Ignore anything marked as ignorable */
426 		if (item->ignore)
427 			continue;
428 
429 		/* In SIGHUP cases in the postmaster, we want to report changes */
430 		if (context == PGC_SIGHUP && applySettings && !IsUnderPostmaster)
431 		{
432 			const char *preval = GetConfigOption(item->name, true, false);
433 
434 			/* If option doesn't exist yet or is NULL, treat as empty string */
435 			if (!preval)
436 				preval = "";
437 			/* must dup, else might have dangling pointer below */
438 			pre_value = pstrdup(preval);
439 		}
440 
441 		scres = set_config_option(item->name, item->value,
442 								  context, PGC_S_FILE,
443 								  GUC_ACTION_SET, applySettings, 0, false);
444 		if (scres > 0)
445 		{
446 			/* variable was updated, so log the change if appropriate */
447 			if (pre_value)
448 			{
449 				const char *post_value = GetConfigOption(item->name, true, false);
450 
451 				if (!post_value)
452 					post_value = "";
453 				if (strcmp(pre_value, post_value) != 0)
454 					ereport(elevel,
455 							(errmsg("parameter \"%s\" changed to \"%s\"",
456 									item->name, item->value)));
457 			}
458 			item->applied = true;
459 		}
460 		else if (scres == 0)
461 		{
462 			error = true;
463 			item->errmsg = pstrdup("setting could not be applied");
464 			ConfFileWithError = item->filename;
465 		}
466 		else
467 		{
468 			/* no error, but variable's active value was not changed */
469 			item->applied = true;
470 		}
471 
472 		/*
473 		 * We should update source location unless there was an error, since
474 		 * even if the active value didn't change, the reset value might have.
475 		 * (In the postmaster, there won't be a difference, but it does matter
476 		 * in backends.)
477 		 */
478 		if (scres != 0 && applySettings)
479 			set_config_sourcefile(item->name, item->filename,
480 								  item->sourceline);
481 
482 		if (pre_value)
483 			pfree(pre_value);
484 	}
485 
486 	/* Remember when we last successfully loaded the config file. */
487 	if (applySettings)
488 		PgReloadTime = GetCurrentTimestamp();
489 
490 bail_out:
491 	if (error && applySettings)
492 	{
493 		/* During postmaster startup, any error is fatal */
494 		if (context == PGC_POSTMASTER)
495 			ereport(ERROR,
496 					(errcode(ERRCODE_CONFIG_FILE_ERROR),
497 					 errmsg("configuration file \"%s\" contains errors",
498 							ConfFileWithError)));
499 		else if (applying)
500 			ereport(elevel,
501 					(errcode(ERRCODE_CONFIG_FILE_ERROR),
502 					 errmsg("configuration file \"%s\" contains errors; unaffected changes were applied",
503 							ConfFileWithError)));
504 		else
505 			ereport(elevel,
506 					(errcode(ERRCODE_CONFIG_FILE_ERROR),
507 					 errmsg("configuration file \"%s\" contains errors; no changes were applied",
508 							ConfFileWithError)));
509 	}
510 
511 	/* Successful or otherwise, return the collected data list */
512 	return head;
513 }
514 
515 /*
516  * Given a configuration file or directory location that may be a relative
517  * path, return an absolute one.  We consider the location to be relative to
518  * the directory holding the calling file, or to DataDir if no calling file.
519  */
520 static char *
AbsoluteConfigLocation(const char * location,const char * calling_file)521 AbsoluteConfigLocation(const char *location, const char *calling_file)
522 {
523 	char		abs_path[MAXPGPATH];
524 
525 	if (is_absolute_path(location))
526 		return pstrdup(location);
527 	else
528 	{
529 		if (calling_file != NULL)
530 		{
531 			strlcpy(abs_path, calling_file, sizeof(abs_path));
532 			get_parent_directory(abs_path);
533 			join_path_components(abs_path, abs_path, location);
534 			canonicalize_path(abs_path);
535 		}
536 		else
537 		{
538 			AssertState(DataDir);
539 			join_path_components(abs_path, DataDir, location);
540 			canonicalize_path(abs_path);
541 		}
542 		return pstrdup(abs_path);
543 	}
544 }
545 
546 /*
547  * Read and parse a single configuration file.  This function recurses
548  * to handle "include" directives.
549  *
550  * If "strict" is true, treat failure to open the config file as an error,
551  * otherwise just skip the file.
552  *
553  * calling_file/calling_lineno identify the source of the request.
554  * Pass NULL/0 if not recursing from an inclusion request.
555  *
556  * See ParseConfigFp for further details.  This one merely adds opening the
557  * config file rather than working from a caller-supplied file descriptor,
558  * and absolute-ifying the path name if necessary.
559  */
560 bool
ParseConfigFile(const char * config_file,bool strict,const char * calling_file,int calling_lineno,int depth,int elevel,ConfigVariable ** head_p,ConfigVariable ** tail_p)561 ParseConfigFile(const char *config_file, bool strict,
562 				const char *calling_file, int calling_lineno,
563 				int depth, int elevel,
564 				ConfigVariable **head_p,
565 				ConfigVariable **tail_p)
566 {
567 	char	   *abs_path;
568 	bool		OK = true;
569 	FILE	   *fp;
570 
571 	/*
572 	 * Reject file name that is all-blank (including empty), as that leads to
573 	 * confusion --- we'd try to read the containing directory as a file.
574 	 */
575 	if (strspn(config_file, " \t\r\n") == strlen(config_file))
576 	{
577 		ereport(elevel,
578 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
579 				 errmsg("empty configuration file name: \"%s\"",
580 						config_file)));
581 		record_config_file_error("empty configuration file name",
582 								 calling_file, calling_lineno,
583 								 head_p, tail_p);
584 		return false;
585 	}
586 
587 	/*
588 	 * Reject too-deep include nesting depth.  This is just a safety check to
589 	 * avoid dumping core due to stack overflow if an include file loops back
590 	 * to itself.  The maximum nesting depth is pretty arbitrary.
591 	 */
592 	if (depth > 10)
593 	{
594 		ereport(elevel,
595 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
596 				 errmsg("could not open configuration file \"%s\": maximum nesting depth exceeded",
597 						config_file)));
598 		record_config_file_error("nesting depth exceeded",
599 								 calling_file, calling_lineno,
600 								 head_p, tail_p);
601 		return false;
602 	}
603 
604 	abs_path = AbsoluteConfigLocation(config_file, calling_file);
605 
606 	/*
607 	 * Reject direct recursion.  Indirect recursion is also possible, but it's
608 	 * harder to detect and so doesn't seem worth the trouble.  (We test at
609 	 * this step because the canonicalization done by AbsoluteConfigLocation
610 	 * makes it more likely that a simple strcmp comparison will match.)
611 	 */
612 	if (calling_file && strcmp(abs_path, calling_file) == 0)
613 	{
614 		ereport(elevel,
615 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
616 				 errmsg("configuration file recursion in \"%s\"",
617 						calling_file)));
618 		record_config_file_error("configuration file recursion",
619 								 calling_file, calling_lineno,
620 								 head_p, tail_p);
621 		pfree(abs_path);
622 		return false;
623 	}
624 
625 	fp = AllocateFile(abs_path, "r");
626 	if (!fp)
627 	{
628 		if (strict)
629 		{
630 			ereport(elevel,
631 					(errcode_for_file_access(),
632 					 errmsg("could not open configuration file \"%s\": %m",
633 							abs_path)));
634 			record_config_file_error(psprintf("could not open file \"%s\"",
635 											  abs_path),
636 									 calling_file, calling_lineno,
637 									 head_p, tail_p);
638 			OK = false;
639 		}
640 		else
641 		{
642 			ereport(LOG,
643 					(errmsg("skipping missing configuration file \"%s\"",
644 							abs_path)));
645 		}
646 		goto cleanup;
647 	}
648 
649 	OK = ParseConfigFp(fp, abs_path, depth, elevel, head_p, tail_p);
650 
651 cleanup:
652 	if (fp)
653 		FreeFile(fp);
654 	pfree(abs_path);
655 
656 	return OK;
657 }
658 
659 /*
660  * Capture an error message in the ConfigVariable list returned by
661  * config file parsing.
662  */
663 static void
record_config_file_error(const char * errmsg,const char * config_file,int lineno,ConfigVariable ** head_p,ConfigVariable ** tail_p)664 record_config_file_error(const char *errmsg,
665 						 const char *config_file,
666 						 int lineno,
667 						 ConfigVariable **head_p,
668 						 ConfigVariable **tail_p)
669 {
670 	ConfigVariable *item;
671 
672 	item = palloc(sizeof *item);
673 	item->name = NULL;
674 	item->value = NULL;
675 	item->errmsg = pstrdup(errmsg);
676 	item->filename = config_file ? pstrdup(config_file) : NULL;
677 	item->sourceline = lineno;
678 	item->ignore = true;
679 	item->applied = false;
680 	item->next = NULL;
681 	if (*head_p == NULL)
682 		*head_p = item;
683 	else
684 		(*tail_p)->next = item;
685 	*tail_p = item;
686 }
687 
688 /*
689  * Flex fatal errors bring us here.  Stash the error message and jump back to
690  * ParseConfigFp().  Assume all msg arguments point to string constants; this
691  * holds for flex 2.5.31 (earliest we support) and flex 2.5.35 (latest as of
692  * this writing).  Otherwise, we would need to copy the message.
693  *
694  * We return "int" since this takes the place of calls to fprintf().
695 */
696 static int
GUC_flex_fatal(const char * msg)697 GUC_flex_fatal(const char *msg)
698 {
699 	GUC_flex_fatal_errmsg = msg;
700 	siglongjmp(*GUC_flex_fatal_jmp, 1);
701 	return 0;					/* keep compiler quiet */
702 }
703 
704 /*
705  * Read and parse a single configuration file.  This function recurses
706  * to handle "include" directives.
707  *
708  * Input parameters:
709  *	fp: file pointer from AllocateFile for the configuration file to parse
710  *	config_file: absolute or relative path name of the configuration file
711  *	depth: recursion depth (should be 0 in the outermost call)
712  *	elevel: error logging level to use
713  * Input/Output parameters:
714  *	head_p, tail_p: head and tail of linked list of name/value pairs
715  *
716  * *head_p and *tail_p must be initialized, either to NULL or valid pointers
717  * to a ConfigVariable list, before calling the outer recursion level.  Any
718  * name-value pairs read from the input file(s) will be appended to the list.
719  * Error reports will also be appended to the list, if elevel < ERROR.
720  *
721  * Returns TRUE if successful, FALSE if an error occurred.  The error has
722  * already been ereport'd, it is only necessary for the caller to clean up
723  * its own state and release the ConfigVariable list.
724  *
725  * Note: if elevel >= ERROR then an error will not return control to the
726  * caller, so there is no need to check the return value in that case.
727  *
728  * Note: this function is used to parse not only postgresql.conf, but
729  * various other configuration files that use the same "name = value"
730  * syntax.  Hence, do not do anything here or in the subsidiary routines
731  * ParseConfigFile/ParseConfigDirectory that assumes we are processing
732  * GUCs specifically.
733  */
734 bool
ParseConfigFp(FILE * fp,const char * config_file,int depth,int elevel,ConfigVariable ** head_p,ConfigVariable ** tail_p)735 ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
736 			  ConfigVariable **head_p, ConfigVariable **tail_p)
737 {
738 	volatile bool OK = true;
739 	unsigned int save_ConfigFileLineno = ConfigFileLineno;
740 	sigjmp_buf *save_GUC_flex_fatal_jmp = GUC_flex_fatal_jmp;
741 	sigjmp_buf	flex_fatal_jmp;
742 	volatile YY_BUFFER_STATE lex_buffer = NULL;
743 	int			errorcount;
744 	int			token;
745 
746 	if (sigsetjmp(flex_fatal_jmp, 1) == 0)
747 		GUC_flex_fatal_jmp = &flex_fatal_jmp;
748 	else
749 	{
750 		/*
751 		 * Regain control after a fatal, internal flex error.  It may have
752 		 * corrupted parser state.  Consequently, abandon the file, but trust
753 		 * that the state remains sane enough for yy_delete_buffer().
754 		 */
755 		elog(elevel, "%s at file \"%s\" line %u",
756 			 GUC_flex_fatal_errmsg, config_file, ConfigFileLineno);
757 		record_config_file_error(GUC_flex_fatal_errmsg,
758 								 config_file, ConfigFileLineno,
759 								 head_p, tail_p);
760 		OK = false;
761 		goto cleanup;
762 	}
763 
764 	/*
765 	 * Parse
766 	 */
767 	ConfigFileLineno = 1;
768 	errorcount = 0;
769 
770 	lex_buffer = yy_create_buffer(fp, YY_BUF_SIZE);
771 	yy_switch_to_buffer(lex_buffer);
772 
773 	/* This loop iterates once per logical line */
774 	while ((token = yylex()))
775 	{
776 		char	   *opt_name = NULL;
777 		char	   *opt_value = NULL;
778 		ConfigVariable *item;
779 
780 		if (token == GUC_EOL)	/* empty or comment line */
781 			continue;
782 
783 		/* first token on line is option name */
784 		if (token != GUC_ID && token != GUC_QUALIFIED_ID)
785 			goto parse_error;
786 		opt_name = pstrdup(yytext);
787 
788 		/* next we have an optional equal sign; discard if present */
789 		token = yylex();
790 		if (token == GUC_EQUALS)
791 			token = yylex();
792 
793 		/* now we must have the option value */
794 		if (token != GUC_ID &&
795 			token != GUC_STRING &&
796 			token != GUC_INTEGER &&
797 			token != GUC_REAL &&
798 			token != GUC_UNQUOTED_STRING)
799 			goto parse_error;
800 		if (token == GUC_STRING)	/* strip quotes and escapes */
801 			opt_value = DeescapeQuotedString(yytext);
802 		else
803 			opt_value = pstrdup(yytext);
804 
805 		/* now we'd like an end of line, or possibly EOF */
806 		token = yylex();
807 		if (token != GUC_EOL)
808 		{
809 			if (token != 0)
810 				goto parse_error;
811 			/* treat EOF like \n for line numbering purposes, cf bug 4752 */
812 			ConfigFileLineno++;
813 		}
814 
815 		/* OK, process the option name and value */
816 		if (guc_name_compare(opt_name, "include_dir") == 0)
817 		{
818 			/*
819 			 * An include_dir directive isn't a variable and should be
820 			 * processed immediately.
821 			 */
822 			if (!ParseConfigDirectory(opt_value,
823 									  config_file, ConfigFileLineno - 1,
824 									  depth + 1, elevel,
825 									  head_p, tail_p))
826 				OK = false;
827 			yy_switch_to_buffer(lex_buffer);
828 			pfree(opt_name);
829 			pfree(opt_value);
830 		}
831 		else if (guc_name_compare(opt_name, "include_if_exists") == 0)
832 		{
833 			/*
834 			 * An include_if_exists directive isn't a variable and should be
835 			 * processed immediately.
836 			 */
837 			if (!ParseConfigFile(opt_value, false,
838 								 config_file, ConfigFileLineno - 1,
839 								 depth + 1, elevel,
840 								 head_p, tail_p))
841 				OK = false;
842 			yy_switch_to_buffer(lex_buffer);
843 			pfree(opt_name);
844 			pfree(opt_value);
845 		}
846 		else if (guc_name_compare(opt_name, "include") == 0)
847 		{
848 			/*
849 			 * An include directive isn't a variable and should be processed
850 			 * immediately.
851 			 */
852 			if (!ParseConfigFile(opt_value, true,
853 								 config_file, ConfigFileLineno - 1,
854 								 depth + 1, elevel,
855 								 head_p, tail_p))
856 				OK = false;
857 			yy_switch_to_buffer(lex_buffer);
858 			pfree(opt_name);
859 			pfree(opt_value);
860 		}
861 		else
862 		{
863 			/* ordinary variable, append to list */
864 			item = palloc(sizeof *item);
865 			item->name = opt_name;
866 			item->value = opt_value;
867 			item->errmsg = NULL;
868 			item->filename = pstrdup(config_file);
869 			item->sourceline = ConfigFileLineno - 1;
870 			item->ignore = false;
871 			item->applied = false;
872 			item->next = NULL;
873 			if (*head_p == NULL)
874 				*head_p = item;
875 			else
876 				(*tail_p)->next = item;
877 			*tail_p = item;
878 		}
879 
880 		/* break out of loop if read EOF, else loop for next line */
881 		if (token == 0)
882 			break;
883 		continue;
884 
885 parse_error:
886 		/* release storage if we allocated any on this line */
887 		if (opt_name)
888 			pfree(opt_name);
889 		if (opt_value)
890 			pfree(opt_value);
891 
892 		/* report the error */
893 		if (token == GUC_EOL || token == 0)
894 		{
895 			ereport(elevel,
896 					(errcode(ERRCODE_SYNTAX_ERROR),
897 			  errmsg("syntax error in file \"%s\" line %u, near end of line",
898 					 config_file, ConfigFileLineno - 1)));
899 			record_config_file_error("syntax error",
900 									 config_file, ConfigFileLineno - 1,
901 									 head_p, tail_p);
902 		}
903 		else
904 		{
905 			ereport(elevel,
906 					(errcode(ERRCODE_SYNTAX_ERROR),
907 			 errmsg("syntax error in file \"%s\" line %u, near token \"%s\"",
908 					config_file, ConfigFileLineno, yytext)));
909 			record_config_file_error("syntax error",
910 									 config_file, ConfigFileLineno,
911 									 head_p, tail_p);
912 		}
913 		OK = false;
914 		errorcount++;
915 
916 		/*
917 		 * To avoid producing too much noise when fed a totally bogus file,
918 		 * give up after 100 syntax errors per file (an arbitrary number).
919 		 * Also, if we're only logging the errors at DEBUG level anyway, might
920 		 * as well give up immediately.  (This prevents postmaster children
921 		 * from bloating the logs with duplicate complaints.)
922 		 */
923 		if (errorcount >= 100 || elevel <= DEBUG1)
924 		{
925 			ereport(elevel,
926 					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
927 			   errmsg("too many syntax errors found, abandoning file \"%s\"",
928 					  config_file)));
929 			break;
930 		}
931 
932 		/* resync to next end-of-line or EOF */
933 		while (token != GUC_EOL && token != 0)
934 			token = yylex();
935 		/* break out of loop on EOF */
936 		if (token == 0)
937 			break;
938 	}
939 
940 cleanup:
941 	yy_delete_buffer(lex_buffer);
942 	/* Each recursion level must save and restore these static variables. */
943 	ConfigFileLineno = save_ConfigFileLineno;
944 	GUC_flex_fatal_jmp = save_GUC_flex_fatal_jmp;
945 	return OK;
946 }
947 
948 /*
949  * Read and parse all config files in a subdirectory in alphabetical order
950  *
951  * includedir is the absolute or relative path to the subdirectory to scan.
952  *
953  * calling_file/calling_lineno identify the source of the request.
954  * Pass NULL/0 if not recursing from an inclusion request.
955  *
956  * See ParseConfigFp for further details.
957  */
958 bool
ParseConfigDirectory(const char * includedir,const char * calling_file,int calling_lineno,int depth,int elevel,ConfigVariable ** head_p,ConfigVariable ** tail_p)959 ParseConfigDirectory(const char *includedir,
960 					 const char *calling_file, int calling_lineno,
961 					 int depth, int elevel,
962 					 ConfigVariable **head_p,
963 					 ConfigVariable **tail_p)
964 {
965 	char	   *directory;
966 	DIR		   *d;
967 	struct dirent *de;
968 	char	  **filenames;
969 	int			num_filenames;
970 	int			size_filenames;
971 	bool		status;
972 
973 	/*
974 	 * Reject directory name that is all-blank (including empty), as that
975 	 * leads to confusion --- we'd read the containing directory, typically
976 	 * resulting in recursive inclusion of the same file(s).
977 	 */
978 	if (strspn(includedir, " \t\r\n") == strlen(includedir))
979 	{
980 		ereport(elevel,
981 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
982 				 errmsg("empty configuration directory name: \"%s\"",
983 						includedir)));
984 		record_config_file_error("empty configuration directory name",
985 								 calling_file, calling_lineno,
986 								 head_p, tail_p);
987 		return false;
988 	}
989 
990 	/*
991 	 * We don't check for recursion or too-deep nesting depth here; the
992 	 * subsequent calls to ParseConfigFile will take care of that.
993 	 */
994 
995 	directory = AbsoluteConfigLocation(includedir, calling_file);
996 	d = AllocateDir(directory);
997 	if (d == NULL)
998 	{
999 		ereport(elevel,
1000 				(errcode_for_file_access(),
1001 				 errmsg("could not open configuration directory \"%s\": %m",
1002 						directory)));
1003 		record_config_file_error(psprintf("could not open directory \"%s\"",
1004 										  directory),
1005 								 calling_file, calling_lineno,
1006 								 head_p, tail_p);
1007 		status = false;
1008 		goto cleanup;
1009 	}
1010 
1011 	/*
1012 	 * Read the directory and put the filenames in an array, so we can sort
1013 	 * them prior to processing the contents.
1014 	 */
1015 	size_filenames = 32;
1016 	filenames = (char **) palloc(size_filenames * sizeof(char *));
1017 	num_filenames = 0;
1018 
1019 	while ((de = ReadDir(d, directory)) != NULL)
1020 	{
1021 		struct stat st;
1022 		char		filename[MAXPGPATH];
1023 
1024 		/*
1025 		 * Only parse files with names ending in ".conf".  Explicitly reject
1026 		 * files starting with ".".  This excludes things like "." and "..",
1027 		 * as well as typical hidden files, backup files, and editor debris.
1028 		 */
1029 		if (strlen(de->d_name) < 6)
1030 			continue;
1031 		if (de->d_name[0] == '.')
1032 			continue;
1033 		if (strcmp(de->d_name + strlen(de->d_name) - 5, ".conf") != 0)
1034 			continue;
1035 
1036 		join_path_components(filename, directory, de->d_name);
1037 		canonicalize_path(filename);
1038 		if (stat(filename, &st) == 0)
1039 		{
1040 			if (!S_ISDIR(st.st_mode))
1041 			{
1042 				/* Add file to array, increasing its size in blocks of 32 */
1043 				if (num_filenames >= size_filenames)
1044 				{
1045 					size_filenames += 32;
1046 					filenames = (char **) repalloc(filenames,
1047 											size_filenames * sizeof(char *));
1048 				}
1049 				filenames[num_filenames] = pstrdup(filename);
1050 				num_filenames++;
1051 			}
1052 		}
1053 		else
1054 		{
1055 			/*
1056 			 * stat does not care about permissions, so the most likely reason
1057 			 * a file can't be accessed now is if it was removed between the
1058 			 * directory listing and now.
1059 			 */
1060 			ereport(elevel,
1061 					(errcode_for_file_access(),
1062 					 errmsg("could not stat file \"%s\": %m",
1063 							filename)));
1064 			record_config_file_error(psprintf("could not stat file \"%s\"",
1065 											  filename),
1066 									 calling_file, calling_lineno,
1067 									 head_p, tail_p);
1068 			status = false;
1069 			goto cleanup;
1070 		}
1071 	}
1072 
1073 	if (num_filenames > 0)
1074 	{
1075 		int			i;
1076 
1077 		qsort(filenames, num_filenames, sizeof(char *), pg_qsort_strcmp);
1078 		for (i = 0; i < num_filenames; i++)
1079 		{
1080 			if (!ParseConfigFile(filenames[i], true,
1081 								 calling_file, calling_lineno,
1082 								 depth, elevel,
1083 								 head_p, tail_p))
1084 			{
1085 				status = false;
1086 				goto cleanup;
1087 			}
1088 		}
1089 	}
1090 	status = true;
1091 
1092 cleanup:
1093 	if (d)
1094 		FreeDir(d);
1095 	pfree(directory);
1096 	return status;
1097 }
1098 
1099 /*
1100  * Free a list of ConfigVariables, including the names and the values
1101  */
1102 void
FreeConfigVariables(ConfigVariable * list)1103 FreeConfigVariables(ConfigVariable *list)
1104 {
1105 	ConfigVariable *item;
1106 
1107 	item = list;
1108 	while (item)
1109 	{
1110 		ConfigVariable *next = item->next;
1111 
1112 		FreeConfigVariable(item);
1113 		item = next;
1114 	}
1115 }
1116 
1117 /*
1118  * Free a single ConfigVariable
1119  */
1120 static void
FreeConfigVariable(ConfigVariable * item)1121 FreeConfigVariable(ConfigVariable *item)
1122 {
1123 	if (item->name)
1124 		pfree(item->name);
1125 	if (item->value)
1126 		pfree(item->value);
1127 	if (item->errmsg)
1128 		pfree(item->errmsg);
1129 	if (item->filename)
1130 		pfree(item->filename);
1131 	pfree(item);
1132 }
1133 
1134 
1135 /*
1136  *		DeescapeQuotedString
1137  *
1138  * Strip the quotes surrounding the given string, and collapse any embedded
1139  * '' sequences and backslash escapes.
1140  *
1141  * The string returned is palloc'd and should eventually be pfree'd by the
1142  * caller.
1143  *
1144  * This is exported because it is also used by the bootstrap scanner.
1145  */
1146 char *
DeescapeQuotedString(const char * s)1147 DeescapeQuotedString(const char *s)
1148 {
1149 	char	   *newStr;
1150 	int			len,
1151 				i,
1152 				j;
1153 
1154 	/* We just Assert that there are leading and trailing quotes */
1155 	Assert(s != NULL && s[0] == '\'');
1156 	len = strlen(s);
1157 	Assert(len >= 2);
1158 	Assert(s[len - 1] == '\'');
1159 
1160 	/* Skip the leading quote; we'll handle the trailing quote below */
1161 	s++, len--;
1162 
1163 	/* Since len still includes trailing quote, this is enough space */
1164 	newStr = palloc(len);
1165 
1166 	for (i = 0, j = 0; i < len; i++)
1167 	{
1168 		if (s[i] == '\\')
1169 		{
1170 			i++;
1171 			switch (s[i])
1172 			{
1173 				case 'b':
1174 					newStr[j] = '\b';
1175 					break;
1176 				case 'f':
1177 					newStr[j] = '\f';
1178 					break;
1179 				case 'n':
1180 					newStr[j] = '\n';
1181 					break;
1182 				case 'r':
1183 					newStr[j] = '\r';
1184 					break;
1185 				case 't':
1186 					newStr[j] = '\t';
1187 					break;
1188 				case '0':
1189 				case '1':
1190 				case '2':
1191 				case '3':
1192 				case '4':
1193 				case '5':
1194 				case '6':
1195 				case '7':
1196 					{
1197 						int			k;
1198 						long		octVal = 0;
1199 
1200 						for (k = 0;
1201 							 s[i + k] >= '0' && s[i + k] <= '7' && k < 3;
1202 							 k++)
1203 							octVal = (octVal << 3) + (s[i + k] - '0');
1204 						i += k - 1;
1205 						newStr[j] = ((char) octVal);
1206 					}
1207 					break;
1208 				default:
1209 					newStr[j] = s[i];
1210 					break;
1211 			}					/* switch */
1212 		}
1213 		else if (s[i] == '\'' && s[i + 1] == '\'')
1214 		{
1215 			/* doubled quote becomes just one quote */
1216 			newStr[j] = s[++i];
1217 		}
1218 		else
1219 			newStr[j] = s[i];
1220 		j++;
1221 	}
1222 
1223 	/* We copied the ending quote to newStr, so replace with \0 */
1224 	Assert(j > 0 && j <= len);
1225 	newStr[--j] = '\0';
1226 
1227 	return newStr;
1228 }
1229