1 karl 1.8 //%2006////////////////////////////////////////////////////////////////////////
|
2 h.sterling 1.1 //
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 karl 1.8 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 h.sterling 1.1 //
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 // 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 // Author: Mike Day (mdday@us.ibm.com)
33 //
34 h.sterling 1.1 // Modified By: Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
35 // Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com)
36 // Marek Szermutzky, IBM (ddt6szer@de.ibm.com)
37 //%/////////////////////////////////////////////////////////////////////////////
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #if defined(PEGASUS_OS_HPUX)
41 #include <sys/pstat.h>
|
42 mateus.baur 1.11.18.1 #include <libgen.h>
|
43 h.sterling 1.1 #endif
44 #include <fcntl.h>
45 #include <unistd.h>
46 #include <Pegasus/Common/Signal.h>
|
47 mike 1.11 #include <Pegasus/Common/AutoPtr.h>
|
48 h.sterling 1.1 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
49 #include <sys/ps.h>
50 #endif
|
51 w.otsuka 1.4 #define MAX_WAIT_TIME 240
|
52 h.sterling 1.1 #if defined(PEGASUS_OS_AIX)
53 extern "C" {
54 #include <procinfo.h>
55 extern int getprocs(struct procsinfo *, int, struct fdsinfo *, int,pid_t *,int);
56 #define PROCSIZE sizeof(struct procsinfo)
57 }
58 #endif
59
60 PEGASUS_USING_PEGASUS;
61 PEGASUS_USING_STD;
62
63 Boolean handleSigUsr1 = false;
64 Boolean graveError = false;
65
|
66 r.kieninger 1.9 // the current pid is the server pid. After fork it is overwritten.
67 pid_t server_pid = getpid();
|
68 h.sterling 1.3 Uint32 parentPid = 0;
|
69 h.sterling 1.1
70 void sigUsr1Handler(int s_n, PEGASUS_SIGINFO_T * s_info, void * sig)
71 {
72 handleSigUsr1 = true;
73 }
74
75 void sigTermHandler(int s_n, PEGASUS_SIGINFO_T * s_info, void * sig)
76 {
77 graveError= handleSigUsr1=true;
78 }
79
80
81 //constructor
82 ServerProcess::ServerProcess() {}
83
84 //destructor
85 ServerProcess::~ServerProcess() {}
86
87 // no-ops
88 void ServerProcess::cimserver_set_process(void* p) {}
89 void ServerProcess::cimserver_exitRC(int rc) {}
90 h.sterling 1.1 int ServerProcess::cimserver_initialize(void) { return 1; }
|
91 marek 1.10
92 // for all OSes supporting signals provide a cimserver_wait function
93 // that waits to be awakened by signal PEGASUS_SIGTERM or PEGASUS_SIGHUP
94 #ifdef PEGASUS_HAS_SIGNALS
95 int ServerProcess::cimserver_wait(void)
96 {
97 int sig = -1;
98 sigset_t set;
99 sigemptyset(&set);
100 sigaddset(&set, PEGASUS_SIGTERM);
101 sigaddset(&set, PEGASUS_SIGHUP);
102 errno = 0;
103 do
104 {
105 #if defined(PEGASUS_OS_ZOS) || defined(PEGASUS_OS_SOLARIS)
106 sig = sigwait(&set);
107 #else // else for platforms = LINUX, HPUX, AIX
108 sigwait(&set, &sig);
109 #endif
110 } while (errno == EINTR);
111 return sig;
112 marek 1.10 }
113 #else
|
114 h.sterling 1.1 int ServerProcess::cimserver_wait(void) { return 1; }
|
115 marek 1.10 #endif
116
|
117 h.sterling 1.1 String ServerProcess::getHome(void) { return String::EMPTY; }
118
119 // daemon_init , RW Stevens, "Advance UNIX Programming"
120
121 int ServerProcess::cimserver_fork(void)
122 {
123 getSigHandle()->registerHandler(PEGASUS_SIGUSR1, sigUsr1Handler);
124 getSigHandle()->activate(PEGASUS_SIGUSR1);
125 getSigHandle()->registerHandler(SIGTERM, sigTermHandler);
126 getSigHandle()->activate(SIGTERM);
127
128 pid_t pid;
129 if( (pid = fork() ) < 0)
130 {
131 getSigHandle()->deactivate(PEGASUS_SIGUSR1);
132 getSigHandle()->deactivate(SIGTERM);
133 return(-1);
134 }
135 else if (pid != 0)
136 {
137 //
138 h.sterling 1.1 // parent wait for child
139 // if there is a problem with signal, parent process terminates
140 // when waitTime expires
141 //
142 Uint32 waitTime = MAX_WAIT_TIME;
143
144 while(!handleSigUsr1 && waitTime > 0)
145 {
146 sleep(1);
147 waitTime--;
148 }
|
149 w.otsuka 1.4 if( !handleSigUsr1 )
150 {
151 MessageLoaderParms parms("src.Service.ServerProcessUnix.CIMSERVER_START_TIMEOUT",
152 "The cimserver command timed out waiting for the CIM server to start.");
153 PEGASUS_STD(cerr) << MessageLoader::getMessage(parms) << PEGASUS_STD(endl);
154 }
|
155 h.sterling 1.1 exit(graveError);
156 }
157
158 setsid();
|
159 marek 1.10 umask(S_IRWXG | S_IRWXO );
160
161 // spawned daemon process doesn't need the old signal handlers of its parent
162 getSigHandle()->deactivate(PEGASUS_SIGUSR1);
163 getSigHandle()->deactivate(SIGTERM);
|
164 h.sterling 1.1
165 // get the pid of the cimserver process
166 server_pid = getpid();
167 return(0);
168 }
169
170 long ServerProcess::get_server_pid()
171 {
172 return server_pid;
173 }
174
|
175 h.sterling 1.3 void ServerProcess::set_parent_pid(int pid)
176 {
177 parentPid = pid;
178 }
179
180
|
181 jim.wunderlich 1.5 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_OS_SOLARIS)
|
182 h.sterling 1.1
183 //===========================================================================
184 // NAME : verify_process_name
185 // DESCRIPTION : Opens the 'stat' file in the /proc/<pid> directory to
186 // verify that the process name is that of the cimserver.
187 //===========================================================================
188 int verify_process_name(char *directory, const char* server_process_name)
189 {
190 static char filename[80];
191 static char buffer[512];
192 int fd, bytesRead;
193
194 // generate the name of the stat file in the process's /proc directory,
195 // and open it
196 sprintf(filename, "%s/%s", directory, "stat");
197 if ( (fd = open(filename, O_RDONLY, 0)) == -1 )
198 {
199 return -1;
200 }
201
202 // read the contents
203 h.sterling 1.1 if ( (bytesRead = read( fd, buffer, (sizeof buffer) - 1 )) <= 0 )
204 {
205 close(fd);
206 return -1;
207 }
208
209 // null terminate the file contents
210 buffer[bytesRead] = 0;
211
212 close(fd);
213
214 // the process name is the second element of the file contents and
215 // is surrounded by parentheses.
216 //
217 // find the positions of the parentheses in the file contents
218 char * open_paren;
219 char * close_paren;
220
221 open_paren = strchr (buffer, '(');
222 close_paren = strchr (buffer, ')');
223 if (open_paren == NULL || close_paren == NULL || close_paren < open_paren)
224 h.sterling 1.1 {
225 return -1;
226 }
227
228 // allocate memory for the result
|
229 kumpf 1.6 AutoArrayPtr<char> process_name(new char[close_paren - open_paren]);
|
230 h.sterling 1.1
231 // copy the process name into the result
|
232 kumpf 1.6 strncpy (process_name.get(), open_paren + 1, close_paren - open_paren -1);
|
233 h.sterling 1.1
234 // strncpy doesn't NULL-terminate the result, so do it here
|
235 kumpf 1.6 process_name.get()[close_paren - open_paren -1] = '\0';
|
236 h.sterling 1.1
|
237 kumpf 1.6 if (strcmp(process_name.get(), server_process_name) != 0)
|
238 h.sterling 1.1 {
239 return -1;
240 }
241
242 return 0;
243 }
244
245 //=============================================================================
246 // NAME : get_proc
247 // DESCRIPTION : get_proc() makes a stat() system call on the directory in
248 // /proc with a name that matches the pid of the cimserver.
249 // It returns 0 if it successfully located the process dir
250 // and verified that the process name matches that of the
251 // cimserver. It returns -1 if it fails to open /proc, or
252 // the cimserver process does not exist.
253 //=============================================================================
254 int ServerProcess::get_proc(int pid)
255 {
256 static char path[32];
257 static struct stat stat_buff;
258
259 h.sterling 1.1 sprintf(path, "/proc/%d", pid);
260 if (stat(path, &stat_buff) == -1) // process stopped running
261 {
262 return -1;
263 }
264
265 // get the process name to make sure it is the cimserver process
266 // ATTN: skip verify for Solaris
|
267 jim.wunderlich 1.5 #if !defined(PEGASUS_OS_SOLARIS)
|
268 h.sterling 1.1 if ((verify_process_name(path, getProcessName())) == -1)
269 {
270 return -1;
271 }
272 #endif
273
274 //
275 // Check to see if this command process has the same pid as the cimserver
276 // daemon process pid stored in the cimserver_start.conf file. Since the
277 // command has the same name as the cimserver daemon process, this could
278 // happen after a system reboot. If the pids are the same, cimserver
279 // isn't really running.
280 //
281 Uint32 mypid = System::getPID();
282 if ((mypid == (unsigned)pid) || ((unsigned)parentPid == (unsigned)pid))
283 {
284 return -1;
285 }
286 return 0;
287 }
288 #endif
289 h.sterling 1.1
290 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
291 Boolean isProcRunning(pid_t pid)
292 {
293 W_PSPROC buf;
294 int token = 0;
295 memset(&buf, 0x00, sizeof(buf));
296 buf.ps_conttyptr =(char *) malloc(buf.ps_conttylen =PS_CONTTYBLEN);
297 buf.ps_pathptr =(char *) malloc(buf.ps_pathlen =PS_PATHBLEN);
298 buf.ps_cmdptr =(char *) malloc(buf.ps_cmdlen =PS_CMDBLEN);
299
|
300 marek 1.11.18.2 while((token = w_getpsent(token, &buf, sizeof(buf))) > 0)
301 {
302 if (buf.ps_pid==pid)
303 {
304 // If the process id is associated with the program
305 // "cimserver", then a cimserver is still running.
306 if (strstr(buf.ps_pathptr,"cimserver")!= NULL )
307 {
|
308 h.sterling 1.1 free(buf.ps_conttyptr);
309 free(buf.ps_pathptr);
310 free(buf.ps_cmdptr);
311 return true;
312 }
|
313 marek 1.11.18.2 // pid found was not associated with a cimserver
314 break;
315 }
316 }
|
317 h.sterling 1.1
318 free(buf.ps_conttyptr);
319 free(buf.ps_pathptr);
320 free(buf.ps_cmdptr);
321 return false;
322 }
323 #endif
324
325 #if defined(PEGASUS_OS_AIX)
326
327 /////////////////////////////////////////////////////////////////////////////
328 // NAME : processdata
329 // FUNCTION : it calls subroutine getprocs() to get information
330 // about all processes.
331 /////////////////////////////////////////////////////////////////////////////
332 // ARGUMENTS:
333 // cnt: the number of the processes in the returned table
334 // RETURN VALUES:
335 // when it successfully gets the process table entries,
336 // an array of procsinfo structures filled with process table
337 // entries are returned. Otherewise, a null pointer is
338 h.sterling 1.1 // returned.
339 //
340 /////////////////////////////////////////////////////////////////////////////
341 struct procsinfo *processdata(int *cnt)
342 {
343 struct procsinfo *proctable=NULL, *rtnp=NULL;
344 int count=1048576, rtncnt, repeat=1, nextp=0;
345
346 *cnt=0;
347 while ( repeat && (rtncnt=getprocs(rtnp,PROCSIZE,0,0,&nextp, count))>0)
348 {
349 if (!rtnp)
350 {
351 count=rtncnt;
352 proctable=(struct procsinfo *) malloc((size_t) \
353 PROCSIZE*count);
354 if (!proctable)
355 return NULL;
356 rtnp=proctable;
357 nextp=0;
358 } else
359 h.sterling 1.1 {
360 *cnt+=rtncnt;
361 if (rtncnt>=count)
362 {
363 proctable=(struct procsinfo *) realloc(\
364 (void*)proctable, (size_t)\
365 (PROCSIZE*(*cnt+count)));
366 if (!proctable)
367 return NULL;
368 rtnp=proctable+(*cnt);
369 } else
370 repeat=0;
371 } // end of if(!rtnp)
372 } //end of while
373 return proctable;
374 }
375
376 /////////////////////////////////////////////////////////////////////////////
377 // NAME : aixcimsrvrunning
378 // FUNCTION : it figures out if the cimserver process is running
379 // by checking the process table entries in the array
380 h.sterling 1.1 // returned from processdata(). If the cimserver process is
381 // running and its pid is the same as the pid in the file
382 // getPIDFileName(), it will return 0, otherwise it will
383 // return -1.
384 /////////////////////////////////////////////////////////////////////////////
385 // ARGUMENTS:
386 // pid: the process identifier saved in the file
387 // getPIDFileName()
388 // RETURN VALUES:
389 // 0: successful
390 // -1: errors
391 //
392 /////////////////////////////////////////////////////////////////////////////
393
|
394 h.sterling 1.2 int aixcimsrvrunning(pid_t pid, const char* processName)
|
395 h.sterling 1.1 {
396 int i,count;
397 struct procsinfo *proctable;
398
399 proctable=processdata(&count);
400 if (proctable==NULL)
401 return -1;
402 for (i=0;i<count;i++)
|
403 h.sterling 1.2 if (!strcmp(proctable[i].pi_comm, processName) && \
|
404 h.sterling 1.1 proctable[i].pi_pid==pid)
405 {
406 free(proctable);
407 return 0;
408 }
409
410 free(proctable);
411 return -1;
412 }
413 #endif
414
415 Boolean ServerProcess::isCIMServerRunning(void)
416 {
417 FILE *pid_file;
418 pid_t pid = 0;
419
420 // open the file containing the CIMServer process ID
421 pid_file = fopen(getPIDFileName(), "r");
422 if (!pid_file)
423 {
424 return false;
425 h.sterling 1.1 }
426
427 // get the pid from the file
428 fscanf(pid_file, "%d\n", &pid);
429
430 fclose(pid_file);
431
432 if (pid == 0)
433 {
434 return false;
435 }
436
437 //
438 // check to see if cimserver process is alive
439 //
440 #if defined(PEGASUS_OS_HPUX)
441 struct pst_status pstru;
442
443 int ret_code;
444 ret_code = pstat_getproc(&pstru, sizeof(struct pst_status), (size_t)0, pid);
445
|
446 mateus.baur 1.11.18.1 if (ret_code != -1)
|
447 h.sterling 1.1 {
448 //
|
449 mateus.baur 1.11.18.1 // Gets the command basename disregarding the command parameters
|
450 h.sterling 1.1 //
|
451 mateus.baur 1.11.18.1 char *execName = strchr(pstru.pst_cmd,' ');
452 if (execName)
453 {
454 *execName = '\0';
455 }
456 execName = basename(pstru.pst_cmd);
457
458 if (strcmp(execName, getProcessName()) == 0)
|
459 h.sterling 1.1 {
|
460 mateus.baur 1.11.18.1 //
461 // Check to see if this command process has the same pid as the
462 // cimserver daemon process pid stored in the cimserver_start.conf
463 // file. Since the command has the same name as the cimserver daemon
464 // process, this could happen after a system reboot. If the pids are
465 // the same, cimserver isn't really running.
466 //
467 Uint32 mypid = System::getPID();
468 if ((mypid != pid) && (parentPid != pid))
469 {
470 // cimserver is running
471 return true;
472 }
|
473 h.sterling 1.1 }
474 }
475 #endif
|
476 jim.wunderlich 1.5 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_OS_SOLARIS)
|
477 h.sterling 1.1 if (get_proc(pid) != -1 )
478 {
479 // cimserver is running
480 return true;
481 }
482 #endif
483 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
484 return isProcRunning(pid);
485 #endif
486 #if defined(PEGASUS_OS_AIX)
|
487 h.sterling 1.2 if (aixcimsrvrunning(pid, getProcessName())!=-1)
|
488 h.sterling 1.1 return true;
489 #endif
490 return false;
491 }
492
493 int ServerProcess::cimserver_kill(int id)
494 {
495 FILE *pid_file;
496 pid_t pid = 0;
497
498 // open the file containing the CIMServer process ID
499 pid_file = fopen(getPIDFileName(), "r");
500 if (!pid_file)
501 {
502 return (-1);
503 }
504
505 // get the pid from the file
506 fscanf(pid_file, "%d\n", &pid);
507
508 fclose(pid_file);
509 h.sterling 1.1
510 if (pid == 0)
511 {
512 System::removeFile(getPIDFileName());
513 return (-1);
514 }
515
516 //
517 // kill the process if it is still alive
518 //
519 #if defined(PEGASUS_OS_HPUX)
520 struct pst_status pstru;
521
522 int ret_code;
523 ret_code = pstat_getproc(&pstru, sizeof(struct pst_status), (size_t)0, pid);
524
525 if ( (ret_code != -1 ) && (strcmp(pstru.pst_ucomm, getProcessName())) == 0)
526 {
527 // cimserver is running, kill the process
528 kill(pid, SIGKILL);
529 }
530 h.sterling 1.1 #endif
|
531 jim.wunderlich 1.5 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_OS_SOLARIS)
|
532 h.sterling 1.1 if (get_proc(pid) != -1 )
533 {
534 kill(pid, SIGKILL);
535 }
536 #endif
537 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
538 if (isProcRunning(pid)) {
539 kill(pid, SIGKILL);
540 }
541 #endif
542 #if defined(PEGASUS_OS_AIX)
|
543 h.sterling 1.2 if (!aixcimsrvrunning(pid, getProcessName()))
|
544 h.sterling 1.1 kill(pid,SIGKILL);
545 #endif
546 // remove the file
547 System::removeFile(getPIDFileName());
548
549 return(0);
550 }
551
552 // notify parent process to terminate so user knows that cimserver
553 // is ready to serve CIM requests.
554 void ServerProcess::notify_parent(int id)
555 {
556 pid_t ppid = getppid();
557 if (id)
558 kill(ppid, SIGTERM);
559 else
560 kill(ppid, PEGASUS_SIGUSR1);
561 }
562
563
564 // Platform specific run
|
565 kumpf 1.7 int ServerProcess::platform_run(
566 int argc,
567 char** argv,
568 Boolean shutdownOption,
569 Boolean debugOutputOption)
|
570 h.sterling 1.1 {
|
571 kumpf 1.7 return cimserver_run(argc, argv, shutdownOption, debugOutputOption);
|
572 h.sterling 1.1 }
|