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