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