Merge branch 'jl/submodule-mv'
[gitweb.git] / contrib / credential / gnome-keyring / git-credential-gnome-keyring.c
index 273c43bcc42b2b1532e96bc0a8d272e8f33bd0a9..635c96bc563a21e98df181e3a179e50e0eaeadaa 100644 (file)
 
 #include <stdio.h>
 #include <string.h>
-#include <stdarg.h>
 #include <stdlib.h>
 #include <glib.h>
 #include <gnome-keyring.h>
+
+#ifdef GNOME_KEYRING_DEFAULT
+
+   /* Modern gnome-keyring */
+
 #include <gnome-keyring-memory.h>
 
+#else
+
+   /*
+    * Support ancient gnome-keyring, circ. RHEL 5.X.
+    * GNOME_KEYRING_DEFAULT seems to have been introduced with Gnome 2.22,
+    * and the other features roughly around Gnome 2.20, 6 months before.
+    * Ubuntu 8.04 used Gnome 2.22 (I think).  Not sure any distro used 2.20.
+    * So the existence/non-existence of GNOME_KEYRING_DEFAULT seems like
+    * a decent thing to use as an indicator.
+    */
+
+#define GNOME_KEYRING_DEFAULT NULL
+
+/*
+ * ancient gnome-keyring returns DENIED when an entry is not found.
+ * Setting NO_MATCH to DENIED will prevent us from reporting DENIED
+ * errors during get and erase operations, but we will still report
+ * DENIED errors during a store.
+ */
+#define GNOME_KEYRING_RESULT_NO_MATCH GNOME_KEYRING_RESULT_DENIED
+
+#define gnome_keyring_memory_alloc g_malloc
+#define gnome_keyring_memory_free gnome_keyring_free_password
+#define gnome_keyring_memory_strdup g_strdup
+
+static const char* gnome_keyring_result_to_message(GnomeKeyringResult result)
+{
+       switch (result) {
+       case GNOME_KEYRING_RESULT_OK:
+               return "OK";
+       case GNOME_KEYRING_RESULT_DENIED:
+               return "Denied";
+       case GNOME_KEYRING_RESULT_NO_KEYRING_DAEMON:
+               return "No Keyring Daemon";
+       case GNOME_KEYRING_RESULT_ALREADY_UNLOCKED:
+               return "Already UnLocked";
+       case GNOME_KEYRING_RESULT_NO_SUCH_KEYRING:
+               return "No Such Keyring";
+       case GNOME_KEYRING_RESULT_BAD_ARGUMENTS:
+               return "Bad Arguments";
+       case GNOME_KEYRING_RESULT_IO_ERROR:
+               return "IO Error";
+       case GNOME_KEYRING_RESULT_CANCELLED:
+               return "Cancelled";
+       case GNOME_KEYRING_RESULT_ALREADY_EXISTS:
+               return "Already Exists";
+       default:
+               return "Unknown Error";
+       }
+}
+
+/*
+ * Support really ancient gnome-keyring, circ. RHEL 4.X.
+ * Just a guess for the Glib version.  Glib 2.8 was roughly Gnome 2.12 ?
+ * Which was released with gnome-keyring 0.4.3 ??
+ */
+#if GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 8
+
+static void gnome_keyring_done_cb(GnomeKeyringResult result, gpointer user_data)
+{
+       gpointer *data = (gpointer*) user_data;
+       int *done = (int*) data[0];
+       GnomeKeyringResult *r = (GnomeKeyringResult*) data[1];
+
+       *r = result;
+       *done = 1;
+}
+
+static void wait_for_request_completion(int *done)
+{
+       GMainContext *mc = g_main_context_default();
+       while (!*done)
+               g_main_context_iteration(mc, TRUE);
+}
+
+static GnomeKeyringResult gnome_keyring_item_delete_sync(const char *keyring, guint32 id)
+{
+       int done = 0;
+       GnomeKeyringResult result;
+       gpointer data[] = { &done, &result };
+
+       gnome_keyring_item_delete(keyring, id, gnome_keyring_done_cb, data,
+               NULL);
+
+       wait_for_request_completion(&done);
+
+       return result;
+}
+
+#endif
+#endif
+
 /*
  * This credential struct and API is simplified from git's credential.{h,c}
  */
@@ -58,30 +154,6 @@ struct credential_operation
 #define CREDENTIAL_OP_END \
   { NULL,NULL }
 
-/* ---------------- common helper functions ----------------- */
-
-static inline void warning(const char *fmt, ...)
-{
-       va_list ap;
-
-       va_start(ap, fmt);
-       fprintf(stderr, "warning: ");
-       vfprintf(stderr, fmt, ap);
-       fprintf(stderr, "\n" );
-       va_end(ap);
-}
-
-static inline void error(const char *fmt, ...)
-{
-       va_list ap;
-
-       va_start(ap, fmt);
-       fprintf(stderr, "error: ");
-       vfprintf(stderr, fmt, ap);
-       fprintf(stderr, "\n" );
-       va_end(ap);
-}
-
 /* ----------------- GNOME Keyring functions ----------------- */
 
 /* create a special keyring option string, if path is given */
@@ -127,7 +199,7 @@ static int keyring_get(struct credential *c)
                return EXIT_SUCCESS;
 
        if (result != GNOME_KEYRING_RESULT_OK) {
-               error("%s",gnome_keyring_result_to_message(result));
+               g_critical("%s", gnome_keyring_result_to_message(result));
                return EXIT_FAILURE;
        }
 
@@ -150,6 +222,7 @@ static int keyring_store(struct credential *c)
 {
        guint32 item_id;
        char  *object = NULL;
+       GnomeKeyringResult result;
 
        /*
         * Sanity check that what we are storing is actually sensible.
@@ -164,7 +237,7 @@ static int keyring_store(struct credential *c)
 
        object = keyring_object(c);
 
-       gnome_keyring_set_network_password_sync(
+       result = gnome_keyring_set_network_password_sync(
                                GNOME_KEYRING_DEFAULT,
                                c->username,
                                NULL /* domain */,
@@ -177,6 +250,13 @@ static int keyring_store(struct credential *c)
                                &item_id);
 
        g_free(object);
+
+       if (result != GNOME_KEYRING_RESULT_OK &&
+           result != GNOME_KEYRING_RESULT_CANCELLED) {
+               g_critical("%s", gnome_keyring_result_to_message(result));
+               return EXIT_FAILURE;
+       }
+
        return EXIT_SUCCESS;
 }
 
@@ -220,7 +300,7 @@ static int keyring_erase(struct credential *c)
 
        if (result != GNOME_KEYRING_RESULT_OK)
        {
-               error("%s",gnome_keyring_result_to_message(result));
+               g_critical("%s", gnome_keyring_result_to_message(result));
                return EXIT_FAILURE;
        }
 
@@ -234,7 +314,7 @@ static int keyring_erase(struct credential *c)
 
        if (result != GNOME_KEYRING_RESULT_OK)
        {
-               error("%s",gnome_keyring_result_to_message(result));
+               g_critical("%s", gnome_keyring_result_to_message(result));
                return EXIT_FAILURE;
        }
 
@@ -292,7 +372,7 @@ static int credential_read(struct credential *c)
 
                value = strchr(buf,'=');
                if (!value) {
-                       warning("invalid credential line: %s", key);
+                       g_warning("invalid credential line: %s", key);
                        gnome_keyring_memory_free(buf);
                        return -1;
                }