2N/A * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. 2N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2N/A * This code is free software; you can redistribute it and/or modify it 2N/A * under the terms of the GNU General Public License version 2 only, as 2N/A * published by the Free Software Foundation. Oracle designates this 2N/A * particular file as subject to the "Classpath" exception as provided 2N/A * by Oracle in the LICENSE file that accompanied this code. 2N/A * This code is distributed in the hope that it will be useful, but WITHOUT 2N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2N/A * version 2 for more details (a copy is included in the LICENSE file that 2N/A * accompanied this code). 2N/A * You should have received a copy of the GNU General Public License version 2N/A * 2 along with this work; if not, write to the Free Software Foundation, 2N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2N/A * or visit www.oracle.com if you need additional information or have any 2N/A/* This class is for the exclusive use of ProcessBuilder.start() to 2N/A * create new processes. 2N/A * @author Martin Buchholz 2N/A * Open a file for writing. If {@code append} is {@code true} then the file 2N/A * is opened for atomic append directly and a FileOutputStream constructed 2N/A * with the resulting handle. This is because a FileOutputStream created 2N/A * to append to a file does not open the file in a manner that guarantees 2N/A * that writes by the child process will be atomic. // System-dependent portion of ProcessBuilder.start() // In theory, close() can throw IOException // (although it is rather unlikely to happen here) // Escape-support version: // "(\")((?:\\\\\\1|.)+?)\\1|([^\\s\"]+)"; /* Parses the command string parameter into the executable name and * The command string is broken into tokens. The token separator is a space * or quota character. The space inside quotation is not a token separator. * There are no escape sequences. // We guarantee the only command file execution for implicit [cmd.exe] run. {
' ',
'\t',
'<',
'>',
'&',
'|',
'^'},
// The code protects the [java.exe] and console command line // parser, that interprets the [\"] combination as an escape // sequence for the ["] char. // If the argument is an FS path, doubling of the tail [\] // char is not a problem for non-console applications. // The [\"] sequence is not an escape sequence for the [cmd.exe] // command line parser. The case of the [""] tail escape // sequence could not be realized due to the argument validation // The argument has already been quoted. // Switch off MS heuristic for internal ["]. // Please, use the explicit [cmd.exe] call // if you need the internal ["]. // Example: "cmd.exe", "/C", "Extended_MS_Syntax" // in the argument is not a problem. arg,
"Argument has embedded quote, use the explicit CMD.EXE call.");
"Executable name has embedded quote, split the arguments");
// Win32 CreateProcess requires path to be normalized // From the [CreateProcess] function documentation: // "If the file name does not contain an extension, .exe is appended. // Therefore, if the file name extension is .com, this parameter // must include the .com extension. If the file name ends in // a period (.) with no extension, or if the file name contains a path, // .exe is not appended." // "If the file name !does not contain a directory path!, // the system searches for the executable file in the following // In practice ANY non-existent path is extended by [.exe] extension // in the [CreateProcess] funcion with the only exception: // Normalize path if possible. //legacy mode doesn't worry about extended verification // Workaround for the calls like // Runtime.getRuntime().exec("\"C:\\Program Files\\foo\" bar") // No chance to avoid CMD/BAT injection, except to do the work // right from the beginning. Otherwise we have too many corner // Runtime.getRuntime().exec(String[] cmd [, ...]) // calls with internal ["] and escape sequences. // Restore original command line. // terminal space in command line is ok // Parse the command line again. // Check new executable name once more // Quotation protects from interpretation of the [path] argument as // start of longer path with spaces. Quotation has no influence to // [.exe] extension heuristic. // We need the extended verification procedure for CMD files. * Create a process using the win32 function CreateProcess. * @param cmdstr the Windows commandline * @param envblock NUL-separated, double-NUL-terminated list of * environment strings in VAR=VALUE form * @param dir the working directory of the process, or null if * inheriting the current directory from the parent process * @param stdHandles array of windows HANDLEs. Indexes 0, 1, and * 2 correspond to standard input, standard output and * standard error, respectively. On input, a value of -1 * means to create a pipe to connect child and parent * processes. On output, a value which is not -1 is the * parent pipe handle corresponding to the pipe which has * been created. An element of this array is -1 on input * if and only if it is <em>not</em> -1 on output. * @param redirectErrorStream redirectErrorStream attribute * @return the native subprocess HANDLE returned by CreateProcess * Opens a file for atomic append. The file is created if it doesn't * @param file the file to open or create * @return the native HANDLE