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.6 2003/09/25 06:58:06 petere 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"),
65 static const char *const GENERIC_DESC[] = {
66 gettext_noop("Description: %s\n%s\n"),
69 static const char *const BOOL_FORMAT[] = {
70 gettext_noop("Type: Boolean\nReset value: %-s\n"),
73 static const char *const INT_FORMAT[] = {
74 gettext_noop("Type: integer\nReset value: %-20d\nMin value: %-20d\nMax value: %-20d\n"),
77 static const char *const REAL_FORMAT[] = {
78 gettext_noop("Type: real\nReset value: %-20g\nMin value: %-20g\nMax value: %-20g\n"),
81 static const char *const STRING_FORMAT[] = {
82 gettext_noop("Type: string\nReset value: %-s\n"),
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
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);
137 * Reads in the the command line options and sets the state of the program
138 * accordingly. Initializes the result list and sorts it.
141 GucInfoMain(int argc, char *argv[])
143 mixedStruct **varList;
148 while ((c = getopt(argc, argv, "g:rGmMlh")) != -1)
153 groupString = optarg;
155 case 'r': /* not actually implemented yet */
156 nameRegexBool = true;
159 groupResults = false;
162 outFormat = MACHINE_OUTPUT;
165 outFormat = MACHINE_OUTPUT;
166 suppressAllHeaders = true;
176 fprintf(stderr, gettext("%s \n Try -h for further details\n"), usageErrMsg());
182 nameString = argv[optind];
184 /* get the list of variables that match the user's specs. */
185 varList = varsToDisplay(&resultListSize);
187 /* sort them by group if desired */
188 /* (without this, we get the original sort by name from guc.c) */
190 qsort(varList, resultListSize,
191 sizeof(mixedStruct *), compareMixedStructs);
193 /* output the results */
194 if (!suppressAllHeaders)
195 printf(gettext(COLUMN_HEADER[outFormat]));
197 for (i = 0; varList[i] != NULL; i++)
199 printf(gettext(ROW_SEPARATOR[outFormat]));
200 printMixedStruct(varList[i]);
208 * This function is used to compare two mixedStruct types. It compares based
209 * on the value of the 'group' field, and then the name of the variable.
210 * Each void* is expected to be a pointer to a pointer to a struct.
211 * (This is because it is used by qsort to sort an array of struct pointers)
213 * Returns an integer less than, equal to, or greater than zero if the first
214 * argument (struct1) is considered to be respectively less than, equal to,
215 * or greater than the second (struct2). The comparison is made frist on the
216 * value of struct{1,2}.generic.group and then struct{1,2}.generic.name. The
217 * groups will display in the order they are defined in enum config_group
220 compareMixedStructs(const void *struct1, const void *struct2)
222 mixedStruct *structVar1 = *(mixedStruct **) struct1;
223 mixedStruct *structVar2 = *(mixedStruct **) struct2;
225 if (structVar1->generic.group > structVar2->generic.group)
227 else if (structVar1->generic.group < structVar2->generic.group)
230 return strcmp(structVar1->generic.name, structVar2->generic.name);
235 * This function returns a complete list of all the variables to display,
236 * according to what the user wants to see.
238 static mixedStruct **
239 varsToDisplay(int *resultListSize)
241 mixedStruct **resultList;
245 /* Initialize the guc_variables[] array */
246 build_guc_variables();
248 /* Extract just the ones we want to display */
249 resultList = malloc((num_guc_variables + 1) * sizeof(mixedStruct *));
252 for (i = 0; i < num_guc_variables; i++)
254 mixedStruct *var = (mixedStruct *) guc_variables[i];
257 resultList[arrayIndex++] = var;
260 /* add an end marker */
261 resultList[arrayIndex] = NULL;
263 *resultListSize = arrayIndex;
269 * This function will return true if the struct passed to it
270 * should be displayed to the user.
272 * The criteria to determine if the struct should not be displayed is:
273 * + It's flag bits are set to GUC_NO_SHOW_ALL
274 * + It's flag bits are set to GUC_NOT_IN_SAMPLE
275 * + It's flag bits are set to GUC_DISALLOW_IN_FILE
278 displayStruct(mixedStruct *structToDisplay)
280 if (structToDisplay->generic.flags & (GUC_NO_SHOW_ALL |
282 GUC_DISALLOW_IN_FILE))
290 * Used to determine if a variable matches the user's specifications (stored in
291 * global variables). Returns true if this particular variable information should
292 * be returned to the user.
295 varMatches(mixedStruct *structToTest)
297 bool matches = false;
298 bool specificSearch = false; /* This is true if the user
299 * searched for a variable in
302 if (nameString != NULL && !nameRegexBool)
304 if (strstr(structToTest->generic.name, nameString) != NULL)
307 specificSearch = true;
311 if (nameString != NULL && nameRegexBool)
313 /* We do not support this option yet */
316 if (groupString != NULL && !groupRegexBool)
318 if (strstr(config_group_names[structToTest->generic.group], groupString) != NULL)
320 if (nameString != NULL)
321 matches = (matches && true);
329 if (groupString != NULL && groupRegexBool)
331 /* We do not support this option yet */
334 /* return all variables */
335 if (nameString == NULL && groupString == NULL)
341 return matches && displayStruct(structToTest);
346 * This function prints out the generic struct passed to it. It will print out
347 * a different format, depending on what the user wants to see.
350 printMixedStruct(mixedStruct *structToPrint)
352 printGenericHead(structToPrint->generic);
354 switch (structToPrint->generic.vartype)
358 printf(gettext(BOOL_FORMAT[outFormat]),
359 (structToPrint->bool.reset_val == 0) ?
360 gettext("FALSE") : gettext("TRUE"));
364 printf(gettext(INT_FORMAT[outFormat]),
365 structToPrint->integer.reset_val,
366 structToPrint->integer.min,
367 structToPrint->integer.max);
371 printf(gettext(REAL_FORMAT[outFormat]),
372 structToPrint->real.reset_val,
373 structToPrint->real.min,
374 structToPrint->real.max);
378 printf(gettext(STRING_FORMAT[outFormat]),
379 structToPrint->string.boot_val);
383 printf(gettext("Unrecognized variable type!\n"));
387 printGenericFoot(structToPrint->generic);
391 printGenericHead(struct config_generic structToPrint)
393 printf(gettext(GENERIC_FORMAT[outFormat]),
395 GucContext_Names[structToPrint.context],
396 gettext(config_group_names[structToPrint.group]));
400 printGenericFoot(struct config_generic sPrint)
402 printf(gettext(GENERIC_DESC[outFormat]),
403 (sPrint.short_desc == NULL) ? "" : gettext(sPrint.short_desc),
404 (sPrint.long_desc == NULL) ? "" : gettext(sPrint.long_desc));
412 printf(gettext("All currently defined groups\n"));
413 printf(gettext("----------------------------\n"));
414 for (i = 0; config_group_names[i] != NULL; i++)
415 printf(gettext("%s\n"), gettext(config_group_names[i]));
421 return gettext("Usage for --help-config option: [-h] [-g <group>] [-l] [-G] [-m] [-M] [string]\n");
427 printf(gettext("Description:\n"
428 "--help-config displays all the runtime options available in PostgreSQL.\n"
429 "It groups them by category and sorts them by name. If available, it will\n"
430 "present a short description, default, max and min values as well as other\n"
431 "information about each option.\n\n"
432 "With no options specified, it will output all available runtime options\n"
433 "in human friendly format, grouped by category and sorted by name.\n\n"
438 " [string] All options with names that match this string\n"
439 " -g GROUP All options in categories that match GROUP\n"
440 " -l Prints list of all groups / subgroups\n"
441 " -h Prints this help message\n"
442 "\nOutput Options:\n"
443 " -G Do not group by category\n"
444 " -m Machine friendly format: tab separated fields\n"
445 " -M Same as m, except header with column names is suppressed\n"),