]> granicus.if.org Git - postgresql/blob - src/backend/utils/misc/guc.c
Add GUC setting for Australian timezones. Uses new GUC boolean callback
[postgresql] / src / backend / utils / misc / guc.c
1 /*--------------------------------------------------------------------
2  * guc.c
3  *
4  * Support for grand unified configuration scheme, including SET
5  * command, configuration file, and command line options.
6  *
7  * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.39 2001/06/18 16:14:43 momjian Exp $
8  *
9  * Copyright 2000 by PostgreSQL Global Development Group
10  * Written by Peter Eisentraut <peter_e@gmx.net>.
11  *--------------------------------------------------------------------
12  */
13
14 #include "postgres.h"
15
16 #include <errno.h>
17 #include <float.h>
18 #include <limits.h>
19 #include <unistd.h>
20
21 #include "utils/guc.h"
22
23 #include "access/xlog.h"
24 #include "commands/async.h"
25 #include "fmgr.h"
26 #include "libpq/auth.h"
27 #include "libpq/pqcomm.h"
28 #include "miscadmin.h"
29 #include "optimizer/cost.h"
30 #include "optimizer/geqo.h"
31 #include "optimizer/paths.h"
32 #include "optimizer/planmain.h"
33 #include "parser/parse_expr.h"
34 #include "storage/proc.h"
35 #include "tcop/tcopprot.h"
36 #include "utils/datetime.h"
37
38
39 /* XXX these should be in other modules' header files */
40 extern bool Log_connections;
41 extern int      CheckPointTimeout;
42 extern int      CommitDelay;
43 extern int      CommitSiblings;
44 extern bool FixBTree;
45
46 #ifdef ENABLE_SYSLOG
47 extern char *Syslog_facility;
48 extern char *Syslog_ident;
49 static bool check_facility(const char *facility);
50 #endif
51
52 /*
53  * Debugging options
54  */
55 #ifdef USE_ASSERT_CHECKING
56 bool            assert_enabled = true;
57 #endif
58 bool            Debug_print_query = false;
59 bool            Debug_print_plan = false;
60 bool            Debug_print_parse = false;
61 bool            Debug_print_rewritten = false;
62 bool            Debug_pretty_print = false;
63
64 bool            Show_parser_stats = false;
65 bool            Show_planner_stats = false;
66 bool            Show_executor_stats = false;
67 bool            Show_query_stats = false;       /* this is sort of all three above
68                                                                                  * together */
69 bool            Show_btree_build_stats = false;
70
71 bool            SQL_inheritance = true;
72
73 bool            Australian_timezones = false;
74
75 #ifndef PG_KRB_SRVTAB
76 #define PG_KRB_SRVTAB ""
77 #endif
78
79
80 /*
81  * Declarations for GUC tables
82  */
83 enum config_type
84 {
85         PGC_NONE = 0,
86         PGC_BOOL,
87         PGC_INT,
88         PGC_REAL,
89         PGC_STRING
90 };
91
92
93 struct config_generic
94 {
95         const char *name;
96         GucContext      context;
97         void       *variable;
98 };
99
100
101 struct config_bool
102 {
103         const char *name;
104         GucContext      context;
105         bool       *variable;
106         bool            default_val;
107         /* No need for parse_hook ... presumably both values are legal */
108         void            (*assign_hook) (bool newval);
109 };
110
111
112 struct config_int
113 {
114         const char *name;
115         GucContext      context;
116         int                *variable;
117         int                     default_val;
118         int                     min;
119         int                     max;
120         bool            (*parse_hook) (int proposed);
121         void            (*assign_hook) (int newval);
122 };
123
124
125 struct config_real
126 {
127         const char *name;
128         GucContext      context;
129         double     *variable;
130         double          default_val;
131         double          min;
132         double          max;
133         bool            (*parse_hook) (double proposed);
134         void            (*assign_hook) (double newval);
135 };
136
137 /*
138  * String value options are allocated with strdup, not with the
139  * pstrdup/palloc mechanisms. That is because configuration settings
140  * are already in place before the memory subsystem is up. It would
141  * perhaps be an idea to change that sometime.
142  */
143 struct config_string
144 {
145         const char *name;
146         GucContext      context;
147         char      **variable;
148         const char *boot_default_val;
149         bool            (*parse_hook) (const char *proposed);
150         void            (*assign_hook) (const char *newval);
151         char            *default_val;
152 };
153
154
155 /*
156  * TO ADD AN OPTION:
157  *
158  * 1. Declare a global variable of type bool, int, double, or char*
159  * and make use of it.
160  *
161  * 2. Decide at what times it's safe to set the option. See guc.h for
162  * details.
163  *
164  * 3. Decide on a name, a default value, upper and lower bounds (if
165  * applicable), etc.
166  *
167  * 4. Add a record below.
168  *
169  * 5. Add it to postgresql.conf.sample
170  *
171  * 6. Don't forget to document that option.
172  *
173  * WHEN MAKING MODIFICATIONS, remember to update postgresql.conf.sample
174  *
175  */
176
177
178 /******** option names follow ********/
179
180 static struct config_bool
181                         ConfigureNamesBool[] =
182 {
183         {"enable_seqscan", PGC_USERSET, &enable_seqscan, true, NULL},
184         {"enable_indexscan", PGC_USERSET, &enable_indexscan, true, NULL},
185         {"enable_tidscan", PGC_USERSET, &enable_tidscan, true, NULL},
186         {"enable_sort", PGC_USERSET, &enable_sort, true, NULL},
187         {"enable_nestloop", PGC_USERSET, &enable_nestloop, true, NULL},
188         {"enable_mergejoin", PGC_USERSET, &enable_mergejoin, true, NULL},
189         {"enable_hashjoin", PGC_USERSET, &enable_hashjoin, true, NULL},
190
191         {"ksqo", PGC_USERSET, &_use_keyset_query_optimizer, false, NULL},
192         {"geqo", PGC_USERSET, &enable_geqo, true, NULL},
193
194         {"tcpip_socket", PGC_POSTMASTER, &NetServer, false, NULL},
195         {"ssl", PGC_POSTMASTER, &EnableSSL, false, NULL},
196         {"fsync", PGC_SIGHUP, &enableFsync, true, NULL},
197         {"silent_mode", PGC_POSTMASTER, &SilentMode, false, NULL},
198
199         {"log_connections", PGC_SIGHUP, &Log_connections, false, NULL},
200         {"log_timestamp", PGC_SIGHUP, &Log_timestamp, false, NULL},
201         {"log_pid", PGC_SIGHUP, &Log_pid, false, NULL},
202
203 #ifdef USE_ASSERT_CHECKING
204         {"debug_assertions", PGC_USERSET, &assert_enabled, true, NULL},
205 #endif
206
207         {"debug_print_query", PGC_USERSET, &Debug_print_query, false, NULL},
208         {"debug_print_parse", PGC_USERSET, &Debug_print_parse, false, NULL},
209         {"debug_print_rewritten", PGC_USERSET, &Debug_print_rewritten, false, NULL},
210         {"debug_print_plan", PGC_USERSET, &Debug_print_plan, false, NULL},
211         {"debug_pretty_print", PGC_USERSET, &Debug_pretty_print, false, NULL},
212
213         {"show_parser_stats", PGC_USERSET, &Show_parser_stats, false, NULL},
214         {"show_planner_stats", PGC_USERSET, &Show_planner_stats, false, NULL},
215         {"show_executor_stats", PGC_USERSET, &Show_executor_stats, false, NULL},
216         {"show_query_stats", PGC_USERSET, &Show_query_stats, false, NULL},
217 #ifdef BTREE_BUILD_STATS
218         {"show_btree_build_stats", PGC_SUSET, &Show_btree_build_stats, false, NULL},
219 #endif
220
221         {"trace_notify", PGC_USERSET, &Trace_notify, false, NULL},
222
223 #ifdef LOCK_DEBUG
224         {"trace_locks", PGC_SUSET, &Trace_locks, false, NULL},
225         {"trace_userlocks", PGC_SUSET, &Trace_userlocks, false, NULL},
226         {"trace_spinlocks", PGC_SUSET, &Trace_spinlocks, false, NULL},
227         {"debug_deadlocks", PGC_SUSET, &Debug_deadlocks, false, NULL},
228 #endif
229
230         {"hostname_lookup", PGC_SIGHUP, &HostnameLookup, false, NULL},
231         {"show_source_port", PGC_SIGHUP, &ShowPortNumber, false, NULL},
232
233         {"sql_inheritance", PGC_USERSET, &SQL_inheritance, true, NULL},
234
235         {"australian_timezones", PGC_USERSET, &Australian_timezones,
236         false, ClearDateCache},
237
238         {"fixbtree", PGC_POSTMASTER, &FixBTree, true, NULL},
239
240         {NULL, 0, NULL, false, NULL}
241 };
242
243
244 static struct config_int
245                         ConfigureNamesInt[] =
246 {
247         {"geqo_threshold", PGC_USERSET, &geqo_rels,
248         DEFAULT_GEQO_RELS, 2, INT_MAX, NULL, NULL},
249         {"geqo_pool_size", PGC_USERSET, &Geqo_pool_size,
250         DEFAULT_GEQO_POOL_SIZE, 0, MAX_GEQO_POOL_SIZE, NULL, NULL},
251         {"geqo_effort", PGC_USERSET, &Geqo_effort,
252         1, 1, INT_MAX, NULL, NULL},
253         {"geqo_generations", PGC_USERSET, &Geqo_generations,
254         0, 0, INT_MAX, NULL, NULL},
255         {"geqo_random_seed", PGC_USERSET, &Geqo_random_seed,
256         -1, INT_MIN, INT_MAX, NULL, NULL},
257
258         {"deadlock_timeout", PGC_POSTMASTER, &DeadlockTimeout,
259         1000, 0, INT_MAX, NULL, NULL},
260
261 #ifdef ENABLE_SYSLOG
262         {"syslog", PGC_SIGHUP, &Use_syslog,
263         0, 0, 2, NULL, NULL},
264 #endif
265
266         /*
267          * Note: There is some postprocessing done in PostmasterMain() to make
268          * sure the buffers are at least twice the number of backends, so the
269          * constraints here are partially unused.
270          */
271         {"max_connections", PGC_POSTMASTER, &MaxBackends,
272         DEF_MAXBACKENDS, 1, MAXBACKENDS, NULL, NULL},
273         {"shared_buffers", PGC_POSTMASTER, &NBuffers,
274         DEF_NBUFFERS, 16, INT_MAX, NULL, NULL},
275         {"port", PGC_POSTMASTER, &PostPortNumber,
276         DEF_PGPORT, 1, 65535, NULL, NULL},
277
278         {"sort_mem", PGC_USERSET, &SortMem,
279         512, 1, INT_MAX, NULL, NULL},
280
281         {"debug_level", PGC_USERSET, &DebugLvl,
282         0, 0, 16, NULL, NULL},
283
284 #ifdef LOCK_DEBUG
285         {"trace_lock_oidmin", PGC_SUSET, &Trace_lock_oidmin,
286         BootstrapObjectIdData, 1, INT_MAX, NULL, NULL},
287         {"trace_lock_table", PGC_SUSET, &Trace_lock_table,
288         0, 0, INT_MAX, NULL, NULL},
289 #endif
290         {"max_expr_depth", PGC_USERSET, &max_expr_depth,
291         DEFAULT_MAX_EXPR_DEPTH, 10, INT_MAX, NULL, NULL},
292
293         {"unix_socket_permissions", PGC_POSTMASTER, &Unix_socket_permissions,
294         0777, 0000, 0777, NULL, NULL},
295
296         {"checkpoint_segments", PGC_SIGHUP, &CheckPointSegments,
297         3, 1, INT_MAX, NULL, NULL},
298
299         {"checkpoint_timeout", PGC_SIGHUP, &CheckPointTimeout,
300         300, 30, 3600, NULL, NULL},
301
302         {"wal_buffers", PGC_POSTMASTER, &XLOGbuffers,
303         8, 4, INT_MAX, NULL, NULL},
304
305         {"wal_files", PGC_SIGHUP, &XLOGfiles,
306         0, 0, 64, NULL, NULL},
307
308         {"wal_debug", PGC_SUSET, &XLOG_DEBUG,
309         0, 0, 16, NULL, NULL},
310
311         {"commit_delay", PGC_USERSET, &CommitDelay,
312         0, 0, 100000, NULL, NULL},
313
314         {"commit_siblings", PGC_USERSET, &CommitSiblings,
315         5, 1, 1000, NULL, NULL},
316
317         {NULL, 0, NULL, 0, 0, 0, NULL, NULL}
318 };
319
320
321 static struct config_real
322                         ConfigureNamesReal[] =
323 {
324         {"effective_cache_size", PGC_USERSET, &effective_cache_size,
325         DEFAULT_EFFECTIVE_CACHE_SIZE, 0, DBL_MAX, NULL, NULL},
326         {"random_page_cost", PGC_USERSET, &random_page_cost,
327         DEFAULT_RANDOM_PAGE_COST, 0, DBL_MAX, NULL, NULL},
328         {"cpu_tuple_cost", PGC_USERSET, &cpu_tuple_cost,
329         DEFAULT_CPU_TUPLE_COST, 0, DBL_MAX, NULL, NULL},
330         {"cpu_index_tuple_cost", PGC_USERSET, &cpu_index_tuple_cost,
331         DEFAULT_CPU_INDEX_TUPLE_COST, 0, DBL_MAX, NULL, NULL},
332         {"cpu_operator_cost", PGC_USERSET, &cpu_operator_cost,
333         DEFAULT_CPU_OPERATOR_COST, 0, DBL_MAX, NULL, NULL},
334
335         {"geqo_selection_bias", PGC_USERSET, &Geqo_selection_bias,
336         DEFAULT_GEQO_SELECTION_BIAS, MIN_GEQO_SELECTION_BIAS,
337         MAX_GEQO_SELECTION_BIAS, NULL, NULL},
338
339         {NULL, 0, NULL, 0.0, 0.0, 0.0, NULL, NULL}
340 };
341
342
343 static struct config_string
344                         ConfigureNamesString[] =
345 {
346         {"dynamic_library_path", PGC_SUSET, &Dynamic_library_path,
347          "$libdir", NULL, NULL},
348
349         {"krb_server_keyfile", PGC_POSTMASTER, &pg_krb_server_keyfile,
350         PG_KRB_SRVTAB, NULL, NULL},
351
352 #ifdef ENABLE_SYSLOG
353         {"syslog_facility", PGC_POSTMASTER, &Syslog_facility,
354         "LOCAL0", check_facility, NULL},
355         {"syslog_ident", PGC_POSTMASTER, &Syslog_ident,
356         "postgres", NULL, NULL},
357 #endif
358
359         {"unix_socket_group", PGC_POSTMASTER, &Unix_socket_group,
360         "", NULL, NULL},
361
362         {"unix_socket_directory", PGC_POSTMASTER, &UnixSocketDir,
363         "", NULL, NULL},
364
365         {"virtual_host", PGC_POSTMASTER, &VirtualHost,
366         "", NULL, NULL},
367
368         {"wal_sync_method", PGC_SIGHUP, &XLOG_sync_method,
369         XLOG_sync_method_default, check_xlog_sync_method,
370         assign_xlog_sync_method},
371
372         {NULL, 0, NULL, NULL, NULL, NULL}
373 };
374
375 /******** end of options list ********/
376
377
378
379 /*
380  * Look up option NAME. If it exists, return it's data type, else
381  * PGC_NONE (zero). If record is not NULL, store the description of
382  * the option there.
383  */
384 static enum config_type
385 find_option(const char *name, struct config_generic ** record)
386 {
387         int                     i;
388
389         Assert(name);
390
391         for (i = 0; ConfigureNamesBool[i].name; i++)
392                 if (strcasecmp(ConfigureNamesBool[i].name, name) == 0)
393                 {
394                         if (record)
395                                 *record = (struct config_generic *) & ConfigureNamesBool[i];
396                         return PGC_BOOL;
397                 }
398
399         for (i = 0; ConfigureNamesInt[i].name; i++)
400                 if (strcasecmp(ConfigureNamesInt[i].name, name) == 0)
401                 {
402                         if (record)
403                                 *record = (struct config_generic *) & ConfigureNamesInt[i];
404                         return PGC_INT;
405                 }
406
407         for (i = 0; ConfigureNamesReal[i].name; i++)
408                 if (strcasecmp(ConfigureNamesReal[i].name, name) == 0)
409                 {
410                         if (record)
411                                 *record = (struct config_generic *) & ConfigureNamesReal[i];
412                         return PGC_REAL;
413                 }
414
415         for (i = 0; ConfigureNamesString[i].name; i++)
416                 if (strcasecmp(ConfigureNamesString[i].name, name) == 0)
417                 {
418                         if (record)
419                                 *record = (struct config_generic *) & ConfigureNamesString[i];
420                         return PGC_STRING;
421                 }
422
423         return PGC_NONE;
424 }
425
426
427
428 /*
429  * Reset all options to their specified default values.  Must be called
430  * with isStartup = true at program startup.  May be called later with
431  * isStartup = false to reset all resettable options.
432  */
433 void
434 ResetAllOptions(bool isStartup)
435 {
436         int                     i;
437
438         for (i = 0; ConfigureNamesBool[i].name; i++)
439         {
440                 struct config_bool *conf = &ConfigureNamesBool[i];
441
442                 if (isStartup ||
443                         conf->context == PGC_SUSET || conf->context == PGC_USERSET)
444                 {
445                         if (conf->assign_hook)
446                                 (conf->assign_hook) (conf->default_val);
447                         *conf->variable = conf->default_val;
448                 }
449         }
450
451         for (i = 0; ConfigureNamesInt[i].name; i++)
452         {
453                 struct config_int *conf = &ConfigureNamesInt[i];
454
455                 if (isStartup ||
456                         conf->context == PGC_SUSET || conf->context == PGC_USERSET)
457                 {
458                         if (conf->assign_hook)
459                                 (conf->assign_hook) (conf->default_val);
460                         *conf->variable = conf->default_val;
461                 }
462         }
463
464         for (i = 0; ConfigureNamesReal[i].name; i++)
465         {
466                 struct config_real *conf = &ConfigureNamesReal[i];
467
468                 if (isStartup ||
469                         conf->context == PGC_SUSET || conf->context == PGC_USERSET)
470                 {
471                         if (conf->assign_hook)
472                                 (conf->assign_hook) (conf->default_val);
473                         *conf->variable = conf->default_val;
474                 }
475         }
476
477         for (i = 0; ConfigureNamesString[i].name; i++)
478         {
479                 struct config_string *conf = &ConfigureNamesString[i];
480
481                 if (isStartup ||
482                         conf->context == PGC_SUSET || conf->context == PGC_USERSET)
483                 {
484                         char       *str = NULL;
485
486                         if (conf->default_val == NULL &&
487                                 conf->boot_default_val)
488                         {
489                                 str = strdup(conf->boot_default_val);
490                                 if (str == NULL)
491                                         elog(ERROR, "out of memory");
492                                 conf->default_val = str;
493                         }
494                         if (conf->default_val)
495                         {
496                                 str = strdup(conf->default_val);
497                                 if (str == NULL)
498                                         elog(ERROR, "out of memory");
499                         }
500                         if (conf->assign_hook)
501                                 (conf->assign_hook) (str);
502                         if (*conf->variable)
503                                 free(*conf->variable);
504                         *conf->variable = str;
505                 }
506         }
507 }
508
509
510
511 /*
512  * Try to interpret value as boolean value.  Valid values are: true,
513  * false, yes, no, on, off, 1, 0.  If the string parses okay, return
514  * true, else false.  If result is not NULL, return the parsing result
515  * there.
516  */
517 static bool
518 parse_bool(const char *value, bool *result)
519 {
520         size_t          len = strlen(value);
521
522         if (strncasecmp(value, "true", len) == 0)
523         {
524                 if (result)
525                         *result = true;
526         }
527         else if (strncasecmp(value, "false", len) == 0)
528         {
529                 if (result)
530                         *result = false;
531         }
532
533         else if (strncasecmp(value, "yes", len) == 0)
534         {
535                 if (result)
536                         *result = true;
537         }
538         else if (strncasecmp(value, "no", len) == 0)
539         {
540                 if (result)
541                         *result = false;
542         }
543
544         else if (strcasecmp(value, "on") == 0)
545         {
546                 if (result)
547                         *result = true;
548         }
549         else if (strcasecmp(value, "off") == 0)
550         {
551                 if (result)
552                         *result = false;
553         }
554
555         else if (strcasecmp(value, "1") == 0)
556         {
557                 if (result)
558                         *result = true;
559         }
560         else if (strcasecmp(value, "0") == 0)
561         {
562                 if (result)
563                         *result = false;
564         }
565
566         else
567                 return false;
568         return true;
569 }
570
571
572
573 /*
574  * Try to parse value as an integer.  The accepted formats are the
575  * usual decimal, octal, or hexadecimal formats.  If the string parses
576  * okay, return true, else false.  If result is not NULL, return the
577  * value there.
578  */
579 static bool
580 parse_int(const char *value, int *result)
581 {
582         long            val;
583         char       *endptr;
584
585         errno = 0;
586         val = strtol(value, &endptr, 0);
587         if (endptr == value || *endptr != '\0' || errno == ERANGE
588 #ifdef HAVE_LONG_INT_64
589                 /* if long > 32 bits, check for overflow of int4 */
590                 || val != (long) ((int32) val)
591 #endif
592            )
593                 return false;
594         if (result)
595                 *result = (int) val;
596         return true;
597 }
598
599
600
601 /*
602  * Try to parse value as a floating point constant in the usual
603  * format.      If the value parsed okay return true, else false.  If
604  * result is not NULL, return the semantic value there.
605  */
606 static bool
607 parse_real(const char *value, double *result)
608 {
609         double          val;
610         char       *endptr;
611
612         errno = 0;
613         val = strtod(value, &endptr);
614         if (endptr == value || *endptr != '\0' || errno == ERANGE)
615                 return false;
616         if (result)
617                 *result = val;
618         return true;
619 }
620
621
622
623 /*
624  * Sets option `name' to given value. The value should be a string
625  * which is going to be parsed and converted to the appropriate data
626  * type. Parameter context should indicate in which context this
627  * function is being called so it can apply the access restrictions
628  * properly.
629  *
630  * If value is NULL, set the option to its default value. If the
631  * parameter DoIt is false then don't really set the option but do all
632  * the checks to see if it would work.
633  *
634  * If there is an error (non-existing option, invalid value) then an
635  * elog(ERROR) is thrown *unless* this is called as part of the
636  * configuration file re-read in the SIGHUP handler, in which case we
637  * simply write the error message via elog(DEBUG) and return false. In
638  * all other cases the function returns true. This is working around
639  * the deficiencies in the elog mechanism, so don't blame me.
640  *
641  * See also SetConfigOption for an external interface.
642  */
643 bool
644 set_config_option(const char *name, const char *value,
645                                   GucContext context, bool DoIt, bool makeDefault)
646 {
647         struct config_generic *record;
648         enum config_type type;
649         int                     elevel;
650
651         elevel = (context == PGC_SIGHUP) ? DEBUG : ERROR;
652
653         type = find_option(name, &record);
654         if (type == PGC_NONE)
655         {
656                 elog(elevel, "'%s' is not a valid option name", name);
657                 return false;
658         }
659
660         /*
661          * Check if the option can be set at this time. See guc.h for the
662          * precise rules. Note that we don't want to throw errors if we're in
663          * the SIGHUP context. In that case we just ignore the attempt.
664          */
665         if (record->context == PGC_POSTMASTER && context != PGC_POSTMASTER)
666         {
667                 if (context != PGC_SIGHUP)
668                         elog(ERROR, "'%s' cannot be changed after server start", name);
669                 else
670                         return true;
671         }
672         else if (record->context == PGC_SIGHUP && context != PGC_SIGHUP &&
673                          context != PGC_POSTMASTER)
674         {
675                 elog(ERROR, "'%s' cannot be changed now", name);
676
677                 /*
678                  * Hmm, the idea of the SIGHUP context is "ought to be global, but
679                  * can be changed after postmaster start". But there's nothing
680                  * that prevents a crafty administrator from sending SIGHUP
681                  * signals to individual backends only.
682                  */
683         }
684         else if (record->context == PGC_BACKEND && context != PGC_BACKEND
685                          && context != PGC_POSTMASTER)
686         {
687                 if (context != PGC_SIGHUP)
688                         elog(ERROR, "'%s' cannot be set after connection start", name);
689                 else
690                         return true;
691         }
692         else if (record->context == PGC_SUSET &&
693                          (context == PGC_USERSET || context == PGC_BACKEND))
694                 elog(ERROR, "permission denied");
695
696
697         /*
698          * Evaluate value and set variable
699          */
700         switch (type)
701         {
702                 case PGC_BOOL:
703                         {
704                                 struct config_bool *conf = (struct config_bool *) record;
705
706                                 if (value)
707                                 {
708                                         bool            boolval;
709
710                                         if (!parse_bool(value, &boolval))
711                                         {
712                                                 elog(elevel, "option '%s' requires a boolean value", name);
713                                                 return false;
714                                         }
715                                         /* no parse_hook needed for booleans */
716                                         if (DoIt)
717                                         {
718                                                 if (conf->assign_hook)
719                                                         (conf->assign_hook) (boolval);
720                                                 *conf->variable = boolval;
721                                                 if (makeDefault)
722                                                         conf->default_val = boolval;
723                                         }
724                                 }
725                                 else if (DoIt)
726                                 {
727                                         if (conf->assign_hook)
728                                                 (conf->assign_hook) (conf->default_val);
729                                         *conf->variable = conf->default_val;
730                                 }
731                                 break;
732                         }
733
734                 case PGC_INT:
735                         {
736                                 struct config_int *conf = (struct config_int *) record;
737
738                                 if (value)
739                                 {
740                                         int                     intval;
741
742                                         if (!parse_int(value, &intval))
743                                         {
744                                                 elog(elevel, "option '%s' expects an integer value", name);
745                                                 return false;
746                                         }
747                                         if (intval < conf->min || intval > conf->max)
748                                         {
749                                                 elog(elevel, "option '%s' value %d is outside"
750                                                          " of permissible range [%d .. %d]",
751                                                          name, intval, conf->min, conf->max);
752                                                 return false;
753                                         }
754                                         if (conf->parse_hook && !(conf->parse_hook) (intval))
755                                         {
756                                                 elog(elevel, "invalid value for option '%s': %d",
757                                                          name, intval);
758                                                 return false;
759                                         }
760                                         if (DoIt)
761                                         {
762                                                 if (conf->assign_hook)
763                                                         (conf->assign_hook) (intval);
764                                                 *conf->variable = intval;
765                                                 if (makeDefault)
766                                                         conf->default_val = intval;
767                                         }
768                                 }
769                                 else if (DoIt)
770                                 {
771                                         if (conf->assign_hook)
772                                                 (conf->assign_hook) (conf->default_val);
773                                         *conf->variable = conf->default_val;
774                                 }
775                                 break;
776                         }
777
778                 case PGC_REAL:
779                         {
780                                 struct config_real *conf = (struct config_real *) record;
781
782                                 if (value)
783                                 {
784                                         double          dval;
785
786                                         if (!parse_real(value, &dval))
787                                         {
788                                                 elog(elevel, "option '%s' expects a real number", name);
789                                                 return false;
790                                         }
791                                         if (dval < conf->min || dval > conf->max)
792                                         {
793                                                 elog(elevel, "option '%s' value %g is outside"
794                                                          " of permissible range [%g .. %g]",
795                                                          name, dval, conf->min, conf->max);
796                                                 return false;
797                                         }
798                                         if (conf->parse_hook && !(conf->parse_hook) (dval))
799                                         {
800                                                 elog(elevel, "invalid value for option '%s': %g",
801                                                          name, dval);
802                                                 return false;
803                                         }
804                                         if (DoIt)
805                                         {
806                                                 if (conf->assign_hook)
807                                                         (conf->assign_hook) (dval);
808                                                 *conf->variable = dval;
809                                                 if (makeDefault)
810                                                         conf->default_val = dval;
811                                         }
812                                 }
813                                 else if (DoIt)
814                                 {
815                                         if (conf->assign_hook)
816                                                 (conf->assign_hook) (conf->default_val);
817                                         *conf->variable = conf->default_val;
818                                 }
819                                 break;
820                         }
821
822                 case PGC_STRING:
823                         {
824                                 struct config_string *conf = (struct config_string *) record;
825
826                                 if (value)
827                                 {
828                                         if (conf->parse_hook && !(conf->parse_hook) (value))
829                                         {
830                                                 elog(elevel, "invalid value for option '%s': '%s'",
831                                                          name, value);
832                                                 return false;
833                                         }
834                                         if (DoIt)
835                                         {
836                                                 char       *str;
837
838                                                 str = strdup(value);
839                                                 if (str == NULL)
840                                                 {
841                                                         elog(elevel, "out of memory");
842                                                         return false;
843                                                 }
844                                                 if (conf->assign_hook)
845                                                         (conf->assign_hook) (str);
846                                                 if (*conf->variable)
847                                                         free(*conf->variable);
848                                                 *conf->variable = str;
849                                                 if (makeDefault)
850                                                 {
851                                                         str = strdup(value);
852                                                         if (str == NULL) {
853                                                                 elog(elevel, "out of memory");
854                                                                 return false;
855                                                         }
856                                                         if (conf->default_val)
857                                                                 free(conf->default_val);
858                                                         conf->default_val = str;
859                                                 }
860                                         }
861                                 }
862                                 else if (DoIt)
863                                 {
864                                         char       *str;
865
866                                         if (!conf->default_val && conf->boot_default_val)
867                                         {
868                                                 str = strdup(conf->boot_default_val);
869                                                 if (str == NULL)
870                                                 {
871                                                         elog(elevel, "out of memory");
872                                                         return false;
873                                                 }
874                                                 conf->default_val = str;
875                                         }
876                                         str = strdup(conf->default_val);
877                                         if (str == NULL)
878                                         {
879                                                 elog(elevel, "out of memory");
880                                                 return false;
881                                         }
882                                         if (conf->assign_hook)
883                                                 (conf->assign_hook) (str);
884                                         if (*conf->variable)
885                                                 free(*conf->variable);
886                                         *conf->variable = str;
887                                 }
888                                 break;
889                         }
890
891                 default:;
892         }
893         return true;
894 }
895
896
897
898 /*
899  * Set a config option to the given value. See also set_config_option,
900  * this is just the wrapper to be called from the outside.
901  */
902 void
903 SetConfigOption(const char *name, const char *value,
904                                 GucContext context, bool makeDefault)
905 {
906         (void) set_config_option(name, value, context, true, makeDefault);
907 }
908
909
910
911 /*
912  * This is more or less the SHOW command. It returns a string with the
913  * value of the option `name'. If the option doesn't exist, throw an
914  * elog and don't return.
915  *
916  * The string is *not* allocated for modification and is really only
917  * valid until the next call to configuration related functions.
918  */
919 const char *
920 GetConfigOption(const char *name)
921 {
922         struct config_generic *record;
923         static char buffer[256];
924         enum config_type opttype;
925
926         opttype = find_option(name, &record);
927         if (opttype == PGC_NONE)
928                 elog(ERROR, "Option '%s' is not recognized", name);
929
930         switch (opttype)
931         {
932                 case PGC_BOOL:
933                         return *((struct config_bool *) record)->variable ? "on" : "off";
934
935                 case PGC_INT:
936                         snprintf(buffer, sizeof(buffer), "%d",
937                                          *((struct config_int *) record)->variable);
938                         return buffer;
939
940                 case PGC_REAL:
941                         snprintf(buffer, sizeof(buffer), "%g",
942                                          *((struct config_real *) record)->variable);
943                         return buffer;
944
945                 case PGC_STRING:
946                         return *((struct config_string *) record)->variable;
947
948                 default:
949                         ;
950         }
951         return NULL;
952 }
953
954 static void
955 _ShowOption(enum config_type opttype, struct config_generic *record)
956 {
957         char buffer[256];
958         char *val;
959
960         switch (opttype)
961         {
962                 case PGC_BOOL:
963                         val = *((struct config_bool *) record)->variable ? "on" : "off";
964                         break;
965
966                 case PGC_INT:
967                         snprintf(buffer, sizeof(buffer), "%d",
968                                          *((struct config_int *) record)->variable);
969                         val = buffer;
970                         break;
971
972                 case PGC_REAL:
973                         snprintf(buffer, sizeof(buffer), "%g",
974                                          *((struct config_real *) record)->variable);
975                         val = buffer;
976                         break;
977
978                 case PGC_STRING:
979                         val = strlen(*((struct config_string *) record)->variable) != 0 ?
980                                 *((struct config_string *) record)->variable : "unset";
981                         break;
982
983                 default:
984                         val = "???";
985         }
986         elog(NOTICE, "%s is %s", record->name, val);
987 }
988
989 void
990 ShowAllGUCConfig(void)
991 {
992         int                     i;
993
994         for (i = 0; ConfigureNamesBool[i].name; i++)
995                 _ShowOption(PGC_BOOL, (struct config_generic *)&ConfigureNamesBool[i]);
996
997         for (i = 0; ConfigureNamesInt[i].name; i++)
998                 _ShowOption(PGC_INT, (struct config_generic *)&ConfigureNamesInt[i]);
999
1000         for (i = 0; ConfigureNamesReal[i].name; i++)
1001                 _ShowOption(PGC_REAL, (struct config_generic *)&ConfigureNamesReal[i]);
1002
1003         for (i = 0; ConfigureNamesString[i].name; i++)
1004                 _ShowOption(PGC_STRING, (struct config_generic *)&ConfigureNamesString[i]);
1005 }
1006
1007
1008
1009
1010
1011 /*
1012  * A little "long argument" simulation, although not quite GNU
1013  * compliant. Takes a string of the form "some-option=some value" and
1014  * returns name = "some_option" and value = "some value" in malloc'ed
1015  * storage. Note that '-' is converted to '_' in the option name. If
1016  * there is no '=' in the input string then value will be NULL.
1017  */
1018 void
1019 ParseLongOption(const char *string, char **name, char **value)
1020 {
1021         size_t          equal_pos;
1022         char       *cp;
1023
1024         AssertArg(string);
1025         AssertArg(name);
1026         AssertArg(value);
1027
1028         equal_pos = strcspn(string, "=");
1029
1030         if (string[equal_pos] == '=')
1031         {
1032                 *name = malloc(equal_pos + 1);
1033                 if (!*name)
1034                         elog(FATAL, "out of memory");
1035                 strncpy(*name, string, equal_pos);
1036                 (*name)[equal_pos] = '\0';
1037
1038                 *value = strdup(&string[equal_pos + 1]);
1039                 if (!*value)
1040                         elog(FATAL, "out of memory");
1041         }
1042         else
1043         {
1044                 /* no equal sign in string */
1045                 *name = strdup(string);
1046                 if (!*name)
1047                         elog(FATAL, "out of memory");
1048                 *value = NULL;
1049         }
1050
1051         for (cp = *name; *cp; cp++)
1052                 if (*cp == '-')
1053                         *cp = '_';
1054 }
1055
1056
1057
1058 #ifdef ENABLE_SYSLOG
1059
1060 static bool
1061 check_facility(const char *facility)
1062 {
1063         if (strcasecmp(facility, "LOCAL0") == 0)
1064                 return true;
1065         if (strcasecmp(facility, "LOCAL1") == 0)
1066                 return true;
1067         if (strcasecmp(facility, "LOCAL2") == 0)
1068                 return true;
1069         if (strcasecmp(facility, "LOCAL3") == 0)
1070                 return true;
1071         if (strcasecmp(facility, "LOCAL4") == 0)
1072                 return true;
1073         if (strcasecmp(facility, "LOCAL5") == 0)
1074                 return true;
1075         if (strcasecmp(facility, "LOCAL6") == 0)
1076                 return true;
1077         if (strcasecmp(facility, "LOCAL7") == 0)
1078                 return true;
1079         return false;
1080 }
1081
1082 #endif