VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/process-posix.cpp@ 5285

Last change on this file since 5285 was 4475, checked in by vboxsync, 17 years ago

Some adjustments to RTEnv and RTProcCreate. Should work on darwin now.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.9 KB
Line 
1/* $Id: process-posix.cpp 4475 2007-09-01 01:21:19Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Process, POSIX.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19
20/*******************************************************************************
21* Header Files *
22*******************************************************************************/
23#define LOG_GROUP RTLOGGROUP_PROCESS
24#include <unistd.h>
25#include <stdlib.h>
26#include <errno.h>
27#include <sys/stat.h>
28#include <sys/wait.h>
29#include <signal.h>
30#if defined(RT_OS_LINUX) || defined(RT_OS_OS2)
31# define HAVE_POSIX_SPAWN 1
32#endif
33#ifdef HAVE_POSIX_SPAWN
34# include <spawn.h>
35#endif
36#ifdef RT_OS_DARWIN
37# include <mach-o/dyld.h>
38#endif
39
40#include <iprt/process.h>
41#include <iprt/string.h>
42#include <iprt/assert.h>
43#include <iprt/err.h>
44#include <iprt/env.h>
45#include "internal/process.h"
46
47
48
49RTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess)
50{
51 /*
52 * Validate input.
53 */
54 AssertPtrReturn(pszExec, VERR_INVALID_POINTER);
55 AssertReturn(*pszExec, VERR_INVALID_PARAMETER);
56 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
57 AssertReturn(Env != NIL_RTENV, VERR_INVALID_PARAMETER);
58 const char * const *papszEnv = RTEnvGetExecEnvP(Env);
59 AssertPtrReturn(papszEnv, VERR_INVALID_HANDLE);
60 /* later: path searching. */
61
62
63 /*
64 * Check for execute access to the file.
65 */
66 if (access(pszExec, X_OK))
67 {
68 int rc = RTErrConvertFromErrno(errno);
69 AssertMsgFailed(("'%s' %Vrc!\n", pszExec, rc));
70 return rc;
71 }
72
73#if 0
74 /*
75 * Squeeze gdb --args in front of what's being spawned.
76 */
77 unsigned cArgs = 0;
78 while (papszArgs[cArgs])
79 cArgs++;
80 cArgs += 3;
81 const char **papszArgsTmp = (const char **)alloca(cArgs * sizeof(char *));
82 papszArgsTmp[0] = "/usr/bin/gdb";
83 papszArgsTmp[1] = "--args";
84 papszArgsTmp[2] = pszExec;
85 for (unsigned i = 1; papszArgs[i]; i++)
86 papszArgsTmp[i + 2] = papszArgs[i];
87 papszArgsTmp[cArgs - 1] = NULL;
88 pszExec = papszArgsTmp[0];
89 papszArgs = papszArgsTmp;
90#endif
91
92 /*
93 * Spawn the child.
94 */
95 pid_t pid;
96#ifdef HAVE_POSIX_SPAWN
97 /** @todo check if it requires any of those two attributes, don't remember atm. */
98 int rc = posix_spawn(&pid, pszExec, NULL, NULL, (char * const *)papszArgs,
99 (char * const *)papszEnv);
100 if (!rc)
101 {
102 if (pProcess)
103 *pProcess = pid;
104 return VINF_SUCCESS;
105 }
106
107#else
108
109 pid = fork();
110 if (!pid)
111 {
112 int rc;
113 rc = execve(pszExec, (char * const *)papszArgs, (char * const *)papszEnv);
114 AssertReleaseMsgFailed(("execve returns %d errno=%d\n", rc, errno));
115 exit(127);
116 }
117 if (pid > 0)
118 {
119 if (pProcess)
120 *pProcess = pid;
121 return VINF_SUCCESS;
122 }
123 int rc = errno;
124#endif
125
126 /* failure, errno value in rc. */
127 AssertMsgFailed(("spawn/exec failed rc=%d\n", rc)); /* this migth be annoying... */
128 return RTErrConvertFromErrno(rc);
129}
130
131
132RTR3DECL(int) RTProcWait(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus)
133{
134 int rc;
135 do rc = RTProcWaitNoResume(Process, fFlags, pProcStatus);
136 while (rc == VERR_INTERRUPTED);
137 return rc;
138}
139
140RTR3DECL(int) RTProcWaitNoResume(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus)
141{
142 /*
143 * Validate input.
144 */
145 if (Process <= 0)
146 {
147 AssertMsgFailed(("Invalid Process=%d\n", Process));
148 return VERR_INVALID_PARAMETER;
149 }
150 if (fFlags & ~(RTPROCWAIT_FLAGS_NOBLOCK | RTPROCWAIT_FLAGS_BLOCK))
151 {
152 AssertMsgFailed(("Invalid flags %#x\n", fFlags));
153 return VERR_INVALID_PARAMETER;
154 }
155
156 /*
157 * Performe the wait.
158 */
159 int iStatus = 0;
160 int rc = waitpid(Process, &iStatus, fFlags & RTPROCWAIT_FLAGS_NOBLOCK ? WNOHANG : 0);
161 if (rc > 0)
162 {
163 /*
164 * Fill in the status structure.
165 */
166 if (pProcStatus)
167 {
168 if (WIFEXITED(iStatus))
169 {
170 pProcStatus->enmReason = RTPROCEXITREASON_NORMAL;
171 pProcStatus->iStatus = WEXITSTATUS(iStatus);
172 }
173 else if (WIFSIGNALED(iStatus))
174 {
175 pProcStatus->enmReason = RTPROCEXITREASON_SIGNAL;
176 pProcStatus->iStatus = WTERMSIG(iStatus);
177 }
178 else
179 {
180 Assert(!WIFSTOPPED(iStatus));
181 pProcStatus->enmReason = RTPROCEXITREASON_ABEND;
182 pProcStatus->iStatus = iStatus;
183 }
184 }
185 return VINF_SUCCESS;
186 }
187
188 /*
189 * Child running?
190 */
191 if (!rc)
192 {
193 Assert(fFlags & RTPROCWAIT_FLAGS_NOBLOCK);
194 return VERR_PROCESS_RUNNING;
195 }
196
197 /*
198 * Figure out which error to return.
199 */
200 int iErr = errno;
201 if (iErr == ECHILD)
202 return VERR_PROCESS_NOT_FOUND;
203 return RTErrConvertFromErrno(iErr);
204}
205
206
207RTR3DECL(int) RTProcTerminate(RTPROCESS Process)
208{
209 if (!kill(Process, SIGKILL))
210 return VINF_SUCCESS;
211 return RTErrConvertFromErrno(errno);
212}
213
214
215RTR3DECL(uint64_t) RTProcGetAffinityMask()
216{
217 // @todo
218 return 1;
219}
220
221
222RTR3DECL(char *) RTProcGetExecutableName(char *pszExecName, size_t cchExecName)
223{
224 /*
225 * I don't think there is a posix API for this, but
226 * because I'm lazy I'm not creating OS specific code
227 * files and code for this.
228 */
229#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_SOLARIS)
230# ifdef RT_OS_LINUX
231 int cchLink = readlink("/proc/self/exe", pszExecName, cchExecName - 1);
232# elif defined(RT_OS_SOLARIS)
233 char szFileBuf[80];
234 RTStrPrintf(szFileBuf, sizeof(szFileBuf), "/proc/%ld/path/a.out", (long)getpid());
235 int cchLink = readlink(szFileBuf, pszExecName, cchExecName - 1);
236# else
237 int cchLink = readlink("/proc/curproc/file", pszExecName, cchExecName - 1);
238# endif
239 if (cchLink > 0 && (size_t)cchLink <= cchExecName - 1)
240 {
241 pszExecName[cchLink] = '\0';
242 return pszExecName;
243 }
244
245#elif defined(RT_OS_OS2) || defined(RT_OS_L4)
246 if (!_execname(pszExecName, cchExecName))
247 return pszExecName;
248
249#elif defined(RT_OS_DARWIN)
250 const char *pszImageName = _dyld_get_image_name(0);
251 if (pszImageName)
252 {
253 size_t cchImageName = strlen(pszImageName);
254 if (cchImageName < cchExecName)
255 return (char *)memcpy(pszExecName, pszImageName, cchImageName + 1);
256 }
257
258#else
259# error "Port me!"
260#endif
261 return NULL;
262}
263
Note: See TracBrowser for help on using the repository browser.

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