(file) Return to ServerProcessUnix.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Service

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2