Example #1
0
/*
 * This both sets a hook function, and calls it on the current value (if any)
 */
bool
SetVariableAssignHook(VariableSpace space, const char *name, VariableAssignHook hook)
{
	struct _variable *current,
			   *previous;

	if (!space)
		return false;

	if (!valid_variable_name(name))
		return false;

	for (previous = space, current = space->next;
		 current;
		 previous = current, current = current->next)
	{
		if (strcmp(current->name, name) == 0)
		{
			/* found entry, so update */
			current->assign_hook = hook;
			(*hook) (current->value);
			return true;
		}
	}

	/* not present, make new entry */
	current = pg_malloc(sizeof *current);
	current->name = pg_strdup(name);
	current->value = NULL;
	current->assign_hook = hook;
	current->next = NULL;
	previous->next = current;
	(*hook) (NULL);
	return true;
}
Example #2
0
/*
 * Attach substitute and/or assign hook functions to the named variable.
 * If you need only one hook, pass NULL for the other.
 *
 * If the variable doesn't already exist, create it with value NULL, just so
 * we have a place to store the hook function(s).  (The substitute hook might
 * immediately change the NULL to something else; if not, this state is
 * externally the same as the variable not being defined.)
 *
 * The substitute hook, if given, is immediately called on the variable's
 * value.  Then the assign hook, if given, is called on the variable's value.
 * This is meant to let it update any derived psql state.  If the assign hook
 * doesn't like the current value, it will print a message to that effect,
 * but we'll ignore it.  Generally we do not expect any such failure here,
 * because this should get called before any user-supplied value is assigned.
 */
void
SetVariableHooks(VariableSpace space, const char *name,
				 VariableSubstituteHook shook,
				 VariableAssignHook ahook)
{
	struct _variable *current,
			   *previous;

	if (!space || !name)
		return;

	if (!valid_variable_name(name))
		return;

	for (previous = space, current = space->next;
		 current;
		 previous = current, current = current->next)
	{
		int			cmp = strcmp(current->name, name);

		if (cmp == 0)
		{
			/* found entry, so update */
			current->substitute_hook = shook;
			current->assign_hook = ahook;
			if (shook)
				current->value = (*shook) (current->value);
			if (ahook)
				(void) (*ahook) (current->value);
			return;
		}
		if (cmp > 0)
			break;				/* it's not there */
	}

	/* not present, make new entry */
	current = pg_malloc(sizeof *current);
	current->name = pg_strdup(name);
	current->value = NULL;
	current->substitute_hook = shook;
	current->assign_hook = ahook;
	current->next = previous->next;
	previous->next = current;
	if (shook)
		current->value = (*shook) (current->value);
	if (ahook)
		(void) (*ahook) (current->value);
}
Example #3
0
/*
 * Set the variable named "name" to value "value",
 * or delete it if "value" is NULL.
 *
 * Returns true if successful, false if not; in the latter case a suitable
 * error message has been printed, except for the unexpected case of
 * space or name being NULL.
 */
bool
SetVariable(VariableSpace space, const char *name, const char *value)
{
	struct _variable *current,
			   *previous;

	if (!space || !name)
		return false;

	if (!valid_variable_name(name))
	{
		/* Deletion of non-existent variable is not an error */
		if (!value)
			return true;
		psql_error("invalid variable name: \"%s\"\n", name);
		return false;
	}

	for (previous = space, current = space->next;
		 current;
		 previous = current, current = current->next)
	{
		int			cmp = strcmp(current->name, name);

		if (cmp == 0)
		{
			/*
			 * Found entry, so update, unless assign hook returns false.
			 *
			 * We must duplicate the passed value to start with.  This
			 * simplifies the API for substitute hooks.  Moreover, some assign
			 * hooks assume that the passed value has the same lifespan as the
			 * variable.  Having to free the string again on failure is a
			 * small price to pay for keeping these APIs simple.
			 */
			char	   *new_value = value ? pg_strdup(value) : NULL;
			bool		confirmed;

			if (current->substitute_hook)
				new_value = (*current->substitute_hook) (new_value);

			if (current->assign_hook)
				confirmed = (*current->assign_hook) (new_value);
			else
				confirmed = true;

			if (confirmed)
			{
				if (current->value)
					pg_free(current->value);
				current->value = new_value;

				/*
				 * If we deleted the value, and there are no hooks to
				 * remember, we can discard the variable altogether.
				 */
				if (new_value == NULL &&
					current->substitute_hook == NULL &&
					current->assign_hook == NULL)
				{
					previous->next = current->next;
					free(current->name);
					free(current);
				}
			}
			else if (new_value)
				pg_free(new_value); /* current->value is left unchanged */

			return confirmed;
		}
		if (cmp > 0)
			break;				/* it's not there */
	}

	/* not present, make new entry ... unless we were asked to delete */
	if (value)
	{
		current = pg_malloc(sizeof *current);
		current->name = pg_strdup(name);
		current->value = pg_strdup(value);
		current->substitute_hook = NULL;
		current->assign_hook = NULL;
		current->next = previous->next;
		previous->next = current;
	}
	return true;
}