diff options
author | 2012-09-05 17:44:22 -0400 | |
---|---|---|
committer | 2012-09-05 19:09:32 -0400 | |
commit | 6345767b932f2ac1927be91d0213be251391f30b (patch) | |
tree | d15c6ee92c9d89ef4dff7eda2138418769726762 | |
parent | Wrong g_free() due to careless copy/paste (diff) | |
download | openrc-settingsd-6345767b932f2ac1927be91d0213be251391f30b.tar.gz openrc-settingsd-6345767b932f2ac1927be91d0213be251391f30b.tar.bz2 openrc-settingsd-6345767b932f2ac1927be91d0213be251391f30b.zip |
Merge *-utils, rename ShellUtilsTrivial to ShellParser, fix memory leaks
-rw-r--r-- | Makefile.am | 6 | ||||
-rw-r--r-- | src/bus-utils.c | 109 | ||||
-rw-r--r-- | src/bus-utils.h | 11 | ||||
-rw-r--r-- | src/hostnamed.c | 47 | ||||
-rw-r--r-- | src/localed.c | 59 | ||||
-rw-r--r-- | src/main.c | 6 | ||||
-rw-r--r-- | src/shell-utils.h | 86 | ||||
-rw-r--r-- | src/timedated.c | 9 | ||||
-rw-r--r-- | src/utils.c (renamed from src/shell-utils.c) | 308 | ||||
-rw-r--r-- | src/utils.h | 102 |
10 files changed, 378 insertions, 365 deletions
diff --git a/Makefile.am b/Makefile.am index 32890fb..e12c3d7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -59,10 +59,8 @@ openrc_settingsd_SOURCES = \ src/localed.h \ src/timedated.c \ src/timedated.h \ - src/bus-utils.c \ - src/bus-utils.h \ - src/shell-utils.c \ - src/shell-utils.h \ + src/utils.c \ + src/utils.h \ src/main.c \ $(NULL) diff --git a/src/bus-utils.c b/src/bus-utils.c index f78f8f2..8db9bb4 100644 --- a/src/bus-utils.c +++ b/src/bus-utils.c @@ -22,113 +22,4 @@ #include "bus-utils.h" -struct check_polkit_data { - const gchar *unique_name; - const gchar *action_id; - gboolean user_interaction; - GAsyncReadyCallback callback; - gpointer user_data; - PolkitAuthority *authority; - PolkitSubject *subject; -}; - -void -check_polkit_data_free (struct check_polkit_data *data) -{ - if (data == NULL) - return; - - if (data->subject != NULL) - g_object_unref (data->subject); - if (data->authority != NULL) - g_object_unref (data->authority); - - g_free (data); -} - -gboolean -check_polkit_finish (GAsyncResult *res, - GError **error) -{ - GSimpleAsyncResult *simple; - - simple = G_SIMPLE_ASYNC_RESULT (res); - if (g_simple_async_result_propagate_error (simple, error)) - return FALSE; - - return g_simple_async_result_get_op_res_gboolean (simple); -} - -static void -check_polkit_authorization_cb (GObject *source_object, - GAsyncResult *res, - gpointer _data) -{ - struct check_polkit_data *data; - PolkitAuthorizationResult *result; - GSimpleAsyncResult *simple; - GError *err = NULL; - - data = (struct check_polkit_data *) _data; - if ((result = polkit_authority_check_authorization_finish (data->authority, res, &err)) == NULL) { - g_simple_async_report_take_gerror_in_idle (NULL, data->callback, data->user_data, err); - goto out; - } - - if (!polkit_authorization_result_get_is_authorized (result)) { - g_simple_async_report_error_in_idle (NULL, data->callback, data->user_data, POLKIT_ERROR, POLKIT_ERROR_NOT_AUTHORIZED, "Authorizing for '%s': not authorized", data->action_id); - goto out; - } - simple = g_simple_async_result_new (NULL, data->callback, data->user_data, check_polkit_async); - g_simple_async_result_set_op_res_gboolean (simple, TRUE); - g_simple_async_result_complete_in_idle (simple); - g_object_unref (simple); - - out: - check_polkit_data_free (data); - if (result != NULL) - g_object_unref (result); -} - -static void -check_polkit_authority_cb (GObject *source_object, - GAsyncResult *res, - gpointer _data) -{ - struct check_polkit_data *data; - GError *err = NULL; - - data = (struct check_polkit_data *) _data; - if ((data->authority = polkit_authority_get_finish (res, &err)) == NULL) { - g_simple_async_report_take_gerror_in_idle (NULL, data->callback, data->user_data, err); - check_polkit_data_free (data); - return; - } - if (data->unique_name == NULL || data->action_id == NULL || - (data->subject = polkit_system_bus_name_new (data->unique_name)) == NULL) { - g_simple_async_report_error_in_idle (NULL, data->callback, data->user_data, POLKIT_ERROR, POLKIT_ERROR_FAILED, "Authorizing for '%s': failed sanity check", data->action_id); - check_polkit_data_free (data); - return; - } - polkit_authority_check_authorization (data->authority, data->subject, data->action_id, NULL, (PolkitCheckAuthorizationFlags) data->user_interaction, NULL, check_polkit_authorization_cb, data); -} - -void -check_polkit_async (const gchar *unique_name, - const gchar *action_id, - const gboolean user_interaction, - GAsyncReadyCallback callback, - gpointer user_data) -{ - struct check_polkit_data *data; - - data = g_new0 (struct check_polkit_data, 1); - data->unique_name = unique_name; - data->action_id = action_id; - data->user_interaction = user_interaction; - data->callback = callback; - data->user_data = user_data; - - polkit_authority_get_async (NULL, check_polkit_authority_cb, data); -} diff --git a/src/bus-utils.h b/src/bus-utils.h index 4a57bb5..282a63e 100644 --- a/src/bus-utils.h +++ b/src/bus-utils.h @@ -21,15 +21,6 @@ #include <glib.h> -void -check_polkit_async (const gchar *unique_name, - const gchar *action_id, - const gboolean user_interaction, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean -check_polkit_finish (GAsyncResult *res, - GError **error); + #endif diff --git a/src/hostnamed.c b/src/hostnamed.c index f0992bd..1fb14c0 100644 --- a/src/hostnamed.c +++ b/src/hostnamed.c @@ -28,8 +28,7 @@ #include "hostnamed.h" #include "hostname1-generated.h" -#include "bus-utils.h" -#include "shell-utils.h" +#include "utils.h" #include "config.h" @@ -66,10 +65,12 @@ hostname_is_valid (const gchar *name) name, G_REGEX_MULTILINE, 0); } -static void +static gchar * guess_icon_name () { /* TODO: detect virtualization by reading rc_sys */ + gchar *filebuf = NULL; + gchar *ret = NULL; #if defined(__i386__) || defined(__x86_64__) /* @@ -80,32 +81,34 @@ guess_icon_name () http://www.dmtf.org/sites/default/files/standards/documents/DSP0134_2.7.1.pdf */ - gchar *contents; - if (g_file_get_contents ("/sys/class/dmi/id/chassis_type", &contents, NULL, NULL)) { - switch (g_ascii_strtoull (contents, NULL, 10)) { + if (g_file_get_contents ("/sys/class/dmi/id/chassis_type", &filebuf, NULL, NULL)) { + switch (g_ascii_strtoull (filebuf, NULL, 10)) { case 0x3: case 0x4: case 0x5: case 0x6: case 0x7: - icon_name = g_strdup ("computer-desktop"); - return; + ret = g_strdup ("computer-desktop"); + goto out; case 0x9: case 0xA: case 0xE: - icon_name = g_strdup ("computer-laptop"); - return; + ret = g_strdup ("computer-laptop"); + goto out; case 0x11: case 0x17: case 0x1C: case 0x1D: - icon_name = g_strdup ("computer-server"); - return; + ret = g_strdup ("computer-server"); + goto out; } } #endif - icon_name = g_strdup ("computer"); + ret = g_strdup ("computer"); + out: + g_free (filebuf); + return ret; } static void @@ -198,7 +201,7 @@ on_handle_set_static_hostname_authorized_cb (GObject *source_object, data->name = g_strdup ("localhost"); } - if (!shell_utils_trivial_set_and_save (static_hostname_file, &err, "hostname", "HOSTNAME", data->name, NULL)) { + if (!shell_parser_set_and_save (static_hostname_file, &err, "hostname", "HOSTNAME", data->name, NULL)) { g_dbus_method_invocation_return_gerror (data->invocation, err); G_UNLOCK (static_hostname); goto out; @@ -257,7 +260,7 @@ on_handle_set_pretty_hostname_authorized_cb (GObject *source_object, if (data->name == NULL) data->name = g_strdup (""); - if (!shell_utils_trivial_set_and_save (machine_info_file, &err, "PRETTY_HOSTNAME", NULL, data->name, NULL)) { + if (!shell_parser_set_and_save (machine_info_file, &err, "PRETTY_HOSTNAME", NULL, data->name, NULL)) { g_dbus_method_invocation_return_gerror (data->invocation, err); G_UNLOCK (machine_info); goto out; @@ -316,7 +319,7 @@ on_handle_set_icon_name_authorized_cb (GObject *source_object, if (data->name == NULL) data->name = g_strdup (""); - if (!shell_utils_trivial_set_and_save (machine_info_file, &err, "ICON_NAME", NULL, data->name, NULL)) { + if (!shell_parser_set_and_save (machine_info_file, &err, "ICON_NAME", NULL, data->name, NULL)) { g_dbus_method_invocation_return_gerror (data->invocation, err); G_UNLOCK (machine_info); goto out; @@ -425,13 +428,13 @@ hostnamed_init (gboolean _read_only) static_hostname_file = g_file_new_for_path (SYSCONFDIR "/conf.d/hostname"); machine_info_file = g_file_new_for_path (SYSCONFDIR "/machine-info"); - static_hostname = shell_utils_source_var (static_hostname_file, "${hostname-${HOSTNAME-localhost}}", &err); + static_hostname = shell_source_var (static_hostname_file, "${hostname-${HOSTNAME-localhost}}", &err); if (err != NULL) { g_debug ("%s", err->message); g_error_free (err); err = NULL; } - pretty_hostname = shell_utils_source_var (machine_info_file, "${PRETTY_HOSTNAME}", &err); + pretty_hostname = shell_source_var (machine_info_file, "${PRETTY_HOSTNAME}", &err); if (pretty_hostname == NULL) pretty_hostname = g_strdup (""); if (err != NULL) { @@ -439,7 +442,7 @@ hostnamed_init (gboolean _read_only) g_error_free (err); err = NULL; } - icon_name = shell_utils_source_var (machine_info_file, "${ICON_NAME}", &err); + icon_name = shell_source_var (machine_info_file, "${ICON_NAME}", &err); if (icon_name == NULL) icon_name = g_strdup (""); if (err != NULL) { @@ -448,8 +451,10 @@ hostnamed_init (gboolean _read_only) err = NULL; } - if (icon_name == NULL || strlen (icon_name) == 0) - guess_icon_name (); + if (icon_name == NULL || *icon_name == 0) { + g_free (icon_name); + icon_name = guess_icon_name (); + } read_only = _read_only; diff --git a/src/localed.c b/src/localed.c index 2e8e44e..0cb4404 100644 --- a/src/localed.c +++ b/src/localed.c @@ -26,8 +26,7 @@ #include "localed.h" #include "locale1-generated.h" -#include "bus-utils.h" -#include "shell-utils.h" +#include "utils.h" #include "config.h" @@ -215,16 +214,17 @@ kbd_model_map_load (GError **error) for (line = filebuf; *line != 0; line = newline + 1) { struct kbd_model_map_entry *entry = NULL; GMatchInfo *match_info = NULL; + gboolean m = FALSE; if ((newline = strstr (line, "\n")) != NULL) *newline = 0; else newline = line + strlen (line) - 1; - if (g_regex_match (kbd_model_map_line_comment_re, line, 0, &match_info)) { - g_match_info_free (match_info); + m = g_regex_match (kbd_model_map_line_comment_re, line, 0, &match_info); + _g_match_info_clear (&match_info); + if (m) continue; - } if (!g_regex_match (kbd_model_map_line_re, line, 0, &match_info)) { g_propagate_error (error, @@ -253,7 +253,7 @@ kbd_model_map_load (GError **error) entry->x11_options[0] = 0; ret = g_list_prepend (ret, entry); - g_match_info_free (match_info); + _g_match_info_clear (&match_info); } out: if (ret != NULL) @@ -452,6 +452,7 @@ xorg_confd_parser_new (GFile *xorg_confd_file, struct xorg_confd_line_entry *entry = NULL; GMatchInfo *match_info = NULL; gboolean matched = FALSE; + gboolean m = FALSE; if ((newline = strstr (line, "\n")) != NULL) *newline = 0; @@ -463,48 +464,48 @@ xorg_confd_parser_new (GFile *xorg_confd_file, if (g_regex_match (xorg_confd_line_comment_re, line, 0, &match_info)) { g_debug ("Parsed line '%s' as comment", line); entry->type = XORG_CONFD_LINE_TYPE_COMMENT; - } else if (g_regex_match (xorg_confd_line_section_input_class_re, line, 0, &match_info)) { + } else if (_g_match_info_clear (&match_info) && g_regex_match (xorg_confd_line_section_input_class_re, line, 0, &match_info)) { g_debug ("Parsed line '%s' as InputClass section", line); if (in_section) goto no_match; in_section = TRUE; entry->type = XORG_CONFD_LINE_TYPE_SECTION_INPUT_CLASS; - } else if (g_regex_match (xorg_confd_line_section_re, line, 0, &match_info)) { + } else if (_g_match_info_clear (&match_info) && g_regex_match (xorg_confd_line_section_re, line, 0, &match_info)) { g_debug ("Parsed line '%s' as non-InputClass section", line); if (in_section) goto no_match; in_section = TRUE; entry->type = XORG_CONFD_LINE_TYPE_SECTION_OTHER; - } else if (g_regex_match (xorg_confd_line_end_section_re, line, 0, &match_info)) { + } else if (_g_match_info_clear (&match_info) && g_regex_match (xorg_confd_line_end_section_re, line, 0, &match_info)) { g_debug ("Parsed line '%s' as end of section", line); if (!in_section) goto no_match; entry->type = XORG_CONFD_LINE_TYPE_END_SECTION; - } else if (g_regex_match (xorg_confd_line_match_is_keyboard_re, line, 0, &match_info)) { + } else if (_g_match_info_clear (&match_info) && g_regex_match (xorg_confd_line_match_is_keyboard_re, line, 0, &match_info)) { g_debug ("Parsed line '%s' as MatchIsKeyboard declaration", line); if (!in_section) goto no_match; entry->type = XORG_CONFD_LINE_TYPE_MATCH_IS_KEYBOARD; in_xkb_section = TRUE; - } else if (g_regex_match (xorg_confd_line_xkb_layout_re, line, 0, &match_info)) { + } else if (_g_match_info_clear (&match_info) && g_regex_match (xorg_confd_line_xkb_layout_re, line, 0, &match_info)) { g_debug ("Parsed line '%s' as XkbLayout option", line); if (!in_section) goto no_match; entry->type = XORG_CONFD_LINE_TYPE_XKB_LAYOUT; entry->value = g_match_info_fetch (match_info, 2); - } else if (g_regex_match (xorg_confd_line_xkb_model_re, line, 0, &match_info)) { + } else if (_g_match_info_clear (&match_info) && g_regex_match (xorg_confd_line_xkb_model_re, line, 0, &match_info)) { g_debug ("Parsed line '%s' as XkbModel option", line); if (!in_section) goto no_match; entry->type = XORG_CONFD_LINE_TYPE_XKB_MODEL; entry->value = g_match_info_fetch (match_info, 2); - } else if (g_regex_match (xorg_confd_line_xkb_variant_re, line, 0, &match_info)) { + } else if (_g_match_info_clear (&match_info) && g_regex_match (xorg_confd_line_xkb_variant_re, line, 0, &match_info)) { g_debug ("Parsed line '%s' as XkbVariant option", line); if (!in_section) goto no_match; entry->type = XORG_CONFD_LINE_TYPE_XKB_VARIANT; entry->value = g_match_info_fetch (match_info, 2); - } else if (g_regex_match (xorg_confd_line_xkb_options_re, line, 0, &match_info)) { + } else if (_g_match_info_clear (&match_info) && g_regex_match (xorg_confd_line_xkb_options_re, line, 0, &match_info)) { g_debug ("Parsed line '%s' as XkbOptions option", line); if (!in_section) goto no_match; @@ -515,7 +516,7 @@ xorg_confd_parser_new (GFile *xorg_confd_file, if (entry->type == XORG_CONFD_LINE_TYPE_UNKNOWN) g_debug ("Parsing line '%s' as unknown", line); - g_match_info_free (match_info); + _g_match_info_clear (&match_info); parser->line_list = g_list_prepend (parser->line_list, entry); if (in_section) { if (entry->type == XORG_CONFD_LINE_TYPE_SECTION_INPUT_CLASS) @@ -534,7 +535,7 @@ xorg_confd_parser_new (GFile *xorg_confd_file, no_match: /* Nothing matched... */ g_free (entry); - g_match_info_free (match_info); + _g_match_info_clear (&match_info); goto parse_fail; } @@ -787,7 +788,7 @@ on_handle_set_locale_authorized_cb (GObject *source_object, GError *err = NULL; struct invoked_locale *data; gchar **loc, **var, **val, **locale_values = NULL; - ShellUtilsTrivial *locale_file_parsed = NULL; + ShellParser *locale_file_parsed = NULL; data = (struct invoked_locale *) user_data; if (!check_polkit_finish (res, &err)) { @@ -825,16 +826,16 @@ on_handle_set_locale_authorized_cb (GObject *source_object, } } - if ((locale_file_parsed = shell_utils_trivial_new (locale_file, &err)) == NULL) { + if ((locale_file_parsed = shell_parser_new (locale_file, &err)) == NULL) { g_dbus_method_invocation_return_gerror (data->invocation, err); G_UNLOCK (locale); goto out; } - if (shell_utils_trivial_is_empty (locale_file_parsed)) { + if (shell_parser_is_empty (locale_file_parsed)) { /* Simply write the new env file */ - shell_utils_trivial_free (locale_file_parsed); - if ((locale_file_parsed = shell_utils_trivial_new_from_string (locale_file, "# Configuration file for eselect\n# This file has been automatically generated\n", &err)) == NULL) { + shell_parser_free (locale_file_parsed); + if ((locale_file_parsed = shell_parser_new_from_string (locale_file, "# Configuration file for eselect\n# This file has been automatically generated\n", &err)) == NULL) { g_dbus_method_invocation_return_gerror (data->invocation, err); G_UNLOCK (locale); goto out; @@ -843,12 +844,12 @@ on_handle_set_locale_authorized_cb (GObject *source_object, for (val = locale_values, var = locale_variables; *var != NULL; val++, var++) { if (*val == NULL) - shell_utils_trivial_clear_variable (locale_file_parsed, *var); + shell_parser_clear_variable (locale_file_parsed, *var); else - shell_utils_trivial_set_variable (locale_file_parsed, *var, *val, TRUE); + shell_parser_set_variable (locale_file_parsed, *var, *val, TRUE); } - if (!shell_utils_trivial_save (locale_file_parsed, &err)) { + if (!shell_parser_save (locale_file_parsed, &err)) { g_dbus_method_invocation_return_gerror (data->invocation, err); G_UNLOCK (locale); goto out; @@ -869,7 +870,7 @@ on_handle_set_locale_authorized_cb (GObject *source_object, G_UNLOCK (locale); out: - shell_utils_trivial_free (locale_file_parsed); + shell_parser_free (locale_file_parsed); g_strfreev (locale_values); invoked_locale_free (data); if (err != NULL) @@ -954,7 +955,7 @@ on_handle_set_vconsole_keyboard_authorized_cb (GObject *source_object, } /* We do not set vconsole_keymap_toggle because there is no good equivalent for it in OpenRC */ - if (!shell_utils_trivial_set_and_save (keymaps_file, &err, "keymap", NULL, data->vconsole_keymap, NULL)) { + if (!shell_parser_set_and_save (keymaps_file, &err, "keymap", NULL, data->vconsole_keymap, NULL)) { g_dbus_method_invocation_return_gerror (data->invocation, err); goto unlock; } @@ -1145,7 +1146,7 @@ on_handle_set_x11_keyboard_authorized_cb (GObject *source_object, g_printerr ("Failed to find conversion entry for x11 layout '%s' in '%s'\n", data->x11_layout, filename); g_free (filename); } else { - if (!shell_utils_trivial_set_and_save (keymaps_file, &err, "keymap", NULL, best_entry->vconsole_keymap, NULL)) { + if (!shell_parser_set_and_save (keymaps_file, &err, "keymap", NULL, best_entry->vconsole_keymap, NULL)) { g_dbus_method_invocation_return_gerror (data->invocation, err); goto unlock; } @@ -1273,7 +1274,7 @@ localed_init (gboolean _read_only) x11_systemd_file = g_file_new_for_path (SYSCONFDIR "/X11/xorg.conf.d/00-keyboard.conf"); locale = g_new0 (gchar *, g_strv_length (locale_variables) + 1); - locale_values = shell_utils_trivial_source_var_list (locale_file, (const gchar * const *)locale_variables, &err); + locale_values = shell_parser_source_var_list (locale_file, (const gchar * const *)locale_variables, &err); if (locale_values != NULL) { gchar **variable, **value, **loc; loc = locale; @@ -1291,7 +1292,7 @@ localed_init (gboolean _read_only) g_clear_error (&err); } - vconsole_keymap = shell_utils_source_var (keymaps_file, "${keymap}", &err); + vconsole_keymap = shell_source_var (keymaps_file, "${keymap}", &err); if (vconsole_keymap == NULL) vconsole_keymap = g_strdup (""); if (err != NULL) { @@ -25,7 +25,7 @@ #include "hostnamed.h" #include "localed.h" #include "timedated.h" -#include "shell-utils.h" +#include "utils.h" #include "config.h" @@ -76,7 +76,7 @@ main (gint argc, gchar *argv[]) } else g_log_set_default_handler (log_handler, NULL); - shell_utils_init (); + utils_init (); hostnamed_init (read_only); localed_init (read_only); timedated_init (read_only, ntp_preferred_service); @@ -87,7 +87,7 @@ main (gint argc, gchar *argv[]) timedated_destroy (); localed_destroy (); hostnamed_destroy (); - shell_utils_destroy (); + utils_destroy (); g_free (ntp_preferred_service); return 0; } diff --git a/src/shell-utils.h b/src/shell-utils.h deleted file mode 100644 index 629d017..0000000 --- a/src/shell-utils.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - Copyright 2012 Alexandre Rostovtsev - - 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 St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef _SHELL_UTILS_H_ -#define _SHELL_UTILS_H_ - -#include <glib.h> -#include <gio/gio.h> - -typedef struct _ShellUtilsTrivial ShellUtilsTrivial; - -struct _ShellUtilsTrivial -{ - GFile *file; - gchar *filename; - GList *entry_list; -}; - -gchar * -shell_utils_source_var (GFile *file, - const gchar *variable, - GError **error); - -void -shell_utils_init (void); - -void -shell_utils_destroy (void); - -ShellUtilsTrivial * -shell_utils_trivial_new (GFile *file, - GError **error); - -ShellUtilsTrivial * -shell_utils_trivial_new_from_string (GFile *file, - gchar *filebuf, - GError **error); - -void -shell_utils_trivial_free (ShellUtilsTrivial *trivial); - -gboolean -shell_utils_trivial_is_empty (ShellUtilsTrivial *trivial); - -gboolean -shell_utils_trivial_set_variable (ShellUtilsTrivial *trivial, - const gchar *variable, - const gchar *value, - gboolean add_if_unset); - -void -shell_utils_trivial_clear_variable (ShellUtilsTrivial *trivial, - const gchar *variable); - -gboolean -shell_utils_trivial_save (ShellUtilsTrivial *trivial, - GError **error); - -gboolean -shell_utils_trivial_set_and_save (GFile *file, - GError **error, - const gchar *first_var_name, - const gchar *first_alt_var_name, - const gchar *first_value, - ...); - -gchar ** -shell_utils_trivial_source_var_list (GFile *file, - const gchar * const *var_names, - GError **error); -#endif diff --git a/src/timedated.c b/src/timedated.c index b8a41fc..d6588f4 100644 --- a/src/timedated.c +++ b/src/timedated.c @@ -30,8 +30,7 @@ #include "copypaste/hwclock.h" #include "timedated.h" #include "timedate1-generated.h" -#include "bus-utils.h" -#include "shell-utils.h" +#include "utils.h" #include "config.h" @@ -61,7 +60,7 @@ get_local_rtc (GError **error) gchar *clock = NULL; gboolean ret = FALSE; - clock = shell_utils_source_var (hwclock_file, "${clock}", error); + clock = shell_source_var (hwclock_file, "${clock}", error); if (!g_strcmp0 (clock, "local")) ret = TRUE; return ret; @@ -468,9 +467,9 @@ on_handle_set_local_rtc_authorized_cb (GObject *source_object, } G_LOCK (clock); - clock = shell_utils_source_var (hwclock_file, "${clock}", NULL); + clock = shell_source_var (hwclock_file, "${clock}", NULL); if (clock != NULL || data->local_rtc) - if (!shell_utils_trivial_set_and_save (hwclock_file, &err, "clock", NULL, clock_types[data->local_rtc], NULL)) { + if (!shell_parser_set_and_save (hwclock_file, &err, "clock", NULL, clock_types[data->local_rtc], NULL)) { g_dbus_method_invocation_return_gerror (data->invocation, err); goto unlock; } diff --git a/src/shell-utils.c b/src/utils.c index f5c9b20..d21f9f4 100644 --- a/src/shell-utils.c +++ b/src/utils.c @@ -21,8 +21,9 @@ #include <glib.h> #include <gio/gio.h> +#include <polkit/polkit.h> -#include "shell-utils.h" +#include "utils.h" #include "config.h" @@ -34,6 +35,128 @@ GRegex *single_quoted_regex = NULL; GRegex *double_quoted_regex = NULL; GRegex *unquoted_regex = NULL; +/* Always returns TRUE */ +gboolean +_g_match_info_clear (GMatchInfo **match_info) +{ + if (match_info == NULL || *match_info == NULL) + return TRUE; + g_match_info_free (*match_info); + *match_info = NULL; + return TRUE; +} + +struct check_polkit_data { + const gchar *unique_name; + const gchar *action_id; + gboolean user_interaction; + GAsyncReadyCallback callback; + gpointer user_data; + + PolkitAuthority *authority; + PolkitSubject *subject; +}; + +void +check_polkit_data_free (struct check_polkit_data *data) +{ + if (data == NULL) + return; + + if (data->subject != NULL) + g_object_unref (data->subject); + if (data->authority != NULL) + g_object_unref (data->authority); + + g_free (data); +} + +gboolean +check_polkit_finish (GAsyncResult *res, + GError **error) +{ + GSimpleAsyncResult *simple; + + simple = G_SIMPLE_ASYNC_RESULT (res); + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + + return g_simple_async_result_get_op_res_gboolean (simple); +} + +static void +check_polkit_authorization_cb (GObject *source_object, + GAsyncResult *res, + gpointer _data) +{ + struct check_polkit_data *data; + PolkitAuthorizationResult *result; + GSimpleAsyncResult *simple; + GError *err = NULL; + + data = (struct check_polkit_data *) _data; + if ((result = polkit_authority_check_authorization_finish (data->authority, res, &err)) == NULL) { + g_simple_async_report_take_gerror_in_idle (NULL, data->callback, data->user_data, err); + goto out; + } + + if (!polkit_authorization_result_get_is_authorized (result)) { + g_simple_async_report_error_in_idle (NULL, data->callback, data->user_data, POLKIT_ERROR, POLKIT_ERROR_NOT_AUTHORIZED, "Authorizing for '%s': not authorized", data->action_id); + goto out; + } + simple = g_simple_async_result_new (NULL, data->callback, data->user_data, check_polkit_async); + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + g_simple_async_result_complete_in_idle (simple); + g_object_unref (simple); + + out: + check_polkit_data_free (data); + if (result != NULL) + g_object_unref (result); +} + +static void +check_polkit_authority_cb (GObject *source_object, + GAsyncResult *res, + gpointer _data) +{ + struct check_polkit_data *data; + GError *err = NULL; + + data = (struct check_polkit_data *) _data; + if ((data->authority = polkit_authority_get_finish (res, &err)) == NULL) { + g_simple_async_report_take_gerror_in_idle (NULL, data->callback, data->user_data, err); + check_polkit_data_free (data); + return; + } + if (data->unique_name == NULL || data->action_id == NULL || + (data->subject = polkit_system_bus_name_new (data->unique_name)) == NULL) { + g_simple_async_report_error_in_idle (NULL, data->callback, data->user_data, POLKIT_ERROR, POLKIT_ERROR_FAILED, "Authorizing for '%s': failed sanity check", data->action_id); + check_polkit_data_free (data); + return; + } + polkit_authority_check_authorization (data->authority, data->subject, data->action_id, NULL, (PolkitCheckAuthorizationFlags) data->user_interaction, NULL, check_polkit_authorization_cb, data); +} + +void +check_polkit_async (const gchar *unique_name, + const gchar *action_id, + const gboolean user_interaction, + GAsyncReadyCallback callback, + gpointer user_data) +{ + struct check_polkit_data *data; + + data = g_new0 (struct check_polkit_data, 1); + data->unique_name = unique_name; + data->action_id = action_id; + data->user_interaction = user_interaction; + data->callback = callback; + data->user_data = user_data; + + polkit_authority_get_async (NULL, check_polkit_authority_cb, data); +} + enum ShellEntryType { SHELL_ENTRY_TYPE_INDENT, SHELL_ENTRY_TYPE_COMMENT, @@ -49,9 +172,9 @@ struct ShellEntry { }; gchar * -shell_utils_source_var (GFile *file, - const gchar *variable, - GError **error) +shell_source_var (GFile *file, + const gchar *variable, + GError **error) { gchar *argv[4] = { "sh", "-c", NULL, NULL }; gchar *filename = NULL, *quoted_filename = NULL; @@ -110,26 +233,27 @@ shell_entry_free (struct ShellEntry *entry) } void -shell_utils_trivial_free (ShellUtilsTrivial *trivial) +shell_parser_free (ShellParser *parser) { - if (trivial == NULL) + if (parser == NULL) return; - if (trivial->file != NULL) - g_object_unref (trivial->file); - if (trivial->filename != NULL) - g_free (trivial->filename); - if (trivial->entry_list != NULL) - g_list_free_full (trivial->entry_list, (GDestroyNotify)shell_entry_free); - g_free (trivial); + if (parser->file != NULL) + g_object_unref (parser->file); + if (parser->filename != NULL) + g_free (parser->filename); + if (parser->entry_list != NULL) + g_list_free_full (parser->entry_list, (GDestroyNotify)shell_entry_free); + g_free (parser); } -ShellUtilsTrivial * -shell_utils_trivial_new (GFile *file, - GError **error) +ShellParser * +shell_parser_new (GFile *file, + GError **error) { gchar *filebuf = NULL; GError *local_err = NULL; + ShellParser *ret = NULL; if (file == NULL) return NULL; @@ -138,10 +262,8 @@ shell_utils_trivial_new (GFile *file, if (local_err != NULL) { /* Inability to parse or open is a failure; file not existing at all is *not* a failure */ if (local_err->code == G_IO_ERROR_NOT_FOUND) { - ShellUtilsTrivial *ret = NULL; - g_error_free (local_err); - ret = g_new0 (ShellUtilsTrivial, 1); + ret = g_new0 (ShellParser, 1); g_object_ref (file); ret->file = file; ret->filename = g_file_get_path (file); @@ -155,22 +277,24 @@ shell_utils_trivial_new (GFile *file, } return NULL; } - return shell_utils_trivial_new_from_string (file, filebuf, error); + ret = shell_parser_new_from_string (file, filebuf, error); + g_free (filebuf); + return ret; } -ShellUtilsTrivial * -shell_utils_trivial_new_from_string (GFile *file, +ShellParser * +shell_parser_new_from_string (GFile *file, gchar *filebuf, GError **error) { - ShellUtilsTrivial *ret = NULL; + ShellParser *ret = NULL; GError *local_err = NULL; gchar *s; if (file == NULL || filebuf == NULL) return NULL; - ret = g_new0 (ShellUtilsTrivial, 1); + ret = g_new0 (ShellParser, 1); g_object_ref (file); ret->file = file; ret->filename = g_file_get_path (file); @@ -191,13 +315,11 @@ shell_utils_trivial_new_from_string (GFile *file, ret->entry_list = g_list_prepend (ret->entry_list, entry); s += strlen (entry->string); g_debug ("Scanned comment: ``%s''", entry->string); - g_match_info_free (match_info); - match_info = NULL; + _g_match_info_clear (&match_info); want_separator = FALSE; continue; } - g_match_info_free (match_info); - match_info = NULL; + _g_match_info_clear (&match_info); matched = g_regex_match (separator_regex, s, 0, &match_info); if (matched) { @@ -207,13 +329,11 @@ shell_utils_trivial_new_from_string (GFile *file, ret->entry_list = g_list_prepend (ret->entry_list, entry); s += strlen (entry->string); g_debug ("Scanned separator: ``%s''", entry->string); - g_match_info_free (match_info); - match_info = NULL; + _g_match_info_clear (&match_info); want_separator = FALSE; continue; } - g_match_info_free (match_info); - match_info = NULL; + _g_match_info_clear (&match_info); matched = g_regex_match (indent_regex, s, 0, &match_info); if (matched) { @@ -223,12 +343,10 @@ shell_utils_trivial_new_from_string (GFile *file, ret->entry_list = g_list_prepend (ret->entry_list, entry); s += strlen (entry->string); g_debug ("Scanned indent: ``%s''", entry->string); - g_match_info_free (match_info); - match_info = NULL; + _g_match_info_clear (&match_info); continue; } - g_match_info_free (match_info); - match_info = NULL; + _g_match_info_clear (&match_info); matched = g_regex_match (var_equals_regex, s, 0, &match_info); if (matched) { @@ -243,8 +361,7 @@ shell_utils_trivial_new_from_string (GFile *file, entry->variable = g_match_info_fetch (match_info, 1); s += strlen (entry->string); g_debug ("Scanned variable: ``%s''", entry->string); - g_match_info_free (match_info); - match_info = NULL; + _g_match_info_clear (&match_info); want_separator = TRUE; while (*s != 0) { @@ -255,26 +372,23 @@ shell_utils_trivial_new_from_string (GFile *file, if (matched2) goto append_value; - g_match_info_free (match_info); - match_info = NULL; + _g_match_info_clear (&match_info); matched2 = g_regex_match (double_quoted_regex, s, 0, &match_info); if (matched2) goto append_value; - g_match_info_free (match_info); - match_info = NULL; + _g_match_info_clear (&match_info); matched2 = g_regex_match (unquoted_regex, s, 0, &match_info); if (matched2) goto append_value; - g_match_info_free (match_info); - match_info = NULL; + _g_match_info_clear (&match_info); break; -append_value: + append_value: if (raw_value == NULL) { raw_value = g_match_info_fetch (match_info, 0); s += strlen (raw_value); @@ -288,8 +402,7 @@ append_value: g_free (temp1); g_free (temp2); } - g_match_info_free (match_info); - match_info = NULL; + _g_match_info_clear (&match_info); } if (raw_value != NULL) { @@ -307,17 +420,16 @@ append_value: continue; } -no_match: + no_match: /* Nothing matches, parsing has failed! */ - g_match_info_free (match_info); - match_info = NULL; + _g_match_info_clear (&match_info); if (local_err != NULL) g_propagate_prefixed_error (error, local_err, "Unable to parse '%s':", ret->filename); else g_propagate_error (error, g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED, "Unable to parse '%s'", ret->filename)); - shell_utils_trivial_free (ret); + shell_parser_free (ret); return NULL; } @@ -326,28 +438,28 @@ no_match: } gboolean -shell_utils_trivial_is_empty (ShellUtilsTrivial *trivial) +shell_parser_is_empty (ShellParser *parser) { - if (trivial == NULL || trivial->entry_list == NULL) + if (parser == NULL || parser->entry_list == NULL) return TRUE; return FALSE; } gboolean -shell_utils_trivial_set_variable (ShellUtilsTrivial *trivial, - const gchar *variable, - const gchar *value, - gboolean add_if_unset) +shell_parser_set_variable (ShellParser *parser, + const gchar *variable, + const gchar *value, + gboolean add_if_unset) { GList *curr = NULL; struct ShellEntry *found_entry = NULL; gchar *quoted_value = NULL; gboolean ret = FALSE; - g_assert (trivial != NULL); + g_assert (parser != NULL); g_assert (variable != NULL); - for (curr = trivial->entry_list; curr != NULL; curr = curr->next) { + for (curr = parser->entry_list; curr != NULL; curr = curr->next) { struct ShellEntry *entry; entry = (struct ShellEntry *)(curr->data); @@ -367,7 +479,7 @@ shell_utils_trivial_set_variable (ShellUtilsTrivial *trivial, found_entry->type = SHELL_ENTRY_TYPE_ASSIGNMENT; found_entry->variable = g_strdup (variable); found_entry->string = g_strdup_printf ("%s=%s", variable, quoted_value); - trivial->entry_list = g_list_append (trivial->entry_list, found_entry); + parser->entry_list = g_list_append (parser->entry_list, found_entry); ret = TRUE; } } @@ -377,16 +489,16 @@ shell_utils_trivial_set_variable (ShellUtilsTrivial *trivial, } void -shell_utils_trivial_clear_variable (ShellUtilsTrivial *trivial, - const gchar *variable) +shell_parser_clear_variable (ShellParser *parser, + const gchar *variable) { GList *curr = NULL; gboolean ret = FALSE; - g_assert (trivial != NULL); + g_assert (parser != NULL); g_assert (variable != NULL); - for (curr = trivial->entry_list; curr != NULL; ) { + for (curr = parser->entry_list; curr != NULL; ) { struct ShellEntry *entry; entry = (struct ShellEntry *)(curr->data); @@ -409,32 +521,32 @@ shell_utils_trivial_clear_variable (ShellUtilsTrivial *trivial, } gboolean -shell_utils_trivial_save (ShellUtilsTrivial *trivial, - GError **error) +shell_parser_save (ShellParser *parser, + GError **error) { gboolean ret = FALSE; GList *curr = NULL; GFileOutputStream *os; - g_assert (trivial != NULL && trivial->file != NULL && trivial->filename != NULL); - if ((os = g_file_replace (trivial->file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error)) == NULL) { - g_prefix_error (error, "Unable to save '%s': ", trivial->filename); + g_assert (parser != NULL && parser->file != NULL && parser->filename != NULL); + if ((os = g_file_replace (parser->file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, error)) == NULL) { + g_prefix_error (error, "Unable to save '%s': ", parser->filename); goto out; } - for (curr = trivial->entry_list; curr != NULL; curr = curr->next) { + for (curr = parser->entry_list; curr != NULL; curr = curr->next) { struct ShellEntry *entry; gsize written; entry = (struct ShellEntry *)(curr->data); if (!g_output_stream_write_all (G_OUTPUT_STREAM (os), entry->string, strlen (entry->string), &written, NULL, error)) { - g_prefix_error (error, "Unable to save '%s': ", trivial->filename); + g_prefix_error (error, "Unable to save '%s': ", parser->filename); goto out; } } if (!g_output_stream_close (G_OUTPUT_STREAM (os), NULL, error)) { - g_prefix_error (error, "Unable to save '%s': ", trivial->filename); + g_prefix_error (error, "Unable to save '%s': ", parser->filename); g_output_stream_close (G_OUTPUT_STREAM (os), NULL, NULL); goto out; } @@ -447,20 +559,20 @@ shell_utils_trivial_save (ShellUtilsTrivial *trivial, } gboolean -shell_utils_trivial_set_and_save (GFile *file, - GError **error, - const gchar *first_var_name, - const gchar *first_alt_var_name, - const gchar *first_value, - ...) +shell_parser_set_and_save (GFile *file, + GError **error, + const gchar *first_var_name, + const gchar *first_alt_var_name, + const gchar *first_value, + ...) { va_list ap; - ShellUtilsTrivial *trivial; + ShellParser *parser; gboolean ret = FALSE; const gchar *var_name, *alt_var_name, *value; va_start (ap, first_value); - if ((trivial = shell_utils_trivial_new (file, error)) == NULL) + if ((parser = shell_parser_new (file, error)) == NULL) goto out; var_name = first_var_name; @@ -468,56 +580,56 @@ shell_utils_trivial_set_and_save (GFile *file, value = first_value; do { if (alt_var_name == NULL) { - if (!shell_utils_trivial_set_variable (trivial, var_name, value, TRUE)) { + if (!shell_parser_set_variable (parser, var_name, value, TRUE)) { g_propagate_error (error, g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED, - "Unable to set %s in '%s'", var_name, trivial->filename)); + "Unable to set %s in '%s'", var_name, parser->filename)); goto out; } } else { - if (!shell_utils_trivial_set_variable (trivial, var_name, value, FALSE) && - !shell_utils_trivial_set_variable (trivial, alt_var_name, value, FALSE) && - !shell_utils_trivial_set_variable (trivial, var_name, value, TRUE)) { + if (!shell_parser_set_variable (parser, var_name, value, FALSE) && + !shell_parser_set_variable (parser, alt_var_name, value, FALSE) && + !shell_parser_set_variable (parser, var_name, value, TRUE)) { g_propagate_error (error, g_error_new (G_FILE_ERROR, G_FILE_ERROR_FAILED, - "Unable to set %s or %s in '%s'", var_name, alt_var_name, trivial->filename)); + "Unable to set %s or %s in '%s'", var_name, alt_var_name, parser->filename)); goto out; } } } while ((var_name = va_arg (ap, const gchar*)) != NULL ? alt_var_name = va_arg (ap, const gchar*), value = va_arg (ap, const gchar*), 1 : 0); - if (!shell_utils_trivial_save (trivial, error)) + if (!shell_parser_save (parser, error)) goto out; ret = TRUE; out: va_end (ap); - if (trivial != NULL) - shell_utils_trivial_free (trivial); + if (parser != NULL) + shell_parser_free (parser); return ret; } gchar ** -shell_utils_trivial_source_var_list (GFile *file, - const gchar * const *var_names, - GError **error) +shell_parser_source_var_list (GFile *file, + const gchar * const *var_names, + GError **error) { - ShellUtilsTrivial *trivial; + ShellParser *parser; gchar **ret = NULL, **value; const gchar* const* var_name; if (var_names == NULL) return NULL; - if ((trivial = shell_utils_trivial_new (file, error)) == NULL) + if ((parser = shell_parser_new (file, error)) == NULL) return NULL; ret = g_new0 (gchar *, g_strv_length ((gchar **)var_names) + 1); for (var_name = var_names, value = ret; *var_name != NULL; var_name++, value++) { GList *curr; - for (curr = trivial->entry_list; curr != NULL; curr = curr->next) { + for (curr = parser->entry_list; curr != NULL; curr = curr->next) { struct ShellEntry *entry; entry = (struct ShellEntry *)(curr->data); @@ -525,12 +637,12 @@ shell_utils_trivial_source_var_list (GFile *file, *value = g_strdup (entry->unquoted_value); } } - shell_utils_trivial_free (trivial); + shell_parser_free (parser); return ret; } void -shell_utils_destroy (void) +utils_destroy (void) { if (indent_regex != NULL) { g_regex_unref (indent_regex); @@ -563,7 +675,7 @@ shell_utils_destroy (void) } void -shell_utils_init (void) +utils_init (void) { if (indent_regex == NULL) { indent_regex = g_regex_new ("^[ \\t]+", G_REGEX_ANCHORED, 0, NULL); diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..bf03d3e --- /dev/null +++ b/src/utils.h @@ -0,0 +1,102 @@ +/* + Copyright 2012 Alexandre Rostovtsev + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _SHELL_UTILS_H_ +#define _SHELL_UTILS_H_ + +#include <glib.h> +#include <gio/gio.h> + +typedef struct _ShellParser ShellParser; + +struct _ShellParser +{ + GFile *file; + gchar *filename; + GList *entry_list; +}; + +/* Always return TRUE */ +gboolean +_g_match_info_clear (GMatchInfo **match_info); + +void +check_polkit_async (const gchar *unique_name, + const gchar *action_id, + const gboolean user_interaction, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean +check_polkit_finish (GAsyncResult *res, + GError **error); + +gchar * +shell_source_var (GFile *file, + const gchar *variable, + GError **error); + +ShellParser * +shell_parser_new (GFile *file, + GError **error); + +ShellParser * +shell_parser_new_from_string (GFile *file, + gchar *filebuf, + GError **error); + +void +shell_parser_free (ShellParser *parser); + +gboolean +shell_parser_is_empty (ShellParser *parser); + +gboolean +shell_parser_set_variable (ShellParser *parser, + const gchar *variable, + const gchar *value, + gboolean add_if_unset); + +void +shell_parser_clear_variable (ShellParser *parser, + const gchar *variable); + +gboolean +shell_parser_save (ShellParser *parser, + GError **error); + +gboolean +shell_parser_set_and_save (GFile *file, + GError **error, + const gchar *first_var_name, + const gchar *first_alt_var_name, + const gchar *first_value, + ...); + +gchar ** +shell_parser_source_var_list (GFile *file, + const gchar * const *var_names, + GError **error); + +void +utils_init (void); + +void +utils_destroy (void); + +#endif |