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 #if defined(PEGASUS_OS_OS400)
62 # include <Pegasus/Common/Logger.h>
63 # include "OS400ConvertChar.h"
64 kumpf 1.1 #endif
65
66 PEGASUS_NAMESPACE_BEGIN
67
68 #ifdef PEGASUS_OS_TYPE_WINDOWS
69
70 //////////////////////////////////////
71 //
72 // Windows implementation
73 //
74 //////////////////////////////////////
75
76 ServerRunStatus::ServerRunStatus(
77 const char* serverName,
78 const char* pidFilePath)
79 : _serverName(serverName),
80 _pidFilePath(pidFilePath),
81 _parentPid(0),
82 _event(NULL),
83 _wasAlreadyRunning(false)
84 {
85 kumpf 1.1 }
86
87 ServerRunStatus::~ServerRunStatus()
88 {
89 if (_event != NULL)
90 {
91 CloseHandle(_event);
92 }
93 }
94
95 Boolean ServerRunStatus::isServerRunning()
96 {
|
122 kumpf 1.1
123 //////////////////////////////////////
124 //
125 // Unix and OpenVMS implementation
126 //
127 //////////////////////////////////////
128
129 ServerRunStatus::ServerRunStatus(
130 const char* serverName,
131 const char* pidFilePath)
132 : _serverName(serverName),
133 _pidFilePath(pidFilePath),
134 _parentPid(0)
135 {
136 }
137
138 ServerRunStatus::~ServerRunStatus()
139 {
140 }
141
142 Boolean ServerRunStatus::isServerRunning()
143 kumpf 1.1 {
144 PidFile pidFile(_pidFilePath);
145 PEGASUS_PID_T pid = (PEGASUS_PID_T) pidFile.getPid();
146
147 if (pid == 0)
148 {
149 return false;
150 }
151
152 return (pid != (PEGASUS_PID_T) System::getPID()) &&
153 (pid != _parentPid) &&
154 _isServerProcess(pid);
155 }
156
157 void ServerRunStatus::setServerRunning()
158 {
159 PidFile pidFile(_pidFilePath);
160 pidFile.setPid(System::getPID());
161 }
162
163 void ServerRunStatus::setParentPid(PEGASUS_PID_T parentPid)
164 kumpf 1.1 {
165 _parentPid = parentPid;
166 }
167
168 Boolean ServerRunStatus::kill()
169 {
170 PidFile pidFile(_pidFilePath);
171 PEGASUS_PID_T pid = (PEGASUS_PID_T) pidFile.getPid();
172
173 if ((pid == 0) ||
174 (pid == (PEGASUS_PID_T) System::getPID()) ||
175 (pid == _parentPid) ||
176 !_isServerProcess(pid))
177 {
178 pidFile.remove();
179 return false;
180 }
181
182 #if defined(PEGASUS_OS_HPUX) || \
183 defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || \
184 defined(PEGASUS_OS_SOLARIS) || \
185 kumpf 1.1 defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) || \
186 defined(PEGASUS_OS_AIX)
187
188 ::kill(pid, SIGKILL);
189
190 #endif
191
192 pidFile.remove();
193 return true;
194 }
195
196 # if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
197
198 ///////////////////////////////////////////////////////
199 // z/OS implementation of _isServerProcess
200 ///////////////////////////////////////////////////////
201 Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
202 {
203 W_PSPROC buf;
204 int token = 0;
205 memset(&buf, 0x00, sizeof(buf));
206 kumpf 1.1 buf.ps_conttyptr =(char *) malloc(buf.ps_conttylen =PS_CONTTYBLEN);
207 buf.ps_pathptr =(char *) malloc(buf.ps_pathlen =PS_PATHBLEN);
208 buf.ps_cmdptr =(char *) malloc(buf.ps_cmdlen =PS_CMDBLEN);
209 Boolean returnValue = false;
210
211 while ((token = w_getpsent(token, &buf, sizeof(buf))) > 0)
212 {
213 if (buf.ps_pid == pid)
214 {
215 // If the process id is associated with the server program,
216 // then a server is still running.
217 if (strstr(buf.ps_pathptr, _serverName) != NULL)
218 {
219 returnValue = true;
220 }
221 // else the pid was not associated with the server
222 break;
223 }
224 }
225
226 free(buf.ps_conttyptr);
227 kumpf 1.1 free(buf.ps_pathptr);
228 free(buf.ps_cmdptr);
229 return returnValue;
230 }
231
232 # elif defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || \
233 defined(PEGASUS_OS_SOLARIS)
234
235 ///////////////////////////////////////////////////////
236 // Linux and Solaris implementation of _isServerProcess
237 ///////////////////////////////////////////////////////
238 /*
239 Opens the 'stat' file in the /proc/<pid> directory to
240 verify that the process name is that of the server.
241 */
242 static Boolean _isServerPidDir(
243 const char *directory,
244 const char* serverProcessName)
245 {
246 static char filename[80];
247 static char buffer[512];
248 kumpf 1.1 int fd, bytesRead;
249
250 // generate the name of the stat file in the process's /proc directory,
251 // and open it
252 sprintf(filename, "%s/%s", directory, "stat");
253 if ( (fd = open(filename, O_RDONLY, 0)) == -1 )
254 {
255 return false;
256 }
257
258 // read the contents
259 if ( (bytesRead = read( fd, buffer, (sizeof buffer) - 1 )) <= 0 )
260 {
261 close(fd);
262 return false;
263 }
264
265 // null terminate the file contents
266 buffer[bytesRead] = 0;
267
268 close(fd);
269 kumpf 1.1
270 // the process name is the second element of the file contents and
271 // is surrounded by parentheses.
272 //
273 // find the positions of the parentheses in the file contents
274 const char* openParen;
275 const char* closeParen;
276
277 openParen = strchr(buffer, '(');
278 closeParen = strchr(buffer, ')');
279 if (openParen == NULL || closeParen == NULL || closeParen < openParen)
280 {
281 return false;
282 }
283
284 // allocate memory for the result
285 AutoArrayPtr<char> processName(new char[closeParen - openParen]);
286
287 // copy the process name into the result
288 strncpy(processName.get(), openParen + 1, closeParen - openParen -1);
289
290 kumpf 1.1 // strncpy doesn't NULL-terminate the result, so do it here
291 processName[closeParen - openParen -1] = '\0';
292
293 return strcmp(processName.get(), serverProcessName) == 0;
294 }
295
296 Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
297 {
298 // This method makes a stat() system call on the directory in /proc
299 // with a name that matches the pid of the server. It returns true
300 // if it successfully located the process dir and verified that the
301 // process name matches that of the server.
302
303 static char path[32];
304 static struct stat statBuffer;
305
306 sprintf(path, "/proc/%d", pid);
307 if (stat(path, &statBuffer) == -1) // process stopped running
308 {
309 return false;
310 }
311 kumpf 1.1
312 // get the process name to make sure it is the cimserver process
313 // ATTN: skip verify for Solaris
314 # if !defined(PEGASUS_OS_SOLARIS)
315 if (!_isServerPidDir(path, _serverName))
316 {
317 return false;
318 }
319 # endif
320
321 return true;
322 }
323
324 # elif defined(PEGASUS_OS_AIX)
325
326 ///////////////////////////////////////////////////////
327 // AIX implementation of _isServerProcess
328 ///////////////////////////////////////////////////////
329 /*
330 Calls subroutine getprocs() to get information about all processes.
331 If successful, an array of procsinfo structures filled with process table
332 kumpf 1.1 entries is returned. Otherwise, a null pointer is returned.
333 The output parameter cnt specifies the number of the processes in the
334 returned table.
335 */
336 static struct procsinfo* _getProcessData(int& cnt)
337 {
338 struct procsinfo* proctable = NULL;
339 struct procsinfo* rtnp = NULL;
340 int count = 1048576;
341 int rtncnt;
342 int repeat = 1;
343 int nextp = 0;
344
345 cnt = 0;
346 while (repeat &&
347 (rtncnt = getprocs(rtnp, PROCSIZE, 0, 0, &nextp, count) > 0))
348 {
349 if (!rtnp)
350 {
351 count=rtncnt;
352 proctable = (struct procsinfo*) malloc((size_t) PROCSIZE*count);
353 kumpf 1.1 if (!proctable)
354 {
355 return NULL;
356 }
357 rtnp = proctable;
358 nextp = 0;
359 }
360 else
361 {
362 cnt += rtncnt;
363 if (rtncnt >= count)
364 {
365 proctable=(struct procsinfo *) realloc(
366 (void*)proctable, (size_t) (PROCSIZE*(cnt+count)));
367 if (!proctable)
368 {
369 return NULL;
370 }
371 rtnp = proctable+(cnt);
372 }
373 else
374 kumpf 1.1 {
375 repeat = 0;
376 }
377 } // end of if(!rtnp)
378 } //end of while
379 return proctable;
380 }
381
382 Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
383 {
384 int count;
385 struct procsinfo* proctable;
386
387 proctable = _getProcessData(count);
388 if (proctable == NULL)
389 {
390 return false;
391 }
392
393 for (int i=0; i < count; i++)
394 {
395 kumpf 1.1 if (!strcmp(proctable[i].pi_comm, _serverName) && \
396 proctable[i].pi_pid == pid)
397 {
398 free(proctable);
399 return true;
400 }
401 }
402
403 free(proctable);
404 return false;
405 }
406
407 # elif defined(PEGASUS_OS_HPUX)
408
409 ///////////////////////////////////////////////////////
410 // HP-UX implementation of _isServerProcess
411 ///////////////////////////////////////////////////////
412 Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
413 {
414 struct pst_status pstru;
415
416 kumpf 1.1 if (pstat_getproc(&pstru, sizeof(struct pst_status), (size_t)0, pid) != -1)
417 {
418 //
419 // Gets the command basename disregarding the command parameters
420 //
421 char *execName = strchr(pstru.pst_cmd,' ');
422 if (execName)
423 {
424 *execName = '\0';
425 }
426 execName = basename(pstru.pst_cmd);
427
428 if (strcmp(execName, _serverName) == 0)
429 {
430 return true;
431 }
432 }
433
434 return false;
435 }
436
437 kumpf 1.1 # else
438
439 ///////////////////////////////////////////////////////
440 // Generic implementation of _isServerProcess
441 ///////////////////////////////////////////////////////
442 Boolean ServerRunStatus::_isServerProcess(PEGASUS_PID_T pid)
443 {
444 return false;
445 }
446
447 # endif
448
449 #elif defined(PEGASUS_OS_OS400)
450
451 //////////////////////////////////////
452 //
453 // OS/400 implementation
454 //
455 //////////////////////////////////////
456
457 ServerRunStatus::ServerRunStatus(
458 kumpf 1.1 const char* serverName,
459 const char* pidFilePath)
460 : _serverName(serverName),
461 _pidFilePath(pidFilePath),
462 _parentPid(0)
463 {
464 }
465
466 ServerRunStatus::~ServerRunStatus()
467 {
468 }
469
470 /*
471 NOTE: This implementation is specific to the CIM Server.
472 */
473 Boolean ServerRunStatus::isServerRunning()
474 {
475 #pragma convert(37)
476 // Construct a ycmJob object
477 ycmJob cppJob(YCMJOB_SRVNAME_10, YCMJOB_SRVUSER_10);
478
479 kumpf 1.1 // Find the QYCMCIMOM job
480 char cppStatus = cppJob.find(YCMJOB_ALL_NUMBERS);
481
482 if (cppStatus == YCMJOB_FOUND) // CIMOM Server is Running
483 {
484 return true;
485 }
486
487 return false;
488 #pragma convert(0)
489 }
490
491 void ServerRunStatus::setServerRunning()
492 {
493 }
494
495 void ServerRunStatus::setParentPid(PEGASUS_PID_T parentPid)
496 {
497 }
498
499 /*
500 kumpf 1.1 The iSeries qycmctlcimCimomServer.C (QYCMCTLCIM program) code has
501 already checked that the server is already running prior to calling
502 the CIMOM server (QYCMCIMOM) and telling it to shutdown.
503 However, a check is still made in this method because we have to
504 find the job number in order to kill the job.
505
506 For iSeries, this method is called regardless of whether we took
507 errors trying to connect to the server - if the CIMOM server job
508 is anywhere on the system, in any state, this method will find it
509 and kill it dead!!
510
511 NEVER call this method unless the server is unable to be shut down
512 gracefully.
513
514 NOTE: This implementation is specific to the CIM Server.
515 */
516 Boolean ServerRunStatus::kill()
517 {
518 #pragma convert(37)
519 char rc2[3] = "02"; // CIMOM server failed to end
520 char cppServ[10] = "QYCMCIMOM";
521 kumpf 1.1
522 // Construct a ycmJob object
523 ycmJob cppJob(YCMJOB_SRVNAME_10, YCMJOB_SRVUSER_10);
524 // Find the QYCMCIMOM job
525 char cppStatus = cppJob.find(YCMJOB_ALL_NUMBERS);
526
527 if (cppStatus == YCMJOB_FOUND) // CIMOM Server is Running
528 {
529 if (cppJob.end((char *)cppJob.getNumber().c_str(), 'C', 30) ==
530 YCMJOB_END_FAILED)
531 {
532 char chData[sizeof(rc2)+sizeof(cppServ)];
533 strcpy((char *)&chData,rc2);
534 strcat(chData,cppServ);
535
536 ycmMessage message(
537 "CPDDF81",
538 chData,
539 strlen(chData),
540 "cimserver_os400::cimserver_kill()",
541 ycmCTLCIMID,
542 kumpf 1.1 utf8);
543 message.joblogIt(UserError,ycmMessage::Diagnostic);
544
545 #pragma convert(0)
546
547 Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
548 "src.Server.cimserver_os400.FAILED_TO_END_JOB",
549 "$0 FAILED to end the $1 job!!",
550 "cimserver_os400::cimserver_kill -",
551 "QYCMCIMOM");
552
553 return false; // Note: this return code is ignored
554 }
555 }
556
557 // The case of the job not found is already handled in QYCMCTLCIM program
558 return true;
559 }
560
561 #endif
562
563 kumpf 1.1 PEGASUS_NAMESPACE_END
|