VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/threads/nsProcessCommon.cpp@ 36233

最後變更 在這個檔案從36233是 31259,由 vboxsync 提交於 14 年 前

xpcom: Use RTMem* for memory alloc so that we can more easily wrap direct it to the electric fence heap.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 10.3 KB
 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is Mozilla Communicator client code, released
16 * March 31, 1998.
17 *
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998-1999
21 * the Initial Developer. All Rights Reserved.
22 *
23 * Contributor(s):
24 * Don Bragg <[email protected]>
25 *
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
37 *
38 * ***** END LICENSE BLOCK ***** */
39
40/*****************************************************************************
41 *
42 * nsProcess is used to execute new processes and specify if you want to
43 * wait (blocking) or continue (non-blocking).
44 *
45 *****************************************************************************
46 */
47
48#include "nsCOMPtr.h"
49#include "nsMemory.h"
50#include "nsProcess.h"
51#include "prtypes.h"
52#include "prio.h"
53#include "prenv.h"
54#include "nsCRT.h"
55
56#include <stdlib.h>
57
58#if defined( XP_WIN )
59#include "prmem.h"
60#include "nsString.h"
61#include "nsLiteralString.h"
62#include "nsReadableUtils.h"
63#include <windows.h>
64#endif
65
66//-------------------------------------------------------------------//
67// nsIProcess implementation
68//-------------------------------------------------------------------//
69NS_IMPL_ISUPPORTS1(nsProcess, nsIProcess)
70
71//Constructor
72nsProcess::nsProcess():mExitValue(-1),
73 mProcess(nsnull)
74{
75}
76
77NS_IMETHODIMP
78nsProcess::Init(nsIFile* executable)
79{
80 PRBool isFile;
81
82 //First make sure the file exists
83 nsresult rv = executable->IsFile(&isFile);
84 if (NS_FAILED(rv)) return rv;
85 if (!isFile)
86 return NS_ERROR_FAILURE;
87
88 //Store the nsIFile in mExecutable
89 mExecutable = executable;
90 //Get the path because it is needed by the NSPR process creation
91#ifdef XP_WIN
92 rv = mExecutable->GetNativeTarget(mTargetPath);
93 if (NS_FAILED(rv) || mTargetPath.IsEmpty() )
94#endif
95 rv = mExecutable->GetNativePath(mTargetPath);
96
97 return rv;
98}
99
100
101#if defined( XP_WIN )
102static int assembleCmdLine(char *const *argv, char **cmdLine)
103{
104 char *const *arg;
105 char *p, *q;
106 int cmdLineSize;
107 int numBackslashes;
108 int i;
109 int argNeedQuotes;
110
111 /*
112 * Find out how large the command line buffer should be.
113 */
114 cmdLineSize = 0;
115 for (arg = argv; *arg; arg++) {
116 /*
117 * \ and " need to be escaped by a \. In the worst case,
118 * every character is a \ or ", so the string of length
119 * may double. If we quote an argument, that needs two ".
120 * Finally, we need a space between arguments, and
121 * a null byte at the end of command line.
122 */
123 cmdLineSize += 2 * strlen(*arg) /* \ and " need to be escaped */
124 + 2 /* we quote every argument */
125 + 1; /* space in between, or final null */
126 }
127 p = *cmdLine = (char *) PR_MALLOC(cmdLineSize);
128 if (p == NULL) {
129 return -1;
130 }
131
132 for (arg = argv; *arg; arg++) {
133 /* Add a space to separates the arguments */
134 if (arg != argv) {
135 *p++ = ' ';
136 }
137 q = *arg;
138 numBackslashes = 0;
139 argNeedQuotes = 0;
140
141 /* If the argument contains white space, it needs to be quoted. */
142 if (strpbrk(*arg, " \f\n\r\t\v")) {
143 argNeedQuotes = 1;
144 }
145
146 if (argNeedQuotes) {
147 *p++ = '"';
148 }
149 while (*q) {
150 if (*q == '\\') {
151 numBackslashes++;
152 q++;
153 } else if (*q == '"') {
154 if (numBackslashes) {
155 /*
156 * Double the backslashes since they are followed
157 * by a quote
158 */
159 for (i = 0; i < 2 * numBackslashes; i++) {
160 *p++ = '\\';
161 }
162 numBackslashes = 0;
163 }
164 /* To escape the quote */
165 *p++ = '\\';
166 *p++ = *q++;
167 } else {
168 if (numBackslashes) {
169 /*
170 * Backslashes are not followed by a quote, so
171 * don't need to double the backslashes.
172 */
173 for (i = 0; i < numBackslashes; i++) {
174 *p++ = '\\';
175 }
176 numBackslashes = 0;
177 }
178 *p++ = *q++;
179 }
180 }
181
182 /* Now we are at the end of this argument */
183 if (numBackslashes) {
184 /*
185 * Double the backslashes if we have a quote string
186 * delimiter at the end.
187 */
188 if (argNeedQuotes) {
189 numBackslashes *= 2;
190 }
191 for (i = 0; i < numBackslashes; i++) {
192 *p++ = '\\';
193 }
194 }
195 if (argNeedQuotes) {
196 *p++ = '"';
197 }
198 }
199
200 *p = '\0';
201 return 0;
202}
203#endif
204
205// XXXldb |args| has the wrong const-ness
206NS_IMETHODIMP
207nsProcess::Run(PRBool blocking, const char **args, PRUint32 count, PRUint32 *pid)
208{
209 nsresult rv = NS_OK;
210
211 // make sure that when we allocate we have 1 greater than the
212 // count since we need to null terminate the list for the argv to
213 // pass into PR_CreateProcess
214 char **my_argv = NULL;
215#ifdef VBOX
216 my_argv = (char **)nsMemory::Alloc(sizeof(char *) * (count + 2) );
217#else
218 my_argv = (char **)malloc(sizeof(char *) * (count + 2) );
219#endif
220 if (!my_argv) {
221 return NS_ERROR_OUT_OF_MEMORY;
222 }
223
224 // copy the args
225 PRUint32 i;
226 for (i=0; i < count; i++) {
227 my_argv[i+1] = NS_CONST_CAST(char*, args[i]);
228 }
229 // we need to set argv[0] to the program name.
230 my_argv[0] = mTargetPath.BeginWriting();
231 // null terminate the array
232 my_argv[count+1] = NULL;
233
234 #if defined(XP_WIN)
235 STARTUPINFO startupInfo;
236 PROCESS_INFORMATION procInfo;
237 BOOL retVal;
238 char *cmdLine;
239
240 if (assembleCmdLine(my_argv, &cmdLine) == -1) {
241 nsMemory::Free(my_argv);
242 return NS_ERROR_FILE_EXECUTION_FAILED;
243 }
244
245 ZeroMemory(&startupInfo, sizeof(startupInfo));
246 startupInfo.cb = sizeof(startupInfo);
247
248 retVal = CreateProcess(NULL,
249 // NS_CONST_CAST(char*, mTargetPath.get()),
250 cmdLine,
251 NULL, /* security attributes for the new
252 * process */
253 NULL, /* security attributes for the primary
254 * thread in the new process */
255 FALSE, /* inherit handles */
256 0, /* creation flags */
257 NULL, /* env */
258 NULL, /* current drive and directory */
259 &startupInfo,
260 &procInfo
261 );
262 PR_FREEIF( cmdLine );
263 if (blocking) {
264
265 // if success, wait for process termination. the early returns and such
266 // are a bit ugly but preserving the logic of the nspr code I copied to
267 // minimize our risk abit.
268
269 if ( retVal == TRUE ) {
270 DWORD dwRetVal;
271 unsigned long exitCode;
272
273 dwRetVal = WaitForSingleObject(procInfo.hProcess, INFINITE);
274 if (dwRetVal == WAIT_FAILED) {
275 nsMemory::Free(my_argv);
276 return PR_FAILURE;
277 }
278 if (GetExitCodeProcess(procInfo.hProcess, &exitCode) == FALSE) {
279 mExitValue = exitCode;
280 nsMemory::Free(my_argv);
281 return PR_FAILURE;
282 }
283 mExitValue = exitCode;
284 CloseHandle(procInfo.hProcess);
285 }
286 else
287 rv = PR_FAILURE;
288 }
289 else {
290
291 // map return value into success code
292
293 if ( retVal == TRUE )
294 rv = PR_SUCCESS;
295 else
296 rv = PR_FAILURE;
297 }
298
299#else
300 if ( blocking ) {
301 mProcess = PR_CreateProcess(mTargetPath.get(), my_argv, NULL, NULL);
302 if (mProcess)
303 rv = PR_WaitProcess(mProcess, &mExitValue);
304 }
305 else {
306 rv = PR_CreateProcessDetached(mTargetPath.get(), my_argv, NULL, NULL);
307 }
308#endif
309
310 // free up our argv
311 nsMemory::Free(my_argv);
312
313 if (rv != PR_SUCCESS)
314 return NS_ERROR_FILE_EXECUTION_FAILED;
315 return NS_OK;
316}
317
318NS_IMETHODIMP nsProcess::InitWithPid(PRUint32 pid)
319{
320 return NS_ERROR_NOT_IMPLEMENTED;
321}
322
323NS_IMETHODIMP
324nsProcess::GetLocation(nsIFile** aLocation)
325{
326 return NS_ERROR_NOT_IMPLEMENTED;
327}
328
329NS_IMETHODIMP
330nsProcess::GetPid(PRUint32 *aPid)
331{
332 return NS_ERROR_NOT_IMPLEMENTED;
333}
334
335NS_IMETHODIMP
336nsProcess::GetProcessName(char** aProcessName)
337{
338 return NS_ERROR_NOT_IMPLEMENTED;
339}
340
341NS_IMETHODIMP
342nsProcess::GetProcessSignature(PRUint32 *aProcessSignature)
343{
344 return NS_ERROR_NOT_IMPLEMENTED;
345}
346
347NS_IMETHODIMP
348nsProcess::Kill()
349{
350 nsresult rv = NS_OK;
351 if (mProcess)
352 rv = PR_KillProcess(mProcess);
353
354 return rv;
355}
356
357NS_IMETHODIMP
358nsProcess::GetExitValue(PRInt32 *aExitValue)
359{
360 *aExitValue = mExitValue;
361
362 return NS_OK;
363}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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