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