VirtualBox

Ignore:
Timestamp:
Jan 22, 2008 2:19:50 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
27420
Message:

Put VbglR3Daemonize into a separate file and merged the solaris and linux code. (untested)

Location:
trunk/src/VBox/Additions/common/VBoxGuestLib
Files:
2 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuestLib/Makefile.kmk

    r6044 r6445  
    9696VBoxGuestR3Lib_TEMPLATE    = VBOXGUESTR3LIB
    9797VBoxGuestR3Lib_DEFS        = VBOX_HGCM
    98 VBoxGuestR3Lib_SOURCES     = VBoxGuestR3Lib.cpp VBoxGuestR3LibClipboard.cpp
     98VBoxGuestR3Lib_SOURCES     = \
     99        VBoxGuestR3Lib.cpp \
     100        VBoxGuestR3LibDaemonize.cpp \
     101        VBoxGuestR3LibClipboard.cpp
    99102
    100103
     
    150153VBoxGuestR3LibLinux_SOURCES  = \
    151154        VBoxGuestR3Lib.cpp \
     155        VBoxGuestR3LibDaemonize.cpp \
    152156        VBoxGuestR3LibClipboard.cpp \
    153157        VBoxGuestR3LibSeamless.cpp
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3Lib.cpp

    r6434 r6445  
    2424# define INCL_ERRORS
    2525# include <os2.h>
    26 
    27 # include <iprt/alloca.h>
    28 # include <iprt/string.h>
    29 #elif defined(RT_OS_LINUX)
    30 # include <sys/stat.h>
    31 # include <fcntl.h>
    32 # include <stdlib.h>
    33 # include <unistd.h>
    34 # include <sys/time.h>
    35 # include <sys/resource.h>
    3626#elif defined(RT_OS_SOLARIS)
    3727# include <sys/types.h>
    3828# include <sys/stat.h>
    3929# include <errno.h>
    40 # include <stdio.h>
    41 # include <stdlib.h>
    4230# include <unistd.h>
    43 # include <signal.h>
    44 # include <fcntl.h>
    4531#endif
    4632
     
    5137#include <iprt/assert.h>
    5238#include <iprt/mem.h>
     39#include <iprt/alloca.h>
    5340#include <VBox/VBoxGuest.h>
    5441
     
    187174
    188175#else
    189     /* Default implementation (linux, solaris). */
     176    /* Default implementation - PORTME: Do not use this without testings that error passing works! */
    190177    int rc2 = VERR_INTERNAL_ERROR;
    191178    int rc = RTFileIoCtl(g_File, (int)iFunction, pvData, cbData, &rc2);
     
    335322}
    336323
    337 
    338 /**
    339  * Daemonize the process for running in the background.
    340  *
    341  * @returns 0 on success
    342  *
    343  * @param   nochdir     Pass 0 to change working directory to root.
    344  * @param   noclose     Pass 0 to redirect standard file streams to /dev/null.
    345  */
    346 VBGLR3DECL(int) VbglR3Daemonize(int nochdir, int noclose)
    347 {
    348 #if defined(RT_OS_LINUX)
    349     /** rlimit structure for finding out how many open files we may have. */
    350     struct rlimit rlim;
    351 
    352     /* To make sure that we are not currently a session leader, we must first fork and let
    353        the parent process exit, as a newly created child is never session leader.  This will
    354        allow us to call setsid() later. */
    355     if (fork() != 0)
    356     {
    357         exit(0);
    358     }
    359     /* Find the maximum number of files we can have open and close them all. */
    360     if (0 != getrlimit(RLIMIT_NOFILE, &rlim))
    361     {
    362         /* For some reason the call failed.  In that case we will just close the three
    363            standard files and hope. */
    364         rlim.rlim_cur = 3;
    365     }
    366     for (unsigned int i = 0; i < rlim.rlim_cur; ++i)
    367     {
    368         close(i);
    369     }
    370     /* Change to the root directory to avoid keeping the one we were started in open. */
    371     chdir("/");
    372     /* Set our umask to zero. */
    373     umask(0);
    374     /* And open /dev/null on stdin/out/err. */
    375     open("/dev/null", O_RDONLY);
    376     open("/dev/null", O_WRONLY);
    377     dup(1);
    378     /* Detach from the controlling terminal by creating our own session, to avoid receiving
    379        signals from the old session. */
    380     setsid();
    381     /* And fork again, letting the parent exit, to make us a child of init and avoid zombies. */
    382     if (fork() != 0)
    383     {
    384         exit(0);
    385     }
    386     NOREF(nochdir);
    387     NOREF(noclose);
    388 
    389     return 0;
    390 
    391 #elif defined(RT_OS_OS2)
    392     PPIB pPib;
    393     PTIB pTib;
    394     DosGetInfoBlocks(&pTib, &pPib);
    395 
    396     /* Get the full path to the executable. */
    397     char szExe[CCHMAXPATH];
    398     APIRET rc = DosQueryModuleName(pPib->pib_hmte, sizeof(szExe), szExe);
    399     if (rc)
    400     {
    401         errno = EDOOFUS;
    402         return -1;
    403     }
    404 
    405     /* calc the length of the command line. */
    406     char *pch = pPib->pib_pchcmd;
    407     size_t cch0 = strlen(pch);
    408     pch += cch0 + 1;
    409     size_t cch1 = strlen(pch);
    410     pch += cch1 + 1;
    411     char *pchArgs;
    412     if (cch1 && *pch)
    413     {
    414         do  pch = strchr(pch, '\0') + 1;
    415         while (*pch);
    416 
    417         size_t cchTotal = pch - pPib->pib_pchcmd;
    418         pchArgs = (char *)alloca(cchTotal + sizeof("--daemonized\0\0"));
    419         memcpy(pchArgs, pPib->pib_pchcmd, cchTotal - 1);
    420         memcpy(pchArgs + cchTotal - 1, "--daemonized\0\0", sizeof("--daemonized\0\0"));
    421     }
    422     else
    423     {
    424         size_t cchTotal = pch - pPib->pib_pchcmd + 1;
    425         pchArgs = (char *)alloca(cchTotal + sizeof(" --daemonized "));
    426         memcpy(pchArgs, pPib->pib_pchcmd, cch0 + 1);
    427         pch = pchArgs + cch0 + 1;
    428         memcpy(pch, " --daemonized ", sizeof(" --daemonized ") - 1);
    429         pch += sizeof(" --daemonized ") - 1;
    430         if (cch1)
    431             memcpy(pch, pPib->pib_pchcmd + cch0 + 1, cch1 + 2);
    432         else
    433             pch[0] = pch[1] = '\0';
    434     }
    435 
    436     /* spawn a detach process  */
    437     char szObj[128];
    438     RESULTCODES ResCodes = { 0, 0 };
    439     szObj[0] = '\0';
    440     rc = DosExecPgm(szObj, sizeof(szObj), EXEC_BACKGROUND, (PCSZ)pchArgs, NULL, &ResCodes, (PCSZ)szExe);
    441     if (rc)
    442     {
    443         /** @todo Change this to some standard log/print error?? */
    444         /* VBoxServiceError("DosExecPgm failed with rc=%d and szObj='%s'\n", rc, szObj); */
    445         errno = EDOOFUS;
    446         return -1;
    447     }
    448     DosExit(EXIT_PROCESS, 0);
    449     return -1;
    450 
    451 #elif defined(RT_OS_SOLARIS)
    452     if (getppid() == 1) /* We already belong to init process */
    453         return -1;
    454 
    455     pid_t pid = fork();
    456     if (pid < 0)         /* The fork() failed. Bad. */
    457         return -1;
    458 
    459     if (pid > 0)         /* Quit parent process */
    460         exit(0);
    461 
    462     /*
    463      * The orphaned child becomes a daemon after attaching to init. We need to get
    464      * rid of signals, file descriptors & other stuff we inherited from the parent.
    465      */
    466     pid_t newpgid = setsid();
    467     if (newpgid < 0)     /* Failed to create new sesion */
    468         return -1;
    469 
    470     /* BSD daemon style. */
    471     if (!noclose)
    472     {
    473         /* Open stdin(0), stdout(1) and stderr(2) to /dev/null */
    474         int fd = open("/dev/null", O_RDWR);
    475         dup2(fd, STDIN_FILENO);
    476         dup2(fd, STDOUT_FILENO);
    477         dup2(fd, STDERR_FILENO);
    478         if (fd > 2)
    479             close(fd);
    480     }
    481 
    482     /* Switch our current directory to root */
    483     if (!nochdir)
    484         chdir("/");     /* @todo Check if switching to '/' is the convention for Solaris daemons. */
    485 
    486     /* Set file permission to something secure, as we need to run as root on Solaris */
    487     umask(027);
    488     return 0;
    489 #endif
    490 }
    491 
  • trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDaemonize.cpp

    r6425 r6445  
    11/** $Id$ */
    22/** @file
    3  * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions.
     3 * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, daemonize a process.
    44 */
    55
     
    2020*   Header Files                                                               *
    2121*******************************************************************************/
    22 #ifdef RT_OS_OS2
     22#if defined(RT_OS_DARWIN)
     23# error "PORTME"
     24
     25#elif defined(RT_OS_OS2)
    2326# define INCL_BASE
    2427# define INCL_ERRORS
     
    2730# include <iprt/alloca.h>
    2831# include <iprt/string.h>
    29 #elif defined(RT_OS_LINUX)
     32
     33#elif defined(RT_OS_WINDOWS)
     34# error "PORTME"
     35
     36#else /* the unices */
     37# include <sys/types.h>
    3038# include <sys/stat.h>
     39# include <stdio.h>
    3140# include <fcntl.h>
    3241# include <stdlib.h>
    3342# include <unistd.h>
    34 # include <sys/time.h>
    35 # include <sys/resource.h>
    36 #elif defined(RT_OS_SOLARIS)
    37 # include <sys/types.h>
    38 # include <sys/stat.h>
    39 # include <stdio.h>
    40 # include <stdlib.h>
    41 # include <unistd.h>
    4243# include <signal.h>
    43 # include <fcntl.h>
     44# include <errno.h>
    4445#endif
    4546
    46 #include <iprt/time.h>
    47 #include <iprt/asm.h>
    4847#include <iprt/string.h>
    49 #include <iprt/file.h>
    50 #include <iprt/assert.h>
    51 #include <iprt/mem.h>
    5248#include <VBox/VBoxGuest.h>
    53 
    54 
    55 /*******************************************************************************
    56 *   Global Variables                                                           *
    57 *******************************************************************************/
    58 /** The VBoxGuest device handle. */
    59 static RTFILE g_File = NIL_RTFILE;
    60 
    61 
    62 VBGLR3DECL(int) VbglR3Init(void)
    63 {
    64     if (g_File != NIL_RTFILE)
    65         return VINF_SUCCESS;
    66 
    67 #if defined(RT_OS_OS2)
    68     /*
    69      * We might wish to compile this with Watcom, so stick to
    70      * the OS/2 APIs all the way. And in any case we have to use
    71      * DosDevIOCtl for the requests, why not use Dos* for everything.
    72      */
    73     HFILE hf = NULLHANDLE;
    74     ULONG ulAction = 0;
    75     APIRET rc = DosOpen((PCSZ)VBOXGUEST_DEVICE_NAME, &hf, &ulAction, 0, FILE_NORMAL,
    76                         OPEN_ACTION_OPEN_IF_EXISTS,
    77                         OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NOINHERIT | OPEN_SHARE_DENYNONE | OPEN_ACCESS_READWRITE,
    78                         NULL);
    79     if (rc)
    80         return RTErrConvertFromOS2(rc);
    81 
    82     if (hf < 16)
    83     {
    84         HFILE ahfs[16];
    85         unsigned i;
    86         for (i = 0; i < RT_ELEMENTS(ahfs); i++)
    87         {
    88             ahfs[i] = 0xffffffff;
    89             rc = DosDupHandle(hf, &ahfs[i]);
    90             if (rc)
    91                 break;
    92         }
    93 
    94         if (i-- > 1)
    95         {
    96             ULONG fulState = 0;
    97             rc = DosQueryFHState(ahfs[i], &fulState);
    98             if (!rc)
    99             {
    100                 fulState |= OPEN_FLAGS_NOINHERIT;
    101                 fulState &= OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT; /* Turn off non-participating bits. */
    102                 rc = DosSetFHState(ahfs[i], fulState);
    103             }
    104             if (!rc)
    105             {
    106                 rc = DosClose(hf);
    107                 AssertMsg(!rc, ("%ld\n", rc));
    108                 hf = ahfs[i];
    109             }
    110             else
    111                 i++;
    112             while (i-- > 0)
    113                 DosClose(ahfs[i]);
    114         }
    115     }
    116     g_File = hf;
    117 
    118      /* PORTME */
    119 #else
    120     /* the default implemenation. (linux, solaris) */
    121     RTFILE File;
    122     int rc = RTFileOpen(&File, VBOXGUEST_DEVICE_NAME, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    123     if (RT_FAILURE(rc))
    124         return rc;
    125     g_File = File;
    126 
    127 #endif
    128 
    129     return VINF_SUCCESS;
    130 }
    131 
    132 
    133 VBGLR3DECL(void) VbglR3Term(void)
    134 {
    135     RTFILE File = g_File;
    136     g_File = NIL_RTFILE;
    137     if (File == NIL_RTFILE)
    138         return;
    139 #if defined(RT_OS_OS2)
    140     APIRET rc = DosClose(File);
    141     AssertMsg(!rc, ("%ld\n", rc));
    142 #else
    143     int rc = RTFileClose(File);
    144     AssertRC(rc);
    145 #endif
    146 }
    147 
    148 
    149 /**
    150  * Internal wrapper around various OS specific ioctl implemenations.
    151  *
    152  * @returns VBox status code as returned by VBoxGuestCommonIOCtl, or
    153  *          an failure returned by the OS specific ioctl APIs.
    154  *
    155  * @param   iFunction   The requested function.
    156  * @param   pvData      The input and output data buffer.
    157  * @param   cbData      The size of the buffer.
    158  *
    159  * @remark  Exactly how the VBoxGuestCommonIOCtl is ferried back
    160  *          here is OS specific. On BSD and Darwin we can use errno,
    161  *          while on OS/2 we use the 2nd buffer of the IOCtl.
    162  */
    163 int vbglR3DoIOCtl(unsigned iFunction, void *pvData, size_t cbData)
    164 {
    165 #ifdef RT_OS_OS2
    166     ULONG cbOS2Parm = cbData;
    167     int32_t vrc = VERR_INTERNAL_ERROR;
    168     ULONG cbOS2Data = sizeof(vrc);
    169     APIRET rc = DosDevIOCtl(g_File, VBOXGUEST_IOCTL_CATEGORY, iFunction,
    170                             pvData, cbData, &cbOS2Parm,
    171                             &vrc, sizeof(vrc), &cbOS2Data);
    172     if (RT_LIKELY(!rc))
    173         return vrc;
    174     return RTErrConvertFromOS2(rc);
    175 
    176 #elif defined(RT_OS_SOLARIS) && 0
    177     VBGLBIGREQ Hdr;
    178     Hdr.u32Magic = VBGLBIGREQ_MAGIC;
    179     Hdr.cbData = cbData;
    180     Hdr.pvData = pvData;
    181     Assert(_IOC_SIZE(iFunction) == sizeof(Hdr));
    182 
    183     int rc = ioctl((int)File, iFunction, &Hdr);
    184     if (rc == -1)
    185         rc = errno;
    186     return rc;
    187 
    188     /* PORTME */
    189 #else
    190     /* Default implementation (linux, solaris). */
    191     int rc2 = VERR_INTERNAL_ERROR;
    192     int rc = RTFileIoCtl(g_File, (int)iFunction, pvData, cbData, &rc2);
    193     if (RT_SUCCESS(rc))
    194         rc = rc2;
    195     return rc;
    196 #endif
    197 }
    198 
    199 
    200 VBGLR3DECL(int) VbglR3GRAlloc(VMMDevRequestHeader **ppReq, uint32_t cb, VMMDevRequestType enmReqType)
    201 {
    202     VMMDevRequestHeader *pReq;
    203 
    204     AssertPtrReturn(ppReq, VERR_INVALID_PARAMETER);
    205     AssertMsgReturn(cb >= sizeof(VMMDevRequestHeader), ("%#x vs %#zx\n", cb, sizeof(VMMDevRequestHeader)),
    206                     VERR_INVALID_PARAMETER);
    207 
    208     pReq = (VMMDevRequestHeader *)RTMemTmpAlloc(cb);
    209     if (RT_UNLIKELY(!pReq))
    210         return VERR_NO_MEMORY;
    211 
    212     pReq->size        = cb;
    213     pReq->version     = VMMDEV_REQUEST_HEADER_VERSION;
    214     pReq->requestType = enmReqType;
    215     pReq->rc          = VERR_GENERAL_FAILURE;
    216     pReq->reserved1   = 0;
    217     pReq->reserved2   = 0;
    218 
    219     *ppReq = pReq;
    220 
    221     return VINF_SUCCESS;
    222 }
    223 
    224 
    225 VBGLR3DECL(int) VbglR3GRPerform(VMMDevRequestHeader *pReq)
    226 {
    227     return vbglR3DoIOCtl(VBOXGUEST_IOCTL_VMMREQUEST(pReq->size), pReq, pReq->size);
    228 }
    229 
    230 
    231 VBGLR3DECL(void) VbglR3GRFree(VMMDevRequestHeader *pReq)
    232 {
    233     RTMemTmpFree(pReq);
    234 }
    235 
    236 
    237 VBGLR3DECL(int) VbglR3GetHostTime(PRTTIMESPEC pTime)
    238 {
    239     VMMDevReqHostTime Req;
    240     vmmdevInitRequest(&Req.header, VMMDevReq_GetHostTime);
    241     Req.time = UINT64_MAX;
    242     int rc = VbglR3GRPerform(&Req.header);
    243     if (RT_SUCCESS(rc))
    244         RTTimeSpecSetMilli(pTime, (int64_t)Req.time);
    245     return rc;
    246 }
    247 
    248 
    249 VBGLR3DECL(int) VbglR3GetMouseStatus(uint32_t *pfFeatures, uint32_t *px, uint32_t *py)
    250 {
    251     VMMDevReqMouseStatus Req;
    252     vmmdevInitRequest(&Req.header, VMMDevReq_GetMouseStatus);
    253     Req.mouseFeatures = 0;
    254     Req.pointerXPos = 0;
    255     Req.pointerYPos = 0;
    256     int rc = VbglR3GRPerform(&Req.header);
    257     if (RT_SUCCESS(rc))
    258     {
    259         if (pfFeatures)
    260             *pfFeatures = Req.mouseFeatures;
    261         if (px)
    262             *px = Req.pointerXPos;
    263         if (py)
    264             *py = Req.pointerYPos;
    265     }
    266     return rc;
    267 }
    268 
    269 
    270 VBGLR3DECL(int) VbglR3SetMouseStatus(uint32_t fFeatures)
    271 {
    272     VMMDevReqMouseStatus Req;
    273     vmmdevInitRequest(&Req.header, VMMDevReq_SetMouseStatus);
    274     Req.mouseFeatures = fFeatures;
    275     Req.pointerXPos = 0;
    276     Req.pointerYPos = 0;
    277     return VbglR3GRPerform(&Req.header);
    278 }
    279 
    280 
    281 /**
    282  * Cause any pending WaitEvent calls (VBOXGUEST_IOCTL_WAITEVENT) to return
    283  * with a VERR_INTERRUPTED status.
    284  *
    285  * Can be used in combination with a termination flag variable for interrupting
    286  * event loops. Avoiding race conditions is the responsibility of the caller.
    287  *
    288  * @returns IPRT status code
    289  */
    290 VBGLR3DECL(int) VbglR3InterruptEventWaits(void)
    291 {
    292     return vbglR3DoIOCtl(VBOXGUEST_IOCTL_WAITEVENT_INTERRUPT_ALL, 0, 0);
    293 }
    294 
    295 
    296 /**
    297  * Write to the backdoor logger from ring 3 guest code.
    298  *
    299  * @returns IPRT status code
    300  *
    301  * @remarks This currently does not accept more than 255 bytes of data at
    302  *          one time. It should probably be rewritten to use pass a pointer
    303  *          in the IOCtl.
    304  */
    305 VBGLR3DECL(int) VbglR3WriteLog(const char *pch, size_t cb)
    306 {
    307     /*
    308      * Solaris does not accept more than 255 bytes of data per ioctl request,
    309      * so split large string into 128 byte chunks to prevent truncation.
    310      */
    311 #define STEP 128 /** @todo increase to 512 when solaris ioctl code is fixed. (darwin limits us to 1024 IIRC) */
    312     int rc = VINF_SUCCESS;
    313     for (size_t off = 0; off < cb && RT_SUCCESS(rc); off += STEP)
    314     {
    315         size_t cbStep = RT_MIN(cb - off, STEP);
    316         rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_LOG(cbStep), (char *)pch + off, cbStep);
    317     }
    318 #undef STEP
    319     return rc;
    320 }
    321 
    322 
    323 /**
    324  * Change the IRQ filter mask.
    325  *
    326  * @returns IPRT status code
    327  * @param   fOr     The OR mask.
    328  * @param   fNo     The NOT mask.
    329  */
    330 VBGLR3DECL(int) VbglR3CtlFilterMask(uint32_t fOr, uint32_t fNot)
    331 {
    332     VBoxGuestFilterMaskInfo Info;
    333     Info.u32OrMask = fOr;
    334     Info.u32NotMask = fNot;
    335     return vbglR3DoIOCtl(VBOXGUEST_IOCTL_CTL_FILTER_MASK, &Info, sizeof(Info));
    336 }
    33749
    33850
     
    34052 * Daemonize the process for running in the background.
    34153 *
     54 * This is supposed to do the same job as the BSD daemon() call.
     55 *
    34256 * @returns 0 on success
    34357 *
    344  * @param   nochdir     Pass 0 to change working directory to root.
    345  * @param   noclose     Pass 0 to redirect standard file streams to /dev/null.
     58 * @param   fNoChDir    Pass false to change working directory to root.
     59 * @param   fNoClose    Pass false to redirect standard file streams to /dev/null.
    34660 */
    347 VBGLR3DECL(int) VbglR3Daemonize(int nochdir, int noclose)
     61VBGLR3DECL(int) VbglR3Daemonize(bool fNoChDir, bool fNoClose)
    34862{
    349 #if defined(RT_OS_LINUX)
    350     /** rlimit structure for finding out how many open files we may have. */
    351     struct rlimit rlim;
    352 
    353     /* To make sure that we are not currently a session leader, we must first fork and let
    354        the parent process exit, as a newly created child is never session leader.  This will
    355        allow us to call setsid() later. */
    356     if (fork() != 0)
    357     {
    358         exit(0);
    359     }
    360     /* Find the maximum number of files we can have open and close them all. */
    361     if (0 != getrlimit(RLIMIT_NOFILE, &rlim))
    362     {
    363         /* For some reason the call failed.  In that case we will just close the three
    364            standard files and hope. */
    365         rlim.rlim_cur = 3;
    366     }
    367     for (unsigned int i = 0; i < rlim.rlim_cur; ++i)
    368     {
    369         close(i);
    370     }
    371     /* Change to the root directory to avoid keeping the one we were started in open. */
    372     chdir("/");
    373     /* Set our umask to zero. */
    374     umask(0);
    375     /* And open /dev/null on stdin/out/err. */
    376     open("/dev/null", O_RDONLY);
    377     open("/dev/null", O_WRONLY);
    378     dup(1);
    379     /* Detach from the controlling terminal by creating our own session, to avoid receiving
    380        signals from the old session. */
    381     setsid();
    382     /* And fork again, letting the parent exit, to make us a child of init and avoid zombies. */
    383     if (fork() != 0)
    384     {
    385         exit(0);
    386     }
    387     NOREF(nochdir);
    388     NOREF(noclose);
    389 
    390     return 0;
     63#if defined(RT_OS_DARWIN)
     64# error "PORTME"
    39165
    39266#elif defined(RT_OS_OS2)
     
    39973    APIRET rc = DosQueryModuleName(pPib->pib_hmte, sizeof(szExe), szExe);
    40074    if (rc)
    401     {
    402         errno = EDOOFUS;
    403         return -1;
    404     }
     75        return RTErrConvertFromOS2(rc);
    40576
    40677    /* calc the length of the command line. */
     
    444115        /** @todo Change this to some standard log/print error?? */
    445116        /* VBoxServiceError("DosExecPgm failed with rc=%d and szObj='%s'\n", rc, szObj); */
    446         errno = EDOOFUS;
    447         return -1;
     117        return RTErrConvertFromOS2(rc);
    448118    }
    449119    DosExit(EXIT_PROCESS, 0);
    450     return -1;
    451 
    452 #elif defined(RT_OS_SOLARIS)
    453     if (getppid() == 1) /* We already belong to init process */
    454         return -1;
     120    return VERR_GENERAL_FAILURE;
     121
     122#elif defined(RT_OS_WINDOWS)
     123# error "PORTME"
     124
     125#else /* the unices */
     126
     127# ifdef RT_OS_SOLARIS
     128    /*
     129     * Check if we already belong the init process (pid 1).
     130     */
     131    /** @todo Why do we need to check for this? */
     132    if (getppid() == 1)
     133        return VERR_GENERAL_FAILURE;
     134# endif
     135
     136    /*
     137     * Fork the child process and quit the parent.
     138     *
     139     * On Linux we'll fork once more at the end of it all just to be sure that
     140     * we're not leaving any zombies behind. The SIGHUP stuff is ignored because
     141     * the parent may throw us one before we get to the setsid stuff one some
     142     * systems (BSD).
     143     */
     144    struct sigaction OldSigAct;
     145    struct sigaction SigAct;
     146    memset(&SigAct, 0, sizeof(SigAct));
     147    SigAct.sa_handler = SIG_IGN;
     148    int rcSigAct = sigaction(SIGHUP, &SigAct, &OldSigAct);
    455149
    456150    pid_t pid = fork();
    457     if (pid < 0)         /* The fork() failed. Bad. */
    458         return -1;
    459 
    460     if (pid > 0)         /* Quit parent process */
     151    if (pid == -1)
     152        return RTErrConvertFromErrno(errno);
     153    if (pid != 0)
    461154        exit(0);
    462155
    463156    /*
    464      * The orphaned child becomes a daemon after attaching to init. We need to get
    465      * rid of signals, file descriptors & other stuff we inherited from the parent.
     157     * The orphaned child becomes is reparented to the init process.
     158     * We create a new session for it (setsid), point the standard
     159     * file descriptors to /dev/null, and change to the root directory.
    466160     */
    467161    pid_t newpgid = setsid();
    468     if (newpgid < 0)     /* Failed to create new sesion */
    469         return -1;
    470 
    471     /* BSD daemon style. */
    472     if (!noclose)
    473     {
    474         /* Open stdin(0), stdout(1) and stderr(2) to /dev/null */
     162    int SavedErrno = errno;
     163    if (rcSigAct != -1)
     164        sigaction(SIGHUP, &OldSigAct, NULL);
     165    if (newpgid == -1)
     166        return RTErrConvertFromErrno(SavedErrno);
     167
     168    if (!fNoClose)
     169    {
     170        /* Open stdin(0), stdout(1) and stderr(2) as /dev/null. */
    475171        int fd = open("/dev/null", O_RDWR);
    476         dup2(fd, STDIN_FILENO);
    477         dup2(fd, STDOUT_FILENO);
    478         dup2(fd, STDERR_FILENO);
    479         if (fd > 2)
    480             close(fd);
    481     }
    482 
    483     /* Switch our current directory to root */
    484     if (!nochdir)
    485         chdir("/");     /* @todo Check if switching to '/' is the convention for Solaris daemons. */
    486 
    487     /* Set file permission to something secure, as we need to run as root on Solaris */
     172        if (fd == -1) /* paranoia */
     173        {
     174            close(STDIN_FILENO);
     175            close(STDOUT_FILENO);
     176            close(STDERR_FILENO);
     177            fd = open("/dev/null", O_RDWR);
     178        }
     179        if (fd != -1)
     180        {
     181            dup2(fd, STDIN_FILENO);
     182            dup2(fd, STDOUT_FILENO);
     183            dup2(fd, STDERR_FILENO);
     184            if (fd > 2)
     185                close(fd);
     186        }
     187    }
     188
     189    if (!fNoChDir)
     190        chdir("/");
     191
     192    /*
     193     * Change the umask - this is non-standard daemon() behavior.
     194     */
     195    /** @todo why is umask set to 0 on linux? the solaris value is more sensible... */
     196# ifdef RT_OS_SOLARIS
    488197    umask(027);
    489     return 0;
     198# else
     199    umask(0);
     200# endif
     201
     202# ifdef RT_OS_LINUX
     203    /*
     204     * And fork again to avoid zomibies and stuff (non-standard daemon() behaviour).
     205     */
     206    pid = fork();
     207    if (pid == -1)
     208        return RTErrConvertFromErrno(errno);
     209    if (pid != 0)
     210        exit(0);
     211# endif /* RT_OS_LINUX */
     212
     213    return VINF_SUCCESS;
    490214#endif
    491215}
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