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