Ejemplo n.º 1
0
static bool
SpawnIOChild(char* const* aArgs, PRProcess** aPID,
             PRFileDesc** aFromChildFD, PRFileDesc** aToChildFD)
{
    PRFileDesc* toChildPipeRead;
    PRFileDesc* toChildPipeWrite;
    if (PR_CreatePipe(&toChildPipeRead, &toChildPipeWrite) != PR_SUCCESS)
        return false;
    PR_SetFDInheritable(toChildPipeRead, true);
    PR_SetFDInheritable(toChildPipeWrite, false);

    PRFileDesc* fromChildPipeRead;
    PRFileDesc* fromChildPipeWrite;
    if (PR_CreatePipe(&fromChildPipeRead, &fromChildPipeWrite) != PR_SUCCESS) {
        PR_Close(toChildPipeRead);
        PR_Close(toChildPipeWrite);
        return false;
    }
    PR_SetFDInheritable(fromChildPipeRead, false);
    PR_SetFDInheritable(fromChildPipeWrite, true);

    PRProcessAttr* attr = PR_NewProcessAttr();
    if (!attr) {
        PR_Close(fromChildPipeRead);
        PR_Close(fromChildPipeWrite);
        PR_Close(toChildPipeRead);
        PR_Close(toChildPipeWrite);
        return false;
    }

    PR_ProcessAttrSetStdioRedirect(attr, PR_StandardInput, toChildPipeRead);
    PR_ProcessAttrSetStdioRedirect(attr, PR_StandardOutput, fromChildPipeWrite);   

    PRProcess* process = PR_CreateProcess(aArgs[0], aArgs, nullptr, attr);
    PR_DestroyProcessAttr(attr);
    PR_Close(fromChildPipeWrite);
    PR_Close(toChildPipeRead);
    if (!process) {
        LOG(("ntlm_auth exec failure [%d]", PR_GetError()));
        PR_Close(fromChildPipeRead);
        PR_Close(toChildPipeWrite);
        return false;        
    }

    *aPID = process;
    *aFromChildFD = fromChildPipeRead;
    *aToChildFD = toChildPipeWrite;
    return true;
}
Ejemplo n.º 2
0
PR_SetStdioRedirect(
    PRProcessAttr *attr,
    PRSpecialFD stdioFd,
    PRFileDesc *redirectFd)
{
#if defined(DEBUG)
    static PRBool warn = PR_TRUE;
    if (warn) {
        warn = _PR_Obsolete("PR_SetStdioRedirect()",
                "PR_ProcessAttrSetStdioRedirect()");
    }
#endif
    PR_ProcessAttrSetStdioRedirect(attr, stdioFd, redirectFd);
}
Ejemplo n.º 3
0
static nsresult vboxsvcSpawnDaemon(void)
{
    PRFileDesc *readable = nsnull, *writable = nsnull;
    PRProcessAttr *attr = nsnull;
    nsresult rv = NS_ERROR_FAILURE;
    PRFileDesc *devNull;
    // The ugly casts are necessary because the PR_CreateProcessDetached has
    // a const array of writable strings as a parameter. It won't write. */
    char * const args[] = { (char *)VBoxSVCPath, (char *)"--auto-shutdown", 0 };

    // Use a pipe to determine when the daemon process is in the position
    // to actually process requests. The daemon will write "READY" to the pipe.
    if (PR_CreatePipe(&readable, &writable) != PR_SUCCESS)
        goto end;
    PR_SetFDInheritable(writable, PR_TRUE);

    attr = PR_NewProcessAttr();
    if (!attr)
        goto end;

    if (PR_ProcessAttrSetInheritableFD(attr, writable, VBOXSVC_STARTUP_PIPE_NAME) != PR_SUCCESS)
        goto end;

    devNull = PR_Open("/dev/null", PR_RDWR, 0);
    if (!devNull)
        goto end;

    PR_ProcessAttrSetStdioRedirect(attr, PR_StandardInput, devNull);
    PR_ProcessAttrSetStdioRedirect(attr, PR_StandardOutput, devNull);
    PR_ProcessAttrSetStdioRedirect(attr, PR_StandardError, devNull);

    if (PR_CreateProcessDetached(VBoxSVCPath, args, nsnull, attr) != PR_SUCCESS)
        goto end;

    // Close /dev/null
    PR_Close(devNull);
    // Close the child end of the pipe to make it the only owner of the
    // file descriptor, so that unexpected closing can be detected.
    PR_Close(writable);
    writable = nsnull;

    char msg[10];
    RT_ZERO(msg);
    if (   PR_Read(readable, msg, sizeof(msg)-1) != 5
        || strcmp(msg, "READY"))
    {
        /* If several clients start VBoxSVC simultaneously only one can
         * succeed. So treat this as success as well. */
        rv = NS_OK;
        goto end;
    }

    rv = NS_OK;

end:
    if (readable)
        PR_Close(readable);
    if (writable)
        PR_Close(writable);
    if (attr)
        PR_DestroyProcessAttr(attr);
    return rv;
}
Ejemplo n.º 4
0
nsresult
sbProcess::Run()
{
  PRStatus status;
  nsresult rv;

  // Set up to auto-kill process.
  sbAutoKillProcess autoSelf(this);

  // Operate under the process lock.
  {
    NS_ENSURE_TRUE(mProcessLock, NS_ERROR_NOT_INITIALIZED);
    nsAutoLock autoProcessLock(mProcessLock);

    // Get the number of arguments.
    PRUint32 argCount = mArgList.Length();
    NS_ENSURE_TRUE(argCount > 0, NS_ERROR_ILLEGAL_VALUE);

    // Convert the UTF-16 argument list to a UTF-8 argument list.
    nsTArray<nsCString> argListUTF8;
    for (PRUint32 i = 0; i < argCount; i++) {
      NS_ENSURE_TRUE(argListUTF8.AppendElement
                                   (NS_ConvertUTF16toUTF8(mArgList[i])),
                     NS_ERROR_OUT_OF_MEMORY);
    }

    // Allocate a null-terminated char* argument list and set it up for
    // auto-disposal.
    char** argList = reinterpret_cast<char**>
                       (NS_Alloc((argCount + 1) * sizeof(char*)));
    NS_ENSURE_TRUE(argList, NS_ERROR_OUT_OF_MEMORY);
    sbAutoNSTypePtr<char*> autoArgList(argList);

    // Convert the argument list to a null-terminated char* argument list.
    for (PRUint32 i = 0; i < argCount; i++) {
      argList[i] = const_cast<char*>(argListUTF8[i].get());
    }
    argList[argCount] = NULL;

    // Set up the process attributes and set them up for auto-disposal.
    PRProcessAttr* processAttr = PR_NewProcessAttr();
    NS_ENSURE_TRUE(processAttr, NS_ERROR_FAILURE);
    sbAutoPRProcessAttr autoProcessAttr(processAttr);

    // Set up process stdin.
    if (mPipeStdinString) {
      // Create a process stdin pipe and set it up for auto-disposal.
      PRFileDesc* stdinReadFD;
      PRFileDesc* stdinWriteFD;
      status = PR_CreatePipe(&stdinReadFD, &stdinWriteFD);
      NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE);
      sbAutoPRFileDesc autoStdinReadFD(stdinReadFD);
      sbAutoPRFileDesc autoStdinWriteFD(stdinWriteFD);

      // Set up stdin pipe file descriptors.
      status = PR_SetFDInheritable(stdinReadFD, PR_TRUE);
      NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE);
      status = PR_SetFDInheritable(stdinWriteFD, PR_FALSE);
      NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE);

      // Fill pipe.
      nsCAutoString writeData = NS_ConvertUTF16toUTF8(mStdinString);
      PRInt32 bytesWritten;
      bytesWritten = PR_Write(stdinWriteFD,
                              writeData.get(),
                              writeData.Length());
      NS_ENSURE_TRUE(bytesWritten == writeData.Length(), NS_ERROR_FAILURE);

      // Redirect process stdin.
      PR_ProcessAttrSetStdioRedirect(processAttr,
                                     PR_StandardInput,
                                     stdinReadFD);

      // Keep stdin read descriptor open for the process to read.  Close the
      // stdin write descriptor so that the process gets EOF when all of the
      // data is read.
      mStdinReadFD = autoStdinReadFD.forget();
      PR_Close(autoStdinWriteFD.forget());
    }

    // Set up process stdout.
    if (mPipeStdoutString) {
      // Create a process stdout pipe and set it up for auto-disposal.
      PRFileDesc* stdoutReadFD;
      PRFileDesc* stdoutWriteFD;
      status = PR_CreatePipe(&stdoutReadFD, &stdoutWriteFD);
      NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE);
      sbAutoPRFileDesc autoStdoutReadFD(stdoutReadFD);
      sbAutoPRFileDesc autoStdoutWriteFD(stdoutWriteFD);

      // Set up stdout pipe file descriptors.
      status = PR_SetFDInheritable(stdoutReadFD, PR_FALSE);
      NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE);
      status = PR_SetFDInheritable(stdoutWriteFD, PR_TRUE);
      NS_ENSURE_TRUE(status == PR_SUCCESS, NS_ERROR_FAILURE);

      // Redirect process stdout.
      PR_ProcessAttrSetStdioRedirect(processAttr,
                                     PR_StandardOutput,
                                     stdoutWriteFD);

      // Keep descriptors.
      mStdoutReadFD = autoStdoutReadFD.forget();
      mStdoutWriteFD = autoStdoutWriteFD.forget();
    }

    // Create and start running the process.
    mBaseProcess = PR_CreateProcess(argList[0], argList, NULL, processAttr);
    NS_ENSURE_TRUE(mBaseProcess, NS_ERROR_FAILURE);

    // Wait for process done on another thread.
    nsCOMPtr<nsIRunnable> runnable = NS_NEW_RUNNABLE_METHOD(sbProcess,
                                                            this,
                                                            WaitForDone);
    NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
    rv = NS_NewThread(getter_AddRefs(mWaitForDoneThread), runnable);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  // Clear process auto-kill.
  autoSelf.forget();

  return NS_OK;
}