(file) Return to cimserver.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / WMIMapper / WMIServer

Diff for /pegasus/src/WMIMapper/WMIServer/cimserver.cpp between version 1.1 and 1.41

version 1.1, 2002/11/19 21:32:49 version 1.41, 2008/12/01 17:52:04
Line 1 
Line 1 
 //%/////////////////////////////////////////////////////////////////////////////  //%LICENSE////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,  // Licensed to The Open Group (TOG) under one or more contributor license
 // The Open Group, Tivoli Systems  // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
   // this work for additional information regarding copyright ownership.
   // Each contributor licenses this file to you under the OpenPegasus Open
   // Source License; you may not use this file except in compliance with the
   // License.
   //
   // Permission is hereby granted, free of charge, to any person obtaining a
   // copy of this software and associated documentation files (the "Software"),
   // to deal in the Software without restriction, including without limitation
   // the rights to use, copy, modify, merge, publish, distribute, sublicense,
   // and/or sell copies of the Software, and to permit persons to whom the
   // Software is furnished to do so, subject to the following conditions:
   //
   // The above copyright notice and this permission notice shall be included
   // in all copies or substantial portions of the Software.
   //
   // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
   // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
   // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
   // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
   // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 // //
 // Permission is hereby granted, free of charge, to any person obtaining a copy  //////////////////////////////////////////////////////////////////////////
 // of this software and associated documentation files (the "Software"), to  
 // deal in the Software without restriction, including without limitation the  
 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or  
 // sell copies of the Software, and to permit persons to whom the Software is  
 // furnished to do so, subject to the following conditions:  
 //  
 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN  
 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED  
 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT  
 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR  
 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT  
 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN  
 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION  
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  
 //  
 //==============================================================================  
 //  
 // Author: Mike Brasher (mbrasher@bmc.com)  
 //  
 // Modified By: Mike Day (mdday@us.ibm.com)  
 //  
 // Modified By: Karl Schopmeyer (k.schopmeyer@opengroup.org)  
 //  
 // Modified By: Nag Boranna (nagaraja_boranna@hp.com)  
 //  
 // Modified By: Jenny Yu (jenny_yu@hp.com)  
 //  
 // Modified By: Sushma Fernandes (sushma_fernandes@hp.com)  
 //  
 // Modified By: Barbara Packard (barbara_packard@hp.com)  
 // //
 //%/////////////////////////////////////////////////////////////////////////////  //%////////////////////////////////////////////////////////////////////////////
  
  
 ////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
Line 70 
Line 62 
 // To START the Pegasus service, // To START the Pegasus service,
 // //
 // net start cimserver // net start cimserver
   // or
   // cimserver -start
 // //
 // To STOP the Pegasus service, // To STOP the Pegasus service,
 // //
 // net stop cimserver // net stop cimserver
   // or
   // cimserver -stop
 // //
 // Alternatively, you can use the windows service manager. Pegasus shows up // Alternatively, you can use the windows service manager. Pegasus shows up
 // in the service database as "Pegasus CIM Object Manager" // in the service database as "Pegasus CIM Object Manager"
 // //
 // Mike Day, mdday@us.ibm.com  
 //  
 ////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
  
  
 #include <Pegasus/Common/Config.h> #include <Pegasus/Common/Config.h>
 #include <Pegasus/Common/Constants.h> #include <Pegasus/Common/Constants.h>
 #include <iostream> #include <iostream>
 #include <cassert>  #include <Pegasus/Common/PegasusAssert.h>
 #include <cstdlib>  
 #include <fstream> #include <fstream>
 #include <Pegasus/Common/FileSystem.h> #include <Pegasus/Common/FileSystem.h>
 #include <Pegasus/Common/Monitor.h>  
 #include <WMIMapper/PegServer/CIMServer.h>  
 #include <Pegasus/Common/PegasusVersion.h> #include <Pegasus/Common/PegasusVersion.h>
 #include <Pegasus/Common/Logger.h> #include <Pegasus/Common/Logger.h>
 #include <Pegasus/Common/System.h> #include <Pegasus/Common/System.h>
 #include <Pegasus/Common/Tracer.h> #include <Pegasus/Common/Tracer.h>
   #include <Pegasus/Common/LanguageParser.h>
 #include <Pegasus/Config/ConfigManager.h> #include <Pegasus/Config/ConfigManager.h>
 #include <Pegasus/Client/CIMClient.h> #include <Pegasus/Client/CIMClient.h>
 #include <Pegasus/Server/ShutdownService.h>  #include <Pegasus/Server/CIMServer.h>
 #include <Pegasus/Common/Destroyer.h>  #include <Service/ServerProcess.h>
 #if !defined(PEGASUS_OS_ZOS) && ! defined(PEGASUS_OS_HPUX)  #include <Service/ServerShutdownClient.h>
 #include <slp/slp.h>  #include <Service/ServerRunStatus.h>
 #endif  
  
   PEGASUS_USING_PEGASUS;
   PEGASUS_USING_STD;
  
 #if defined(PEGASUS_OS_TYPE_WINDOWS)  #define PEGASUS_PROCESS_NAME "WMI Mapper"
 # include "cimserver_windows.cpp"  
 #elif defined(PEGASUS_OS_TYPE_UNIX)  //Windows service variables are not defined elsewhere in the product
 # if defined(PEGASUS_OS_OS400)  //enable ability to override these
 #  include "cimserver_os400.cpp"  #ifndef PEGASUS_SERVICE_NAME
 # else  #define PEGASUS_SERVICE_NAME "Pegasus WMI Mapper";
 #  include "cimserver_unix.cpp"  
 #endif #endif
 #else  #ifndef PEGASUS_SERVICE_DESCRIPTION
 # error "Unsupported platform"  #define PEGASUS_SERVICE_DESCRIPTION "Pegasus WMI Mapper Service";
 #endif #endif
  
 PEGASUS_USING_PEGASUS;  class CIMServerProcess : public ServerProcess
 PEGASUS_USING_STD;  {
   public:
   
       CIMServerProcess(void)
       {
           cimserver_set_process(this);
       }
   
       virtual ~CIMServerProcess(void)
       {
       }
   
       //defined in PegasusVersion.h
       virtual const char* getProductName() const
       {
           return PEGASUS_PRODUCT_NAME;
       }
   
       virtual const char* getExtendedName() const
       {
           return PEGASUS_SERVICE_NAME;
       }
   
       virtual const char* getDescription() const
       {
           return PEGASUS_SERVICE_DESCRIPTION;
       }
   
       //defined in PegasusVersion.h
       virtual const char* getVersion() const
       {
           return PEGASUS_PRODUCT_VERSION;
       }
   
       virtual const char* getProcessName() const
       {
           return PEGASUS_PROCESS_NAME;
       }
   
       int cimserver_run(
           int argc,
           char** argv,
           Boolean shutdownOption,
           Boolean debugOutputOption);
   
       void cimserver_stop(void);
   };
   
   ServerRunStatus _serverRunStatus(
       PEGASUS_PROCESS_NAME, PEGASUS_CIMSERVER_START_FILE);
   AutoPtr<CIMServerProcess> _cimServerProcess(new CIMServerProcess());
   static CIMServer* _cimServer = 0;
  
 // //
 //  The command name. //  The command name.
Line 141 
Line 184 
  
 static const char OPTION_SHUTDOWN    = 's'; static const char OPTION_SHUTDOWN    = 's';
  
   static const char   LONG_HELP []  = "help";
   
   static const char   LONG_VERSION []  = "version";
   
 #if defined(PEGASUS_OS_HPUX) #if defined(PEGASUS_OS_HPUX)
 static const char OPTION_BINDVERBOSE = 'X'; static const char OPTION_BINDVERBOSE = 'X';
 #endif #endif
  
 static const String PROPERTY_TIMEOUT = "shutdownTimeout";  
 static const String CIMSERVERSTART_FILE = "/etc/opt/wbem/cimserver_start.conf";  
   
 ConfigManager*    configManager;  
   
 /** GetOptions function - This function defines the Options Table /** GetOptions function - This function defines the Options Table
     and sets up the options from that table using the config manager.     and sets up the options from that table using the config manager.
   
       Some possible exceptions:  NoSuchFile, FileNotReadable, CannotRenameFile,
       ConfigFileSyntaxError, UnrecognizedConfigProperty, InvalidPropertyValue,
       CannotOpenFile.
 */ */
 void GetOptions( void GetOptions(
     ConfigManager* cm,     ConfigManager* cm,
     int& argc,     int& argc,
     char** argv,      char** argv)
     const String& pegasusHome)  
 {  
     try  
     {     {
         cm->mergeConfigFiles();         cm->mergeConfigFiles();
   
         cm->mergeCommandLine(argc, argv);         cm->mergeCommandLine(argc, argv);
     }     }
     catch (NoSuchFile nsf)  
     {  
         throw nsf;  
     }  
     catch (FileNotReadable fnr)  
     {  
         throw fnr;  
     }  
     catch (CannotRenameFile ftrf)  
     {  
         throw ftrf;  
     }  
     catch (ConfigFileSyntaxError cfse)  
     {  
         throw cfse;  
     }  
     catch(UnrecognizedConfigProperty ucp)  
     {  
         throw ucp;  
     }  
     catch(InvalidPropertyValue ipv)  
     {  
         throw ipv;  
     }  
 }  
  
 /* PrintHelp - This is temporary until we expand the options manager to allow /* PrintHelp - This is temporary until we expand the options manager to allow
    options help to be defined with the OptionRow entries and presented from    options help to be defined with the OptionRow entries and presented from
Line 197 
Line 214 
 */ */
 void PrintHelp(const char* arg0) void PrintHelp(const char* arg0)
 { {
     /**  
         Build the usage string for the config command.  
     */  
     String usage = String (USAGE);     String usage = String (USAGE);
     usage.append (COMMAND_NAME);     usage.append (COMMAND_NAME);
     usage.append (" [ [ options ] | [ configProperty=value, ... ] ]\n");     usage.append (" [ [ options ] | [ configProperty=value, ... ] ]\n");
     usage.append ("  options\n");     usage.append ("  options\n");
     usage.append ("    -v          - displays CIM Server version number\n");      usage.append("    -v, --version   - displays CIM Server version number\n");
     usage.append ("    -h          - prints this help message\n");      usage.append ("    -h, --help      - prints this help message\n");
     usage.append ("    -s          - shuts down CIM Server\n");     usage.append ("    -s          - shuts down CIM Server\n");
 #ifndef PEGASUS_OS_HPUX  #if !defined(PEGASUS_USE_RELEASE_DIRS)
     usage.append ("    -D [home]   - sets pegasus home directory\n");     usage.append ("    -D [home]   - sets pegasus home directory\n");
 #endif #endif
 #if defined(PEGASUS_OS_TYPE_WINDOWS) #if defined(PEGASUS_OS_TYPE_WINDOWS)
     usage.append ("    -install    - installs pegasus as a Windows NT Service\n");      usage.append ("    -install [name] - installs pegasus as a Windows "
     usage.append ("    -remove     - removes pegasus as a Windows NT Service\n");          "Service\n");
       usage.append ("                      [name] is optional and overrides "
           "the\n");
       usage.append ("                      default CIM Server Service Name\n");
       usage.append ("    -remove [name]  - removes pegasus as a Windows "
           "Service\n");
       usage.append ("                      [name] is optional and overrides "
           "the\n");
       usage.append ("                      default CIM Server Service Name\n");
       usage.append ("    -start [name]   - starts pegasus as a Windows "
           "Service\n");
       usage.append ("                      [name] is optional and overrides "
           "the\n");
       usage.append ("                      default CIM Server Service Name\n");
       usage.append ("    -stop [name]    - stops pegasus as a Windows "
           "Service\n");
       usage.append ("                      [name] is optional and overrides "
           "the\n");
       usage.append ("                      default CIM Server Service Name\n\n");
 #endif #endif
     usage.append ("  configProperty=value\n");     usage.append ("  configProperty=value\n");
     usage.append ("                - sets CIM Server configuration property\n");      usage.append ("                    - sets CIM Server configuration "
           "property\n");
  
     cout << endl;     cout << endl;
 #if defined(PEGASUS_OS_HPUX)      cout << _cimServerProcess->getProductName() << " " <<
     cout << PLATFORM_PRODUCT_NAME << " " << PLATFORM_PRODUCT_VERSION << endl;          _cimServerProcess->getVersion() << endl;
 #else  
     cout << PEGASUS_NAME << PEGASUS_VERSION << endl;  
 #endif  
     cout << endl;     cout << endl;
     cout << usage << endl;  
 }  
  
 void shutdownCIMOM(Uint32 timeoutValue)  #if defined(PEGASUS_OS_TYPE_WINDOWS)
 {      MessageLoaderParms parms("src.Server.cimserver.MENU.WINDOWS", usage);
     //  #elif defined(PEGASUS_USE_RELEASE_DIRS)
     // Create CIMClient object      MessageLoaderParms parms(
     //          "src.Server.cimserver.MENU.HPUXLINUXIA64GNU", usage);
     CIMClient client;  #else
       MessageLoaderParms parms("src.Server.cimserver.MENU.STANDARD", usage);
     //  
     // Get local host name  
     //  
     String hostStr = System::getHostName();  
   
     //  
     // open connection to CIMOM  
     //  
     try  
     {  
         client.connectLocal();  
   
         //  
         // set client timeout to 2 seconds  
         //  
         client.setTimeout(2000);  
     }  
     catch(Exception& e)  
     {  
         PEGASUS_STD(cerr) << "Unable to connect to CIM Server." << PEGASUS_STD(endl);  
         PEGASUS_STD(cerr) << "CIM Server may not be running." << PEGASUS_STD(endl);  
 #ifdef PEGASUS_OS_OS400  
         // The server job may still be active but not responding.  
         // Kill the job if it exists.  
         cimserver_kill();  
 #endif #endif
         exit(0);      cout << MessageLoader::getMessage(parms) << endl;
     }     }
  
     try  // This needs to be called at various points in the code depending on the
   // platform and error conditions. We need to delete the _cimServer
   // reference on exit in order for the destructors to get called.
   void deleteCIMServer()
     {     {
         //      delete _cimServer;
         // construct CIMObjectPath      _cimServer = 0;
         //  
         String referenceStr = "//";  
         referenceStr.append(hostStr);  
         referenceStr.append(PEGASUS_NAMESPACENAME_SHUTDOWN);  
         referenceStr.append(":");  
         referenceStr.append(PEGASUS_CLASSNAME_SHUTDOWN);  
         CIMObjectPath reference(referenceStr);  
   
         //  
         // issue the invokeMethod request on the shutdown method  
         //  
         Array<CIMParamValue> inParams;  
         Array<CIMParamValue> outParams;  
   
         // set force option to true for now  
         inParams.append(CIMParamValue("force",  
             CIMValue(Boolean(true))));  
   
         inParams.append(CIMParamValue("timeout",  
             CIMValue(Uint32(timeoutValue))));  
   
         CIMValue retValue = client.invokeMethod(  
             PEGASUS_NAMESPACENAME_SHUTDOWN,  
             reference,  
             "shutdown",  
             inParams,  
             outParams);  
     }  
     catch(CIMException& e)  
     {  
         PEGASUS_STD(cerr) << "Failed to shutdown server: ";  
         if (e.getCode() == CIM_ERR_INVALID_NAMESPACE)  
         {  
             PEGASUS_STD(cerr) << "The repository may be empty.";  
             PEGASUS_STD(cerr) << PEGASUS_STD(endl);  
         }  
         else  
         {  
             PEGASUS_STD(cerr) << e.getMessage() << PEGASUS_STD(endl);  
         }         }
 #ifdef PEGASUS_OS_OS400  
         // Kill the server job.  
         cimserver_kill();  
 #endif  
         exit(1);  
     }  
     catch(Exception& e)  
     {  
         //  
         // This may mean the CIM Server has been terminated and returns a  
         // "Empty HTTP response message" HTTP error response.  To be sure  
         // CIM Server gets shutdown, if CIM Server is still running at  
         // this time, we will kill the cimserver process.  
         //  
         // give CIM Server some time to finish up  
         //  
         //System::sleep(1);  
         //cimserver_kill();  
  
   // l10n
         //         //
         // Check to see if CIMServer is still running.  If CIMServer  // Dummy function for the Thread object associated with the initial thread.
         // is still running and the shutdown timeout has not expired,  // Since the initial thread is used to process CIM requests, this is
         // loop and wait one second until either CIM Server is  // needed to localize the exceptions thrown during CIM request processing.
         // terminated or until timeout expires.  If timeout expires  // Note: This function should never be called!
         // and CIMServer is still running, kill the CIMServer  
         // process.  
         //         //
         Uint32 maxWaitTime = timeoutValue - 2;  ThreadReturnType PEGASUS_THREAD_CDECL dummyThreadFunc(void *parm)
         Boolean running = isCIMServerRunning();  
         while ( running && maxWaitTime > 0 )  
         {  
             System::sleep(1);  
             running = isCIMServerRunning();  
             maxWaitTime = maxWaitTime - 1;  
         }  
   
         if (running)  
         {         {
             cimserver_kill();     return((ThreadReturnType)0);
         }  
     }  
     //catch(Exception& e)  
     //{  
     //    PEGASUS_STD(cerr) << "Error occurred while stopping the CIM Server: ";  
     //    PEGASUS_STD(cerr) << e.getMessage() << PEGASUS_STD(endl);  
     //    exit(1);  
     //}  
   
     return;  
 } }
  
  
Line 364 
Line 293 
 ////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
 int main(int argc, char** argv) int main(int argc, char** argv)
 { {
     String pegasusHome  = String::EMPTY;      String pegasusHome;
     Boolean pegasusIOLog = false;  
     String httpPort = String::EMPTY;  
     String httpsPort = String::EMPTY;  
     String logsDirectory = String::EMPTY;  
     Boolean useSLP = false;  
     Boolean useSSL = false;  
     Boolean daemonOption = false;  
     Boolean shutdownOption = false;     Boolean shutdownOption = false;
     Uint32 timeoutValue  = 0;      Boolean debugOutputOption = false;
   
   //l10n
   // Set Message loading to process locale
   MessageLoader::_useProcessLocale = true;
   //l10n
  
 #ifdef PEGASUS_OS_OS400  //l10n
     // Initialize Pegasus home to the shipped OS/400 directory.  #if defined(PEGASUS_OS_AIX) && defined(PEGASUS_HAS_MESSAGES)
     pegasusHome = OS400_DEFAULT_PEGASUS_HOME;  setlocale(LC_ALL, "");
 #endif #endif
  
   #ifndef PEGASUS_OS_TYPE_WINDOWS
     //     //
     // Get environment variables:     // Get environment variables:
     //     //
     #if defined(PEGASUS_OS_AIX) && defined(PEGASUS_USE_RELEASE_DIRS)
       pegasusHome = AIX_RELEASE_PEGASUS_HOME;
     #elif !defined(PEGASUS_USE_RELEASE_DIRS)
     const char* tmp = getenv("PEGASUS_HOME");     const char* tmp = getenv("PEGASUS_HOME");
  
     if (tmp)     if (tmp)
     {     {
         pegasusHome = tmp;         pegasusHome = tmp;
     }     }
     #endif
  
     FileSystem::translateSlashes(pegasusHome);     FileSystem::translateSlashes(pegasusHome);
   #else
  
     // on Windows NT if there are no command-line options, run as a service    // windows only
     //setHome(pegasusHome);
     pegasusHome = _cimServerProcess->getHome();
   #endif
  
     if (argc == 1 )  
     {  
       cim_server_service(argc, argv);  
     }  
     else  
     {  
         // Get help, version, and shutdown options         // Get help, version, and shutdown options
  
         for (int i = 1; i < argc; )         for (int i = 1; i < argc; )
         {         {
             const char* arg = argv[i];             const char* arg = argv[i];
               if(String::equal(arg,"--help"))
               {
                       PrintHelp(argv[0]);
                       exit(0);
               }
               else if(String::equal(arg,"--version"))
               {
                   cout << _cimServerProcess->getVersion() << endl;
                   exit(0);
               }
             // Check for -option             // Check for -option
             if (*arg == '-')              else if (*arg == '-')
             {             {
                 // Get the option                 // Get the option
                 const char* option = arg + 1;                 const char* option = arg + 1;
Line 415 
Line 354 
                 //                 //
                 // Check to see if user asked for the version (-v option):                 // Check to see if user asked for the version (-v option):
                 //                 //
                 if (*option == OPTION_VERSION)                  if (*option == OPTION_VERSION &&
                       strlen(option) == 1)
                 {                 {
 #if defined(PEGASUS_OS_HPUX)                      cout << _cimServerProcess->getVersion() << endl;
                     cout << PLATFORM_PRODUCT_VERSION << endl;  
 #else  
                     cout << PEGASUS_VERSION << endl;  
 #endif  
                     exit(0);                     exit(0);
                 }                 }
                 //                 //
                 // Check to see if user asked for help (-h option):                 // Check to see if user asked for help (-h option):
                 //                 //
                 else if (*option == OPTION_HELP)                  else if (*option == OPTION_HELP &&
                           (strlen(option) == 1))
                 {                 {
                     PrintHelp(argv[0]);                     PrintHelp(argv[0]);
                     exit(0);                     exit(0);
                 }                 }
 #ifndef PEGASUS_OS_HPUX  #if !defined(PEGASUS_USE_RELEASE_DIRS)
                 else if (*option == OPTION_HOME)                  else if (*option == OPTION_HOME &&
                           (strlen(option) == 1))
                 {                 {
                     if (i + 1 < argc)                     if (i + 1 < argc)
                     {                     {
Line 441 
Line 379 
                     }                     }
                     else                     else
                     {                     {
                         cout << "Missing argument for option -" << option << endl;                          String opt(option);
                           MessageLoaderParms parms(
                               "src.Server.cimserver.MISSING_ARGUMENT",
                               "Missing argument for option -$0",
                               opt);
                           cout << MessageLoader::getMessage(parms) << endl;
                         exit(0);                         exit(0);
                     }                     }
  
                     memmove(&argv[i], &argv[i + 2], (argc-i-1) * sizeof(char*));                      memmove(&argv[i], &argv[i + 2],
                           (argc-i-1) * sizeof(char*));
                     argc -= 2;                     argc -= 2;
                 }                 }
 #endif #endif
Line 453 
Line 397 
                 //                 //
                 // Check to see if user asked for the version (-X option):                 // Check to see if user asked for the version (-X option):
                 //                 //
                 if (*option == OPTION_BINDVERBOSE)                  if (*option == OPTION_BINDVERBOSE &&
                           (strlen(option) == 1))
                 {                 {
                     System::bindVerbose = true;                     System::bindVerbose = true;
                     cout << "Unsupported debug option, BIND_VERBOSE, enabled."  
                          << endl;                      MessageLoaderParms parms(
                           "src.Server.cimserver.UNSUPPORTED_DEBUG_OPTION",
                           "Unsupported debug option, BIND_VERBOSE, enabled.");
                       cout << MessageLoader::getMessage(parms) << endl;
                     // remove the option from the command line                     // remove the option from the command line
                     memmove(&argv[i], &argv[i + 1], (argc-i) * sizeof(char*));                     memmove(&argv[i], &argv[i + 1], (argc-i) * sizeof(char*));
                     argc--;                     argc--;
Line 466 
Line 414 
                 //                 //
                 // Check to see if user asked for shutdown (-s option):                 // Check to see if user asked for shutdown (-s option):
                 //                 //
                 else if (*option == OPTION_SHUTDOWN)                  else if (*option == OPTION_SHUTDOWN &&
                           (strlen(option) == 1))
                 {                 {
                     //                     //
                     // check to see if user is root  
                     //  
                     if (!System::isPrivilegedUser(System::getEffectiveUserName()))  
                     {  
                         cout << "You must have superuser privilege to run ";  
                         cout << "cimserver." << endl;  
                         exit(0);  
                     }  
   
                     //  
                     // Check to see if shutdown has already been specified:                     // Check to see if shutdown has already been specified:
                     //                     //
                     if (shutdownOption)                     if (shutdownOption)
                     {                     {
                         cout << "Duplicate shutdown option specified." << endl;                          MessageLoaderParms parms(
                               "src.Server.cimserver.DUPLICATE_SHUTDOWN_OPTION",
                               "Duplicate shutdown option specified.");
   
                           cout << MessageLoader::getMessage(parms) << endl;
                         exit(0);                         exit(0);
                     }                     }
  
Line 499 
Line 442 
             else             else
                 i++;                 i++;
         }         }
     }  
  
     //     //
     // Set the value for pegasusHome property     // Set the value for pegasusHome property
Line 507 
Line 449 
     ConfigManager::setPegasusHome(pegasusHome);     ConfigManager::setPegasusHome(pegasusHome);
  
     //     //
     // Get an instance of the Config Manager.      // Do the plaform specific run
     //     //
     configManager = ConfigManager::getInstance();  
  
     //      return _cimServerProcess->platform_run(
     // Get options (from command line and from configuration file); this          argc, argv, shutdownOption, debugOutputOption);
     // removes corresponding options and their arguments from the command  
     // line.  
     //  
     try  
     {  
         GetOptions(configManager, argc, argv, pegasusHome);  
     }     }
     catch (Exception& e)  
   void CIMServerProcess::cimserver_stop()
     {     {
         cerr << argv[0] << ": " << e.getMessage() << endl;      _cimServer->shutdownSignal();
         exit(1);  
     }     }
  
     try  
     {  
         //         //
         // Check to see if we should (can) install as a NT service  // The main, common, running code
   //
   // NOTE: Do NOT call exit().  Use return(), otherwise some platforms
   // will fail to shutdown properly/cleanly.
   //
   // TODO: Current change minimal for platform "service" shutdown bug fixes.
   // Perhpas further extract out common stuff and put into main(), put
   // daemon stuff into platform specific platform_run(), etc.
   // Note: make sure to not put error handling stuff that platform
   // specific runs may need to deal with bettter (instead of exit(), etc).
         //         //
  
         if (String::equal(configManager->getCurrentValue("install"), "true"))  int CIMServerProcess::cimserver_run(
         {      int argc,
             if( 0 != cimserver_install_nt_service( pegasusHome ))      char** argv,
       Boolean shutdownOption,
       Boolean debugOutputOption)
             {             {
                 cout << "\nPegasus installed as NT Service";      String logsDirectory;
                 exit(0);      Boolean daemonOption = false;
             }  
         }  
  
         //         //
         // Check to see if we should (can) remove Pegasus as an NT service      // Get an instance of the Config Manager.
         //         //
       ConfigManager* configManager = ConfigManager::getInstance();
       configManager->useConfigFiles = true;
  
         if (String::equal(configManager->getCurrentValue("remove"), "true"))      //
         {      // Get options (from command line and from configuration file); this
             if( 0 != cimserver_remove_nt_service() )      // removes corresponding options and their arguments from the command
       // line.
       //
       try
             {             {
                 cout << "\nPegasus removed as NT Service";          GetOptions(configManager, argc, argv);
                 exit(0);  
             }  
         }         }
       catch (Exception& e)
       {
           MessageLoaderParms parms("src.Server.cimserver.SERVER_NOT_STARTED",
               "cimserver not started: $0", e.getMessage());
  
         //          Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
         // Check to see if we should Pegasus as a daemon              parms);
         //  
  
         if (String::equal(configManager->getCurrentValue("daemon"), "true"))          PEGASUS_STD(cerr) << argv[0] << ": " <<
         {              MessageLoader::getMessage(parms) << PEGASUS_STD(endl);
             daemonOption = true;  
           return(1);
       }
   
   // l10n
       // Set the home directory, msg sub-dir, into the MessageLoader.
       // This will be the default directory where the resource bundles
       // are found.
       MessageLoader::setPegasusMsgHome(ConfigManager::getHomedPath(
           ConfigManager::getInstance()->getCurrentValue("messageDir")));
   
       Boolean enableHttpConnection = ConfigManager::parseBooleanValue(
           configManager->getCurrentValue("enableHttpConnection"));
       Boolean enableHttpsConnection = ConfigManager::parseBooleanValue(
           configManager->getCurrentValue("enableHttpsConnection"));
   
       // Make sure at least one connection is enabled
   #ifdef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
       if (!enableHttpConnection && !enableHttpsConnection)
       {
           MessageLoaderParms parms(
               "src.Server.cimserver.HTTP_NOT_ENABLED_SERVER_NOT_STARTING",
               "Neither HTTP nor HTTPS connection is enabled.");
           Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER, Logger::WARNING,
               parms);
           cerr << MessageLoader::getMessage(parms) << endl;
           return 1;
         }         }
   #endif
  
       try
       {
         //         //
         // Check the log trace options and set global variable          // Check to see if we should Pegasus as a daemon
         //         //
  
         if (String::equal(configManager->getCurrentValue("logtrace"), "true"))          daemonOption = ConfigManager::parseBooleanValue(
         {              configManager->getCurrentValue("daemon"));
             pegasusIOLog = true;  
         }  
  
         // Get the log file directory definition.  
         // We put String into Cstring because  
         // Directory functions only handle Cstring.  
         // ATTN-KS: create String based directory functions.  
   
         logsDirectory = configManager->getCurrentValue("logdir");  
         logsDirectory =         logsDirectory =
             ConfigManager::getHomedPath(configManager->getCurrentValue("logdir"));             ConfigManager::getHomedPath(configManager->getCurrentValue("logdir"));
  
Line 585 
Line 554 
         // Might be more logical to clean before set.         // Might be more logical to clean before set.
         // ATTN: Need tool to completely disable logging.         // ATTN: Need tool to completely disable logging.
  
 #ifndef PEGASUS_OS_HPUX  #if !defined(PEGASUS_OS_HPUX) && !defined(PEGASUS_PLATFORM_LINUX_IA64_GNU)
         Logger::setHomeDirectory(logsDirectory);         Logger::setHomeDirectory(logsDirectory);
 #endif #endif
  
Line 596 
Line 565 
         {         {
             String configTimeout =             String configTimeout =
                 configManager->getCurrentValue("shutdownTimeout");                 configManager->getCurrentValue("shutdownTimeout");
             timeoutValue = strtol(configTimeout.getCString(), (char **)0, 10);              Uint32 timeoutValue = strtol(
                   configTimeout.getCString(), (char **)0, 10);
  
             shutdownCIMOM(timeoutValue);              ServerShutdownClient serverShutdownClient(&_serverRunStatus);
               serverShutdownClient.shutdown(timeoutValue);
  
             cout << "CIM Server stopped." << endl;              MessageLoaderParms parms(
             exit(0);                  "src.Server.cimserver.SERVER_STOPPED",
                   "CIM Server stopped.");
   
               cout << MessageLoader::getMessage(parms) << endl;
               return(0);
         }         }
  
   #if defined(PEGASUS_DEBUG) && !defined(PEGASUS_USE_SYSLOGS)
           // Leave this in until people get familiar with the logs.
           MessageLoaderParms parms("src.Server.cimserver.LOGS_DIRECTORY",
                                    "Logs Directory = ");
           cout << MessageLoader::getMessage(parms) << logsDirectory << endl;
   #endif
       }
       catch (UnrecognizedConfigProperty& e)
       {
       //l10n
       //cout << "Error: " << e.getMessage() << endl;
       MessageLoaderParms parms("src.Server.cimserver.ERROR",
                                "Error: $0",
                                e.getMessage());
       cout << MessageLoader::getMessage(parms) << endl;
       }
   
       // Bug 2148 - Here is the order of operations for determining the server
       // HTTP and HTTPS ports.
       // 1) If the user explicitly specified a port, use it.
       // 2) If the user did not specify a port, get the port from the
       //    services file.
       // 3) If no value is specified in the services file, use the IANA WBEM
       //    default port.
       // Note that 2 and 3 are done within the System::lookupPort method
       // An empty string from the ConfigManager implies that the user did
       // not specify a port.
   
       Uint32 portNumberHttps=0;
       Uint32 portNumberHttp=0;
       Uint32 portNumberExportHttps=0;
   
       if (enableHttpsConnection)
       {
           String httpsPort = configManager->getCurrentValue("httpsPort");
           if (httpsPort == String::EMPTY)
           {
         //         //
         // Get the port numbers              // Look up the WBEM-HTTPS port number
         //         //
               portNumberHttps = System::lookupPort(WBEM_HTTPS_SERVICE_NAME,
                   WBEM_DEFAULT_HTTPS_PORT);
  
         httpPort = configManager->getCurrentValue("httpPort");          } else
           {
         httpsPort = configManager->getCurrentValue("httpsPort");              //
               // user-specified
         // Leave this in until people get familiar with the logs.              //
 #ifndef PEGASUS_OS_HPUX              CString portString = httpsPort.getCString();
         cout << "Logs Directory = " << logsDirectory << endl;              char* end = 0;
 #endif              portNumberHttps = strtol(portString, &end, 10);
               if(!(end != 0 && *end == '\0'))
         if (String::equal(configManager->getCurrentValue("cleanlogs"), "true"))  
         {         {
             Logger::clean(logsDirectory);;                  InvalidPropertyValue e("httpsPort", httpsPort);
                   cerr << e.getMessage() << endl;
                   exit(1);
               }
           }
         }         }
  
         if (String::equal(configManager->getCurrentValue("slp"), "true"))      if (enableHttpConnection)
         {         {
             useSLP =  true;          String httpPort = configManager->getCurrentValue("httpPort");
         }          if (httpPort == String::EMPTY)
           {
               //
               // Look up the WBEM-HTTP port number
               //
               portNumberHttp = System::lookupPort(WBEM_HTTP_SERVICE_NAME,
                   WBEM_DEFAULT_HTTP_PORT);
  
         if (String::equal(configManager->getCurrentValue("SSL"), "true"))          } else
         {         {
             useSSL =  true;              //
               // user-specified
               //
               CString portString = httpPort.getCString();
               char* end = 0;
               portNumberHttp = strtol(portString, &end, 10);
               if(!(end != 0 && *end == '\0'))
               {
                   InvalidPropertyValue e("httpPort", httpPort);
                   cerr << e.getMessage() << endl;
                   exit(1);
         }         }
     }     }
     catch (UnrecognizedConfigProperty e)  
     {  
         cout << "Error: " << e.getMessage() << endl;  
     }     }
  
     Uint32 portNumber;  #if defined(PEGASUS_DEBUG)
       // Put out startup up message.
       cout << _cimServerProcess->getProductName() << " " <<
           _cimServerProcess->getVersion() << endl;
   #endif
  
     char address[32];      // reset message loading to NON-process locale
       MessageLoader::_useProcessLocale = false;
  
     if (useSSL)      // Get the parent's PID before forking
       _serverRunStatus.setParentPid(System::getPID());
   
       // do we need to run as a daemon ?
       if (daemonOption)
     {     {
         char* end = 0;          if(-1 == _cimServerProcess->cimserver_fork())
         CString portString = httpsPort.getCString();      {
         Uint32 port = strtol(portString, &end, 10);          return(-1);
         assert(end != 0 && *end == '\0');      }
       }
   
   // l10n
       // Now we are after the fork...
       // Create a dummy Thread object that can be used to store the
       // AcceptLanguageList object for CIM requests that are serviced
       // by this thread (initial thread of server).  Need to do this
       // because this thread is not in a ThreadPool, but is used
       // to service CIM requests.
       // The run function for the dummy Thread should never be called,
       Thread *dummyInitialThread = new Thread(dummyThreadFunc, NULL, false);
       Thread::setCurrent(dummyInitialThread);
       try
       {
            Thread::setLanguages(LanguageParser::getDefaultAcceptLanguages());
       }
       catch(InvalidAcceptLanguageHeader& e)
       {
             Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
                 MessageLoaderParms(
                     "src.Server.cimserver.FAILED_TO_SET_PROCESS_LOCALE",
                     "Could not convert the system process locale into "
                           "a valid AcceptLanguage format."));
             Logger::put(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
                                e.getMessage());
       }
   
   #if defined(PEGASUS_OS_HPUX) || defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU) \
   || defined(PEGASUS_OS_ZOS) || defined(PEGASUS_OS_AIX) \
   || defined(PEGASUS_OS_SOLARIS) || defined (PEGASUS_OS_VMS)
       umask(S_IWGRP|S_IWOTH);
  
         //         //
         // Look up the WBEM-HTTPS port number      // check if CIMServer is already running
       // if CIMServer is already running, print message and
       // notify parent process (if there is a parent process) to terminate
         //         //
         portNumber = System::lookupPort(WBEM_HTTPS_SERVICE_NAME, port);      if (_serverRunStatus.isServerRunning())
         sprintf(address, "%u", portNumber);  
     }  
     else  
     {     {
         char* end = 0;          MessageLoaderParms parms(
         CString portString = httpPort.getCString();              "src.Server.cimserver.UNABLE_TO_START_SERVER_ALREADY_RUNNING",
         Uint32 port = strtol(portString, &end, 10);              "Unable to start CIMServer.\nCIMServer is already running.");
         assert(end != 0 && *end == '\0');          PEGASUS_STD(cerr) << MessageLoader::getMessage(parms) <<
               PEGASUS_STD(endl);
  
         //         //
         // Look up the WBEM-HTTP port number          // notify parent process (if there is a parent process) to terminate
         //         //
         portNumber = System::lookupPort(WBEM_HTTP_SERVICE_NAME, port);          if (daemonOption)
         sprintf(address, "%u", portNumber);          {
               _cimServerProcess->notify_parent(1);
           }
   
           return 1;
     }     }
  
     // Put out startup up message.  
 #ifndef PEGASUS_OS_HPUX  
     cout << PEGASUS_NAME << PEGASUS_VERSION <<  
          " on port " << address << endl;  
     cout << "Built " << __DATE__ << " " << __TIME__ << endl;  
     cout <<"Starting..."  
          << (pegasusIOLog ? " Tracing to Log ": " ")  
          << (useSLP ? " SLP reg. " : " No SLP ")  
          << (useSSL ? " Use SSL " : " No SSL ")  
         << endl;  
 #endif #endif
  
     // do we need to run as a daemon ?      // try loop to bind the address, and run the server
     if (daemonOption)      try
     {     {
         if(-1 == cimserver_fork())          _cimServer = new CIMServer();
           exit(-1);  
     }  
  
 #ifdef PEGASUS_OS_OS400          if (enableHttpConnection)
     // Special server initialization code for OS/400.  
     if (cimserver_initialize() != 0)  
     {     {
        // do some logging here!  #ifdef PEGASUS_ENABLE_IPV6
        exit(-1);              _cimServer->addAcceptor(HTTPAcceptor::IPV6_CONNECTION,
     }                  portNumberHttp, false);
 #endif #endif
  
 #ifdef PEGASUS_OS_HPUX  #if !defined (PEGASUS_ENABLE_IPV6) || defined (PEGASUS_OS_TYPE_WINDOWS)
     umask(S_IWGRP|S_IWOTH);              _cimServer->addAcceptor(HTTPAcceptor::IPV4_CONNECTION,
                   portNumberHttp, false);
 #endif #endif
  
     // try loop to bind the address, and run the server              Logger::put_l(
     try                  Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
                   MessageLoaderParms(
                       "src.Server.cimserver.LISTENING_ON_HTTP_PORT",
                       "Listening on HTTP port $0.", portNumberHttp));
           }
   
           if (enableHttpsConnection)
     {     {
 #if !defined(PEGASUS_OS_ZOS) && ! defined(PEGASUS_OS_HPUX)  #ifdef PEGASUS_ENABLE_IPV6
         slp_client *discovery = new slp_client() ;;              _cimServer->addAcceptor(HTTPAcceptor::IPV6_CONNECTION,
         String serviceURL;                  portNumberHttps, true);
         serviceURL.assign("service:cim.pegasus://");  
         String host_name = slp_get_host_name();  
         serviceURL.append(host_name);  
         serviceURL.append(":");  
         serviceURL.append(address);  
 #endif #endif
  
         Monitor monitor(true);  #if !defined (PEGASUS_ENABLE_IPV6) || defined (PEGASUS_OS_TYPE_WINDOWS)
         CIMServer server(&monitor, useSSL);              _cimServer->addAcceptor(HTTPAcceptor::IPV4_CONNECTION,
                   portNumberHttps, true);
   #endif
  
         // bind throws an exception if the bind fails              Logger::put_l(
 #ifdef PEGASUS_LOCAL_DOMAIN_SOCKET                  Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
         cout << "Binding to domain socket" << endl;                  MessageLoaderParms(
 #elif !defined(PEGASUS_OS_HPUX)                      "src.Server.cimserver.LISTENING_ON_HTTPS_PORT",
         cout << "Binding to " << address << endl;                      "Listening on HTTPS port $0.", portNumberHttps));
           }
   
   #ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
           _cimServer->addAcceptor(HTTPAcceptor::LOCAL_CONNECTION, 0, false);
   
           Logger::put_l(
               Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
               MessageLoaderParms(
                   "src.Server.cimserver.LISTENING_ON_LOCAL",
                   "Listening on local connection socket."));
 #endif #endif
  
         server.bind(portNumber);  #if defined(PEGASUS_DEBUG)
           if (enableHttpConnection)
           {
               MessageLoaderParms parms(
                   "src.Server.cimserver.LISTENING_ON_HTTP_PORT",
                   "Listening on HTTP port $0.", portNumberHttp);
               cout << MessageLoader::getMessage(parms) << endl;
           }
           if (enableHttpsConnection)
           {
               MessageLoaderParms parms(
                   "src.Server.cimserver.LISTENING_ON_HTTPS_PORT",
                   "Listening on HTTPS port $0.", portNumberHttps);
               cout << MessageLoader::getMessage(parms) << endl;
           }
   
   # ifndef PEGASUS_DISABLE_LOCAL_DOMAIN_SOCKET
           MessageLoaderParms parms(
               "src.Server.cimserver.LISTENING_ON_LOCAL",
               "Listening on local connection socket.");
           cout << MessageLoader::getMessage(parms) << endl;
   # endif
   #endif
  
         time_t last = 0;          // bind throws an exception if the bind fails
           _cimServer->bind();
  
 #if defined(PEGASUS_OS_HPUX)          // notify parent process (if there is a parent process) to terminate
           // so user knows that there is cimserver ready to serve CIM requests.
           if (daemonOption)
           {
               _cimServerProcess->notify_parent(0);
           }
   
   #if defined(PEGASUS_OS_HPUX) || \
       defined(PEGASUS_OS_LINUX) || \
       defined(PEGASUS_OS_ZOS) || \
       defined(PEGASUS_OS_AIX) || \
       defined(PEGASUS_OS_SOLARIS) || \
       defined(PEGASUS_OS_VMS)
         //         //
         // create a file to indicate that the cimserver has started and         // create a file to indicate that the cimserver has started and
         // save the process id of the cimserver process in the file         // save the process id of the cimserver process in the file
         //         //
           _serverRunStatus.setServerRunning();
         // remove the old file if it exists  
         System::removeFile(fname);  
   
         // open the file  
         FILE *pid_file = fopen(fname, "w");  
         if (pid_file)  
         {  
             // save the pid in the file  
             fprintf(pid_file, "%ld\n", (long)server_pid);  
             fclose(pid_file);  
         }  
 #endif #endif
 #ifndef PEGASUS_OS_HPUX  
   #if defined(PEGASUS_DEBUG)
         cout << "Started. " << endl;         cout << "Started. " << endl;
 #endif #endif
  
         // Put server started message to the logger         // Put server started message to the logger
 #ifdef PEGASUS_OS_HPUX          Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER,
         Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,              Logger::INFORMATION,
                     "Started $0 version $1 on port $2.",              MessageLoaderParms(
                     PLATFORM_PRODUCT_NAME, PLATFORM_PRODUCT_VERSION, address);                  "src.Server.cimserver.STARTED_VERSION",
 #else                  "Started $0 version $1.",
         Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,                  _cimServerProcess->getProductName(),
                     "Started $0 version $1 on port $2.",                  _cimServerProcess->getVersion()));
                     PEGASUS_NAME, PEGASUS_VERSION, address);  
 #endif  
   
  
         //         //
         // Loop to call CIMServer's runForever() method until CIMServer         // Loop to call CIMServer's runForever() method until CIMServer
         // has been shutdown         // has been shutdown
         //         //
         while( !server.terminated() )      while( !_cimServer->terminated() )
         {  
 #if !defined(PEGASUS_OS_ZOS) && ! defined(PEGASUS_OS_HPUX)  
           if(useSLP  )  
           {  
             if(  (time(NULL) - last ) > 60 )  
             {             {
               if( discovery != NULL && serviceURL.size() )  
                 discovery->srv_reg_all(serviceURL.getCString(),  
                                        "(namespace=root/cimv2)",  
                                        "service:cim.pegasus",  
                                        "DEFAULT",  
                                        70) ;  
               time(&last);  
             }  
  
             discovery->service_listener();        _cimServer->runForever();
           }  
 #endif  
           server.runForever();  
         }         }
  
         //         //
         // normal termination         // normal termination
         //         //
         // Put server shutdown message to the logger  
         Logger::put(Logger::STANDARD_LOG, "CIMServer", Logger::INFORMATION,  
             "$0 stopped.", PEGASUS_NAME);  
  
 #if defined(PEGASUS_OS_HPUX)          // Put server shutdown message to the logger
         //          Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER,
         // close the file created at startup time to indicate that the              Logger::INFORMATION,
         // cimserver has terminated normally.              MessageLoaderParms(
         //                  "src.Server.cimserver.STOPPED",
         FileSystem::removeFile(CIMSERVERSTART_FILE);                  "$0 stopped.", _cimServerProcess->getProductName()));
 #endif  
     }     }
     catch(Exception& e)     catch(Exception& e)
     {     {
         PEGASUS_STD(cerr) << "Error: " << e.getMessage() << PEGASUS_STD(endl);          MessageLoaderParms parms("src.Server.cimserver.SERVER_NOT_STARTED",
               "cimserver not started: $0", e.getMessage());
           Logger::put_l(Logger::ERROR_LOG, System::CIMSERVER, Logger::SEVERE,
               parms);
           cerr << MessageLoader::getMessage(parms) << endl;
   
           //
           // notify parent process (if there is a parent process) to terminate
           //
           if (daemonOption)
                   _cimServerProcess->notify_parent(1);
   
           deleteCIMServer();
         return 1;         return 1;
     }     }
  
       deleteCIMServer();
     return 0;     return 0;
 } }
   


Legend:
Removed from v.1.1  
changed lines
  Added in v.1.41

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2