Implemented crossplatform automatic startup management.
authorshort <>
Sun, 26 Jun 2005 01:58:58 +0000 (01:58 +0000)
committershort <>
Sun, 26 Jun 2005 01:58:58 +0000 (01:58 +0000)
src/main.c
src/startup-chkconfig.c
src/startup-chkconfig.h
src/startup-debian.c [new file with mode: 0644]
src/startup-debian.h [new file with mode: 0644]
src/startup-lsb.c [new file with mode: 0644]
src/startup-lsb.h [new file with mode: 0644]
src/startup.c
src/startup.h
src/static-startup.c [new file with mode: 0644]
src/static-startup.h [new file with mode: 0644]

index a2a7c61..e9833d9 100644 (file)
@@ -37,7 +37,7 @@
 #include "ui-line.h"
 #include "network.h"
 #include "configuration.h"
-#include "startup.h"
+#include "static-startup.h"
 #ifdef ENABLE_BUNDLE
 #include "bundle-util.h"
 #endif
@@ -276,16 +276,13 @@ guint handler_id;
 
        if (!is_interactive) {
 
-               if (optarg_startup_query || optarg_startup_off || optarg_startup_on)
-                       startup_init();
-
                if (optarg_stop)
                        if (!network_stop())
                                exit_rc=2;
                if (optarg_startup_query) {
 gboolean is_on;
 
-                       if (startup_query(&is_on)) {
+                       if (static_startup_query(&is_on)) {
                                g_message((is_on
                                                ? _("System startup registrance is turned on.")
                                                : _("System startup registrance is turned off.")));
@@ -296,11 +293,11 @@ gboolean is_on;
                                exit_rc=2;
                        }
                if (optarg_startup_off) {
-                       if (!startup_off())
+                       if (!static_startup_off())
                                exit_rc=2;
                        }
                if (optarg_startup_on) {
-                       if (!startup_on())
+                       if (!static_startup_on())
                                exit_rc=2;
                        }
                if (optarg_start)
index 09900d6..6c0aa0d 100644 (file)
@@ -42,9 +42,6 @@
  */
 #define INIT_D_PATHNAME G_STRINGIFY(SYSCONFDIR) "/init.d/" PACKAGE
 
-#define COMMAND_INSTALL_INIT_D "/usr/lib/lsb/install_initd"
-#define COMMAND_REMOVE_INIT_D  "/usr/lib/lsb/remove_initd"
-
 
 #define STATUS_0_1(status) ( \
                !(WIFEXITED((status)) && (WEXITSTATUS((status))==0 || WEXITSTATUS((status))==1) \
                                                && !WIFSTOPPED((status))) \
                                ? -1 : WEXITSTATUS((status)))
 
-static gboolean chkexec(const gchar *binary)
+
+static gboolean udpgate_startup_chkconfig_init(UdpgateStartup *udpgate_startup)
 {
-struct stat statbuf;
+int status;
+const gchar *command="chkconfig " PACKAGE " 2>/dev/null";
 
-       g_return_val_if_fail(binary!=NULL,FALSE);
+       g_return_val_if_fail(UDPGATE_IS_STARTUP_CHKCONFIG(udpgate_startup),FALSE);
 
-       if (stat(COMMAND_INSTALL_INIT_D,&statbuf))
-               return FALSE;
-       if ((statbuf.st_mode&(S_IFMT|0111))!=(S_IFREG|0111))
+       status=system(command);
+       if (STATUS_0_1(status)<0)
                return FALSE;
-
        return TRUE;
 }
 
-
-gboolean startup_chkconfig_init(void)
-{
-static gboolean r,r_set=FALSE;
-
-       if (!r_set) {
-int status;
-const gchar *command="chkconfig " PACKAGE;
-
-               /* LSB compliant 'query' is not standardized. */
-               if (chkexec(COMMAND_INSTALL_INIT_D) && chkexec(COMMAND_REMOVE_INIT_D))
-                       r=TRUE;
-               else {
-                       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)
+static gboolean udpgate_startup_chkconfig_query(UdpgateStartup *udpgate_startup,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;
+       g_return_val_if_fail(UDPGATE_IS_STARTUP_CHKCONFIG(udpgate_startup),FALSE);
 
-       /* LSB compliant 'query' is not standardized. */
        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);
+       if (is_on)
+               *is_on=(status_0_1==0);
        return TRUE;
 }
 
-gboolean startup_chkconfig_on(void)
+static gboolean udpgate_startup_chkconfig_on(UdpgateStartup *udpgate_startup)
 {
+const gchar *command="chkconfig --add " PACKAGE;
 int status;
-const gchar *command="chkconfig --add";
 
-       if (!startup_chkconfig_init())
-               return FALSE;
+       g_return_val_if_fail(UDPGATE_IS_STARTUP_CHKCONFIG(udpgate_startup),FALSE);
 
 #ifdef ENABLE_BUNDLE
        if (!bundle_util_file_write(
@@ -130,9 +97,6 @@ const gchar *command="chkconfig --add";
                return FALSE;
 #endif /* ENABLE_BUNDLE */
 
-       if (chkexec(COMMAND_INSTALL_INIT_D))
-               command=COMMAND_INSTALL_INIT_D;
-       command=udpgate_printf_alloca("%s %s",command,PACKAGE);
        status=system(command);
 
        if (0!=STATUS_0_1(status)) {
@@ -142,25 +106,58 @@ const gchar *command="chkconfig --add";
        return TRUE;
 }
 
-gboolean startup_chkconfig_off(void)
+static gboolean udpgate_startup_chkconfig_off(UdpgateStartup *udpgate_startup)
 {
-const gchar *command="chkconfig --del";
+const gchar *command="chkconfig --del " PACKAGE;
 int status;
 
-       if (!startup_chkconfig_init())
-               return FALSE;
+       g_return_val_if_fail(UDPGATE_IS_STARTUP_CHKCONFIG(udpgate_startup),FALSE);
 
-       if (chkexec(COMMAND_REMOVE_INIT_D))
-               command=COMMAND_REMOVE_INIT_D;
-       command=udpgate_printf_alloca("%s %s",command,PACKAGE);
        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;
 }
+
+static void udpgate_startup_chkconfig_class_init (UdpgateStartupChkconfigClass *class)
+{
+       UdpgateStartupClass *udpgate_startup_class = UDPGATE_STARTUP_CLASS(class);
+
+       udpgate_startup_class->init = udpgate_startup_chkconfig_init;
+       udpgate_startup_class->query = udpgate_startup_chkconfig_query;
+       udpgate_startup_class->on = udpgate_startup_chkconfig_on;
+       udpgate_startup_class->off = udpgate_startup_chkconfig_off;
+}
+
+GType udpgate_startup_chkconfig_get_type(void)
+{
+  static GType udpgate_startup_chkconfig_type=0;
+
+  if (!udpgate_startup_chkconfig_type) {
+               static const GTypeInfo udpgate_startup_chkconfig_info={
+                       sizeof(UdpgateStartupChkconfigClass),
+                       NULL,           /* base_init */
+                       NULL,           /* base_finalize */
+                       (GClassInitFunc)udpgate_startup_chkconfig_class_init,
+                       NULL,           /* class_finalize */
+                       NULL,           /* class_data */
+                       sizeof(UdpgateStartupChkconfig),
+                       0,              /* n_preallocs */
+                       NULL,           /* instance_init */
+                       NULL,           /* value_table */
+      };
+
+               udpgate_startup_chkconfig_type=g_type_register_static(UDPGATE_TYPE_STARTUP,"UdpgateStartupChkconfig",
+                                &udpgate_startup_chkconfig_info,0);
+    }
+
+  return udpgate_startup_chkconfig_type;
+}
index 829d21d..6abcecd 100644 (file)
@@ -1,5 +1,5 @@
 /* $Id$
- * Include file for UDP Gateway utility startup scripts support using chkconfig(8)
+ * Include file for UDP Gateway utility startup_chkconfig scripts inheritance support
  * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
  * 
  * This program is free software; you can redistribute it and/or modify
 
 
 #include <glib/gtypes.h>
+#include <glib-object.h>
+#include "startup.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);
+#define UDPGATE_TYPE_STARTUP_CHKCONFIG (udpgate_startup_chkconfig_get_type())
+#define UDPGATE_STARTUP_CHKCONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),UDPGATE_TYPE_STARTUP_CHKCONFIG,UdpgateStartupChkconfig))
+#define UDPGATE_STARTUP_CHKCONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),UDPGATE_TYPE_STARTUP_CHKCONFIG,UdpgateStartupChkconfigClass))
+#define UDPGATE_IS_STARTUP_CHKCONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),UDPGATE_TYPE_STARTUP_CHKCONFIG))
+#define UDPGATE_IS_STARTUP_CHKCONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),UDPGATE_TYPE_STARTUP_CHKCONFIG))
+#define UDPGATE_STARTUP_CHKCONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),UDPGATE_TYPE_STARTUP_CHKCONFIG,UdpgateStartupChkconfigClass))
+
+typedef struct _UdpgateStartupChkconfig UdpgateStartupChkconfig;
+typedef struct _UdpgateStartupChkconfigClass UdpgateStartupChkconfigClass;
+
+struct _UdpgateStartupChkconfig
+{
+       UdpgateStartup parent_instance;
+};
+
+struct _UdpgateStartupChkconfigClass
+{
+       UdpgateStartupClass parent_class;
+};
+
+GType udpgate_startup_chkconfig_get_type(void) G_GNUC_CONST;
+UdpgateStartupChkconfig *udpgate_startup_chkconfig_new(void);
 
 G_END_DECLS
 
diff --git a/src/startup-debian.c b/src/startup-debian.c
new file mode 100644 (file)
index 0000000..16a931c
--- /dev/null
@@ -0,0 +1,238 @@
+/* $Id$
+ * UDP Gateway utility startup scripts support using debian(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 <sys/stat.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "startup-debian.h"    /* self */
+
+#ifdef ENABLE_BUNDLE
+#include "bundle-util.h"
+#endif
+
+
+/* Config: */
+/* Do not: /etc/rc.d/init.d/...
+ * to comply with http://www.linuxbase.org/spec/booksets/LSB-Core/LSB-Core.html#INITSRCINSTRM
+ */
+#define INIT_D_PATHNAME G_STRINGIFY(SYSCONFDIR) "/init.d/" PACKAGE
+
+
+#define STATUS_0_1(status) ( \
+               !(WIFEXITED((status)) && (WEXITSTATUS((status))==0 || WEXITSTATUS((status))==1) \
+                                               && !WIFSIGNALED((status)) \
+                                               && !WIFSTOPPED((status))) \
+                               ? -1 : WEXITSTATUS((status)))
+
+
+static gboolean udpgate_startup_debian_init(UdpgateStartup *udpgate_startup)
+{
+int status;
+/* ">/dev/null" for: Adding system startup for /etc/init.d/PACKAGE ...
+ * "2>/dev/null" for: bash: update-rc.d: command not found
+ */
+const gchar *command="update-rc.d -n " PACKAGE " defaults &>/dev/null";
+
+       g_return_val_if_fail(UDPGATE_IS_STARTUP_DEBIAN(udpgate_startup),FALSE);
+
+       status=system(command);
+       if (STATUS_0_1(status)<0) {
+               g_warning(_("Error checking validity of debian(8) setup; automatic startup disabled; failed command: %s"),command);
+               return FALSE;
+               }
+       return TRUE;
+}
+
+static gboolean udpgate_startup_debian_query(UdpgateStartup *udpgate_startup,gboolean *is_on)
+{
+const gchar *command="update-rc.d -n " PACKAGE " defaults 2>/dev/null";
+static char buffer[0x1000];
+char *s;
+size_t fread_got;
+FILE *f;
+
+       g_return_val_if_fail(UDPGATE_IS_STARTUP_DEBIAN(udpgate_startup),FALSE);
+
+       if (!(f=popen(command,"r"))) {
+#if 0
+               g_warning(_("Error checking registrance of this program automatic startup opening \"%s\": %m"),command);
+#endif
+               return FALSE;
+               }
+       fread_got=fread(buffer,1,sizeof(buffer),f);
+       if (fclose(f)) {
+#if 0
+               g_warning(_("Error checking registrance of this program automatic startup closing \"%s\": %m"),command);
+#endif
+               return FALSE;
+       }
+       if (fread_got<=0 || fread_got>=sizeof(buffer)) {
+#if 0
+               g_warning(_("Error checking registrance of this program automatic startup reading \"%s\": %m"),command);
+#endif
+               return FALSE;
+       }
+       buffer[fread_got]='\0';
+       for (s=buffer;*s && isspace(*s);s++);
+       /* Fortunately update-rc.d(8) is just a dumb script without messages localization. */
+
+#define TEXT_ADDING_SYSTEM_STARTUP_FOR "Adding system startup for"
+/*
+ Adding system startup for /etc/init.d/PACKAGE ...
+   /etc/rc0.d/K20PACKAGE -> ../init.d/PACKAGE
+...
+   /etc/rc5.d/S20PACKAGE -> ../init.d/PACKAGE
+*/
+       if (!strncasecmp(s,TEXT_ADDING_SYSTEM_STARTUP_FOR,strlen(TEXT_ADDING_SYSTEM_STARTUP_FOR))) {
+               if (is_on)
+                       *is_on=FALSE;
+               return TRUE;
+               }
+
+#define TEXT_SYSTEM_STARTUP_LINKS_FOR "System startup links for"
+/*
+ System startup links for /etc/init.d/PACKAGE already exist.
+*/
+       if (!strncasecmp(s,TEXT_SYSTEM_STARTUP_LINKS_FOR,strlen(TEXT_SYSTEM_STARTUP_LINKS_FOR))) {
+               if (is_on)
+                       *is_on=TRUE;
+               return TRUE;
+               }
+
+       /* Failed: */
+       if ((s=strchr(buffer,'\n')))
+               *s='\0';
+       g_warning(_("Error checking registrance of this program, unknown output of \"%s\": %s"),command,buffer);
+       return FALSE;
+}
+
+static gboolean udpgate_startup_debian_on(UdpgateStartup *udpgate_startup)
+{
+/* Do not: " >/dev/null"
+ * as it is useful for: Adding system startup for /etc/init.d/PACKAGE ...
+ * but it is bad for:
+ *      Adding system startup for /etc/init.d/PACKAGE ...
+ *        /etc/rc0.d/K20PACKAGE -> ../init.d/PACKAGE
+ *     update-rc.d: symlink: Permission denied
+ * as the second line also gets hidden.
+ */
+const gchar *command="update-rc.d " PACKAGE " defaults";
+int status;
+
+       g_return_val_if_fail(UDPGATE_IS_STARTUP_DEBIAN(udpgate_startup),FALSE);
+
+#ifdef ENABLE_BUNDLE
+       if (!bundle_util_file_write(
+                       INIT_D_PATHNAME,        /* pathname */
+                       PACKAGE ".init",        /* basename */
+                       0755,   /* pathname_mode */
+                       TRUE))  /* pathname_backup */
+               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;
+}
+
+static gboolean udpgate_startup_debian_off(UdpgateStartup *udpgate_startup)
+{
+/* Do not: " >/dev/null"
+ * as it is useful for: Removing any system startup links for /etc/init.d/PACKAGE ...
+ * but it is bad for:
+ *      Removing any system startup links for /etc/init.d/PACKAGE ...
+ *        /etc/rc0.d/S30PACKAGE
+ *      update-rc.d: unlink: Permission denied
+ * as the second line also gets hidden.
+ */
+/* "-f" can be prevented for: ENABLE_BUNDLE
+ * by removing 'INIT_D_PATHNAME' first but it would still not work for
+ * regular non-bundled packaging.
+ */
+const gchar *command="update-rc.d -f " PACKAGE " remove";
+int status;
+
+       g_return_val_if_fail(UDPGATE_IS_STARTUP_DEBIAN(udpgate_startup),FALSE);
+
+#ifdef ENABLE_BUNDLE
+       /* init.d file must no longer exist for: update-rc.d PACKAGE remove
+        * without using its: -f|--force
+        */
+       if (!bundle_util_file_remove(INIT_D_PATHNAME,PACKAGE ".init"))
+               return FALSE;
+#endif /* ENABLE_BUNDLE */
+
+       status=system(command);
+       if (0!=STATUS_0_1(status)) {
+               g_warning(_("Error removing program's system startup registrance by: %s"),command);
+               return FALSE;
+               }
+
+       return TRUE;
+}
+
+static void udpgate_startup_debian_class_init (UdpgateStartupDebianClass *class)
+{
+       UdpgateStartupClass *udpgate_startup_class = UDPGATE_STARTUP_CLASS(class);
+
+       udpgate_startup_class->init = udpgate_startup_debian_init;
+       udpgate_startup_class->query = udpgate_startup_debian_query;
+       udpgate_startup_class->on = udpgate_startup_debian_on;
+       udpgate_startup_class->off = udpgate_startup_debian_off;
+}
+
+GType udpgate_startup_debian_get_type(void)
+{
+  static GType udpgate_startup_debian_type=0;
+
+  if (!udpgate_startup_debian_type) {
+               static const GTypeInfo udpgate_startup_debian_info={
+                       sizeof(UdpgateStartupDebianClass),
+                       NULL,           /* base_init */
+                       NULL,           /* base_finalize */
+                       (GClassInitFunc)udpgate_startup_debian_class_init,
+                       NULL,           /* class_finalize */
+                       NULL,           /* class_data */
+                       sizeof(UdpgateStartupDebian),
+                       0,              /* n_preallocs */
+                       NULL,           /* instance_init */
+                       NULL,           /* value_table */
+      };
+
+               udpgate_startup_debian_type=g_type_register_static(UDPGATE_TYPE_STARTUP,"UdpgateStartupDebian",
+                                &udpgate_startup_debian_info,0);
+    }
+
+  return udpgate_startup_debian_type;
+}
diff --git a/src/startup-debian.h b/src/startup-debian.h
new file mode 100644 (file)
index 0000000..d49b38f
--- /dev/null
@@ -0,0 +1,57 @@
+/* $Id$
+ * Include file for UDP Gateway utility startup_debian scripts inheritance 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_DEBIAN_H
+#define _UDPGATE_STARTUP_DEBIAN_H 1
+
+
+#include <glib/gtypes.h>
+#include <glib-object.h>
+#include "startup.h"
+
+
+G_BEGIN_DECLS
+
+#define UDPGATE_TYPE_STARTUP_DEBIAN (udpgate_startup_debian_get_type())
+#define UDPGATE_STARTUP_DEBIAN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),UDPGATE_TYPE_STARTUP_DEBIAN,UdpgateStartupDebian))
+#define UDPGATE_STARTUP_DEBIAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),UDPGATE_TYPE_STARTUP_DEBIAN,UdpgateStartupDebianClass))
+#define UDPGATE_IS_STARTUP_DEBIAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),UDPGATE_TYPE_STARTUP_DEBIAN))
+#define UDPGATE_IS_STARTUP_DEBIAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),UDPGATE_TYPE_STARTUP_DEBIAN))
+#define UDPGATE_STARTUP_DEBIAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),UDPGATE_TYPE_STARTUP_DEBIAN,UdpgateStartupDebianClass))
+
+typedef struct _UdpgateStartupDebian UdpgateStartupDebian;
+typedef struct _UdpgateStartupDebianClass UdpgateStartupDebianClass;
+
+struct _UdpgateStartupDebian
+{
+       UdpgateStartup parent_instance;
+};
+
+struct _UdpgateStartupDebianClass
+{
+       UdpgateStartupClass parent_class;
+};
+
+GType udpgate_startup_debian_get_type(void) G_GNUC_CONST;
+UdpgateStartupDebian *udpgate_startup_debian_new(void);
+
+G_END_DECLS
+
+
+#endif /* _UDPGATE_STARTUP_DEBIAN_H */
diff --git a/src/startup-lsb.c b/src/startup-lsb.c
new file mode 100644 (file)
index 0000000..00d8839
--- /dev/null
@@ -0,0 +1,166 @@
+/* $Id$
+ * UDP Gateway utility startup scripts support using lsb(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 <sys/stat.h>
+
+#include "startup-lsb.h"       /* self */
+
+#ifdef ENABLE_BUNDLE
+#include "bundle-util.h"
+#endif
+
+
+/* Config: */
+/* Do not: /etc/rc.d/init.d/...
+ * to comply with http://www.linuxbase.org/spec/booksets/LSB-Core/LSB-Core.html#INITSRCINSTRM
+ */
+#define INIT_D_PATHNAME G_STRINGIFY(SYSCONFDIR) "/init.d/" PACKAGE
+
+#define COMMAND_INSTALL_INIT_D "/usr/lib/lsb/install_initd"
+#define COMMAND_REMOVE_INIT_D  "/usr/lib/lsb/remove_initd"
+
+
+#define STATUS_0_1(status) ( \
+               !(WIFEXITED((status)) && (WEXITSTATUS((status))==0 || WEXITSTATUS((status))==1) \
+                                               && !WIFSIGNALED((status)) \
+                                               && !WIFSTOPPED((status))) \
+                               ? -1 : WEXITSTATUS((status)))
+
+static gboolean chkexec(const gchar *binary)
+{
+struct stat statbuf;
+
+       g_return_val_if_fail(binary!=NULL,FALSE);
+
+       if (stat(COMMAND_INSTALL_INIT_D,&statbuf))
+               return FALSE;
+       if ((statbuf.st_mode&(S_IFMT|0111))!=(S_IFREG|0111))
+               return FALSE;
+
+       return TRUE;
+}
+
+
+static gboolean udpgate_startup_lsb_init(UdpgateStartup *udpgate_startup)
+{
+       g_return_val_if_fail(UDPGATE_IS_STARTUP_LSB(udpgate_startup),FALSE);
+
+       /* LSB compliant 'query' is not standardized. */
+       if (chkexec(COMMAND_INSTALL_INIT_D) && chkexec(COMMAND_REMOVE_INIT_D))
+               return TRUE;
+       return FALSE;
+}
+
+static gboolean udpgate_startup_lsb_query(UdpgateStartup *udpgate_startup,gboolean *is_on)
+{
+       g_return_val_if_fail(UDPGATE_IS_STARTUP_LSB(udpgate_startup),FALSE);
+
+       /* LSB compliant 'query' is not standardized. */
+       return FALSE;
+}
+
+static gboolean udpgate_startup_lsb_on(UdpgateStartup *udpgate_startup)
+{
+const gchar *command=COMMAND_INSTALL_INIT_D " " PACKAGE;
+int status;
+
+       g_return_val_if_fail(UDPGATE_IS_STARTUP_LSB(udpgate_startup),FALSE);
+
+#ifdef ENABLE_BUNDLE
+       if (!bundle_util_file_write(
+                       INIT_D_PATHNAME,        /* pathname */
+                       PACKAGE ".init",        /* basename */
+                       0755,   /* pathname_mode */
+                       TRUE))  /* pathname_backup */
+               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;
+}
+
+static gboolean udpgate_startup_lsb_off(UdpgateStartup *udpgate_startup)
+{
+const gchar *command=COMMAND_REMOVE_INIT_D " " PACKAGE;
+int status;
+
+       g_return_val_if_fail(UDPGATE_IS_STARTUP_LSB(udpgate_startup),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;
+}
+
+static void udpgate_startup_lsb_class_init (UdpgateStartupLsbClass *class)
+{
+       UdpgateStartupClass *udpgate_startup_class = UDPGATE_STARTUP_CLASS(class);
+
+       udpgate_startup_class->init = udpgate_startup_lsb_init;
+       udpgate_startup_class->query = udpgate_startup_lsb_query;
+       udpgate_startup_class->on = udpgate_startup_lsb_on;
+       udpgate_startup_class->off = udpgate_startup_lsb_off;
+}
+
+GType udpgate_startup_lsb_get_type(void)
+{
+  static GType udpgate_startup_lsb_type=0;
+
+  if (!udpgate_startup_lsb_type) {
+               static const GTypeInfo udpgate_startup_lsb_info={
+                       sizeof(UdpgateStartupLsbClass),
+                       NULL,           /* base_init */
+                       NULL,           /* base_finalize */
+                       (GClassInitFunc)udpgate_startup_lsb_class_init,
+                       NULL,           /* class_finalize */
+                       NULL,           /* class_data */
+                       sizeof(UdpgateStartupLsb),
+                       0,              /* n_preallocs */
+                       NULL,           /* instance_init */
+                       NULL,           /* value_table */
+      };
+
+               udpgate_startup_lsb_type=g_type_register_static(UDPGATE_TYPE_STARTUP,"UdpgateStartupLsb",
+                                &udpgate_startup_lsb_info,0);
+    }
+
+  return udpgate_startup_lsb_type;
+}
diff --git a/src/startup-lsb.h b/src/startup-lsb.h
new file mode 100644 (file)
index 0000000..2c2c575
--- /dev/null
@@ -0,0 +1,57 @@
+/* $Id$
+ * Include file for UDP Gateway utility startup_lsb scripts inheritance 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_LSB_H
+#define _UDPGATE_STARTUP_LSB_H 1
+
+
+#include <glib/gtypes.h>
+#include <glib-object.h>
+#include "startup.h"
+
+
+G_BEGIN_DECLS
+
+#define UDPGATE_TYPE_STARTUP_LSB (udpgate_startup_lsb_get_type())
+#define UDPGATE_STARTUP_LSB(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),UDPGATE_TYPE_STARTUP_LSB,UdpgateStartupLsb))
+#define UDPGATE_STARTUP_LSB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),UDPGATE_TYPE_STARTUP_LSB,UdpgateStartupLsbClass))
+#define UDPGATE_IS_STARTUP_LSB(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),UDPGATE_TYPE_STARTUP_LSB))
+#define UDPGATE_IS_STARTUP_LSB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),UDPGATE_TYPE_STARTUP_LSB))
+#define UDPGATE_STARTUP_LSB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),UDPGATE_TYPE_STARTUP_LSB,UdpgateStartupLsbClass))
+
+typedef struct _UdpgateStartupLsb UdpgateStartupLsb;
+typedef struct _UdpgateStartupLsbClass UdpgateStartupLsbClass;
+
+struct _UdpgateStartupLsb
+{
+       UdpgateStartup parent_instance;
+};
+
+struct _UdpgateStartupLsbClass
+{
+       UdpgateStartupClass parent_class;
+};
+
+GType udpgate_startup_lsb_get_type(void) G_GNUC_CONST;
+UdpgateStartupLsb *udpgate_startup_lsb_new(void);
+
+G_END_DECLS
+
+
+#endif /* _UDPGATE_STARTUP_LSB_H */
index 16114fd..d8e1928 100644 (file)
 #include <glib/gmessages.h>
 
 #include "startup.h"   /* self */
+#include "startup-lsb.h"
 #include "startup-chkconfig.h"
+#include "startup-debian.h"
 
 
-/* FIXME: Provide some layer for multiple 'startup' handling backends. */
+gboolean udpgate_startup_query(UdpgateStartup *udpgate_startup,gboolean *is_on)
+{
+       g_return_val_if_fail(UDPGATE_IS_STARTUP(udpgate_startup),FALSE);
 
+       return (*UDPGATE_STARTUP_GET_CLASS(udpgate_startup)->query)(udpgate_startup,is_on);
+}
 
-gboolean startup_init(void)
+gboolean udpgate_startup_on(UdpgateStartup *udpgate_startup)
 {
-       return startup_chkconfig_init();
+gboolean is_on;
+
+       g_return_val_if_fail(UDPGATE_IS_STARTUP(udpgate_startup),FALSE);
+
+       if (!udpgate_startup_query(udpgate_startup,&is_on))
+               return FALSE;
+       if (is_on==TRUE)
+               return TRUE;
+
+       return (*UDPGATE_STARTUP_GET_CLASS(udpgate_startup)->on)(udpgate_startup);
 }
 
-gboolean startup_query(gboolean *is_on)
+gboolean udpgate_startup_off(UdpgateStartup *udpgate_startup)
 {
-       g_return_val_if_fail(is_on!=NULL,FALSE);
+gboolean is_on;
+
+       g_return_val_if_fail(UDPGATE_IS_STARTUP(udpgate_startup),FALSE);
 
-       return startup_chkconfig_query(is_on);
+       if (!udpgate_startup_query(udpgate_startup,&is_on))
+               return FALSE;
+       if (is_on==FALSE)
+               return TRUE;
+
+       return (*UDPGATE_STARTUP_GET_CLASS(udpgate_startup)->off)(udpgate_startup);
 }
 
-gboolean startup_on(void)
+UdpgateStartup *udpgate_startup_new(void)
+{
+       const GType impl_type_array[]={
+               UDPGATE_TYPE_STARTUP_LSB,
+               UDPGATE_TYPE_STARTUP_CHKCONFIG,
+               UDPGATE_TYPE_STARTUP_DEBIAN,
+               };
+       const GType *impl_type_pointer;
+
+       for (impl_type_pointer = impl_type_array;
+            impl_type_pointer < impl_type_array + G_N_ELEMENTS(impl_type_array);
+            impl_type_pointer++) {
+               UdpgateStartup *udpgate_startup;
+               
+               udpgate_startup=g_object_new(*impl_type_pointer,NULL);
+               g_assert(UDPGATE_IS_STARTUP(udpgate_startup));
+               if (UDPGATE_STARTUP_GET_CLASS(udpgate_startup)->init(udpgate_startup))
+                       return udpgate_startup;
+               g_object_unref(udpgate_startup);
+       }
+
+       return NULL;
+}
+
+static void
+udpgate_startup_class_init (UdpgateStartupClass *class)
 {
-       return startup_chkconfig_on();
 }
 
-gboolean startup_off(void)
+GType
+udpgate_startup_get_type(void)
 {
-       return startup_chkconfig_off();
+  static GType startup_type=0;
+
+  if (!startup_type) {
+               static const GTypeInfo startup_info={
+                       sizeof(UdpgateStartupClass),
+                       NULL,           /* base_init */
+                       NULL,           /* base_finalize */
+                       (GClassInitFunc)udpgate_startup_class_init,
+                       NULL,           /* class_finalize */
+                       NULL,           /* class_data */
+                       sizeof(UdpgateStartup),
+                       0,              /* n_preallocs */
+                       NULL,           /* instance_init */
+                       NULL,           /* value_table */
+      };
+
+               startup_type=g_type_register_static(G_TYPE_OBJECT,"UdpgateStartup",
+                                &startup_info,G_TYPE_FLAG_ABSTRACT);
+    }
+
+  return startup_type;
 }
index da8727d..68abed1 100644 (file)
@@ -1,5 +1,5 @@
 /* $Id$
- * Include file for UDP Gateway utility startup scripts support
+ * Include file for UDP Gateway utility startup scripts s inheritance support
  * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
  * 
  * This program is free software; you can redistribute it and/or modify
 
 
 #include <glib/gtypes.h>
+#include <glib-object.h>
 
 
 G_BEGIN_DECLS
 
-gboolean startup_init(void);
-gboolean startup_query(gboolean *is_on);
-gboolean startup_on(void);
-gboolean startup_off(void);
+#define UDPGATE_TYPE_STARTUP (udpgate_startup_get_type())
+#define UDPGATE_STARTUP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),UDPGATE_TYPE_STARTUP,UdpgateStartup))
+#define UDPGATE_STARTUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),UDPGATE_TYPE_STARTUP,UdpgateStartupClass))
+#define UDPGATE_IS_STARTUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),UDPGATE_TYPE_STARTUP))
+#define UDPGATE_IS_STARTUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),UDPGATE_TYPE_STARTUP))
+#define UDPGATE_STARTUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),UDPGATE_TYPE_STARTUP,UdpgateStartupClass))
+
+typedef struct _UdpgateStartup UdpgateStartup;
+typedef struct _UdpgateStartupClass UdpgateStartupClass;
+
+struct _UdpgateStartup
+{
+       GObject parent_instance;
+};
+
+struct _UdpgateStartupClass
+{
+       GObjectClass parent_class;
+
+       gboolean (*init)(UdpgateStartup *udpgate_startup);
+       gboolean (*query)(UdpgateStartup *udpgate_startup,gboolean *is_on);
+       gboolean (*on)(UdpgateStartup *udpgate_startup);
+       gboolean (*off)(UdpgateStartup *udpgate_startup);
+};
+
+GType udpgate_startup_get_type(void) G_GNUC_CONST;
+UdpgateStartup *udpgate_startup_new(void);
+gboolean udpgate_startup_query(UdpgateStartup *udpgate_startup,gboolean *is_on);
+gboolean udpgate_startup_on(UdpgateStartup *udpgate_startup);
+gboolean udpgate_startup_off(UdpgateStartup *udpgate_startup);
 
 G_END_DECLS
 
diff --git a/src/static-startup.c b/src/static-startup.c
new file mode 100644 (file)
index 0000000..431150f
--- /dev/null
@@ -0,0 +1,81 @@
+/* $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 <string.h>
+
+#include "static-startup.h"    /* self */
+#include "startup.h"
+#include "main.h"      /* for: optarg_verbose */
+
+
+static UdpgateStartup *static_startup_udpgate;
+
+
+static gboolean static_startup_udpgate_init(void)
+{
+static gboolean first=TRUE;
+
+       if (!static_startup_udpgate && first) {
+               first=FALSE;
+               static_startup_udpgate=udpgate_startup_new();
+               if (!static_startup_udpgate)
+                       g_warning(_("All automatic startup methods failed; automatic startup disabled."));
+               else {
+                       if (optarg_verbose) {
+                               const gchar *startup_base_name=g_type_name(UDPGATE_TYPE_STARTUP);
+                               const gchar *startup_used_name=G_OBJECT_TYPE_NAME(static_startup_udpgate);
+
+                               if (!strncmp(startup_base_name,startup_used_name,strlen(startup_base_name)))
+                                       startup_used_name+=strlen(startup_base_name);
+
+                               g_message(_("Using automatic startup type: %s"),startup_used_name);
+                               }
+                       }
+               }
+       return !!static_startup_udpgate;
+}
+
+gboolean static_startup_supported(void)
+{
+       return static_startup_udpgate_init();
+}
+
+gboolean static_startup_query(gboolean *is_on)
+{
+       if (!static_startup_udpgate_init())
+               return FALSE;
+       return udpgate_startup_query(static_startup_udpgate,is_on);
+}
+
+gboolean static_startup_on(void)
+{
+       if (!static_startup_udpgate_init())
+               return FALSE;
+       return udpgate_startup_on(static_startup_udpgate);
+}
+
+gboolean static_startup_off(void)
+{
+       if (!static_startup_udpgate_init())
+               return FALSE;
+       return udpgate_startup_off(static_startup_udpgate);
+}
diff --git a/src/static-startup.h b/src/static-startup.h
new file mode 100644 (file)
index 0000000..21cb358
--- /dev/null
@@ -0,0 +1,37 @@
+/* $Id$
+ * Include file for UDP Gateway utility startup scripts static 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_STATIC_STARTUP_H
+#define _UDPGATE_STATIC_STARTUP_H 1
+
+
+#include <glib/gtypes.h>
+
+
+G_BEGIN_DECLS
+
+gboolean static_startup_supported(void);
+gboolean static_startup_query(gboolean *is_on);
+gboolean static_startup_on(void);
+gboolean static_startup_off(void);
+
+G_END_DECLS
+
+
+#endif /* _UDPGATE_STATIC_STARTUP_H */