title: ProcessBuilder - A potential bug
body: <p>I am having a strange issue when trying to execute a block of code (more particularly the ProcessBuilder class in Java)</p>
  
  <p>Code that works:</p>
  
  <pre><code>package modules.user.verify;
  
  import java.io.*;
  import java.util.*;
  import java.net.*;
  
  public class VerifyUser {
  public static void main(String[] args) {
      boolean listening = true;
  
      try {
          ServerSocket server = new ServerSocket(20002);
  
          while(listening) {
              Socket client = server.accept();
  
              PrintWriter out = new PrintWriter(client.getOutputStream(), true);
              BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
  
              String input, store = "", request = "";
  
              // For all input received, write it to the request buffer.
              while((input = in.readLine()) != null) {
                  request += input;
              }   // end while loop
  
              BufferedReader reader = new BufferedReader(new FileReader("store/address-book/address-book.xml"));
  
              while((input = reader.readLine()) != null) {
                  store += input;
              }   // end while loop
  
              String acl2 = "(include-book \"modules/user/verify/verify-user\")" + 
                                "(in-package \"ACL2\")" +
                           "(set-state-ok t)" +
                                "(set-guard-checking :none)" + 
                            "(testUser \"" + request + "\" \"" + store + "\" state)";
  
              System.out.println("Executing ACL2 runtime...");
              ProcessBuilder processBuilder = new ProcessBuilder("acl2");
              File log = new File("logs/user/verify/acl2_log.txt");
              processBuilder.redirectErrorStream(true);
              processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(log));
              Process process = processBuilder.start();
              PrintWriter procIn = new PrintWriter(process.getOutputStream());
  
              // Write the ACL2 to the process, exit ACL2 and close the socket
              procIn.println(acl2);
              procIn.println("(good-bye)");
              procIn.flush();
              procIn.close();
              out.close();
              in.close();
              client.close();
          }   // end while loop
  
          server.close();
          System.exit(0);
      } catch(Exception e) {
          e.printStackTrace();
      }   // end try/catch
  }   // end function main
  }   // end class VerifyUser
  </code></pre>
  
  <p>Code that doesn't work:</p>
  
  <pre><code>package modules.user.register;
  
  import java.io.*;
  import java.util.*;
  import java.net.*;
  
  public class RegisterUser {
  public static void main(String[] args) {
      boolean listening = true;
  
      try {
          // Acquire the listening port for connection to client.
          ServerSocket server = new ServerSocket(20001);
  
          while(listening) {
              // Wait until the client connects
              Socket client = server.accept();
  
              // Handles for input and output streams relating to the socket connection
              PrintWriter out = new PrintWriter(client.getOutputStream(), true);
              BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
  
              // Buffers
              String input, store="", request="";
  
              // Read the input from the connection
              while((input = in.readLine()) != null) {
                  request += input;
              }   // end while
  
              // Read the contents of the address-book currently stored
              BufferedReader reader = new BufferedReader(new FileReader("store/address-book/address-book.xml"));
              while((input = reader.readLine()) != null) {
                  store += input;
              }   // end while
  
              // The ACL2 code to execute.
              String acl2 = "(include-book \"register-user\")" +
                            "(in-package \"ACL2\")"            +
                            "(registerUser \"" + request + "\" \"" + store + "\" state)";
  
              // Initialize ACL2 and dump its output to the log
              System.out.println("Executing ACL2 runtime for RegisterUser...");
              ProcessBuilder processBuilder = new ProcessBuilder("acl2");
              File log = new File("logs/user/register/acl2_log.txt");
              processBuilder.redirectErrorStream(true);
              processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(log));
  
              Process process = processBuilder.start();
              PrintWriter procIn = new PrintWriter(process.getOutputStream());
  
              // Write the ACL2 to the process, close ACL2
              //procIn.println(acl2);
              //procIn.println("(good-bye)");
              //procIn.flush();
              //procIn.close();
  
              // Old store is old address-book file and new store is newly generated
              File oldStore = new File("store/address-book/address-book.xml");
              File newStore = new File("store/address-book/temp_address-book.xml");
  
              // Response header information
              String response = "&lt;?xml version='1.0'?&gt;"                        + 
                                "&lt;!DOCTYPE response SYSTEM 'dtd/reponse.dtd'&gt;" +
                                "&lt;response&gt;";
  
              // Determine if there was a change.
              // If entry was added, the length &gt; that old length.
              if(oldStore.length() &lt; newStore.length()) {
                  // Replace old file with new file
                  oldStore.delete();
                  newStore.renameTo(oldStore);
  
                  // Extract data from request XML
                  String name   = request.substring(request.indexOf("&lt;name&gt;")+6, request.indexOf("&lt;/name&gt;")-7);
                  String domain = request.substring(request.indexOf("&lt;domain&gt;")+8, request.indexOf("&lt;/domain&gt;")-9);
  
                  // Create the store directory for the user's emails
                  File storeDirectory = new File("store/email/" + domain + "/" + name + "/");
                  storeDirectory.mkdirs();
  
                  response += "&lt;message&gt;ACCEPT&lt;/message&gt;";
              } else {
                  // Remove new file as it is pointless
                  newStore.delete();
                  response += "&lt;message&gt;REJECT&lt;/message&gt;";
              }   // end if-else
  
              response += "&lt;/response&gt;";
  
              // Writeback the response to the client
              out.print(response);
              out.flush();
  
              // Close all streams
              out.close();
              in.close();
              client.close();
          }   // end while
      } catch(Exception e) {
          e.printStackTrace();
      }   // end try/catch
  }   // end function main
  }   // end class RegisterUser
  </code></pre>
  
  <p>As you can see, I am not passing any arguments the the program.  when I echo %PATH% on my windows DOS shell, it shows that C:\ACL2 is in my ENV vars (which is the folder acl2.exe is located).  I've tried changing the acl2 to C:\ACL2\acl2.exe only to have the same results.</p>
  
  <p>What is boggling me is why the first one works perfect and the second one (with almost the same exact code - same exact ProcessBuilder code) does not work.</p>
  
  <p>It appears this block of code is where my problem is:</p>
  
  <pre><code>        System.out.println("Executing ACL2 runtime...");
          ProcessBuilder processBuilder = new ProcessBuilder("acl2");
          File log = new File("logs/user/register/acl2_log.txt");
          processBuilder.redirectErrorStream(true);
          processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(log));
          Process process = processBuilder.start();
          PrintWriter procIn = new PrintWriter(process.getOutputStream());
  </code></pre>
  
  <p>The error:</p>
  
  <pre><code>Executing ACL2 runtime for RegisterUser...
  java.io.IOException: Cannot run program "acl2": The system cannot find the path specified
          at java.lang.ProcessBuilder.start(Unknown Source)
      at modules.user.register.RegisterUser.main(RegisterUser.java:74)
  Caused by: java.io.IOException: The system cannot find the path specified
      at java.lang.ProcessImpl.openForAtomicAppend(Native Method)
      at java.lang.ProcessImpl.newFileOutputStream(Unknown Source)
      at java.lang.ProcessImpl.start(Unknown Source)
      ... 2 more
  </code></pre>
  
  <p>What is supposed to happen, is that the Process that gets started is the ACL2 environment, code is sent to it which is executed and then the process is killed (via the (good-bye) command in ACL2).  After that the code should exit after a little bit of Java, which is not related to the ACL2 process where the error occurs.</p>
  
  <p>The VerifyUser program invokes ACL2, writes a response to a "server-response.xml" file and exits gracefully without incident.</p>
  
  <p>The RegisterUser program should invoke ACL2, write a response and exit gracefully, and a little java code creates a directory for a user and deletes a store file and renames the newly generated one for user registration.</p>