/* $Id$ * UDP Gateway utility startup scripts support using debian(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 #include #include #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 update-rc.d(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 */ BUNDLE_UTIL_BACKUP_MASK)) /* flags */ 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; }