2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2015, PostgreSQL Global Development Group
6 * src/bin/psql/variables.c
8 #include "postgres_fe.h"
11 #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
22 valid_variable_name(const char *name)
24 const unsigned char *ptr = (const unsigned char *) name;
26 /* Mustn't be zero-length */
32 if (IS_HIGHBIT_SET(*ptr) ||
33 strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
34 "_0123456789", *ptr) != NULL)
44 * A "variable space" is represented by an otherwise-unused struct _variable
45 * that serves as list header.
48 CreateVariableSpace(void)
50 struct _variable *ptr;
52 ptr = pg_malloc(sizeof *ptr);
55 ptr->assign_hook = NULL;
62 GetVariable(VariableSpace space, const char *name)
64 struct _variable *current;
69 for (current = space->next; current; current = current->next)
71 if (strcmp(current->name, name) == 0)
73 /* this is correct answer when value is NULL, too */
74 return current->value;
82 * Try to interpret "value" as boolean value.
84 * Valid values are: true, false, yes, no, on, off, 1, 0; as well as unique
87 * "name" is the name of the variable we're assigning to, to use in error
88 * report if any. Pass name == NULL to suppress the error report.
91 ParseVariableBool(const char *value, const char *name)
96 return false; /* not set -> assume "off" */
100 if (pg_strncasecmp(value, "true", len) == 0)
102 else if (pg_strncasecmp(value, "false", len) == 0)
104 else if (pg_strncasecmp(value, "yes", len) == 0)
106 else if (pg_strncasecmp(value, "no", len) == 0)
108 /* 'o' is not unique enough */
109 else if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0)
111 else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0)
113 else if (pg_strcasecmp(value, "1") == 0)
115 else if (pg_strcasecmp(value, "0") == 0)
119 /* NULL is treated as false, so a non-matching value is 'true' */
121 psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
129 * Read numeric variable, or defaultval if it is not set, or faultval if its
130 * value is not a valid numeric string. If allowtrail is false, this will
131 * include the case where there are trailing characters after the number.
134 ParseVariableNum(const char *val,
149 result = strtol(val, &end, 0);
150 if (!allowtrail && *end)
158 GetVariableNum(VariableSpace space,
166 val = GetVariable(space, name);
167 return ParseVariableNum(val, defaultval, faultval, allowtrail);
171 PrintVariables(VariableSpace space)
173 struct _variable *ptr;
178 for (ptr = space->next; ptr; ptr = ptr->next)
181 printf("%s = '%s'\n", ptr->name, ptr->value);
188 SetVariable(VariableSpace space, const char *name, const char *value)
190 struct _variable *current,
196 if (!valid_variable_name(name))
200 return DeleteVariable(space, name);
202 for (previous = space, current = space->next;
204 previous = current, current = current->next)
206 if (strcmp(current->name, name) == 0)
208 /* found entry, so update */
210 free(current->value);
211 current->value = pg_strdup(value);
212 if (current->assign_hook)
213 (*current->assign_hook) (current->value);
218 /* not present, make new entry */
219 current = pg_malloc(sizeof *current);
220 current->name = pg_strdup(name);
221 current->value = pg_strdup(value);
222 current->assign_hook = NULL;
223 current->next = NULL;
224 previous->next = current;
229 * This both sets a hook function, and calls it on the current value (if any)
232 SetVariableAssignHook(VariableSpace space, const char *name, VariableAssignHook hook)
234 struct _variable *current,
240 if (!valid_variable_name(name))
243 for (previous = space, current = space->next;
245 previous = current, current = current->next)
247 if (strcmp(current->name, name) == 0)
249 /* found entry, so update */
250 current->assign_hook = hook;
251 (*hook) (current->value);
256 /* not present, make new entry */
257 current = pg_malloc(sizeof *current);
258 current->name = pg_strdup(name);
259 current->value = NULL;
260 current->assign_hook = hook;
261 current->next = NULL;
262 previous->next = current;
268 SetVariableBool(VariableSpace space, const char *name)
270 return SetVariable(space, name, "on");
274 DeleteVariable(VariableSpace space, const char *name)
276 struct _variable *current,
282 for (previous = space, current = space->next;
284 previous = current, current = current->next)
286 if (strcmp(current->name, name) == 0)
289 free(current->value);
290 current->value = NULL;
291 /* Physically delete only if no hook function to remember */
292 if (current->assign_hook)
293 (*current->assign_hook) (NULL);
296 previous->next = current->next;