#include "util.h"
#include "i18n.h"
#include "exechelp.h"
+#include "sysutils.h"
#include "gc-opt-flags.h"
#include "gpgconf.h"
(GC_OPT_FLAG_ARG_OPT|GC_OPT_FLAG_NO_CHANGE), GC_LEVEL_INVISIBLE,
NULL, NULL,
GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
+ { "trust-model",
+ GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
+ NULL, NULL,
+ GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
{ "Debug",
{ "auto-key-locate", GC_OPT_FLAG_NONE, GC_LEVEL_ADVANCED,
"gnupg", N_("|MECHANISMS|use MECHANISMS to locate keys by mail address"),
GC_ARG_TYPE_STRING, GC_BACKEND_GPG },
+ { "auto-key-retrieve", GC_OPT_FLAG_NONE, GC_LEVEL_INVISIBLE,
+ NULL, NULL, GC_ARG_TYPE_NONE, GC_BACKEND_GPG },
GC_OPTION_NULL
config = es_fopen (config_filename, "r");
if (!config)
- gc_error (0, errno, "warning: can not open config file %s",
- config_filename);
+ {
+ if (errno != ENOENT)
+ gc_error (0, errno, "warning: can not open config file %s",
+ config_filename);
+ }
else
{
while ((length = es_read_line (config, &line, &line_len, NULL)) > 0)
gc_option_t *list_option;
gc_option_t *config_option;
char *list_filename;
- FILE *list_file;
+ gpgrt_stream_t list_file;
char *line = NULL;
size_t line_len = 0;
ssize_t length;
assert (!list_option->active);
list_filename = get_config_filename (component, backend);
- list_file = fopen (list_filename, "r");
+ list_file = gpgrt_fopen (list_filename, "r");
if (!list_file)
gc_error (0, errno, "warning: can not open list file %s", list_filename);
else
{
- while ((length = read_line (list_file, &line, &line_len, NULL)) > 0)
+ while ((length = gpgrt_read_line (list_file, &line, &line_len, NULL)) > 0)
{
char *start;
char *end;
else
list = xasprintf ("\"%s", gc_percent_escape (start));
}
- if (length < 0 || ferror (list_file))
+ if (length < 0 || gpgrt_ferror (list_file))
gc_error (1, errno, "can not read list file %s", list_filename);
}
if (config_option->flags & GC_OPT_FLAG_NO_CHANGE)
list_option->flags |= GC_OPT_FLAG_NO_CHANGE;
- if (list_file && fclose (list_file))
+ if (list_file && gpgrt_fclose (list_file))
gc_error (1, errno, "error closing %s", list_filename);
xfree (line);
}
while (arg && *arg);
}
-
#ifdef HAVE_W32_SYSTEM
int
copy_file (const char *src_name, const char *dst_name)
#define BUF_LEN 4096
char buffer[BUF_LEN];
int len;
- FILE *src;
- FILE *dst;
+ gpgrt_stream_t src;
+ gpgrt_stream_t dst;
- src = fopen (src_name, "r");
+ src = gpgrt_fopen (src_name, "r");
if (src == NULL)
return -1;
- dst = fopen (dst_name, "w");
+ dst = gpgrt_fopen (dst_name, "w");
if (dst == NULL)
{
int saved_err = errno;
- fclose (src);
+ gpgrt_fclose (src);
gpg_err_set_errno (saved_err);
return -1;
}
{
int written;
- len = fread (buffer, 1, BUF_LEN, src);
+ len = gpgrt_fread (buffer, 1, BUF_LEN, src);
if (len == 0)
break;
- written = fwrite (buffer, 1, len, dst);
+ written = gpgrt_fwrite (buffer, 1, len, dst);
if (written != len)
break;
}
- while (!feof (src) && !ferror (src) && !ferror (dst));
+ while (! gpgrt_feof (src) && ! gpgrt_ferror (src) && ! gpgrt_ferror (dst));
- if (ferror (src) || ferror (dst) || !feof (src))
+ if (gpgrt_ferror (src) || gpgrt_ferror (dst) || ! gpgrt_feof (src))
{
int saved_errno = errno;
- fclose (src);
- fclose (dst);
+ gpgrt_fclose (src);
+ gpgrt_fclose (dst);
unlink (dst_name);
gpg_err_set_errno (saved_errno);
return -1;
}
- if (fclose (dst))
+ if (gpgrt_fclose (dst))
gc_error (1, errno, "error closing %s", dst_name);
- if (fclose (src))
+ if (gpgrt_fclose (src))
gc_error (1, errno, "error closing %s", src_name);
return 0;
/* Create and verify the new configuration file for the specified
- backend and component. Returns 0 on success and -1 on error. */
+ * backend and component. Returns 0 on success and -1 on error. This
+ * function may store pointers to malloced strings in SRC_FILENAMEP,
+ * DEST_FILENAMEP, and ORIG_FILENAMEP. Those must be freed by the
+ * caller. The strings refer to three versions of the configuration
+ * file:
+ *
+ * SRC_FILENAME: The updated configuration is written to this file.
+ * DEST_FILENAME: Name of the configuration file read by the
+ * component.
+ * ORIG_FILENAME: A backup of the previous configuration file.
+ *
+ * To apply the configuration change, rename SRC_FILENAME to
+ * DEST_FILENAME. To revert to the previous configuration, rename
+ * ORIG_FILENAME to DEST_FILENAME. */
static int
change_options_file (gc_component_t component, gc_backend_t backend,
char **src_filenamep, char **dest_filenamep,
ssize_t length;
int res;
int fd;
- FILE *src_file = NULL;
- FILE *dest_file = NULL;
+ gpgrt_stream_t src_file = NULL;
+ gpgrt_stream_t dest_file = NULL;
char *src_filename;
char *dest_filename;
char *orig_filename;
if (res < 0 && errno != ENOENT)
{
xfree (dest_filename);
+ xfree (src_filename);
+ xfree (orig_filename);
return -1;
}
if (res < 0)
fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
if (fd < 0)
return -1;
- src_file = fdopen (fd, "w");
+ src_file = gpgrt_fdopen (fd, "w");
res = errno;
if (!src_file)
{
process. */
if (orig_filename)
{
- dest_file = fopen (dest_filename, "r");
+ dest_file = gpgrt_fopen (dest_filename, "r");
if (!dest_file)
goto change_file_one_err;
- while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
+ while ((length = gpgrt_read_line (dest_file, &line, &line_len, NULL)) > 0)
{
int disable = 0;
char *start;
{
if (!in_marker)
{
- fprintf (src_file,
+ gpgrt_fprintf (src_file,
"# %s disabled this option here at %s\n",
GPGCONF_DISP_NAME, asctimestamp (gnupg_get_time ()));
- if (ferror (src_file))
+ if (gpgrt_ferror (src_file))
goto change_file_one_err;
- fprintf (src_file, "# %s", line);
- if (ferror (src_file))
+ gpgrt_fprintf (src_file, "# %s", line);
+ if (gpgrt_ferror (src_file))
goto change_file_one_err;
}
}
else
{
- fprintf (src_file, "%s", line);
- if (ferror (src_file))
+ gpgrt_fprintf (src_file, "%s", line);
+ if (gpgrt_ferror (src_file))
goto change_file_one_err;
}
}
- if (length < 0 || ferror (dest_file))
+ if (length < 0 || gpgrt_ferror (dest_file))
goto change_file_one_err;
}
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))
+ gpgrt_fprintf (src_file, "\n%s\n", marker);
+ if (gpgrt_ferror (src_file))
goto change_file_one_err;
}
followed by the rest of the original file. */
while (cur_arg)
{
- fprintf (src_file, "%s\n", cur_arg);
+ gpgrt_fprintf (src_file, "%s\n", cur_arg);
/* Find next argument. */
if (arg)
cur_arg = NULL;
}
- fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
- if (ferror (src_file))
+ gpgrt_fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
+ if (gpgrt_ferror (src_file))
goto change_file_one_err;
if (!in_marker)
{
- fprintf (src_file, "# %s edited this configuration file.\n",
+ gpgrt_fprintf (src_file, "# %s edited this configuration file.\n",
GPGCONF_DISP_NAME);
- if (ferror (src_file))
+ if (gpgrt_ferror (src_file))
goto change_file_one_err;
- fprintf (src_file, "# It will disable options before this marked "
+ gpgrt_fprintf (src_file, "# It will disable options before this marked "
"block, but it will\n");
- if (ferror (src_file))
+ if (gpgrt_ferror (src_file))
goto change_file_one_err;
- fprintf (src_file, "# never change anything below these lines.\n");
- if (ferror (src_file))
+ gpgrt_fprintf (src_file, "# never change anything below these lines.\n");
+ if (gpgrt_ferror (src_file))
goto change_file_one_err;
}
if (dest_file)
{
- while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
+ while ((length = gpgrt_read_line (dest_file, &line, &line_len, NULL)) > 0)
{
- fprintf (src_file, "%s", line);
- if (ferror (src_file))
+ gpgrt_fprintf (src_file, "%s", line);
+ if (gpgrt_ferror (src_file))
goto change_file_one_err;
}
- if (length < 0 || ferror (dest_file))
+ if (length < 0 || gpgrt_ferror (dest_file))
goto change_file_one_err;
}
xfree (line);
line = NULL;
- res = fclose (src_file);
+ res = gpgrt_fclose (src_file);
if (res)
{
res = errno;
close (fd);
if (dest_file)
- fclose (dest_file);
+ gpgrt_fclose (dest_file);
gpg_err_set_errno (res);
return -1;
}
close (fd);
if (dest_file)
{
- res = fclose (dest_file);
+ res = gpgrt_fclose (dest_file);
if (res)
return -1;
}
res = errno;
if (src_file)
{
- fclose (src_file);
+ gpgrt_fclose (src_file);
close (fd);
}
if (dest_file)
- fclose (dest_file);
+ gpgrt_fclose (dest_file);
gpg_err_set_errno (res);
return -1;
}
/* Create and verify the new configuration file for the specified
* backend and component. Returns 0 on success and -1 on error. If
- * VERBATIM is set the profile mode is used. */
+ * VERBATIM is set the profile mode is used. This function may store
+ * pointers to malloced strings in SRC_FILENAMEP, DEST_FILENAMEP, and
+ * ORIG_FILENAMEP. Those must be freed by the caller. The strings
+ * refer to three versions of the configuration file:
+ *
+ * SRC_FILENAME: The updated configuration is written to this file.
+ * DEST_FILENAME: Name of the configuration file read by the
+ * component.
+ * ORIG_FILENAME: A backup of the previous configuration file.
+ *
+ * To apply the configuration change, rename SRC_FILENAME to
+ * DEST_FILENAME. To revert to the previous configuration, rename
+ * ORIG_FILENAME to DEST_FILENAME. */
static int
change_options_program (gc_component_t component, gc_backend_t backend,
char **src_filenamep, char **dest_filenamep,
ssize_t length;
int res;
int fd;
- FILE *src_file = NULL;
- FILE *dest_file = NULL;
+ gpgrt_stream_t src_file = NULL;
+ gpgrt_stream_t dest_file = NULL;
char *src_filename;
char *dest_filename;
char *orig_filename;
fd = open (src_filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
if (fd < 0)
return -1;
- src_file = fdopen (fd, "w");
+ src_file = gpgrt_fdopen (fd, "w");
res = errno;
if (!src_file)
{
process. */
if (orig_filename)
{
- dest_file = fopen (dest_filename, "r");
+ dest_file = gpgrt_fopen (dest_filename, "r");
if (!dest_file)
goto change_one_err;
- while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
+ while ((length = gpgrt_read_line (dest_file, &line, &line_len, NULL)) > 0)
{
int disable = 0;
char *start;
{
if (!in_marker)
{
- fprintf (src_file,
+ gpgrt_fprintf (src_file,
"# %s disabled this option here at %s\n",
GPGCONF_DISP_NAME, asctimestamp (gnupg_get_time ()));
- if (ferror (src_file))
+ if (gpgrt_ferror (src_file))
goto change_one_err;
- fprintf (src_file, "# %s", line);
- if (ferror (src_file))
+ gpgrt_fprintf (src_file, "# %s", line);
+ if (gpgrt_ferror (src_file))
goto change_one_err;
}
}
else
{
- fprintf (src_file, "%s", line);
- if (ferror (src_file))
+ gpgrt_fprintf (src_file, "%s", line);
+ if (gpgrt_ferror (src_file))
goto change_one_err;
}
}
- if (length < 0 || ferror (dest_file))
+ if (length < 0 || gpgrt_ferror (dest_file))
goto change_one_err;
}
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))
+ gpgrt_fprintf (src_file, "\n%s\n", marker);
+ if (gpgrt_ferror (src_file))
goto change_one_err;
}
/* At this point, we have copied everything up to the end marker
/* We have to turn on UTF8 strings for GnuPG. */
if (backend == GC_BACKEND_GPG && ! utf8strings_seen)
- fprintf (src_file, "utf8-strings\n");
+ gpgrt_fprintf (src_file, "utf8-strings\n");
option = gc_component[component].options;
while (option->name)
{
if (*arg == '\0' || *arg == ',')
{
- fprintf (src_file, "%s\n", option->name);
- if (ferror (src_file))
+ gpgrt_fprintf (src_file, "%s\n", option->name);
+ if (gpgrt_ferror (src_file))
goto change_one_err;
}
else if (gc_arg_type[option->arg_type].fallback
== GC_ARG_TYPE_NONE)
{
assert (*arg == '1');
- fprintf (src_file, "%s\n", option->name);
- if (ferror (src_file))
+ gpgrt_fprintf (src_file, "%s\n", option->name);
+ if (gpgrt_ferror (src_file))
goto change_one_err;
arg++;
else
end = NULL;
- fprintf (src_file, "%s %s\n", option->name,
+ gpgrt_fprintf (src_file, "%s %s\n", option->name,
verbatim? arg : percent_deescape (arg));
- if (ferror (src_file))
+ if (gpgrt_ferror (src_file))
goto change_one_err;
if (end)
if (end)
*end = '\0';
- fprintf (src_file, "%s %s\n", option->name, arg);
- if (ferror (src_file))
+ gpgrt_fprintf (src_file, "%s %s\n", option->name, arg);
+ if (gpgrt_ferror (src_file))
goto change_one_err;
if (end)
option++;
}
- fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
- if (ferror (src_file))
+ gpgrt_fprintf (src_file, "%s %s\n", marker, asctimestamp (gnupg_get_time ()));
+ if (gpgrt_ferror (src_file))
goto change_one_err;
if (!in_marker)
{
- fprintf (src_file, "# %s edited this configuration file.\n",
+ gpgrt_fprintf (src_file, "# %s edited this configuration file.\n",
GPGCONF_DISP_NAME);
- if (ferror (src_file))
+ if (gpgrt_ferror (src_file))
goto change_one_err;
- fprintf (src_file, "# It will disable options before this marked "
+ gpgrt_fprintf (src_file, "# It will disable options before this marked "
"block, but it will\n");
- if (ferror (src_file))
+ if (gpgrt_ferror (src_file))
goto change_one_err;
- fprintf (src_file, "# never change anything below these lines.\n");
- if (ferror (src_file))
+ gpgrt_fprintf (src_file, "# never change anything below these lines.\n");
+ if (gpgrt_ferror (src_file))
goto change_one_err;
}
if (dest_file)
{
- while ((length = read_line (dest_file, &line, &line_len, NULL)) > 0)
+ while ((length = gpgrt_read_line (dest_file, &line, &line_len, NULL)) > 0)
{
- fprintf (src_file, "%s", line);
- if (ferror (src_file))
+ gpgrt_fprintf (src_file, "%s", line);
+ if (gpgrt_ferror (src_file))
goto change_one_err;
}
- if (length < 0 || ferror (dest_file))
+ if (length < 0 || gpgrt_ferror (dest_file))
goto change_one_err;
}
xfree (line);
line = NULL;
- res = fclose (src_file);
+ res = gpgrt_fclose (src_file);
if (res)
{
res = errno;
close (fd);
if (dest_file)
- fclose (dest_file);
+ gpgrt_fclose (dest_file);
gpg_err_set_errno (res);
return -1;
}
close (fd);
if (dest_file)
{
- res = fclose (dest_file);
+ res = gpgrt_fclose (dest_file);
if (res)
return -1;
}
res = errno;
if (src_file)
{
- fclose (src_file);
+ gpgrt_fclose (src_file);
close (fd);
}
if (dest_file)
- fclose (dest_file);
+ gpgrt_fclose (dest_file);
gpg_err_set_errno (res);
return -1;
}
int verbatim)
{
int err = 0;
+ int block = 0;
int runtime[GC_BACKEND_NR];
char *src_filename[GC_BACKEND_NR];
char *dest_filename[GC_BACKEND_NR];
change_one_value (option, runtime, flags, new_value, 0);
}
+ if (length < 0 || gpgrt_ferror (in))
+ gc_error (1, errno, "error reading stream 'in'");
}
/* Now that we have collected and locally verified the changes,
option++;
}
+ /* We are trying to atomically commit all changes. Unfortunately,
+ we cannot rely on gnupg_rename_file to manage the signals for us,
+ doing so would require us to pass NULL as BLOCK to any subsequent
+ call to it. Instead, we just manage the signal handling
+ manually. */
+ block = 1;
+ gnupg_block_all_signals ();
+
if (! err && ! opt.dry_run)
{
int i;
assert (dest_filename[i]);
if (orig_filename[i])
- {
-#ifdef HAVE_W32_SYSTEM
- /* There is no atomic update on W32. */
- err = unlink (dest_filename[i]);
-#endif /* HAVE_W32_SYSTEM */
- if (!err)
- err = rename (src_filename[i], dest_filename[i]);
- }
+ err = gnupg_rename_file (src_filename[i], dest_filename[i], NULL);
else
{
#ifdef HAVE_W32_SYSTEM
/* We skip the unlink if we expect the file not to
be there. */
- err = rename (src_filename[i], dest_filename[i]);
+ err = gnupg_rename_file (src_filename[i], dest_filename[i], NULL);
#else /* HAVE_W32_SYSTEM */
/* This is a bit safer than rename() because we
expect DEST_FILENAME not to be there. If it
a version of the file that is even newer than the one
we just installed. */
if (orig_filename[i])
- {
-#ifdef HAVE_W32_SYSTEM
- /* There is no atomic update on W32. */
- unlink (dest_filename[i]);
-#endif /* HAVE_W32_SYSTEM */
- rename (orig_filename[i], dest_filename[i]);
- }
+ gnupg_rename_file (orig_filename[i], dest_filename[i], NULL);
else
unlink (dest_filename[i]);
}
backup_filename = xasprintf ("%s.%s.bak",
dest_filename[backend], GPGCONF_NAME);
-
-#ifdef HAVE_W32_SYSTEM
- /* There is no atomic update on W32. */
- unlink (backup_filename);
-#endif /* HAVE_W32_SYSTEM */
- rename (orig_filename[backend], backup_filename);
+ gnupg_rename_file (orig_filename[backend], backup_filename, NULL);
xfree (backup_filename);
}
leave:
+ if (block)
+ gnupg_unblock_all_signals ();
xfree (line);
for (backend = 0; backend < GC_BACKEND_NR; backend++)
{
char *line = NULL;
size_t line_len = 0;
ssize_t length;
- FILE *config;
+ gpgrt_stream_t config;
int lineno = 0;
int in_rule = 0;
int got_match = 0;
for (backend_id = 0; backend_id < GC_BACKEND_NR; backend_id++)
runtime[backend_id] = 0;
- config = fopen (fname, "r");
+ config = gpgrt_fopen (fname, "r");
if (!config)
{
/* Do not print an error if the file is not available, except
return result;
}
- while ((length = read_line (config, &line, &line_len, NULL)) > 0)
+ while ((length = gpgrt_read_line (config, &line, &line_len, NULL)) > 0)
{
char *key, *component, *option, *flags, *value;
char *empty;
}
}
- if (length < 0 || ferror (config))
+ if (length < 0 || gpgrt_ferror (config))
{
gc_error (0, errno, "error reading from '%s'", fname);
result = -1;
}
- if (fclose (config))
+ if (gpgrt_fclose (config))
gc_error (0, errno, "error closing '%s'", fname);
xfree (line);