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