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