Consistently use "superuser" instead of "super user"
[pgsql.git] / src / bin / psql / variables.c
blob92a34f870fd22df0aa42707819d43bb8362c1d09
1 /*
2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2021, PostgreSQL Global Development Group
6 * src/bin/psql/variables.c
7 */
8 #include "postgres_fe.h"
10 #include "common.h"
11 #include "common/logging.h"
12 #include "variables.h"
15 * Check whether a variable's name is allowed.
17 * We allow any non-ASCII character, as well as ASCII letters, digits, and
18 * underscore. Keep this in sync with the definition of variable_char in
19 * psqlscan.l and psqlscanslash.l.
21 static bool
22 valid_variable_name(const char *name)
24 const unsigned char *ptr = (const unsigned char *) name;
26 /* Mustn't be zero-length */
27 if (*ptr == '\0')
28 return false;
30 while (*ptr)
32 if (IS_HIGHBIT_SET(*ptr) ||
33 strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
34 "_0123456789", *ptr) != NULL)
35 ptr++;
36 else
37 return false;
40 return true;
44 * A "variable space" is represented by an otherwise-unused struct _variable
45 * that serves as list header.
47 * The list entries are kept in name order (according to strcmp). This
48 * is mainly to make the results of PrintVariables() more pleasing.
50 VariableSpace
51 CreateVariableSpace(void)
53 struct _variable *ptr;
55 ptr = pg_malloc(sizeof *ptr);
56 ptr->name = NULL;
57 ptr->value = NULL;
58 ptr->substitute_hook = NULL;
59 ptr->assign_hook = NULL;
60 ptr->next = NULL;
62 return ptr;
66 * Get string value of variable, or NULL if it's not defined.
68 * Note: result is valid until variable is next assigned to.
70 const char *
71 GetVariable(VariableSpace space, const char *name)
73 struct _variable *current;
75 if (!space)
76 return NULL;
78 for (current = space->next; current; current = current->next)
80 int cmp = strcmp(current->name, name);
82 if (cmp == 0)
84 /* this is correct answer when value is NULL, too */
85 return current->value;
87 if (cmp > 0)
88 break; /* it's not there */
91 return NULL;
95 * Try to interpret "value" as a boolean value, and if successful,
96 * store it in *result. Otherwise don't clobber *result.
98 * Valid values are: true, false, yes, no, on, off, 1, 0; as well as unique
99 * prefixes thereof.
101 * "name" is the name of the variable we're assigning to, to use in error
102 * report if any. Pass name == NULL to suppress the error report.
104 * Return true when "value" is syntactically valid, false otherwise.
106 bool
107 ParseVariableBool(const char *value, const char *name, bool *result)
109 size_t len;
110 bool valid = true;
112 /* Treat "unset" as an empty string, which will lead to error below */
113 if (value == NULL)
114 value = "";
116 len = strlen(value);
118 if (len > 0 && pg_strncasecmp(value, "true", len) == 0)
119 *result = true;
120 else if (len > 0 && pg_strncasecmp(value, "false", len) == 0)
121 *result = false;
122 else if (len > 0 && pg_strncasecmp(value, "yes", len) == 0)
123 *result = true;
124 else if (len > 0 && pg_strncasecmp(value, "no", len) == 0)
125 *result = false;
126 /* 'o' is not unique enough */
127 else if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0)
128 *result = true;
129 else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0)
130 *result = false;
131 else if (pg_strcasecmp(value, "1") == 0)
132 *result = true;
133 else if (pg_strcasecmp(value, "0") == 0)
134 *result = false;
135 else
137 /* string is not recognized; don't clobber *result */
138 if (name)
139 pg_log_error("unrecognized value \"%s\" for \"%s\": Boolean expected",
140 value, name);
141 valid = false;
143 return valid;
147 * Try to interpret "value" as an integer value, and if successful,
148 * store it in *result. Otherwise don't clobber *result.
150 * "name" is the name of the variable we're assigning to, to use in error
151 * report if any. Pass name == NULL to suppress the error report.
153 * Return true when "value" is syntactically valid, false otherwise.
155 bool
156 ParseVariableNum(const char *value, const char *name, int *result)
158 char *end;
159 long numval;
161 /* Treat "unset" as an empty string, which will lead to error below */
162 if (value == NULL)
163 value = "";
165 errno = 0;
166 numval = strtol(value, &end, 0);
167 if (errno == 0 && *end == '\0' && end != value && numval == (int) numval)
169 *result = (int) numval;
170 return true;
172 else
174 /* string is not recognized; don't clobber *result */
175 if (name)
176 pg_log_error("invalid value \"%s\" for \"%s\": integer expected",
177 value, name);
178 return false;
183 * Print values of all variables.
185 void
186 PrintVariables(VariableSpace space)
188 struct _variable *ptr;
190 if (!space)
191 return;
193 for (ptr = space->next; ptr; ptr = ptr->next)
195 if (ptr->value)
196 printf("%s = '%s'\n", ptr->name, ptr->value);
197 if (cancel_pressed)
198 break;
203 * Set the variable named "name" to value "value",
204 * or delete it if "value" is NULL.
206 * Returns true if successful, false if not; in the latter case a suitable
207 * error message has been printed, except for the unexpected case of
208 * space or name being NULL.
210 bool
211 SetVariable(VariableSpace space, const char *name, const char *value)
213 struct _variable *current,
214 *previous;
216 if (!space || !name)
217 return false;
219 if (!valid_variable_name(name))
221 /* Deletion of non-existent variable is not an error */
222 if (!value)
223 return true;
224 pg_log_error("invalid variable name: \"%s\"", name);
225 return false;
228 for (previous = space, current = space->next;
229 current;
230 previous = current, current = current->next)
232 int cmp = strcmp(current->name, name);
234 if (cmp == 0)
237 * Found entry, so update, unless assign hook returns false.
239 * We must duplicate the passed value to start with. This
240 * simplifies the API for substitute hooks. Moreover, some assign
241 * hooks assume that the passed value has the same lifespan as the
242 * variable. Having to free the string again on failure is a
243 * small price to pay for keeping these APIs simple.
245 char *new_value = value ? pg_strdup(value) : NULL;
246 bool confirmed;
248 if (current->substitute_hook)
249 new_value = current->substitute_hook(new_value);
251 if (current->assign_hook)
252 confirmed = current->assign_hook(new_value);
253 else
254 confirmed = true;
256 if (confirmed)
258 if (current->value)
259 pg_free(current->value);
260 current->value = new_value;
263 * If we deleted the value, and there are no hooks to
264 * remember, we can discard the variable altogether.
266 if (new_value == NULL &&
267 current->substitute_hook == NULL &&
268 current->assign_hook == NULL)
270 previous->next = current->next;
271 free(current->name);
272 free(current);
275 else if (new_value)
276 pg_free(new_value); /* current->value is left unchanged */
278 return confirmed;
280 if (cmp > 0)
281 break; /* it's not there */
284 /* not present, make new entry ... unless we were asked to delete */
285 if (value)
287 current = pg_malloc(sizeof *current);
288 current->name = pg_strdup(name);
289 current->value = pg_strdup(value);
290 current->substitute_hook = NULL;
291 current->assign_hook = NULL;
292 current->next = previous->next;
293 previous->next = current;
295 return true;
299 * Attach substitute and/or assign hook functions to the named variable.
300 * If you need only one hook, pass NULL for the other.
302 * If the variable doesn't already exist, create it with value NULL, just so
303 * we have a place to store the hook function(s). (The substitute hook might
304 * immediately change the NULL to something else; if not, this state is
305 * externally the same as the variable not being defined.)
307 * The substitute hook, if given, is immediately called on the variable's
308 * value. Then the assign hook, if given, is called on the variable's value.
309 * This is meant to let it update any derived psql state. If the assign hook
310 * doesn't like the current value, it will print a message to that effect,
311 * but we'll ignore it. Generally we do not expect any such failure here,
312 * because this should get called before any user-supplied value is assigned.
314 void
315 SetVariableHooks(VariableSpace space, const char *name,
316 VariableSubstituteHook shook,
317 VariableAssignHook ahook)
319 struct _variable *current,
320 *previous;
322 if (!space || !name)
323 return;
325 if (!valid_variable_name(name))
326 return;
328 for (previous = space, current = space->next;
329 current;
330 previous = current, current = current->next)
332 int cmp = strcmp(current->name, name);
334 if (cmp == 0)
336 /* found entry, so update */
337 current->substitute_hook = shook;
338 current->assign_hook = ahook;
339 if (shook)
340 current->value = (*shook) (current->value);
341 if (ahook)
342 (void) (*ahook) (current->value);
343 return;
345 if (cmp > 0)
346 break; /* it's not there */
349 /* not present, make new entry */
350 current = pg_malloc(sizeof *current);
351 current->name = pg_strdup(name);
352 current->value = NULL;
353 current->substitute_hook = shook;
354 current->assign_hook = ahook;
355 current->next = previous->next;
356 previous->next = current;
357 if (shook)
358 current->value = (*shook) (current->value);
359 if (ahook)
360 (void) (*ahook) (current->value);
364 * Return true iff the named variable has substitute and/or assign hook
365 * functions.
367 bool
368 VariableHasHook(VariableSpace space, const char *name)
370 struct _variable *current;
372 Assert(space);
373 Assert(name);
375 for (current = space->next; current; current = current->next)
377 int cmp = strcmp(current->name, name);
379 if (cmp == 0)
380 return (current->substitute_hook != NULL ||
381 current->assign_hook != NULL);
382 if (cmp > 0)
383 break; /* it's not there */
386 return false;
390 * Convenience function to set a variable's value to "on".
392 bool
393 SetVariableBool(VariableSpace space, const char *name)
395 return SetVariable(space, name, "on");
399 * Attempt to delete variable.
401 * If unsuccessful, print a message and return "false".
402 * Deleting a nonexistent variable is not an error.
404 bool
405 DeleteVariable(VariableSpace space, const char *name)
407 return SetVariable(space, name, NULL);
411 * Emit error with suggestions for variables or commands
412 * accepting enum-style arguments.
413 * This function just exists to standardize the wording.
414 * suggestions should follow the format "fee, fi, fo, fum".
416 void
417 PsqlVarEnumError(const char *name, const char *value, const char *suggestions)
419 pg_log_error("unrecognized value \"%s\" for \"%s\"\n"
420 "Available values are: %s.",
421 value, name, suggestions);