VirtualBox

Ignore:
Timestamp:
Oct 12, 2010 1:20:50 PM (14 years ago)
Author:
vboxsync
Message:

Guest Execution/Copy: Added support for input handling, added more code for data copying.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp

    r32852 r33064  
    4747extern RTLISTNODE g_GuestControlExecThreads;
    4848
     49
    4950/**
    5051 * Handle an error event on standard input.
    5152 *
     53 * @returns IPRT status code.
    5254 * @param   hPollSet            The polling set.
    5355 * @param   fPollEvt            The event mask returned by RTPollNoResume.
     
    5557 * @param   pStdInBuf           The standard input buffer.
    5658 */
    57 static void VBoxServiceControlExecProcHandleStdInErrorEvent(RTPOLLSET hPollSet, uint32_t fPollEvt, PRTPIPE phStdInW,
    58                                                             PVBOXSERVICECTRLSTDINBUF pStdInBuf)
    59 {
    60     int rc2;
    61     if (pStdInBuf->off < pStdInBuf->cb)
    62     {
    63         rc2 = RTPollSetRemove(hPollSet, 4 /*TXSEXECHNDID_STDIN_WRITABLE*/);
     59static int VBoxServiceControlExecProcHandleStdInErrorEvent(RTPOLLSET hPollSet, uint32_t fPollEvt, PRTPIPE phStdInW,
     60                                                           PVBOXSERVICECTRLEXECPIPEBUF pStdInBuf)
     61{
     62    int rc = RTCritSectEnter(&pStdInBuf->CritSect);
     63    if (RT_SUCCESS(rc))
     64    {
     65        int rc2;
     66        /* If no data is to be processed anymore, remove the writable pipe from
     67         * the poll set. */
     68        if (pStdInBuf->cbProcessed <= pStdInBuf->cbSize)
     69        {
     70            rc2 = RTPollSetRemove(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_WRITABLE);
     71            AssertRC(rc2);
     72
     73            rc2 = RTPipeClose(*phStdInW);
     74            AssertRC(rc2);
     75            *phStdInW = NIL_RTPIPE;
     76
     77            /* Mark the stdin buffer as dead; we're not using it anymore. */
     78            pStdInBuf->fAlive = false;
     79        }
     80
     81        rc2 = RTPollSetRemove(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_ERROR);
    6482        AssertRC(rc2);
    65     }
    66 
    67     rc2 = RTPollSetRemove(hPollSet, 0 /*TXSEXECHNDID_STDIN*/);
    68     AssertRC(rc2);
    69 
    70     rc2 = RTPipeClose(*phStdInW);
    71     AssertRC(rc2);
    72     *phStdInW = NIL_RTPIPE;
    73 
    74     RTMemFree(pStdInBuf->pch);
    75     pStdInBuf->pch          = NULL;
    76     pStdInBuf->off          = 0;
    77     pStdInBuf->cb           = 0;
    78     pStdInBuf->cbAllocated  = 0;
    79     pStdInBuf->fBitBucket   = true;
     83
     84        rc2 = RTCritSectLeave(&pStdInBuf->CritSect);
     85        if (RT_SUCCESS(rc))
     86            rc = rc2;
     87    }
     88    return rc;
    8089}
    8190
     
    8897 * @param   hStdInW             The standard input pipe.
    8998 */
    90 static int VBoxServiceControlExecProcWriteStdIn(PVBOXSERVICECTRLSTDINBUF pStdInBuf, RTPIPE hStdInW)
    91 {
    92     size_t  cbToWrite = pStdInBuf->cb - pStdInBuf->off;
    93     size_t  cbWritten;
    94     int     rc = RTPipeWrite(hStdInW, &pStdInBuf->pch[pStdInBuf->off], cbToWrite, &cbWritten);
     99static int VBoxServiceControlExecProcWriteStdIn(PVBOXSERVICECTRLEXECPIPEBUF pStdInBuf, RTPIPE hStdInW, size_t *pcbWritten)
     100{
     101    AssertPtrReturn(pcbWritten, VERR_INVALID_PARAMETER);
     102
     103    int rc = RTCritSectEnter(&pStdInBuf->CritSect);
    95104    if (RT_SUCCESS(rc))
    96105    {
    97         Assert(cbWritten == cbToWrite);
    98         pStdInBuf->off += cbWritten;
     106        size_t cbToWrite = pStdInBuf->cbSize - pStdInBuf->cbProcessed;
     107        int rc = VINF_SUCCESS;
     108        if (cbToWrite && pStdInBuf->fAlive)
     109        {
     110            rc = RTPipeWrite(hStdInW, &pStdInBuf->pbData[pStdInBuf->cbProcessed], cbToWrite, pcbWritten);
     111            if (RT_SUCCESS(rc))
     112            {
     113                Assert(*pcbWritten <= cbToWrite);
     114                pStdInBuf->cbProcessed += *pcbWritten;
     115            }
     116            else
     117                *pcbWritten = 0;
     118        }
     119        else
     120            rc = VERR_BAD_PIPE;
     121        int rc2 = RTCritSectLeave(&pStdInBuf->CritSect);
     122        if (RT_SUCCESS(rc))
     123            rc = rc2;
    99124    }
    100125    return rc;
     
    106131 * child process.
    107132 *
     133 * @returns IPRT status code.
    108134 * @param   hPollSet            The polling set.
    109135 * @param   fPollEvt            The event mask returned by RTPollNoResume.
     
    111137 * @param   pStdInBuf           The standard input buffer.
    112138 */
    113 static void VBoxServiceControlExecProcHandleStdInWritableEvent(RTPOLLSET hPollSet, uint32_t fPollEvt, PRTPIPE phStdInW,
    114                                                                PVBOXSERVICECTRLSTDINBUF pStdInBuf)
    115 {
    116     int rc;
     139static int  VBoxServiceControlExecProcHandleStdInWritableEvent(RTPOLLSET hPollSet, uint32_t fPollEvt, PRTPIPE phStdInW,
     140                                                               PVBOXSERVICECTRLEXECPIPEBUF pStdInBuf)
     141{
     142    VBoxServiceVerbose(4, "ControlExec: HandleStdInWritableEvent: fPollEvt=%#x\n", fPollEvt);
     143
     144    int rc = VINF_SUCCESS;
    117145    if (!(fPollEvt & RTPOLL_EVT_ERROR))
    118146    {
    119         rc = VBoxServiceControlExecProcWriteStdIn(pStdInBuf, *phStdInW);
    120         if (RT_FAILURE(rc) && rc != VERR_BAD_PIPE)
    121         {
    122             /** @todo do we need to do something about this error condition? */
     147        size_t cbWritten;
     148        rc = VBoxServiceControlExecProcWriteStdIn(pStdInBuf, *phStdInW, &cbWritten);
     149        if (   RT_FAILURE(rc)
     150            && rc != VERR_BAD_PIPE)
     151        {
     152            /** @todo Do we need to do something about this error condition? */
    123153            AssertRC(rc);
    124154        }
    125155
    126         if (pStdInBuf->off < pStdInBuf->cb)
    127         {
    128             rc = RTPollSetRemove(hPollSet, 4 /*TXSEXECHNDID_STDIN_WRITABLE*/);
     156        /* No more data to write to stdin? Then remove stdin from poll set. */
     157        if (   cbWritten <= 0
     158            || rc == VERR_BAD_PIPE)
     159        {
     160            rc = RTPollSetRemove(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_WRITABLE);
    129161            AssertRC(rc);
    130162        }
    131163    }
    132164    else
    133         VBoxServiceControlExecProcHandleStdInErrorEvent(hPollSet, fPollEvt, phStdInW, pStdInBuf);
     165        rc = VBoxServiceControlExecProcHandleStdInErrorEvent(hPollSet, fPollEvt, phStdInW, pStdInBuf);
     166    return rc;
     167}
     168
     169
     170static int VBoxServiceControlExecProcHandleInputEvent(RTPOLLSET hPollSet, uint32_t fPollEvt, PRTPIPE phStdInW,
     171                                                      uint32_t uHandleId, PVBOXSERVICECTRLEXECPIPEBUF pStdInBuf)
     172{
     173    VBoxServiceVerbose(4, "ControlExec: HandleInputEvent: fPollEvt=%#x\n", fPollEvt);
     174
     175    int rc = VINF_SUCCESS;
     176    if (fPollEvt & RTPOLL_EVT_ERROR)
     177        rc = VBoxServiceControlExecProcHandleStdInErrorEvent(hPollSet, fPollEvt, phStdInW, pStdInBuf);
     178    return rc;
    134179}
    135180
     
    146191 * @param   pu32Crc             The current CRC-32 of the stream. (In/Out)
    147192 * @param   uHandleId           The handle ID.
    148  * @param   pszOpcode           The opcode for the data upload.
    149193 *
    150194 * @todo    Put the last 4 parameters into a struct!
    151195 */
    152 static int VBoxServiceControlExecProcHandleOutputEvent(PVBOXSERVICECTRLTHREAD pThread,
    153                                                        RTPOLLSET hPollSet, uint32_t fPollEvt, PRTPIPE phPipeR,
    154                                                        uint32_t *puCrc32 , uint32_t uHandleId)
    155 {
    156     Log(("VBoxServiceControlExecProcHandleOutputEvent: fPollEvt=%#x\n",  fPollEvt));
     196static int VBoxServiceControlExecProcHandleOutputEvent(RTPOLLSET hPollSet, uint32_t fPollEvt, PRTPIPE phPipeR,
     197                                                       uint32_t uHandleId, PVBOXSERVICECTRLEXECPIPEBUF pStdOutBuf)
     198{
     199    VBoxServiceVerbose(4, "ControlExec: HandleOutputEvent: fPollEvt=%#x\n", fPollEvt);
    157200
    158201    /*
     
    163206    uint8_t abBuf[_64K];
    164207
    165     AssertPtr(pThread);
    166     PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)pThread->pvData;
    167     AssertPtr(pData);
    168 
    169208    int rc2 = RTPipeRead(*phPipeR, abBuf, sizeof(abBuf), &cbRead);
    170209    if (RT_SUCCESS(rc2) && cbRead)
     
    183222        {
    184223#endif
    185             rc = VBoxServiceControlExecWritePipeBuffer(&pData->stdOut, abBuf, cbRead);
     224            rc = VBoxServiceControlExecWritePipeBuffer(pStdOutBuf, abBuf, cbRead);
    186225            if (RT_SUCCESS(rc))
    187226            {
     
    229268 */
    230269static int VBoxServiceControlExecProcHandleTransportEvent(RTPOLLSET hPollSet, uint32_t fPollEvt, uint32_t idPollHnd,
    231                                                           PRTPIPE phStdInW, PVBOXSERVICECTRLSTDINBUF pStdInBuf)
    232 {
    233 
    234     int rc = RTPollSetAddPipe(hPollSet, *phStdInW, RTPOLL_EVT_WRITE, 4 /*TXSEXECHNDID_STDIN_WRITABLE*/);
    235 
    236     return rc;
     270                                                          PRTPIPE phStdInW, PVBOXSERVICECTRLEXECPIPEBUF pStdInBuf)
     271{
     272    return 0; //RTPollSetAddPipe(hPollSet, *phStdInW, RTPOLL_EVT_WRITE, 4 /*TXSEXECHNDID_STDIN_WRITABLE*/);
    237273}
    238274
     
    244280    int                         rc;
    245281    int                         rc2;
    246     VBOXSERVICECTRLSTDINBUF     StdInBuf            = { 0, 0, NULL, 0, hStdInW == NIL_RTPIPE, RTCrc32Start() };
    247     uint32_t                    uStdOutCrc32        = RTCrc32Start();
    248     uint32_t                    uStdErrCrc32        = uStdOutCrc32;
    249282    uint64_t const              MsStart             = RTTimeMilliTS();
    250283    RTPROCSTATUS                ProcessStatus       = { 254, RTPROCEXITREASON_ABEND };
     
    253286    uint64_t                    MsProcessKilled     = UINT64_MAX;
    254287    RTMSINTERVAL const          cMsPollBase         = hStdInW != NIL_RTPIPE
    255                                                       ? 100   /* need to poll for input */
    256                                                       : 1000; /* need only poll for process exit and aborts */
     288                                                      ? 100   /* Need to poll for input. */
     289                                                      : 1000; /* Need only poll for process exit and aborts. */
    257290    RTMSINTERVAL                cMsPollCur          = 0;
    258291
     
    290323            continue;
    291324
    292         cMsPollCur = 0;                 /* no rest until we've checked everything. */
     325        cMsPollCur = 0; /* No rest until we've checked everything. */
    293326
    294327        if (RT_SUCCESS(rc2))
    295328        {
     329            VBoxServiceVerbose(4, "ControlExec: RTPollNoResume idPollHnd=%u\n", idPollHnd);
    296330            switch (idPollHnd)
    297331            {
    298                 case 0 /* TXSEXECHNDID_STDIN */:
    299                     VBoxServiceControlExecProcHandleStdInErrorEvent(hPollSet, fPollEvt, &hStdInW, &StdInBuf);
     332                case VBOXSERVICECTRLPIPEID_STDIN_ERROR:
     333                    rc = VBoxServiceControlExecProcHandleInputEvent(hPollSet, fPollEvt, &hStdInW,
     334                                                                    VBOXSERVICECTRLPIPEID_STDIN_ERROR, &pData->stdIn);
    300335                    break;
    301336
    302                 case 1 /* TXSEXECHNDID_STDOUT */:
    303                     rc = VBoxServiceControlExecProcHandleOutputEvent(pThread, hPollSet, fPollEvt, &hStdOutR, &uStdOutCrc32, 1 /* TXSEXECHNDID_STDOUT */);
     337                case VBOXSERVICECTRLPIPEID_STDIN_WRITABLE:
     338                    rc = VBoxServiceControlExecProcHandleStdInWritableEvent(hPollSet, fPollEvt, &hStdInW, &pData->stdIn);
    304339                    break;
    305340
    306                 case 2 /*TXSEXECHNDID_STDERR */:
    307                     rc = VBoxServiceControlExecProcHandleOutputEvent(pThread, hPollSet, fPollEvt, &hStdErrR, &uStdErrCrc32, 2 /*TXSEXECHNDID_STDERR */);
     341                case VBOXSERVICECTRLPIPEID_STDOUT:
     342                    rc = VBoxServiceControlExecProcHandleOutputEvent(hPollSet, fPollEvt, &hStdOutR,
     343                                                                     VBOXSERVICECTRLPIPEID_STDOUT, &pData->stdOut);
    308344                    break;
    309345
    310                 case 4 /* TXSEXECHNDID_STDIN_WRITABLE */:
    311                     VBoxServiceControlExecProcHandleStdInWritableEvent(hPollSet, fPollEvt, &hStdInW, &StdInBuf);
     346                case VBOXSERVICECTRLPIPEID_STDERR:
     347                    rc = VBoxServiceControlExecProcHandleOutputEvent(hPollSet, fPollEvt, &hStdErrR,
     348                                                                     VBOXSERVICECTRLPIPEID_STDERR, &pData->stdOut);
    312349                    break;
    313350
    314351                default:
    315                     rc = VBoxServiceControlExecProcHandleTransportEvent(hPollSet, fPollEvt, idPollHnd, &hStdInW, &StdInBuf);
     352                    //rc = VBoxServiceControlExecProcHandleTransportEvent(hPollSet, fPollEvt, idPollHnd, &hStdInW, &pData->stdIn);
    316353                    break;
    317354            }
    318355            if (RT_FAILURE(rc) || rc == VINF_EOF)
    319                 break; /* abort command, or client dead or something */
     356                break; /* Abort command, or client dead or something. */
    320357            continue;
    321358        }
    322 
    323         /*
    324          * Check for incoming data.
    325          */
    326359
    327360        /*
     
    501534    else
    502535        VBoxServiceError("ControlExec: Process loop failed with rc=%Rrc\n", rc);
    503     RTMemFree(StdInBuf.pch);
    504536    return rc;
    505537}
     
    510542 *
    511543 * @returns IPRT status code.  No client replies made.
    512  * @param   pszHowTo            How to set up this standard handle.
    513544 * @param   fd                  Which standard handle it is (0 == stdin, 1 ==
    514545 *                              stdout, 2 == stderr).
     
    560591    AssertPtr(pBuf);
    561592
     593    /** @todo Add allocation size as function parameter! */
    562594    pBuf->pbData = (uint8_t*)RTMemAlloc(_64K); /* Start with a 64k buffer. */
    563595    AssertReturn(pBuf->pbData, VERR_NO_MEMORY);
     596    pBuf->cbAllocated = _64K;
    564597    pBuf->cbSize = 0;
    565     pBuf->cbOffset = 0;
    566     pBuf->cbRead = 0;
     598    pBuf->cbProcessed = 0;
     599    pBuf->fAlive = true;
    567600
    568601    return RTCritSectInit(&pBuf->CritSect);
     
    576609            RTMemFree(pBuf->pbData);
    577610        pBuf->pbData = NULL;
     611        pBuf->cbAllocated = 0;
    578612        pBuf->cbSize = 0;
    579         pBuf->cbOffset = 0;
    580         pBuf->cbRead = 0;
    581     }
     613        pBuf->cbProcessed = 0;
     614    }
     615    pBuf->fAlive = false;
    582616    return RTCritSectDelete(&pBuf->CritSect);
    583617}
     
    592626    if (RT_SUCCESS(rc))
    593627    {
    594         Assert(pBuf->cbOffset >= pBuf->cbRead);
    595         if (*pcbToRead > pBuf->cbOffset - pBuf->cbRead)
    596             *pcbToRead = pBuf->cbOffset - pBuf->cbRead;
     628        Assert(pBuf->cbSize >= pBuf->cbProcessed);
     629        if (*pcbToRead > pBuf->cbSize - pBuf->cbProcessed)
     630            *pcbToRead = pBuf->cbSize - pBuf->cbProcessed;
    597631
    598632        if (*pcbToRead > cbBuffer)
     
    601635        if (*pcbToRead > 0)
    602636        {
    603             memcpy(pbBuffer, pBuf->pbData + pBuf->cbRead, *pcbToRead);
    604             pBuf->cbRead += *pcbToRead;
     637            memcpy(pbBuffer, pBuf->pbData + pBuf->cbProcessed, *pcbToRead);
     638            pBuf->cbProcessed += *pcbToRead;
    605639        }
    606640        else
     
    622656    if (RT_SUCCESS(rc))
    623657    {
    624         /** @todo Use RTMemCache or RTMemObj here? */
    625         uint8_t *pNewBuf;
    626         while (pBuf->cbSize - pBuf->cbOffset < cbData)
    627         {
    628             pNewBuf = (uint8_t*)RTMemRealloc(pBuf->pbData, pBuf->cbSize + _4K);
    629             if (pNewBuf == NULL)
    630                 break;
    631             pBuf->cbSize += _4K;
    632             pBuf->pbData = pNewBuf;
    633         }
    634 
    635         rc = VINF_SUCCESS;
    636         if (pBuf->pbData)
    637         {
    638             memcpy(pBuf->pbData + pBuf->cbOffset, pbData, cbData);
    639             pBuf->cbOffset += cbData;
    640             /** @todo Add offset clamping! */
    641         }
    642         else
    643             rc = VERR_NO_MEMORY;
     658        if (pBuf->fAlive)
     659        {
     660            /** @todo Buffer size limit! 4MB */
     661
     662            /* Resize buffer if not enough space for storing the read in data left. */
     663            uint8_t *pNewBuf;
     664            while (pBuf->cbAllocated - pBuf->cbSize < cbData)
     665            {
     666                pNewBuf = (uint8_t*)RTMemRealloc(pBuf->pbData, pBuf->cbAllocated + _4K);
     667                if (pNewBuf == NULL)
     668                    break;
     669                pBuf->cbAllocated += _4K;
     670                pBuf->pbData = pNewBuf;
     671            }
     672
     673            rc = VINF_SUCCESS;
     674            if (pBuf->pbData)
     675            {
     676                memcpy(pBuf->pbData + pBuf->cbSize, pbData, cbData);
     677                pBuf->cbSize += cbData;
     678                /** @todo Add offset clamping! */
     679            }
     680            else
     681                rc = VERR_NO_MEMORY;
     682        }
    644683        int rc2 = RTCritSectLeave(&pBuf->CritSect);
    645684        if (RT_SUCCESS(rc))
     
    731770        if (RT_SUCCESS(rc))
    732771            rc = VBoxServiceControlExecInitPipeBuffer(&pData->stdErr);
     772            if (RT_SUCCESS(rc))
     773                rc = VBoxServiceControlExecInitPipeBuffer(&pData->stdIn);
    733774    }
    734775
     
    763804        VBoxServiceControlExecDestroyPipeBuffer(&pData->stdOut);
    764805        VBoxServiceControlExecDestroyPipeBuffer(&pData->stdErr);
     806        VBoxServiceControlExecDestroyPipeBuffer(&pData->stdIn);
    765807
    766808        RTMemFree(pData);
     
    852894            RTHANDLE    hStdIn;
    853895            PRTHANDLE   phStdIn;
    854             RTPIPE      hStdInW;
    855             rc = VBoxServiceControlExecSetupPipe(0 /* stdin */, &hStdIn, &phStdIn, &hStdInW);
     896            rc = VBoxServiceControlExecSetupPipe(0 /*STDIN_FILENO*/, &hStdIn, &phStdIn, &pData->pipeStdInW);
    856897            if (RT_SUCCESS(rc))
    857898            {
     
    859900                PRTHANDLE   phStdOut;
    860901                RTPIPE      hStdOutR;
    861                 rc = VBoxServiceControlExecSetupPipe(1 /* stdout */, &hStdOut, &phStdOut, &hStdOutR);
     902                rc = VBoxServiceControlExecSetupPipe(1 /*STDOUT_FILENO*/, &hStdOut, &phStdOut, &hStdOutR);
    862903                if (RT_SUCCESS(rc))
    863904                {
     
    865906                    PRTHANDLE   phStdErr;
    866907                    RTPIPE      hStdErrR;
    867                     rc = VBoxServiceControlExecSetupPipe(2 /* stderr */, &hStdErr, &phStdErr, &hStdErrR);
     908                    rc = VBoxServiceControlExecSetupPipe(2 /*STDERR_FILENO*/, &hStdErr, &phStdErr, &hStdErrR);
    868909                    if (RT_SUCCESS(rc))
    869910                    {
     
    876917                        if (RT_SUCCESS(rc))
    877918                        {
    878                             rc = RTPollSetAddPipe(hPollSet, hStdInW, RTPOLL_EVT_ERROR, 0 /* TXSEXECHNDID_STDIN */);
     919                            rc = RTPollSetAddPipe(hPollSet, pData->pipeStdInW, RTPOLL_EVT_ERROR, VBOXSERVICECTRLPIPEID_STDIN_ERROR);
    879920                            if (RT_SUCCESS(rc))
    880                                 rc = RTPollSetAddPipe(hPollSet, hStdOutR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, 1 /* TXSEXECHNDID_STDOUT */);
     921                                rc = RTPollSetAddPipe(hPollSet, hStdOutR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, VBOXSERVICECTRLPIPEID_STDOUT);
    881922                            if (RT_SUCCESS(rc))
    882                                 rc = RTPollSetAddPipe(hPollSet, hStdErrR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, 2 /* TXSEXECHNDID_TESTPIPE */);
     923                                rc = RTPollSetAddPipe(hPollSet, hStdErrR, RTPOLL_EVT_READ | RTPOLL_EVT_ERROR, VBOXSERVICECTRLPIPEID_STDERR);
     924                            if (RT_SUCCESS(rc))
     925                                rc = RTPollSetAddPipe(hPollSet, pData->pipeStdInW, RTPOLL_EVT_WRITE, VBOXSERVICECTRLPIPEID_STDIN_WRITABLE);
    883926                            if (RT_SUCCESS(rc))
    884927                            {
     
    915958                                    rc = VBoxServiceControlExecProcLoop(pThread,
    916959                                                                        hProcess, pData->uTimeLimitMS, hPollSet,
    917                                                                         hStdInW, hStdOutR, hStdErrR);
     960                                                                        pData->pipeStdInW, hStdOutR, hStdErrR);
    918961
    919962                                    /*
     
    924967                                     */
    925968                                    if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, 0 /* stdin */, NULL)))
    926                                         hStdInW = NIL_RTPIPE;
     969                                        pData->pipeStdInW = NIL_RTPIPE;
    927970                                    if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, 1 /* stdout */, NULL)))
    928971                                        hStdOutR = NIL_RTPIPE;
     
    943986                                }
    944987                            }
     988                            RTPollSetDestroy(hPollSet);
    945989                        }
    946990                        RTPipeClose(hStdErrR);
     
    950994                    RTHandleClose(phStdOut);
    951995                }
    952                 RTPipeClose(hStdInW);
     996                RTPipeClose(pData->pipeStdInW);
    953997                RTHandleClose(phStdIn);
    954998            }
     
    9681012        RTThreadUserSignal(RTThreadSelf());
    9691013    return rc;
     1014}
     1015
     1016PVBOXSERVICECTRLTHREAD VBoxServiceControlExecFindProcess(uint32_t uPID)
     1017{
     1018    PVBOXSERVICECTRLTHREAD pNode;
     1019    bool fFound = false;
     1020    RTListForEach(&g_GuestControlExecThreads, pNode, VBOXSERVICECTRLTHREAD, Node)
     1021    {
     1022        if (   pNode->fStarted
     1023            && pNode->enmType == VBoxServiceCtrlThreadDataExec)
     1024        {
     1025            PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)pNode->pvData;
     1026            if (pData && pData->uPID == uPID)
     1027            {
     1028                return pNode;
     1029            }
     1030        }
     1031    }
     1032    return NULL;
    9701033}
    9711034
     
    10331096}
    10341097
     1098
     1099/**
     1100 *
     1101 *
     1102 * @return  int
     1103 *
     1104 * @param   u32ClientId
     1105 * @param   uNumParms
     1106 */
     1107int VBoxServiceControlExecHandleCmdStartProcess(uint32_t u32ClientId, uint32_t uNumParms)
     1108{
     1109    uint32_t uContextID;
     1110    char szCmd[_1K];
     1111    uint32_t uFlags;
     1112    char szArgs[_1K];
     1113    uint32_t uNumArgs;
     1114    char szEnv[_64K];
     1115    uint32_t cbEnv = sizeof(szEnv);
     1116    uint32_t uNumEnvVars;
     1117    char szUser[128];
     1118    char szPassword[128];
     1119    uint32_t uTimeLimitMS;
     1120
     1121#if 0 /* for valgrind */
     1122    RT_ZERO(szCmd);
     1123    RT_ZERO(szArgs);
     1124    RT_ZERO(szEnv);
     1125    RT_ZERO(szUser);
     1126    RT_ZERO(szPassword);
     1127#endif
     1128
     1129    if (uNumParms != 11)
     1130        return VERR_INVALID_PARAMETER;
     1131
     1132    int rc = VbglR3GuestCtrlExecGetHostCmd(u32ClientId,
     1133                                           uNumParms,
     1134                                           &uContextID,
     1135                                           /* Command */
     1136                                           szCmd,      sizeof(szCmd),
     1137                                           /* Flags */
     1138                                           &uFlags,
     1139                                           /* Arguments */
     1140                                           szArgs,     sizeof(szArgs), &uNumArgs,
     1141                                           /* Environment */
     1142                                           szEnv, &cbEnv, &uNumEnvVars,
     1143                                           /* Credentials */
     1144                                           szUser,     sizeof(szUser),
     1145                                           szPassword, sizeof(szPassword),
     1146                                           /* Timelimit */
     1147                                           &uTimeLimitMS);
     1148    if (RT_FAILURE(rc))
     1149    {
     1150        VBoxServiceError("ControlExec: Failed to retrieve exec start command! Error: %Rrc\n", rc);
     1151    }
     1152    else
     1153    {
     1154        rc = VBoxServiceControlExecProcess(uContextID, szCmd, uFlags, szArgs, uNumArgs,
     1155                                           szEnv, cbEnv, uNumEnvVars,
     1156                                           szUser, szPassword, uTimeLimitMS);
     1157    }
     1158
     1159    VBoxServiceVerbose(3, "ControlExec: VBoxServiceControlExecHandleCmdStartProcess returned with %Rrc\n", rc);
     1160    return rc;
     1161}
     1162
     1163
     1164/**
     1165 * Handles input for the started process by copying the received data into its
     1166 * stdin pipe.
     1167 *
     1168 * @return  int
     1169 *
     1170 * @param   u32ClientId
     1171 * @param   uNumParms
     1172 */
     1173int VBoxServiceControlExecHandleCmdSetInput(uint32_t u32ClientId, uint32_t uNumParms)
     1174{
     1175    uint32_t uContextID;
     1176    uint32_t uPID;
     1177    uint32_t uFlags;
     1178    uint8_t  aBuffer[_64K];
     1179    uint32_t cbSize;
     1180
     1181    if (uNumParms != 5)
     1182        return VERR_INVALID_PARAMETER;
     1183
     1184    int rc = VbglR3GuestCtrlExecGetHostCmdInput(u32ClientId, uNumParms,
     1185                                                &uContextID, &uPID, &uFlags,
     1186                                                aBuffer, sizeof(aBuffer), &cbSize);
     1187    if (RT_FAILURE(rc))
     1188    {
     1189        VBoxServiceError("ControlExec: Failed to retrieve exec input command! Error: %Rrc\n", rc);
     1190    }
     1191    else
     1192    {
     1193        PVBOXSERVICECTRLTHREAD pNode = VBoxServiceControlExecFindProcess(uPID);
     1194        if (pNode)
     1195        {
     1196            PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)pNode->pvData;
     1197            AssertPtr(pData);
     1198            rc = VBoxServiceControlExecWritePipeBuffer(&pData->stdIn, aBuffer, cbSize);
     1199            if (RT_SUCCESS(rc))
     1200            {
     1201                size_t cbWritten;
     1202                rc = VBoxServiceControlExecProcWriteStdIn(&pData->stdIn, pData->pipeStdInW, &cbWritten);
     1203                if (RT_SUCCESS(rc))
     1204                    rc = VbglR3GuestCtrlExecReportStatusIn(u32ClientId, uContextID, uPID, 0 /* Flags */,
     1205                                                           cbWritten);
     1206            }
     1207        }
     1208        else
     1209            rc = VERR_NOT_FOUND; /* PID not found! */
     1210    }
     1211    VBoxServiceVerbose(3, "ControlExec: VBoxServiceControlExecHandleCmdSetInput returned with %Rrc\n", rc);
     1212    return rc;
     1213}
     1214
     1215
     1216/**
     1217 *
     1218 *
     1219 * @return  int
     1220 *
     1221 * @param   u32ClientId
     1222 * @param   uNumParms
     1223 */
     1224int VBoxServiceControlExecHandleCmdGetOutput(uint32_t u32ClientId, uint32_t uNumParms)
     1225{
     1226    uint32_t uContextID;
     1227    uint32_t uPID;
     1228    uint32_t uHandleID;
     1229    uint32_t uFlags;
     1230
     1231    int rc = VbglR3GuestCtrlExecGetHostCmdOutput(u32ClientId, uNumParms,
     1232                                                 &uContextID, &uPID, &uHandleID, &uFlags);
     1233    if (RT_FAILURE(rc))
     1234    {
     1235        VBoxServiceError("ControlExec: Failed to retrieve exec output command! Error: %Rrc\n", rc);
     1236    }
     1237    else
     1238    {
     1239        PVBOXSERVICECTRLTHREAD pNode = VBoxServiceControlExecFindProcess(uPID);
     1240        if (pNode)
     1241        {
     1242            PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)pNode->pvData;
     1243            AssertPtr(pData);
     1244
     1245            const uint32_t cbSize = _4K;
     1246            uint32_t cbRead = cbSize;
     1247            uint8_t *pBuf = (uint8_t*)RTMemAlloc(cbSize);
     1248            if (pBuf)
     1249            {
     1250                rc = VBoxServiceControlExecReadPipeBufferContent(&pData->stdOut, pBuf, cbSize, &cbRead);
     1251                if (RT_SUCCESS(rc))
     1252                {
     1253                    /* cbRead now contains actual size. */
     1254                    rc = VbglR3GuestCtrlExecSendOut(u32ClientId, uContextID, uPID, 0 /* handle ID */, 0 /* flags */,
     1255                                                    pBuf, cbRead);
     1256                }
     1257                RTMemFree(pBuf);
     1258            }
     1259            else
     1260                rc = VERR_NO_MEMORY;
     1261        }
     1262        else
     1263            rc = VERR_NOT_FOUND; /* PID not found! */
     1264    }
     1265    VBoxServiceVerbose(3, "ControlExec: VBoxServiceControlExecHandleCmdGetOutput returned with %Rrc\n", rc);
     1266    return rc;
     1267}
     1268
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette