diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Makefile.am | 30 | ||||
-rw-r--r-- | common/gdm-common-config.c | 398 | ||||
-rw-r--r-- | common/gdm-common-config.h | 71 | ||||
-rw-r--r-- | common/gdm-common.c | 374 | ||||
-rw-r--r-- | common/gdm-common.h | 102 | ||||
-rw-r--r-- | common/ve-signal.c | 160 | ||||
-rw-r--r-- | common/ve-signal.h | 46 |
7 files changed, 1181 insertions, 0 deletions
diff --git a/common/Makefile.am b/common/Makefile.am new file mode 100644 index 00000000..63f670e9 --- /dev/null +++ b/common/Makefile.am @@ -0,0 +1,30 @@ +## Process this file with automake to produce Makefile.in + +NULL = + +INCLUDES = \ + -I. \ + -I.. \ + -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \ + $(GLIB_CFLAGS) + +noinst_LIBRARIES = \ + libgdmcommon.a \ + $(null) + +libgdmcommon_a_SOURCES = \ + gdm-common.h \ + gdm-common.c \ + gdm-common-config.h \ + gdm-common-config.c \ + ve-signal.h \ + ve-signal.c \ + $(NULL) + +libgdmcommon_ui_a_SOURCES = \ + $(libgdmcommon_a_SOURCES) \ + glade-helper.c \ + glade-helper.h \ + gdm-common-ui.c \ + gdm-common-ui.h \ + $(NULL) diff --git a/common/gdm-common-config.c b/common/gdm-common-config.c new file mode 100644 index 00000000..42f06777 --- /dev/null +++ b/common/gdm-common-config.c @@ -0,0 +1,398 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <locale.h> +#include <syslog.h> + +#include <glib.h> + +#include "gdm-common-config.h" + +gboolean +gdm_common_config_parse_key_string (const char *keystring, + char **group, + char **key, + char **value) +{ + char **split1; + char **split2; + char *g; + char *k; + char *v; + gboolean ret; + + ret = FALSE; + g = k = v = NULL; + split1 = split2 = NULL; + + split1 = g_strsplit (keystring, "/", 2); + if (split1 == NULL) { + goto out; + } + + g = split1 [0]; + + split2 = g_strsplit (split1 [1], "=", 2); + if (split2 == NULL) { + k = split1 [1]; + } else { + k = split2 [0]; + v = split2 [1]; + } + + ret = TRUE; + out: + if (group != NULL) { + *group = g_strdup (g); + } + if (key != NULL) { + *key = g_strdup (k); + } + if (value != NULL) { + *value = g_strdup (v); + } + + g_strfreev (split1); + g_strfreev (split2); + + return ret; +} + +GKeyFile * +gdm_common_config_load (const char *filename, + GError **error) +{ + GKeyFile *config; + GError *local_error; + gboolean res; + + config = g_key_file_new (); + + local_error = NULL; + res = g_key_file_load_from_file (config, + filename, + G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, + &local_error); + if (! res) { + g_propagate_error (error, local_error); + g_key_file_free (config); + return NULL; + } + + return config; +} + +gboolean +gdm_common_config_save (GKeyFile *config, + const char *filename, + GError **error) +{ + GError *local_error; + gboolean res; + char *contents; + gsize length; + + local_error = NULL; + contents = g_key_file_to_data (config, &length, &local_error); + if (local_error != NULL) { + g_propagate_error (error, local_error); + return FALSE; + } + + local_error = NULL; + res = g_file_set_contents (filename, + contents, + length, + &local_error); + if (local_error != NULL) { + g_propagate_error (error, local_error); + g_free (contents); + return FALSE; + } + + g_free (contents); + return TRUE; +} + +gboolean +gdm_common_config_get_int (GKeyFile *config, + const char *keystring, + int *value, + GError **error) +{ + char *group; + char *key; + char *default_value; + int val; + GError *local_error; + + group = key = default_value = NULL; + if (! gdm_common_config_parse_key_string (keystring, &group, &key, &default_value)) + return FALSE; + + local_error = NULL; + val = g_key_file_get_integer (config, + group, + key, + &local_error); + if (local_error != NULL) { + /* use the default */ + if (default_value != NULL) { + val = atoi (default_value); + } else { + val = 0; + } + g_propagate_error (error, local_error); + } + + *value = val; + + g_free (key); + g_free (group); + g_free (default_value); + + return TRUE; +} + +gboolean +gdm_common_config_get_translated_string (GKeyFile *config, + const char *keystring, + char **value, + GError **error) +{ + char *group; + char *key; + char *default_value; + char *val; + const char * const *langs; + int i; + + val = NULL; + + group = key = default_value = NULL; + if (! gdm_common_config_parse_key_string (keystring, &group, &key, &default_value)) + return FALSE; + + langs = g_get_language_names (); + + for (i = 0; langs[i] != NULL; i++) { + const char *locale; + locale = langs[i]; + + val = g_key_file_get_locale_string (config, + group, + key, + locale, + NULL); + if (val != NULL) { + break; + } + } + + if (val == NULL) { + /* use the default */ + val = g_strdup (default_value); + } + + *value = val; + + g_free (key); + g_free (group); + g_free (default_value); + + return TRUE; +} + +gboolean +gdm_common_config_get_string (GKeyFile *config, + const char *keystring, + char **value, + GError **error) +{ + char *group; + char *key; + char *default_value; + char *val; + GError *local_error; + + group = key = default_value = NULL; + if (! gdm_common_config_parse_key_string (keystring, &group, &key, &default_value)) { + g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE, "Unable to parse key: %s", keystring); + return FALSE; + } + + local_error = NULL; + val = g_key_file_get_string (config, + group, + key, + &local_error); + if (local_error != NULL) { + /* use the default */ + val = g_strdup (default_value); + g_propagate_error (error, local_error); + } + + *value = val; + + g_free (key); + g_free (group); + g_free (default_value); + + return TRUE; +} + +gboolean +gdm_common_config_get_boolean (GKeyFile *config, + const char *keystring, + gboolean *value, + GError **error) +{ + char *group; + char *key; + char *default_value; + gboolean val; + GError *local_error; + + group = key = default_value = NULL; + if (! gdm_common_config_parse_key_string (keystring, &group, &key, &default_value)) + return FALSE; + + local_error = NULL; + val = g_key_file_get_boolean (config, + group, + key, + &local_error); + if (local_error != NULL) { + /* use the default */ + if (default_value != NULL && + (default_value[0] == 'T' || + default_value[0] == 't' || + default_value[0] == 'Y' || + default_value[0] == 'y' || + atoi (default_value) != 0)) { + val = TRUE; + } else { + val = FALSE; + } + g_propagate_error (error, local_error); + } + + *value = val; + + g_free (key); + g_free (group); + g_free (default_value); + + return TRUE; +} + +void +gdm_common_config_set_string (GKeyFile *config, + const char *keystring, + const char *value) +{ + char *group; + char *key; + char *default_value; + + group = key = default_value = NULL; + if (! gdm_common_config_parse_key_string (keystring, &group, &key, &default_value)) { + return; + } + + g_key_file_set_string (config, group, key, value); + + g_free (key); + g_free (group); + g_free (default_value); +} + +void +gdm_common_config_set_boolean (GKeyFile *config, + const char *keystring, + gboolean value) +{ + char *group; + char *key; + char *default_value; + + group = key = default_value = NULL; + if (! gdm_common_config_parse_key_string (keystring, &group, &key, &default_value)) { + return; + } + + g_key_file_set_boolean (config, group, key, value); + + g_free (key); + g_free (group); + g_free (default_value); +} + +void +gdm_common_config_set_int (GKeyFile *config, + const char *keystring, + int value) +{ + char *group; + char *key; + char *default_value; + + group = key = default_value = NULL; + if (! gdm_common_config_parse_key_string (keystring, &group, &key, &default_value)) { + return; + } + + g_key_file_set_integer (config, group, key, value); + + g_free (key); + g_free (group); + g_free (default_value); +} + +void +gdm_common_config_remove_key (GKeyFile *config, + const char *keystring, + GError **error) +{ + char *group; + char *key; + char *default_value; + GError *local_error; + + group = key = default_value = NULL; + if (! gdm_common_config_parse_key_string (keystring, &group, &key, &default_value)) { + return; + } + + local_error = NULL; + g_key_file_remove_key (config, group, key, &local_error); + if (local_error != NULL) { + g_propagate_error (error, local_error); + } + + g_free (key); + g_free (group); + g_free (default_value); +} diff --git a/common/gdm-common-config.h b/common/gdm-common-config.h new file mode 100644 index 00000000..1243ac81 --- /dev/null +++ b/common/gdm-common-config.h @@ -0,0 +1,71 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GDM_COMMON_CONFIG_H +#define _GDM_COMMON_CONFIG_H + +#include <glib.h> + +G_BEGIN_DECLS + +GKeyFile * gdm_common_config_load (const char *filename, + GError **error); +gboolean gdm_common_config_save (GKeyFile *config, + const char *filename, + GError **error); + +gboolean gdm_common_config_get_string (GKeyFile *config, + const char *keystring, + char **value, + GError **error); +gboolean gdm_common_config_get_translated_string (GKeyFile *config, + const char *keystring, + char **value, + GError **error); +gboolean gdm_common_config_get_int (GKeyFile *config, + const char *keystring, + int *value, + GError **error); +gboolean gdm_common_config_get_boolean (GKeyFile *config, + const char *keystring, + gboolean *value, + GError **error); +gboolean gdm_common_config_parse_key_string (const char *keystring, + char **group, + char **key, + char **value); + +void gdm_common_config_set_string (GKeyFile *config, + const char *keystring, + const char *value); +void gdm_common_config_set_boolean (GKeyFile *config, + const char *keystring, + gboolean value); +void gdm_common_config_set_int (GKeyFile *config, + const char *keystring, + int value); + +void gdm_common_config_remove_key (GKeyFile *config, + const char *keystring, + GError **error); + +G_END_DECLS + +#endif /* _GDM_COMMON_CONFIG_H */ diff --git a/common/gdm-common.c b/common/gdm-common.c new file mode 100644 index 00000000..ad4b58a3 --- /dev/null +++ b/common/gdm-common.c @@ -0,0 +1,374 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * (c) 2000 Eazel, Inc. + * (c) 2001,2002 George Lebl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <locale.h> + +#ifdef HAVE_CRT_EXTERNS_H +#include <crt_externs.h> +#endif + +#include "gdm-common.h" + +/** + * ve_clearenv: + * + * Description: Clears out the environment completely. + * In case there is no native implementation of clearenv, + * this could cause leaks depending on the implementation + * of environment. + * + **/ +void +ve_clearenv (void) +{ +#ifdef HAVE_CLEARENV + clearenv (); +#else + +#ifdef HAVE__NSGETENVIRON +#define environ (*_NSGetEnviron()) +#else + extern char **environ; +#endif + + if (environ != NULL) + environ[0] = NULL; +#endif +} + +char * +ve_first_word (const char *s) +{ + int argc; + char **argv; + char *ret; + + if (s == NULL) + return NULL; + + if ( ! g_shell_parse_argv (s, &argc, &argv, NULL)) { + char *p; + ret = g_strdup (s); + p = strchr (ret, ' '); + if (p != NULL) + *p = '\0'; + return ret; + } + + ret = g_strdup (argv[0]); + + g_strfreev (argv); + + return ret; +} + +gboolean +ve_first_word_executable (const char *s, gboolean only_existance) +{ + char *bin = ve_first_word (s); + if (bin == NULL) + return FALSE; + if (g_access (bin, only_existance ? F_OK : X_OK) == 0) { + g_free (bin); + return TRUE; + } else { + g_free (bin); + return FALSE; + } +} + +char * +ve_get_first_working_command (const char *list, + gboolean only_existance) +{ + int i; + char **vector; + char *ret = NULL; + + if (list == NULL) + return NULL; + + vector = g_strsplit (list, ";", -1); + for (i = 0; vector[i] != NULL; i++) { + if (ve_first_word_executable (vector[i], + only_existance)) { + ret = g_strdup (vector[i]); + break; + } + } + g_strfreev (vector); + return ret; +} + +char * +ve_rest (const char *s) +{ + const char *p; + gboolean single_quot = FALSE; + gboolean double_quot = FALSE; + gboolean escape = FALSE; + + if (s == NULL) + return NULL; + + for (p = s; *p != '\0'; p++) { + if (single_quot) { + if (*p == '\'') { + single_quot = FALSE; + } + } else if (escape) { + escape = FALSE; + } else if (double_quot) { + if (*p == '"') { + double_quot = FALSE; + } else if (*p == '\\') { + escape = TRUE; + } + } else if (*p == '\'') { + single_quot = TRUE; + } else if (*p == '"') { + double_quot = TRUE; + } else if (*p == '\\') { + escape = TRUE; + } else if (*p == ' ' || *p == '\t') { + while (*p == ' ' || *p == '\t') + p++; + return g_strdup (p); + } + } + + return NULL; +} + +gboolean +ve_bool_equal (gboolean a, gboolean b) +{ + if ((a && b) || (!a && !b)) + return TRUE; + else + return FALSE; +} + +gboolean +ve_is_string_in_list (const GList *list, const char *string) +{ + g_return_val_if_fail (string != NULL, FALSE); + + while (list != NULL) { + if (list->data != NULL && + strcmp (string, list->data) == 0) + return TRUE; + + list = list->next; + } + + return FALSE; +} + +gboolean +ve_is_string_in_list_case_no_locale (const GList *list, const char *string) +{ + g_return_val_if_fail (string != NULL, FALSE); + + while (list != NULL) { + if (list->data != NULL && + g_ascii_strcasecmp (string, list->data) == 0) + return TRUE; + + list = list->next; + } + + return FALSE; +} + +char * +ve_find_file_simple (const char *filename, const GList *directories) +{ + char *s; + const GList *li; + + if (filename == NULL) + return NULL; + + if (g_access (filename, F_OK) == 0) + return g_strdup (filename); + + /* an absolute path is just checked */ + if (g_path_is_absolute (filename)) + return NULL; + + for (li = directories; li != NULL; li = li->next) { + s = g_build_filename (li->data, filename, NULL); + if (g_access (s, F_OK) == 0) + return s; + g_free (s); + } + + return NULL; +} + +char * +ve_locale_to_utf8 (const char *str) +{ + char *ret = g_locale_to_utf8 (str, -1, NULL, NULL, NULL); + if (ret == NULL) { + g_warning ("string not in proper locale encoding: \"%s\"", str); + return g_strdup (str); + } else { + return ret; + } +} + +char * +ve_locale_from_utf8 (const char *str) +{ + char *ret = g_locale_from_utf8 (str, -1, NULL, NULL, NULL); + if (ret == NULL) { + g_warning ("string not in proper utf8 encoding: \"%s\"", str); + return g_strdup (str); + } else { + return ret; + } +} + +char * +ve_filename_to_utf8 (const char *str) +{ + char *ret = g_filename_to_utf8 (str, -1, NULL, NULL, NULL); + if (ret == NULL) { + g_warning ("string not in proper locale encoding: \"%s\"", str); + return g_strdup (str); + } else { + return ret; + } +} + +char * +ve_filename_from_utf8 (const char *str) +{ + char *ret = g_filename_from_utf8 (str, -1, NULL, NULL, NULL); + if (ret == NULL) { + g_warning ("string not in proper utf8 encoding: \"%s\"", str); + return g_strdup (str); + } else { + return ret; + } +} + +char * +ve_strftime (struct tm *the_tm, const char *format) +{ + char str[1024]; + char *loc_format = ve_locale_from_utf8 (format); + + if (strftime (str, sizeof (str)-1, loc_format, the_tm) == 0) { + /* according to docs, if the string does not fit, the + * contents of str are undefined, thus just use + * ??? */ + strcpy (str, "???"); + } + str [sizeof (str)-1] = '\0'; /* just for sanity */ + g_free (loc_format); + + return ve_locale_to_utf8 (str); +} + +pid_t +ve_waitpid_no_signal (pid_t pid, int *status, int options) +{ + pid_t ret; + + for (;;) { + ret = waitpid (pid, status, options); + if (ret == 0) + return 0; + if (errno != EINTR) + return ret; + } +} + +gboolean +ve_locale_exists (const char *loc) +{ + gboolean ret; + char *old = g_strdup (setlocale (LC_MESSAGES, NULL)); + if (setlocale (LC_MESSAGES, loc) != NULL) + ret = TRUE; + else + ret = FALSE; + setlocale (LC_MESSAGES, old); + g_free (old); + return ret; +} + +char * +ve_find_prog_in_path (const char *prog, const char *path) +{ + char **vec; + int i; + + if (ve_string_empty (prog) || ve_string_empty (path)) + return NULL; + + vec = g_strsplit (path, ":", -1); + for (i = 0; vec != NULL && vec[i] != NULL; i++) { + char *full = g_build_filename (vec[i], prog, NULL); + /* Do not use X_OK, we may be looking for things + that are not executables */ + if (g_access (full, F_OK) == 0) { + g_strfreev(vec); + return full; + } + g_free (full); + } + g_strfreev(vec); + return NULL; +} + +gboolean +ve_is_prog_in_path (const char *prog, const char *path) +{ + char *full = ve_find_prog_in_path (prog, path); + if (full != NULL) { + g_free (full); + return TRUE; + } else { + return FALSE; + } +} + +char * +ve_shell_quote_filename (const char *name) +{ + if (name[0] != '-') { + return g_shell_quote (name); + } else { + char *fname = g_strconcat ("./", name, NULL); + char *quoted = g_shell_quote (fname); + g_free (fname); + return quoted; + } +} diff --git a/common/gdm-common.h b/common/gdm-common.h new file mode 100644 index 00000000..92dd8108 --- /dev/null +++ b/common/gdm-common.h @@ -0,0 +1,102 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * (c) 2000 Eazel, Inc. + * (c) 2001,2002 George Lebl + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GDM_COMMON_H +#define _GDM_COMMON_H + +#include <glib.h> +#include <glib/gstdio.h> +#include <time.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <locale.h> + +#include "ve-signal.h" +#include "gdm-common-config.h" + +G_BEGIN_DECLS +void ve_clearenv (void); +char * ve_first_word (const char *s); +gboolean ve_first_word_executable (const char *s, + gboolean only_existance); +char * ve_rest (const char *s); + +/* Gets the first existing command out of a list separated by semicolons */ +char * ve_get_first_working_command (const char *list, + gboolean only_existance); + +gboolean ve_bool_equal (gboolean a, gboolean b); + +gboolean ve_is_string_in_list (const GList *list, + const char *string); +gboolean ve_is_string_in_list_case_no_locale (const GList *list, + const char *string); + +#define ve_string_empty(x) ((x)==NULL||(x)[0]=='\0') +#define ve_sure_string(x) ((x)!=NULL?(x):"") + +/* Find a file using the specified list of directories, an absolute path is + * just checked, whereas a relative path is search in the given directories, + */ +char * ve_find_file_simple (const char *filename, + const GList *directories); + +/* Find a file using the specified list of directories, an absolute path is + * just checked, whereas a relative path is search in the given directories, + * gnome_datadir, g_get_prgname() subdirectory, in GNOME_PATH + * under /share/ and /share/<g_get_prgname()> */ +char * ve_find_file (const char *filename, + const GList *directories); + +/* These two functions will ALWAYS return a non-NULL string, + * if there is an error, they return the unconverted string */ +char * ve_locale_to_utf8 (const char *str); +char * ve_locale_from_utf8 (const char *str); + +/* These two functions will ALWAYS return a non-NULL string, + * if there is an error, they return the unconverted string */ +char * ve_filename_to_utf8 (const char *str); +char * ve_filename_from_utf8 (const char *str); + +/* works with utf-8 strings and always returns something */ +char * ve_strftime (struct tm *the_tm, const char *format); + +/* function which doesn't stop on signals */ +pid_t ve_waitpid_no_signal (pid_t pid, int *status, int options); + +/* Testing for existance of a certain locale */ +gboolean ve_locale_exists (const char *loc); + +char * ve_find_prog_in_path (const char *prog, const char *path); +gboolean ve_is_prog_in_path (const char *prog, const char *path); + +char *ve_shell_quote_filename (const char *name); + +#define VE_IGNORE_EINTR(expr) \ + do { \ + errno = 0; \ + expr; \ + } while G_UNLIKELY (errno == EINTR); + +G_END_DECLS + +#endif /* _GDM_COMMON_H */ diff --git a/common/ve-signal.c b/common/ve-signal.c new file mode 100644 index 00000000..76f7ed4e --- /dev/null +++ b/common/ve-signal.c @@ -0,0 +1,160 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Signal routines + * + * (c) 2000, 2002 Queen of England + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "config.h" + +#include <signal.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <glib.h> +#include <glib/gi18n.h> + +#include "ve-signal.h" + +typedef struct _SignalSource SignalSource; +struct _SignalSource { + GSource source; + + int signal; + guint8 index; + guint8 shift; +}; + +static guint32 signals_notified[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +static gboolean +ve_signal_prepare (GSource *source, + int *timeout) +{ + SignalSource *ss = (SignalSource *)source; + + return signals_notified[ss->index] & (1 << ss->shift); +} + +static gboolean +ve_signal_check (GSource *source) +{ + SignalSource *ss = (SignalSource *)source; + + return signals_notified[ss->index] & (1 << ss->shift); +} + +static gboolean +ve_signal_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + SignalSource *ss = (SignalSource *)source; + + signals_notified[ss->index] &= ~(1 << ss->shift); + + return ((VeSignalFunc)callback) (ss->signal, user_data); +} + +static GSourceFuncs signal_funcs = { + ve_signal_prepare, + ve_signal_check, + ve_signal_dispatch +}; + +guint +ve_signal_add (int signal, + VeSignalFunc function, + gpointer data) +{ + return ve_signal_add_full (G_PRIORITY_DEFAULT, signal, function, data, NULL); +} + +guint +ve_signal_add_full (int priority, + int signal, + VeSignalFunc function, + gpointer data, + GDestroyNotify destroy) +{ + GSource *source; + SignalSource *ss; + guint s = 128 + signal; + + g_return_val_if_fail (function != NULL, 0); + + source = g_source_new (&signal_funcs, sizeof (SignalSource)); + ss = (SignalSource *)source; + + ss->signal = signal; + ss->index = s / 32; + ss->shift = s % 32; + + g_assert (ss->index < 8); + + g_source_set_priority (source, priority); + g_source_set_callback (source, (GSourceFunc)function, data, destroy); + g_source_set_can_recurse (source, TRUE); + + return g_source_attach (source, NULL); +} + +void +ve_signal_notify (int signal) +{ + guint index, shift; + guint s = 128 + signal; + + index = s / 32; + shift = s % 32; + + g_assert (index < 8); + + signals_notified[index] |= 1 << shift; + + g_main_context_wakeup (NULL); +} + +gboolean +ve_signal_was_notified (int signal) +{ + guint index, shift; + guint s = 128 + signal; + + index = s / 32; + shift = s % 32; + + g_assert (index < 8); + + return ((signals_notified[index]) & (1 << shift)) ? TRUE : FALSE; +} + +void +ve_signal_unnotify (int signal) +{ + guint index, shift; + guint s = 128 + signal; + + index = s / 32; + shift = s % 32; + + g_assert (index < 8); + + signals_notified[index] &= ~(1 << shift); +} diff --git a/common/ve-signal.h b/common/ve-signal.h new file mode 100644 index 00000000..f8f4c4c3 --- /dev/null +++ b/common/ve-signal.h @@ -0,0 +1,46 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Signal routines + * + * (c) 2000, 2002 Queen of England + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _VE_SIGNAL_H +#define _VE_SIGNAL_H + +#include <glib.h> + +typedef gboolean (*VeSignalFunc) (int signal, + gpointer data); +guint ve_signal_add (int signal, + VeSignalFunc function, + gpointer data); +guint ve_signal_add_full (int priority, + int signal, + VeSignalFunc function, + gpointer data, + GDestroyNotify destroy); +/* You must handle the signal notify yourself, you add + * this function as the signal notification function + * however */ +void ve_signal_notify (int signal); + +gboolean ve_signal_was_notified (int signal); +void ve_signal_unnotify (int signal); + +#endif /* _VE_CONFIG_H */ |