[monkey-bubble: 1/753] Initial revision
- From: Sven Herzberg <herzi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [monkey-bubble: 1/753] Initial revision
- Date: Wed, 14 Jul 2010 21:55:46 +0000 (UTC)
commit ac21e25d96c21b9a2d1eef92a9d0ffa1da3c87e0
Author: Elliot Lee <sopwith src gnome org>
Date: Mon Nov 24 22:32:10 1997 +0000
Initial revision
libgnome/.cvsignore | 6 +
libgnome/Makefile.am | 42 +++
libgnome/gnome-config.c | 645 +++++++++++++++++++++++++++++++++++++++++++++
libgnome/gnome-config.h | 39 +++
libgnome/gnome-defs.h | 7 +
libgnome/gnome-dentry.c | 199 ++++++++++++++
libgnome/gnome-dentry.h | 30 ++
libgnome/gnome-dns.c | 517 ++++++++++++++++++++++++++++++++++++
libgnome/gnome-dns.h | 80 ++++++
libgnome/gnome-hook.c | 85 ++++++
libgnome/gnome-hook.h | 22 ++
libgnome/gnome-i18n.h | 33 +++
libgnome/gnome-init.c | 36 +++
libgnome/gnome-mime.c | 273 +++++++++++++++++++
libgnome/gnome-mime.h | 34 +++
libgnome/gnome-string.c | 92 +++++++
libgnome/gnome-string.h | 10 +
libgnome/gnome-triggers.c | 362 +++++++++++++++++++++++++
libgnome/gnome-triggers.h | 49 ++++
libgnome/gnome-util.c | 231 ++++++++++++++++
libgnome/gnome-util.h | 25 ++
libgnome/gnomelib-init.c | 36 +++
libgnome/libgnome.h | 19 ++
23 files changed, 2872 insertions(+), 0 deletions(-)
---
diff --git a/libgnome/.cvsignore b/libgnome/.cvsignore
new file mode 100644
index 0000000..2485b2b
--- /dev/null
+++ b/libgnome/.cvsignore
@@ -0,0 +1,6 @@
+Makefile.in
+Makefile
+*.lo
+*.la
+.deps
+_libs
diff --git a/libgnome/Makefile.am b/libgnome/Makefile.am
new file mode 100644
index 0000000..e16f804
--- /dev/null
+++ b/libgnome/Makefile.am
@@ -0,0 +1,42 @@
+## Process this file with automake to produce Makefile.in
+
+LINK = $(LIBTOOL) --mode=link $(CC) $(CFLAGS) $(LDFLAGS) -o $@
+
+libgnomeincludedir = $(includedir)/libgnome
+
+INCLUDES = -I.. -I$(srcdir)/.. -I$(includedir) \
+ -DGNOMELIBDIR=\""$(libdir)"\" \
+ -DGNOMEDATADIR=\""$(datadir)"\" \
+ -DGNOMELOCALEDIR=\""$(libdir)/locale\"" \
+ -I$(top_srcdir)/intl \
+ -I$(srcdir)/../programs
+
+lib_LTLIBRARIES = libgnome.la
+
+libgnome_la_SOURCES = \
+ gnome-hook.c \
+ gnome-util.c \
+ gnome-config.c \
+ gnomelib-init.c \
+ gnome-dentry.c \
+ gnome-dns.c \
+ gnome-mime.c \
+ gnome-string.c \
+ gnome-triggers.c
+
+libgnomeinclude_HEADERS = \
+ gnome-config.h \
+ gnome-defs.h \
+ gnome-hook.h \
+ gnome-util.h \
+ gnome-dns.h \
+ gnome-dentry.h \
+ gnome-i18n.h \
+ gnome-mime.h \
+ gnome-triggers.h \
+ gnome-string.h \
+ libgnome.h
+
+
+libgnome_la_LDFLAGS = -version-info 0:0:0 -rpath $(libdir)
+libgnome_la_LIBADD = -lgdk -lglib -lm
diff --git a/libgnome/gnome-config.c b/libgnome/gnome-config.c
new file mode 100644
index 0000000..314f0a3
--- /dev/null
+++ b/libgnome/gnome-config.c
@@ -0,0 +1,645 @@
+/*
+ * Configuration-File Functions.
+ *
+ * Copyright 1993, 1994, 1997 The Free Software Foundation
+ *
+ * Authors: Miguel de Icaza
+
+ This program is g_free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the G_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 G_Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ DOC: gnome configuration routines.
+
+ All of the routines receive a pathname, the pathname has the following
+ form:
+
+ /filename/section/key[=default]
+
+ This format reprensents: a filename relative to the Gnome config
+ directory called filename (ie, ~/.gnome/filename), in that file there
+ is a section called [section] and key is the left handed side of the
+ values.
+
+ If default is provided, it cane be used to return a default value
+ if none is specified on the config file.
+
+ Examples:
+
+ /gmix/Balance/Ratio=0.5
+ /filemanager/Panel Display/html=1
+
+ If the pathname starts with '=', then instead of being a ~/.gnome relative
+ file, it is an abolute pathname, example:
+
+ =/home/miguel/.mc.ini=/Left Panel/reverse=1
+
+ This reprensents the config file: /home/miguel/.mc.ini, section [Left Panel],
+ variable reverse.
+
+ */
+
+/* #include <config.h> */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h> /* For g_free() and atoi() */
+#include <sys/types.h>
+#include <glib.h>
+#include "libgnome.h"
+
+#define STRSIZE 4096
+#define overflow (next == &CharBuffer [STRSIZE-1])
+
+enum {
+ FirstBrace,
+ OnSecHeader,
+ IgnoreToEOL,
+ KeyDef,
+ KeyDefOnKey,
+ KeyValue
+};
+
+typedef enum {
+ LOOKUP,
+ SET
+} access_type;
+
+typedef struct TKeys {
+ char *key_name;
+ char *value;
+ struct TKeys *link;
+} TKeys;
+
+typedef struct TSecHeader {
+ char *section_name;
+ TKeys *keys;
+ struct TSecHeader *link;
+} TSecHeader;
+
+typedef struct TProfile {
+ char *filename;
+ TSecHeader *section;
+ struct TProfile *link;
+} TProfile;
+
+typedef struct {
+ char *file, *section, *key, *def;
+ char *path, *opath;
+} ParsedPath;
+
+/*
+ * Prefix for all the configuration operations
+ * iff the path does not begin with / or with #
+ */
+static char *prefix;
+
+static TProfile *Current = 0;
+
+/*
+ * This one keeps track of all of the opened files
+ */
+static TProfile *Base = 0;
+
+static void
+release_path (ParsedPath *p)
+{
+ g_free (p->opath);
+ g_free (p);
+}
+
+static ParsedPath *
+parse_path (char *path)
+{
+ ParsedPath *p = g_malloc (sizeof (ParsedPath));
+ char *sep;
+
+ g_assert(path != NULL);
+
+ if (*path == '/' || prefix == NULL)
+ p->opath = strdup (path);
+ else
+ p->opath = g_copy_strings (prefix, path, NULL);
+
+ p->path = p->opath;
+
+ if (*p->path == '='){
+ sep = "=";
+ p->path++;
+ } else
+ sep = "/=";
+
+ p->file = strtok (p->path, sep);
+ p->section = strtok (NULL, "/=");
+ p->key = strtok (NULL, "=");
+ p->def = strtok (NULL, "=");
+
+ /* Was it a Gnome-relative pathname? */
+ if (*sep == '/'){
+ char *f = g_concat_dir_and_file (gnome_user_dir, p->file);
+ p->file = f;
+ }
+ return p;
+}
+
+static int
+is_loaded (char *filename, TSecHeader **section)
+{
+ TProfile *p = Base;
+
+ while (p){
+ if (!strcasecmp (filename, p->filename)){
+ Current = p;
+ *section = p->section;
+ return 1;
+ }
+ p = p->link;
+ }
+ return 0;
+}
+
+static TSecHeader *
+load (char *file)
+{
+ FILE *f;
+ int state;
+ TSecHeader *SecHeader = 0;
+ char CharBuffer [STRSIZE];
+ char *next = ""; /* Not needed */
+ int c;
+
+ if ((f = fopen (file, "r"))==NULL)
+ return NULL;
+
+ state = FirstBrace;
+ while ((c = getc (f)) != EOF){
+ if (c == '\r') /* Ignore Carriage Return */
+ continue;
+
+ switch (state){
+
+ case OnSecHeader:
+ if (c == ']' || overflow){
+ *next = '\0';
+ next = CharBuffer;
+ SecHeader->section_name = strdup (CharBuffer);
+ state = IgnoreToEOL;
+ } else
+ *next++ = c;
+ break;
+
+ case IgnoreToEOL:
+ if (c == '\n'){
+ state = KeyDef;
+ next = CharBuffer;
+ }
+ break;
+
+ case FirstBrace:
+ case KeyDef:
+ case KeyDefOnKey:
+ if (c == '['){
+ TSecHeader *temp;
+
+ temp = SecHeader;
+ SecHeader = (TSecHeader *) g_malloc (sizeof (TSecHeader));
+ SecHeader->link = temp;
+ SecHeader->keys = 0;
+ state = OnSecHeader;
+ next = CharBuffer;
+ break;
+ }
+ /* On first pass, don't allow dangling keys */
+ if (state == FirstBrace)
+ break;
+
+ if ((c == ' ' && state != KeyDefOnKey) || c == '\t')
+ break;
+
+ if (c == '\n' || overflow) /* Abort Definition */
+ next = CharBuffer;
+
+ if (c == '=' || overflow){
+ TKeys *temp;
+
+ temp = SecHeader->keys;
+ *next = '\0';
+ SecHeader->keys = (TKeys *) g_malloc (sizeof (TKeys));
+ SecHeader->keys->link = temp;
+ SecHeader->keys->key_name = strdup (CharBuffer);
+ state = KeyValue;
+ next = CharBuffer;
+ } else {
+ *next++ = c;
+ state = KeyDefOnKey;
+ }
+ break;
+
+ case KeyValue:
+ if (overflow || c == '\n'){
+ *next = '\0';
+ SecHeader->keys->value = strdup (CharBuffer);
+ state = c == '\n' ? KeyDef : IgnoreToEOL;
+ next = CharBuffer;
+#ifdef DEBUG
+ printf ("[%s] (%s)=%s\n", SecHeader->section_name,
+ SecHeader->keys->key_name, SecHeader->keys->value);
+#endif
+ } else
+ *next++ = c;
+ break;
+
+ } /* switch */
+
+ } /* while ((c = getc (f)) != EOF) */
+ if (c == EOF && state == KeyValue){
+ *next = '\0';
+ SecHeader->keys->value = strdup (CharBuffer);
+ }
+ fclose (f);
+ return SecHeader;
+}
+
+static void
+new_key (TSecHeader *section, char *key_name, char *value)
+{
+ TKeys *key;
+
+ key = (TKeys *) g_malloc (sizeof (TKeys));
+ key->key_name = strdup (key_name);
+ key->value = strdup (value);
+ key->link = section->keys;
+ section->keys = key;
+}
+
+static char *
+access_config (access_type mode, char *section_name, char *key_name,
+ char *def, char *filename)
+{
+
+ TProfile *New;
+ TSecHeader *section;
+ TKeys *key;
+
+ if (!is_loaded (filename, §ion)){
+ New = (TProfile *) g_malloc (sizeof (TProfile));
+ New->link = Base;
+ New->filename = strdup (filename);
+ New->section = load (filename);
+ Base = New;
+ section = New->section;
+ Current = New;
+ }
+
+ /* Start search */
+ for (; section; section = section->link){
+ if (section->section_name == 0)
+ continue;
+ if (strcasecmp (section->section_name, section_name))
+ continue;
+
+ for (key = section->keys; key; key = key->link){
+ if (strcasecmp (key->key_name, key_name))
+ continue;
+ if (mode == SET){
+ g_free (key->value);
+ key->value = strdup (def);
+ }
+ return key->value;
+ }
+
+ /* No key found */
+ if (mode == SET){
+ new_key (section, key_name, def);
+ return 0;
+ }
+ }
+
+ /* Non existent section */
+ if ((mode == SET) && def){
+ section = (TSecHeader *) g_malloc (sizeof (TSecHeader));
+ section->section_name = strdup (section_name);
+ section->keys = 0;
+ new_key (section, key_name, def);
+ section->link = Current->section;
+ Current->section = section;
+ }
+ return def;
+}
+
+static void
+dump_keys (FILE *profile, TKeys *p)
+{
+ if (!p)
+ return;
+ dump_keys (profile, p->link);
+ if (*p->key_name)
+ fprintf (profile, "%s=%s\n", p->key_name, p->value);
+}
+
+static void
+dump_sections (FILE *profile, TSecHeader *p)
+{
+ if (!p)
+ return;
+ dump_sections (profile, p->link);
+ if (p->section_name [0]){
+ fprintf (profile, "\n[%s]\n", p->section_name);
+ dump_keys (profile, p->keys);
+ }
+}
+
+static void
+dump_profile (TProfile *p)
+{
+ FILE *profile;
+
+ if (!p)
+ return;
+ dump_profile (p->link);
+
+ /* .ado: p->filename can be empty, it's better to jump over */
+ if (p->filename[0] != (char) 0)
+ if ((profile = fopen (p->filename, "w")) != NULL){
+ dump_sections (profile, p->section);
+ fclose (profile);
+ }
+}
+
+/*
+ * Must be called at the end.
+*/
+void
+gnome_config_sync (void)
+{
+ dump_profile (Base);
+}
+
+static void
+free_keys (TKeys *p)
+{
+ if (!p)
+ return;
+ free_keys (p->link);
+ g_free (p->key_name);
+ g_free (p->value);
+ g_free (p);
+}
+
+static void
+free_sections (TSecHeader *p)
+{
+ if (!p)
+ return;
+ free_sections (p->link);
+ free_keys (p->keys);
+ g_free (p->section_name);
+ p->link = 0;
+ p->keys = 0;
+ g_free (p);
+}
+
+static void
+free_profile (TProfile *p)
+{
+ if (!p)
+ return;
+ free_profile (p->link);
+ free_sections (p->section);
+ g_free (p->filename);
+ g_free (p);
+}
+
+void
+gnome_config_clean_file (char *path)
+{
+ TProfile *p;
+ ParsedPath *pp;
+
+ if (!path)
+ return;
+
+ pp = parse_path (path);
+
+ for (p = Base; p; p = p->link){
+ if (strcmp (pp->file, p->filename) != 0)
+ continue;
+
+ free_sections (p->section);
+ p->section = 0;
+ p->filename [0] = 0;
+ release_path (pp);
+ return;
+ }
+ release_path (pp);
+}
+
+void *
+gnome_config_init_iterator (char *path)
+{
+ TProfile *New;
+ TSecHeader *section;
+ ParsedPath *pp;
+
+ pp = parse_path (path);
+
+ if (!is_loaded (pp->file, §ion)){
+ New = (TProfile *) g_malloc (sizeof (TProfile));
+ New->link = Base;
+ New->filename = strdup (pp->file);
+ New->section = load (pp->file);
+ Base = New;
+ section = New->section;
+ Current = New;
+ }
+ for (; section; section = section->link){
+ if (strcasecmp (section->section_name, pp->section))
+ continue;
+ return section->keys;
+ }
+ release_path (pp);
+ return 0;
+}
+
+void *
+gnome_config_iterator_next (void *s, char **key, char **value)
+{
+ TKeys *keys = (TKeys *) s;
+
+ if (keys){
+ *key = g_strdup (keys->key_name);
+ *value = g_strdup (keys->value);
+ keys = keys->link;
+ }
+ return keys;
+}
+
+void
+gnome_config_clean_section (char *path)
+ /* *section_name, char *file */
+{
+ TSecHeader *section;
+ ParsedPath *pp;
+
+ pp = parse_path (path);
+
+ /* We assume the user has called one of the other initialization funcs */
+ if (!is_loaded (pp->file, §ion)){
+ fprintf (stderr,"Warning: profile_clean_section called before init\n");
+ release_path (pp);
+ return;
+ }
+ /* We only disable the section, so it will still be g_freed, but it */
+ /* won't be find by further walks of the structure */
+
+ for (; section; section = section->link){
+ if (strcasecmp (section->section_name, pp->section))
+ continue;
+ section->section_name [0] = 0;
+ }
+ release_path (pp);
+}
+
+void
+gnome_config_clean_key (char *path)
+ /* *section_name, char *file */
+{
+ TSecHeader *section;
+ TKeys *key;
+ ParsedPath *pp;
+
+ pp = parse_path (path);
+
+ /* We assume the user has called one of the other initialization funcs */
+ if (!is_loaded (pp->file, §ion)){
+ fprintf (stderr,"Warning: profile_clean_section called before init\n");
+ release_path (pp);
+ return;
+ }
+ for (; section; section = section->link){
+ if (strcasecmp (section->section_name, pp->section))
+ continue;
+ for (key = section->keys; key; key = key->link){
+ if (strcasecmp (key->key_name, pp->key))
+ continue;
+ key->key_name [0] = 0;
+ }
+ }
+ release_path (pp);
+}
+
+int
+gnome_config_has_section (char *path)
+ /* char *section_name, char *profile */
+{
+ TSecHeader *section;
+ ParsedPath *pp;
+
+ pp = parse_path (path);
+ /* We assume the user has called one of the other initialization funcs */
+ if (!is_loaded (pp->file, §ion)){
+ release_path (pp);
+ return 0;
+ }
+ for (; section; section = section->link){
+ if (strcasecmp (section->section_name, pp->section))
+ continue;
+ release_path (pp);
+ return 1;
+ }
+ release_path (pp);
+ return 0;
+}
+
+void
+gnome_config_drop_all (void)
+{
+ free_profile (Base);
+}
+
+int
+gnome_config_get_int (char *path)
+{
+ ParsedPath *pp;
+ char *r;
+ int v;
+
+ pp = parse_path (path);
+ r = access_config (LOOKUP, pp->section, pp->key, pp->def, pp->file);
+
+ g_return_val_if_fail(r != NULL, 0);
+
+ if (!strcasecmp (r, "true")){
+ release_path (pp);
+ return 1;
+ }
+ if (!strcasecmp (r, "false")){
+ release_path (pp);
+ return 0;
+ }
+ v = atoi (r);
+ release_path (pp);
+ return v;
+}
+
+char *
+gnome_config_get_string (char *path)
+{
+ ParsedPath *pp;
+ char *r;
+
+ pp = parse_path (path);
+ r = access_config (LOOKUP, pp->section, pp->key, pp->def, pp->file);
+ if (r)
+ r = strdup (r);
+ release_path (pp);
+ return r;
+}
+
+void
+gnome_config_set_string (char *path, char *new_value)
+{
+ ParsedPath *pp;
+ char *r;
+
+ pp = parse_path (path);
+ r = access_config (SET, pp->section, pp->key, new_value, pp->file);
+ release_path (pp);
+}
+
+void
+gnome_config_set_int (char *path, int new_value)
+{
+ ParsedPath *pp;
+ char intbuf [40];
+ char *r;
+
+ pp = parse_path (path);
+ sprintf (intbuf, "%d", new_value);
+ r = access_config (SET, pp->section, pp->key, intbuf, pp->file);
+ release_path (pp);
+}
+
+void
+gnome_config_set_prefix (char *path)
+{
+ prefix = strdup (path);
+}
+
+void
+gnome_config_drop_prefix (void)
+{
+ if (!prefix)
+ return;
+ free (prefix);
+ prefix = 0;
+}
diff --git a/libgnome/gnome-config.h b/libgnome/gnome-config.h
new file mode 100644
index 0000000..5bf8843
--- /dev/null
+++ b/libgnome/gnome-config.h
@@ -0,0 +1,39 @@
+#ifndef GNOME_CONFIG_H
+#define GNOME_CONFIG_H
+
+BEGIN_GNOME_DECLS
+
+/* Prototypes for the profile management functions */
+
+char *gnome_config_get_string (char *path);
+int gnome_config_get_int (char *path);
+void gnome_config_set_string (char *path, char *value);
+void gnome_config_set_int (char *path, int value);
+
+/* Returns true if /path/section is defined */
+int gnome_config_has_section (char *path);
+
+/* Returns a pointer for iterating on /file/section contents */
+void *gnome_config_init_iterator (char *path);
+
+/* Get next key and value value from a section */
+void *gnome_config_iterator_next (void *s, char **key, char **value);
+
+void gnome_config_drop_all (void);
+
+void gnome_config_sync (void);
+
+/* This routine drops the information about /file */
+void gnome_config_clean_file (char *path);
+
+/* This routine drops all of the information related to /file/section */
+void gnome_config_clean_section (char *path);
+
+/* Drops the information for a specific key */
+void gnome_config_clean_key (char *path);
+void gnome_config_set_prefix (char *path);
+void gnome_config_drop_prefix (void);
+
+END_GNOME_DECLS
+
+#endif
diff --git a/libgnome/gnome-defs.h b/libgnome/gnome-defs.h
new file mode 100644
index 0000000..0eb284c
--- /dev/null
+++ b/libgnome/gnome-defs.h
@@ -0,0 +1,7 @@
+#ifdef __cplusplus
+#define BEGIN_GNOME_DECLS extern "C" {
+#define END_GNOME_DECLS }
+#else
+#define BEGIN_GNOME_DECLS
+#define END_GNOME_DECLS
+#endif
diff --git a/libgnome/gnome-dentry.c b/libgnome/gnome-dentry.c
new file mode 100644
index 0000000..6d09d7f
--- /dev/null
+++ b/libgnome/gnome-dentry.c
@@ -0,0 +1,199 @@
+/*
+ * Support for manipulating .desktop files
+ *
+ * (C) 1997 the Free Software Foundation
+ *
+ * Authors: Miguel de Icaza.
+ * Federico Mena
+ */
+
+#include <config.h>
+#include <glib.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "gnome-defs.h"
+#include "gnome-util.h"
+#include "gnome-config.h"
+#include "gnome-dentry.h"
+
+#define free_if_empty(x) { if (x) g_free (x); }
+
+int
+gnome_is_program_in_path (char *program)
+{
+ static char *path;
+ static char **paths;
+ char **p;
+ char *f;
+
+ if (!path){
+ char *p;
+ int i, pc = 1;
+
+ path = strdup (getenv ("PATH"));
+ for (p = path; *p; p++)
+ if (*p == ':')
+ pc++;
+
+ paths = (char **) g_malloc (sizeof (char *) * (pc+1));
+
+ for (p = path, i = 0; i < pc; i++){
+ paths [i] = strtok (p, ":");
+ p = NULL;
+ }
+ paths [pc] = NULL;
+ }
+ p = paths;
+ while (*p){
+ f = g_concat_dir_and_file (*p, program);
+ if (g_file_exists (f)){
+ g_free (f);
+ return 1;
+ }
+ g_free (f);
+ p++;
+ }
+ return 0;
+}
+
+GnomeDesktopEntry *
+gnome_desktop_entry_load (char *file)
+{
+ GnomeDesktopEntry *newitem;
+ char *prefix;
+ char *exec_file, *try_file, *dot;
+
+ g_assert(file != NULL);
+
+ prefix = g_copy_strings ("=", file, "=/Desktop Entry/", NULL);
+
+ gnome_config_set_prefix (prefix);
+ g_free (prefix);
+
+ exec_file = gnome_config_get_string ("Exec");
+ if (!exec_file){
+ gnome_config_drop_prefix ();
+ return 0;
+ }
+ try_file = gnome_config_get_string ("TryExec");
+ if (try_file){
+ if (!gnome_is_program_in_path (try_file)){
+ g_free (try_file);
+ g_free (exec_file);
+ gnome_config_drop_prefix ();
+ return 0;
+ }
+ }
+ newitem = g_new(GnomeDesktopEntry, 1);
+ newitem->exec = exec_file;
+ newitem->tryexec = try_file;
+ newitem->icon_base = gnome_config_get_string ("Icon");
+ newitem->docpath = gnome_config_get_string ("DocPath");
+ newitem->info = gnome_config_get_string ("Info");
+ newitem->terminal = gnome_config_get_int ("Terminal");
+ newitem->type = gnome_config_get_string ("Type");
+ newitem->location = strdup (file);
+
+ if (newitem->icon_base && *newitem->icon_base){
+ dot = strstr (newitem->icon_base, ".xpm");
+
+ if (dot){
+ *dot = 0;
+
+ newitem->small_icon = g_copy_strings (newitem->icon_base,
+ "-small.xpm", NULL);
+ newitem->transparent_icon = g_copy_strings (newitem->icon_base,
+ "-transparent.xpm", NULL);
+ *dot = '.';
+ }
+
+ /* Sigh, now we need to make them local to the gnome install */
+ if (*newitem->icon_base != '/'){
+ char *s = newitem->small_icon;
+ char *t = newitem->transparent_icon;
+
+ newitem->small_icon = gnome_pixmap_file (s);
+ newitem->transparent_icon = gnome_pixmap_file (t);
+ g_free (s);
+ g_free (t);
+ }
+ } else {
+ newitem->small_icon = newitem->transparent_icon = 0;
+ }
+ gnome_config_drop_prefix ();
+ return newitem;
+}
+
+void
+gnome_desktop_entry_save (GnomeDesktopEntry *dentry)
+{
+ char *prefix;
+
+ g_assert(dentry != NULL);
+ g_assert(dentry->location != NULL);
+
+ prefix = g_copy_strings("=", dentry->location, "=/Desktop Entry", NULL);
+
+ gnome_config_clean_section(prefix);
+
+ prefix = g_copy_strings(prefix, "/", NULL);
+ gnome_config_set_prefix(prefix);
+ g_free(prefix);
+
+ if (dentry->exec)
+ gnome_config_set_string("Exec", dentry->exec);
+
+ if (dentry->tryexec)
+ gnome_config_set_string("TryExec", dentry->tryexec);
+
+ if (dentry->icon_base)
+ gnome_config_set_string("Icon", dentry->icon_base);
+
+ if (dentry->docpath)
+ gnome_config_set_string("DocPath", dentry->docpath);
+
+ if (dentry->info)
+ gnome_config_set_string("Info", dentry->info);
+
+ gnome_config_set_int("Terminal", dentry->terminal);
+
+ if (dentry->type)
+ gnome_config_set_string("Type", dentry->type);
+
+ gnome_config_drop_prefix();
+ gnome_config_sync();
+}
+
+void
+gnome_desktop_entry_free (GnomeDesktopEntry *item)
+{
+ g_assert(item != NULL);
+
+ free_if_empty (item->exec);
+ free_if_empty (item->icon_base);
+ free_if_empty (item->docpath);
+ free_if_empty (item->info);
+ free_if_empty (item->type);
+ free_if_empty (item->small_icon);
+ free_if_empty (item->transparent_icon);
+ free_if_empty (item->location);
+ g_free (item);
+}
+
+void
+gnome_desktop_entry_launch (GnomeDesktopEntry *item)
+{
+ char *command;
+
+ g_assert(item != NULL);
+
+ if (item->terminal)
+ command = g_copy_strings ("(xterm -e \"", item->exec, "\") &", NULL);
+ else
+ command = g_copy_strings ("(true;", item->exec, ") &", NULL);
+ system (command);
+ g_free (command);
+}
+
diff --git a/libgnome/gnome-dentry.h b/libgnome/gnome-dentry.h
new file mode 100644
index 0000000..a3da000
--- /dev/null
+++ b/libgnome/gnome-dentry.h
@@ -0,0 +1,30 @@
+#ifndef __GNOME_DENTRY_H__
+#define __GNOME_DENTRY_H__
+
+BEGIN_GNOME_DECLS
+
+typedef struct {
+ char *exec;
+ char *tryexec;
+ char *icon_base;
+ char *docpath;
+ char *info;
+ int terminal;
+ char *type;
+ char *location;
+
+ /* These are computed from icon_base */
+ char *small_icon;
+ char *transparent_icon;
+} GnomeDesktopEntry;
+
+GnomeDesktopEntry *gnome_desktop_entry_load (char *file);
+void gnome_desktop_entry_save (GnomeDesktopEntry *dentry);
+void gnome_desktop_entry_free (GnomeDesktopEntry *item);
+void gnome_desktop_entry_launch (GnomeDesktopEntry *item);
+
+int gnome_is_program_in_path (char *progname);
+
+END_GNOME_DECLS
+
+#endif
diff --git a/libgnome/gnome-dns.c b/libgnome/gnome-dns.c
new file mode 100644
index 0000000..42643d7
--- /dev/null
+++ b/libgnome/gnome-dns.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright (C) 1997 Ian Main
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <gtk/gtk.h>
+
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+
+#include "gnome-defs.h"
+#include "gnome-dns.h"
+
+#undef VERBOSE
+
+/* the maximum nuber of servers to spawn.. just as a safty measure
+ * in case something goes wrong -- so we don't have
+ * gnome_fork_bombs() */
+
+#define GNOME_DNS_MAX_SERVERS 8
+
+static void gnome_dns_callback(gpointer server_num, gint source,
+ GdkInputCondition condition);
+static gint gnome_dns_create_server(void);
+static void gnome_dns_server(gint pipefd[2]);
+
+typedef struct
+{
+ /* boolean to tell if server is doing a lookup */
+ gboolean in_use;
+ /* pipefd's to communicate to server with */
+ gint pipefd[2];
+} DnsServer;
+
+static DnsServer dns_server[GNOME_DNS_MAX_SERVERS];
+static int num_servers;
+static int server_init_cnt;
+
+typedef struct
+{
+ /* host hame for cache */
+ char *hostname;
+ gint server; /* -1 if complete, -2 if waiting for server,
+ otherwise index to dns_server */
+ /* address of host - may be 0 on failure. */
+ guint32 ip_addr;
+} GnomeDnsCache;
+
+static GnomeDnsCache *dns_cache;
+static int dns_cache_size, dns_cache_size_max;
+
+typedef struct
+{
+ gint tag;
+ gint server; /* -1 if waiting, otherwise index to dns_server[] */
+ char *hostname;
+ void (*callback) (guint32 ip_addr, void *callback_data);
+ void *callback_data;
+} GnomeDnsCon;
+
+static GnomeDnsCon *dns_con;
+static gint dns_con_size, dns_con_size_max;
+
+static gint dns_con_tag = 0;
+
+
+/*
+ *--------------------------------------------------------------
+ * gnome_dns_init
+ *
+ * Initialize the dns functions for use.
+ *
+ * Arguments:
+ * server_count specifies the number of servers to fork() at
+ * init, or <= 0 to do dynamic server forking. If you are
+ * concerned about virtual mem usage, fork your servers as one of the
+ * first things in your program.
+ *
+ * Note that it will still do dynamic forking if you specify > 0.
+ * when it runs out of servers.. a good init value may be 1 or 2.
+ *
+ * Results:
+ * gnome_dns_lookup() will be ready for use.
+ *
+ * Side effects:
+ * The library is initialized.
+ *
+ *--------------------------------------------------------------
+ */
+
+
+void gnome_dns_init (gint server_count)
+{
+ dns_con_size = 0;
+ dns_con_size_max = 16;
+ dns_con = g_new (GnomeDnsCon, dns_con_size_max);
+
+ dns_cache_size = 0;
+ dns_cache_size_max = 16;
+ dns_cache = g_new (GnomeDnsCache, dns_cache_size_max);
+
+ num_servers = 0;
+ while (num_servers < server_count) {
+ if ( (gnome_dns_create_server()) < 0) {
+ g_error ("Unable to fork: %s", g_strerror(errno));
+ }
+ }
+}
+
+
+/* Send the request to the server. */
+void
+gnome_dns_server_req (gint server, const char *hostname) {
+ dns_server[server].in_use = TRUE;
+ gdk_input_add(dns_server[server].pipefd[0],
+ GDK_INPUT_READ,
+ (GdkInputFunction) gnome_dns_callback,
+ (gpointer) server);
+ write (dns_server[server].pipefd[1], hostname, strlen (hostname) + 1);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gnome_dns_lookup
+ *
+ * looks up an address and returns a tag for use with
+ * gnome_dns_abort() if desired. May not return -1 if
+ * hostname was in cache.
+ *
+ * Arguments:
+ * char *hostname - hostname to lookup
+ * callback - function to call when dns lookup is complete.
+ * callback_data - data to pass to this function.
+ *
+ * Results:
+ * callback function is called when dns_lookup is complete.
+ * returns a tag identifying this lookup or -1 if lookup was
+ * in cache.
+ *
+ * Side effects:
+ * a new dns server may be spawned if all the current servers
+ * are in use.
+ *
+ *--------------------------------------------------------------
+ */
+
+
+guint32 gnome_dns_lookup (const char *hostname,
+ void (* callback) (guint32 ip_addr, void *callback_data),
+ void *callback_data)
+{
+ gint i;
+ gint tag;
+ gint server;
+
+ /* check for cache hit. */
+ for (i = 0; i < dns_cache_size; i++)
+ if (!strcmp (hostname, dns_cache[i].hostname))
+ break;
+
+ /* if it hit, call the callback immediately. */
+ if (i < dns_cache_size && dns_cache[i].server == -1) {
+ callback (dns_cache[i].ip_addr, callback_data);
+ return 0;
+ }
+
+ /* It didn't hit in the cache with an answer - need to put request
+ into the dns_con table. */
+ if (i < dns_cache_size) {
+ /* hit in cache but answer hasn't come back yet. */
+ server = dns_cache[i].server;
+ } else {
+ /* missed in cache -- create a cache entry */
+ if (dns_cache_size == dns_cache_size_max) {
+ dns_cache_size_max <<= 1;
+ dns_cache = g_realloc (dns_cache, dns_cache_size_max * sizeof (GnomeDnsCache));
+ }
+ dns_cache[dns_cache_size].hostname = g_strdup (hostname);
+ /* Find a server we can send the request to. */
+ for (server = 0; server < num_servers; server++)
+ if (!dns_server[server].in_use) {
+ break;
+ }
+ if (server < num_servers) {
+ /* found an unused server - give it the request */
+ gnome_dns_server_req (server, hostname);
+ dns_cache[dns_cache_size].server = server;
+ } else {
+ /* no unused servers - fork a new one */
+ dns_cache[dns_cache_size].server = gnome_dns_create_server();
+ if (dns_cache[dns_cache_size].server < 0) {
+ g_error ("Unable to fork: %s", g_strerror(errno));
+ }
+
+ }
+ dns_cache_size++;
+ }
+
+ if (dns_con_size == dns_con_size_max) {
+ dns_con_size_max <<= 1;
+ dns_con = g_realloc (dns_con, dns_con_size_max * sizeof (GnomeDnsCon));
+ }
+ tag = dns_con_tag++;
+ dns_con[dns_con_size].tag = tag;
+ dns_con[dns_con_size].server = server;
+ dns_con[dns_con_size].hostname = g_strdup (hostname);
+ dns_con[dns_con_size].callback = callback;
+ dns_con[dns_con_size].callback_data = callback_data;
+ dns_con_size++;
+
+ return tag;
+}
+
+/*
+ *--------------------------------------------------------------
+ * gnome_dns_abort
+ *
+ * aborts a previous call to gnome_dns_lookup().
+ *
+ * Arguments:
+ * gint tag32 - the tag returned from previous call to gnome_dns_lookup().
+ *
+ * Results:
+ * callback function is not called.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+
+void
+gnome_dns_abort (guint32 tag)
+{
+ gint i;
+
+ for (i = 0; i < dns_con_size; i++) {
+ if (dns_con[i].tag == tag) {
+ g_free (dns_con[i].hostname);
+ dns_con[i] = dns_con[--dns_con_size];
+ return;
+ }
+ }
+ g_warning ("gnome_dns_abort: aborting a nonexistent tag\n");
+}
+
+/*
+ *--------------------------------------------------------------
+ * gnome_dns_callback
+ *
+ * internal function - called when dns lookup completes.. this
+ * function dispatches the callback passed to gnome_dns_lookup().
+ *
+ * Arguments:
+ * gint server_num - the index into the dns_server struct.
+ * gint source - unkown.
+ * GdkIputCondition - unkown.
+ *
+ * Results:
+ * callback function passed to gnome_dns_lookup is called.
+ *
+ * Side effects:
+ * this dns_server[server_num]->in_use set to 0 for future lookups.
+ * ie, the lock is removed.
+ *
+ *--------------------------------------------------------------
+ */
+
+void gnome_dns_callback(gpointer serv_num, gint source,
+ GdkInputCondition condition)
+{
+ guint32 ip_addr;
+ gint server_num;
+ gint i;
+ gint j;
+
+ /* cast it back to an integer */
+ server_num = (int) serv_num;
+
+#ifdef VERBOSE
+ g_printf("callback called!\n");
+#endif
+ /* read ip from server. It's done as a single int rather than a string.
+ * hopefully it works ok */
+ if ( (read(dns_server[server_num].pipefd[0], &ip_addr, sizeof(guint32))) < 0)
+ g_error("reading from pipe: %s\n", g_strerror(errno));
+
+#ifdef VERBOSE
+ g_printf("ip_addr in callback is %x\n", ip_addr);
+#endif
+
+ /* write ip address into cache. */
+ for (i = 0; i < dns_cache_size; i++)
+ if (dns_cache[i].server == server_num)
+ break;
+ if (i < dns_cache_size) {
+ dns_cache[i].ip_addr = ip_addr;
+ dns_cache[i].server = -1;
+ } else {
+ g_warning ("gnome_dns_callback: no cache item for server\n");
+ }
+
+ /* Give answer to all callbacks. */
+ for (i = 0; i < dns_con_size; i++) {
+ if (dns_con[i].server == server_num) {
+ dns_con[i].callback (ip_addr, dns_con[i].callback_data);
+ g_free (dns_con[i].hostname);
+ dns_con[i--] = dns_con[--dns_con_size];
+ }
+ }
+
+ dns_server[server_num].in_use = FALSE;
+
+ /* See if there's an outstanding request and, if so, serve it. */
+ for (i = 0; i < dns_cache_size; i++) {
+ if (dns_cache[i].server == -2) {
+ dns_cache[i].server = server_num;
+ for (j = 0; j < dns_con_size; j++) {
+ if (!strcmp (dns_con[j].hostname, dns_cache[i].hostname))
+ dns_con[j].server = server_num;
+ }
+ gnome_dns_server_req (server_num, dns_cache[i].hostname);
+ break;
+ }
+ }
+}
+
+
+/*
+ *--------------------------------------------------------------
+ * gnome_dns_create_server
+ *
+ * internal function - creates a new server (currently using fork()).
+ *
+ * Arguments:
+ *
+ * Results:
+ * initializes the first free dns_server structure and returns
+ * the index into the dns_server structure which is
+ * also the tag. Returns -1 on error.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+gint gnome_dns_create_server(void)
+{
+
+ int pid;
+ int index = 0;
+
+
+ /* for talking to dns server. Once setup, always write to pipefd[1],
+ * and read from pipefd[0]. */
+ int pipefd[2];
+ int pipefd0[2];
+ int pipefd1[2];
+
+ /* check that we're not spawning too many servers.. this should really
+ * only be a sanity check.. I'm hoping that we'll never really spawn
+ * anywhere near the max allowed servers. */
+ if (num_servers >= GNOME_DNS_MAX_SERVERS) {
+ fprintf(stderr, "gnome: spawned too many dns processes - limit set to %d.\n",
+ GNOME_DNS_MAX_SERVERS);
+ return(-1);
+ }
+
+ /* create pipe to write to dns_server with */
+ if ( (pipe(pipefd0)) < 0) {
+ fprintf(stderr, "gnome: creating pipe: %s\n", strerror(errno));
+ return(-1);
+ }
+
+ /* create pipe to read from dns_server */
+ if ( (pipe(pipefd1)) < 0) {
+ fprintf(stderr, "gnome: creating pipe: %s\n", strerror(errno));
+ return(-1);
+ }
+
+ pid = fork();
+ if (pid < 0) {
+ fprintf(stderr, "gnome: forking: %s\n", strerror(errno));
+ return(-1);
+ }
+
+ /* start server in child */
+ if (pid == 0) {
+ pipefd[0] = pipefd0[0];
+ pipefd[1] = pipefd1[1];
+ gnome_dns_server(pipefd);
+ /* does not return */
+ }
+
+ index = num_servers;
+
+ /* initialize structure */
+
+ dns_server[index].in_use = FALSE;
+ dns_server[index].pipefd[1] = pipefd0[1];
+ dns_server[index].pipefd[0] = pipefd1[0];
+ close(pipefd0[0]);
+ close(pipefd1[1]);
+ /* only used as a sanity check to gnome_dns_abort() */
+ num_servers++;
+
+ return(index);
+}
+
+/*
+ *--------------------------------------------------------------
+ * gnome_dns_server
+ *
+ * internal function - this is the actual server process.
+ * Called from gnome_dns_server_create().
+ *
+ *
+ * Arguments:
+ *
+ * pipefd[2] - an open set of pipes - 0 for writing, 1 for
+ * reading.
+ *
+ * Results:
+ * sets up a server listening for char *hostnames on pipefd[0],
+ * and writing results of dns lookups as guints into pipefd[1].
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+
+
+void gnome_dns_server(gint pipefd[2])
+{
+ char hostname[4096];
+ gint nread;
+ struct hostent *host;
+ gint fd;
+ gint max_fd;
+ guint32 ip_addr;
+
+
+ /* todo: just close the pipe fd's */
+ /* close all file descriptors except ones used by the pipes. */
+ /* FIXME! getdtablesize is probably not a terribly portable call. */
+ max_fd = getdtablesize();
+ for(fd = 0; fd < max_fd; fd++)
+ if ( (fd != pipefd[0]) && (fd != pipefd[1]) && (fd !=1) && (fd != 2) )
+ close(fd);
+
+#ifdef VERBOSE
+ g_print ("gnome_dns_server: started\n");
+#endif
+ while(1) {
+ /* block on read from client */
+ nread = read(pipefd[0], hostname, 4096);
+
+ /* will return 0 if parent exits. */
+ /* where are those errors coming from anyway ??
+ * "** ERROR **: an x io error occurred" */
+ if (nread == 0) {
+#ifdef VERBOSE
+ g_print("---> dns_server - returned 0 - Exiting.\n");
+#endif
+ exit(0);
+ }
+
+ if (nread < 0) {
+ g_error("gnome_dns_server: reading from pipe: %s\n", g_strerror(errno));
+ }
+
+#ifdef VERBOSE
+ g_print("---> dns_server - looking up >%s<\n", hostname);
+#endif
+
+ host = gethostbyname(hostname);
+
+ if (host == NULL) {
+#ifdef VERBOSE
+ g_printf("---> dns_server - NULL return\n");
+#endif
+ ip_addr = 0;
+ } else {
+#ifdef VERBOSE
+ g_printf("---> dns_server - good return\n");
+#endif
+ memcpy(&ip_addr, host->h_addr_list[0], sizeof(ip_addr));
+ ip_addr = ntohl(ip_addr);
+ }
+
+#ifdef VERBOSE
+ g_printf("gnome_dns_server: ip of %s is %x\n", hostname, ip_addr);
+#endif
+ /* write hostname to client */
+ if ( (write(pipefd[1], &ip_addr, sizeof(ip_addr))) < 0)
+ g_error("gnome_dns_server: writing to pipe: %s\n", g_strerror(errno));
+ }
+}
diff --git a/libgnome/gnome-dns.h b/libgnome/gnome-dns.h
new file mode 100644
index 0000000..36e3072
--- /dev/null
+++ b/libgnome/gnome-dns.h
@@ -0,0 +1,80 @@
+#ifndef __GNOME_DNS_H__
+#define __GNOME_DNS_H__
+
+BEGIN_GNOME_DECLS
+
+/*
+ *--------------------------------------------------------------
+ * gnome_dns_init
+ *
+ * Initialize the dns functions for use.
+ *
+ * Arguments:
+ * server_count specifies the number of servers to fork() at
+ * init, or <= 0 to do dynamic server forking. If you are
+ * concerned about virtual mem usage, fork your servers as one of the
+ * first things in your program.
+ *
+ * Note that it will still do dynamic forking if you specify > 0.
+ * when it runs out of servers.. a good init value may be 1 or 2.
+ *
+ * Results:
+ * gnome_dns_lookup() will be ready for use.
+ *
+ * Side effects:
+ * The library is initialized.
+ *
+ *--------------------------------------------------------------
+ */
+void gnome_dns_init (gint server_count);
+
+/*
+ *--------------------------------------------------------------
+ * gnome_dns_lookup
+ *
+ * looks up an address and returns a tag for use with
+ * gnome_dns_abort() if desired. May not return -1 if
+ * hostname was in cache.
+ *
+ * Arguments:
+ * char *hostname - hostname to lookup
+ * callback - function to call when dns lookup is complete.
+ * callback_data - data to pass to this function.
+ *
+ * Results:
+ * callback function is called when dns_lookup is complete.
+ * returns a tag identifying this lookup or -1 if lookup was
+ * in cache.
+ *
+ * Side effects:
+ * a new dns server may be spawned if all the current servers
+ * are in use.
+ *
+ *--------------------------------------------------------------
+ */
+
+guint32 gnome_dns_lookup (const char *hostname,
+ void (* callback) (guint32 ip_addr, void *callback_data),
+ void *callback_data);
+
+/*
+ *--------------------------------------------------------------
+ * gnome_dns_abort
+ *
+ * aborts a previous call to gnome_dns_lookup().
+ *
+ * Arguments:
+ * gint tag32 - the tag returned from previous call to gnome_dns_lookup().
+ *
+ * Results:
+ * callback function is not called.
+ *
+ * Side effects:
+ *
+ *--------------------------------------------------------------
+ */
+void gnome_dns_abort (guint32 tag);
+
+END_GNOME_DECLS
+
+#endif /* __GNOME_DNS_H__ */
diff --git a/libgnome/gnome-hook.c b/libgnome/gnome-hook.c
new file mode 100644
index 0000000..25149e9
--- /dev/null
+++ b/libgnome/gnome-hook.c
@@ -0,0 +1,85 @@
+/*
+ * Hook management routines.
+ * Copyright (C) 1994, 1995, 1996 the Free Software Foundation.
+ * Written 1994, 1995, 1996 by:
+ * Miguel de Icaza, Janne Kukonlehto, Dugan Porter,
+ * Jakub Jelinek
+ */
+#include <config.h>
+#include <glib.h>
+#include "gnome-defs.h"
+#include "gnome-hook.h"
+
+void
+gnome_add_hook (GnomeHook **hook_list, GnomeHookFunc func, void *data)
+{
+ GnomeHook *new_hook = g_malloc (sizeof (GnomeHook));
+
+ new_hook->hook_fn = func;
+ new_hook->hook_data = data;
+ new_hook->next = *hook_list;
+
+ *hook_list = new_hook;
+}
+
+void
+gnome_execute_hooks (GnomeHook *hook_list)
+{
+ GnomeHook *new_hook = NULL;
+ GnomeHook *p;
+
+ /*
+ * We copy the hook list first so tahat we let the hook
+ * function call delete_hook
+ */
+
+ while (hook_list) {
+ gnome_add_hook (&new_hook, hook_list->hook_fn, hook_list->hook_data);
+ hook_list = hook_list->next;
+ }
+
+ p = new_hook;
+
+ while (new_hook) {
+ (*new_hook->hook_fn) (new_hook->hook_data);
+ new_hook = new_hook->next;
+ }
+
+ for (hook_list = p; hook_list;) {
+ p = hook_list;
+ hook_list = hook_list->next;
+ g_free (p);
+ }
+}
+
+
+void
+gnome_delete_hook (GnomeHook **hook_list, GnomeHookFunc func)
+{
+ GnomeHook *current, *new_list, *next;
+
+ new_list = NULL;
+
+ for (current = *hook_list; current; current = next) {
+ next = current->next;
+
+ if (current->hook_fn == func)
+ g_free (current);
+ else
+ gnome_add_hook (&new_list, current->hook_fn, current->hook_data);
+ }
+
+ *hook_list = new_list;
+}
+
+int
+gnome_hook_present (GnomeHook *hook_list, GnomeHookFunc func)
+{
+ GnomeHook *p;
+
+ for (p = hook_list; p; p = p->next)
+ if (p->hook_fn == func)
+ return TRUE;
+
+ return FALSE;
+}
diff --git a/libgnome/gnome-hook.h b/libgnome/gnome-hook.h
new file mode 100644
index 0000000..a49941d
--- /dev/null
+++ b/libgnome/gnome-hook.h
@@ -0,0 +1,22 @@
+#ifndef GNOME_HOOK_H
+#define GNOME_HOOK_H
+
+BEGIN_GNOME_DECLS
+
+typedef void (*GnomeHookFunc)(void *);
+
+typedef struct GnomeHook {
+ GnomeHookFunc hook_fn;
+ void *hook_data;
+ struct GnomeHook *next;
+} GnomeHook;
+
+
+void gnome_add_hook (GnomeHook **hook_list, GnomeHookFunc func, void *data);
+void gnome_execute_hooks (GnomeHook *hook_list);
+void gnome_delete_hook (GnomeHook **hook_list, GnomeHookFunc func);
+int gnome_hook_present (GnomeHook *hook_list, GnomeHookFunc func);
+
+END_GNOME_DECLS
+
+#endif
diff --git a/libgnome/gnome-i18n.h b/libgnome/gnome-i18n.h
new file mode 100644
index 0000000..c11cdd1
--- /dev/null
+++ b/libgnome/gnome-i18n.h
@@ -0,0 +1,33 @@
+/*
+ * Handles all of the internationalization configuration options.
+ * Author: Tom Tromey <tromey creche cygnus com>
+ */
+
+#ifndef __GNOME_I18N_H__
+#define __GNOME_I18N_H__
+
+BEGIN_GNOME_DECLS
+
+#ifdef HAVE_LIBINTL_H
+# include <libintl.h>
+# define _(String) gettext (String)
+# ifdef gettext_noop
+# define N_(String) gettext_noop (String)
+# else
+# define N_(String) (String)
+# endif
+#else
+/* Stubs that do something close enough. */
+# define textdomain(String) (String)
+# define gettext(String) (String)
+# define dgettext(Domain,Message) (Message)
+# define dcgettext(Domain,Message,Type) (Message)
+# define bindtextdomain(Domain,Directory) (Domain)
+# define _(String) (String)
+# define N_(String) (String)
+#endif
+
+END_GNOME_DECLS
+
+#endif __GNOME_UTIL_H__
+
diff --git a/libgnome/gnome-init.c b/libgnome/gnome-init.c
new file mode 100644
index 0000000..3010e76
--- /dev/null
+++ b/libgnome/gnome-init.c
@@ -0,0 +1,36 @@
+#include <config.h>
+#include <errno.h>
+#include <locale.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <glib.h>
+#include "gnome-defs.h"
+#include "gnome-util.h"
+
+#ifdef HAVE_LIBINTL
+#include "libintl.h"
+#endif
+
+char *gnome_user_home_dir = 0;
+char *gnome_user_dir = 0;
+
+void
+gnomelib_init (int *argc, char ***argv)
+{
+ gnome_user_home_dir = getenv ("HOME");
+ gnome_user_dir = g_concat_dir_and_file (gnome_user_home_dir, ".gnome");
+ mkdir (gnome_user_dir, 0755);
+
+ setlocale (LC_ALL, "");
+#ifdef HAVE_LIBINTL
+ bindtextdomain (PACKAGE, GNOMELOCALEDIR);
+#endif
+}
+
+
+
diff --git a/libgnome/gnome-mime.c b/libgnome/gnome-mime.c
new file mode 100644
index 0000000..2208922
--- /dev/null
+++ b/libgnome/gnome-mime.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright 1997 Paolo Molaro
+ * This is LGPL'ed code.
+ */
+#include "gnome.h"
+#include "gnome-mime.h"
+#include <string.h>
+#include <ctype.h>
+
+static void mime_fill_from_file (gchar * filename);
+static void mcap_fill_from_file (gchar * filename);
+
+static GHashTable *mime_hash = NULL;
+static GHashTable *mcap_hash = NULL;
+
+static void
+mime_fill_from_file (gchar * filename)
+{
+ FILE *f;
+ gchar buf[1024];
+ gchar *p, *s, *mtype;
+ gint used;
+ const gchar *blancks = " \t\n\r";
+
+ if (!(f = fopen (filename, "r")))
+ return;
+
+ while (fgets (buf, 1024, f)) {
+ p = buf;
+ while (*p && isspace (*p))
+ ++p;
+ if (!*p || *p == '#')
+ continue;
+ used = 0;
+ s = g_strdup (p);
+ mtype = strtok (s, blancks);
+ while ((p = strtok (NULL, blancks))) {
+ g_hash_table_insert (mime_hash, p, mtype);
+ used = 1;
+ }
+ if (!used)
+ g_free (s);
+ }
+ fclose (f);
+}
+
+gchar *
+gnome_mime_type (gchar * filename)
+{
+ gchar *ext;
+ gchar *result;
+ gchar *defaultv = "text/plain"; /* maybe NULL? */
+
+ if (!filename)
+ return defaultv;
+ ext = strrchr (filename, '.');
+ if (!ext)
+ ext = filename;
+ else
+ ++ext;
+
+ if (!mime_hash) {
+ gchar *f;
+ mime_hash = g_hash_table_new ((GHashFunc) g_string_hash, (GCompareFunc) g_string_equal);
+ mime_fill_from_file ("/etc/mime.types");
+ f = gnome_util_prepend_user_home (".mime.types");
+ if (f) {
+ mime_fill_from_file (f);
+ g_free (f);
+ }
+ }
+ result = g_hash_table_lookup (mime_hash, ext);
+ if (!result) {
+ gchar *s = alloca (strlen (ext) + 1);
+ gchar *p = s;
+ while (*ext) {
+ *p++ = tolower (*ext);
+ ++ext;
+ }
+ *p = 0;
+ result = g_hash_table_lookup (mime_hash, s);
+ if (!result)
+ return defaultv;
+ }
+ return result;
+}
+
+static void
+mcap_fill_from_file (gchar * filename)
+{
+ FILE *f;
+ gchar buf[1024];
+ gchar *p, *s, *mtype;
+ GList *list;
+ GnomeMailCap *mcap;
+ const gchar *blancks = ";";
+
+ if (!(f = fopen (filename, "r")))
+ return;
+ while (fgets (buf, 1024, f)) {
+ p = buf;
+ while (*p && isspace (*p))
+ ++p;
+ if (!*p || *p == '#')
+ continue;
+ s = g_strdup (p);
+ mtype = strtok (s, blancks);
+ list = g_hash_table_lookup (mcap_hash, mtype);
+
+ mcap = g_new (GnomeMailCap, 1);
+ mcap->program = NULL;
+ mcap->description = NULL;
+ mcap->nametemplate = NULL;
+ mcap->test = NULL;
+ mcap->composetyped = NULL;
+ mcap->copiousoutput = 0;
+ mcap->needsterminal = 0;
+
+ list = g_list_append (list, mcap);
+ g_hash_table_insert (mcap_hash, mtype, list);
+
+ p = strtok (NULL, blancks);
+ while (*p && isspace (*p))
+ ++p;
+ mcap->program = p;
+
+ while ((p = strtok (NULL, blancks))) {
+ while (*p && isspace (*p))
+ ++p;
+ /* printf("parsing: %s\n", p); */
+ if (!strncmp ("test=", p, 5))
+ mcap->test = p + 5;
+ else if (!strncmp ("description=", p, 12))
+ mcap->description = p + 12;
+ else if (!strncmp ("nametemplate=", p, 13))
+ mcap->nametemplate = p + 13;
+ else if (!strncmp ("composetyped=", p, 13))
+ mcap->composetyped = p + 13;
+ else if (!strncmp ("copiousoutput", p, 13))
+ mcap->copiousoutput = 1;
+ else if (!strncmp ("needsterminal", p, 13))
+ mcap->needsterminal = 1;
+ }
+ }
+ fclose (f);
+}
+
+GList *
+gnome_mime_entries (gchar * mime_type)
+{
+
+ if (!mcap_hash) {
+ gchar *f;
+ mcap_hash = g_hash_table_new ((GHashFunc) g_string_hash, (GCompareFunc) g_string_equal);
+ f = gnome_util_prepend_user_home (".mailcap");
+ if (f) {
+ mcap_fill_from_file (f);
+ g_free (f);
+ }
+ mcap_fill_from_file ("/etc/mailcap");
+ }
+ return g_hash_table_lookup (mcap_hash, mime_type);
+}
+
+GnomeMailCap *
+gnome_mime_default_entry (gchar * mime_type)
+{
+ GList *list;
+ list = gnome_mime_entries (mime_type);
+ if (list)
+ return (GnomeMailCap *) list->data;
+ return NULL;
+}
+
+gchar *
+gnome_mime_program (gchar * mime_type)
+{
+ GnomeMailCap *mcap;
+
+ mcap = gnome_mime_default_entry (mime_type);
+ if (mcap)
+ return mcap->program;
+ return NULL;
+}
+
+gchar *
+gnome_mime_description (gchar * mime_type)
+{
+ GnomeMailCap *mcap;
+
+ mcap = gnome_mime_default_entry (mime_type);
+ if (mcap)
+ return mcap->description;
+ return NULL;
+}
+
+gchar *
+gnome_mime_nametemplate (gchar * mime_type)
+{
+ GnomeMailCap *mcap;
+
+ mcap = gnome_mime_default_entry (mime_type);
+ if (mcap)
+ return mcap->nametemplate;
+ return NULL;
+}
+
+gchar *
+gnome_mime_test (gchar * mime_type)
+{
+ GnomeMailCap *mcap;
+
+ mcap = gnome_mime_default_entry (mime_type);
+ if (mcap)
+ return mcap->test;
+ return NULL;
+}
+
+gchar *
+gnome_mime_composetyped (gchar * mime_type)
+{
+ GnomeMailCap *mcap;
+
+ mcap = gnome_mime_default_entry (mime_type);
+ if (mcap)
+ return mcap->composetyped;
+ return NULL;
+}
+
+gint
+gnome_mime_copiousoutput (gchar * mime_type)
+{
+ GnomeMailCap *mcap;
+
+ mcap = gnome_mime_default_entry (mime_type);
+ if (mcap)
+ return mcap->copiousoutput;
+ return 0;
+}
+
+gint
+gnome_mime_needsterminal (gchar * mime_type)
+{
+ GnomeMailCap *mcap;
+
+ mcap = gnome_mime_default_entry (mime_type);
+ if (mcap)
+ return mcap->needsterminal;
+ return 0;
+}
+
+#ifdef MIMETEST
+
+int main (int argc, char *argv[])
+{
+ gint i;
+ gchar *mtype;
+ gchar *program;
+ gchar *desc;
+
+ gnome_mime_init ();
+
+ for (i = 1; i < argc; ++i) {
+ mtype = gnome_mime_type (argv[i]);
+ printf ("%-24s\t%s\n", mtype ? mtype : "", argv[i]);
+ program = gnome_mime_program (mtype);
+ desc = gnome_mime_description (mtype);
+ printf ("Program: %s\nDescription: %s\n", program, desc);
+ }
+ return 0;
+}
+
+#endif
diff --git a/libgnome/gnome-mime.h b/libgnome/gnome-mime.h
new file mode 100644
index 0000000..cf7825b
--- /dev/null
+++ b/libgnome/gnome-mime.h
@@ -0,0 +1,34 @@
+#ifndef __GNOME_MIME_H__
+#define __GNOME_MIME_H__
+
+BEGIN_GNOME_DECLS
+
+typedef struct {
+ gchar* program;
+ gchar* description;
+ gchar* nametemplate;
+ gchar* test;
+ gchar* composetyped;
+ gint copiousoutput;
+ gint needsterminal;
+ /* where are the specs for the mailcap format? */
+} GnomeMailCap;
+
+void gnome_mime_init (void);
+
+/* do not free() any of the returned values */
+gchar* gnome_mime_type (gchar* filename);
+GnomeMailCap* gnome_mime_default_entry (gchar* mime_type);
+GList* gnome_mime_entries (gchar* mime_type);
+gchar* gnome_mime_program (gchar* mime_type);
+gchar* gnome_mime_description (gchar* mime_type);
+gchar* gnome_mime_nametemplate (gchar* mime_type);
+gchar* gnome_mime_test (gchar* mime_type);
+gchar* gnome_mime_composetyped (gchar* mime_type);
+gint gnome_mime_copiousoutput (gchar* mime_type);
+gint gnome_mime_needsterminal (gchar* mime_type);
+
+END_GNOME_DECLS
+
+#endif
+
diff --git a/libgnome/gnome-string.c b/libgnome/gnome-string.c
new file mode 100644
index 0000000..4452f30
--- /dev/null
+++ b/libgnome/gnome-string.c
@@ -0,0 +1,92 @@
+#include "gnome-string.h"
+#include <string.h>
+
+#include <glib.h>
+#include <string.h>
+#include <limits.h>
+
+gchar **gnome_split_string(gchar *string, gchar *delim, gint max_tokens)
+{
+ gchar **retval = NULL;
+ GList *items = NULL, *anode;
+ gint numitems = 0, dlen, i;
+ gchar *src, *cur, *nxt;
+
+ g_return_val_if_fail(string != NULL, NULL);
+ g_return_val_if_fail(delim != NULL, NULL);
+
+ if(max_tokens < 0)
+ max_tokens = INT_MAX;
+
+ dlen = strlen(delim);
+ nxt = strstr(string, delim);
+ if(!nxt) {
+ retval = g_malloc(sizeof(gchar *) * 2);
+ retval[0] = g_strdup(string);
+ retval[1] = NULL;
+ return retval;
+ }
+ src = cur = g_strdup(string);
+ nxt = strstr(src, delim);
+
+ while(nxt && numitems < (max_tokens - 1)) {
+ *nxt = '\0';
+ items = g_list_append(items, g_strdup(cur));
+ cur = nxt + dlen;
+ nxt = strstr(cur, delim);
+ numitems++;
+ }
+ /* We have to take the rest of the string and put it as last token */
+ if(*cur) {
+ items = g_list_append(items, g_strdup(cur));
+ numitems++;
+ }
+ g_free(src);
+
+ retval = g_malloc(sizeof(gchar *) * (numitems + 1));
+ for(anode = items, i = 0; anode; anode = anode->next, i++)
+ retval[i] = anode->data;
+ retval[i] = NULL;
+ g_list_free(items);
+
+ return retval;
+}
+
+gchar *
+gnome_join_strings(gchar *separator, ...)
+{
+ va_list l;
+ va_start(l, separator);
+ /* Elliot: this can not be done like this: */
+ /* return gnome_join_vstrings(separator, l);*/
+}
+
+gchar *
+gnome_join_vstrings(gchar *separator, gchar **strings)
+{
+ gchar *retval;
+ gint total_size, i, seplen;
+
+ g_return_val_if_fail(separator != NULL, NULL);
+ g_return_val_if_fail(strings != NULL, NULL);
+
+ /* While it's not an error to have no strings to join, it
+ still needs to be handled differently */
+ if(!strings[0])
+ return g_strdup("");
+
+ total_size = strlen(strings[0]) + 1;
+ retval = g_malloc(total_size);
+ strcpy(retval, strings[0]);
+ seplen = strlen(separator);
+
+ for(i = 1; strings[i]; i++)
+ {
+ total_size += seplen + strlen(strings[i]);
+ retval = g_realloc(retval, total_size);
+ strcat(retval, separator);
+ strcat(retval, strings[i]);
+ }
+
+ return retval;
+}
diff --git a/libgnome/gnome-string.h b/libgnome/gnome-string.h
new file mode 100644
index 0000000..62ee2c7
--- /dev/null
+++ b/libgnome/gnome-string.h
@@ -0,0 +1,10 @@
+#include "gnome-defs.h"
+#include <glib.h>
+#include <stdarg.h>
+
+gchar **gnome_split_string (gchar *string,
+ gchar *delim,
+ gint max_tokens);
+gchar * gnome_join_strings (gchar *separator, ...);
+gchar * gnome_join_vstrings (gchar *separator,
+ gchar **strings);
diff --git a/libgnome/gnome-triggers.c b/libgnome/gnome-triggers.c
new file mode 100644
index 0000000..6c1f358
--- /dev/null
+++ b/libgnome/gnome-triggers.c
@@ -0,0 +1,362 @@
+/* By Elliot Lee */
+
+#include "gnome-triggers.h"
+#include "gnome-util.h"
+#include "gnome-string.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <glib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+/* TYPE DECLARATIONS */
+
+typedef struct _TriggerList * TriggerList;
+
+struct _TriggerList {
+ char *nodename;
+ TriggerList *subtrees;
+ gint numsubtrees;
+ GnomeTrigger *actions;
+ gint numactions;
+};
+
+typedef void (*GnomeTriggerTypeFunction)(GnomeTrigger t, char *msg, char *level, char *supinfo[]);
+
+/* PROTOTYPES */
+static GnomeTrigger
+gnome_trigger_dup(GnomeTrigger dupme);
+static TriggerList
+gnome_triggerlist_new(char *nodename);
+static void
+gnome_triggerlist_free(TriggerList t);
+static void
+gnome_trigger_free(GnomeTrigger t);
+static void
+gnome_trigger_do(GnomeTrigger t, char *msg, char *level, char *supinfo[]);
+static void
+gnome_trigger_do_function(GnomeTrigger t,
+ char *msg, char *level, char *supinfo[]);
+static void
+gnome_trigger_do_command(GnomeTrigger t,
+ char *msg, char *level, char *supinfo[]);
+
+/* FILEWIDE VARIABLES */
+
+static TriggerList topnode = NULL;
+
+static GnomeTriggerTypeFunction actiontypes[] =
+/* This list should have entries for all the trigger types in
+ gnome-triggers.h */
+{
+ (GnomeTriggerTypeFunction)NULL,
+ gnome_trigger_do_function,
+ gnome_trigger_do_command,
+ (GnomeTriggerTypeFunction)NULL,
+ (GnomeTriggerTypeFunction)NULL
+};
+
+/* IMPLEMENTATIONS */
+void
+gnome_triggers_init(void)
+{
+ char *fn;
+ fn = gnome_datadir_file("gnome/triggers/list");
+ if(fn) {
+ gnome_triggers_readfile(fn);
+ g_free(fn);
+ }
+
+ fn = gnome_util_prepend_user_home(".gnome/triggers/list");
+ if(fn) {
+ gnome_triggers_readfile(fn);
+ g_free(fn);
+ }
+}
+
+gint
+gnome_triggers_readfile(gchar *infilename)
+{
+ GnomeTrigger nt;
+ char aline[512];
+ char **subnames = NULL;
+ char **parts = NULL;
+ FILE *infile;
+ int i;
+
+ infile = fopen(infilename, "r");
+ if(infile == NULL)
+ return 1;
+
+ nt = gnome_trigger_dup(NULL);
+ while(fgets(aline, sizeof(aline), infile)) {
+ i = strlen(aline) - 1;
+ while(isspace(aline[i])) aline[i--] = '\0';
+
+ if(aline[0] == '\0' || aline[0] == '#')
+ continue;
+
+ parts = gnome_split_string(aline, " ", -1);
+ if(!parts || !parts[0] || !parts[1] || !parts[2] || !parts[3]) {
+ if(parts) {
+ for(i = 0; parts[i]; i++)
+ g_free(parts[i]);
+ g_free(parts);
+ }
+ g_warning("Invalid triggers line \'%s\'\n", aline);
+ continue;
+ }
+
+ if(!strcmp(parts[1], "NULL")) {
+ subnames = g_malloc(sizeof(gchar *));
+ subnames[0] = NULL;
+ } else
+ subnames = gnome_split_string(parts[1], ":", -1);
+
+ if(!strcmp(parts[2], "command"))
+ nt->type = GTRIG_COMMAND;
+ else if(!strcmp(parts[2], "play"))
+ nt->type = GTRIG_MEDIAPLAY;
+ nt->u.command = parts[3];
+ if(!strcmp(parts[0], "NULL"))
+ nt->level = NULL;
+ else
+ nt->level = parts[0];
+ gnome_triggers_vadd_trigger(nt, subnames);
+
+ for(i = 0; subnames[i]; i++)
+ g_free(subnames[i]);
+ g_free(subnames); subnames = NULL;
+
+ for(i = 0; parts[i]; i++)
+ g_free(parts[i]);
+ g_free(parts); parts = NULL;
+ }
+ g_free(nt);
+
+ return 0;
+}
+
+void gnome_triggers_add_trigger(GnomeTrigger nt, ...)
+{
+ va_list l;
+ va_start(l, nt);
+ /* gnome_triggers_vadd_trigger(nt, l);*/
+}
+
+static GnomeTrigger
+gnome_trigger_dup(GnomeTrigger dupme)
+{
+ GnomeTrigger retval;
+ retval = g_malloc(sizeof(struct _GnomeTrigger));
+ if(dupme) {
+ *retval = *dupme;
+ if(dupme->level)
+ retval->level = g_strdup(dupme->level);
+ else
+ retval->level = NULL;
+ switch(retval->type) {
+ case GTRIG_COMMAND:
+ retval->u.command = g_strdup(dupme->u.command);
+ break;
+ default:
+ break;
+ }
+ } else {
+ retval->level = NULL;
+ retval->type = GTRIG_NONE;
+ memset(&retval->u, 0, sizeof(retval->u));
+ }
+ return retval;
+}
+
+static TriggerList
+gnome_triggerlist_new(char *nodename)
+{
+ TriggerList retval;
+ retval = g_malloc0(sizeof(struct _TriggerList));
+ retval->nodename = g_strdup(nodename);
+ return retval;
+}
+
+void gnome_triggers_vadd_trigger(GnomeTrigger nt,
+ char *supinfo[])
+{
+ g_return_if_fail(nt != NULL);
+ if(!topnode)
+ topnode = gnome_triggerlist_new(NULL);
+
+ if(supinfo == NULL || supinfo[0] == NULL) {
+ topnode->actions = g_realloc(topnode->actions, ++topnode->numactions);
+ topnode->actions[topnode->numactions - 1] = gnome_trigger_dup(nt);
+ } else {
+ int i, j;
+ TriggerList curnode;
+
+ for(i = 0, curnode = topnode;
+ supinfo[i]; i++) {
+ for(j = 0;
+ j < curnode->numsubtrees
+ && strcmp(curnode->subtrees[j]->nodename, supinfo[i]);
+ j++) /* Do nothing */ ;
+
+ if(j < curnode->numsubtrees) {
+ curnode = curnode->subtrees[j];
+ } else {
+ curnode->subtrees = g_realloc(curnode->subtrees,
+ ++curnode->numsubtrees
+ * sizeof(TriggerList));
+ curnode->subtrees[curnode->numsubtrees - 1] =
+ gnome_triggerlist_new(supinfo[i]);
+ curnode = curnode->subtrees[curnode->numsubtrees - 1];
+ } /* end for j */
+ } /* end for i */
+
+ curnode->actions = g_realloc(curnode->actions,
+ ++curnode->numactions
+ * sizeof(GnomeTrigger));
+ curnode->actions[curnode->numactions - 1] = gnome_trigger_dup(nt);
+ } /* end if */
+}
+
+void
+gnome_triggers_do(char *msg, char *level, ...)
+{
+ va_list l;
+ va_start(l, level);
+ /* gnome_triggers_vdo(msg, level, l);*/
+}
+
+void
+gnome_triggers_vdo(char *msg, char *level, char *supinfo[])
+{
+ TriggerList curnode = topnode;
+ int i, j;
+
+ for(i = 0; curnode && supinfo[i]; i++)
+ {
+
+ for(j = 0; j < curnode->numactions; j++)
+ {
+ if(!curnode->actions[j]->level
+ || !level
+ || !strcmp(level, curnode->actions[j]->level))
+ gnome_trigger_do(curnode->actions[j], msg, level, supinfo);
+ }
+
+ for(j = 0;
+ j < curnode->numsubtrees
+ && strcmp(curnode->subtrees[j]->nodename,supinfo[i]);
+ j++)
+ /* Do nothing */ ;
+ if(j < curnode->numsubtrees)
+ curnode = curnode->subtrees[j];
+ else
+ curnode = NULL;
+ }
+ if(curnode)
+ {
+ for(j = 0; j < curnode->numactions; j++)
+ {
+ if(!curnode->actions[j]->level
+ || !level
+ || !strcmp(level, curnode->actions[j]->level))
+ gnome_trigger_do(curnode->actions[j], msg, level, supinfo);
+ }
+ }
+}
+
+void
+gnome_triggers_destroy(void)
+{
+ g_return_if_fail(topnode != NULL);
+ gnome_triggerlist_free(topnode);
+ topnode = NULL;
+}
+
+static void
+gnome_trigger_free(GnomeTrigger t)
+{
+ if(t->level)
+ g_free(t->level);
+ switch(t->type) {
+ case GTRIG_COMMAND:
+ g_free(t->u.command); break;
+ case GTRIG_MEDIAPLAY:
+ g_free(t->u.mediafile); break;
+ default:
+ break;
+ }
+ g_free(t);
+}
+
+static void
+gnome_triggerlist_free(TriggerList t)
+{
+ int i;
+
+ g_free(t->nodename);
+
+ for(i = 0; i < t->numsubtrees; i++) {
+ gnome_triggerlist_free(t->subtrees[i]);
+ }
+ g_free(t->subtrees);
+
+ for(i = 0; i < t->numactions; i++) {
+ gnome_trigger_free(t->actions[i]);
+ }
+ g_free(t->actions);
+
+ g_free(t);
+}
+
+static void
+gnome_trigger_do(GnomeTrigger t, char *msg, char * level, char *supinfo[])
+{
+ g_return_if_fail(t != NULL);
+
+ actiontypes[t->type](t, msg, level, supinfo);
+}
+
+static void
+gnome_trigger_do_function(GnomeTrigger t,
+ char *msg, char *level, char *supinfo[])
+{
+ t->u.function(msg, level, supinfo);
+}
+
+static void
+gnome_trigger_do_command(GnomeTrigger t, char *msg, char *level, char *supinfo[])
+{
+ char **argv;
+ int nsupinfos, i;
+
+ for(nsupinfos = 0; supinfo[nsupinfos]; nsupinfos++);
+
+ argv = g_malloc(sizeof(char *) * (nsupinfos + 4));
+ argv[0] = t->u.command;
+ argv[1] = msg;
+ argv[2] = level;
+
+ for(i = 0; supinfo[i]; i++) {
+ argv[i + 3] = supinfo[i];
+ }
+ argv[i + 3] = NULL;
+
+ /* We're all set, let's do it */
+ {
+ pid_t childpid;
+ int status;
+ childpid = fork();
+ if(childpid)
+ waitpid(childpid, &status, 0);
+ else
+ execv(t->u.command, argv);
+ }
+
+ g_free(argv);
+}
diff --git a/libgnome/gnome-triggers.h b/libgnome/gnome-triggers.h
new file mode 100644
index 0000000..284667c
--- /dev/null
+++ b/libgnome/gnome-triggers.h
@@ -0,0 +1,49 @@
+#ifndef __GNOME_TRIGGERS_H__
+#define __GNOME_TRIGGERS_H__
+
+#include "gnome-defs.h"
+#include <glib.h>
+BEGIN_GNOME_DECLS
+
+enum _GnomeTriggerType { GTRIG_NONE, GTRIG_FUNCTION, GTRIG_COMMAND, GTRIG_MEDIAPLAY };
+typedef enum _GnomeTriggerType GnomeTriggerType;
+typedef void (*GnomeTriggerActionFunction)(char *msg, char *level, char *supinfo[]);
+
+struct _GnomeTrigger {
+ GnomeTriggerType type;
+ union {
+ /* These will be passed the same info as
+ gnome_triggers_do got */
+ GnomeTriggerActionFunction function;
+ gchar *command;
+ gchar *mediafile;
+ } u;
+ gchar *level;
+};
+typedef struct _GnomeTrigger * GnomeTrigger;
+
+/* Must be called before doing any triggers stuff */
+void gnome_triggers_init(void);
+gint gnome_triggers_readfile(gchar *filename);
+
+/* The optional arguments in some of these functions are just
+ a list of strings that help us know
+ what type of event happened. For example,
+
+ gnome_triggers_do("System is out of disk space on /dev/hda1!",
+ "warning", "system", "device", "disk", "/dev/hda1");
+*/
+
+void gnome_triggers_add_trigger(GnomeTrigger nt, ...);
+void gnome_triggers_vadd_trigger(GnomeTrigger nt,
+ char *supinfo[]);
+
+void gnome_triggers_do(char *msg, char *level, ...);
+
+void gnome_triggers_vdo(char *msg, char *level, char *supinfo[]);
+
+void gnome_triggers_destroy(void);
+
+END_GNOME_DECLS
+
+#endif /* __GNOME_TRIGGERS_H__ */
diff --git a/libgnome/gnome-util.c b/libgnome/gnome-util.c
new file mode 100644
index 0000000..b2476ce
--- /dev/null
+++ b/libgnome/gnome-util.c
@@ -0,0 +1,231 @@
+#include <config.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <glib.h>
+#include <sys/stat.h>
+#include "gnome-defs.h"
+#include "gnome-util.h"
+
+static char *
+gnome_dirrelative_file (char *base, char *sub, char *filename, int unconditional)
+{
+ static char *gnomedir = NULL;
+ char *f, *t, *u;
+
+ /* First try the env GNOMEDIR relative path */
+ if (!gnomedir)
+ gnomedir = getenv ("GNOMEDIR");
+
+ if (gnomedir){
+ t = g_concat_dir_and_file (gnomedir, sub);
+ u = g_copy_strings (t, "/", filename, NULL);
+ g_free (t);
+
+ if (g_file_exists (u) || unconditional)
+ return u;
+
+ g_free (u);
+ }
+
+ /* Then try the hardcoded path */
+ f = g_concat_dir_and_file (base, filename);
+
+ if (g_file_exists (f) || unconditional)
+ return f;
+
+ g_free (f);
+
+ /* Finally, attempt to find it in the current directory */
+ f = g_concat_dir_and_file (".", filename);
+
+ if (g_file_exists (f))
+ return f;
+
+ g_free (f);
+ return NULL;
+}
+
+/* DOC: gnome_libdir_file (char *filename)
+ * Returns a newly allocated pathname pointing to a file in the gnome libdir
+ */
+char *
+gnome_libdir_file (char *filename)
+{
+ return (gnome_dirrelative_file (GNOMELIBDIR, "lib", filename, FALSE));
+}
+
+/* DOC: gnome_sharedir_file (char *filename)
+ * Returns a newly allocated pathname pointing to a file in the gnome sharedir
+ */
+char *
+gnome_datadir_file (char *filename)
+{
+ return (gnome_dirrelative_file (GNOMEDATADIR, "share", filename, FALSE));
+}
+
+char *
+gnome_pixmap_file (char *filename)
+{
+ return (gnome_dirrelative_file (GNOMEDATADIR "/pixmaps", "share/pixmaps", filename, FALSE));
+}
+
+char *
+gnome_unconditional_pixmap_file (char *filename)
+{
+ return (gnome_dirrelative_file (GNOMEDATADIR "/pixmaps", "share/pixmaps", filename, TRUE));
+}
+
+/* DOC: gnome_unconditional_libdir_file (char *filename)
+ * Returns a newly allocated pathname pointing to a (possibly
+ * non-existent) file in the gnome libdir
+ */
+char *
+gnome_unconditional_libdir_file (char *filename)
+{
+ return (gnome_dirrelative_file (GNOMELIBDIR, "lib", filename, TRUE));
+}
+
+/* DOC: gnome_unconditional_datadir_file (char *filename)
+ * Returns a newly allocated pathname pointing to a (possibly
+ * non-existent) file in the gnome libdir
+ */
+char *
+gnome_unconditional_datadir_file (char *filename)
+{
+ return (gnome_dirrelative_file (GNOMEDATADIR, "share", filename, TRUE));
+}
+
+/* DOC: g_file_exists (char *filename)
+ * Returns true if filename exists
+ */
+int
+g_file_exists (char *filename)
+{
+ struct stat s;
+
+ return stat (filename, &s) == 0;
+}
+
+
+/* DOC: g_copy_strings (const char *first,...)
+ * returns a new allocated char * with the concatenation of its arguments
+ */
+char *
+g_copy_strings (const char *first, ...)
+{
+ va_list ap;
+ int len;
+ char *data, *result;
+
+ if (!first)
+ return NULL;
+
+ len = strlen (first);
+ va_start (ap, first);
+
+ while ((data = va_arg (ap, char *)) != NULL)
+ len += strlen (data);
+
+ len++;
+
+ result = (char *) g_malloc (len);
+ va_end (ap);
+ va_start (ap, first);
+ strcpy (result, first);
+ while ((data = va_arg (ap, char *)) != NULL)
+ strcat (result, data);
+ va_end (ap);
+
+ return result;
+}
+
+
+/* DOC: g_unix_error_string (int error_num)
+ * Returns a pointer to a static location with a description of the errno
+ */
+char *
+g_unix_error_string (int error_num)
+{
+ static char buffer [256];
+ char *error_msg;
+
+#ifdef HAVE_STRERROR
+ error_msg = strerror (error_num);
+#else
+ extern int sys_nerr;
+ extern char *sys_errlist [];
+ if ((0 <= error_num) && (error_num < sys_nerr))
+ error_msg = sys_errlist[error_num];
+ else
+ error_msg = "strange errno";
+#endif /* HAVE_STRERROR */
+ sprintf (buffer, "%s (%d)", error_msg, error_num);
+ return buffer;
+}
+
+
+/* DOC: g_concat_dir_and_file (const char *dir, const char *file)
+ * returns a new allocated string that is the concatenation of dir and file,
+ * takes care of the exact details for concatenating them.
+ */
+char *
+g_concat_dir_and_file (const char *dir, const char *file)
+{
+ int l = strlen (dir);
+
+ if (dir [l - 1] == PATH_SEP)
+ return g_copy_strings (dir, file, NULL);
+ else
+ return g_copy_strings (dir, PATH_SEP_STR, file, NULL);
+}
+
+
+/* returns the home directory of the user
+ * This one is NOT to be free'd as it points into the
+ * env structure.
+ *
+ */
+
+char *
+gnome_util_user_home(void)
+{
+ static char *home_dir;
+ static int init = 1;
+
+ if (init) {
+ home_dir = getenv("HOME");
+ init = 0;
+ }
+
+ return(home_dir);
+}
+
+/* pass in a string, and it will add the users home dir ie,
+ * pass in .gnome/bookmarks.html and it will return
+ * /home/imain/.gnome/bookmarks.html
+ *
+ * Remember to g_free() returned value! */
+
+char *
+gnome_util_prepend_user_home(char *file)
+{
+ return g_concat_dir_and_file(gnome_util_user_home(), file);
+}
+
+/* very similar to above, but adds $HOME/.gnome/ to beginning
+ * This is meant to be the most useful version.
+ */
+
+char *
+gnome_util_home_file(char *file)
+{
+ char *path = g_concat_dir_and_file(gnome_util_user_home(), ".gnome");
+ char *ret = g_copy_strings(path, "/", file, NULL);
+
+ g_free(path);
+ return ret;
+}
diff --git a/libgnome/gnome-util.h b/libgnome/gnome-util.h
new file mode 100644
index 0000000..8eddef2
--- /dev/null
+++ b/libgnome/gnome-util.h
@@ -0,0 +1,25 @@
+#ifndef __GNOME_UTIL_H__
+#define __GNOME_UTIL_H__
+
+BEGIN_GNOME_DECLS
+
+#define PATH_SEP '/'
+#define PATH_SEP_STR "/"
+
+char *gnome_libdir_file (char *filename);
+char *gnome_datadir_file (char *filename);
+char *gnome_pixmap_file (char *filename);
+char *gnome_unconditional_libdir_file (char *filename);
+char *gnome_unconditional_datadir_file (char *filename);
+char *gnome_unconditional_pixmap_file (char *filename);
+int g_file_exists (char *filename);
+char *g_copy_strings (const char *first, ...);
+char *g_unix_error_string (int error_num);
+char *g_concat_dir_and_file (const char *dir, const char *file);
+char *gnome_util_user_home(void);
+char *gnome_util_prepend_user_home(char *file);
+char *gnome_util_home_file(char *file);
+
+END_GNOME_DECLS
+
+#endif
diff --git a/libgnome/gnomelib-init.c b/libgnome/gnomelib-init.c
new file mode 100644
index 0000000..3010e76
--- /dev/null
+++ b/libgnome/gnomelib-init.c
@@ -0,0 +1,36 @@
+#include <config.h>
+#include <errno.h>
+#include <locale.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <glib.h>
+#include "gnome-defs.h"
+#include "gnome-util.h"
+
+#ifdef HAVE_LIBINTL
+#include "libintl.h"
+#endif
+
+char *gnome_user_home_dir = 0;
+char *gnome_user_dir = 0;
+
+void
+gnomelib_init (int *argc, char ***argv)
+{
+ gnome_user_home_dir = getenv ("HOME");
+ gnome_user_dir = g_concat_dir_and_file (gnome_user_home_dir, ".gnome");
+ mkdir (gnome_user_dir, 0755);
+
+ setlocale (LC_ALL, "");
+#ifdef HAVE_LIBINTL
+ bindtextdomain (PACKAGE, GNOMELOCALEDIR);
+#endif
+}
+
+
+
diff --git a/libgnome/libgnome.h b/libgnome/libgnome.h
new file mode 100644
index 0000000..27135b6
--- /dev/null
+++ b/libgnome/libgnome.h
@@ -0,0 +1,19 @@
+#ifndef LIBGNOME_H
+#define LIBGNOME_H
+
+#include "libgnome/gnome-defs.h"
+#include "libgnome/gnome-util.h"
+#include "libgnome/gnome-hook.h"
+#include "libgnome/gnome-config.h"
+#include "libgnome/gnome-dns.h"
+#include "libgnome/gnome-dentry.h"
+#include "libgnome/gnome-i18n.h"
+#include "libgnome/gnome-string.h"
+#include "libgnome/gnome-triggers.h"
+
+extern char *gnome_user_home_dir;
+extern char *gnome_user_dir;
+
+void gnomelib_init (int *argc, char ***argv);
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]