Home | History | Annotate | Download | only in lang
      1 /*
      2  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 package java.lang;
     27 
     28 import java.io.IOException;
     29 import java.io.FileInputStream;
     30 import java.io.FileOutputStream;
     31 import java.lang.ProcessBuilder.Redirect;
     32 import java.lang.ProcessBuilder.Redirect;
     33 
     34 /**
     35  * This class is for the exclusive use of ProcessBuilder.start() to
     36  * create new processes.
     37  *
     38  * @author Martin Buchholz
     39  * @since   1.5
     40  */
     41 final class ProcessImpl {
     42 
     43     private ProcessImpl() {}    // Not instantiable
     44 
     45     private static byte[] toCString(String s) {
     46         if (s == null)
     47             return null;
     48         byte[] bytes = s.getBytes();
     49         byte[] result = new byte[bytes.length + 1];
     50         System.arraycopy(bytes, 0,
     51                          result, 0,
     52                          bytes.length);
     53         result[result.length-1] = (byte)0;
     54         return result;
     55     }
     56 
     57     // Only for use by ProcessBuilder.start()
     58     static Process start(String[] cmdarray,
     59                          java.util.Map<String,String> environment,
     60                          String dir,
     61                          ProcessBuilder.Redirect[] redirects,
     62                          boolean redirectErrorStream)
     63         throws IOException
     64     {
     65         assert cmdarray != null && cmdarray.length > 0;
     66 
     67         // Convert arguments to a contiguous block; it's easier to do
     68         // memory management in Java than in C.
     69         byte[][] args = new byte[cmdarray.length-1][];
     70         int size = args.length; // For added NUL bytes
     71         for (int i = 0; i < args.length; i++) {
     72             args[i] = cmdarray[i+1].getBytes();
     73             size += args[i].length;
     74         }
     75         byte[] argBlock = new byte[size];
     76         int i = 0;
     77         for (byte[] arg : args) {
     78             System.arraycopy(arg, 0, argBlock, i, arg.length);
     79             i += arg.length + 1;
     80             // No need to write NUL bytes explicitly
     81         }
     82 
     83         int[] envc = new int[1];
     84         byte[] envBlock = ProcessEnvironment.toEnvironmentBlock(environment, envc);
     85 
     86         int[] std_fds;
     87 
     88         FileInputStream  f0 = null;
     89         FileOutputStream f1 = null;
     90         FileOutputStream f2 = null;
     91 
     92         try {
     93             if (redirects == null) {
     94                 std_fds = new int[] { -1, -1, -1 };
     95             } else {
     96                 std_fds = new int[3];
     97 
     98                 if (redirects[0] == Redirect.PIPE)
     99                     std_fds[0] = -1;
    100                 else if (redirects[0] == Redirect.INHERIT)
    101                     std_fds[0] = 0;
    102                 else {
    103                     f0 = new FileInputStream(redirects[0].file());
    104                     std_fds[0] = f0.getFD().getInt$();
    105                 }
    106 
    107                 if (redirects[1] == Redirect.PIPE)
    108                     std_fds[1] = -1;
    109                 else if (redirects[1] == Redirect.INHERIT)
    110                     std_fds[1] = 1;
    111                 else {
    112                     f1 = new FileOutputStream(redirects[1].file(),
    113                                               redirects[1].append());
    114                     std_fds[1] = f1.getFD().getInt$();
    115                 }
    116 
    117                 if (redirects[2] == Redirect.PIPE)
    118                     std_fds[2] = -1;
    119                 else if (redirects[2] == Redirect.INHERIT)
    120                     std_fds[2] = 2;
    121                 else {
    122                     f2 = new FileOutputStream(redirects[2].file(),
    123                                               redirects[2].append());
    124                     std_fds[2] = f2.getFD().getInt$();
    125                 }
    126             }
    127 
    128         return new UNIXProcess
    129             (toCString(cmdarray[0]),
    130              argBlock, args.length,
    131              envBlock, envc[0],
    132              toCString(dir),
    133                  std_fds,
    134              redirectErrorStream);
    135         } finally {
    136             // In theory, close() can throw IOException
    137             // (although it is rather unlikely to happen here)
    138             try { if (f0 != null) f0.close(); }
    139             finally {
    140                 try { if (f1 != null) f1.close(); }
    141                 finally { if (f2 != null) f2.close(); }
    142             }
    143         }
    144     }
    145 }
    146