test/java/lang/ProcessBuilder/Basic.java

Print this page


   1 /*
   2  * Copyright (c) 2003, 2013, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */


 920         //----------------------------------------------------------------
 921         pb.inheritIO();
 922         checkRedirects(pb, INHERIT, INHERIT, INHERIT);
 923 
 924         //----------------------------------------------------------------
 925         // Check setters and getters agree
 926         //----------------------------------------------------------------
 927         pb.redirectInput(ifile);
 928         equal(pb.redirectInput().file(), ifile);
 929         equal(pb.redirectInput(), Redirect.from(ifile));
 930 
 931         pb.redirectOutput(ofile);
 932         equal(pb.redirectOutput().file(), ofile);
 933         equal(pb.redirectOutput(), Redirect.to(ofile));
 934 
 935         pb.redirectError(efile);
 936         equal(pb.redirectError().file(), efile);
 937         equal(pb.redirectError(), Redirect.to(efile));
 938 
 939         THROWS(IllegalArgumentException.class,
 940             new Fun(){void f() {
 941                 pb.redirectInput(Redirect.to(ofile)); }},
 942             new Fun(){void f() {
 943                 pb.redirectInput(Redirect.appendTo(ofile)); }},
 944             new Fun(){void f() {
 945                 pb.redirectOutput(Redirect.from(ifile)); }},
 946             new Fun(){void f() {
 947                 pb.redirectError(Redirect.from(ifile)); }});
 948 
 949         THROWS(IOException.class,
 950                // Input file does not exist
 951                new Fun(){void f() throws Throwable { pb.start(); }});
 952         setFileContents(ifile, "standard input");
 953 
 954         //----------------------------------------------------------------
 955         // Writing to non-existent files
 956         //----------------------------------------------------------------
 957         {
 958             ProcessResults r = run(pb);
 959             equal(r.exitValue(), 0);
 960             equal(fileContents(ofile), "standard output");
 961             equal(fileContents(efile), "standard error");
 962             equal(r.out(), "");
 963             equal(r.err(), "");
 964             ofile.delete();
 965             efile.delete();
 966         }
 967 
 968         //----------------------------------------------------------------
 969         // Both redirectErrorStream + redirectError
 970         //----------------------------------------------------------------
 971         {


1067 
1068         // Read access to current directory is always granted;
1069         // So create a tmpfile for input instead.
1070         final File tmpFile = File.createTempFile("Basic", "tmp");
1071         setFileContents(tmpFile, "standard input");
1072 
1073         final Policy policy = new Policy();
1074         Policy.setPolicy(policy);
1075         System.setSecurityManager(new SecurityManager());
1076         try {
1077             final Permission xPermission
1078                 = new FilePermission("<<ALL FILES>>", "execute");
1079             final Permission rxPermission
1080                 = new FilePermission("<<ALL FILES>>", "read,execute");
1081             final Permission wxPermission
1082                 = new FilePermission("<<ALL FILES>>", "write,execute");
1083             final Permission rwxPermission
1084                 = new FilePermission("<<ALL FILES>>", "read,write,execute");
1085 
1086             THROWS(SecurityException.class,
1087                new Fun() { void f() throws IOException {
1088                    policy.setPermissions(xPermission);
1089                    redirectIO(pb, from(tmpFile), PIPE, PIPE);
1090                    pb.start();}},
1091                new Fun() { void f() throws IOException {
1092                    policy.setPermissions(rxPermission);
1093                    redirectIO(pb, PIPE, to(ofile), PIPE);
1094                    pb.start();}},
1095                new Fun() { void f() throws IOException {
1096                    policy.setPermissions(rxPermission);
1097                    redirectIO(pb, PIPE, PIPE, to(efile));
1098                    pb.start();}});
1099 
1100             {
1101                 policy.setPermissions(rxPermission);
1102                 redirectIO(pb, from(tmpFile), PIPE, PIPE);
1103                 ProcessResults r = run(pb);
1104                 equal(r.out(), "standard output");
1105                 equal(r.err(), "standard error");
1106             }
1107 
1108             {
1109                 policy.setPermissions(wxPermission);
1110                 redirectIO(pb, PIPE, to(ofile), to(efile));
1111                 Process p = pb.start();
1112                 new PrintStream(p.getOutputStream()).print("standard input");
1113                 p.getOutputStream().close();
1114                 ProcessResults r = run(p);
1115                 policy.setPermissions(rwxPermission);
1116                 equal(fileContents(ofile), "standard output");
1117                 equal(fileContents(efile), "standard error");
1118             }


1241             if (Windows.is()) {
1242                 pb.environment().put("SystemRoot", systemRoot);
1243             }
1244             if (AIX.is()) {
1245                 pb.environment().put("LIBPATH", libpath);
1246             }
1247             String result = getenvInChild(pb);
1248             if (MacOSX.is()) {
1249                 result = removeMacExpectedVars(result);
1250             }
1251             if (AIX.is()) {
1252                 result = removeAixExpectedVars(result);
1253             }
1254             equal(result, expected);
1255         } catch (Throwable t) { unexpected(t); }
1256 
1257         //----------------------------------------------------------------
1258         // System.getenv() is read-only.
1259         //----------------------------------------------------------------
1260         THROWS(UnsupportedOperationException.class,
1261             new Fun(){void f(){ getenv().put("FOO","BAR");}},
1262             new Fun(){void f(){ getenv().remove("PATH");}},
1263             new Fun(){void f(){ getenv().keySet().remove("PATH");}},
1264             new Fun(){void f(){ getenv().values().remove("someValue");}});
1265 
1266         try {
1267             Collection<Map.Entry<String,String>> c = getenv().entrySet();
1268             if (! c.isEmpty())
1269                 try {
1270                     c.iterator().next().setValue("foo");
1271                     fail("Expected UnsupportedOperationException not thrown");
1272                 } catch (UnsupportedOperationException e) {} // OK
1273         } catch (Throwable t) { unexpected(t); }
1274 
1275         //----------------------------------------------------------------
1276         // System.getenv() always returns the same object in our implementation.
1277         //----------------------------------------------------------------
1278         try {
1279             check(System.getenv() == System.getenv());
1280         } catch (Throwable t) { unexpected(t); }
1281 
1282         //----------------------------------------------------------------
1283         // You can't create an env var name containing "=",
1284         // or an env var name or value containing NUL.
1285         //----------------------------------------------------------------
1286         {
1287             final Map<String,String> m = new ProcessBuilder().environment();
1288             THROWS(IllegalArgumentException.class,
1289                 new Fun(){void f(){ m.put("FOO=","BAR");}},
1290                 new Fun(){void f(){ m.put("FOO\u0000","BAR");}},
1291                 new Fun(){void f(){ m.put("FOO","BAR\u0000");}});
1292         }
1293 
1294         //----------------------------------------------------------------
1295         // Commands must never be null.
1296         //----------------------------------------------------------------
1297         THROWS(NullPointerException.class,
1298                new Fun(){void f(){
1299                    new ProcessBuilder((List<String>)null);}},
1300                new Fun(){void f(){
1301                    new ProcessBuilder().command((List<String>)null);}});
1302 
1303         //----------------------------------------------------------------
1304         // Put in a command; get the same one back out.
1305         //----------------------------------------------------------------
1306         try {
1307             List<String> command = new ArrayList<String>();
1308             ProcessBuilder pb = new ProcessBuilder(command);
1309             check(pb.command() == command);
1310             List<String> command2 = new ArrayList<String>(2);
1311             command2.add("foo");
1312             command2.add("bar");
1313             pb.command(command2);
1314             check(pb.command() == command2);
1315             pb.command("foo", "bar");
1316             check(pb.command() != command2 && pb.command().equals(command2));
1317             pb.command(command2);
1318             command2.add("baz");
1319             equal(pb.command().get(2), "baz");
1320         } catch (Throwable t) { unexpected(t); }
1321 
1322         //----------------------------------------------------------------
1323         // Commands must contain at least one element.
1324         //----------------------------------------------------------------
1325         THROWS(IndexOutOfBoundsException.class,
1326             new Fun() { void f() throws IOException {
1327                 new ProcessBuilder().start();}},
1328             new Fun() { void f() throws IOException {
1329                 new ProcessBuilder(new ArrayList<String>()).start();}},
1330             new Fun() { void f() throws IOException {
1331                 Runtime.getRuntime().exec(new String[]{});}});
1332 
1333         //----------------------------------------------------------------
1334         // Commands must not contain null elements at start() time.
1335         //----------------------------------------------------------------
1336         THROWS(NullPointerException.class,
1337             new Fun() { void f() throws IOException {
1338                 new ProcessBuilder("foo",null,"bar").start();}},
1339             new Fun() { void f() throws IOException {
1340                 new ProcessBuilder((String)null).start();}},
1341             new Fun() { void f() throws IOException {
1342                 new ProcessBuilder(new String[]{null}).start();}},
1343             new Fun() { void f() throws IOException {
1344                 new ProcessBuilder(new String[]{"foo",null,"bar"}).start();}});
1345 
1346         //----------------------------------------------------------------
1347         // Command lists are growable.
1348         //----------------------------------------------------------------
1349         try {
1350             new ProcessBuilder().command().add("foo");
1351             new ProcessBuilder("bar").command().add("foo");
1352             new ProcessBuilder(new String[]{"1","2"}).command().add("3");
1353         } catch (Throwable t) { unexpected(t); }
1354 
1355         //----------------------------------------------------------------
1356         // Nulls in environment updates generate NullPointerException
1357         //----------------------------------------------------------------
1358         try {
1359             final Map<String,String> env = new ProcessBuilder().environment();
1360             THROWS(NullPointerException.class,
1361                 new Fun(){void f(){ env.put("foo",null);}},
1362                 new Fun(){void f(){ env.put(null,"foo");}},
1363                 new Fun(){void f(){ env.remove(null);}},
1364                 new Fun(){void f(){
1365                     for (Map.Entry<String,String> e : env.entrySet())
1366                         e.setValue(null);}},
1367                 new Fun() { void f() throws IOException {
1368                     Runtime.getRuntime().exec(new String[]{"foo"},
1369                                               new String[]{null});}});
1370         } catch (Throwable t) { unexpected(t); }
1371 
1372         //----------------------------------------------------------------
1373         // Non-String types in environment updates generate ClassCastException
1374         //----------------------------------------------------------------
1375         try {
1376             final Map<String,String> env = new ProcessBuilder().environment();
1377             THROWS(ClassCastException.class,
1378                 new Fun(){void f(){ env.remove(TRUE);}},
1379                 new Fun(){void f(){ env.keySet().remove(TRUE);}},
1380                 new Fun(){void f(){ env.values().remove(TRUE);}},
1381                 new Fun(){void f(){ env.entrySet().remove(TRUE);}});
1382         } catch (Throwable t) { unexpected(t); }
1383 
1384         //----------------------------------------------------------------
1385         // Check query operations on environment maps
1386         //----------------------------------------------------------------
1387         try {
1388             List<Map<String,String>> envs =
1389                 new ArrayList<Map<String,String>>(2);
1390             envs.add(System.getenv());
1391             envs.add(new ProcessBuilder().environment());
1392             for (final Map<String,String> env : envs) {
1393                 //----------------------------------------------------------------
1394                 // Nulls in environment queries are forbidden.
1395                 //----------------------------------------------------------------
1396                 THROWS(NullPointerException.class,
1397                     new Fun(){void f(){ getenv(null);}},
1398                     new Fun(){void f(){ env.get(null);}},
1399                     new Fun(){void f(){ env.containsKey(null);}},
1400                     new Fun(){void f(){ env.containsValue(null);}},
1401                     new Fun(){void f(){ env.keySet().contains(null);}},
1402                     new Fun(){void f(){ env.values().contains(null);}});
1403 
1404                 //----------------------------------------------------------------
1405                 // Non-String types in environment queries are forbidden.
1406                 //----------------------------------------------------------------
1407                 THROWS(ClassCastException.class,
1408                     new Fun(){void f(){ env.get(TRUE);}},
1409                     new Fun(){void f(){ env.containsKey(TRUE);}},
1410                     new Fun(){void f(){ env.containsValue(TRUE);}},
1411                     new Fun(){void f(){ env.keySet().contains(TRUE);}},
1412                     new Fun(){void f(){ env.values().contains(TRUE);}});
1413 
1414                 //----------------------------------------------------------------
1415                 // Illegal String values in environment queries are (grumble) OK
1416                 //----------------------------------------------------------------
1417                 equal(env.get("\u0000"), null);
1418                 check(! env.containsKey("\u0000"));
1419                 check(! env.containsValue("\u0000"));
1420                 check(! env.keySet().contains("\u0000"));
1421                 check(! env.values().contains("\u0000"));
1422             }
1423 
1424         } catch (Throwable t) { unexpected(t); }
1425 
1426         try {
1427             final Set<Map.Entry<String,String>> entrySet =
1428                 new ProcessBuilder().environment().entrySet();
1429             THROWS(NullPointerException.class,
1430                    new Fun(){void f(){ entrySet.contains(null);}});
1431             THROWS(ClassCastException.class,
1432                 new Fun(){void f(){ entrySet.contains(TRUE);}},
1433                 new Fun(){void f(){
1434                     entrySet.contains(
1435                         new SimpleImmutableEntry<Boolean,String>(TRUE,""));}});
1436 
1437             check(! entrySet.contains
1438                   (new SimpleImmutableEntry<String,String>("", "")));
1439         } catch (Throwable t) { unexpected(t); }
1440 
1441         //----------------------------------------------------------------
1442         // Put in a directory; get the same one back out.
1443         //----------------------------------------------------------------
1444         try {
1445             ProcessBuilder pb = new ProcessBuilder();
1446             File foo = new File("foo");
1447             equal(pb.directory(), null);
1448             equal(pb.directory(foo).directory(), foo);
1449             equal(pb.directory(null).directory(), null);
1450         } catch (Throwable t) { unexpected(t); }
1451 
1452         //----------------------------------------------------------------
1453         // If round-trip conversion works, check envvar pass-through to child
1454         //----------------------------------------------------------------
1455         try {


1885             try {
1886                 List<String> childArgs = new ArrayList<String>(javaChildArgs);
1887                 childArgs.add("PATH search algorithm");
1888                 ProcessBuilder pb = new ProcessBuilder(childArgs);
1889                 pb.environment().put("PATH", "dir1:dir2:");
1890                 ProcessResults r = run(pb);
1891                 equal(r.out(), "");
1892                 equal(r.err(), "");
1893                 equal(r.exitValue(), True.exitValue());
1894             } catch (Throwable t) { unexpected(t); }
1895 
1896             //----------------------------------------------------------------
1897             // Parent's, not child's PATH is used
1898             //----------------------------------------------------------------
1899             try {
1900                 new File("suBdiR").mkdirs();
1901                 copy("/bin/true", "suBdiR/unliKely");
1902                 final ProcessBuilder pb =
1903                     new ProcessBuilder(new String[]{"unliKely"});
1904                 pb.environment().put("PATH", "suBdiR");
1905                 THROWS(IOException.class,
1906                        new Fun() {void f() throws Throwable {pb.start();}});
1907             } catch (Throwable t) { unexpected(t);
1908             } finally {
1909                 new File("suBdiR/unliKely").delete();
1910                 new File("suBdiR").delete();
1911             }
1912         }
1913 
1914         //----------------------------------------------------------------
1915         // Attempt to start bogus program ""
1916         //----------------------------------------------------------------
1917         try {
1918             new ProcessBuilder("").start();
1919             fail("Expected IOException not thrown");
1920         } catch (IOException e) {
1921             String m = e.getMessage();
1922             if (EnglishUnix.is() &&
1923                 ! matches(m, "No such file or directory"))
1924                 unexpected(e);
1925         } catch (Throwable t) { unexpected(t); }
1926 


1959 
1960         //----------------------------------------------------------------
1961         // Attempt to write 4095 bytes to the pipe buffer without a
1962         // reader to drain it would deadlock, if not for the fact that
1963         // interprocess pipe buffers are at least 4096 bytes.
1964         //
1965         // Also, check that available reports all the bytes expected
1966         // in the pipe buffer, and that I/O operations do the expected
1967         // things.
1968         //----------------------------------------------------------------
1969         try {
1970             List<String> childArgs = new ArrayList<String>(javaChildArgs);
1971             childArgs.add("print4095");
1972             final int SIZE = 4095;
1973             final Process p = new ProcessBuilder(childArgs).start();
1974             print4095(p.getOutputStream(), (byte) '!'); // Might hang!
1975             p.waitFor();                                // Might hang!
1976             equal(SIZE, p.getInputStream().available());
1977             equal(SIZE, p.getErrorStream().available());
1978             THROWS(IOException.class,
1979                    new Fun(){void f() throws IOException {
1980                        p.getOutputStream().write((byte) '!');
1981                        p.getOutputStream().flush();
1982                        }});
1983 
1984             final byte[] bytes = new byte[SIZE + 1];
1985             equal(SIZE, p.getInputStream().read(bytes));
1986             for (int i = 0; i < SIZE; i++)
1987                 equal((byte) '!', bytes[i]);
1988             equal((byte) 0, bytes[SIZE]);
1989 
1990             equal(SIZE, p.getErrorStream().read(bytes));
1991             for (int i = 0; i < SIZE; i++)
1992                 equal((byte) 'E', bytes[i]);
1993             equal((byte) 0, bytes[SIZE]);
1994 
1995             equal(0, p.getInputStream().available());
1996             equal(0, p.getErrorStream().available());
1997             equal(-1, p.getErrorStream().read());
1998             equal(-1, p.getInputStream().read());
1999 
2000             equal(p.exitValue(), 5);
2001 
2002             p.getInputStream().close();
2003             p.getErrorStream().close();
2004             try { p.getOutputStream().close(); } catch (IOException flushFailed) { }
2005 
2006             InputStream[] streams = { p.getInputStream(), p.getErrorStream() };
2007             for (final InputStream in : streams) {
2008                 Fun[] ops = {
2009                     new Fun(){void f() throws IOException {
2010                         in.read(); }},
2011                     new Fun(){void f() throws IOException {
2012                         in.read(bytes); }},
2013                     new Fun(){void f() throws IOException {
2014                         in.available(); }}
2015                 };
2016                 for (Fun op : ops) {
2017                     try {
2018                         op.f();
2019                         fail();
2020                     } catch (IOException expected) {
2021                         check(expected.getMessage()
2022                               .matches("[Ss]tream [Cc]losed"));
2023                     }
2024                 }
2025             }
2026         } catch (Throwable t) { unexpected(t); }
2027 
2028         //----------------------------------------------------------------
2029         // Check that reads which are pending when Process.destroy is
2030         // called, get EOF, not IOException("Stream closed").
2031         //----------------------------------------------------------------
2032         try {
2033             final int cases = 4;
2034             for (int i = 0; i < cases; i++) {


2198         } catch (Throwable t) { unexpected(t); }
2199 
2200         new File("emptyCommand").delete();
2201 
2202         //----------------------------------------------------------------
2203         // Check for correct security permission behavior
2204         //----------------------------------------------------------------
2205         final Policy policy = new Policy();
2206         Policy.setPolicy(policy);
2207         System.setSecurityManager(new SecurityManager());
2208 
2209         try {
2210             // No permissions required to CREATE a ProcessBuilder
2211             policy.setPermissions(/* Nothing */);
2212             new ProcessBuilder("env").directory(null).directory();
2213             new ProcessBuilder("env").directory(new File("dir")).directory();
2214             new ProcessBuilder("env").command("??").command();
2215         } catch (Throwable t) { unexpected(t); }
2216 
2217         THROWS(SecurityException.class,
2218             new Fun() { void f() throws IOException {
2219                 policy.setPermissions(/* Nothing */);
2220                 System.getenv("foo");}},
2221             new Fun() { void f() throws IOException {
2222                 policy.setPermissions(/* Nothing */);
2223                 System.getenv();}},
2224             new Fun() { void f() throws IOException {
2225                 policy.setPermissions(/* Nothing */);
2226                 new ProcessBuilder("echo").start();}},
2227             new Fun() { void f() throws IOException {
2228                 policy.setPermissions(/* Nothing */);
2229                 Runtime.getRuntime().exec("echo");}},
2230             new Fun() { void f() throws IOException {
2231                 policy.setPermissions(new RuntimePermission("getenv.bar"));
2232                 System.getenv("foo");}});
2233 
2234         try {
2235             policy.setPermissions(new RuntimePermission("getenv.foo"));
2236             System.getenv("foo");
2237 
2238             policy.setPermissions(new RuntimePermission("getenv.*"));
2239             System.getenv("foo");
2240             System.getenv();
2241             new ProcessBuilder().environment();
2242         } catch (Throwable t) { unexpected(t); }
2243 
2244 
2245         final Permission execPermission
2246             = new FilePermission("<<ALL FILES>>", "execute");
2247 
2248         THROWS(SecurityException.class,
2249             new Fun() { void f() throws IOException {
2250                 // environment permission by itself insufficient
2251                 policy.setPermissions(new RuntimePermission("getenv.*"));
2252                 ProcessBuilder pb = new ProcessBuilder("env");
2253                 pb.environment().put("foo","bar");
2254                 pb.start();}},
2255             new Fun() { void f() throws IOException {
2256                  // exec permission by itself insufficient
2257                  policy.setPermissions(execPermission);
2258                  ProcessBuilder pb = new ProcessBuilder("env");
2259                  pb.environment().put("foo","bar");
2260                  pb.start();}});
2261 
2262         try {
2263             // Both permissions? OK.
2264             policy.setPermissions(new RuntimePermission("getenv.*"),
2265                                   execPermission);
2266             ProcessBuilder pb = new ProcessBuilder("env");
2267             pb.environment().put("foo","bar");
2268             Process p = pb.start();
2269             closeStreams(p);
2270         } catch (IOException e) { // OK
2271         } catch (Throwable t) { unexpected(t); }
2272 
2273         try {
2274             // Don't need environment permission unless READING environment
2275             policy.setPermissions(execPermission);
2276             Runtime.getRuntime().exec("env", new String[]{});
2277         } catch (IOException e) { // OK
2278         } catch (Throwable t) { unexpected(t); }
2279 
2280         try {


2568             return sb.toString();
2569         }
2570     }
2571 
2572     //--------------------- Infrastructure ---------------------------
2573     static volatile int passed = 0, failed = 0;
2574     static void pass() {passed++;}
2575     static void fail() {failed++; Thread.dumpStack();}
2576     static void fail(String msg) {System.out.println(msg); fail();}
2577     static void unexpected(Throwable t) {failed++; t.printStackTrace();}
2578     static void check(boolean cond) {if (cond) pass(); else fail();}
2579     static void check(boolean cond, String m) {if (cond) pass(); else fail(m);}
2580     static void equal(Object x, Object y) {
2581         if (x == null ? y == null : x.equals(y)) pass();
2582         else fail(">'" + x + "'<" + " not equal to " + "'" + y + "'");}
2583 
2584     public static void main(String[] args) throws Throwable {
2585         try {realMain(args);} catch (Throwable t) {unexpected(t);}
2586         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
2587         if (failed > 0) throw new AssertionError("Some tests failed");}
2588     private static abstract class Fun {abstract void f() throws Throwable;}
2589     static void THROWS(Class<? extends Throwable> k, Fun... fs) {
2590         for (Fun f : fs)
2591             try { f.f(); fail("Expected " + k.getName() + " not thrown"); }
2592             catch (Throwable t) {
2593                 if (k.isAssignableFrom(t.getClass())) pass();
2594                 else unexpected(t);}}
2595 }
   1 /*
   2  * Copyright (c) 2003, 2014, 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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */


 920         //----------------------------------------------------------------
 921         pb.inheritIO();
 922         checkRedirects(pb, INHERIT, INHERIT, INHERIT);
 923 
 924         //----------------------------------------------------------------
 925         // Check setters and getters agree
 926         //----------------------------------------------------------------
 927         pb.redirectInput(ifile);
 928         equal(pb.redirectInput().file(), ifile);
 929         equal(pb.redirectInput(), Redirect.from(ifile));
 930 
 931         pb.redirectOutput(ofile);
 932         equal(pb.redirectOutput().file(), ofile);
 933         equal(pb.redirectOutput(), Redirect.to(ofile));
 934 
 935         pb.redirectError(efile);
 936         equal(pb.redirectError().file(), efile);
 937         equal(pb.redirectError(), Redirect.to(efile));
 938 
 939         THROWS(IllegalArgumentException.class,
 940                () -> pb.redirectInput(Redirect.to(ofile)),
 941                () -> pb.redirectOutput(Redirect.from(ifile)),
 942                () -> pb.redirectError(Redirect.from(ifile)));





 943 
 944         THROWS(IOException.class,
 945                // Input file does not exist
 946                () -> pb.start());
 947         setFileContents(ifile, "standard input");
 948 
 949         //----------------------------------------------------------------
 950         // Writing to non-existent files
 951         //----------------------------------------------------------------
 952         {
 953             ProcessResults r = run(pb);
 954             equal(r.exitValue(), 0);
 955             equal(fileContents(ofile), "standard output");
 956             equal(fileContents(efile), "standard error");
 957             equal(r.out(), "");
 958             equal(r.err(), "");
 959             ofile.delete();
 960             efile.delete();
 961         }
 962 
 963         //----------------------------------------------------------------
 964         // Both redirectErrorStream + redirectError
 965         //----------------------------------------------------------------
 966         {


1062 
1063         // Read access to current directory is always granted;
1064         // So create a tmpfile for input instead.
1065         final File tmpFile = File.createTempFile("Basic", "tmp");
1066         setFileContents(tmpFile, "standard input");
1067 
1068         final Policy policy = new Policy();
1069         Policy.setPolicy(policy);
1070         System.setSecurityManager(new SecurityManager());
1071         try {
1072             final Permission xPermission
1073                 = new FilePermission("<<ALL FILES>>", "execute");
1074             final Permission rxPermission
1075                 = new FilePermission("<<ALL FILES>>", "read,execute");
1076             final Permission wxPermission
1077                 = new FilePermission("<<ALL FILES>>", "write,execute");
1078             final Permission rwxPermission
1079                 = new FilePermission("<<ALL FILES>>", "read,write,execute");
1080 
1081             THROWS(SecurityException.class,
1082                    () -> { policy.setPermissions(xPermission);

1083                            redirectIO(pb, from(tmpFile), PIPE, PIPE);
1084                            pb.start();},
1085                    () -> { policy.setPermissions(rxPermission);

1086                            redirectIO(pb, PIPE, to(ofile), PIPE);
1087                            pb.start();},
1088                    () -> { policy.setPermissions(rxPermission);

1089                            redirectIO(pb, PIPE, PIPE, to(efile));
1090                            pb.start();});
1091 
1092             {
1093                 policy.setPermissions(rxPermission);
1094                 redirectIO(pb, from(tmpFile), PIPE, PIPE);
1095                 ProcessResults r = run(pb);
1096                 equal(r.out(), "standard output");
1097                 equal(r.err(), "standard error");
1098             }
1099 
1100             {
1101                 policy.setPermissions(wxPermission);
1102                 redirectIO(pb, PIPE, to(ofile), to(efile));
1103                 Process p = pb.start();
1104                 new PrintStream(p.getOutputStream()).print("standard input");
1105                 p.getOutputStream().close();
1106                 ProcessResults r = run(p);
1107                 policy.setPermissions(rwxPermission);
1108                 equal(fileContents(ofile), "standard output");
1109                 equal(fileContents(efile), "standard error");
1110             }


1233             if (Windows.is()) {
1234                 pb.environment().put("SystemRoot", systemRoot);
1235             }
1236             if (AIX.is()) {
1237                 pb.environment().put("LIBPATH", libpath);
1238             }
1239             String result = getenvInChild(pb);
1240             if (MacOSX.is()) {
1241                 result = removeMacExpectedVars(result);
1242             }
1243             if (AIX.is()) {
1244                 result = removeAixExpectedVars(result);
1245             }
1246             equal(result, expected);
1247         } catch (Throwable t) { unexpected(t); }
1248 
1249         //----------------------------------------------------------------
1250         // System.getenv() is read-only.
1251         //----------------------------------------------------------------
1252         THROWS(UnsupportedOperationException.class,
1253                () -> getenv().put("FOO","BAR"),
1254                () -> getenv().remove("PATH"),
1255                () -> getenv().keySet().remove("PATH"),
1256                () -> getenv().values().remove("someValue"));
1257 
1258         try {
1259             Collection<Map.Entry<String,String>> c = getenv().entrySet();
1260             if (! c.isEmpty())
1261                 try {
1262                     c.iterator().next().setValue("foo");
1263                     fail("Expected UnsupportedOperationException not thrown");
1264                 } catch (UnsupportedOperationException e) {} // OK
1265         } catch (Throwable t) { unexpected(t); }
1266 
1267         //----------------------------------------------------------------
1268         // System.getenv() always returns the same object in our implementation.
1269         //----------------------------------------------------------------
1270         try {
1271             check(System.getenv() == System.getenv());
1272         } catch (Throwable t) { unexpected(t); }
1273 
1274         //----------------------------------------------------------------
1275         // You can't create an env var name containing "=",
1276         // or an env var name or value containing NUL.
1277         //----------------------------------------------------------------
1278         {
1279             final Map<String,String> m = new ProcessBuilder().environment();
1280             THROWS(IllegalArgumentException.class,
1281                    () -> m.put("FOO=","BAR"),
1282                    () -> m.put("FOO\u0000","BAR"),
1283                    () -> m.put("FOO","BAR\u0000"));
1284         }
1285 
1286         //----------------------------------------------------------------
1287         // Commands must never be null.
1288         //----------------------------------------------------------------
1289         THROWS(NullPointerException.class,
1290                () -> new ProcessBuilder((List<String>)null),
1291                () -> new ProcessBuilder().command((List<String>)null));


1292 
1293         //----------------------------------------------------------------
1294         // Put in a command; get the same one back out.
1295         //----------------------------------------------------------------
1296         try {
1297             List<String> command = new ArrayList<String>();
1298             ProcessBuilder pb = new ProcessBuilder(command);
1299             check(pb.command() == command);
1300             List<String> command2 = new ArrayList<String>(2);
1301             command2.add("foo");
1302             command2.add("bar");
1303             pb.command(command2);
1304             check(pb.command() == command2);
1305             pb.command("foo", "bar");
1306             check(pb.command() != command2 && pb.command().equals(command2));
1307             pb.command(command2);
1308             command2.add("baz");
1309             equal(pb.command().get(2), "baz");
1310         } catch (Throwable t) { unexpected(t); }
1311 
1312         //----------------------------------------------------------------
1313         // Commands must contain at least one element.
1314         //----------------------------------------------------------------
1315         THROWS(IndexOutOfBoundsException.class,
1316                () -> new ProcessBuilder().start(),
1317                () -> new ProcessBuilder(new ArrayList<String>()).start(),
1318                () -> Runtime.getRuntime().exec(new String[]{}));



1319 
1320         //----------------------------------------------------------------
1321         // Commands must not contain null elements at start() time.
1322         //----------------------------------------------------------------
1323         THROWS(NullPointerException.class,
1324                () -> new ProcessBuilder("foo",null,"bar").start(),
1325                () -> new ProcessBuilder((String)null).start(),
1326                () -> new ProcessBuilder(new String[]{null}).start(),
1327                () -> new ProcessBuilder(new String[]{"foo",null,"bar"}).start());




1328 
1329         //----------------------------------------------------------------
1330         // Command lists are growable.
1331         //----------------------------------------------------------------
1332         try {
1333             new ProcessBuilder().command().add("foo");
1334             new ProcessBuilder("bar").command().add("foo");
1335             new ProcessBuilder(new String[]{"1","2"}).command().add("3");
1336         } catch (Throwable t) { unexpected(t); }
1337 
1338         //----------------------------------------------------------------
1339         // Nulls in environment updates generate NullPointerException
1340         //----------------------------------------------------------------
1341         try {
1342             final Map<String,String> env = new ProcessBuilder().environment();
1343             THROWS(NullPointerException.class,
1344                    () -> env.put("foo",null),
1345                    () -> env.put(null,"foo"),
1346                    () -> env.remove(null),
1347                    () -> { for (Map.Entry<String,String> e : env.entrySet())
1348                                e.setValue(null);},
1349                    () -> Runtime.getRuntime().exec(new String[]{"foo"},
1350                                                    new String[]{null}));


1351         } catch (Throwable t) { unexpected(t); }
1352 
1353         //----------------------------------------------------------------
1354         // Non-String types in environment updates generate ClassCastException
1355         //----------------------------------------------------------------
1356         try {
1357             final Map<String,String> env = new ProcessBuilder().environment();
1358             THROWS(ClassCastException.class,
1359                    () -> env.remove(TRUE),
1360                    () -> env.keySet().remove(TRUE),
1361                    () -> env.values().remove(TRUE),
1362                    () -> env.entrySet().remove(TRUE));
1363         } catch (Throwable t) { unexpected(t); }
1364 
1365         //----------------------------------------------------------------
1366         // Check query operations on environment maps
1367         //----------------------------------------------------------------
1368         try {
1369             List<Map<String,String>> envs =
1370                 new ArrayList<Map<String,String>>(2);
1371             envs.add(System.getenv());
1372             envs.add(new ProcessBuilder().environment());
1373             for (final Map<String,String> env : envs) {
1374                 //----------------------------------------------------------------
1375                 // Nulls in environment queries are forbidden.
1376                 //----------------------------------------------------------------
1377                 THROWS(NullPointerException.class,
1378                        () -> getenv(null),
1379                        () -> env.get(null),
1380                        () -> env.containsKey(null),
1381                        () -> env.containsValue(null),
1382                        () -> env.keySet().contains(null),
1383                        () -> env.values().contains(null));
1384 
1385                 //----------------------------------------------------------------
1386                 // Non-String types in environment queries are forbidden.
1387                 //----------------------------------------------------------------
1388                 THROWS(ClassCastException.class,
1389                        () -> env.get(TRUE),
1390                        () -> env.containsKey(TRUE),
1391                        () -> env.containsValue(TRUE),
1392                        () -> env.keySet().contains(TRUE),
1393                        () -> env.values().contains(TRUE));
1394 
1395                 //----------------------------------------------------------------
1396                 // Illegal String values in environment queries are (grumble) OK
1397                 //----------------------------------------------------------------
1398                 equal(env.get("\u0000"), null);
1399                 check(! env.containsKey("\u0000"));
1400                 check(! env.containsValue("\u0000"));
1401                 check(! env.keySet().contains("\u0000"));
1402                 check(! env.values().contains("\u0000"));
1403             }
1404 
1405         } catch (Throwable t) { unexpected(t); }
1406 
1407         try {
1408             final Set<Map.Entry<String,String>> entrySet =
1409                 new ProcessBuilder().environment().entrySet();
1410             THROWS(NullPointerException.class,
1411                    () -> entrySet.contains(null));
1412             THROWS(ClassCastException.class,
1413                    () -> entrySet.contains(TRUE),
1414                    () -> entrySet.contains(
1415                              new SimpleImmutableEntry<Boolean,String>(TRUE,"")));

1416 
1417             check(! entrySet.contains
1418                   (new SimpleImmutableEntry<String,String>("", "")));
1419         } catch (Throwable t) { unexpected(t); }
1420 
1421         //----------------------------------------------------------------
1422         // Put in a directory; get the same one back out.
1423         //----------------------------------------------------------------
1424         try {
1425             ProcessBuilder pb = new ProcessBuilder();
1426             File foo = new File("foo");
1427             equal(pb.directory(), null);
1428             equal(pb.directory(foo).directory(), foo);
1429             equal(pb.directory(null).directory(), null);
1430         } catch (Throwable t) { unexpected(t); }
1431 
1432         //----------------------------------------------------------------
1433         // If round-trip conversion works, check envvar pass-through to child
1434         //----------------------------------------------------------------
1435         try {


1865             try {
1866                 List<String> childArgs = new ArrayList<String>(javaChildArgs);
1867                 childArgs.add("PATH search algorithm");
1868                 ProcessBuilder pb = new ProcessBuilder(childArgs);
1869                 pb.environment().put("PATH", "dir1:dir2:");
1870                 ProcessResults r = run(pb);
1871                 equal(r.out(), "");
1872                 equal(r.err(), "");
1873                 equal(r.exitValue(), True.exitValue());
1874             } catch (Throwable t) { unexpected(t); }
1875 
1876             //----------------------------------------------------------------
1877             // Parent's, not child's PATH is used
1878             //----------------------------------------------------------------
1879             try {
1880                 new File("suBdiR").mkdirs();
1881                 copy("/bin/true", "suBdiR/unliKely");
1882                 final ProcessBuilder pb =
1883                     new ProcessBuilder(new String[]{"unliKely"});
1884                 pb.environment().put("PATH", "suBdiR");
1885                 THROWS(IOException.class, () -> pb.start());

1886             } catch (Throwable t) { unexpected(t);
1887             } finally {
1888                 new File("suBdiR/unliKely").delete();
1889                 new File("suBdiR").delete();
1890             }
1891         }
1892 
1893         //----------------------------------------------------------------
1894         // Attempt to start bogus program ""
1895         //----------------------------------------------------------------
1896         try {
1897             new ProcessBuilder("").start();
1898             fail("Expected IOException not thrown");
1899         } catch (IOException e) {
1900             String m = e.getMessage();
1901             if (EnglishUnix.is() &&
1902                 ! matches(m, "No such file or directory"))
1903                 unexpected(e);
1904         } catch (Throwable t) { unexpected(t); }
1905 


1938 
1939         //----------------------------------------------------------------
1940         // Attempt to write 4095 bytes to the pipe buffer without a
1941         // reader to drain it would deadlock, if not for the fact that
1942         // interprocess pipe buffers are at least 4096 bytes.
1943         //
1944         // Also, check that available reports all the bytes expected
1945         // in the pipe buffer, and that I/O operations do the expected
1946         // things.
1947         //----------------------------------------------------------------
1948         try {
1949             List<String> childArgs = new ArrayList<String>(javaChildArgs);
1950             childArgs.add("print4095");
1951             final int SIZE = 4095;
1952             final Process p = new ProcessBuilder(childArgs).start();
1953             print4095(p.getOutputStream(), (byte) '!'); // Might hang!
1954             p.waitFor();                                // Might hang!
1955             equal(SIZE, p.getInputStream().available());
1956             equal(SIZE, p.getErrorStream().available());
1957             THROWS(IOException.class,
1958                    () -> { p.getOutputStream().write((byte) '!');
1959                            p.getOutputStream().flush();});


1960 
1961             final byte[] bytes = new byte[SIZE + 1];
1962             equal(SIZE, p.getInputStream().read(bytes));
1963             for (int i = 0; i < SIZE; i++)
1964                 equal((byte) '!', bytes[i]);
1965             equal((byte) 0, bytes[SIZE]);
1966 
1967             equal(SIZE, p.getErrorStream().read(bytes));
1968             for (int i = 0; i < SIZE; i++)
1969                 equal((byte) 'E', bytes[i]);
1970             equal((byte) 0, bytes[SIZE]);
1971 
1972             equal(0, p.getInputStream().available());
1973             equal(0, p.getErrorStream().available());
1974             equal(-1, p.getErrorStream().read());
1975             equal(-1, p.getInputStream().read());
1976 
1977             equal(p.exitValue(), 5);
1978 
1979             p.getInputStream().close();
1980             p.getErrorStream().close();
1981             try { p.getOutputStream().close(); } catch (IOException flushFailed) { }
1982 
1983             InputStream[] streams = { p.getInputStream(), p.getErrorStream() };
1984             for (final InputStream in : streams) {
1985                 Fun[] ops = {
1986                     () -> in.read(),
1987                     () -> in.read(bytes),
1988                     () -> in.available()



1989                 };
1990                 for (Fun op : ops) {
1991                     try {
1992                         op.f();
1993                         fail();
1994                     } catch (IOException expected) {
1995                         check(expected.getMessage()
1996                               .matches("[Ss]tream [Cc]losed"));
1997                     }
1998                 }
1999             }
2000         } catch (Throwable t) { unexpected(t); }
2001 
2002         //----------------------------------------------------------------
2003         // Check that reads which are pending when Process.destroy is
2004         // called, get EOF, not IOException("Stream closed").
2005         //----------------------------------------------------------------
2006         try {
2007             final int cases = 4;
2008             for (int i = 0; i < cases; i++) {


2172         } catch (Throwable t) { unexpected(t); }
2173 
2174         new File("emptyCommand").delete();
2175 
2176         //----------------------------------------------------------------
2177         // Check for correct security permission behavior
2178         //----------------------------------------------------------------
2179         final Policy policy = new Policy();
2180         Policy.setPolicy(policy);
2181         System.setSecurityManager(new SecurityManager());
2182 
2183         try {
2184             // No permissions required to CREATE a ProcessBuilder
2185             policy.setPermissions(/* Nothing */);
2186             new ProcessBuilder("env").directory(null).directory();
2187             new ProcessBuilder("env").directory(new File("dir")).directory();
2188             new ProcessBuilder("env").command("??").command();
2189         } catch (Throwable t) { unexpected(t); }
2190 
2191         THROWS(SecurityException.class,
2192                () -> { policy.setPermissions(/* Nothing */);
2193                        System.getenv("foo");},
2194                () -> { policy.setPermissions(/* Nothing */);
2195                        System.getenv();},
2196                () -> { policy.setPermissions(/* Nothing */);
2197                        new ProcessBuilder("echo").start();},
2198                () -> { policy.setPermissions(/* Nothing */);
2199                        Runtime.getRuntime().exec("echo");},
2200                () -> { policy.setPermissions(
2201                                new RuntimePermission("getenv.bar"));
2202                        System.getenv("foo");});




2203 
2204         try {
2205             policy.setPermissions(new RuntimePermission("getenv.foo"));
2206             System.getenv("foo");
2207 
2208             policy.setPermissions(new RuntimePermission("getenv.*"));
2209             System.getenv("foo");
2210             System.getenv();
2211             new ProcessBuilder().environment();
2212         } catch (Throwable t) { unexpected(t); }
2213 
2214 
2215         final Permission execPermission
2216             = new FilePermission("<<ALL FILES>>", "execute");
2217 
2218         THROWS(SecurityException.class,
2219                () -> { // environment permission by itself insufficient

2220                        policy.setPermissions(new RuntimePermission("getenv.*"));
2221                        ProcessBuilder pb = new ProcessBuilder("env");
2222                        pb.environment().put("foo","bar");
2223                        pb.start();},
2224                () -> { // exec permission by itself insufficient

2225                        policy.setPermissions(execPermission);
2226                        ProcessBuilder pb = new ProcessBuilder("env");
2227                        pb.environment().put("foo","bar");
2228                        pb.start();});
2229 
2230         try {
2231             // Both permissions? OK.
2232             policy.setPermissions(new RuntimePermission("getenv.*"),
2233                                   execPermission);
2234             ProcessBuilder pb = new ProcessBuilder("env");
2235             pb.environment().put("foo","bar");
2236             Process p = pb.start();
2237             closeStreams(p);
2238         } catch (IOException e) { // OK
2239         } catch (Throwable t) { unexpected(t); }
2240 
2241         try {
2242             // Don't need environment permission unless READING environment
2243             policy.setPermissions(execPermission);
2244             Runtime.getRuntime().exec("env", new String[]{});
2245         } catch (IOException e) { // OK
2246         } catch (Throwable t) { unexpected(t); }
2247 
2248         try {


2536             return sb.toString();
2537         }
2538     }
2539 
2540     //--------------------- Infrastructure ---------------------------
2541     static volatile int passed = 0, failed = 0;
2542     static void pass() {passed++;}
2543     static void fail() {failed++; Thread.dumpStack();}
2544     static void fail(String msg) {System.out.println(msg); fail();}
2545     static void unexpected(Throwable t) {failed++; t.printStackTrace();}
2546     static void check(boolean cond) {if (cond) pass(); else fail();}
2547     static void check(boolean cond, String m) {if (cond) pass(); else fail(m);}
2548     static void equal(Object x, Object y) {
2549         if (x == null ? y == null : x.equals(y)) pass();
2550         else fail(">'" + x + "'<" + " not equal to " + "'" + y + "'");}
2551 
2552     public static void main(String[] args) throws Throwable {
2553         try {realMain(args);} catch (Throwable t) {unexpected(t);}
2554         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
2555         if (failed > 0) throw new AssertionError("Some tests failed");}
2556     @FunctionalInterface interface Fun {void f() throws Throwable;}
2557     static void THROWS(Class<? extends Throwable> k, Fun... fs) {
2558         for (Fun f : fs)
2559             try { f.f(); fail("Expected " + k.getName() + " not thrown"); }
2560             catch (Throwable t) {
2561                 if (k.isAssignableFrom(t.getClass())) pass();
2562                 else unexpected(t);}}
2563 }