title: Running interactive shell program in Java
body: <p>I am trying (and failing) to work out how I can run a fully interactive shell program from within Java.</p>
  
  <p>Here's the scenario:</p>
  
  <p>I have a large GUI application which is cross platform and written in Java.  Into that I am trying to add an interactive command line environment for running headless.  That side of things is all fine and dandy.  However, one of the functions of the main GUI is editing of files.  Now, for the command line interface I want to be able to execute an external editor to edit the files, then return back to where I was after I have saved and exited.  For example, on Linux it may execute "vi /path/to/file".</p>
  
  <p>So how can I execute that command in such a way that the keyboard and display are fully interactive to the application?  I don't want it to run in the background. I don't want it to redirect IO through Java, I just want that one single command to run "in the foreground" until it exists.</p>
  
  <p>Just like as if I'd used the <code>system()</code> function in C.</p>
  
  <p>Everything I have found so far runs commands in the background or pipe the IO through Java, which won't work for interactive (non line-mode) applications.</p>
  
  <p>Oh, and one final caveat: I'm restricted to Java 1.6 compatibility, so I can't do fancy things with <code>ProcessBuilder</code>.</p>
  
  <p>Here's the obligatory SSCCE:</p>
  
  <pre><code>class exetest {
      public static void main(String[] args) { 
          try {
              Process p = Runtime.getRuntime().exec("vi");
              p.waitFor();
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  }
  </code></pre>
  
  <p>I would expect the Runtime.getRuntime().exec() to block until I had finished in <code>vi</code>, and during that time all keyboard input would go direct (<code>RAW</code> as it's known) through to <code>vi</code> and all screen output would come directly back, untouched, to the user.</p>
  
  <p>And this is how I would achieve it in C:</p>
  
  <pre><code>void main() {
      system("vi");
  }
  </code></pre>
  
  <p><strong>Update:</strong></p>
  
  <p>This achieves the desired result, but a) is limited to Linux / OSX (not that much of a problem, but would be nice to have it cross platform), and b) is a terrible kludge:</p>
  
  <pre><code>import java.io.*;
  
  class exetest {
      public static void main(String[] args) {
          try {
              Process p = Runtime.getRuntime().exec("/bin/bash");
              OutputStream stdin = p.getOutputStream();
              PrintWriter pw = new PrintWriter(stdin);
              pw.println("vi &lt; /dev/tty &gt; /dev/tty");
              pw.close();
              p.waitFor();
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  }
  </code></pre>