Browse Source

Use GLib-style error reporting.

Report runtime errors through GLib's GError framework. Also make
sure to free resources before exiting.
master
Damien Goutte-Gattat 2 years ago
parent
commit
92c5744b64
  1. 3
      src/Makefile.am
  2. 38
      src/error.c
  3. 51
      src/error.h
  4. 6
      src/errors.h
  5. 47
      src/gpgutil.c
  6. 13
      src/gpgutil.h
  7. 68
      src/yki.c

3
src/Makefile.am

@ -1,6 +1,7 @@
bin_PROGRAMS = yki
yki_SOURCES = yki.c gpgutil.c gpgutil.h yki-encrypt.ui resources.xml
yki_SOURCES = yki.c gpgutil.c gpgutil.h error.c error.h errors.h \
yki-encrypt.ui resources.xml
nodist_yki_SOURCES = resources.c

38
src/error.c

@ -0,0 +1,38 @@
/*
* Yorkie - A task-oriented GnuPG frontend
* Copyright (C) 2020 Damien Goutte-Gattat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "error.h"
G_DEFINE_QUARK(YKI_ERROR, yki_error)
const char *
yki_error_msg(yki_error_t error)
{
static const char *msgs[] = {
#define DEFINE_YKI_ERROR(code, name, msg) msg,
#include "errors.h"
#undef DEFINE_YKI_ERROR
NULL
};
return msgs[error];
}

51
src/error.h

@ -0,0 +1,51 @@
/*
* Yorkie - A task-oriented GnuPG frontend
* Copyright (C) 2020 Damien Goutte-Gattat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ICP20200503_ERROR_H
#define ICP20200503_ERROR_H
#include <glib.h>
#define YKI_ERROR yki_error_quark()
typedef enum {
#define DEFINE_YKI_ERROR(code, name, msg) \
YKI_ERROR_##name = code,
#include "errors.h"
#undef DEFINE_YKI_ERROR
} yki_error_t;
#define yki_error(err, code, ...) g_set_error((err), YKI_ERROR, (code), __VA_ARGS__)
#define yki_error_gpgme(err, code, gerr) g_set_error((err), YKI_ERROR, (code), gpgme_strerror(gerr))
#ifdef __cpluscplus
extern "C" {
#endif
GQuark
yki_error_quark(void);
const char *
yki_error_msg(yki_error_t);
#ifdef __cplusplus
}
#endif
#endif /* !ICP20200503_ERROR_H */

6
src/errors.h

@ -0,0 +1,6 @@
DEFINE_YKI_ERROR(0, NO_ERROR, "Success")
DEFINE_YKI_ERROR(1, GPGME_INTERNAL, "Internal GpgME error")
DEFINE_YKI_ERROR(2, GPGME_OPEN, "Cannot open GpgME data buffer")
DEFINE_YKI_ERROR(3, GPGME_CLOSE, "Cannot close GpgME data buffer")
DEFINE_YKI_ERROR(4, GPGME_CRYPTO, "Cannot perform cryptographic operation")
DEFINE_YKI_ERROR(5, GPGME_KEYLIST, "Cannot list keys")

47
src/gpgutil.c

@ -26,22 +26,35 @@
#include <errno.h>
#include <locale.h>
#include "error.h"
gpgme_error_t
gpgutil_initialize(gpgme_ctx_t *ctx)
gpgme_ctx_t
gpgutil_initialize(GError **error)
{
gpgme_ctx_t ctx = NULL;
gpgme_error_t gerr;
gpgme_check_version(NULL);
gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
gpgme_set_locale(NULL, LC_MESSAGES, setlocale(LC_MESSAGES, NULL));
return gpgme_new(ctx);
if ( (gerr = gpgme_new(&ctx)) )
yki_error_gpgme(error, YKI_ERROR_GPGME_INTERNAL, gerr);
return ctx;
}
gpgme_error_t
gpgutil_open_file(const char *name, const char *mode, gpgutil_file_t *file)
int
gpgutil_open_file(const char *name,
const char *mode,
gpgutil_file_t *file,
GError **error)
{
gpgme_error_t gerr;
g_assert(name && mode && file);
gerr = 0;
file->buffer = NULL;
file->file = NULL;
@ -56,32 +69,40 @@ gpgutil_open_file(const char *name, const char *mode, gpgutil_file_t *file)
gerr = gpgme_data_set_file_name(file->buffer, name);
if ( gerr ) {
if ( file->buffer ) {
if ( file->buffer) {
gpgme_data_release(file->buffer);
file->buffer = NULL;
}
if ( file->file ) {
fclose(file->file);
file->file = NULL;
}
yki_error_gpgme(error, YKI_ERROR_GPGME_OPEN, gerr);
}
return gerr ? gerr : gpgme_error(GPG_ERR_NO_ERROR);
return gpgme_err_code(gerr);
}
gpgme_error_t
gpgutil_close_file(gpgutil_file_t *file)
int
gpgutil_close_file(gpgutil_file_t *file, GError **error)
{
int ret = GPG_ERR_NO_ERROR;
gpgme_error_t gerr = 0;
g_assert(file);
if ( file->buffer ) {
gpgme_data_release(file->buffer);
file->buffer = NULL;
if ( fclose(file->file) )
return gpgme_error_from_errno(errno);
file->buffer = NULL;
gerr = gpgme_error_from_errno(errno);
file->file = NULL;
}
return gpgme_error(GPG_ERR_NO_ERROR);
if ( gerr )
yki_error_gpgme(error, YKI_ERROR_GPGME_CLOSE, gerr);
return gpgme_err_code(gerr);
}

13
src/gpgutil.h

@ -19,6 +19,7 @@
#ifndef ICP20200502_GPGUTIL_H
#define ICP20200502_GPGUTIL_H
#include <glib.h>
#include <gpgme.h>
typedef struct {
@ -30,14 +31,14 @@ typedef struct {
extern "C" {
#endif
gpgme_error_t
gpgutil_initialize(gpgme_ctx_t *);
gpgme_ctx_t
gpgutil_initialize(GError **);
gpgme_error_t
gpgutil_open_file(const char *, const char *, gpgutil_file_t *);
int
gpgutil_open_file(const char *, const char *, gpgutil_file_t *, GError **);
gpgme_error_t
gpgutil_close_file(gpgutil_file_t *);
int
gpgutil_close_file(gpgutil_file_t *, GError **);
#ifdef __cplusplus
}

68
src/yki.c

@ -27,6 +27,7 @@
#include <glib.h>
#include <gtk/gtk.h>
#include "error.h"
#include "gpgutil.h"
typedef struct {
@ -41,8 +42,8 @@ typedef struct {
} yorkie_ctx_t;
static gpgme_error_t
populate_public_key_list(gpgme_ctx_t ctx, GtkListStore *key_list)
static int
populate_public_key_list(gpgme_ctx_t ctx, GtkListStore *key_list, GError **error)
{
GtkTreeIter iter;
gpgme_key_t key;
@ -67,7 +68,10 @@ populate_public_key_list(gpgme_ctx_t ctx, GtkListStore *key_list)
if ( gpgme_err_code(gerr) == GPG_ERR_EOF )
gerr = 0;
return gerr;
if ( gerr )
yki_error_gpgme(error, YKI_ERROR_GPGME_KEYLIST, gerr);
return gpgme_err_code(gerr);
}
static gpgme_key_t *
@ -99,6 +103,17 @@ get_selected_keys(yorkie_ctx_t *yki)
return keys;
}
static gboolean
free_key_in_list(GtkTreeModel *store, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
{
gpgme_key_t key;
gtk_tree_model_get(store, iter, 2, &key, -1);
gpgme_key_release(key);
return TRUE;
}
static gpgme_error_t
perform_operation(yorkie_ctx_t *yki, gpgme_data_t in, gpgme_data_t out)
{
@ -198,28 +213,31 @@ create_encrypt_dialog(yorkie_ctx_t *yki)
return GTK_DIALOG(gtk_builder_get_object(builder, "dlgEncrypt"));
}
static gpgme_error_t
perform_operation_on_file(yorkie_ctx_t *yki, const char *filename)
static int
perform_operation_on_file(yorkie_ctx_t *yki, const char *filename, GError **error)
{
gpgutil_file_t in, out;
gpgme_error_t gerr;
gchar *outname;
int ret;
gerr = gpgutil_open_file(filename, "r", &in);
ret = gpgutil_open_file(filename, "r", &in, error);
if ( ! gerr ) {
if ( ! ret ) {
outname = g_strdup_printf("%s.gpg", filename);
gerr = gpgutil_open_file(outname, "w", &out);
ret = gpgutil_open_file(outname, "w", &out, error);
g_free(outname);
}
if ( ! gerr )
gerr = perform_operation(yki, in.buffer, out.buffer);
if ( ! ret ) {
gpgme_error_t gerr = perform_operation(yki, in.buffer, out.buffer);
if ( (ret = gpgme_err_code(gerr)) )
yki_error_gpgme(error, YKI_ERROR_GPGME_CRYPTO, gerr);
}
gpgutil_close_file(&in);
gpgutil_close_file(&out);
gpgutil_close_file(&in, NULL);
gpgutil_close_file(&out, NULL);
return gerr;
return ret;
}
@ -228,7 +246,7 @@ main(int argc, char **argv)
{
yorkie_ctx_t yki;
GtkDialog *dlg;
gpgme_error_t gerr;
GError *error = NULL;
yki.selected_keys = 0;
yki.symmetric = yki.sign = yki.detached = FALSE;
@ -239,18 +257,22 @@ main(int argc, char **argv)
dlg = create_encrypt_dialog(&yki);
if ( (gerr = gpgutil_initialize(&yki.gpgme)) )
g_error("Cannot initialize GPGME: %s", gpgme_strerror(gerr));
yki.gpgme = gpgutil_initialize(&error);
if ( ! error )
populate_public_key_list(yki.gpgme, yki.public_keys, &error);
if ( (gerr = populate_public_key_list(yki.gpgme, yki.public_keys)) )
g_error("Cannot get public keys: %s", gpgme_strerror(gerr));
if ( ! error && gtk_dialog_run(dlg) == GTK_RESPONSE_OK && can_proceed(yki) )
perform_operation_on_file(&yki, argv[1], &error);
if ( gtk_dialog_run(dlg) == GTK_RESPONSE_OK && can_proceed(yki) ) {
if ( (gerr = perform_operation_on_file(&yki, argv[1])) )
g_error("Cannot perform requested operation: %s", gpgme_strerror(gerr));
if ( error ) {
g_printerr("Error: %s: %s\n", yki_error_msg(error->code), error->message);
g_error_free(error);
}
gtk_tree_model_foreach(GTK_TREE_MODEL(yki.public_keys), free_key_in_list, NULL);
gtk_widget_destroy(GTK_WIDGET(dlg));
gpgme_release(yki.gpgme);
return 0;
return error ? EXIT_FAILURE : EXIT_SUCCESS;
}

Loading…
Cancel
Save