From: short <> Date: Sun, 26 Jun 2005 01:55:51 +0000 (+0000) Subject: Implemented crossplatform+$HOME configuration file management. X-Git-Tag: udpgate-1_0_2~29 X-Git-Url: http://git.jankratochvil.net/?p=udpgate.git;a=commitdiff_plain;h=163d230a4f49b624b5cfe179e6ea2b14899e62b7 Implemented crossplatform+$HOME configuration file management. --- diff --git a/src/configuration-pathname.c b/src/configuration-pathname.c new file mode 100644 index 0000000..cc816b5 --- /dev/null +++ b/src/configuration-pathname.c @@ -0,0 +1,86 @@ +/* $Id$ + * UDP Gateway persistent configuration pathname detection + * Copyright (C) 2005 Jan Kratochvil + * + * 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; exactly version 2 of June 1991 is required + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "configuration-pathname.h" /* self */ + + +/* OK, GConf would be nice. + * Unfortunately the fully-static build does not support GConf process spawn at + * all. Also /etc/sysconfig directory is standard for the daemon services. + */ + + +static const gchar *static_pathname; +static gboolean verbose=FALSE; + + +static gboolean try_pairname(const gchar *dirname,const gchar *filename) +{ +gchar *pathname; + + g_return_val_if_fail(dirname!=NULL,FALSE); + g_return_val_if_fail(filename!=NULL,FALSE); + + if (static_pathname) + return FALSE; + if (access(dirname,W_OK|X_OK)) { + if (verbose) + g_warning(_("Configuration directory not accessible(X) and/or writable(W): %s"),dirname); + return FALSE; + } + pathname=g_strdup_printf("%s/%s",dirname,filename); + if (access(pathname,R_OK|W_OK) && errno!=ENOENT) { + if (verbose) + g_warning(_("Configuration pathname not readable(R) and/or writable(W): %s"),pathname); + g_free(pathname); + return FALSE; + } + static_pathname=pathname; + return TRUE; +} + +G_CONST_RETURN gchar *configuration_pathname(void) +{ +const gchar *home_val; +static gboolean first=TRUE; + + if (!static_pathname && first) { + try_pairname(G_STRINGIFY(SYSCONFDIR) "/sysconfig",PACKAGE); + try_pairname(G_STRINGIFY(SYSCONFDIR) "/default",PACKAGE); + try_pairname(G_STRINGIFY(SYSCONFDIR) "",PACKAGE); + if ((home_val=getenv("HOME"))) + try_pairname(home_val,"." PACKAGE "rc"); + if (!static_pathname && !verbose) { + verbose=TRUE; + configuration_pathname(); + g_warning(_("All automatic configuration pathnames failed; configuration persistency disabled.")); + } + first=FALSE; + } + return static_pathname; +} diff --git a/src/configuration-pathname.h b/src/configuration-pathname.h new file mode 100644 index 0000000..102624e --- /dev/null +++ b/src/configuration-pathname.h @@ -0,0 +1,34 @@ +/* $Id$ + * Include file for the persistent configuration pathname detection + * Copyright (C) 2005 Jan Kratochvil + * + * 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; exactly version 2 of June 1991 is required + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _UDPGATE_CONFIGURATION_PATHNAME_H +#define _UDPGATE_CONFIGURATION_PATHNAME_H 1 + + +#include + + +G_BEGIN_DECLS + +G_CONST_RETURN gchar *configuration_pathname(void); + +G_END_DECLS + + +#endif /* _UDPGATE_CONFIGURATION_PATHNAME_H */ diff --git a/src/configuration.c b/src/configuration.c index 3dee3cb..d112ed9 100644 --- a/src/configuration.c +++ b/src/configuration.c @@ -30,18 +30,18 @@ #include #include "configuration.h" /* self */ +#include "configuration-pathname.h" #include "network.h" #include "main.h" -/* OK, GConf would be nice. +/* OK, FIXME: GConf would be nice. * Unfortunately the fully-static build does not support GConf process spawn at - * all. Also /etc/sysconfig directory is standard for the daemon services. + * all. */ /* Config: */ -#define CONFIGURATION_FILE "/etc/sysconfig/udpgate" #define LOCATION_LINK "/proc/self/exe" /* for Linux kernel */ @@ -67,20 +67,23 @@ static GHashTable *hash; static gboolean configuration_file_write(const gchar *file_content) { FILE *f; +const gchar *pathname; g_return_val_if_fail(file_content!=NULL,FALSE); - if (!(f=fopen(CONFIGURATION_FILE,("w")))) { - g_warning(_("Error write opening configuration file \"%s\": %m"),CONFIGURATION_FILE); + if (!(pathname=configuration_pathname())) + return FALSE; + if (!(f=fopen(pathname,"w"))) { + g_warning(_("Error write opening configuration file \"%s\": %m"),pathname); return FALSE; } if (fputs(file_content,f)<0) { - g_warning(_("Error writing configuration file \"%s\": %m"),CONFIGURATION_FILE); + g_warning(_("Error writing configuration file \"%s\": %m"),pathname); fclose(f); /* errors ignored */ return FALSE; } if (fclose(f)) - g_warning(_("Error closing configuration file \"%s\": %m"),CONFIGURATION_FILE); + g_warning(_("Error closing configuration file \"%s\": %m"),pathname); return TRUE; } @@ -128,11 +131,14 @@ GHashTable *hash_flushed; GString *gstring; gboolean modified=FALSE; /* 'gstring' contains modified value */ gboolean already_written=FALSE; +const gchar *pathname; + if (!(pathname=configuration_pathname())) + return NULL; open_retry: - if (!(f=fopen(CONFIGURATION_FILE,(!hash_flush ? "r" : "rw")))) { + if (!(f=fopen(pathname,(!hash_flush ? "r" : "rw")))) { if (errno!=ENOENT) - g_warning(_("Error r/o opening configuration file \"%s\": %m"),CONFIGURATION_FILE); + g_warning(_("Error r/o opening configuration file \"%s\": %m"),pathname); if (!hash_flush || already_written) return NULL; else { @@ -186,7 +192,7 @@ err_line: *varname_stop=varname_stop_orig; if (varcontent_stop) *varcontent_stop=varcontent_stop_orig; - g_warning(_("Error parsing line %d of the configuration file \"%s\": %s"),lineno,CONFIGURATION_FILE,line); + g_warning(_("Error parsing line %d of the configuration file \"%s\": %s"),lineno,pathname,line); goto err_append; } while (*s && isspace(*s)) s++; @@ -228,14 +234,14 @@ const char *line_new=udpgate_printf_alloca("%s=%s\n",varname_start,value); goto err_append; } if (errno) { - g_warning(_("Error reading line from the configuration file \"%s\": %s"),CONFIGURATION_FILE,strerror(errno)); + g_warning(_("Error reading line from the configuration file \"%s\": %s"),pathname,strerror(errno)); if (hash_fill) g_hash_table_destroy(hash_fill); fclose(f); /* errors ignored */ return NULL; } if (fclose(f)) - g_warning(_("Error closing configuration file \"%s\": %m"),CONFIGURATION_FILE); + g_warning(_("Error closing configuration file \"%s\": %m"),pathname); if (hash_flushed) { struct configuration_hash_readwrite_hash_flush_foreach_param param; @@ -269,7 +275,7 @@ static void configuration_read_hash_foreach(const gchar *key,const gchar *value, /* nop */; else g_warning(_("Unknown configuration key \"%s\" with value \"%s\" found in the file \"%s\""), - key,value,CONFIGURATION_FILE); + key,value,configuration_pathname()); } gboolean configuration_read(void)