(file) Return to main.c CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Executor

  1 kumpf 1.2 /*
  2           //%2006////////////////////////////////////////////////////////////////////////
  3           //
  4           // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  5           // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  6           // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  7           // IBM Corp.; EMC Corporation, The Open Group.
  8           // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  9           // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
 10           // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 11           // EMC Corporation; VERITAS Software Corporation; The Open Group.
 12           // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 13           // EMC Corporation; Symantec Corporation; The Open Group.
 14           //
 15           // Permission is hereby granted, free of charge, to any person obtaining a copy
 16           // of this software and associated documentation files (the "Software"), to
 17           // deal in the Software without restriction, including without limitation the
 18           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 19           // sell copies of the Software, and to permit persons to whom the Software is
 20           // furnished to do so, subject to the following conditions:
 21           // 
 22 kumpf 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 23           // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 24           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 25           // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 26           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 27           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 28           // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 29           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 30           //
 31           //%/////////////////////////////////////////////////////////////////////////////
 32           */
 33           #include <stdio.h>
 34           #include <sys/types.h>
 35           #include <sys/stat.h>
 36           #include <unistd.h>
 37           #include <string.h>
 38 kumpf 1.10 #include <signal.h>
 39            #include <time.h>
 40 kumpf 1.2  #include "Config.h"
 41            #include "Child.h"
 42            #include "Parent.h"
 43            #include "User.h"
 44            #include "Fatal.h"
 45            #include "Process.h"
 46            #include "Path.h"
 47            #include "Globals.h"
 48            #include "Socket.h"
 49            #include "Strlcpy.h"
 50            #include "Strlcat.h"
 51            #include "Log.h"
 52            #include "Policy.h"
 53            #include "Macro.h"
 54            #include "Assert.h"
 55            #include "Options.h"
 56 kumpf 1.8  #include <Pegasus/Common/PegasusVersion.h>
 57 kumpf 1.2  
 58 kumpf 1.10 #define CIMSERVER_COMMAND_TIMEOUT_SECONDS 240
 59            
 60 kumpf 1.2  /*
 61            **==============================================================================
 62            **
 63            ** GetServerUser
 64            **
 65            **     Determine which user to run CIMSERVERMAIN as.
 66            **
 67            **==============================================================================
 68            */
 69            
 70 kumpf 1.3  int GetServerUser(const char** userName, int* uid, int* gid)
 71 kumpf 1.2  {
 72 kumpf 1.3      *userName = PEGASUS_CIMSERVERMAIN_USER;
 73 kumpf 1.2  
 74 kumpf 1.3      if (GetUserInfo(*userName, uid, gid) != 0)
 75 kumpf 1.2      {
 76                    Fatal(FL,
 77                        "The %s user \"%s\" does not exist.",
 78 kumpf 1.3              CIMSERVERMAIN, *userName);
 79 kumpf 1.2      }
 80            
 81                return 0;
 82            }
 83            
 84            /*
 85            **==============================================================================
 86            **
 87            ** ExecShutdown()
 88            **
 89            **==============================================================================
 90            */
 91            
 92 kumpf 1.5  void ExecShutdown(void)
 93 kumpf 1.2  {
 94                char* tmpArgv[3];
 95                const char* cimshutdownPath;
 96                const char* shutdownTimeout;
 97            
 98                /* Get shutdownTimeout configuration parameter. */
 99            
100                if ((shutdownTimeout = FindMacro("shutdownTimeout")) == NULL)
101                    Fatal(FL, "failed to resolve shutdownTimeout");
102            
103                /* Get absolute CIMSHUTDOWN program name. */
104            
105                if ((cimshutdownPath = FindMacro("cimshutdownPath")) == NULL)
106                    Fatal(FL, "failed to resolve cimshutdownPath");
107            
108                /* Create argument list. */
109            
110                tmpArgv[0] = CIMSHUTDOWN;
111                tmpArgv[1] = (char*)shutdownTimeout;
112                tmpArgv[2] = 0;
113            
114 kumpf 1.2      /* Exec CIMSHUTDOWN program. */
115            
116                /* Flawfinder: ignore */
117                execv(cimshutdownPath, tmpArgv);
118                Fatal(FL, "failed to exec %s", cimshutdownPath);
119            }
120            
121            /*
122            **==============================================================================
123            **
124            ** DefineExecutorMacros()
125            **
126            **     Define macros used by the executor.
127            **
128            **==============================================================================
129            */
130            
131 kumpf 1.5  void DefineExecutorMacros(void)
132 kumpf 1.2  {
133                /* Define ${internalBinDir} */
134                {
135                    char path[EXECUTOR_BUFFER_SIZE];
136            
137                    if (GetPegasusInternalBinDir(path) != 0)
138                        Fatal(FL, "failed to resolve internal pegasus bin directory");
139            
140                    DefineMacro("internalBinDir", path);
141                }
142            
143                /* Define ${cimservermain} */
144            
145                DefineMacro("cimservermain", CIMSERVERMAIN);
146            
147                /* Define ${cimprovagt} */
148            
149                DefineMacro("cimprovagt", CIMPROVAGT);
150            
151                /* Define ${cimshutdown} */
152            
153 kumpf 1.2      DefineMacro("cimshutdown", CIMSHUTDOWN);
154            
155                /* Define ${cimservera} */
156            
157                DefineMacro("cimservera", CIMSERVERA);
158            
159                /* Define ${cimservermainPath} */
160                {
161                    char path[EXECUTOR_BUFFER_SIZE];
162            
163                    if (ExpandMacros("${internalBinDir}/${cimservermain}", path) != 0)
164                        Fatal(FL, "failed to resolve cimservermainPath");
165            
166                    DefineMacro("cimservermainPath", path);
167                }
168            
169                /* Define ${cimprovagtPath} */
170                {
171                    char path[EXECUTOR_BUFFER_SIZE];
172            
173                    if (ExpandMacros("${internalBinDir}/${cimprovagt}", path) != 0)
174 kumpf 1.2              Fatal(FL, "failed to resolve cimprovagtPath");
175            
176                    DefineMacro("cimprovagtPath", path);
177                }
178            
179                /* Define ${cimshutdownPath} */
180                {
181                    char path[EXECUTOR_BUFFER_SIZE];
182            
183                    if (ExpandMacros("${internalBinDir}/${cimshutdown}", path) != 0)
184                        Fatal(FL, "failed to resolve cimshutdownPath");
185            
186                    DefineMacro("cimshutdownPath", path);
187                }
188            
189                /* Define ${cimserveraPath} */
190                {
191                    char path[EXECUTOR_BUFFER_SIZE];
192            
193                    if (ExpandMacros("${internalBinDir}/${cimservera}", path) != 0)
194                        Fatal(FL, "failed to resolve cimserveraPath");
195 kumpf 1.2  
196                    DefineMacro("cimserveraPath", path);
197                }
198            
199                /* Define ${shutdownTimeout} */
200            
201                {
202                    char buffer[EXECUTOR_BUFFER_SIZE];
203            
204                    if (GetConfigParam("shutdownTimeout", buffer) != 0)
205 kumpf 1.7          {
206                        Strlcpy(
207                            buffer,
208                            PEGASUS_DEFAULT_SHUTDOWN_TIMEOUT_SECONDS_STRING,
209                            sizeof(buffer));
210                    }
211 kumpf 1.2  
212                    DefineMacro("shutdownTimeout", buffer);
213                }
214            
215                /* Define ${currentConfigFilePath} */
216                {
217                    char path[EXECUTOR_BUFFER_SIZE];
218            
219                    if (GetHomedPath(PEGASUS_CURRENT_CONFIG_FILE_PATH, path) != 0)
220                    {
221                        Fatal(FL, "GetHomedPath() failed on \"%s\"",
222                            PEGASUS_CURRENT_CONFIG_FILE_PATH);
223                    }
224            
225                    DefineMacro("currentConfigFilePath", path);
226                }
227            
228                /* Define ${plannedConfigFilePath} */
229                {
230                    char path[EXECUTOR_BUFFER_SIZE];
231            
232 kumpf 1.2          if (GetHomedPath(PEGASUS_PLANNED_CONFIG_FILE_PATH, path) != 0)
233                    {
234                        Fatal(FL, "GetHomedPath() failed on \"%s\"",
235                            PEGASUS_PLANNED_CONFIG_FILE_PATH);
236                    }
237            
238                    DefineMacro("plannedConfigFilePath", path);
239                }
240            
241                /* Define ${passwordFilePath} */
242            
243                if (DefineConfigPathMacro("passwordFilePath", "cimserver.passwd") != 0)
244                    Fatal(FL, "missing \"passwordFilePath\" configuration parameter.");
245            
246                /* Define ${sslKeyFilePath} */
247            
248                if (DefineConfigPathMacro("sslKeyFilePath", "file.pem") != 0)
249                    Fatal(FL, "missing \"sslKeyFilePath\" configuration parameter.");
250            
251                /* Define ${sslTrustStore} */
252            
253 kumpf 1.2      if (DefineConfigPathMacro("sslTrustStore", "cimserver_trust") != 0)
254                    Fatal(FL, "missing \"sslTrustStore\" configuration parameter.");
255            
256                /* Define ${crlStore} */
257            
258                if (DefineConfigPathMacro("crlStore", "crl") != 0)
259                    Fatal(FL, "missing \"crlStore\" configuration parameter.");
260            }
261            
262            /*
263            **==============================================================================
264            **
265            ** main()
266            **
267            **==============================================================================
268            */
269            
270            int main(int argc, char** argv)
271            {
272                const char* cimservermainPath;
273 kumpf 1.11     const char* workingDirectory;
274 kumpf 1.2      int pair[2];
275 kumpf 1.10     int initCompletePipe[2];
276                int pid;
277 kumpf 1.2      char username[EXECUTOR_BUFFER_SIZE];
278 kumpf 1.6      const char* childUserName;
279                int childUid;
280                int childGid;
281 kumpf 1.2      int childPid;
282                struct Options options;
283            
284                /* Get options. */
285            
286                GetOptions(&argc, &argv, &options);
287            
288                /* Save argc-argv as globals. */
289            
290                globals.argc = argc;
291                globals.argv = argv;
292            
293 kumpf 1.6      /* Open the log. */
294            
295                OpenLog("cimserver");
296            
297 kumpf 1.2      /* Define macros needed by the executor. */
298            
299                DefineExecutorMacros();
300            
301 kumpf 1.6      /* If shutting down, then run CIMSHUTDOWN client. */
302 kumpf 1.2  
303                if (options.shutdown)
304                    ExecShutdown();
305            
306                /* Process --policy and --macros options. */
307            
308                if (options.dump)
309                {
310 kumpf 1.4          DumpPolicy(stdout, 1);
311                    DumpMacros(stdout);
312 kumpf 1.2          exit(0);
313                }
314            
315                /* Get absolute CIMSERVERMAIN program name. */
316            
317                if ((cimservermainPath = FindMacro("cimservermainPath")) == NULL)
318                    Fatal(FL, "Failed to locate %s program", CIMSERVERMAIN);
319            
320                /* If CIMSERVERMAIN is already running, warn and exit now, unless one of
321                 * the following options are given: -v, --version, -h, --help (these are
322                 * passed through to CIMSERVERMAIN).
323                 */
324            
325 kumpf 1.4      if (!options.version &&
326                    !options.help &&
327                    TestProcessRunning(PEGASUS_CIMSERVER_START_FILE, CIMSERVERMAIN) == 0)
328 kumpf 1.2      {
329                    fprintf(stderr,
330                        "%s: cimserver is already running (the PID found in the file "
331                        "\"%s\" corresponds to an existing process named \"%s\").\n\n",
332                        globals.argv[0], PEGASUS_CIMSERVER_START_FILE, CIMSERVERMAIN);
333            
334                    exit(1);
335                }
336            
337                /* Get enableAuthentication configuration option. */
338            
339                {
340                    char buffer[EXECUTOR_BUFFER_SIZE];
341            
342                    if (GetConfigParam("enableAuthentication", buffer) == 0 &&
343                        strcasecmp(buffer, "true") == 0)
344                    {
345                        globals.enableAuthentication = 1;
346                    }
347                }
348            
349 kumpf 1.4      /* Initialize the log-level from the configuration parameter. */
350 kumpf 1.2  
351 kumpf 1.4      InitLogLevel();
352 kumpf 1.2  
353 denise.eckstein 1.13     Log(LL_TRACE, "starting");
354 kumpf           1.2  
355                          /* Be sure this process is running as root (otherwise fail). */
356                      
357                          if (setuid(0) != 0 || setgid(0) != 0)
358                              Fatal(FL, "attempted to run program as non-root user");
359                      
360                          /* Warn if authentication not enabled (suspicious use of executor). */
361                      
362                          if (!globals.enableAuthentication)
363                              Log(LL_WARNING, "authentication is NOT enabled");
364                          else
365                              Log(LL_TRACE, "authentication is enabled");
366                      
367                          /* Print user info. */
368                      
369                          if (GetUserName(getuid(), username) != 0)
370                              Fatal(FL, "cannot resolve user from uid=%d", getuid());
371                      
372                          Log(LL_TRACE, "running as %s (uid=%d, gid=%d)",
373                              username, (int)getuid(), (int)getgid());
374                      
375 mateus.baur     1.9      /* Change the current directory */
376                      
377 kumpf           1.11 #if defined(PEGASUS_USE_RELEASE_DIRS) && defined(PEGASUS_CORE_DIR)
378                          workingDirectory = PEGASUS_CORE_DIR;
379 denise.eckstein 1.12 #elif defined(PEGASUS_DEBUG)
380                          workingDirectory = getenv("PEGASUS_TMP");
381 mateus.baur     1.9  #endif
382 denise.eckstein 1.12     if (workingDirectory == NULL)
383                          {
384                              workingDirectory = "/";
385                          }
386 kumpf           1.11     if (chdir(workingDirectory) != 0)
387                          {
388                              Log(LL_WARNING, "Failed to change working directory to %s",
389                                  workingDirectory);
390                          }
391                      
392 kumpf           1.10     /* Create a pipe for communicating with cimserver daemon process. */
393                      
394                          if (pipe(initCompletePipe) != 0)
395                              Fatal(FL, "Failed to create pipe");
396                      
397                          CloseOnExec(initCompletePipe[0]);
398                          CloseOnExec(initCompletePipe[1]);
399                      
400                          /* Fork to ensure we are not a session leader so setsid() will succeed. */
401                      
402                          pid = fork();
403                      
404                          if (pid < 0)
405                          {
406                              Fatal(FL, "fork() failed");
407                          }
408                      
409                          if (pid > 0)
410                          {
411                              /* Wait until daemon writes an exit code or closes the pipe. */
412                      
413 kumpf           1.10         char exitRC;
414                              ssize_t result;
415                              time_t startTime;
416                              time_t now;
417                      
418                              close(initCompletePipe[1]);
419                              SetNonBlocking(initCompletePipe[0]);
420                              time(&startTime);
421                      
422                              do
423                              {
424                                  time(&now);
425                                  result = WaitForReadEnable(
426                                      initCompletePipe[0],
427                                      (CIMSERVER_COMMAND_TIMEOUT_SECONDS - (now - startTime)) * 1000);
428                              } while (result == -1 && errno == EINTR);
429                      
430                              if (result == 0)
431                              {
432                                  fprintf(stderr,
433                                      "The cimserver command timed out waiting for the CIM server "
434 kumpf           1.10                     "to start.");
435                                  _exit(0);
436                              }
437                      
438                              EXECUTOR_RESTART(read(initCompletePipe[0], &exitRC, 1), result);
439                              if (result <= 0)
440                              {
441                                  exitRC = 1;
442                              }
443                              _exit(exitRC);
444                          }
445                      
446                          close(initCompletePipe[0]);
447                      
448                          /* Become session leader (so that our child process will not be one) */
449                      
450                          if (setsid() < 0)
451                          {
452                              Fatal(FL, "setsid() failed");
453                          }
454                      
455 kumpf           1.10     /* Ignore SIGHUP: */
456                      
457                          signal(SIGHUP, SIG_IGN);
458                      
459                          /* Ignore SIGCHLD: */
460                      
461                          signal(SIGCHLD, SIG_IGN);
462                      
463                          /* Ignore SIGPIPE: */
464                      
465                          signal(SIGPIPE, SIG_IGN);
466                      
467                          /* Fork cimserver daemon process (not a session leader since parent is). */
468                      
469                          pid = fork();
470                      
471                          if (pid < 0)
472                          {
473                              Fatal(FL, "fork() failed");
474                          }
475                      
476 kumpf           1.10     if (pid > 0)
477                          {
478                              _exit(0);
479                          }
480                      
481 kumpf           1.2      /* Determine user for running CIMSERVERMAIN. */
482                      
483 kumpf           1.6      GetServerUser(&childUserName, &childUid, &childGid);
484 kumpf           1.2  
485 kumpf           1.10     /* Create a socket pair for communicating with the child process. */
486                      
487                          if (CreateSocketPair(pair) != 0)
488                              Fatal(FL, "Failed to create socket pair");
489                      
490                          CloseOnExec(pair[1]);
491                      
492 kumpf           1.2      /* Fork child process. */
493                      
494                          childPid = fork();
495                      
496                          if (childPid == 0)
497                          {
498                              /* Child. */
499                              close(pair[1]);
500 kumpf           1.3          Child(
501                                  argc,
502                                  argv,
503                                  cimservermainPath,
504 kumpf           1.6              childUserName,
505                                  childUid,
506                                  childGid,
507 kumpf           1.3              pair[0]);
508 kumpf           1.2      }
509                          else if (childPid > 0)
510                          {
511                              /* Parent. */
512                              close(pair[0]);
513 kumpf           1.10         Parent(pair[1], initCompletePipe[1], childPid, options.bindVerbose);
514 kumpf           1.2      }
515                          else
516                          {
517                              Fatal(FL, "fork() failed");
518                          }
519                      
520                          return 0;
521                      }

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2