1 h.sterling 1.1 //%2005////////////////////////////////////////////////////////////////////////
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 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
13 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
18 //
19 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
20 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
22 h.sterling 1.1 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
29 //
30 // Author: Mike Day (mdday@us.ibm.com)
31 //
32 // Modified By: Jenny Yu, Hewlett-Packard Company (jenny_yu@hp.com)
33 // Yi Zhou, Hewlett-Packard Company (yi_zhou@hp.com)
34 // Marek Szermutzky, IBM (ddt6szer@de.ibm.com)
35 //%/////////////////////////////////////////////////////////////////////////////
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #if defined(PEGASUS_OS_HPUX)
39 #include <sys/pstat.h>
40 #endif
41 #include <fcntl.h>
42 #include <unistd.h>
43 h.sterling 1.1 #include <Pegasus/Common/Signal.h>
44 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
45 #include <sys/ps.h>
46 #endif
47 #define MAX_WAIT_TIME 25
48 #if defined(PEGASUS_OS_AIX)
49 extern "C" {
50 #include <procinfo.h>
51 extern int getprocs(struct procsinfo *, int, struct fdsinfo *, int,pid_t *,int);
52 #define PROCSIZE sizeof(struct procsinfo)
53 }
54 #endif
55
56 PEGASUS_USING_PEGASUS;
57 PEGASUS_USING_STD;
58
59 Boolean handleSigUsr1 = false;
60 Boolean graveError = false;
61
62 pid_t server_pid;
|
63 h.sterling 1.3 Uint32 parentPid = 0;
|
64 h.sterling 1.1
65 void sigUsr1Handler(int s_n, PEGASUS_SIGINFO_T * s_info, void * sig)
66 {
67 handleSigUsr1 = true;
68 }
69
70 void sigTermHandler(int s_n, PEGASUS_SIGINFO_T * s_info, void * sig)
71 {
72 graveError= handleSigUsr1=true;
73 }
74
75
76 //constructor
77 ServerProcess::ServerProcess() {}
78
79 //destructor
80 ServerProcess::~ServerProcess() {}
81
82 // no-ops
83 void ServerProcess::cimserver_set_process(void* p) {}
84 void ServerProcess::cimserver_exitRC(int rc) {}
85 h.sterling 1.1 int ServerProcess::cimserver_initialize(void) { return 1; }
86 int ServerProcess::cimserver_wait(void) { return 1; }
87 String ServerProcess::getHome(void) { return String::EMPTY; }
88
89 // daemon_init , RW Stevens, "Advance UNIX Programming"
90
91 int ServerProcess::cimserver_fork(void)
92 {
93 getSigHandle()->registerHandler(PEGASUS_SIGUSR1, sigUsr1Handler);
94 getSigHandle()->activate(PEGASUS_SIGUSR1);
95 getSigHandle()->registerHandler(SIGTERM, sigTermHandler);
96 getSigHandle()->activate(SIGTERM);
97
98 pid_t pid;
99 if( (pid = fork() ) < 0)
100 {
101 getSigHandle()->deactivate(PEGASUS_SIGUSR1);
102 getSigHandle()->deactivate(SIGTERM);
103 return(-1);
104 }
105 else if (pid != 0)
106 h.sterling 1.1 {
107 //
108 // parent wait for child
109 // if there is a problem with signal, parent process terminates
110 // when waitTime expires
111 //
112 Uint32 waitTime = MAX_WAIT_TIME;
113
114 while(!handleSigUsr1 && waitTime > 0)
115 {
116 sleep(1);
117 waitTime--;
118 }
119 exit(graveError);
120 }
121
122 setsid();
123 umask(0);
124
125 // get the pid of the cimserver process
126 server_pid = getpid();
127 h.sterling 1.1 return(0);
128 }
129
130 long ServerProcess::get_server_pid()
131 {
132 return server_pid;
133 }
134
|
135 h.sterling 1.3 void ServerProcess::set_parent_pid(int pid)
136 {
137 parentPid = pid;
138 }
139
140
|
141 h.sterling 1.1 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC)
142
143 //===========================================================================
144 // NAME : verify_process_name
145 // DESCRIPTION : Opens the 'stat' file in the /proc/<pid> directory to
146 // verify that the process name is that of the cimserver.
147 //===========================================================================
148 int verify_process_name(char *directory, const char* server_process_name)
149 {
150 static char filename[80];
151 static char buffer[512];
152 int fd, bytesRead;
153
154 // generate the name of the stat file in the process's /proc directory,
155 // and open it
156 sprintf(filename, "%s/%s", directory, "stat");
157 if ( (fd = open(filename, O_RDONLY, 0)) == -1 )
158 {
159 return -1;
160 }
161
162 h.sterling 1.1 // read the contents
163 if ( (bytesRead = read( fd, buffer, (sizeof buffer) - 1 )) <= 0 )
164 {
165 close(fd);
166 return -1;
167 }
168
169 // null terminate the file contents
170 buffer[bytesRead] = 0;
171
172 close(fd);
173
174 // the process name is the second element of the file contents and
175 // is surrounded by parentheses.
176 //
177 // find the positions of the parentheses in the file contents
178 char * open_paren;
179 char * close_paren;
180
181 open_paren = strchr (buffer, '(');
182 close_paren = strchr (buffer, ')');
183 h.sterling 1.1 if (open_paren == NULL || close_paren == NULL || close_paren < open_paren)
184 {
185 return -1;
186 }
187
188 // allocate memory for the result
189 char * process_name;
190 process_name = (char*) malloc(close_paren - open_paren - 1);
191
192 // copy the process name into the result
193 strncpy (process_name, open_paren + 1, close_paren - open_paren -1);
194
195 // strncpy doesn't NULL-terminate the result, so do it here
196 process_name[close_paren - open_paren -1] = '\0';
197
198 if (strcmp(process_name, server_process_name) != 0)
199 {
200 return -1;
201 }
202
203 return 0;
204 h.sterling 1.1 }
205
206 //=============================================================================
207 // NAME : get_proc
208 // DESCRIPTION : get_proc() makes a stat() system call on the directory in
209 // /proc with a name that matches the pid of the cimserver.
210 // It returns 0 if it successfully located the process dir
211 // and verified that the process name matches that of the
212 // cimserver. It returns -1 if it fails to open /proc, or
213 // the cimserver process does not exist.
214 //=============================================================================
215 int ServerProcess::get_proc(int pid)
216 {
217 static char path[32];
218 static struct stat stat_buff;
219
220 sprintf(path, "/proc/%d", pid);
221 if (stat(path, &stat_buff) == -1) // process stopped running
222 {
223 return -1;
224 }
225 h.sterling 1.1
226 // get the process name to make sure it is the cimserver process
227 // ATTN: skip verify for Solaris
228 #if !defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC)
229 if ((verify_process_name(path, getProcessName())) == -1)
230 {
231 return -1;
232 }
233 #endif
234
235 //
236 // Check to see if this command process has the same pid as the cimserver
237 // daemon process pid stored in the cimserver_start.conf file. Since the
238 // command has the same name as the cimserver daemon process, this could
239 // happen after a system reboot. If the pids are the same, cimserver
240 // isn't really running.
241 //
242 Uint32 mypid = System::getPID();
243 if ((mypid == (unsigned)pid) || ((unsigned)parentPid == (unsigned)pid))
244 {
245 return -1;
246 h.sterling 1.1 }
247 return 0;
248 }
249 #endif
250
251 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
252 Boolean isProcRunning(pid_t pid)
253 {
254 W_PSPROC buf;
255 int token = 0;
256 memset(&buf, 0x00, sizeof(buf));
257 buf.ps_conttyptr =(char *) malloc(buf.ps_conttylen =PS_CONTTYBLEN);
258 buf.ps_pathptr =(char *) malloc(buf.ps_pathlen =PS_PATHBLEN);
259 buf.ps_cmdptr =(char *) malloc(buf.ps_cmdlen =PS_CMDBLEN);
260
261 token = w_getpsent(token, &buf, sizeof(buf));
262 do {
263 token = w_getpsent(token, &buf, sizeof(buf));
264 if (buf.ps_pid==pid) {
265 free(buf.ps_conttyptr);
266 free(buf.ps_pathptr);
267 h.sterling 1.1 free(buf.ps_cmdptr);
268 return true;
269 }
270 } while(token>0);
271
272 free(buf.ps_conttyptr);
273 free(buf.ps_pathptr);
274 free(buf.ps_cmdptr);
275 return false;
276 }
277 #endif
278
279 #if defined(PEGASUS_OS_AIX)
280
281 /////////////////////////////////////////////////////////////////////////////
282 // NAME : processdata
283 // FUNCTION : it calls subroutine getprocs() to get information
284 // about all processes.
285 /////////////////////////////////////////////////////////////////////////////
286 // ARGUMENTS:
287 // cnt: the number of the processes in the returned table
288 h.sterling 1.1 // RETURN VALUES:
289 // when it successfully gets the process table entries,
290 // an array of procsinfo structures filled with process table
291 // entries are returned. Otherewise, a null pointer is
292 // returned.
293 //
294 /////////////////////////////////////////////////////////////////////////////
295 struct procsinfo *processdata(int *cnt)
296 {
297 struct procsinfo *proctable=NULL, *rtnp=NULL;
298 int count=1048576, rtncnt, repeat=1, nextp=0;
299
300 *cnt=0;
301 while ( repeat && (rtncnt=getprocs(rtnp,PROCSIZE,0,0,&nextp, count))>0)
302 {
303 if (!rtnp)
304 {
305 count=rtncnt;
306 proctable=(struct procsinfo *) malloc((size_t) \
307 PROCSIZE*count);
308 if (!proctable)
309 h.sterling 1.1 return NULL;
310 rtnp=proctable;
311 nextp=0;
312 } else
313 {
314 *cnt+=rtncnt;
315 if (rtncnt>=count)
316 {
317 proctable=(struct procsinfo *) realloc(\
318 (void*)proctable, (size_t)\
319 (PROCSIZE*(*cnt+count)));
320 if (!proctable)
321 return NULL;
322 rtnp=proctable+(*cnt);
323 } else
324 repeat=0;
325 } // end of if(!rtnp)
326 } //end of while
327 return proctable;
328 }
329
330 h.sterling 1.1 /////////////////////////////////////////////////////////////////////////////
331 // NAME : aixcimsrvrunning
332 // FUNCTION : it figures out if the cimserver process is running
333 // by checking the process table entries in the array
334 // returned from processdata(). If the cimserver process is
335 // running and its pid is the same as the pid in the file
336 // getPIDFileName(), it will return 0, otherwise it will
337 // return -1.
338 /////////////////////////////////////////////////////////////////////////////
339 // ARGUMENTS:
340 // pid: the process identifier saved in the file
341 // getPIDFileName()
342 // RETURN VALUES:
343 // 0: successful
344 // -1: errors
345 //
346 /////////////////////////////////////////////////////////////////////////////
347
|
348 h.sterling 1.2 int aixcimsrvrunning(pid_t pid, const char* processName)
|
349 h.sterling 1.1 {
350 int i,count;
351 struct procsinfo *proctable;
352
353 proctable=processdata(&count);
354 if (proctable==NULL)
355 return -1;
356 for (i=0;i<count;i++)
|
357 h.sterling 1.2 if (!strcmp(proctable[i].pi_comm, processName) && \
|
358 h.sterling 1.1 proctable[i].pi_pid==pid)
359 {
360 free(proctable);
361 return 0;
362 }
363
364 free(proctable);
365 return -1;
366 }
367 #endif
368
369 Boolean ServerProcess::isCIMServerRunning(void)
370 {
371 FILE *pid_file;
372 pid_t pid = 0;
373
374 // open the file containing the CIMServer process ID
375 pid_file = fopen(getPIDFileName(), "r");
376 if (!pid_file)
377 {
378 return false;
379 h.sterling 1.1 }
380
381 // get the pid from the file
382 fscanf(pid_file, "%d\n", &pid);
383
384 fclose(pid_file);
385
386 if (pid == 0)
387 {
388 return false;
389 }
390
391 //
392 // check to see if cimserver process is alive
393 //
394 #if defined(PEGASUS_OS_HPUX)
395 struct pst_status pstru;
396
397 int ret_code;
398 ret_code = pstat_getproc(&pstru, sizeof(struct pst_status), (size_t)0, pid);
399
400 h.sterling 1.1 if ( (ret_code != -1 ) && (strcmp(pstru.pst_ucomm, getProcessName())) == 0)
401 {
402 //
403 // Check to see if this command process has the same pid as the
404 // cimserver daemon process pid stored in the cimserver_start.conf
405 // file. Since the command has the same name as the cimserver daemon
406 // process, this could happen after a system reboot. If the pids are
407 // the same, cimserver isn't really running.
408 //
409 Uint32 mypid = System::getPID();
410 if ((mypid != pid) && (parentPid != pid))
411 {
412 // cimserver is running
413 return true;
414 }
415 }
416 #endif
417 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC)
418 if (get_proc(pid) != -1 )
419 {
420 // cimserver is running
421 h.sterling 1.1 return true;
422 }
423 #endif
424 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
425 return isProcRunning(pid);
426 #endif
427 #if defined(PEGASUS_OS_AIX)
|
428 h.sterling 1.2 if (aixcimsrvrunning(pid, getProcessName())!=-1)
|
429 h.sterling 1.1 return true;
430 #endif
431 return false;
432 }
433
434 int ServerProcess::cimserver_kill(int id)
435 {
436 FILE *pid_file;
437 pid_t pid = 0;
438
439 // open the file containing the CIMServer process ID
440 pid_file = fopen(getPIDFileName(), "r");
441 if (!pid_file)
442 {
443 return (-1);
444 }
445
446 // get the pid from the file
447 fscanf(pid_file, "%d\n", &pid);
448
449 fclose(pid_file);
450 h.sterling 1.1
451 if (pid == 0)
452 {
453 System::removeFile(getPIDFileName());
454 return (-1);
455 }
456
457 //
458 // kill the process if it is still alive
459 //
460 #if defined(PEGASUS_OS_HPUX)
461 struct pst_status pstru;
462
463 int ret_code;
464 ret_code = pstat_getproc(&pstru, sizeof(struct pst_status), (size_t)0, pid);
465
466 if ( (ret_code != -1 ) && (strcmp(pstru.pst_ucomm, getProcessName())) == 0)
467 {
468 // cimserver is running, kill the process
469 kill(pid, SIGKILL);
470 }
471 h.sterling 1.1 #endif
472 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) || defined(PEGASUS_PLATFORM_SOLARIS_SPARC_CC)
473 if (get_proc(pid) != -1 )
474 {
475 kill(pid, SIGKILL);
476 }
477 #endif
478 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
479 if (isProcRunning(pid)) {
480 kill(pid, SIGKILL);
481 }
482 #endif
483 #if defined(PEGASUS_OS_AIX)
|
484 h.sterling 1.2 if (!aixcimsrvrunning(pid, getProcessName()))
|
485 h.sterling 1.1 kill(pid,SIGKILL);
486 #endif
487 // remove the file
488 System::removeFile(getPIDFileName());
489
490 return(0);
491 }
492
493 // notify parent process to terminate so user knows that cimserver
494 // is ready to serve CIM requests.
495 void ServerProcess::notify_parent(int id)
496 {
497 pid_t ppid = getppid();
498 if (id)
499 kill(ppid, SIGTERM);
500 else
501 kill(ppid, PEGASUS_SIGUSR1);
502 }
503
504
505 // Platform specific run
506 h.sterling 1.1 int ServerProcess::platform_run( int argc, char** argv, Boolean shutdownOption )
507 {
508 return cimserver_run( argc, argv, shutdownOption );
509 }
510
511
512
513
514
515
|