Changeset 6445 in vbox for trunk/src/VBox/Additions/common/VBoxGuestLib
- Timestamp:
- Jan 22, 2008 2:19:50 PM (17 years ago)
- svn:sync-xref-src-repo-rev:
- 27420
- 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 96 96 VBoxGuestR3Lib_TEMPLATE = VBOXGUESTR3LIB 97 97 VBoxGuestR3Lib_DEFS = VBOX_HGCM 98 VBoxGuestR3Lib_SOURCES = VBoxGuestR3Lib.cpp VBoxGuestR3LibClipboard.cpp 98 VBoxGuestR3Lib_SOURCES = \ 99 VBoxGuestR3Lib.cpp \ 100 VBoxGuestR3LibDaemonize.cpp \ 101 VBoxGuestR3LibClipboard.cpp 99 102 100 103 … … 150 153 VBoxGuestR3LibLinux_SOURCES = \ 151 154 VBoxGuestR3Lib.cpp \ 155 VBoxGuestR3LibDaemonize.cpp \ 152 156 VBoxGuestR3LibClipboard.cpp \ 153 157 VBoxGuestR3LibSeamless.cpp -
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3Lib.cpp
r6434 r6445 24 24 # define INCL_ERRORS 25 25 # 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>36 26 #elif defined(RT_OS_SOLARIS) 37 27 # include <sys/types.h> 38 28 # include <sys/stat.h> 39 29 # include <errno.h> 40 # include <stdio.h>41 # include <stdlib.h>42 30 # include <unistd.h> 43 # include <signal.h>44 # include <fcntl.h>45 31 #endif 46 32 … … 51 37 #include <iprt/assert.h> 52 38 #include <iprt/mem.h> 39 #include <iprt/alloca.h> 53 40 #include <VBox/VBoxGuest.h> 54 41 … … 187 174 188 175 #else 189 /* Default implementation (linux, solaris).*/176 /* Default implementation - PORTME: Do not use this without testings that error passing works! */ 190 177 int rc2 = VERR_INTERNAL_ERROR; 191 178 int rc = RTFileIoCtl(g_File, (int)iFunction, pvData, cbData, &rc2); … … 335 322 } 336 323 337 338 /**339 * Daemonize the process for running in the background.340 *341 * @returns 0 on success342 *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 let353 the parent process exit, as a newly created child is never session leader. This will354 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 three363 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 receiving379 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 else423 {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 else433 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 get464 * 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 #endif490 }491 -
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDaemonize.cpp
r6425 r6445 1 1 /** $Id$ */ 2 2 /** @file 3 * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions .3 * VBoxGuestR3Lib - Ring-3 Support Library for VirtualBox guest additions, daemonize a process. 4 4 */ 5 5 … … 20 20 * Header Files * 21 21 *******************************************************************************/ 22 #ifdef RT_OS_OS2 22 #if defined(RT_OS_DARWIN) 23 # error "PORTME" 24 25 #elif defined(RT_OS_OS2) 23 26 # define INCL_BASE 24 27 # define INCL_ERRORS … … 27 30 # include <iprt/alloca.h> 28 31 # 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> 30 38 # include <sys/stat.h> 39 # include <stdio.h> 31 40 # include <fcntl.h> 32 41 # include <stdlib.h> 33 42 # 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>42 43 # include <signal.h> 43 # include < fcntl.h>44 # include <errno.h> 44 45 #endif 45 46 46 #include <iprt/time.h>47 #include <iprt/asm.h>48 47 #include <iprt/string.h> 49 #include <iprt/file.h>50 #include <iprt/assert.h>51 #include <iprt/mem.h>52 48 #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 to70 * the OS/2 APIs all the way. And in any case we have to use71 * 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 else111 i++;112 while (i-- > 0)113 DosClose(ahfs[i]);114 }115 }116 g_File = hf;117 118 /* PORTME */119 #else120 /* 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 #endif128 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 #else143 int rc = RTFileClose(File);144 AssertRC(rc);145 #endif146 }147 148 149 /**150 * Internal wrapper around various OS specific ioctl implemenations.151 *152 * @returns VBox status code as returned by VBoxGuestCommonIOCtl, or153 * 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 back160 * 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_OS2166 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) && 0177 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 #else190 /* 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 #endif197 }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 return283 * with a VERR_INTERRUPTED status.284 *285 * Can be used in combination with a termination flag variable for interrupting286 * event loops. Avoiding race conditions is the responsibility of the caller.287 *288 * @returns IPRT status code289 */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 code300 *301 * @remarks This currently does not accept more than 255 bytes of data at302 * one time. It should probably be rewritten to use pass a pointer303 * 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 STEP319 return rc;320 }321 322 323 /**324 * Change the IRQ filter mask.325 *326 * @returns IPRT status code327 * @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 }337 49 338 50 … … 340 52 * Daemonize the process for running in the background. 341 53 * 54 * This is supposed to do the same job as the BSD daemon() call. 55 * 342 56 * @returns 0 on success 343 57 * 344 * @param nochdir Pass 0to change working directory to root.345 * @param noclose Pass 0to 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. 346 60 */ 347 VBGLR3DECL(int) VbglR3Daemonize( int nochdir, int noclose)61 VBGLR3DECL(int) VbglR3Daemonize(bool fNoChDir, bool fNoClose) 348 62 { 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" 391 65 392 66 #elif defined(RT_OS_OS2) … … 399 73 APIRET rc = DosQueryModuleName(pPib->pib_hmte, sizeof(szExe), szExe); 400 74 if (rc) 401 { 402 errno = EDOOFUS; 403 return -1; 404 } 75 return RTErrConvertFromOS2(rc); 405 76 406 77 /* calc the length of the command line. */ … … 444 115 /** @todo Change this to some standard log/print error?? */ 445 116 /* VBoxServiceError("DosExecPgm failed with rc=%d and szObj='%s'\n", rc, szObj); */ 446 errno = EDOOFUS; 447 return -1; 117 return RTErrConvertFromOS2(rc); 448 118 } 449 119 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); 455 149 456 150 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) 461 154 exit(0); 462 155 463 156 /* 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. 466 160 */ 467 161 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. */ 475 171 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 488 197 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; 490 214 #endif 491 215 }
Note:
See TracChangeset
for help on using the changeset viewer.