Changeset 26802 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Feb 25, 2010 4:25:41 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 58070
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/posix/process-posix.cpp
r26415 r26802 54 54 55 55 #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> 56 63 #include <iprt/string.h> 57 #include <iprt/assert.h>58 #include <iprt/err.h>59 #include <iprt/env.h>60 64 #include "internal/process.h" 61 65 … … 64 68 RTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess) 65 69 { 70 #if 0 66 71 int rc; 67 72 … … 136 141 if (!rc) 137 142 { 138 /** @todo check if it requires any mandatory attributes or something, don't139 * remember atm. */140 143 rc = posix_spawn(&pid, pszExec, NULL, &Attr, (char * const *)papszArgs, 141 144 (char * const *)papszEnv); … … 181 184 AssertMsgFailed(("spawn/exec failed rc=%d\n", rc)); /* this migth be annoying... */ 182 185 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 195 RTR3DECL(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; 183 425 } 184 426
Note:
See TracChangeset
for help on using the changeset viewer.