1 /*-------------------------------------------------------------------------
4 * Displays available options under grand unified configuration scheme
6 * The purpose of this option is to list, sort, and make searchable, all
7 * runtime options available to Postgresql, by their description and grouping.
9 * Valid command-line options to this program:
11 * none : All available variables are sorted by group and name
12 * and formatted nicely. ( for human consumption )
13 * <string> : list all the variables whose name matches this string
14 * -g <string> : list all the variables whose group matches this string
15 * -l : lists all currently defined groups and terminates
16 * -G : no sort by groups (you get strict name order, instead)
17 * -m : output the list in Machine friendly format, with a header row
18 * -M : same as m, except no header
21 * Options whose flag bits are set to GUC_NO_SHOW_ALL, GUC_NOT_IN_SAMPLE,
22 * or GUC_DISALLOW_IN_FILE are not displayed, unless the user specifically
23 * requests that variable by name
25 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
28 * $Header: /cvsroot/pgsql/src/backend/utils/misc/help_config.c,v 1.2 2003/07/09 17:57:47 momjian Exp $
30 *-------------------------------------------------------------------------
43 #include "utils/guc.h"
44 #include "utils/guc_tables.h"
45 #include "utils/help_config.h"
52 * The following char constructs provide the different formats the variables
53 * can be outputted in.
61 static const char * const GENERIC_FORMAT[] = {
62 gettext_noop("Name : %-20s \nContext : %-20s \nGroup : %-20s\n"),
63 gettext_noop("%s\t%s\t%s\t")
65 static const char * const GENERIC_DESC[] = {
66 gettext_noop("Description: %s\n%s\n"),
67 gettext_noop("%s %s\n")
69 static const char * const BOOL_FORMAT[] = {
70 gettext_noop("Type : BOOL\nReset Value: %-s \n"),
71 gettext_noop("BOOL\t%s\t\t\t")
73 static const char * const INT_FORMAT[] = {
74 gettext_noop("Type : INT\nReset Value: %-20d \nMin Value : %-20d \nMax Value : %-20d \n"),
75 gettext_noop("INT\t%d\t%d\t%d\t")
77 static const char * const REAL_FORMAT[] = {
78 gettext_noop("Type : REAL\nReset Value: %-20g \nMin Value : %-20g \nMax Value : %-20g \n"),
79 gettext_noop("REAL\t%g\t%g\t%g\t")
81 static const char * const STRING_FORMAT[] = {
82 gettext_noop("Type : STRING\nReset Value: %-s \n"),
83 gettext_noop("STRING\t%s\t\t\t")
85 static const char * const COLUMN_HEADER[] = {
87 gettext_noop("NAME\tCONTEXT\tGROUP\tTYPE\tRESET_VALUE\tMIN\tMAX\tSHORT_DESCRIPTION\tLONG_DESCRIPTION\n")
89 static const char * const ROW_SEPARATOR[] = {
90 "------------------------------------------------------------\n",
95 * Variables loaded from the command line
97 static char *nameString = NULL; /* The var name pattern to match */
98 static bool nameRegexBool = false; /* Match the name pattern as a
100 static char *groupString = NULL; /* The var group pattern to match */
101 static bool groupRegexBool = false; /* Match the group pattern as a
103 static enum outputFormat outFormat = HUMAN_OUTPUT;
104 static bool suppressAllHeaders = false; /* MACHINE_OUTPUT output, no column
106 static bool groupResults = true; /* sort result list by groups */
110 * This union allows us to mix the numerous different types of structs
111 * that we are organizing.
115 struct config_generic generic;
116 struct config_bool bool;
117 struct config_real real;
118 struct config_int integer;
119 struct config_string string;
123 /* function prototypes */
124 static bool varMatches(mixedStruct * structToTest);
125 static int compareMixedStructs(const void *, const void *);
126 static mixedStruct **varsToDisplay(int *resultListSize);
127 static const char *usageErrMsg(void);
128 static void helpMessage(void);
129 static void listAllGroups(void);
130 static void printGenericHead(struct config_generic structToPrint);
131 static void printGenericFoot(struct config_generic structToPrint);
132 static void printMixedStruct(mixedStruct * structToPrint);
133 static bool displayStruct(mixedStruct * structToDisplay);
136 * This array contains the display names for each of the GucContexts available
138 * Note: these strings are deliberately not localized.
140 static const char *const GucContext_names[] = {
151 * Reads in the the command line options and sets the state of the program
152 * accordingly. Initializes the result list and sorts it.
155 GucInfoMain(int argc, char *argv[])
157 mixedStruct **varList;
162 while ((c = getopt(argc, argv, "g:rGmMlh")) != -1)
167 groupString = optarg;
169 case 'r': /* not actually implemented yet */
170 nameRegexBool = true;
173 groupResults = false;
176 outFormat = MACHINE_OUTPUT;
179 outFormat = MACHINE_OUTPUT;
180 suppressAllHeaders = true;
190 fprintf(stderr, gettext("%s \n Try -h for further details\n"), usageErrMsg());
196 nameString = argv[optind];
198 /* get the list of variables that match the user's specs. */
199 varList = varsToDisplay(&resultListSize);
201 /* sort them by group if desired */
202 /* (without this, we get the original sort by name from guc.c) */
204 qsort(varList, resultListSize,
205 sizeof(mixedStruct *), compareMixedStructs);
207 /* output the results */
208 if (!suppressAllHeaders)
209 printf(gettext(COLUMN_HEADER[outFormat]));
211 for (i = 0; varList[i] != NULL; i++)
213 printf(gettext(ROW_SEPARATOR[outFormat]));
214 printMixedStruct(varList[i]);
222 * This function is used to compare two mixedStruct types. It compares based
223 * on the value of the 'group' field, and then the name of the variable.
224 * Each void* is expected to be a pointer to a pointer to a struct.
225 * (This is because it is used by qsort to sort an array of struct pointers)
227 * Returns an integer less than, equal to, or greater than zero if the first
228 * argument (struct1) is considered to be respectively less than, equal to,
229 * or greater than the second (struct2). The comparison is made frist on the
230 * value of struct{1,2}.generic.group and then struct{1,2}.generic.name. The
231 * groups will display in the order they are defined in enum config_group
234 compareMixedStructs(const void *struct1, const void *struct2)
236 mixedStruct *structVar1 = *(mixedStruct **) struct1;
237 mixedStruct *structVar2 = *(mixedStruct **) struct2;
239 if (structVar1->generic.group > structVar2->generic.group)
241 else if (structVar1->generic.group < structVar2->generic.group)
244 return strcmp(structVar1->generic.name, structVar2->generic.name);
249 * This function returns a complete list of all the variables to display,
250 * according to what the user wants to see.
252 static mixedStruct **
253 varsToDisplay(int *resultListSize)
255 mixedStruct **resultList;
259 /* Initialize the guc_variables[] array */
260 build_guc_variables();
262 /* Extract just the ones we want to display */
263 resultList = malloc((num_guc_variables + 1) * sizeof(mixedStruct *));
266 for (i = 0; i < num_guc_variables; i++)
268 mixedStruct *var = (mixedStruct *) guc_variables[i];
271 resultList[arrayIndex++] = var;
274 /* add an end marker */
275 resultList[arrayIndex] = NULL;
277 *resultListSize = arrayIndex;
283 * This function will return true if the struct passed to it
284 * should be displayed to the user.
286 * The criteria to determine if the struct should not be displayed is:
287 * + It's flag bits are set to GUC_NO_SHOW_ALL
288 * + It's flag bits are set to GUC_NOT_IN_SAMPLE
289 * + It's flag bits are set to GUC_DISALLOW_IN_FILE
292 displayStruct(mixedStruct * structToDisplay)
294 if (structToDisplay->generic.flags & (GUC_NO_SHOW_ALL |
296 GUC_DISALLOW_IN_FILE))
304 * Used to determine if a variable matches the user's specifications (stored in
305 * global variables). Returns true if this particular variable information should
306 * be returned to the user.
309 varMatches(mixedStruct * structToTest)
311 bool matches = false;
312 bool specificSearch = false; /* This is true if the user
313 * searched for a variable in
316 if (nameString != NULL && !nameRegexBool)
318 if (strstr(structToTest->generic.name, nameString) != NULL)
321 specificSearch = true;
325 if (nameString != NULL && nameRegexBool)
327 /* We do not support this option yet */
330 if (groupString != NULL && !groupRegexBool)
332 if (strstr(config_group_names[structToTest->generic.group], groupString) != NULL)
334 if (nameString != NULL)
335 matches = (matches && true);
343 if (groupString != NULL && groupRegexBool)
345 /* We do not support this option yet */
348 /* return all variables */
349 if (nameString == NULL && groupString == NULL)
355 return matches && displayStruct(structToTest);
360 * This function prints out the generic struct passed to it. It will print out
361 * a different format, depending on what the user wants to see.
364 printMixedStruct(mixedStruct * structToPrint)
366 printGenericHead(structToPrint->generic);
368 switch (structToPrint->generic.vartype)
372 printf(gettext(BOOL_FORMAT[outFormat]),
373 (structToPrint->bool.reset_val == 0) ?
374 gettext("FALSE") : gettext("TRUE"));
378 printf(gettext(INT_FORMAT[outFormat]),
379 structToPrint->integer.reset_val,
380 structToPrint->integer.min,
381 structToPrint->integer.max);
385 printf(gettext(REAL_FORMAT[outFormat]),
386 structToPrint->real.reset_val,
387 structToPrint->real.min,
388 structToPrint->real.max);
392 printf(gettext(STRING_FORMAT[outFormat]),
393 structToPrint->string.boot_val);
397 printf(gettext("Unrecognized variable type!\n"));
401 printGenericFoot(structToPrint->generic);
405 printGenericHead(struct config_generic structToPrint)
407 printf(gettext(GENERIC_FORMAT[outFormat]),
409 GucContext_names[structToPrint.context],
410 gettext(config_group_names[structToPrint.group]));
414 printGenericFoot(struct config_generic sPrint)
416 printf(gettext(GENERIC_DESC[outFormat]),
417 (sPrint.short_desc == NULL) ? "" : gettext(sPrint.short_desc),
418 (sPrint.long_desc == NULL) ? "" : gettext(sPrint.long_desc));
426 printf(gettext("All currently defined groups\n"));
427 printf(gettext("----------------------------\n"));
428 for (i = 0; config_group_names[i] != NULL; i++)
429 printf(gettext("%s\n"), gettext(config_group_names[i]));
435 return gettext("Usage for --help-config option: [-h] [-g <group>] [-l] [-G] [-m] [-M] [string]\n");
441 printf(gettext("Description:\n"
442 "--help-config displays all the runtime options available in PostgreSQL.\n"
443 "It groups them by category and sorts them by name. If available, it will\n"
444 "present a short description, default, max and min values as well as other\n"
445 "information about each option.\n\n"
446 "With no options specified, it will output all available runtime options\n"
447 "in human friendly format, grouped by category and sorted by name.\n\n"
452 " [string] All options with names that match this string\n"
453 " -g GROUP All options in categories that match GROUP\n"
454 " -l Prints list of all groups / subgroups\n"
455 " -h Prints this help message\n"
456 "\nOutput Options:\n"
457 " -G Do not group by category\n"
458 " -m Machine friendly format: tab separated fields\n"
459 " -M Same as m, except header with column names is suppressed\n"),