VirtualBox

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

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

Rebranding: replacing more innotek strings.

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