Path: csiph.com!usenet.pasdenom.info!aioe.org!eternal-september.org!feeder.eternal-september.org!mx02.eternal-september.org!.POSTED!not-for-mail From: Eric Sosman Newsgroups: comp.lang.java.programmer Subject: Re: Getting results of command execution Date: Fri, 19 Jun 2015 11:01:01 -0400 Organization: A noiseless patient Spider Lines: 136 Message-ID: References: <7a28b01f-2a86-4703-98e7-79a7be418abf@googlegroups.com> <7e0fd613-2e77-44bb-9c7e-7f31dfb33273@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Injection-Date: Fri, 19 Jun 2015 14:59:46 +0000 (UTC) Injection-Info: mx02.eternal-september.org; posting-host="858a9d65d95f4ea4d355bd116aa2cdbf"; logging-data="32679"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+SZFdZbFG5p7a2WQnB0W63" User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 In-Reply-To: <7e0fd613-2e77-44bb-9c7e-7f31dfb33273@googlegroups.com> Cancel-Lock: sha1:UEqLzkqyGF25e6uSuVXxa0zgf1U= Xref: csiph.com comp.lang.java.programmer:31829 On 6/18/2015 10:30 AM, FredK wrote: > > The requirement is essentially that I want to include a panel in my program that acts like a shell. So throughout the lifetime of the program, in addition to interacting with the program the user can also use it as if it were a shell - kind of like a Unix xterm, with additional capabilities. For example, the user could type "ls", then point to a file name, right-click on it and it would open up an editor for that file (based on what kind of file it is), or if it is the name of a directory, cd to that directory and possibly execute ls in that directory. Typing "+U" would execute "cd ..;pwd;ls", plus other features. > > I have written something like this in C using Motif, and it works fine - I just fork at the beginning and the child becomes a shell, and I redirect the pipes such that I have access to the shell's input, output, and error streams. > > But I don't know how to do this in Java. Quick and (very) dirty, Windows version: import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.SwingUtilities; public class Foo extends JPanel { private final JTextArea screen; private final Process shellProcess; private final Writer shellInput; private final Reader shellOutput; private Foo() throws IOException { assert SwingUtilities.isEventDispatchThread(); screen = new JTextArea(24, 80); add(new JScrollPane(screen)); ProcessBuilder builder = new ProcessBuilder(); builder.command("cmd"); builder.redirectErrorStream(true); shellProcess = builder.start(); shellInput = new OutputStreamWriter(shellProcess.getOutputStream()); shellOutput = new InputStreamReader(shellProcess.getInputStream()); Runnable listener = () -> { char[] buffer = new char[512]; int len; do { String text; try { len = shellOutput.read(buffer); text = (len >= 0) ? new String(buffer, 0, len) : "*** EOF ***"; } catch (IOException ex) { len = -1; text = "*** " + ex.getLocalizedMessage() + " ***"; } final String finalText = text; SwingUtilities.invokeLater(() -> { screen.append(finalText); }); } while (len >= 0); }; new Thread(listener).start(); } public void stopProcess() { shellProcess.destroyForcibly(); } private static final String NEWLINE = System.getProperty("line.separator"); public void sendCommand(String command) { if (!command.endsWith(NEWLINE)) { command += NEWLINE; } try { shellInput.write(command); shellInput.flush(); } catch (IOException ex) { Logger.getLogger(Foo.class.getName()).log(Level.SEVERE, null, ex); System.exit(1); } } public static void main(String[] unused) { SwingUtilities.invokeLater(() -> { JFrame frame = new JFrame("Foo"); final Foo foo; try { foo = new Foo(); } catch (IOException ex) { Logger.getLogger(Foo.class.getName()).log(Level.SEVERE, null, ex); System.exit(1); return; // to placate the compiler } frame.add(foo, BorderLayout.CENTER); final JTextField command = new JTextField(60); command.addActionListener((ActionEvent e) -> { foo.sendCommand(command.getText()); }); JLabel label = new JLabel("Command me:"); label.setLabelFor(command); JPanel controls = new JPanel(); controls.add(label); controls.add(command); frame.add(controls, BorderLayout.SOUTH); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { foo.stopProcess(); System.exit(0); } }); frame.pack(); frame.setVisible(true); }); } } -- esosman@comcast-dot-net.invalid "Don't be afraid of work. Make work afraid of you." -- TLM