1 /*
   2  * Copyright (c) 2004, 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  */
  23 
  24 /* @test
  25  * @bug 5006520
  26  * @summary Check many different ways to run Windows programs
  27  * @author Martin Buchholz
  28  */
  29 
  30 import java.io.*;
  31 import java.util.*;
  32 import static java.lang.System.*;
  33 
  34 class StreamDrainer extends Thread {
  35     private final InputStream is;
  36     private final ByteArrayOutputStream os = new ByteArrayOutputStream();
  37     public StreamDrainer(InputStream is) { this.is = is; }
  38     public void run() {
  39         try {
  40             int i;
  41             while ((i = is.read()) >= 0)
  42                 os.write(i);
  43         } catch (Exception e) {}
  44     }
  45     public String toString() { return os.toString(); }
  46 }
  47 
  48 class CommandRunner {
  49     private static Random generator = new Random();
  50     public final int exitValue;
  51     public final String out;
  52     public final String err;
  53     CommandRunner(String... args) throws Exception {
  54         Process p = (generator.nextInt(2) == 0)
  55             ? new ProcessBuilder(args).start()
  56             : Runtime.getRuntime().exec(args);
  57         StreamDrainer d1 = new StreamDrainer(p.getInputStream());
  58         StreamDrainer d2 = new StreamDrainer(p.getErrorStream());
  59         d1.start();
  60         d2.start();
  61         p.waitFor();
  62         d1.join();
  63         d2.join();
  64         this.exitValue = p.exitValue();
  65         this.out = d1.toString();
  66         this.err = d2.toString();
  67     }
  68 }
  69 
  70 public class WinCommand {
  71     private static int failed = 0;
  72 
  73     private static void fail(String msg) {
  74         err.printf("FAIL: %s%n", msg);
  75         failed++;
  76     }
  77 
  78     private static String outputOf(String... args) {
  79         try {
  80             CommandRunner cr = new CommandRunner(args);
  81             if (cr.exitValue != 0)
  82                 fail("exitValue != 0");
  83             if (! cr.err.equals(""))
  84                 fail("stderr: " + cr.err);
  85             return cr.out.replaceFirst("[\r\n]+$", "");
  86         } catch (Exception e) {
  87             fail(e.toString());
  88             return "";
  89         }
  90     }
  91 
  92     private static void checkCD(String... filespecs) {
  93         String firstCD = null;
  94         for (String filespec : filespecs) {
  95             String CD = outputOf(filespec, "/C", "CD");
  96             out.printf("%s CD ==> %s%n", filespec, CD);
  97             if (firstCD == null) {
  98                 firstCD = CD;
  99                 checkDir(CD);
 100             }
 101             if (! CD.equals(firstCD)) {
 102                 fail("Inconsistent result from CD subcommand");
 103                 checkDir(CD);
 104             }
 105         }
 106     }
 107 
 108     private static void checkDir(String dirname) {
 109         if (! new File(dirname).isDirectory())
 110             fail(String.format("Not a directory: %s%n", dirname));
 111     }
 112 
 113     private static void writeFile(String filename, String contents) {
 114         try {
 115             FileOutputStream fos = new FileOutputStream(filename);
 116             fos.write(contents.getBytes());
 117             fos.close();
 118         } catch (Exception e) {
 119             fail("Unexpected exception" + e.toString());
 120         }
 121     }
 122 
 123     public static void main(String[] args) throws Exception {
 124         File systemRoot =
 125             getenv("SystemRoot") != null ? new File(getenv("SystemRoot")) :
 126             getenv("WINDIR")     != null ? new File(getenv ("WINDIR")) :
 127             null;
 128         if (systemRoot == null || ! systemRoot.isDirectory())
 129             return; // Not Windows as we know it
 130 
 131         String systemDirW = new File(systemRoot, "System32").getPath();
 132         String systemDirM = systemDirW.replace('\\', '/');
 133         out.printf("systemDirW=%s%n", systemDirW);
 134         out.printf("systemDirM=%s%n", systemDirM);
 135 
 136         // Win9x systems don't have a cmd.exe
 137         if (new File(systemDirW, "cmd.exe").exists()) {
 138             try {
 139                 out.println("Running cmd.exe tests...");
 140                 writeFile("cdcmd.cmd", "@echo off\r\nCD\r\n");
 141                 writeFile("cdbat.bat", "@echo off\r\nCD\r\n");
 142                 checkCD("cmd",
 143                         "cmd.exe",
 144                         systemDirW + "\\cmd.exe",
 145                         // Only the ".exe" extension can be omitted
 146                         systemDirW + "\\cmd",
 147                         systemDirM + "/cmd.exe",
 148                         systemDirM + "/cmd",
 149                         "/" + systemDirM + "/cmd",
 150                         "cdcmd.cmd", "./cdcmd.cmd", ".\\cdcmd.cmd",
 151                         "cdbat.bat", "./cdbat.bat", ".\\cdbat.bat");
 152             } finally {
 153                 new File("cdcmd.cmd").delete();
 154                 new File("cdbat.bat").delete();
 155             }                
 156         }
 157 
 158         // 16-bit apps like command.com must have a console;
 159         // fix this someday...
 160 
 161 //      // Win64 systems don't have a command.com
 162 //      if (new File(systemDirW, "command.com").exists()
 163 //          // no output if running without a console;
 164 //          // fix this in Mustang
 165 //          && ! outputOf("command.com", "/C", "CD").equals("")) {
 166 //          out.println("Running command.com tests...");
 167 //          checkCD("command.com",
 168 //                  systemDirM + "/command.com",
 169 //                  systemDirW + "\\command.com");
 170 //      }
 171 
 172         // Win9x systems have a %SYSTEMDRIVE%\command.com
 173 //      if (new File("C:\\COMMAND.COM").exists()
 174 //          && ! outputOf("COMMAND.COM", "/C", "CD").equals("")) {
 175 //          out.println("Running COMMAND.COM tests...");
 176 //          checkCD("C:/command.com",
 177 //                  "C:\\command.com");
 178 //      }
 179 
 180         if (failed > 0)
 181             throw new Exception(failed + " tests failed");
 182     }
 183 }