1 kumpf 1.1 //%2006////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 kumpf 1.1 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 //%/////////////////////////////////////////////////////////////////////////////
33
34 #include <Pegasus/Common/System.h>
35 #include <Pegasus/Common/Signal.h>
36 #include <Pegasus/Common/AutoPtr.h>
37 #include <Service/PidFile.h>
38 #include <Service/ServerRunStatus.h>
39
40 #include <sys/types.h>
41 #include <sys/stat.h>
42
43 kumpf 1.1 #if defined(PEGASUS_OS_HPUX)
44 # include <sys/pstat.h>
45 # include <libgen.h>
46 #endif
47
48 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
49 # include <sys/ps.h>
50 #endif
51
52 #if defined(PEGASUS_OS_AIX)
53 extern "C"
54 {
55 # include <procinfo.h>
56 extern int getprocs(struct procsinfo *, int, struct fdsinfo *, int,pid_t *,int);
57 # define PROCSIZE sizeof(struct procsinfo)
58 }
59 #endif
60
61 PEGASUS_NAMESPACE_BEGIN
62
63 #ifdef PEGASUS_OS_TYPE_WINDOWS
64 kumpf 1.1
65 //////////////////////////////////////
66 //
67 // Windows implementation
68 //
69 //////////////////////////////////////
70
71 ServerRunStatus::ServerRunStatus(
72 const char* serverName,
73 const char* pidFilePath)
74 : _serverName(serverName),
75 _pidFilePath(pidFilePath),
76 _parentPid(0),
77 _event(NULL),
78 _wasAlreadyRunning(false)
79 {
80 }
81
82 ServerRunStatus::~ServerRunStatus()
83 {
84 if (_event != NULL)
85 kumpf 1.1 {
86 CloseHandle(_event);
87 }
88 }
89
90 Boolean ServerRunStatus::isServerRunning()
91 {
|
117 kumpf 1.1
118 //////////////////////////////////////
119 //
120 // Unix and OpenVMS implementation
121 //
122 //////////////////////////////////////
123
124 ServerRunStatus::ServerRunStatus(
125 const char* serverName,
126 const char* pidFilePath)
127 : _serverName(serverName),
128 _pidFilePath(pidFilePath),
129 _parentPid(0)
130 {
131 }
132
133 ServerRunStatus::~ServerRunStatus()
134 {
135 }
136
137 Boolean ServerRunStatus::isServerRunning()
138 kumpf 1.1 {
139 PidFile pidFile(_pidFilePath);
140 PEGASUS_PID_T pid = (PEGASUS_PID_T) pidFile.getPid();
141
142 if (pid == 0)
143 {
144 return false;
145 }
146
147 return (pid != (PEGASUS_PID_T) System::getPID()) &&
148 (pid != _parentPid) &&
149 _isServerProcess(pid);
150 }
151
152 void ServerRunStatus::setServerRunning()
153 {
154 PidFile pidFile(_pidFilePath);
155 pidFile.setPid(System::getPID());
156 }
157
158 void ServerRunStatus::setParentPid(PEGASUS_PID_T parentPid)
159 kumpf 1.1 {
160 _parentPid = parentPid;
161 }
162
163 Boolean ServerRunStatus::kill()
164 {
165 PidFile pidFile(_pidFilePath);
166 PEGASUS_PID_T pid = (PEGASUS_PID_T) pidFile.getPid();
167
168 if ((pid == 0) ||
169 (pid == (PEGASUS_PID_T) System::getPID()) ||
170 (pid == _parentPid) ||
171 !_isServerProcess(pid))
172 {
173 pidFile.remove();
174 return false;
175 }
176
177 #if defined(PEGASUS_OS_HPUX) || \
178 defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || \
179 defined(PEGASUS_OS_SOLARIS) || \
180 kumpf 1.1 defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) || \
181 defined(PEGASUS_OS_AIX)
182
183 ::kill(pid, SIGKILL);
184
185 #endif
186
187 pidFile.remove();
188 return true;
189 }
190
191 # if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
192
193 ///////////////////////////////////////////////////////
194 // z/OS implementation of _isServerProcess
195 ///////////////////////////////////////////////////////
196 Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
197 {
198 W_PSPROC buf;
199 int token = 0;
200 memset(&buf, 0x00, sizeof(buf));
201 kumpf 1.1 buf.ps_conttyptr =(char *) malloc(buf.ps_conttylen =PS_CONTTYBLEN);
202 buf.ps_pathptr =(char *) malloc(buf.ps_pathlen =PS_PATHBLEN);
203 buf.ps_cmdptr =(char *) malloc(buf.ps_cmdlen =PS_CMDBLEN);
204 Boolean returnValue = false;
205
206 while ((token = w_getpsent(token, &buf, sizeof(buf))) > 0)
207 {
208 if (buf.ps_pid == pid)
209 {
210 // If the process id is associated with the server program,
211 // then a server is still running.
212 if (strstr(buf.ps_pathptr, _serverName) != NULL)
213 {
214 returnValue = true;
215 }
216 // else the pid was not associated with the server
217 break;
218 }
219 }
220
221 free(buf.ps_conttyptr);
222 kumpf 1.1 free(buf.ps_pathptr);
223 free(buf.ps_cmdptr);
224 return returnValue;
225 }
226
227 # elif defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || \
228 defined(PEGASUS_OS_SOLARIS)
229
230 ///////////////////////////////////////////////////////
231 // Linux and Solaris implementation of _isServerProcess
232 ///////////////////////////////////////////////////////
233 /*
234 Opens the 'stat' file in the /proc/<pid> directory to
235 verify that the process name is that of the server.
236 */
237 static Boolean _isServerPidDir(
238 const char *directory,
239 const char* serverProcessName)
240 {
241 static char filename[80];
242 static char buffer[512];
243 kumpf 1.1 int fd, bytesRead;
244
245 // generate the name of the stat file in the process's /proc directory,
246 // and open it
247 sprintf(filename, "%s/%s", directory, "stat");
248 if ( (fd = open(filename, O_RDONLY, 0)) == -1 )
249 {
250 return false;
251 }
252
253 // read the contents
254 if ( (bytesRead = read( fd, buffer, (sizeof buffer) - 1 )) <= 0 )
255 {
256 close(fd);
257 return false;
258 }
259
260 // null terminate the file contents
261 buffer[bytesRead] = 0;
262
263 close(fd);
264 kumpf 1.1
265 // the process name is the second element of the file contents and
266 // is surrounded by parentheses.
267 //
268 // find the positions of the parentheses in the file contents
269 const char* openParen;
270 const char* closeParen;
271
272 openParen = strchr(buffer, '(');
273 closeParen = strchr(buffer, ')');
274 if (openParen == NULL || closeParen == NULL || closeParen < openParen)
275 {
276 return false;
277 }
278
279 // allocate memory for the result
280 AutoArrayPtr<char> processName(new char[closeParen - openParen]);
281
282 // copy the process name into the result
283 strncpy(processName.get(), openParen + 1, closeParen - openParen -1);
284
285 kumpf 1.1 // strncpy doesn't NULL-terminate the result, so do it here
286 processName[closeParen - openParen -1] = '\0';
287
288 return strcmp(processName.get(), serverProcessName) == 0;
289 }
290
291 Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
292 {
293 // This method makes a stat() system call on the directory in /proc
294 // with a name that matches the pid of the server. It returns true
295 // if it successfully located the process dir and verified that the
296 // process name matches that of the server.
297
298 static char path[32];
299 static struct stat statBuffer;
300
301 sprintf(path, "/proc/%d", pid);
302 if (stat(path, &statBuffer) == -1) // process stopped running
303 {
304 return false;
305 }
306 kumpf 1.1
307 // get the process name to make sure it is the cimserver process
308 // ATTN: skip verify for Solaris
309 # if !defined(PEGASUS_OS_SOLARIS)
310 if (!_isServerPidDir(path, _serverName))
311 {
312 return false;
313 }
314 # endif
315
316 return true;
317 }
318
319 # elif defined(PEGASUS_OS_AIX)
320
321 ///////////////////////////////////////////////////////
322 // AIX implementation of _isServerProcess
323 ///////////////////////////////////////////////////////
324 /*
325 Calls subroutine getprocs() to get information about all processes.
326 If successful, an array of procsinfo structures filled with process table
327 kumpf 1.1 entries is returned. Otherwise, a null pointer is returned.
328 The output parameter cnt specifies the number of the processes in the
329 returned table.
330 */
331 static struct procsinfo* _getProcessData(int& cnt)
332 {
333 struct procsinfo* proctable = NULL;
334 struct procsinfo* rtnp = NULL;
335 int count = 1048576;
336 int rtncnt;
337 int repeat = 1;
338 int nextp = 0;
339
340 cnt = 0;
341 while (repeat &&
342 (rtncnt = getprocs(rtnp, PROCSIZE, 0, 0, &nextp, count) > 0))
343 {
344 if (!rtnp)
345 {
346 count=rtncnt;
347 proctable = (struct procsinfo*) malloc((size_t) PROCSIZE*count);
348 kumpf 1.1 if (!proctable)
349 {
350 return NULL;
351 }
352 rtnp = proctable;
353 nextp = 0;
354 }
355 else
356 {
357 cnt += rtncnt;
358 if (rtncnt >= count)
359 {
360 proctable=(struct procsinfo *) realloc(
361 (void*)proctable, (size_t) (PROCSIZE*(cnt+count)));
362 if (!proctable)
363 {
364 return NULL;
365 }
366 rtnp = proctable+(cnt);
367 }
368 else
369 kumpf 1.1 {
370 repeat = 0;
371 }
372 } // end of if(!rtnp)
373 } //end of while
374 return proctable;
375 }
376
377 Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
378 {
379 int count;
380 struct procsinfo* proctable;
381
382 proctable = _getProcessData(count);
383 if (proctable == NULL)
384 {
385 return false;
386 }
387
388 for (int i=0; i < count; i++)
389 {
390 kumpf 1.1 if (!strcmp(proctable[i].pi_comm, _serverName) && \
391 proctable[i].pi_pid == pid)
392 {
393 free(proctable);
394 return true;
395 }
396 }
397
398 free(proctable);
399 return false;
400 }
401
402 # elif defined(PEGASUS_OS_HPUX)
403
404 ///////////////////////////////////////////////////////
405 // HP-UX implementation of _isServerProcess
406 ///////////////////////////////////////////////////////
407 Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
408 {
409 struct pst_status pstru;
410
411 kumpf 1.1 if (pstat_getproc(&pstru, sizeof(struct pst_status), (size_t)0, pid) != -1)
412 {
413 //
414 // Gets the command basename disregarding the command parameters
415 //
416 char *execName = strchr(pstru.pst_cmd,' ');
417 if (execName)
418 {
419 *execName = '\0';
420 }
421 execName = basename(pstru.pst_cmd);
422
423 if (strcmp(execName, _serverName) == 0)
424 {
425 return true;
426 }
427 }
428
429 return false;
430 }
431
432 kumpf 1.1 # else
433
434 ///////////////////////////////////////////////////////
435 // Generic implementation of _isServerProcess
436 ///////////////////////////////////////////////////////
437 Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
438 {
439 return false;
440 }
441
442 # endif
443
444 #endif
445
446 PEGASUS_NAMESPACE_END
|