VirtualBox

Changeset 26802 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Feb 25, 2010 4:25:41 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
58070
Message:

Implemented RTProcCreateEx for posix. The new features hasn't been tested yet (no testcase).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/posix/process-posix.cpp

    r26415 r26802  
    5454
    5555#include <iprt/process.h>
     56#include "internal/iprt.h"
     57
     58#include <iprt/assert.h>
     59#include <iprt/env.h>
     60#include <iprt/err.h>
     61#include <iprt/file.h>
     62#include <iprt/pipe.h>
    5663#include <iprt/string.h>
    57 #include <iprt/assert.h>
    58 #include <iprt/err.h>
    59 #include <iprt/env.h>
    6064#include "internal/process.h"
    6165
     
    6468RTR3DECL(int)   RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess)
    6569{
     70#if 0
    6671    int rc;
    6772
     
    136141            if (!rc)
    137142            {
    138                 /** @todo check if it requires any mandatory attributes or something, don't
    139                  *        remember atm. */
    140143                rc = posix_spawn(&pid, pszExec, NULL, &Attr, (char * const *)papszArgs,
    141144                                 (char * const *)papszEnv);
     
    181184    AssertMsgFailed(("spawn/exec failed rc=%d\n", rc)); /* this migth be annoying... */
    182185    return RTErrConvertFromErrno(rc);
     186#else
     187    return RTProcCreateEx(pszExec, papszArgs, Env, fFlags,
     188                          NULL, NULL, NULL,  /* standard handles */
     189                          NULL /*pszAsUser*/,
     190                          pProcess);
     191#endif
     192}
     193
     194
     195RTR3DECL(int)   RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
     196                               PCRTHANDLE phStdIn, PCRTHANDLE phStdOut, PCRTHANDLE phStdErr, const char *pszAsUser,
     197                               PRTPROCESS phProcess)
     198{
     199    int rc;
     200
     201    /*
     202     * Input validation
     203     */
     204    AssertPtrReturn(pszExec, VERR_INVALID_POINTER);
     205    AssertReturn(*pszExec, VERR_INVALID_PARAMETER);
     206    AssertReturn(!(fFlags & ~RTPROC_FLAGS_DAEMONIZE), VERR_INVALID_PARAMETER);
     207    AssertReturn(hEnv != NIL_RTENV, VERR_INVALID_PARAMETER);
     208    const char * const *papszEnv = RTEnvGetExecEnvP(hEnv);
     209    AssertPtrReturn(papszEnv, VERR_INVALID_HANDLE);
     210    AssertPtrReturn(papszArgs, VERR_INVALID_PARAMETER);
     211    /** @todo search the PATH (add flag for this). */
     212    AssertPtrNullReturn(pszAsUser, VERR_INVALID_POINTER);
     213
     214    /*
     215     * Get the file descriptors for the handles we've been passed.
     216     */
     217    PCRTHANDLE  paHandles[3] = { phStdIn, phStdOut, phStdErr };
     218    int         aStdFds[3]   = {      -1,       -1,       -1 };
     219    for (int i = 0; i < 3; i++)
     220    {
     221        if (paHandles[i])
     222        {
     223            AssertPtrReturn(paHandles[i], VERR_INVALID_POINTER);
     224            switch (paHandles[i]->enmType)
     225            {
     226                case RTHANDLETYPE_FILE:
     227                    aStdFds[i] = paHandles[i]->u.hFile != NIL_RTFILE
     228                               ? (int)RTFileToNative(paHandles[i]->u.hFile)
     229                               : -2 /* close it */;
     230                    break;
     231
     232                case RTHANDLETYPE_PIPE:
     233                    aStdFds[i] = paHandles[i]->u.hPipe != NIL_RTPIPE
     234                               ? (int)RTPipeToNative(paHandles[i]->u.hPipe)
     235                               : -2 /* close it */;
     236                    break;
     237
     238                case RTHANDLETYPE_SOCKET:
     239                    aStdFds[i] = paHandles[i]->u.hSocket != NIL_RTSOCKET
     240                               ? (int)paHandles[i]->u.hSocket //RTPipeToNative(paHandles[i]->u.hPipe)
     241                               : -2 /* close it */;
     242                    break;
     243
     244                default:
     245                    AssertMsgFailedReturn(("%d: %d\n", i, paHandles[i]->enmType), VERR_INVALID_PARAMETER);
     246            }
     247            /** @todo check the close-on-execness of these handles?  */
     248        }
     249    }
     250
     251    for (int i = 0; i < 3; i++)
     252        if (aStdFds[i] == i)
     253            aStdFds[i] = -1;
     254
     255    for (int i = 0; i < 3; i++)
     256        AssertMsgReturn(aStdFds[i] < 0 || aStdFds[i] > i,
     257                        ("%i := %i not possible because we're lazy\n", i, aStdFds[i]),
     258                        VERR_NOT_SUPPORTED);
     259
     260    /*
     261     * Resolve the user id if specified.
     262     */
     263    uid_t uid = ~(uid_t)0;
     264    gid_t gid = ~(gid_t)0;
     265    if (pszAsUser)
     266    {
     267        AssertMsgFailed(("Implement get uid by name lookup\n"));
     268        return VERR_NOT_IMPLEMENTED;
     269    }
     270
     271    /*
     272     * Check for execute access to the file.
     273     */
     274    if (access(pszExec, X_OK))
     275    {
     276        rc = RTErrConvertFromErrno(errno);
     277        AssertMsgFailed(("'%s' %Rrc!\n", pszExec, rc));
     278        return rc;
     279    }
     280
     281    /*
     282     * Spawn the child.
     283     *
     284     * HACK ALERT! Put the process into a new process group with pgid = pid
     285     * to make sure it differs from that of the parent process to ensure that
     286     * the IPRT waipit call doesn't race anyone (read XPCOM) doing group wide
     287     * waits.
     288     */
     289    pid_t pid = -1;
     290#ifdef HAVE_POSIX_SPAWN
     291    if (   !(fFlags & RTPROC_FLAGS_DAEMONIZE)
     292        && uid == ~(uid_t)0
     293        && gid == ~(gid_t)0
     294        )
     295    {
     296        /* Spawn attributes. */
     297        posix_spawnattr_t Attr;
     298        rc = posix_spawnattr_init(&Attr);
     299        if (!rc)
     300        {
     301# ifndef RT_OS_OS2 /* We don't need this on OS/2 and I don't recall if it's actually implemented. */
     302            rc = posix_spawnattr_setflags(&Attr, POSIX_SPAWN_SETPGROUP);
     303            Assert(rc == 0);
     304            if (!rc)
     305            {
     306                rc = posix_spawnattr_setpgroup(&Attr, 0 /* pg == child pid */);
     307                Assert(rc == 0);
     308            }
     309# endif
     310
     311            /* File changes. */
     312            posix_spawn_file_actions_t  FileActions;
     313            posix_spawn_file_actions_t *pFileActions = NULL;
     314            if (aStdFds[0] != -1 || aStdFds[1] != -1 || aStdFds[2] != -1)
     315            {
     316                rc = posix_spawn_file_actions_init(&FileActions);
     317                if (!rc)
     318                {
     319                    pFileActions = &FileActions;
     320                    for (int i = 0; i < 3; i++)
     321                    {
     322                        if (aStdFds[i] == -2)
     323                            rc = posix_spawn_file_actions_addclose(&FileActions, i);
     324                        else if (aStdFds[i] >= 0 && aStdFds[i] != i)
     325                        {
     326                            rc = posix_spawn_file_actions_adddup2(&FileActions, aStdFds[i], i);
     327                            if (!rc)
     328                                rc = posix_spawn_file_actions_addclose(&FileActions, aStdFds[i]);
     329                        }
     330                        if (rc)
     331                            break;
     332                    }
     333                }
     334            }
     335
     336            if (!rc)
     337                rc = posix_spawn(&pid, pszExec, NULL, &Attr, (char * const *)papszArgs,
     338                                 (char * const *)papszEnv);
     339
     340            /* cleanup */
     341            int rc2 = posix_spawnattr_destroy(&Attr); Assert(rc2 == 0); NOREF(rc2);
     342            if (pFileActions)
     343            {
     344                rc2 = posix_spawn_file_actions_destroy(pFileActions);
     345                Assert(rc2 == 0);
     346            }
     347
     348            /* return on success.*/
     349            if (!rc)
     350            {
     351                if (phProcess)
     352                    *phProcess = pid;
     353                return VINF_SUCCESS;
     354            }
     355        }
     356    }
     357    else
     358#endif
     359    {
     360        pid = fork();
     361        if (!pid)
     362        {
     363            setpgid(0, 0); /* see comment above */
     364
     365            /*
     366             * Change group and user if requested.
     367             */
     368#if 1 /** @todo This needs more work, see suplib/hardening. */
     369            if (gid != ~(gid_t)0)
     370            {
     371                if (setgid(gid))
     372                    exit(127);
     373            }
     374
     375            if (uid != ~(uid_t)0)
     376            {
     377                if (setuid(uid))
     378                    exit(127);
     379            }
     380#endif
     381
     382            /*
     383             * Apply changes to the standard file descriptor and stuff.
     384             */
     385            for (int i = 0; i < 3; i++)
     386            {
     387                if (aStdFds[i] == -2)
     388                    close(aStdFds[i]);
     389                else if (aStdFds[i] >= 0)
     390                {
     391                    if (dup2(aStdFds[i], i) != i)
     392                        exit(127);
     393                    close(aStdFds[i]);
     394                }
     395            }
     396
     397            /*
     398             * Daemonize the process if requested.
     399             */
     400            if (fFlags & RTPROC_FLAGS_DAEMONIZE)
     401            {
     402                rc = RTProcDaemonize(true /* fNoChDir */, false /* fNoClose */, NULL /* pszPidFile */);
     403                AssertReleaseMsgFailed(("RTProcDaemonize returns %Rrc errno=%d\n", rc, errno));
     404                exit(127);
     405            }
     406
     407            /*
     408             * Finally, execute the requested program.
     409             */
     410            rc = execve(pszExec, (char * const *)papszArgs, (char * const *)papszEnv);
     411            AssertReleaseMsgFailed(("execve returns %d errno=%d\n", rc, errno));
     412            exit(127);
     413        }
     414        if (pid > 0)
     415        {
     416            if (phProcess)
     417                *phProcess = pid;
     418            return VINF_SUCCESS;
     419        }
     420        rc = errno;
     421    }
     422
     423
     424    return VERR_NOT_IMPLEMENTED;
    183425}
    184426
Note: See TracChangeset for help on using the changeset viewer.

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