Implemented LSB init scripts compliance.
[udpgate.git] / src / startup-chkconfig.c
1 /* $Id$
2  * UDP Gateway utility startup scripts support using chkconfig(8)
3  * Copyright (C) 2004 Jan Kratochvil <project-udpgate@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include <glib/gmessages.h>
23 #include <stdlib.h>
24 #include <sys/types.h>
25 #include <sys/wait.h>
26 #include <unistd.h>
27 #include <glib/gmem.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <sys/stat.h>
31
32 #include "startup-chkconfig.h"  /* self */
33
34 #ifdef ENABLE_BUNDLE
35 #include "bundle-util.h"
36 #endif
37
38
39 /* Config: */
40 /* Do not: /etc/rc.d/init.d/...
41  * to comply with http://www.linuxbase.org/spec/booksets/LSB-Core/LSB-Core.html#INITSRCINSTRM
42  */
43 #define INIT_D_PATHNAME G_STRINGIFY(SYSCONFDIR) "/init.d/" PACKAGE
44
45 #define COMMAND_INSTALL_INIT_D "/usr/lib/lsb/install_initd"
46 #define COMMAND_REMOVE_INIT_D  "/usr/lib/lsb/remove_initd"
47
48
49 #define STATUS_0_1(status) ( \
50                 !(WIFEXITED((status)) && (WEXITSTATUS((status))==0 || WEXITSTATUS((status))==1) \
51                                                 && !WIFSIGNALED((status)) \
52                                                 && !WIFSTOPPED((status))) \
53                                 ? -1 : WEXITSTATUS((status)))
54
55 static gboolean chkexec(const gchar *binary)
56 {
57 struct stat statbuf;
58
59         g_return_val_if_fail(binary!=NULL,FALSE);
60
61         if (stat(COMMAND_INSTALL_INIT_D,&statbuf))
62                 return FALSE;
63         if ((statbuf.st_mode&(S_IFMT|0111))!=(S_IFREG|0111))
64                 return FALSE;
65
66         return TRUE;
67 }
68
69
70 gboolean startup_chkconfig_init(void)
71 {
72 static gboolean r,r_set=FALSE;
73
74         if (!r_set) {
75 int status;
76 const gchar *command="chkconfig " PACKAGE;
77
78                 /* LSB compliant 'query' is not standardized. */
79                 if (chkexec(COMMAND_INSTALL_INIT_D) && chkexec(COMMAND_REMOVE_INIT_D))
80                         r=TRUE;
81                 else {
82                         status=system(command);
83                         if (STATUS_0_1(status)<0) {
84                                 g_warning(_("Error checking validity of chkconfig(8) setup; automatic startup disabled; failed command: %s"),command);
85                                 r=FALSE;
86                                 }
87                         else
88                                 r=TRUE;
89                         }
90                 r_set=TRUE;
91                 }
92         return r;
93 }
94
95 gboolean startup_chkconfig_query(gboolean *is_on)
96 {
97 int status,status_0_1;
98 const gchar *command="chkconfig " PACKAGE;
99
100         g_return_val_if_fail(is_on!=NULL,FALSE);
101
102         if (!startup_chkconfig_init())
103                 return FALSE;
104
105         /* LSB compliant 'query' is not standardized. */
106         status=system(command);
107         status_0_1=STATUS_0_1(status);
108         if (status_0_1<0) {
109                 g_warning(_("Error checking registrance of this program automatic startup by: %s"),command);
110                 return FALSE;
111                 }
112         *is_on=(status_0_1==0);
113         return TRUE;
114 }
115
116 gboolean startup_chkconfig_on(void)
117 {
118 int status;
119 const gchar *command="chkconfig --add";
120
121         if (!startup_chkconfig_init())
122                 return FALSE;
123
124 #ifdef ENABLE_BUNDLE
125         if (!bundle_util_file_write(
126                         INIT_D_PATHNAME,        /* pathname */
127                         PACKAGE ".init",        /* basename */
128                         0755,   /* pathname_mode */
129                         TRUE))  /* pathname_backup */
130                 return FALSE;
131 #endif /* ENABLE_BUNDLE */
132
133         if (chkexec(COMMAND_INSTALL_INIT_D))
134                 command=COMMAND_INSTALL_INIT_D;
135         command=udpgate_printf_alloca("%s %s",command,PACKAGE);
136         status=system(command);
137
138         if (0!=STATUS_0_1(status)) {
139                 g_warning(_("Error registering automatic program startup by: %s"),command);
140                 return FALSE;
141                 }
142         return TRUE;
143 }
144
145 gboolean startup_chkconfig_off(void)
146 {
147 const gchar *command="chkconfig --del";
148 int status;
149
150         if (!startup_chkconfig_init())
151                 return FALSE;
152
153         if (chkexec(COMMAND_REMOVE_INIT_D))
154                 command=COMMAND_REMOVE_INIT_D;
155         command=udpgate_printf_alloca("%s %s",command,PACKAGE);
156         status=system(command);
157         if (0!=STATUS_0_1(status)) {
158                 g_warning(_("Error removing program's system startup registrance by: %s"),command);
159                 return FALSE;
160                 }
161 #ifdef ENABLE_BUNDLE
162         if (!bundle_util_file_remove(INIT_D_PATHNAME,PACKAGE ".init"))
163                 return FALSE;
164 #endif /* ENABLE_BUNDLE */
165         return TRUE;
166 }