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

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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2