r10656: BIG merge from trunk. Features not copied over
[samba.git] / source3 / services / svc_rcinit.c
1
2 /* 
3  *  Unix SMB/CIFS implementation.
4  *  Service Control API Implementation
5  *  Copyright (C) Gerald Carter                   2005.
6  *  
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *  
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *  
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include "includes.h"
23
24 /* Implementation for LSB compliant init scripts */
25
26 /*******************************************************************************
27  Get the services information  by reading and parsing the shell scripts. These 
28  are symbolically linked into the  SVCCTL_SCRIPT_DIR  directory.
29
30  Get the names of the services/scripts to read from the smb.conf file.
31 *******************************************************************************/
32
33 BOOL get_LSB_data(char *fname,Service_info *si )
34 {
35         pstring initdfile;
36         char mybuffer[256];
37         const char *tokenptr;
38         char **qlines;
39         int fd = -1;
40         int nlines, *numlines,i,in_section,in_description;
41         
42         pstrcpy(si->servicename,"");
43         pstrcpy(si->servicetype,"EXTERNAL");
44         pstrcpy(si->filename,fname);
45         pstrcpy(si->provides,"");
46         pstrcpy(si->dependencies,"");
47         pstrcpy(si->shouldstart,"");
48         pstrcpy(si->shouldstop,"");
49         pstrcpy(si->requiredstart,"");
50         pstrcpy(si->requiredstop,"");
51         pstrcpy(si->description,"");
52         pstrcpy(si->shortdescription,"");
53
54         numlines = &nlines;
55         in_section = 0;
56         in_description = 0;
57
58    
59         if( !fname || !*fname ) {
60                 DEBUG(0, ("Must define an \"LSB-style init file\" to read.\n"));
61                 return False;
62         }
63         pstrcpy(initdfile,dyn_LIBDIR);
64         pstrcat(initdfile,SVCCTL_SCRIPT_DIR);
65         pstrcat(initdfile,fname);
66
67         /* TODO  - should check to see if the file that we're trying to open is 
68            actually a script. If it's NOT, we should do something like warn, 
69            and not continue to try to find info we're looking for */
70
71         DEBUG(10, ("Opening [%s]\n", initdfile));
72         fd = -1;
73         fd = open(initdfile,O_RDONLY);
74         *numlines = 0;
75
76         if (fd == -1) {
77                 DEBUG(10, ("Couldn't open [%s]\n", initdfile));
78                 return False;
79         }
80
81         qlines = fd_lines_load(fd, numlines);
82         DEBUGADD(10, ("Lines returned = [%d]\n", *numlines));
83         close(fd);
84     
85
86         if (*numlines) {
87         
88                 for(i = 0; i < *numlines; i++) {
89
90                         DEBUGADD(10, ("Line[%d] = %s\n", i, qlines[i]));
91                         if (!in_section && (0==strwicmp("### BEGIN INIT INFO", qlines[i]))) {
92                                 /* we now can look for params */
93                                 DEBUGADD(10, ("Configuration information starts on line = [%d]\n", i));
94                                 in_section = 1;
95
96                         } else if (in_section && (0==strwicmp("### END INIT INFO", qlines[i]))) {
97                                 DEBUGADD(10, ("Configuration information ends on line = [%d]\n", i));
98                                 DEBUGADD(10, ("Description is [%s]\n", si->description));
99                                 in_description = 0;
100                                 in_section = 0;
101                                 break;
102                         } else if (in_section) {
103                                 tokenptr = qlines[i];
104                                 if (in_description) {
105                                         DEBUGADD(10, ("Processing DESCRIPTION [%d]\n", *tokenptr));
106                                         if (tokenptr && (*tokenptr=='#') && (*(tokenptr+1)=='\t')) {
107                                                 DEBUGADD(10, ("Adding to DESCRIPTION [%d]\n", *tokenptr));
108                                                 pstrcat(si->description," ");
109                                                 pstrcat(si->description,tokenptr+2);
110                                                 continue;
111                                         }
112                                         in_description = 0;
113                                         DEBUGADD(10, ("Not a description!\n"));
114                                 }
115                                 if (!next_token(&tokenptr,mybuffer," \t",sizeof(mybuffer))) {
116                                         DEBUGADD(10, ("Invalid line [%d]\n", i));
117                                         break; /* bad line? */
118                                 }
119                                 if (0 != strncmp(mybuffer,"#",1)) {
120                                         DEBUGADD(10, ("Invalid line [%d], is %s\n", i,mybuffer));
121                                         break;
122                                 }
123                                 if (!next_token(&tokenptr,mybuffer," \t",sizeof(mybuffer))) {
124                                         DEBUGADD(10, ("Invalid token on line [%d]\n", i));
125                                         break; /* bad line? */
126                                 }             
127                                 DEBUGADD(10, ("Keyword is  [%s]\n", mybuffer));
128                                 if (0==strwicmp(mybuffer,"Description:")) {
129                                         while (tokenptr && *tokenptr && (strchr(" \t",*tokenptr))) { 
130                                                 tokenptr++; 
131                                         }
132                                         pstrcpy(si->description,tokenptr);
133                                         DEBUGADD(10, ("FOUND DESCRIPTION! Data is [%s]\n", tokenptr));
134                                         in_description = 1;
135                                 } else {
136                                         while (tokenptr && *tokenptr && (strchr(" \t",*tokenptr))) { 
137                                                 tokenptr++; 
138                                         }
139                                         DEBUGADD(10, ("Data is [%s]\n", tokenptr));
140                                         in_description = 0;
141
142                                         /* save certain keywords, don't save others */
143                                         if (0==strwicmp(mybuffer, "Provides:")) {
144                                                 pstrcpy(si->provides,tokenptr);
145                                                 pstrcpy(si->servicename,tokenptr);
146                                         }
147
148                                         if (0==strwicmp(mybuffer, "Short-Description:")) {
149                                                 pstrcpy(si->shortdescription,tokenptr);
150                                         }
151
152                                         if (0==strwicmp(mybuffer, "Required-start:")) {
153                                                 pstrcpy(si->requiredstart,tokenptr);
154                                                 pstrcpy(si->dependencies,tokenptr);
155                                         }
156
157                                         if (0==strwicmp(mybuffer, "Should-start:")) {
158                                                 pstrcpy(si->shouldstart,tokenptr);
159                                         }
160                                 }
161                         }
162                 }
163
164                 file_lines_free(qlines);
165                         return True;
166         }
167
168         return False;
169 }
170
171 /*********************************************************************
172 *********************************************************************/
173
174 static WERROR rcinit_stop( const char *service, SERVICE_STATUS *status )
175 {
176         pstring command;
177         int ret, fd;
178         
179         pstr_sprintf( command, "%s/%s/%s stop", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, service );
180         
181         /* we've already performed the access check when the service was opened */
182         
183         become_root();
184         ret = smbrun( command , &fd );
185         unbecome_root();
186         
187         DEBUGADD(5, ("rcinit_start: [%s] returned [%d]\n", command, ret));
188         close(fd);
189         
190         ZERO_STRUCTP( status );
191         status->type = 0x0020;
192         status->state = (ret == 0 ) ? 0x0001 : 0x0004;
193         status->controls_accepted = 0x0005;
194
195         return ( ret == 0 ) ? WERR_OK : WERR_ACCESS_DENIED;
196 }
197
198 /*********************************************************************
199 *********************************************************************/
200
201 static WERROR rcinit_start( const char *service )
202 {
203         pstring command;
204         int ret, fd;
205         
206         pstr_sprintf( command, "%s/%s/%s start", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, service );
207         
208         /* we've already performed the access check when the service was opened */
209         
210         become_root();
211         ret = smbrun( command , &fd );
212         unbecome_root();
213         
214         DEBUGADD(5, ("rcinit_start: [%s] returned [%d]\n", command, ret));
215         close(fd);      
216
217         return ( ret == 0 ) ? WERR_OK : WERR_ACCESS_DENIED;
218 }
219
220 /*********************************************************************
221 *********************************************************************/
222
223 static WERROR rcinit_status( const char *service, SERVICE_STATUS *status )
224 {
225         pstring command;
226         int ret, fd;
227         
228         pstr_sprintf( command, "%s/%s/%s status", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, service );
229         
230         /* we've already performed the access check when the service was opened */
231         /* assume as return code of 0 means that the service is ok.  Anything else
232            is STOPPED */
233         
234         become_root();
235         ret = smbrun( command , &fd );
236         unbecome_root();
237         
238         DEBUGADD(5, ("rcinit_start: [%s] returned [%d]\n", command, ret));
239         close(fd);
240         
241         ZERO_STRUCTP( status );
242         status->type = 0x0020;
243         status->state = (ret == 0 ) ? 0x0004 : 0x0001;
244         status->controls_accepted = 0x0005;
245
246         return WERR_OK;
247 }
248
249 /*********************************************************************
250 *********************************************************************/
251
252 /* struct for svcctl control to manipulate rcinit service */
253
254 SERVICE_CONTROL_OPS rcinit_svc_ops = {
255         rcinit_stop,
256         rcinit_start,
257         rcinit_status
258 };