Fixes of the startup script engine.
nodist_udpgate_SOURCES=bundle.c
BUNDLE_SRCS= \
- bundle.h
+ bundle.h \
+ bundle-util.c \
+ bundle-util.h
EXTRA_DIST+= \
bundle.pl
network.h \
packet.c \
packet.h \
+ startup-chkconfig.c \
+ startup-chkconfig.h \
+ startup.c \
+ startup.h \
ui-line.c \
ui-line.h \
$(GNOME_SRCS) \
EXTRA_DIST+= \
$(GLADE_IN)
-udpgate_CFLAGS=
+udpgate_CFLAGS=-DSYSCONFDIR="$(sysconfdir)"
udpgate_LDADD=
udpgate-ui-gnome-interface.$(OBJEXT): ui-gnome-callbacks.h
--- /dev/null
+/* $Id$
+ * UDP Gateway single-file bundle utility functions
+ * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
+ *
+ * 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 <glib/gmessages.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <glib/gmem.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+
+#include "bundle-util.h" /* self */
+#include "bundle.h"
+
+
+static const guint8 *bundle_util_file_retrieve(guint32 *data_length_return,const gchar *pathname,const gchar *basename)
+{
+const guint8 *data;
+
+ g_return_val_if_fail(data_length_return!=NULL,NULL);
+ g_return_val_if_fail(pathname!=NULL,NULL);
+ g_return_val_if_fail(basename!=NULL,NULL);
+
+ data=g_hash_table_lookup(bundle_hash_new(),basename);
+ g_return_val_if_fail(data!=NULL,NULL);
+ *data_length_return=GUINT32_FROM_BE(*(guint32 *)data);
+ data+=sizeof(*data_length_return);
+
+ return data;
+}
+
+/* Returns TRUE if it safe to overwrite/unlink the file.
+ */
+static gboolean bundle_util_file_backup_conditional(const gchar *pathname,const gchar *basename)
+{
+const guint8 *data;
+guint32 data_length;
+int fd;
+guint8 *data_found;
+int got;
+char strftime_buffer[LINE_MAX];
+const gchar *destination;
+time_t time_current;
+
+ g_return_val_if_fail(pathname!=NULL,FALSE);
+ g_return_val_if_fail(basename!=NULL,FALSE);
+
+ if (!(data=bundle_util_file_retrieve(&data_length,pathname,basename)))
+ return FALSE;
+
+ if (-1==(fd=open(pathname,O_RDONLY))) {
+ if (errno==ENOENT)
+ return TRUE;
+ else {
+ g_warning(_("Error checking file modifications of \"%s\": %m"),pathname);
+ return FALSE;
+ }
+ }
+
+ /* WARNING: 'data_found' allocated in this block! */
+ data_found=g_malloc(data_length+1);
+ if (-1==(got=read(fd,data_found,data_length+1)))
+ g_warning(_("Error reading during the check of file modifications of \"%s\": %m"),pathname);
+ if (close(fd))
+ g_warning(_("Error closing the file \"%s\" during the check of its modifications: %m"),pathname);
+ g_free(data_found);
+
+ if (got==(int)data_length && !memcmp(data_found,data,data_length))
+ return TRUE;
+
+ time_current=time(NULL); /* It is segfault to gmtime(NULL). */
+ if (!strftime(strftime_buffer,sizeof(strftime_buffer),"GMT%FT%T",gmtime(&time_current))) {
+ g_warning("strftime(3): %m"); /* shouldn't happen */
+ return FALSE;
+ }
+ destination=udpgate_printf_alloca("%s-%s-%d",pathname,strftime_buffer,(int)getpid());
+ if (rename(pathname,destination)) {
+ g_warning(_("Error renaming your modified file \"%s\" to the backup \"%s\", giving up: %m"),
+ pathname,destination);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean bundle_util_file_remove(const gchar *pathname,const gchar *basename)
+{
+ g_return_val_if_fail(pathname!=NULL,FALSE);
+ g_return_val_if_fail(basename!=NULL,FALSE);
+
+ if (!bundle_util_file_backup_conditional(pathname,basename))
+ return FALSE;
+
+ if (unlink(pathname) && errno!=ENOENT) {
+ g_warning(_("Error removing the file \"%s\": %m"),pathname);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean bundle_util_file_write(const gchar *pathname,const gchar *basename,mode_t pathname_mode)
+{
+const guint8 *data;
+guint32 data_length;
+int fd;
+
+ g_return_val_if_fail(pathname!=NULL,FALSE);
+ g_return_val_if_fail(basename!=NULL,FALSE);
+
+ if (!(data=bundle_util_file_retrieve(&data_length,pathname,basename)))
+ return FALSE;
+
+ if (!bundle_util_file_backup_conditional(pathname,basename))
+ return FALSE;
+
+ if (-1==(fd=open(pathname,O_WRONLY|O_CREAT|O_TRUNC,pathname_mode))) {
+ g_warning(_("Error opening the file \"%s\" for rewrite: %m"),pathname);
+ return FALSE;
+ }
+ if ((int)data_length!=write(fd,data,data_length)) {
+ g_warning(_("Error writing the data of the file \"%s\" being overwritten: %m"),pathname);
+ close(fd); /* errors ignored */
+ return FALSE;
+ }
+ if (close(fd)) {
+ g_warning(_("Error closing the file \"%s\" after its rewrite: %m"),pathname);
+ return FALSE;
+ }
+ return TRUE;
+}
--- /dev/null
+/* $Id$
+ * Include file for UDP Gateway single-file bundle utility functions
+ * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
+ *
+ * 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_BUNDLE_UTIL_H
+#define _UDPGATE_BUNDLE_UTIL_H 1
+
+
+#include <glib/gtypes.h>
+
+
+G_BEGIN_DECLS
+
+gboolean bundle_util_file_remove(const gchar *pathname,const gchar *basename);
+gboolean bundle_util_file_write(const gchar *pathname,const gchar *basename,mode_t pathname_mode);
+
+G_END_DECLS
+
+
+#endif /* _UDPGATE_BUNDLE_UTIL_H */
GHashTable *bundle_hash_new(void)
{
static GHashTable *hash;
+/* Prefixed 32-bit network byte order file length. */
EOH
my @files;
for my $pathname (@ARGV) {
"filename" =>$filename,
"filename_sym"=>$filename_sym,
};
+ $F=pack("N*",length($F)).$F; # Prefix 32-bit network byte order file length.
my $Fout=unpack "H*",$F;
$Fout=~s/../0x$&,/g;
$Fout=~s/(?:.....){1,16}/\t\t$&\n/g;
#include "ui-line.h"
#include "network.h"
#include "configuration.h"
+#include "startup.h"
#ifdef HAVE_GNOME
#include "ui-gnome.h"
static int optarg_start;
static int optarg_stop;
int optarg_no_fork;
+static int optarg_startup_query;
+static int optarg_startup_on;
+static int optarg_startup_off;
void (*ui_interactive)(void);
#else /* HAVE_GNOME */
#define OPT_TEXT_IF_GNOME N_("(no Gnome UI compiled - stub only); --text must be first argument")
#endif /* HAVE_GNOME */
- UDPGATE_POPT(0 ,"text" ,POPT_ARG_NONE ,&optarg_text ,0,
- OPT_TEXT_IF_GNOME,NULL),
-#undef OPT_TEXT_IF_GNOME
- UDPGATE_POPT('v',"verbose",POPT_ARG_NONE ,&optarg_verbose,0,
- N_("Display additional debug information"),NULL),
- UDPGATE_POPT('p',"port" ,POPT_ARG_INT |POPT_ARGFLAG_SHOW_DEFAULT,&optarg_port ,0,
- N_("Listen on this UDP port"),NULL),
- UDPGATE_POPT('s',"start" ,POPT_ARG_NONE ,&optarg_start ,0,
- N_("Start the daemon"),NULL),
- UDPGATE_POPT('S',"stop" ,POPT_ARG_NONE ,&optarg_stop ,0,
+ UDPGATE_POPT(0 ,"text" ,POPT_ARG_NONE ,&optarg_text ,0,
+ OPT_TEXT_IF_GNOME,NULL),
+#undef OPT_TEXT_IF_GNOME
+ UDPGATE_POPT('v',"verbose" ,POPT_ARG_NONE ,&optarg_verbose ,0,
+ N_("Display additional debug information"),NULL),
+ UDPGATE_POPT('p',"port" ,POPT_ARG_INT |POPT_ARGFLAG_SHOW_DEFAULT,&optarg_port ,0,
+ N_("Listen on this UDP port"),NULL),
+ UDPGATE_POPT('s',"start" ,POPT_ARG_NONE ,&optarg_start ,0,
+ N_("Start the daemon"),NULL),
+ UDPGATE_POPT('S',"stop" ,POPT_ARG_NONE ,&optarg_stop ,0,
N_("Stop the daemon"),NULL),
- UDPGATE_POPT('1',"no-fork",POPT_ARG_NONE ,&optarg_no_fork,0,
+ UDPGATE_POPT('1',"no-fork" ,POPT_ARG_NONE ,&optarg_no_fork ,0,
N_("Do not detach from the current process"),NULL),
+ UDPGATE_POPT(0 ,"startup-query",POPT_ARG_NONE ,&optarg_startup_query,0,
+ N_("Query the current state of the system startup registrance"),NULL),
+ UDPGATE_POPT(0 ,"startup-on" ,POPT_ARG_NONE ,&optarg_startup_on ,0,
+ N_("Register for the automatic system startup"),NULL),
+ UDPGATE_POPT(0 ,"startup-off" ,POPT_ARG_NONE ,&optarg_startup_off ,0,
+ N_("Unregister from the automatic system startup"),NULL),
#undef UDPGATE_POPT
POPT_TABLEEND
#ifdef HAVE_GNOME
gboolean no_gnome;
#endif /* HAVE_GNOME */
+int exit_rc=EXIT_SUCCESS;
#if 0
g_log_set_always_fatal(~(0
is_interactive=(1
&& !optarg_start
- && !optarg_stop);
+ && !optarg_stop
+ && !optarg_startup_query
+ && !optarg_startup_on
+ && !optarg_startup_off);
/* Initialize UI here to catch all GLog errors below. */
if (is_interactive
g_error(_("No UI interface could be initialized"));
if (!is_interactive) {
+
+ if (optarg_startup_query || optarg_startup_off || optarg_startup_on)
+ startup_init();
+
if (optarg_stop)
- network_stop();
+ if (!network_stop())
+ exit_rc=2;
+ if (optarg_startup_query) {
+gboolean is_on;
+
+ if (startup_query(&is_on)) {
+ g_message((is_on
+ ? _("System startup registrance is turned on.")
+ : _("System startup registrance is turned off.")));
+ if (exit_rc<2)
+ exit_rc=(is_on ? 0 : 1);
+ }
+ else
+ exit_rc=2;
+ }
+ if (optarg_startup_off) {
+ if (!startup_off())
+ exit_rc=2;
+ }
+ if (optarg_startup_on) {
+ if (!startup_on())
+ exit_rc=2;
+ }
if (optarg_start)
- network_start(optarg_port);
+ if (!network_start(optarg_port))
+ exit_rc=2;
+
network_detach();
}
else
configuration_write();
- return EXIT_SUCCESS;
+ exit(exit_rc);
}
--- /dev/null
+/* $Id$
+ * UDP Gateway utility startup scripts support using chkconfig(8)
+ * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
+ *
+ * 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 <glib/gmessages.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <glib/gmem.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "startup-chkconfig.h" /* self */
+
+#ifdef ENABLE_BUNDLE
+#include "bundle-util.h"
+#endif
+
+
+/* Config: */
+#define INIT_D_PATHNAME G_STRINGIFY(SYSCONFDIR) "/rc.d/init.d/" PACKAGE
+
+
+#define STATUS_0_1(status) ( \
+ !(WIFEXITED((status)) && (WEXITSTATUS((status))==0 || WEXITSTATUS((status))==1) \
+ && !WIFSIGNALED((status)) \
+ && !WIFSTOPPED((status))) \
+ ? -1 : WEXITSTATUS((status)))
+
+gboolean startup_chkconfig_init(void)
+{
+static gboolean r,r_set=FALSE;
+
+ if (!r_set) {
+int status;
+const gchar *command="chkconfig " PACKAGE;
+
+ status=system(command);
+ if (STATUS_0_1(status)<0) {
+ g_warning(_("Error checking validity of chkconfig(8) setup; automatic startup disabled; failed command: %s"),command);
+ r=FALSE;
+ }
+ else
+ r=TRUE;
+ r_set=TRUE;
+ }
+ return r;
+}
+
+gboolean startup_chkconfig_query(gboolean *is_on)
+{
+int status,status_0_1;
+const gchar *command="chkconfig " PACKAGE;
+
+ g_return_val_if_fail(is_on!=NULL,FALSE);
+
+ if (!startup_chkconfig_init())
+ return FALSE;
+
+ status=system(command);
+ status_0_1=STATUS_0_1(status);
+ if (status_0_1<0) {
+ g_warning(_("Error checking registrance of this program automatic startup by: %s"),command);
+ return FALSE;
+ }
+ *is_on=(status_0_1==0);
+ return TRUE;
+}
+
+gboolean startup_chkconfig_on(void)
+{
+int status;
+const gchar *command="chkconfig --add " PACKAGE;
+
+ if (!startup_chkconfig_init())
+ return FALSE;
+
+#ifdef ENABLE_BUNDLE
+ if (!bundle_util_file_write(INIT_D_PATHNAME,PACKAGE ".init",0755))
+ return FALSE;
+#endif /* ENABLE_BUNDLE */
+ status=system(command);
+ if (0!=STATUS_0_1(status)) {
+ g_warning(_("Error registering automatic program startup by: %s"),command);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+gboolean startup_chkconfig_off(void)
+{
+const gchar *command="chkconfig --del " PACKAGE;
+int status;
+
+ if (!startup_chkconfig_init())
+ return FALSE;
+
+ status=system(command);
+ if (0!=STATUS_0_1(status)) {
+ g_warning(_("Error removing program's system startup registrance by: %s"),command);
+ return FALSE;
+ }
+#ifdef ENABLE_BUNDLE
+ if (!bundle_util_file_remove(INIT_D_PATHNAME,PACKAGE ".init"))
+ return FALSE;
+#endif /* ENABLE_BUNDLE */
+ return TRUE;
+}
--- /dev/null
+/* $Id$
+ * Include file for UDP Gateway utility startup scripts support using chkconfig(8)
+ * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
+ *
+ * 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_STARTUP_CHKCONFIG_H
+#define _UDPGATE_STARTUP_CHKCONFIG_H 1
+
+
+#include <glib/gtypes.h>
+
+
+G_BEGIN_DECLS
+
+gboolean startup_chkconfig_init(void);
+gboolean startup_chkconfig_query(gboolean *is_on);
+gboolean startup_chkconfig_on(void);
+gboolean startup_chkconfig_off(void);
+
+G_END_DECLS
+
+
+#endif /* _UDPGATE_STARTUP_CHKCONFIG_H */
--- /dev/null
+/* $Id$
+ * UDP Gateway utility startup scripts support
+ * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
+ *
+ * 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 <glib/gmessages.h>
+
+#include "startup.h" /* self */
+#include "startup-chkconfig.h"
+
+
+/* FIXME: Provide some layer for multiple 'startup' handling backends. */
+
+
+gboolean startup_init(void)
+{
+ return startup_chkconfig_init();
+}
+
+gboolean startup_query(gboolean *is_on)
+{
+ g_return_val_if_fail(is_on!=NULL,FALSE);
+
+ return startup_chkconfig_query(is_on);
+}
+
+gboolean startup_on(void)
+{
+ return startup_chkconfig_on();
+}
+
+gboolean startup_off(void)
+{
+ return startup_chkconfig_off();
+}
--- /dev/null
+/* $Id$
+ * Include file for UDP Gateway utility startup scripts support
+ * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
+ *
+ * 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_STARTUP_H
+#define _UDPGATE_STARTUP_H 1
+
+
+#include <glib/gtypes.h>
+
+
+G_BEGIN_DECLS
+
+gboolean startup_init(void);
+gboolean startup_query(gboolean *is_on);
+gboolean startup_on(void);
+gboolean startup_off(void);
+
+G_END_DECLS
+
+
+#endif /* _UDPGATE_STARTUP_H */