コード例 #1
0
    /*!a test case for the interaction of remove() and item().
    */
    void removeItem()
    {
       UtlString v1("a");
       UtlString v2("b");
       UtlString v3("c");
       UtlString v4("d");
       UtlContainable* e;

       UtlSList h;
       h.insert(&v1);
       h.insert(&v2);
       h.insert(&v3);
       h.insert(&v4);

       UtlSListIterator iter(h);

       // Check that item() returns NULL in the initial state.
       CPPUNIT_ASSERT(iter.item() == NULL);

       // Step the iterator and check that item() returns v1.
       e = iter();
       CPPUNIT_ASSERT(e == &v1);
       CPPUNIT_ASSERT(iter.item() == &v1);

       // Delete the element and check that item() returns NULL.
       h.remove(e);
       CPPUNIT_ASSERT(iter.item() == NULL);

       // Step the iterator and check that item() returns v2.
       e = iter();
       CPPUNIT_ASSERT(e == &v2);
       CPPUNIT_ASSERT(iter.item() == &v2);

       // Step the iterator and check that item() returns v3.
       e = iter();
       CPPUNIT_ASSERT(e == &v3);
       CPPUNIT_ASSERT(iter.item() == &v3);

       // Delete the element and check that item() returns v2.
       // (Because deleting an element of a list backs the iterator up
       // to the previous element.)
       h.remove(e);
       CPPUNIT_ASSERT(iter.item() == &v2);

       // Step the iterator and check that item() returns v4.
       e = iter();
       CPPUNIT_ASSERT(e == &v4);
       CPPUNIT_ASSERT(iter.item() == &v4);

       // Step the iterator after the last element and check that
       // item() returns NULL.
       e = iter();
       CPPUNIT_ASSERT(e == NULL);
       CPPUNIT_ASSERT(iter.item() == NULL);

    } //removeItem()
コード例 #2
0
    void testPeekAtNext()
    {
       UtlString v1("a");
       UtlString v2("b");
       UtlString v3("c");
       UtlString v4("d");
       UtlContainable* e;

       UtlSList h;
       h.insert(&v1);
       h.insert(&v2);
       h.insert(&v3);
       h.insert(&v4);

       UtlSListIterator iter(h);

       // check that peekAtNext() returns v1 while iterator points at NULL
       e = iter.peekAtNext();
       CPPUNIT_ASSERT(e == &v1);
       CPPUNIT_ASSERT(iter.item() == NULL );

       // Step the iterator and check that peekAtNext() returns v2
       // while iterator points at v1
       iter();
       e = iter.peekAtNext();
       CPPUNIT_ASSERT(e == &v2);
       CPPUNIT_ASSERT(iter.item() == &v1);

       // Step the iterator and check that peekAtNext() returns v3
       // while iterator points at v2
       iter();
       e = iter.peekAtNext();
       CPPUNIT_ASSERT(e == &v3);
       CPPUNIT_ASSERT(iter.item() == &v2);

       // Step the iterator and check that peekAtNext() returns v4
       // while iterator points at v3
       iter();
       e = iter.peekAtNext();
       CPPUNIT_ASSERT(e == &v4);
       CPPUNIT_ASSERT(iter.item() == &v3);

       // Step the iterator and check that peekAtNext() returns NULL
       // while iterator points at v4
       iter();
       e = iter.peekAtNext();
       CPPUNIT_ASSERT(e == NULL);
       CPPUNIT_ASSERT(iter.item() == &v4);
    }
コード例 #3
0
ファイル: DialByNameDB.cpp プロジェクト: mranga/sipxecs
UtlBoolean 
DialByNameDB::getDigitStrings (
    const UtlString& displayName, 
    UtlSList& rDTMFStrings ) const
{
    UtlString lowerString = displayName;
    lowerString.toLower();
    lowerString = lowerString.strip(UtlString::both, '"');
    UtlTokenizer next( lowerString );
    UtlString token;
    UtlSList names;

    // Parse the Display name into a list of names
    // The algorithm for breaking up the string is as follows
    // if the string has > 2 tokens (forget about , separators)
    // create multiple entries in the IMDB for the all combinations
    // so for example
    // John Peter Smith Jr would result in DTMF entries for
    // PeterSmithJrJohn, SmithJrJohnPeter and JrJohnPeterSmith
    // @JC Added - separator for MIT's Avery-Smith example
   
    while (next.next(token, "\t\n,- ")) 
    {
        names.insert ( new UtlString ( token ) );
    }

    size_t numNames = names.entries();

    if ( numNames > 0 ) 
    {
        UtlString reorderedString;
        unsigned int splitPosition = 1;
        do 
        {
            unsigned int i;
            UtlString firstNames;
            for ( i=0; i<splitPosition; i++ ) 
            {
                firstNames += *(UtlString*)names.at(i);
            }

            UtlString lastNames;
            for ( i = splitPosition; i<numNames; i++) 
            {
                lastNames += *(UtlString*)names.at(i);
            }

            // add the new string
            reorderedString = lastNames + firstNames;

            unsigned int len = reorderedString.length();
            
            // calculate thd DTMF digits for the display name
            // firstly strip all , 's and spaces
            UtlString digitString;
            for ( i = 0; i<len; i++ )
            {
                int offset = (int) ( reorderedString(i) - 'a' );
                // filter out white space and comma separators
                if ( (offset >= 0) && (offset < 26) )
                    digitString += digitmap[ offset ];
            }

            rDTMFStrings.insert ( new UtlString (digitString) );

            splitPosition++;
        } while ( splitPosition<numNames );
    }

    // call the desctuctors on all the temp strings
    names.destroyAll();
    return TRUE;
}
コード例 #4
0
ファイル: ZoneAdminRpc.cpp プロジェクト: LordGaav/sipxecs
bool ZoneAdminRpcExec::execute(const HttpRequestContext& requestContext,
                               UtlSList&                 params,
                               void*                     userData,
                               XmlRpcResponse&           response,
                               ExecutionStatus&          status)
{

   bool result = false;
   status = XmlRpcMethod::FAILED;

   if (2 != params.entries())
   {
      handleExtraExecuteParam(name(), response, status);
   }
   else
   {
      if (!params.at(0) || !params.at(0)->isInstanceOf(UtlString::TYPE))
      {
         handleMissingExecuteParam(name(), PARAM_NAME_CALLING_HOST, response, status);
      }
      else
      {
         if (!params.at(1) || !params.at(1)->isInstanceOf(UtlString::TYPE))
         {
            handleMissingExecuteParam(name(), PARAM_NAME_COMMAND, response, status);
         }
         else
         {
            UtlString* pCallingHostname = dynamic_cast<UtlString*>(params.at(0));
            SipxRpc* pSipxRpcImpl = ((SipxRpc *)userData);

            if(validCaller(requestContext, *pCallingHostname, response, *pSipxRpcImpl, name()))
            {
               UtlBool   method_result(true);
               UtlString arguments[3];
               OsPath    mWorkingDirectory = ".";
               OsPath    mExec = SipXecsService::Path(SipXecsService::LibExecDirType,"sipxzoneadmin");
               UtlString mStdOutFile;
               UtlString mStdErrFile;

               UtlString* pSubCommand = dynamic_cast<UtlString*>(params.at(1));

               if ( !buildOutputFiles(*pSubCommand, mStdOutFile, mStdErrFile))
               {
                    // Invalid request. Set a Fault.
                    response.setFault(ZoneAdminRpcMethod::FailureToLaunch, "Invalid command");
                    status = XmlRpcMethod::FAILED;
                    return result;
               }

               OsPath    mStdOutPath = SipXecsService::Path(SipXecsService::LogDirType, mStdOutFile.data());
               OsPath    mStdErrPath = SipXecsService::Path(SipXecsService::LogDirType, mStdErrFile.data());

               // Pass the argumenst to sipx-zoneadmin.sh
               arguments[0] = "-n";                 // non-interactive
               arguments[1] = pSubCommand->data();  // string "<primary server> -o <secondary server>"

               // Make sure that there is no other instance running.
               if (! duplicateProcess(ZoneAdminExec, response, status))
               {
                  // execute the command and return whether or not the launch was successful.
                  OsProcess* zoneCheck = new OsProcess();

                  // Setup the Standard Output and Standard Error files.
                  OsPath mStdInFile;   // Blank
                  int rc;
                  rc = zoneCheck->setIORedirect(mStdInFile, mStdOutPath, mStdErrPath);

                  // Launch the process but tell the parent to ignore the child's signals (especially on shutdown).
                  // It will let the system handle it to avoid a defunct process.
                  if ( (rc=zoneCheck->launch(mExec, &arguments[0], mWorkingDirectory,
                                   zoneCheck->NormalPriorityClass, FALSE,
                                   TRUE)) // Parent to ignore child signals.
                           == OS_SUCCESS )
                  {
                      // Construct and set the response.
                      UtlSList outputPaths;
                      outputPaths.insert(&mStdOutPath);
                      outputPaths.insert(&mStdErrPath);

                      // Add the file resources to Supervisor Process so they can be retrieved
                      FileResource::logFileResource( mStdOutPath, SipxProcessManager::getInstance()->findProcess(SUPERVISOR_PROCESS_NAME));
                      FileResource::logFileResource( mStdErrPath, SipxProcessManager::getInstance()->findProcess(SUPERVISOR_PROCESS_NAME));
                      response.setResponse(&outputPaths);
                      status = XmlRpcMethod::OK;
                      result = true;
                  }   // launch
                  else
                  {
                     // Failed to launch the command, send a fault.
                     response.setFault(ZoneAdminRpcMethod::FailureToLaunch, "Failure to launch command");
                     status = XmlRpcMethod::FAILED;
                  }

                  delete zoneCheck;
               }  // duplicateProcess
            }  // validcaller
            else
            {
               status = XmlRpcMethod::FAILED;
            }
         }  // param 1 okay
      }  // param 0 okay
   } //number of parms check

   return result;
}
コード例 #5
0
ファイル: UtlSList.cpp プロジェクト: Konnekt/lib-sipx
    void utlTestAppend_Insert(TestInsertOrAppend type)
    {
        int testCount = 2 ; 
        const char* prefix = ""; 
        UtlInt testInt(1234) ;
        UtlString testString("Test String") ;    
        if (type == TEST_APPEND) 
        {
            commonList.append(&testInt) ; 
            commonList.append(&testString) ; 
            prefix = "Test the append(UtlContainable*) method for a non empty list" ;
        }
        else if (type == TEST_INSERT)
        {
            commonList.insert(&testInt) ; 
            commonList.insert(&testString) ; 
            prefix = "Test the insert(UtlContainable*) method for a non empty list" ;
        }
        int expectedCount  = commonEntriesCount + testCount ; 
        
        UtlContainable* uActual ; 
        UtlContainable* uExpected ; 
        string msg ; 

        // Verify that the number of entries has increased accordingly
        TestUtilities::createMessage(2, &msg, prefix, " :- Verify the number of entries") ; 
        CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), expectedCount, \
            (int)commonList.entries()) ; 

        // Verify that the first entry has still not changed.
        uActual = commonList.at(0) ; 
        uExpected = commonContainables[0] ; 
        TestUtilities::createMessage(2, &msg, prefix, \
            " :- Verify that the first entry is not changed") ; 
        CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), uActual, uExpected) ; 

        // Verify the entry at the previous last position
        TestUtilities::createMessage(2, &msg, prefix, \
            " :- Verify that the previous last entry is intact") ; 

        // Verify that the number of entries has increased accordingly
        TestUtilities::createMessage(2, &msg, prefix, \
            " :- Verify the number of entries") ;
        CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), expectedCount, \
           (int)commonList.entries()) ; 

        // Verify that the first entry has still not changed.
        uActual = commonList.at(0) ; 
        uExpected = commonContainables[0] ; 
        TestUtilities::createMessage(2, &msg, prefix, \
            " :- Verify that the first entry is not changed") ; 
        CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), uActual, uExpected) ; 

        // Verify the entry at the previous last position
        TestUtilities::createMessage(2, &msg, prefix, \
            " :- Verify that the previous last entry is intact") ; 
        uActual = commonList.at(commonEntriesCount-1) ; 
        uExpected = commonContainables[commonEntriesCount-1] ; 
        CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), uActual, uExpected) ;

        // Verify that the two new entries are added. 
        TestUtilities::createMessage(2, &msg, prefix, \
            " :- Verify that the Collectable Integer has been added") ; 
        uActual = commonList.at(commonEntriesCount) ; 
        uExpected = &testInt ; 
        CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), uActual, uExpected) ;        

        TestUtilities::createMessage(2, &msg, prefix, \
            " :- Verify that the Collectable String has been added") ; 
        uActual = commonList.at(commonEntriesCount + 1) ; 
        uExpected = &testString ; 
        CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), uActual, uExpected) ;

    } //testAppend
コード例 #6
0
int supervisorMain(bool bOriginalSupervisor)
{
    // Create forked process which will do nothing unless parent dies.  Parent continues with initialization.
    forkSupervisorInWaiting();

    // Drop privileges down to the specified user & group
    const char * sipxpbxuser = SipXecsService::User();
    const char * sipxpbxgroup = SipXecsService::Group();

    if (NULL == sipxpbxuser || 0 == strlen(sipxpbxuser))
    {
       osPrintf("sipXsupervisor: Failed to setuid(%s), username not defined.\n",
          sipxpbxuser);
       return 2;
    }
    if (NULL == sipxpbxgroup || 0 == strlen(sipxpbxgroup))
    {
       osPrintf("sipXsupervisor: Failed to setgid(%s), groupname not defined.\n",
          sipxpbxgroup);
       return 2;
    }

    struct group * grp = getgrnam(sipxpbxgroup);
    if (NULL == grp)
    {
       if (0 != errno)
       {
          osPrintf("getgrnam(%s) failed, errno = %d.",
             sipxpbxgroup, errno);
       }
       else
       {
          osPrintf(
             "sipXsupervisor: getgrnam(%s) failed, user does not exist.",
                sipxpbxgroup);
       }
       return 3;
    }

    struct passwd * pwd = getpwnam(sipxpbxuser);
    if (NULL == pwd)
    {
       if (0 != errno)
       {
          osPrintf("getpwnam(%s) failed, errno = %d.",
             sipxpbxuser, errno);
       }
       else
       {
          osPrintf(
             "sipXsupervisor: getpwnam(%s) failed, user does not exist.",
                sipxpbxuser);
       }
       return 3;
    }

    // Change group first, cause once user is changed this cannot be done.
    if (0 != setgid(grp->gr_gid))
    {
       osPrintf("sipXsupervisor: setgid(%d) failed, errno = %d.",
          (int)grp->gr_gid, errno);
       return 4;
    }

    if (0 != setuid(pwd->pw_uid))
    {
       osPrintf("sipXsupervisor: setuid(%d) failed, errno = %d.",
          (int)pwd->pw_uid, errno);
       return 4;
    }


# if 0
// Only output problems.  This keeps the startup output clean.
    osPrintf("sipXsupervisor: Dropped privileges with setuid(%s)/setgid(%s).",
       sipxpbxuser, sipxpbxgroup);
#endif

    OsMsgQShared::setQueuePreference(OsMsgQShared::QUEUE_UNLIMITED);

    // Block all signals in this the main thread
    // Any threads created after this will have all signals masked.
    OsTask::blockSignals();

    // Create a new task to wait for signals.  Only that task
    // will ever see a signal from the outside.
    SignalTask* signalTask = new SignalTask();
    signalTask->start() ;

    // All osPrintf output should go to the console until the log file is initialized.
    enableConsoleOutput(true);

    // Initialize the log file.
    Os::LoggerHelper::instance().processName = "Supervisor";
    UtlString logFile = SipXecsService::Path(SipXecsService::LogDirType, "sipxsupervisor.log");
    Os::LoggerHelper::instance().initialize(PRI_DEBUG, logFile.data());

    if (!bOriginalSupervisor)
    {
       Os::Logger::instance().log(FAC_SUPERVISOR, PRI_CRIT,
                     "Restarting sipxsupervisor after unexpected shutdown");
    }
    Os::Logger::instance().log(FAC_SUPERVISOR, PRI_NOTICE,
                  ">>>>> Starting sipxsupervisor version %s",
                  VERSION);

    // Now that the log file is initialized, stop sending osPrintf to the console.
    // All relevant log messages from this point on must use Os::Logger::instance().log().
    enableConsoleOutput(false);
    fflush(NULL); // Flush all output so children don't get a buffer of output

    // Open the supervisor configuration file
    OsConfigDb supervisorConfiguration;
    OsPath supervisorConfigPath = SipXecsService::Path(SipXecsService::ConfigurationDirType,
                                                       CONFIG_SETTINGS_FILE);
    if (OS_SUCCESS != supervisorConfiguration.loadFromFile(supervisorConfigPath.data()))
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_WARNING,
                     "Failed to open supervisor configuration file at '%s'",
                     supervisorConfigPath.data()
                     );
    }

    // Set logging based on the supervisor configuration - TODO change default to "NOTICE" ?
    OsSysLogPriority logPri = SipXecsService::setLogPriority(supervisorConfiguration, SUPERVISOR_PREFIX, PRI_INFO );
    Os::Logger::instance().setLoggingPriorityForFacility(FAC_ALARM, logPri);

    // Open the domain configuration file
    OsConfigDb domainConfiguration;
    OsPath domainConfigPath = SipXecsService::domainConfigPath();
    if (OS_SUCCESS != domainConfiguration.loadFromFile(domainConfigPath.data()))
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_ERR,
                     "Failed to open domain configuration '%s'",
                     domainConfigPath.data()
                     );
    }
    // @TODO const char* managementIpBindAddress;
    int managementPortNumber;
    managementPortNumber = domainConfiguration.getPort(SipXecsService::DomainDbKey::SUPERVISOR_PORT);
    if (PORT_NONE == managementPortNumber)
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_WARNING,
                     "%s not configured in '%s', using default: %d",
                     SipXecsService::DomainDbKey::SUPERVISOR_PORT,
                     domainConfigPath.data(), DEFAULT_SUPERVISOR_PORT
                     );
       managementPortNumber=DEFAULT_SUPERVISOR_PORT;
    }
    else if (PORT_DEFAULT == managementPortNumber)
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_NOTICE,"%s set to default: %d",
                     SipXecsService::DomainDbKey::SUPERVISOR_PORT, DEFAULT_SUPERVISOR_PORT
                     );
       managementPortNumber=DEFAULT_SUPERVISOR_PORT;
    }

    UtlSList allowedPeers;
    UtlString configHosts;
    domainConfiguration.get(SipXecsService::DomainDbKey::CONFIG_HOSTS, configHosts);
    if (!configHosts.isNull())
    {
       UtlString hostName;
       for (int hostIndex = 0;
            NameValueTokenizer::getSubField(configHosts.data(), hostIndex, ", \t", &hostName);
            hostIndex++)
       {
          // Found at least one config hostname.
          if (!allowedPeers.contains(&hostName))
          {
             Os::Logger::instance().log(FAC_SUPERVISOR,PRI_DEBUG,
                           "%s value '%s'",
                           SipXecsService::DomainDbKey::CONFIG_HOSTS,
                           hostName.data()
                           );
             allowedPeers.insert(new UtlString(hostName));
          }
       }
    }
    else
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_ERR,
                     "%s not configured in '%s'",
                     SipXecsService::DomainDbKey::CONFIG_HOSTS, domainConfigPath.data()
                     );
    }

    UtlString superHost;
    supervisorConfiguration.get(SUPERVISOR_HOST, superHost);
    if (!superHost.isNull())
    {
       if (!allowedPeers.contains(&superHost))
       {
          allowedPeers.insert(new UtlString(superHost));
       }
    }
    else
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_ERR,
                     "%s not configured in '%s'",
                     SUPERVISOR_HOST, supervisorConfigPath.data()
                     );
    }

    if (allowedPeers.isEmpty())
    {
       Os::Logger::instance().log(FAC_SUPERVISOR,PRI_ERR,
                     "No configuration peers configured.");
    }

    if (!cAlarmServer::getInstance()->init())
    {
       Os::Logger::instance().log(FAC_SUPERVISOR, PRI_ERR,
             "sipXsupervisor failed to init AlarmServer");
    }

    // Initialize management interfaces on the TLS socket
    OsSSLServerSocket serverSocket(50, managementPortNumber /*@TODO managementIpBindAddress */);
    HttpServer        httpServer(&serverSocket); // set up but don't start https server
    XmlRpcDispatch    xmlRpcDispatcher(&httpServer); // attach xml-rpc service to https
    pSipxRpcImpl = new SipxRpc(&xmlRpcDispatcher, allowedPeers); // register xml-rpc methods
    HttpFileAccess    fileAccessService(&httpServer, pSipxRpcImpl); // attach file xfer to https

    if (serverSocket.isOk())
    {
       Os::Logger::instance().log(FAC_SUPERVISOR, PRI_DEBUG, "Starting Management HTTP Server");
       httpServer.start();
    }
    else
    {
       Os::Logger::instance().log(FAC_SUPERVISOR, PRI_ERR, "Management listening socket failure");
    }

    // Read the process definitions.
    UtlString processDefinitionDirectory =
       SipXecsService::Path(SipXecsService::DataDirType, "process.d");
    SipxProcessManager* processManager = SipxProcessManager::getInstance();
    processManager->instantiateProcesses(processDefinitionDirectory);

    // 3.0 had different process def files.  The only important thing in them is the
    // state of the services.  Transfer this state to the new process def files.
    upgradeFrom3_0();

    doWaitLoop();

    // Successful run.
    return 0;
}
コード例 #7
0
ファイル: SwAdminRpc.cpp プロジェクト: ATHLSolutions/sipxecs
bool SwAdminRpcSnapshot::execute(const HttpRequestContext& requestContext,
                                 UtlSList&                 params,
                                 void*                     userData,
                                 XmlRpcResponse&           response,
                                 ExecutionStatus&          status)
{

   bool result = false;
   status = XmlRpcMethod::FAILED;

   if (2 != params.entries())
   {
      handleExtraExecuteParam(name(), response, status);
   }
   else
   {
      if (!params.at(0) || !params.at(0)->isInstanceOf(UtlString::TYPE))
      {
         handleMissingExecuteParam(name(), PARAM_NAME_CALLING_HOST, response, status);
      }
      else
      {
         UtlString* pCallingHostname = dynamic_cast<UtlString*>(params.at(0));
         SipxRpc* pSipxRpcImpl = ((SipxRpc *)userData);

         if (!params.at(1) || !params.at(1)->isInstanceOf(UtlSList::TYPE))
         {
            handleMissingExecuteParam(name(), PARAM_NAME_COMMAND, response, status);
         }
         else
         {
            if (validCaller(requestContext, *pCallingHostname, response, *pSipxRpcImpl, name()))
            {
               UtlSList* pArgsList = dynamic_cast<UtlSList*>(params.at(1));
               UtlSListIterator argsListIterator( *pArgsList );
               UtlString * pArg;

               // Make sure that there is no other instance running.
               if (! duplicateProcess(SwAdminSnapshot, response, status))
               {
                  UtlBool   method_result(true);
                  UtlString arguments[pArgsList->entries()+2];
                  UtlString subCommand;
                  OsPath    mWorkingDirectory = ".";
                  OsPath    mExec = SipXecsService::Path(SipXecsService::BinDirType, SwAdminSnapshot);

                  UtlString mStdOutFile(SwAdminSnapshot_cmd);
                  UtlString mStdErrFile(SwAdminSnapshot_cmd);

                  mStdOutFile.append(SwAdminStdOut_filetype);
                  mStdErrFile.append(SwAdminStdErr_filetype);

                  // Construct and set the response.
                  OsPath mStdOutPath = OsPath(SipXecsService::Path(SipXecsService::LogDirType, mStdOutFile.data()));
                  OsPath mStdErrPath = OsPath(SipXecsService::Path(SipXecsService::LogDirType, mStdErrFile.data()));
                  OsPath processOutPath = OsPath(SipXecsService::Path(SipXecsService::TmpDirType, OUTPUT_FILENAME));

                  for (int i = 0; (pArg = dynamic_cast<UtlString*>(argsListIterator())); i++)
                  {
                     XmlUnEscape(arguments[i], *pArg);
                  }

                  arguments[pArgsList->entries()] = processOutPath.data();
                  arguments[pArgsList->entries()+1] = NULL;

                  // execute the command and return whether or not the launch was successful.
                  OsProcess* swCheck = new OsProcess();

                  // Setup the Standard Output and Standard Error files.
                  OsPath mStdInFile;   // Blank
                  int rc;
                  rc = swCheck->setIORedirect(mStdInFile, mStdOutPath, mStdErrPath);

                  // Launch the process but tell the parent to ignore the child's signals (especially on shutdown).
                  // It will let the system handle it to avoid a defunct process.
                  if ( (rc=swCheck->launch(mExec, &arguments[0], mWorkingDirectory,
                                   swCheck->NormalPriorityClass, FALSE,
                                   TRUE)) // Parent to ignore child signals.
                           == OS_SUCCESS )
                  {
                     // Add the file resources to Supervisor Process so they can be retrieved
                     FileResource::logFileResource( mStdOutPath, SipxProcessManager::getInstance()->findProcess(SUPERVISOR_PROCESS_NAME));
                     FileResource::logFileResource( mStdErrPath, SipxProcessManager::getInstance()->findProcess(SUPERVISOR_PROCESS_NAME));
                     FileResource::logFileResource( processOutPath, SipxProcessManager::getInstance()->findProcess(SUPERVISOR_PROCESS_NAME));

                     UtlString outputFilename = processOutPath;

                     // Construct and set the response.
                     UtlSList outputPaths;
                     outputPaths.insert(&outputFilename);
                     outputPaths.insert(&mStdOutPath);
                     outputPaths.insert(&mStdErrPath);

                     response.setResponse(&outputPaths);
                     status = XmlRpcMethod::OK;
                     result = true;
                  } // launch
                  else
                  {
                     // Failed to launch the command, send a fault.
                     response.setFault(SwAdminRpcMethod::FailureToLaunch, "Failure to launch command");
                     status = XmlRpcMethod::FAILED;
                  }

                  delete swCheck;
               }  // duplicateProcess
            }  // validcaller
            else
            {
               status = XmlRpcMethod::FAILED;
            }
         }  // param 1 okay
      }  // param 0 okay
   } //number of parms check

   return result;
}