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