package org.openslx.satserver.util; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; public class Exec { /** * Run command, return exit status of process, or -1 on error * * @param timeoutSec maximum time in seconds to wait for process to finish * @param command Command and arguments * @return exit code */ public static int sync( int timeoutSec, ExecCallback callback, String... command ) { return syncAt( timeoutSec, callback, "/", command ); } public static int sync( int timeoutSec, String... command ) { return sync( timeoutSec, null, command ); } public static int syncAt( int timeoutSec, ExecCallback callback, String cwd, String... command ) { ProcessBuilder pb = new ProcessBuilder( command ); pb.directory( new File( cwd ) ); Process p = null; Thread[] list = null; try { p = pb.start(); if ( callback != null ) { list = setupCallback( p, callback ); } if ( timeoutSec <= 0 ) { return p.waitFor(); } else { for ( int i = 0; i < timeoutSec * 10; ++i ) { Thread.sleep( 100 ); try { return p.exitValue(); } catch ( IllegalThreadStateException e ) { // Wait... } } // Timeout return -1; } } catch ( IOException | InterruptedException e ) { return -2; } finally { try { if ( p != null ) { Util.multiClose( p.getOutputStream(), p.getErrorStream() ); p.destroy(); } } catch ( Exception e ) { // } if ( list != null ) { for ( Thread t : list ) { try { t.interrupt(); } catch ( Exception e ) { // } } } } } public static int syncAt( int timeoutSec, String cwd, String... command ) { return syncAt( timeoutSec, null, cwd, command ); } private static Thread[] setupCallback( final Process p, final ExecCallback cb ) { // Read its stdout Thread stdout = new Thread( new Runnable() { @Override public void run() { try { BufferedReader reader = new BufferedReader( new InputStreamReader( p.getInputStream() ) ); String line; while ( ( line = reader.readLine() ) != null ) { synchronized ( p ) { cb.processStdOut( line ); } } } catch ( Exception e ) { } } } ); // Read its stderr Thread stderr = new Thread( new Runnable() { @Override public void run() { try { BufferedReader reader = new BufferedReader( new InputStreamReader( p.getErrorStream() ) ); String line; while ( ( line = reader.readLine() ) != null ) { synchronized ( p ) { cb.processStdErr( line ); } } } catch ( Exception e ) { } } } ); stdout.start(); stderr.start(); Thread[] t = new Thread[] { stdout, stderr }; return t; } /**/ public interface ExecCallback { public void processStdOut( String line ); public void processStdErr( String line ); } }