57 import java.util.concurrent.TimeUnit;
58 import java.security.*;
59 import java.util.regex.Pattern;
60 import java.util.regex.Matcher;
61 import static java.lang.System.getenv;
62 import static java.lang.System.out;
63 import static java.lang.Boolean.TRUE;
64 import static java.util.AbstractMap.SimpleImmutableEntry;
65
66 public class Basic {
67
68 /* used for Windows only */
69 static final String systemRoot = System.getenv("SystemRoot");
70
71 /* used for Mac OS X only */
72 static final String cfUserTextEncoding = System.getenv("__CF_USER_TEXT_ENCODING");
73
74 /* used for AIX only */
75 static final String libpath = System.getenv("LIBPATH");
76
77 /**
78 * Returns the number of milliseconds since time given by
79 * startNanoTime, which must have been previously returned from a
80 * call to {@link System.nanoTime()}.
81 */
82 private static long millisElapsedSince(long startNanoTime) {
83 return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanoTime);
84 }
85
86 private static String commandOutput(Reader r) throws Throwable {
87 StringBuilder sb = new StringBuilder();
88 int c;
89 while ((c = r.read()) > 0)
90 if (c != '\r')
91 sb.append((char) c);
92 return sb.toString();
93 }
94
95 private static String commandOutput(Process p) throws Throwable {
96 check(p.getInputStream() == p.getInputStream());
288 sb.append(e.getKey())
289 .append('=')
290 .append(e.getValue())
291 .append(',');
292 return sb.toString();
293 }
294
295 static void print4095(OutputStream s, byte b) throws Throwable {
296 byte[] bytes = new byte[4095];
297 Arrays.fill(bytes, b);
298 s.write(bytes); // Might hang!
299 }
300
301 static void checkPermissionDenied(ProcessBuilder pb) {
302 try {
303 pb.start();
304 fail("Expected IOException not thrown");
305 } catch (IOException e) {
306 String m = e.getMessage();
307 if (EnglishUnix.is() &&
308 ! matches(m, "Permission denied"))
309 unexpected(e);
310 } catch (Throwable t) { unexpected(t); }
311 }
312
313 public static class JavaChild {
314 public static void main(String args[]) throws Throwable {
315 String action = args[0];
316 if (action.equals("sleep")) {
317 Thread.sleep(10 * 60 * 1000L);
318 } else if (action.equals("pid")) {
319 System.out.println(ProcessHandle.current().pid());
320 } else if (action.equals("testIO")) {
321 String expected = "standard input";
322 char[] buf = new char[expected.length()+1];
323 int n = new InputStreamReader(System.in).read(buf,0,buf.length);
324 if (n != expected.length())
325 System.exit(5);
326 if (! new String(buf,0,n).equals(expected))
327 System.exit(5);
328 System.err.print("standard error");
398 equal(System.getenv("PATH"), "dir1:dir2:");
399 check(new File("/bin/true").exists());
400 check(new File("/bin/false").exists());
401 String[] cmd = {"prog"};
402 ProcessBuilder pb1 = new ProcessBuilder(cmd);
403 ProcessBuilder pb2 = new ProcessBuilder(cmd);
404 ProcessBuilder pb3 = new ProcessBuilder(cmd);
405 pb2.environment().put("PATH", "anyOldPathIgnoredAnyways");
406 pb3.environment().remove("PATH");
407
408 for (final ProcessBuilder pb :
409 new ProcessBuilder[] {pb1, pb2, pb3}) {
410 try {
411 // Not on PATH at all; directories don't exist
412 try {
413 pb.start();
414 fail("Expected IOException not thrown");
415 } catch (IOException e) {
416 String m = e.getMessage();
417 if (EnglishUnix.is() &&
418 ! matches(m, "No such file"))
419 unexpected(e);
420 } catch (Throwable t) { unexpected(t); }
421
422 // Not on PATH at all; directories exist
423 new File("dir1").mkdirs();
424 new File("dir2").mkdirs();
425 try {
426 pb.start();
427 fail("Expected IOException not thrown");
428 } catch (IOException e) {
429 String m = e.getMessage();
430 if (EnglishUnix.is() &&
431 ! matches(m, "No such file"))
432 unexpected(e);
433 } catch (Throwable t) { unexpected(t); }
434
435 // Can't execute a directory -- permission denied
436 // Report EACCES errno
437 new File("dir1/prog").mkdirs();
438 checkPermissionDenied(pb);
439
440 // continue searching if EACCES
441 copy("/bin/true", "dir2/prog");
442 equal(run(pb).exitValue(), True.exitValue());
443 new File("dir1/prog").delete();
444 new File("dir2/prog").delete();
445
446 new File("dir2/prog").mkdirs();
447 copy("/bin/true", "dir1/prog");
448 equal(run(pb).exitValue(), True.exitValue());
449
450 // Check empty PATH component means current directory.
451 //
1965 final ProcessBuilder pb =
1966 new ProcessBuilder(new String[]{"unliKely"});
1967 pb.environment().put("PATH", "suBdiR");
1968 THROWS(IOException.class, () -> pb.start());
1969 } catch (Throwable t) { unexpected(t);
1970 } finally {
1971 new File("suBdiR/unliKely").delete();
1972 new File("suBdiR").delete();
1973 }
1974 }
1975
1976 //----------------------------------------------------------------
1977 // Attempt to start bogus program ""
1978 //----------------------------------------------------------------
1979 try {
1980 new ProcessBuilder("").start();
1981 fail("Expected IOException not thrown");
1982 } catch (IOException e) {
1983 String m = e.getMessage();
1984 if (EnglishUnix.is() &&
1985 ! matches(m, "No such file or directory"))
1986 unexpected(e);
1987 } catch (Throwable t) { unexpected(t); }
1988
1989 //----------------------------------------------------------------
1990 // Check that attempt to execute program name with funny
1991 // characters throws an exception containing those characters.
1992 //----------------------------------------------------------------
1993 for (String programName : new String[] {"\u00f0", "\u01f0"})
1994 try {
1995 new ProcessBuilder(programName).start();
1996 fail("Expected IOException not thrown");
1997 } catch (IOException e) {
1998 String m = e.getMessage();
1999 Pattern p = Pattern.compile(programName);
2000 if (! matches(m, programName)
2001 || (EnglishUnix.is()
2002 && ! matches(m, "No such file or directory")))
2003 unexpected(e);
2004 } catch (Throwable t) { unexpected(t); }
2005
2006 //----------------------------------------------------------------
2007 // Attempt to start process in nonexistent directory fails.
2008 //----------------------------------------------------------------
2009 try {
2010 new ProcessBuilder("echo")
2011 .directory(new File("UnLiKeLY"))
2012 .start();
2013 fail("Expected IOException not thrown");
2014 } catch (IOException e) {
2015 String m = e.getMessage();
2016 if (! matches(m, "in directory")
2017 || (EnglishUnix.is() &&
2018 ! matches(m, "No such file or directory")))
2019 unexpected(e);
2020 } catch (Throwable t) { unexpected(t); }
2021
2022 //----------------------------------------------------------------
2023 // Attempt to write 4095 bytes to the pipe buffer without a
2024 // reader to drain it would deadlock, if not for the fact that
2025 // interprocess pipe buffers are at least 4096 bytes.
2026 //
2027 // Also, check that available reports all the bytes expected
2028 // in the pipe buffer, and that I/O operations do the expected
2029 // things.
2030 //----------------------------------------------------------------
2031 try {
2032 List<String> childArgs = new ArrayList<String>(javaChildArgs);
2033 childArgs.add("print4095");
2034 final int SIZE = 4095;
2035 final Process p = new ProcessBuilder(childArgs).start();
2036 print4095(p.getOutputStream(), (byte) '!'); // Might hang!
2037 p.waitFor(); // Might hang!
2038 equal(SIZE, p.getInputStream().available());
2278 s = p.toString();
2279 check(s.contains("pid=" + p.pid() + ","));
2280 check(s.contains("exitValue=" + exitValue) &&
2281 !s.contains("not exited"));
2282 }
2283 } catch (Throwable t) { unexpected(t); }
2284
2285 //----------------------------------------------------------------
2286 // Attempt to start process with insufficient permissions fails.
2287 //----------------------------------------------------------------
2288 try {
2289 new File("emptyCommand").delete();
2290 new FileOutputStream("emptyCommand").close();
2291 new File("emptyCommand").setExecutable(false);
2292 new ProcessBuilder("./emptyCommand").start();
2293 fail("Expected IOException not thrown");
2294 } catch (IOException e) {
2295 new File("./emptyCommand").delete();
2296 String m = e.getMessage();
2297 if (EnglishUnix.is() &&
2298 ! matches(m, "Permission denied"))
2299 unexpected(e);
2300 } catch (Throwable t) { unexpected(t); }
2301
2302 new File("emptyCommand").delete();
2303
2304 //----------------------------------------------------------------
2305 // Check for correct security permission behavior
2306 //----------------------------------------------------------------
2307 final Policy policy = new Policy();
2308 Policy.setPolicy(policy);
2309 System.setSecurityManager(new SecurityManager());
2310
2311 try {
2312 // No permissions required to CREATE a ProcessBuilder
2313 policy.setPermissions(/* Nothing */);
2314 new ProcessBuilder("env").directory(null).directory();
2315 new ProcessBuilder("env").directory(new File("dir")).directory();
2316 new ProcessBuilder("env").command("??").command();
2317 } catch (Throwable t) { unexpected(t); }
2318
|
57 import java.util.concurrent.TimeUnit;
58 import java.security.*;
59 import java.util.regex.Pattern;
60 import java.util.regex.Matcher;
61 import static java.lang.System.getenv;
62 import static java.lang.System.out;
63 import static java.lang.Boolean.TRUE;
64 import static java.util.AbstractMap.SimpleImmutableEntry;
65
66 public class Basic {
67
68 /* used for Windows only */
69 static final String systemRoot = System.getenv("SystemRoot");
70
71 /* used for Mac OS X only */
72 static final String cfUserTextEncoding = System.getenv("__CF_USER_TEXT_ENCODING");
73
74 /* used for AIX only */
75 static final String libpath = System.getenv("LIBPATH");
76
77 /* Used for regex String matching for long error messages */
78 static final String PERMISSION_DENIED_ERROR_MSG = "(Permission denied|error=13, The file access permissions do not allow the specified action)";
79 static final String NO_SUCH_FILE_ERROR_MSG = "(No such file|error=2, A file or directory in the path name does not exist.)";
80 static final String NO_SUCH_FILE_OR_DIR_ERROR_MSG = "(No such file or directory|error=2, A file or directory in the path name does not exist)";
81
82 /**
83 * Returns the number of milliseconds since time given by
84 * startNanoTime, which must have been previously returned from a
85 * call to {@link System.nanoTime()}.
86 */
87 private static long millisElapsedSince(long startNanoTime) {
88 return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanoTime);
89 }
90
91 private static String commandOutput(Reader r) throws Throwable {
92 StringBuilder sb = new StringBuilder();
93 int c;
94 while ((c = r.read()) > 0)
95 if (c != '\r')
96 sb.append((char) c);
97 return sb.toString();
98 }
99
100 private static String commandOutput(Process p) throws Throwable {
101 check(p.getInputStream() == p.getInputStream());
293 sb.append(e.getKey())
294 .append('=')
295 .append(e.getValue())
296 .append(',');
297 return sb.toString();
298 }
299
300 static void print4095(OutputStream s, byte b) throws Throwable {
301 byte[] bytes = new byte[4095];
302 Arrays.fill(bytes, b);
303 s.write(bytes); // Might hang!
304 }
305
306 static void checkPermissionDenied(ProcessBuilder pb) {
307 try {
308 pb.start();
309 fail("Expected IOException not thrown");
310 } catch (IOException e) {
311 String m = e.getMessage();
312 if (EnglishUnix.is() &&
313 ! matches(m, PERMISSION_DENIED_ERROR_MSG))
314 unexpected(e);
315 } catch (Throwable t) { unexpected(t); }
316 }
317
318 public static class JavaChild {
319 public static void main(String args[]) throws Throwable {
320 String action = args[0];
321 if (action.equals("sleep")) {
322 Thread.sleep(10 * 60 * 1000L);
323 } else if (action.equals("pid")) {
324 System.out.println(ProcessHandle.current().pid());
325 } else if (action.equals("testIO")) {
326 String expected = "standard input";
327 char[] buf = new char[expected.length()+1];
328 int n = new InputStreamReader(System.in).read(buf,0,buf.length);
329 if (n != expected.length())
330 System.exit(5);
331 if (! new String(buf,0,n).equals(expected))
332 System.exit(5);
333 System.err.print("standard error");
403 equal(System.getenv("PATH"), "dir1:dir2:");
404 check(new File("/bin/true").exists());
405 check(new File("/bin/false").exists());
406 String[] cmd = {"prog"};
407 ProcessBuilder pb1 = new ProcessBuilder(cmd);
408 ProcessBuilder pb2 = new ProcessBuilder(cmd);
409 ProcessBuilder pb3 = new ProcessBuilder(cmd);
410 pb2.environment().put("PATH", "anyOldPathIgnoredAnyways");
411 pb3.environment().remove("PATH");
412
413 for (final ProcessBuilder pb :
414 new ProcessBuilder[] {pb1, pb2, pb3}) {
415 try {
416 // Not on PATH at all; directories don't exist
417 try {
418 pb.start();
419 fail("Expected IOException not thrown");
420 } catch (IOException e) {
421 String m = e.getMessage();
422 if (EnglishUnix.is() &&
423 ! matches(m, NO_SUCH_FILE_ERROR_MSG))
424 unexpected(e);
425 } catch (Throwable t) { unexpected(t); }
426
427 // Not on PATH at all; directories exist
428 new File("dir1").mkdirs();
429 new File("dir2").mkdirs();
430 try {
431 pb.start();
432 fail("Expected IOException not thrown");
433 } catch (IOException e) {
434 String m = e.getMessage();
435 if (EnglishUnix.is() &&
436 ! matches(m, NO_SUCH_FILE_ERROR_MSG))
437 unexpected(e);
438 } catch (Throwable t) { unexpected(t); }
439
440 // Can't execute a directory -- permission denied
441 // Report EACCES errno
442 new File("dir1/prog").mkdirs();
443 checkPermissionDenied(pb);
444
445 // continue searching if EACCES
446 copy("/bin/true", "dir2/prog");
447 equal(run(pb).exitValue(), True.exitValue());
448 new File("dir1/prog").delete();
449 new File("dir2/prog").delete();
450
451 new File("dir2/prog").mkdirs();
452 copy("/bin/true", "dir1/prog");
453 equal(run(pb).exitValue(), True.exitValue());
454
455 // Check empty PATH component means current directory.
456 //
1970 final ProcessBuilder pb =
1971 new ProcessBuilder(new String[]{"unliKely"});
1972 pb.environment().put("PATH", "suBdiR");
1973 THROWS(IOException.class, () -> pb.start());
1974 } catch (Throwable t) { unexpected(t);
1975 } finally {
1976 new File("suBdiR/unliKely").delete();
1977 new File("suBdiR").delete();
1978 }
1979 }
1980
1981 //----------------------------------------------------------------
1982 // Attempt to start bogus program ""
1983 //----------------------------------------------------------------
1984 try {
1985 new ProcessBuilder("").start();
1986 fail("Expected IOException not thrown");
1987 } catch (IOException e) {
1988 String m = e.getMessage();
1989 if (EnglishUnix.is() &&
1990 ! matches(m, NO_SUCH_FILE_OR_DIR_ERROR_MSG))
1991 unexpected(e);
1992 } catch (Throwable t) { unexpected(t); }
1993
1994 //----------------------------------------------------------------
1995 // Check that attempt to execute program name with funny
1996 // characters throws an exception containing those characters.
1997 //----------------------------------------------------------------
1998 for (String programName : new String[] {"\u00f0", "\u01f0"})
1999 try {
2000 new ProcessBuilder(programName).start();
2001 fail("Expected IOException not thrown");
2002 } catch (IOException e) {
2003 String m = e.getMessage();
2004 Pattern p = Pattern.compile(programName);
2005 if (! matches(m, programName)
2006 || (EnglishUnix.is() &&
2007 ! matches(m, NO_SUCH_FILE_OR_DIR_ERROR_MSG)))
2008 unexpected(e);
2009 } catch (Throwable t) { unexpected(t); }
2010
2011 //----------------------------------------------------------------
2012 // Attempt to start process in nonexistent directory fails.
2013 //----------------------------------------------------------------
2014 try {
2015 new ProcessBuilder("echo")
2016 .directory(new File("UnLiKeLY"))
2017 .start();
2018 fail("Expected IOException not thrown");
2019 } catch (IOException e) {
2020 String m = e.getMessage();
2021 if (! matches(m, "in directory")
2022 || (EnglishUnix.is() &&
2023 ! matches(m, NO_SUCH_FILE_OR_DIR_ERROR_MSG)))
2024 unexpected(e);
2025 } catch (Throwable t) { unexpected(t); }
2026
2027 //----------------------------------------------------------------
2028 // Attempt to write 4095 bytes to the pipe buffer without a
2029 // reader to drain it would deadlock, if not for the fact that
2030 // interprocess pipe buffers are at least 4096 bytes.
2031 //
2032 // Also, check that available reports all the bytes expected
2033 // in the pipe buffer, and that I/O operations do the expected
2034 // things.
2035 //----------------------------------------------------------------
2036 try {
2037 List<String> childArgs = new ArrayList<String>(javaChildArgs);
2038 childArgs.add("print4095");
2039 final int SIZE = 4095;
2040 final Process p = new ProcessBuilder(childArgs).start();
2041 print4095(p.getOutputStream(), (byte) '!'); // Might hang!
2042 p.waitFor(); // Might hang!
2043 equal(SIZE, p.getInputStream().available());
2283 s = p.toString();
2284 check(s.contains("pid=" + p.pid() + ","));
2285 check(s.contains("exitValue=" + exitValue) &&
2286 !s.contains("not exited"));
2287 }
2288 } catch (Throwable t) { unexpected(t); }
2289
2290 //----------------------------------------------------------------
2291 // Attempt to start process with insufficient permissions fails.
2292 //----------------------------------------------------------------
2293 try {
2294 new File("emptyCommand").delete();
2295 new FileOutputStream("emptyCommand").close();
2296 new File("emptyCommand").setExecutable(false);
2297 new ProcessBuilder("./emptyCommand").start();
2298 fail("Expected IOException not thrown");
2299 } catch (IOException e) {
2300 new File("./emptyCommand").delete();
2301 String m = e.getMessage();
2302 if (EnglishUnix.is() &&
2303 ! matches(m, PERMISSION_DENIED_ERROR_MSG))
2304 unexpected(e);
2305 } catch (Throwable t) { unexpected(t); }
2306
2307 new File("emptyCommand").delete();
2308
2309 //----------------------------------------------------------------
2310 // Check for correct security permission behavior
2311 //----------------------------------------------------------------
2312 final Policy policy = new Policy();
2313 Policy.setPolicy(policy);
2314 System.setSecurityManager(new SecurityManager());
2315
2316 try {
2317 // No permissions required to CREATE a ProcessBuilder
2318 policy.setPermissions(/* Nothing */);
2319 new ProcessBuilder("env").directory(null).directory();
2320 new ProcessBuilder("env").directory(new File("dir")).directory();
2321 new ProcessBuilder("env").command("??").command();
2322 } catch (Throwable t) { unexpected(t); }
2323
|