[network-manager-openconnect: 6/15] shared: add shared files



commit 14ada44ef66b58ce8dbb4c3c453fecb1ac94e430
Author: Thomas Haller <thaller redhat com>
Date:   Tue Jun 14 22:39:45 2016 +0200

    shared: add shared files
    
    Add and "shared/" directory, that contains headers and source files
    that can be used by all other components of the plugin (that is,
    src/, properties/, and auth-dialog/).
    
    This includes a "nm-default.h" header, which is supposed to be included
    by (almost) every source file in the project as first. It provides
    default includes (config.h, nm-glib.h).
    
    Then there is shared/nm-utils/ directory, which contains utility
    functions in form of header-only and source files. Those functions
    are copied as-is from NetworkManager's shared/ repository and are
    supposed not to be modified locally.

 po/POTFILES.in                              |    1 +
 shared/Makefile.am                          |    5 +
 shared/README                               |    9 +
 shared/nm-default.h                         |  103 +++++++
 shared/nm-utils/nm-glib.h                   |  397 +++++++++++++++++++++++++++
 shared/nm-utils/nm-macros-internal.h        |   10 +-
 shared/nm-utils/nm-vpn-editor-plugin-call.h |    1 -
 shared/nm-utils/nm-vpn-plugin-utils.c       |  130 +++++++++
 shared/nm-utils/nm-vpn-plugin-utils.h       |   42 +++
 9 files changed, 693 insertions(+), 5 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 86a8a62..c1d06d8 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -6,4 +6,5 @@ openconnect-strings.txt
 properties/auth-helpers.c
 properties/nm-openconnect.c
 src/nm-openconnect-service.c
+shared/nm-utils/nm-vpn-plugin-utils.c
 [type: gettext/glade]properties/nm-openconnect-dialog.ui
diff --git a/shared/Makefile.am b/shared/Makefile.am
index a80fc41..d74846e 100644
--- a/shared/Makefile.am
+++ b/shared/Makefile.am
@@ -1,6 +1,11 @@
 EXTRA_DIST = \
+    README \
     nm-utils/gsystem-local-alloc.h \
+    nm-utils/nm-glib.h \
     nm-utils/nm-macros-internal.h \
     nm-utils/nm-vpn-editor-plugin-call.h \
+    nm-utils/nm-vpn-plugin-utils.c \
+    nm-utils/nm-vpn-plugin-utils.h \
+    nm-default.h \
     nm-service-defines.h \
     $(NULL)
diff --git a/shared/README b/shared/README
new file mode 100644
index 0000000..3fe41ef
--- /dev/null
+++ b/shared/README
@@ -0,0 +1,9 @@
+The files in the "shared/" directory are used by all components
+inside the VPN plugin repository (src, properties, auth-dialog).
+
+The files in shared/nm-utils are copied from NetworkManager
+repository and used as is:
+Do *not* modify these files locally so that they don't diverge
+from their original. Fix/extend them in their respective origin
+first, and re-import the files as a whole.
+
diff --git a/shared/nm-default.h b/shared/nm-default.h
new file mode 100644
index 0000000..fa15bc3
--- /dev/null
+++ b/shared/nm-default.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2015 Red Hat, Inc.
+ */
+
+#ifndef __NM_DEFAULT_H__
+#define __NM_DEFAULT_H__
+
+/* makefiles define NETWORKMANAGER_COMPILATION for compiling NetworkManager.
+ * Depending on which parts are compiled, different values are set. */
+#define NM_NETWORKMANAGER_COMPILATION_DEFAULT             0x0001
+#define NM_NETWORKMANAGER_COMPILATION_LIB_BASE            0x0002
+#define NM_NETWORKMANAGER_COMPILATION_LIB_EDITOR          0x0004
+#define NM_NETWORKMANAGER_COMPILATION_LIB                 (0x0002 | 0x0004)
+
+#ifndef NETWORKMANAGER_COMPILATION
+/* For convenience, we don't require our Makefile.am to define
+ * -DNETWORKMANAGER_COMPILATION. As we now include this internal header,
+ *  we know we do a NETWORKMANAGER_COMPILATION. */
+#define NETWORKMANAGER_COMPILATION NM_NETWORKMANAGER_COMPILATION_DEFAULT
+#endif
+
+/*****************************************************************************/
+
+#include <config.h>
+
+/* always include these headers for our internal source files. */
+
+#include "nm-utils/nm-macros-internal.h"
+#include "nm-version.h"
+#include "nm-service-defines.h"
+
+/*****************************************************************************/
+
+#if ((NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_LIB)
+
+#include <glib/gi18n-lib.h>
+
+#else
+
+#include <glib/gi18n.h>
+
+#endif /* NM_NETWORKMANAGER_COMPILATION_LIB */
+
+/*****************************************************************************/
+
+#ifdef NM_VPN_OLD
+
+#define NM_VPN_LIBNM_COMPAT
+#include <nm-connection.h>
+#include <nm-setting-connection.h>
+#include <nm-setting-8021x.h>
+#include <nm-setting-ip4-config.h>
+#include <nm-setting-vpn.h>
+#include <nm-utils.h>
+#include <nm-vpn-plugin-ui-interface.h>
+
+#define nm_simple_connection_new nm_connection_new
+#define NM_SETTING_IP_CONFIG NM_SETTING_IP4_CONFIG
+#define NM_SETTING_IP_CONFIG_METHOD NM_SETTING_IP4_CONFIG_METHOD
+#define NMSettingIPConfig NMSettingIP4Config
+
+#define NMV_EDITOR_PLUGIN_ERROR                     NM_SETTING_VPN_ERROR
+#define NMV_EDITOR_PLUGIN_ERROR_FAILED              NM_SETTING_VPN_ERROR_UNKNOWN
+#define NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY    NM_SETTING_VPN_ERROR_INVALID_PROPERTY
+#define NMV_EDITOR_PLUGIN_ERROR_MISSING_PROPERTY    NM_SETTING_VPN_ERROR_MISSING_PROPERTY
+#define NMV_EDITOR_PLUGIN_ERROR_FILE_NOT_VPN        NM_SETTING_VPN_ERROR_UNKNOWN
+#define NMV_EDITOR_PLUGIN_ERROR_FILE_NOT_READABLE   NM_SETTING_VPN_ERROR_UNKNOWN
+#define NMV_EDITOR_PLUGIN_ERROR_FILE_INVALID        NM_SETTING_VPN_ERROR_UNKNOWN
+
+#else /* !NM_VPN_OLD */
+
+#include <NetworkManager.h>
+
+#define NMV_EDITOR_PLUGIN_ERROR                     NM_CONNECTION_ERROR
+#define NMV_EDITOR_PLUGIN_ERROR_FAILED              NM_CONNECTION_ERROR_FAILED
+#define NMV_EDITOR_PLUGIN_ERROR_INVALID_PROPERTY    NM_CONNECTION_ERROR_INVALID_PROPERTY
+#define NMV_EDITOR_PLUGIN_ERROR_MISSING_PROPERTY    NM_CONNECTION_ERROR_MISSING_PROPERTY
+#define NMV_EDITOR_PLUGIN_ERROR_FILE_NOT_VPN        NM_CONNECTION_ERROR_FAILED
+#define NMV_EDITOR_PLUGIN_ERROR_FILE_NOT_READABLE   NM_CONNECTION_ERROR_FAILED
+#define NMV_EDITOR_PLUGIN_ERROR_FILE_INVALID        NM_CONNECTION_ERROR_FAILED
+
+#endif /* NM_VPN_OLD */
+
+/*****************************************************************************/
+
+#endif /* __NM_DEFAULT_H__ */
diff --git a/shared/nm-utils/nm-glib.h b/shared/nm-utils/nm-glib.h
new file mode 100644
index 0000000..46a8bb2
--- /dev/null
+++ b/shared/nm-utils/nm-glib.h
@@ -0,0 +1,397 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * 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 2 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2008 - 2011 Red Hat, Inc.
+ */
+
+#ifndef __NM_GLIB_H__
+#define __NM_GLIB_H__
+
+
+#include <gio/gio.h>
+#include <string.h>
+
+#include "gsystem-local-alloc.h"
+
+#ifdef __clang__
+
+#undef G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+#undef G_GNUC_END_IGNORE_DEPRECATIONS
+
+#define G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+    _Pragma("clang diagnostic push") \
+    _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
+
+#define G_GNUC_END_IGNORE_DEPRECATIONS \
+    _Pragma("clang diagnostic pop")
+
+#endif
+
+static inline void
+__g_type_ensure (GType type)
+{
+#if !GLIB_CHECK_VERSION(2,34,0)
+       if (G_UNLIKELY (type == (GType)-1))
+               g_error ("can't happen");
+#else
+       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
+       g_type_ensure (type);
+       G_GNUC_END_IGNORE_DEPRECATIONS;
+#endif
+}
+#define g_type_ensure __g_type_ensure
+
+#if !GLIB_CHECK_VERSION(2,34,0)
+
+#define g_clear_pointer(pp, destroy) \
+    G_STMT_START {                                                                 \
+        G_STATIC_ASSERT (sizeof *(pp) == sizeof (gpointer));                       \
+        /* Only one access, please */                                              \
+        gpointer *_pp = (gpointer *) (pp);                                         \
+        gpointer _p;                                                               \
+        /* This assignment is needed to avoid a gcc warning */                     \
+        GDestroyNotify _destroy = (GDestroyNotify) (destroy);                      \
+                                                                                   \
+        _p = *_pp;                                                                 \
+        if (_p)                                                                    \
+        {                                                                          \
+            *_pp = NULL;                                                           \
+            _destroy (_p);                                                         \
+        }                                                                          \
+    } G_STMT_END
+
+/* These are used to clean up the output of test programs; we can just let
+ * them no-op in older glib.
+ */
+#define g_test_expect_message(log_domain, log_level, pattern)
+#define g_test_assert_expected_messages()
+
+#else
+
+/* We build with -DGLIB_MAX_ALLOWED_VERSION set to 2.32 to make sure we don't
+ * accidentally use new API that we shouldn't. But we don't want warnings for
+ * the APIs that we emulate above.
+ */
+
+#define g_test_expect_message(domain, level, format...) \
+       G_STMT_START { \
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+               g_test_expect_message (domain, level, format); \
+               G_GNUC_END_IGNORE_DEPRECATIONS \
+       } G_STMT_END
+
+#define g_test_assert_expected_messages_internal(domain, file, line, func) \
+       G_STMT_START { \
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+               g_test_assert_expected_messages_internal (domain, file, line, func); \
+               G_GNUC_END_IGNORE_DEPRECATIONS \
+       } G_STMT_END
+
+#endif
+
+
+#if GLIB_CHECK_VERSION (2, 35, 0)
+/* For glib >= 2.36, g_type_init() is deprecated.
+ * But since 2.35.1 (7c42ab23b55c43ab96d0ac2124b550bf1f49c1ec) this function
+ * does nothing. Replace the call with empty statement. */
+#define nm_g_type_init()     G_STMT_START { (void) 0; } G_STMT_END
+#else
+#define nm_g_type_init()     G_STMT_START { g_type_init (); } G_STMT_END
+#endif
+
+
+/* g_test_initialized() is only available since glib 2.36. */
+#if !GLIB_CHECK_VERSION (2, 36, 0)
+#define g_test_initialized() (g_test_config_vars->test_initialized)
+#endif
+
+/* g_assert_cmpmem() is only available since glib 2.46. */
+#if !GLIB_CHECK_VERSION (2, 45, 7)
+#define g_assert_cmpmem(m1, l1, m2, l2) G_STMT_START {\
+                                             gconstpointer __m1 = m1, __m2 = m2; \
+                                             int __l1 = l1, __l2 = l2; \
+                                             if (__l1 != __l2) \
+                                               g_assertion_message_cmpnum (G_LOG_DOMAIN, __FILE__, __LINE__, 
G_STRFUNC, \
+                                                                           #l1 " (len(" #m1 ")) == " #l2 " 
(len(" #m2 "))", __l1, "==", __l2, 'i'); \
+                                             else if (memcmp (__m1, __m2, __l1) != 0) \
+                                               g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, 
G_STRFUNC, \
+                                                                    "assertion failed (" #m1 " == " #m2 
")"); \
+                                        } G_STMT_END
+#endif
+
+/* Rumtime check for glib version. First do a compile time check which
+ * (if satisfied) shortcuts the runtime check. */
+#define nm_glib_check_version(major, minor, micro) \
+    (   GLIB_CHECK_VERSION ((major), (minor), (micro)) \
+     || (   (   glib_major_version > (major)) \
+         || (   glib_major_version == (major) \
+             && glib_minor_version > (minor)) \
+         || (   glib_major_version == (major) \
+             && glib_minor_version == (minor) \
+             && glib_micro_version >= (micro))))
+
+/* g_test_skip() is only available since glib 2.38. Add a compatibility wrapper. */
+inline static void
+__nmtst_g_test_skip (const gchar *msg)
+{
+#if GLIB_CHECK_VERSION (2, 38, 0)
+       G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+       g_test_skip (msg);
+       G_GNUC_END_IGNORE_DEPRECATIONS
+#else
+       g_debug ("%s", msg);
+#endif
+}
+#define g_test_skip __nmtst_g_test_skip
+
+
+/* g_test_add_data_func_full() is only available since glib 2.34. Add a compatibility wrapper. */
+inline static void
+__g_test_add_data_func_full (const char     *testpath,
+                             gpointer        test_data,
+                             GTestDataFunc   test_func,
+                             GDestroyNotify  data_free_func)
+{
+#if GLIB_CHECK_VERSION (2, 34, 0)
+       G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+       g_test_add_data_func_full (testpath, test_data, test_func, data_free_func);
+       G_GNUC_END_IGNORE_DEPRECATIONS
+#else
+       g_return_if_fail (testpath != NULL);
+       g_return_if_fail (testpath[0] == '/');
+       g_return_if_fail (test_func != NULL);
+
+       g_test_add_vtable (testpath, 0, test_data, NULL,
+                          (GTestFixtureFunc) test_func,
+                          (GTestFixtureFunc) data_free_func);
+#endif
+}
+#define g_test_add_data_func_full __g_test_add_data_func_full
+
+
+#if !GLIB_CHECK_VERSION (2, 34, 0)
+#define G_DEFINE_QUARK(QN, q_n)               \
+GQuark                                        \
+q_n##_quark (void)                            \
+{                                             \
+       static GQuark q;                          \
+                                              \
+       if G_UNLIKELY (q == 0)                    \
+               q = g_quark_from_static_string (#QN); \
+                                              \
+       return q;                                 \
+}
+#endif
+
+
+static inline gboolean
+nm_g_hash_table_replace (GHashTable *hash, gpointer key, gpointer value)
+{
+       /* glib 2.40 added a return value indicating whether the key already existed
+        * (910191597a6c2e5d5d460e9ce9efb4f47d9cc63c). */
+#if GLIB_CHECK_VERSION(2, 40, 0)
+       return g_hash_table_replace (hash, key, value);
+#else
+       gboolean contained = g_hash_table_contains (hash, key);
+
+       g_hash_table_replace (hash, key, value);
+       return !contained;
+#endif
+}
+
+static inline gboolean
+nm_g_hash_table_insert (GHashTable *hash, gpointer key, gpointer value)
+{
+       /* glib 2.40 added a return value indicating whether the key already existed
+        * (910191597a6c2e5d5d460e9ce9efb4f47d9cc63c). */
+#if GLIB_CHECK_VERSION(2, 40, 0)
+       return g_hash_table_insert (hash, key, value);
+#else
+       gboolean contained = g_hash_table_contains (hash, key);
+
+       g_hash_table_insert (hash, key, value);
+       return !contained;
+#endif
+}
+
+static inline gboolean
+nm_g_hash_table_add (GHashTable *hash, gpointer key)
+{
+       /* glib 2.40 added a return value indicating whether the key already existed
+        * (910191597a6c2e5d5d460e9ce9efb4f47d9cc63c). */
+#if GLIB_CHECK_VERSION(2, 40, 0)
+       return g_hash_table_add (hash, key);
+#else
+       gboolean contained = g_hash_table_contains (hash, key);
+
+       g_hash_table_add (hash, key);
+       return !contained;
+#endif
+}
+
+#if !GLIB_CHECK_VERSION(2, 40, 0) || defined (NM_GLIB_COMPAT_H_TEST)
+static inline void
+_nm_g_ptr_array_insert (GPtrArray *array,
+                        gint       index_,
+                        gpointer   data)
+{
+       g_return_if_fail (array);
+       g_return_if_fail (index_ >= -1);
+       g_return_if_fail (index_ <= (gint) array->len);
+
+       g_ptr_array_add (array, data);
+
+       if (index_ != -1 && index_ != (gint) (array->len - 1)) {
+               memmove (&(array->pdata[index_ + 1]),
+                        &(array->pdata[index_]),
+                        (array->len - index_ - 1) * sizeof (gpointer));
+               array->pdata[index_] = data;
+       }
+}
+#endif
+#if !GLIB_CHECK_VERSION(2, 40, 0)
+#define g_ptr_array_insert(array, index, data) G_STMT_START { _nm_g_ptr_array_insert (array, index, data); } 
G_STMT_END
+#else
+#define g_ptr_array_insert(array, index, data) \
+       G_STMT_START { \
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+               g_ptr_array_insert (array, index, data); \
+               G_GNUC_END_IGNORE_DEPRECATIONS \
+       } G_STMT_END
+#endif
+
+
+#if !GLIB_CHECK_VERSION (2, 40, 0)
+inline static gboolean
+_g_key_file_save_to_file (GKeyFile     *key_file,
+                          const gchar  *filename,
+                          GError      **error)
+{
+       gchar *contents;
+       gboolean success;
+       gsize length;
+
+       g_return_val_if_fail (key_file != NULL, FALSE);
+       g_return_val_if_fail (filename != NULL, FALSE);
+       g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+       contents = g_key_file_to_data (key_file, &length, NULL);
+       g_assert (contents != NULL);
+
+       success = g_file_set_contents (filename, contents, length, error);
+       g_free (contents);
+
+       return success;
+}
+#define g_key_file_save_to_file(key_file, filename, error) \
+       _g_key_file_save_to_file (key_file, filename, error)
+#else
+#define g_key_file_save_to_file(key_file, filename, error) \
+       ({ \
+               gboolean _success; \
+               \
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+               _success = g_key_file_save_to_file (key_file, filename, error); \
+               G_GNUC_END_IGNORE_DEPRECATIONS \
+               _success; \
+       })
+#endif
+
+
+#if GLIB_CHECK_VERSION (2, 36, 0)
+#define g_credentials_get_unix_pid(creds, error) \
+       G_GNUC_EXTENSION ({ \
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+                       (g_credentials_get_unix_pid) ((creds), (error)); \
+               G_GNUC_END_IGNORE_DEPRECATIONS \
+       })
+#else
+#define g_credentials_get_unix_pid(creds, error) \
+       G_GNUC_EXTENSION ({ \
+               struct ucred *native_creds; \
+                \
+               native_creds = g_credentials_get_native ((creds), G_CREDENTIALS_TYPE_LINUX_UCRED); \
+               g_assert (native_creds); \
+               native_creds->pid; \
+       })
+#endif
+
+
+#if !GLIB_CHECK_VERSION(2, 40, 0) || defined (NM_GLIB_COMPAT_H_TEST)
+static inline gpointer *
+_nm_g_hash_table_get_keys_as_array (GHashTable *hash_table,
+                                    guint      *length)
+{
+       GHashTableIter iter;
+       gpointer key, *ret;
+       guint i = 0;
+
+       g_return_val_if_fail (hash_table, NULL);
+
+       ret = g_new0 (gpointer, g_hash_table_size (hash_table) + 1);
+       g_hash_table_iter_init (&iter, hash_table);
+
+       while (g_hash_table_iter_next (&iter, &key, NULL))
+               ret[i++] = key;
+
+       ret[i] = NULL;
+
+       if (length)
+               *length = i;
+
+       return ret;
+}
+#endif
+#if !GLIB_CHECK_VERSION(2, 40, 0)
+#define g_hash_table_get_keys_as_array(hash_table, length) \
+       G_GNUC_EXTENSION ({ \
+               _nm_g_hash_table_get_keys_as_array (hash_table, length); \
+       })
+#else
+#define g_hash_table_get_keys_as_array(hash_table, length) \
+       G_GNUC_EXTENSION ({ \
+               G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
+                       (g_hash_table_get_keys_as_array) ((hash_table), (length)); \
+               G_GNUC_END_IGNORE_DEPRECATIONS \
+       })
+#endif
+
+#ifndef g_info
+/* g_info was only added with 2.39.2 */
+#define g_info(...)     g_log (G_LOG_DOMAIN,         \
+                               G_LOG_LEVEL_INFO,     \
+                               __VA_ARGS__)
+#endif
+
+#if !GLIB_CHECK_VERSION(2, 44, 0)
+static inline gpointer
+g_steal_pointer (gpointer pp)
+{
+       gpointer *ptr = (gpointer *) pp;
+       gpointer ref;
+
+       ref = *ptr;
+       *ptr = NULL;
+
+       return ref;
+}
+
+/* type safety */
+#define g_steal_pointer(pp) \
+  (0 ? (*(pp)) : (g_steal_pointer) (pp))
+#endif
+
+#endif  /* __NM_GLIB_H__ */
diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h
index a8000ac..603689a 100644
--- a/shared/nm-utils/nm-macros-internal.h
+++ b/shared/nm-utils/nm-macros-internal.h
@@ -24,6 +24,8 @@
 
 #include <stdlib.h>
 
+#include "nm-glib.h"
+
 /********************************************************/
 
 #define _nm_packed __attribute__ ((packed))
@@ -485,8 +487,8 @@ nm_strstrip (char *str)
 }
 
 /* g_ptr_array_sort()'s compare function takes pointers to the
- * contentaining value. Thus, you cannot use strcmp directly. You
- * can use nm_strcmp_p().
+ * value. Thus, you cannot use strcmp directly. You can use
+ * nm_strcmp_p().
  *
  * Like strcmp(), this function is not forgiving to accept %NULL. */
 static inline int
@@ -500,8 +502,8 @@ nm_strcmp_p (gconstpointer a, gconstpointer b)
 
 /* like nm_strcmp_p(), suitable for g_ptr_array_sort_with_data().
  * g_ptr_array_sort() just casts nm_strcmp_p() to a function of different
- * signature. I guess, in glib there are knowledgeble people that ensure
- * that this additinal argument doesn't cause problems due to different ABI
+ * signature. I guess, in glib there are knowledgeable people that ensure
+ * that this additional argument doesn't cause problems due to different ABI
  * for every architecture that glib supports.
  * For NetworkManager, we'd rather avoid such stunts.
  **/
diff --git a/shared/nm-utils/nm-vpn-editor-plugin-call.h b/shared/nm-utils/nm-vpn-editor-plugin-call.h
index c6b7ee7..78d041d 100644
--- a/shared/nm-utils/nm-vpn-editor-plugin-call.h
+++ b/shared/nm-utils/nm-vpn-editor-plugin-call.h
@@ -32,7 +32,6 @@
 #include <NetworkManager.h>
 
 /* we make use of other internal header files, you need those too. */
-#include "gsystem-local-alloc.h"
 #include "nm-macros-internal.h"
 
 /*****************************************************************************/
diff --git a/shared/nm-utils/nm-vpn-plugin-utils.c b/shared/nm-utils/nm-vpn-plugin-utils.c
new file mode 100644
index 0000000..772aa39
--- /dev/null
+++ b/shared/nm-utils/nm-vpn-plugin-utils.c
@@ -0,0 +1,130 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2016 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-vpn-plugin-utils.h"
+
+#include <dlfcn.h>
+
+/*****************************************************************************/
+
+NMVpnEditor *
+nm_vpn_plugin_utils_load_editor (const char *module_name,
+                                 const char *factory_name,
+                                 NMVpnPluginUtilsEditorFactory editor_factory,
+                                 NMVpnEditorPlugin *editor_plugin,
+                                 NMConnection *connection,
+                                 gpointer user_data,
+                                 GError **error)
+
+{
+       static struct {
+               gpointer factory;
+               void *dl_module;
+               char *module_name;
+               char *factory_name;
+       } cached = { 0 };
+       NMVpnEditor *editor;
+
+       g_return_val_if_fail (module_name && g_path_is_absolute (module_name), NULL);
+       g_return_val_if_fail (factory_name && factory_name[0], NULL);
+       g_return_val_if_fail (editor_factory, NULL);
+       g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (editor_plugin), NULL);
+       g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+       g_return_val_if_fail (!error || !*error, NULL);
+
+       /* we really expect this function to be called with unchanging @module_name
+        * and @factory_name. And we only want to load the module once, hence it would
+        * be more complicated to accept changing @module_name/@factory_name arguments.
+        *
+        * The reason for only loading once is that due to glib types, we cannot create a
+        * certain type-name more then once, so loading the same module or another version
+        * of the same module will fail horribly as both try to create a GType with the same
+        * name.
+        *
+        * Only support loading once, any future calls will reuse the handle. To simplify
+        * that, we enforce that the @factory_name and @module_name is the same. */
+       if (cached.factory) {
+               g_return_val_if_fail (cached.dl_module, NULL);
+               g_return_val_if_fail (cached.factory_name && nm_streq0 (cached.factory_name, factory_name), 
NULL);
+               g_return_val_if_fail (cached.module_name && nm_streq0 (cached.module_name, module_name), 
NULL);
+       } else {
+               gpointer factory;
+               void *dl_module;
+
+               dl_module = dlopen (module_name, RTLD_LAZY | RTLD_LOCAL);
+               if (!dl_module) {
+                       if (!g_file_test (module_name, G_FILE_TEST_EXISTS)) {
+                               g_set_error (error,
+                                            G_FILE_ERROR,
+                                            G_FILE_ERROR_NOENT,
+                                            _("missing plugin file \"%s\""), module_name);
+                               return NULL;
+                       }
+                       g_set_error (error,
+                                    NM_CONNECTION_ERROR,
+                                    NM_CONNECTION_ERROR_FAILED,
+                                    _("cannot load editor plugin: %s"), dlerror ());
+                       return NULL;
+               }
+
+               factory = dlsym (dl_module, factory_name);
+               if (!factory) {
+                       g_set_error (error,
+                                    NM_CONNECTION_ERROR,
+                                    NM_CONNECTION_ERROR_FAILED,
+                                    _("cannot load factory %s from plugin: %s"),
+                                    factory_name, dlerror ());
+                       dlclose (dl_module);
+                       return NULL;
+               }
+
+               /* we cannot ever unload the module because it creates glib types, which
+                * cannot be unregistered.
+                *
+                * Thus we just leak the dl_module handle indefinitely. */
+               cached.factory = factory;
+               cached.dl_module = dl_module;
+               cached.module_name = g_strdup (module_name);
+               cached.factory_name = g_strdup (factory_name);
+       }
+
+       editor = editor_factory (cached.factory,
+                                editor_plugin,
+                                connection,
+                                user_data,
+                                error);
+       if (!editor) {
+               if (error && !*error ) {
+                       g_set_error_literal (error,
+                                            NM_CONNECTION_ERROR,
+                                            NM_CONNECTION_ERROR_FAILED,
+                                            _("unknown error creating editor instance"));
+                       g_return_val_if_reached (NULL);
+               }
+               return NULL;
+       }
+
+       g_return_val_if_fail (NM_IS_VPN_EDITOR (editor), NULL);
+       return editor;
+}
+
diff --git a/shared/nm-utils/nm-vpn-plugin-utils.h b/shared/nm-utils/nm-vpn-plugin-utils.h
new file mode 100644
index 0000000..f3928d1
--- /dev/null
+++ b/shared/nm-utils/nm-vpn-plugin-utils.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2016 Red Hat, Inc.
+ */
+
+#ifndef __NM_VPN_PLUGIN_UTILS_H__
+#define __NM_VPN_PLUGIN_UTILS_H__
+
+#include <NetworkManager.h>
+
+typedef NMVpnEditor *(NMVpnPluginUtilsEditorFactory) (gpointer factory,
+                                                      NMVpnEditorPlugin *editor_plugin,
+                                                      NMConnection *connection,
+                                                      gpointer user_data,
+                                                      GError **error);
+
+NMVpnEditor *nm_vpn_plugin_utils_load_editor (const char *module_name,
+                                              const char *factory_name,
+                                              NMVpnPluginUtilsEditorFactory editor_factory,
+                                              NMVpnEditorPlugin *editor_plugin,
+                                              NMConnection *connection,
+                                              gpointer user_data,
+                                              GError **error);
+
+#endif /* __NM_VPN_PLUGIN_UTILS_H__ */
+


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]