diff options
Diffstat (limited to 'degesch.c')
| -rw-r--r-- | degesch.c | 160 | 
1 files changed, 130 insertions, 30 deletions
@@ -3647,6 +3647,39 @@ config_dump (struct config_item_ *root, struct str_vector *output)  	config_dump_item (root, &data);  } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +static int +str_vector_sort_cb (const void *a, const void *b) +{ +	return strcmp (*(const char **) a, *(const char **) b); +} + +static void +str_vector_sort (struct str_vector *self) +{ +	qsort (self->vector, self->len, sizeof *self->vector, str_vector_sort_cb); +} + +static void +dump_matching_options +	(struct app_context *ctx, const char *mask, struct str_vector *output) +{ +	config_dump (ctx->config.root, output); +	str_vector_sort (output); + +	// Filter out results by wildcard matching +	for (size_t i = 0; i < output->len; i++) +	{ +		// Yeah, I know +		const char *line = output->vector[i]; +		char *key = xstrndup (line, strcspn (line, " ")); +		if (fnmatch (mask, key, 0)) +			str_vector_remove (output, i--); +		free (key); +	} +} +  // --- User input handling -----------------------------------------------------  static bool handle_command_help (struct app_context *, char *); @@ -3773,6 +3806,78 @@ handle_command_buffer (struct app_context *ctx, char *arguments)  	return true;  } +static ssize_t +str_vector_find (const struct str_vector *v, const char *s) +{ +	for (size_t i = 0; i < v->len; i++) +		if (!strcmp (v->vector[i], s)) +			return i; +	return -1; +} + +static bool +replace_string_array +	(struct config_item_ *item, struct str_vector *array, struct error **e) +{ +	char *changed = join_str_vector (array, ','); +	struct str tmp = { .str = changed, .len = strlen (changed) }; +	bool result = config_item_set_from (item, +		config_item_string_array (&tmp), e); +	free (changed); +	return result; +} + +static bool +handle_command_set_add +	(struct config_item_ *item, const char *value, struct error **e) +{ +	bool result = false; +	struct str_vector items; +	str_vector_init (&items); +	split_str (item->value.string.str, ',', &items); + +	if (str_vector_find (&items, value) != -1) +		error_set (e, "already present in the array: %s", value); +	else +	{ +		str_vector_add (&items, value); +		result = replace_string_array (item, &items, e); +	} + +	str_vector_free (&items); +	return result; +} + +static bool +handle_command_set_remove +	(struct config_item_ *item, const char *value, struct error **e) +{ +	bool result = false; +	struct str_vector items; +	str_vector_init (&items); +	split_str (item->value.string.str, ',', &items); + +	ssize_t i = str_vector_find (&items, value); +	if (i == -1) +		error_set (e, "not present in the array: %s", value); +	else +	{ +		str_vector_remove (&items, i); +		result = replace_string_array (item, &items, e); +	} + +	str_vector_free (&items); +	return result; +} + +static bool +handle_command_set_replace (struct app_context *ctx, +	struct config_item_ *item, struct config_item_ *new_, struct error **e) +{ +	// TODO: replace the item (or log error) +	return false; +} +  static bool  handle_command_set_assign  	(struct app_context *ctx, struct str_vector *all, char *arguments) @@ -3815,53 +3920,48 @@ handle_command_set_assign  			config_item_get (ctx->config.root, key, NULL);  		hard_assert (item); +		struct error *e = NULL;  		if ((add | remove) && item->type != CONFIG_ITEM_STRING_ARRAY) -			buffer_send_error (ctx, ctx->global_buffer, -				"Option is not a string array: %s", key); +			// FIXME: it can also be null, which makes this message confusing +			error_set (&e, "not a string array");  		else if (add) -			; // TODO: add to string array (or log error) +			handle_command_set_add (item, new_->value.string.str, &e);  		else if (remove) -			; // TODO: remove from string array (or log error) +			handle_command_set_remove (item, new_->value.string.str, &e);  		else -			; // TODO: reset the value +			handle_command_set_replace (ctx, item, new_, &e); + +		if (e) +		{ +			buffer_send_error (ctx, ctx->global_buffer, +				"Failed to set option \"%s\": %s", key, e->message); +			error_free (e); +		} +		else +		{ +			struct str_vector tmp; +			str_vector_init (&tmp); +			dump_matching_options (ctx, key, &tmp); +			buffer_send_status (ctx, ctx->global_buffer, +				"Option changed: %s", tmp.vector[0]); +			str_vector_free (&tmp); +		}  		free (key);  	}  	config_item_destroy (new_);  	return true;  } -static int -str_vector_sort_cb (const void *a, const void *b) -{ -	return strcmp (*(const char **) a, *(const char **) b); -} - -static void -str_vector_sort (struct str_vector *self) -{ -	qsort (self->vector, self->len, sizeof *self->vector, str_vector_sort_cb); -} -  static bool  handle_command_set (struct app_context *ctx, char *arguments)  { -	struct str_vector all; -	str_vector_init (&all); -	config_dump (ctx->config.root, &all); -	str_vector_sort (&all); -  	char *option = "*";  	if (*arguments)  		option = cut_word (&arguments); -	// Filter out results by wildcard matching -	for (size_t i = 0; i < all.len; i++) -	{ -		char *key = xstrndup (all.vector[i], strcspn (all.vector[i], " ")); -		if (fnmatch (option, key, 0)) -			str_vector_remove (&all, i--); -		free (key); -	} +	struct str_vector all; +	str_vector_init (&all); +	dump_matching_options (ctx, option, &all);  	bool result = true;  	if (!all.len)  | 
