From: short <> Date: Sun, 23 May 2004 17:40:30 +0000 (+0000) Subject: Implemented startup script registration command-line interface. X-Git-Tag: udpgate-1_0~30 X-Git-Url: https://git.jankratochvil.net/?a=commitdiff_plain;h=b2603c13d727c31f8366a86bd4b06fdc7fb2d3f5;hp=c7f25cdcc123d8d4b062b5a96567dd961d156022;p=udpgate.git Implemented startup script registration command-line interface. Fixes of the startup script engine. --- diff --git a/src/Makefile.am b/src/Makefile.am index cb6d3ba..8c4a7f5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -41,7 +41,9 @@ if ENABLE_BUNDLE nodist_udpgate_SOURCES=bundle.c BUNDLE_SRCS= \ - bundle.h + bundle.h \ + bundle-util.c \ + bundle-util.h EXTRA_DIST+= \ bundle.pl @@ -62,6 +64,10 @@ udpgate_SOURCES= \ network.h \ packet.c \ packet.h \ + startup-chkconfig.c \ + startup-chkconfig.h \ + startup.c \ + startup.h \ ui-line.c \ ui-line.h \ $(GNOME_SRCS) \ @@ -70,7 +76,7 @@ udpgate_SOURCES= \ EXTRA_DIST+= \ $(GLADE_IN) -udpgate_CFLAGS= +udpgate_CFLAGS=-DSYSCONFDIR="$(sysconfdir)" udpgate_LDADD= udpgate-ui-gnome-interface.$(OBJEXT): ui-gnome-callbacks.h diff --git a/src/bundle-util.c b/src/bundle-util.c new file mode 100644 index 0000000..83057b2 --- /dev/null +++ b/src/bundle-util.c @@ -0,0 +1,152 @@ +/* $Id$ + * UDP Gateway single-file bundle utility functions + * Copyright (C) 2004 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 +#include +#include +#include + +#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; +} diff --git a/src/bundle-util.h b/src/bundle-util.h new file mode 100644 index 0000000..482f92f --- /dev/null +++ b/src/bundle-util.h @@ -0,0 +1,35 @@ +/* $Id$ + * Include file for UDP Gateway single-file bundle utility functions + * Copyright (C) 2004 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_BUNDLE_UTIL_H +#define _UDPGATE_BUNDLE_UTIL_H 1 + + +#include + + +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 */ diff --git a/src/bundle.pl b/src/bundle.pl index fdd252b..ba30a48 100755 --- a/src/bundle.pl +++ b/src/bundle.pl @@ -42,6 +42,7 @@ print <<"EOH"; GHashTable *bundle_hash_new(void) { static GHashTable *hash; +/* Prefixed 32-bit network byte order file length. */ EOH my @files; for my $pathname (@ARGV) { @@ -57,6 +58,7 @@ 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; diff --git a/src/main.c b/src/main.c index a0917e6..4e38270 100644 --- a/src/main.c +++ b/src/main.c @@ -37,6 +37,7 @@ #include "ui-line.h" #include "network.h" #include "configuration.h" +#include "startup.h" #ifdef HAVE_GNOME #include "ui-gnome.h" @@ -53,6 +54,9 @@ int optarg_port=LOCAL_PORT_DEFAULT; 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); @@ -74,19 +78,25 @@ static const struct poptOption popt_table[]={ #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 @@ -129,6 +139,7 @@ gboolean is_interactive; #ifdef HAVE_GNOME gboolean no_gnome; #endif /* HAVE_GNOME */ +int exit_rc=EXIT_SUCCESS; #if 0 g_log_set_always_fatal(~(0 @@ -213,7 +224,10 @@ guint handler_id; 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 @@ -224,10 +238,38 @@ guint handler_id; 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 @@ -235,5 +277,5 @@ guint handler_id; configuration_write(); - return EXIT_SUCCESS; + exit(exit_rc); } diff --git a/src/startup-chkconfig.c b/src/startup-chkconfig.c new file mode 100644 index 0000000..c397f46 --- /dev/null +++ b/src/startup-chkconfig.c @@ -0,0 +1,126 @@ +/* $Id$ + * UDP Gateway utility startup scripts support using chkconfig(8) + * Copyright (C) 2004 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 +#include + +#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; +} diff --git a/src/startup-chkconfig.h b/src/startup-chkconfig.h new file mode 100644 index 0000000..829d21d --- /dev/null +++ b/src/startup-chkconfig.h @@ -0,0 +1,37 @@ +/* $Id$ + * Include file for UDP Gateway utility startup scripts support using chkconfig(8) + * Copyright (C) 2004 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_STARTUP_CHKCONFIG_H +#define _UDPGATE_STARTUP_CHKCONFIG_H 1 + + +#include + + +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 */ diff --git a/src/startup.c b/src/startup.c new file mode 100644 index 0000000..16114fd --- /dev/null +++ b/src/startup.c @@ -0,0 +1,51 @@ +/* $Id$ + * UDP Gateway utility startup scripts support + * Copyright (C) 2004 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 "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(); +} diff --git a/src/startup.h b/src/startup.h new file mode 100644 index 0000000..da8727d --- /dev/null +++ b/src/startup.h @@ -0,0 +1,37 @@ +/* $Id$ + * Include file for UDP Gateway utility startup scripts support + * Copyright (C) 2004 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_STARTUP_H +#define _UDPGATE_STARTUP_H 1 + + +#include + + +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 */