aboutsummaryrefslogtreecommitdiffstats
path: root/tools/gpgconf-comp.c
diff options
context:
space:
mode:
authorMarcus Brinkmann <[email protected]>2004-02-26 22:18:36 +0000
committerMarcus Brinkmann <[email protected]>2004-02-26 22:18:36 +0000
commit91a514f2a1b45fb4bd750bcd9ac44fdcf6ff78d7 (patch)
tree83172c78f781e2484a0d5e30c443ad3e42ea857b /tools/gpgconf-comp.c
parent(compare_certs): New. (diff)
downloadgnupg-91a514f2a1b45fb4bd750bcd9ac44fdcf6ff78d7.tar.gz
gnupg-91a514f2a1b45fb4bd750bcd9ac44fdcf6ff78d7.zip
2004-02-26 Marcus Brinkmann <[email protected]>
* gpgconf-comp.c (option_check_validity): Check if option is active. (change_options_file): Implement.
Diffstat (limited to 'tools/gpgconf-comp.c')
-rw-r--r--tools/gpgconf-comp.c291
1 files changed, 288 insertions, 3 deletions
diff --git a/tools/gpgconf-comp.c b/tools/gpgconf-comp.c
index e56f9c49f..bbf0649a9 100644
--- a/tools/gpgconf-comp.c
+++ b/tools/gpgconf-comp.c
@@ -1219,6 +1219,9 @@ option_check_validity (gc_option_t *option, unsigned long flags,
{
char *arg;
+ if (!option->active)
+ gc_error (1, 0, "option %s not supported by backend", option->name);
+
if (option->new_flags || option->new_value)
gc_error (1, 0, "option %s already changed", option->name);
@@ -1320,8 +1323,290 @@ change_options_file (gc_component_t component, gc_backend_t backend,
char **src_filenamep, char **dest_filenamep,
char **orig_filenamep)
{
- /* FIXME. */
- assert (!"Not implemented.");
+ static const char marker[] = "###+++--- GPGConf ---+++###";
+ /* True if we are within the marker in the config file. */
+ int in_marker = 0;
+ gc_option_t *option;
+ char *line = NULL;
+ size_t line_len;
+ ssize_t length;
+ int res;
+ int fd;
+ FILE *src_file = NULL;
+ FILE *dest_file = NULL;
+ char *src_filename;
+ char *dest_filename;
+ char *orig_filename;
+ char *arg;
+ char *cur_arg = NULL;
+
+ option = find_option (component,
+ gc_backend[backend].option_name, GC_BACKEND_ANY);
+ assert (option);
+ assert (option->active);
+ assert (gc_arg_type[option->arg_type].fallback != GC_ARG_TYPE_NONE);
+ assert (!(option->flags & GC_OPT_FLAG_ARG_OPT));
+
+ /* FIXME. Throughout the function, do better error reporting. */
+ /* Note that get_config_pathname() calls percent_deescape(), so we
+ call this before processing the arguments. */
+ dest_filename = xstrdup (get_config_pathname (component, backend));
+ src_filename = xasprintf ("%s.gpgconf.%i.new", dest_filename, getpid ());
+ orig_filename = xasprintf ("%s.gpgconf.%i.bak", dest_filename, getpid ());
+
+ arg = option->new_value;
+ if (arg)
+ {
+ char *end;
+
+ arg++;
+ end = strchr (arg, ',');
+ if (end)
+ *end = '\0';
+
+ cur_arg = percent_deescape (arg);
+ if (end)
+ {
+ *end = ',';
+ arg = end + 1;
+ }
+ else
+ arg = NULL;
+ }
+
+ res = link (dest_filename, orig_filename);
+ if (res < 0 && errno != ENOENT)
+ return -1;
+ if (res < 0)
+ {
+ xfree (orig_filename);
+ orig_filename = NULL;
+ }
+
+ /* We now initialize the return strings, so the caller can do the
+ cleanup for us. */
+ *src_filenamep = src_filename;
+ *dest_filenamep = dest_filename;
+ *orig_filenamep = orig_filename;
+
+ /* Use open() so that we can use O_EXCL. */
+ fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
+ if (fd < 0)
+ return -1;
+ src_file = fdopen (fd, "w");
+ res = errno;
+ if (!src_file)
+ {
+ errno = res;
+ return -1;
+ }
+
+ /* Only if ORIG_FILENAME is not NULL did the configuration file
+ exist already. In this case, we will copy its content into the
+ new configuration file, changing it to our liking in the
+ process. */
+ if (orig_filename)
+ {
+ dest_file = fopen (dest_filename, "r");
+ if (!dest_file)
+ goto change_file_one_err;
+
+ while ((length = getline (&line, &line_len, dest_file)) > 0)
+ {
+ int disable = 0;
+ char *start;
+
+ if (!strncmp (marker, line, sizeof (marker) - 1))
+ {
+ if (!in_marker)
+ in_marker = 1;
+ else
+ break;
+ }
+
+ start = line;
+ while (*start == ' ' || *start == '\t')
+ start++;
+ if (*start && *start != '\r' && *start != '\n' && *start != '#')
+ {
+ char *end;
+ char *endp;
+ char saved_end;
+
+ endp = start;
+ end = endp;
+
+ /* Search for the end of the line. */
+ while (*endp && *endp != '#' && *endp != '\r' && *endp != '\n')
+ {
+ endp++;
+ if (*endp && *endp != ' ' && *endp != '\t'
+ && *endp != '\r' && *endp != '\n' && *endp != '#')
+ end = endp + 1;
+ }
+ saved_end = *end;
+ *end = '\0';
+
+ if ((option->new_flags & GC_OPT_FLAG_DEFAULT)
+ || !cur_arg || strcmp (start, cur_arg))
+ disable = 1;
+ else
+ {
+ /* Find next argument. */
+ if (arg)
+ {
+ char *arg_end;
+
+ arg++;
+ arg_end = strchr (arg, ',');
+ if (arg_end)
+ *arg_end = '\0';
+
+ cur_arg = percent_deescape (arg);
+ if (arg_end)
+ {
+ *arg_end = ',';
+ arg = arg_end + 1;
+ }
+ else
+ arg = NULL;
+ }
+ else
+ cur_arg = NULL;
+ }
+
+ *end = saved_end;
+ }
+
+ if (disable)
+ {
+ if (!in_marker)
+ {
+ fprintf (src_file,
+ "# GPGConf disabled this option here at %s\n",
+ asctimestamp (gnupg_get_time ()));
+ if (ferror (src_file))
+ goto change_file_one_err;
+ fprintf (src_file, "# %s", line);
+ if (ferror (src_file))
+ goto change_file_one_err;
+ }
+ }
+ else
+ {
+ fprintf (src_file, "%s", line);
+ if (ferror (src_file))
+ goto change_file_one_err;
+ }
+ }
+ if (ferror (dest_file))
+ goto change_file_one_err;
+ }
+
+ if (!in_marker)
+ {
+ /* There was no marker. This is the first time we edit the
+ file. We add our own marker at the end of the file and
+ proceed. Note that we first write a newline, this guards us
+ against files which lack the newline at the end of the last
+ line, while it doesn't hurt us in all other cases. */
+ fprintf (src_file, "\n%s\n", marker);
+ if (ferror (src_file))
+ goto change_file_one_err;
+ }
+
+ /* At this point, we have copied everything up to the end marker
+ into the new file, except for the arguments we are going to add.
+ Now, dump the new arguments and write the end marker, possibly
+ followed by the rest of the original file. */
+ while (cur_arg)
+ {
+ fprintf (src_file, "%s\n", cur_arg);
+
+ /* Find next argument. */
+ if (arg)
+ {
+ char *end;
+
+ arg++;
+ end = strchr (arg, ',');
+ if (end)
+ *end = '\0';
+
+ cur_arg = percent_deescape (arg);
+ if (end)
+ {
+ *end = ',';
+ arg = end + 1;
+ }
+ else
+ arg = NULL;
+ }
+ else
+ cur_arg = NULL;
+ }
+
+ fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
+ if (ferror (src_file))
+ goto change_file_one_err;
+
+ if (!in_marker)
+ {
+ fprintf (src_file, "# GPGConf edited this configuration file.\n");
+ if (ferror (src_file))
+ goto change_file_one_err;
+ fprintf (src_file, "# It will disable options before this marked "
+ "block, but it will\n");
+ if (ferror (src_file))
+ goto change_file_one_err;
+ fprintf (src_file, "# never change anything below these lines.\n");
+ if (ferror (src_file))
+ goto change_file_one_err;
+ }
+ if (dest_file)
+ {
+ while ((length = getline (&line, &line_len, dest_file)) > 0)
+ {
+ fprintf (src_file, "%s", line);
+ if (ferror (src_file))
+ goto change_file_one_err;
+ }
+ if (ferror (dest_file))
+ goto change_file_one_err;
+ }
+ if (line)
+ free (line);
+ res = fclose (src_file);
+ if (res)
+ {
+ res = errno;
+ close (fd);
+ if (dest_file)
+ fclose (dest_file);
+ errno = res;
+ return -1;
+ }
+ close (fd);
+ if (dest_file)
+ {
+ res = fclose (dest_file);
+ if (res)
+ return -1;
+ }
+ return 0;
+
+ change_file_one_err:
+ if (line)
+ free (line);
+ res = errno;
+ if (src_file)
+ {
+ fclose (src_file);
+ close (fd);
+ }
+ if (dest_file)
+ fclose (dest_file);
+ errno = res;
return -1;
}
@@ -1394,7 +1679,6 @@ change_options_program (gc_component_t component, gc_backend_t backend,
{
int disable = 0;
char *start;
- char *end;
if (!strncmp (marker, line, sizeof (marker) - 1))
{
@@ -1409,6 +1693,7 @@ change_options_program (gc_component_t component, gc_backend_t backend,
start++;
if (*start && *start != '\r' && *start != '\n' && *start != '#')
{
+ char *end;
char saved_end;
end = start;