PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
variables.c
Go to the documentation of this file.
1 /*
2  * psql - the PostgreSQL interactive terminal
3  *
4  * Copyright (c) 2000-2016, PostgreSQL Global Development Group
5  *
6  * src/bin/psql/variables.c
7  */
8 #include "postgres_fe.h"
9 
10 #include "common.h"
11 #include "variables.h"
12 
13 
14 /*
15  * Check whether a variable's name is allowed.
16  *
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.
20  */
21 static bool
23 {
24  const unsigned char *ptr = (const unsigned char *) name;
25 
26  /* Mustn't be zero-length */
27  if (*ptr == '\0')
28  return false;
29 
30  while (*ptr)
31  {
32  if (IS_HIGHBIT_SET(*ptr) ||
33  strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"
34  "_0123456789", *ptr) != NULL)
35  ptr++;
36  else
37  return false;
38  }
39 
40  return true;
41 }
42 
43 /*
44  * A "variable space" is represented by an otherwise-unused struct _variable
45  * that serves as list header.
46  */
49 {
50  struct _variable *ptr;
51 
52  ptr = pg_malloc(sizeof *ptr);
53  ptr->name = NULL;
54  ptr->value = NULL;
55  ptr->assign_hook = NULL;
56  ptr->next = NULL;
57 
58  return ptr;
59 }
60 
61 const char *
62 GetVariable(VariableSpace space, const char *name)
63 {
64  struct _variable *current;
65 
66  if (!space)
67  return NULL;
68 
69  for (current = space->next; current; current = current->next)
70  {
71  if (strcmp(current->name, name) == 0)
72  {
73  /* this is correct answer when value is NULL, too */
74  return current->value;
75  }
76  }
77 
78  return NULL;
79 }
80 
81 /*
82  * Try to interpret "value" as boolean value.
83  *
84  * Valid values are: true, false, yes, no, on, off, 1, 0; as well as unique
85  * prefixes thereof.
86  *
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.
89  */
90 bool
91 ParseVariableBool(const char *value, const char *name)
92 {
93  size_t len;
94 
95  if (value == NULL)
96  return false; /* not set -> assume "off" */
97 
98  len = strlen(value);
99 
100  if (pg_strncasecmp(value, "true", len) == 0)
101  return true;
102  else if (pg_strncasecmp(value, "false", len) == 0)
103  return false;
104  else if (pg_strncasecmp(value, "yes", len) == 0)
105  return true;
106  else if (pg_strncasecmp(value, "no", len) == 0)
107  return false;
108  /* 'o' is not unique enough */
109  else if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0)
110  return true;
111  else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0)
112  return false;
113  else if (pg_strcasecmp(value, "1") == 0)
114  return true;
115  else if (pg_strcasecmp(value, "0") == 0)
116  return false;
117  else
118  {
119  /* NULL is treated as false, so a non-matching value is 'true' */
120  if (name)
121  psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n",
122  value, name, "on");
123  return true;
124  }
125 }
126 
127 
128 /*
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.
132  */
133 int
134 ParseVariableNum(const char *val,
135  int defaultval,
136  int faultval,
137  bool allowtrail)
138 {
139  int result;
140 
141  if (!val)
142  result = defaultval;
143  else if (!val[0])
144  result = faultval;
145  else
146  {
147  char *end;
148 
149  result = strtol(val, &end, 0);
150  if (!allowtrail && *end)
151  result = faultval;
152  }
153 
154  return result;
155 }
156 
157 int
159  const char *name,
160  int defaultval,
161  int faultval,
162  bool allowtrail)
163 {
164  const char *val;
165 
166  val = GetVariable(space, name);
167  return ParseVariableNum(val, defaultval, faultval, allowtrail);
168 }
169 
170 void
172 {
173  struct _variable *ptr;
174 
175  if (!space)
176  return;
177 
178  for (ptr = space->next; ptr; ptr = ptr->next)
179  {
180  if (ptr->value)
181  printf("%s = '%s'\n", ptr->name, ptr->value);
182  if (cancel_pressed)
183  break;
184  }
185 }
186 
187 bool
188 SetVariable(VariableSpace space, const char *name, const char *value)
189 {
190  struct _variable *current,
191  *previous;
192 
193  if (!space)
194  return false;
195 
196  if (!valid_variable_name(name))
197  return false;
198 
199  if (!value)
200  return DeleteVariable(space, name);
201 
202  for (previous = space, current = space->next;
203  current;
204  previous = current, current = current->next)
205  {
206  if (strcmp(current->name, name) == 0)
207  {
208  /* found entry, so update */
209  if (current->value)
210  free(current->value);
211  current->value = pg_strdup(value);
212  if (current->assign_hook)
213  (*current->assign_hook) (current->value);
214  return true;
215  }
216  }
217 
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;
225  return true;
226 }
227 
228 /*
229  * This both sets a hook function, and calls it on the current value (if any)
230  */
231 bool
233 {
234  struct _variable *current,
235  *previous;
236 
237  if (!space)
238  return false;
239 
240  if (!valid_variable_name(name))
241  return false;
242 
243  for (previous = space, current = space->next;
244  current;
245  previous = current, current = current->next)
246  {
247  if (strcmp(current->name, name) == 0)
248  {
249  /* found entry, so update */
250  current->assign_hook = hook;
251  (*hook) (current->value);
252  return true;
253  }
254  }
255 
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;
263  (*hook) (NULL);
264  return true;
265 }
266 
267 bool
268 SetVariableBool(VariableSpace space, const char *name)
269 {
270  return SetVariable(space, name, "on");
271 }
272 
273 bool
274 DeleteVariable(VariableSpace space, const char *name)
275 {
276  struct _variable *current,
277  *previous;
278 
279  if (!space)
280  return false;
281 
282  for (previous = space, current = space->next;
283  current;
284  previous = current, current = current->next)
285  {
286  if (strcmp(current->name, name) == 0)
287  {
288  if (current->value)
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);
294  else
295  {
296  previous->next = current->next;
297  free(current->name);
298  free(current);
299  }
300  return true;
301  }
302  }
303 
304  return true;
305 }
static struct @76 value
void * pg_malloc(size_t size)
Definition: fe_memutils.c:47
void(* VariableAssignHook)(const char *newval)
Definition: variables.h:23
int GetVariableNum(VariableSpace space, const char *name, int defaultval, int faultval, bool allowtrail)
Definition: variables.c:158
bool SetVariableBool(VariableSpace space, const char *name)
Definition: variables.c:268
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
void PrintVariables(VariableSpace space)
Definition: variables.c:171
volatile bool cancel_pressed
Definition: print.c:47
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
VariableSpace CreateVariableSpace(void)
Definition: variables.c:48
#define IS_HIGHBIT_SET(ch)
Definition: c.h:949
bool SetVariableAssignHook(VariableSpace space, const char *name, VariableAssignHook hook)
Definition: variables.c:232
bool DeleteVariable(VariableSpace space, const char *name)
Definition: variables.c:274
VariableAssignHook assign_hook
Definition: variables.h:29
static bool valid_variable_name(const char *name)
Definition: variables.c:22
char * pg_strdup(const char *in)
Definition: fe_memutils.c:85
bool ParseVariableBool(const char *value, const char *name)
Definition: variables.c:91
struct _variable * next
Definition: variables.h:30
const char * GetVariable(VariableSpace space, const char *name)
Definition: variables.c:62
void psql_error(const char *fmt,...)
Definition: common.c:175
#define free(a)
Definition: header.h:60
char * name
Definition: variables.h:27
#define NULL
Definition: c.h:226
bool SetVariable(VariableSpace space, const char *name, const char *value)
Definition: variables.c:188
const char * name
Definition: encode.c:521
int ParseVariableNum(const char *val, int defaultval, int faultval, bool allowtrail)
Definition: variables.c:134
char * value
Definition: variables.h:28
long val
Definition: informix.c:689