/*******************************************************************************
* Copyright (c) 2008 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Elliott Baron <ebaron@redhat.com> - initial API and implementation
* Alena Laskavaia - javadoc comments and cleanup
*******************************************************************************/
package org.eclipse.linuxtools.internal.valgrind.core;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.cdt.utils.pty.PTY;
import org.eclipse.core.resources.IProject;
import org.eclipse.linuxtools.tools.launch.core.factory.CdtSpawnerProcessFactory;
import org.eclipse.linuxtools.tools.launch.core.factory.RuntimeProcessFactory;
import org.eclipse.linuxtools.valgrind.core.CommandLineConstants;
/**
* Helper class to run valgrind
*/
public class ValgrindCommand {
protected static final String WHICH_CMD = "which"; //$NON-NLS-1$
protected static final String VALGRIND_CMD = "valgrind"; //$NON-NLS-1$
protected Process process;
protected String[] args;
/**
* The valgrind executable name
* @return command line name
*/
public String getValgrindCommand() {
return VALGRIND_CMD;
}
/**
* Attempt to local valgrind version
* @param project - project to get execution context
* @return version or emptry string if execution failed
* @throws IOException if failed to create a process
*/
public String whichVersion(IProject project) throws IOException {
Process p = RuntimeProcessFactory.getFactory()
.exec(new String[] { getValgrindCommand(), CommandLineConstants.OPT_VERSION }, project);
try {
StringBuffer out = new StringBuffer();
readIntoBuffer(out, p);
return out.toString().trim();
} catch (IOException e) {
e.printStackTrace(); // TODO fix
}
return ""; //$NON-NLS-1$
}
/**
* Execute command
* @param commandArray - command line arguments, first argument is executable itelv
* @param env - environment variables
* @param wd - working directory
* @param usePty - option to allocate pty or not
* @param project - project in context of which to launch the process
* @throws IOException - if cannot execute the command
*/
public void execute(String[] commandArray, String[] env, File wd, boolean usePty, IProject project) throws IOException {
args = commandArray;
try {
process = startProcess(commandArray, env, wd, usePty, project);
} catch (IOException e) {
if (process != null) {
process.destroy();
}
throw e;
}
}
/**
* Get current process
* @return process
*/
public Process getProcess() {
return process;
}
/**
* Get current valgrind command line, not escaped
* @return process
*/
public String getCommandLine() {
StringBuffer ret = new StringBuffer();
for (String arg : args) {
ret.append(arg).append(" "); //$NON-NLS-1$
}
return ret.toString().trim();
}
private Process startProcess(String[] commandArray, String[] env, File workDir, boolean usePty, IProject project) throws IOException {
if (workDir == null) {
return CdtSpawnerProcessFactory.getFactory().exec(commandArray, env, project);
}
if (PTY.isSupported() && usePty) {
return CdtSpawnerProcessFactory.getFactory().exec(commandArray, env, workDir, new PTY(), project);
} else {
return CdtSpawnerProcessFactory.getFactory().exec(commandArray, env, workDir, project);
}
}
private void readIntoBuffer(StringBuffer out, Process p) throws IOException {
if (p == null) {
throw new IOException("Null Process object: unabled to read input into buffer"); //$NON-NLS-1$
}
// We need to get the inputs before calling waitFor
try (InputStream err = p.getErrorStream(); InputStream input = p.getInputStream()) {
boolean success = (p.waitFor() == 0);
InputStream in;
if (success) {
in = input;
} else {
in = err;
}
int ch;
while ((ch = in.read()) != -1) {
out.append((char) ch); // TODO fix reading char by char ??
}
if (!success) {
throw new IOException(out.toString());
}
} catch (InterruptedException e) {
e.printStackTrace(); // TODO fix
} finally {
p.getOutputStream().close();
}
}
}