// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.shell;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.io.ByteStreams;
import com.google.devtools.build.lib.shell.Consumers.OutErrConsumers;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Duration;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;

/**
 * An executable command, including its arguments and runtime environment (environment variables,
 * working directory). It lets a caller execute a command, get its results, and optionally forward
 * interrupts to the subprocess. This class creates threads to ensure timely reading of subprocess
 * outputs.
 *
 * <p>This class is immutable and thread-safe.
 *
 * <p>The use of "shell" in the package name of this class is a misnomer.  In terms of the way its
 * arguments are interpreted, this class is closer to {@code execve(2)} than to {@code system(3)}.
 * No shell is executed.
 *
 * <h4>Examples</h4>
 *
 * <p>The most basic use-case for this class is as follows:
 * <pre>
 *   String[] args = { "/bin/du", "-s", directory };
 *   BlazeCommandResult result = new Command(args).execute();
 *   String output = new String(result.getStdout());
 * </pre>
 * which writes the output of the {@code du(1)} command into {@code output}. More complex cases
 * might inspect the stderr stream, kill the subprocess asynchronously, feed input to its standard
 * input, handle the exceptions thrown if the command fails, or print the termination status (exit
 * code or signal name).
 *
 * <h4>Other Features</h4>
 *
 * <p>A caller can optionally specify bytes to be written to the process's "stdin". The returned
 * {@link CommandResult} object gives the caller access to the exit status, as well as output from
 * "stdout" and "stderr". To use this class with processes that generate very large amounts of
 * input/output, consider {@link #execute(OutputStream, OutputStream)},
 * {@link #executeAsync(OutputStream, OutputStream)}, or
 * {@link #executeAsync(InputStream, OutputStream, OutputStream, boolean)}.
 *
 * <p>This class ensures that stdout and stderr streams are read promptly, avoiding potential
 * deadlock if the output is large. See
 * <a href="http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html"> when
 * <code>Runtime.exec()</code> won't</a>.
 *
 * <h4>Caution: Invoking Shell Commands</h4>
 *
 * <p>Perhaps the most common command invoked programmatically is the UNIX shell, {@code /bin/sh}.
 * Because the shell is a general-purpose programming language, care must be taken to ensure that
 * variable parts of the shell command (e.g. strings entered by the user) do not contain shell
 * metacharacters, as this poses a correctness and/or security risk.
 *
 * <p>To execute a shell command directly, use the following pattern:
 * <pre>
 *   String[] args = { "/bin/sh", "-c", shellCommand };
 *   BlazeCommandResult result = new Command(args).execute();
 * </pre>
 * {@code shellCommand} is a complete Bourne shell program, possibly containing all kinds of
 * unescaped metacharacters.  For example, here's a shell command that enumerates the working
 * directories of all processes named "foo":
 * <pre>ps auxx | grep foo | awk '{print $1}' |
 *      while read pid; do readlink /proc/$pid/cwd; done</pre>
 * It is the responsibility of the caller to ensure that this string means what they intend.
 *
 * <p>Consider the risk posed by allowing the "foo" part of the previous command to be some
 * arbitrary (untrusted) string called {@code processName}:
 * <pre>
 *  // WARNING: unsafe!
 *  String shellCommand = "ps auxx | grep " + processName + " | awk '{print $1}' | "
 *  + "while read pid; do readlink /proc/$pid/cwd; done";</pre>
 * </pre>
 * Passing this string to {@link Command} is unsafe because if the string {@processName} contains
 * shell metacharacters, the meaning of the command can be arbitrarily changed; consider:
 * <pre>String processName = ". ; rm -fr $HOME & ";</pre>
 *
 * <p>To defend against this possibility, it is essential to properly quote the variable portions of
 * the shell command so that shell metacharacters are escaped.  Use {@link ShellUtils#shellEscape}
 * for this purpose:
 * <pre>
 *  // Safe.
 *  String shellCommand = "ps auxx | grep " + ShellUtils.shellEscape(processName)
 *      + " | awk '{print $1}' | while read pid; do readlink /proc/$pid/cwd; done";
 * </pre>
 *
 * <p>Tip: if you are only invoking a single known command, and no shell features (e.g. $PATH
 * lookup, output redirection, pipelines, etc) are needed, call it directly without using a shell,
 * as in the {@code du(1)} example above.
 */
public final class Command {

  private static final Logger logger =
      Logger.getLogger("com.google.devtools.build.lib.shell.Command");

  /** Pass this value to {@link #execute} to indicate that no input should be written to stdin. */
  public static final InputStream NO_INPUT = new NullInputStream();

  public static final boolean KILL_SUBPROCESS_ON_INTERRUPT = true;
  public static final boolean CONTINUE_SUBPROCESS_ON_INTERRUPT = false;

  private final SubprocessBuilder subprocessBuilder;

  /**
   * Creates a new {@link Command} for the given command line. The environment is inherited from the
   * current process, as is the working directory. No timeout is enforced. The command line is
   * executed exactly as given, without a shell. Subsequent calls to {@link #execute()} will use the
   * JVM's working directory and environment.
   *
   * @param commandLineElements elements of raw command line to execute
   * @throws IllegalArgumentException if commandLine is null or empty
   */
  public Command(String[] commandLineElements) {
    this(commandLineElements, null, null, Duration.ZERO);
  }

  /**
   * Just like {@link #Command(String[], Map, File, Duration)}, but without a timeout.
   */
  public Command(
      String[] commandLineElements,
      @Nullable Map<String, String> environmentVariables,
      @Nullable File workingDirectory) {
    this(commandLineElements, environmentVariables, workingDirectory, Duration.ZERO);
  }

  /**
   * Creates a new {@link Command} for the given command line elements. The command line is executed
   * without a shell.
   *
   * <p>The given environment variables and working directory are used in subsequent calls to {@link
   * #execute()}.
   *
   * <p>This command treats the 0-th element of {@code commandLineElement} (the name of an
   * executable to run) specially.
   *
   * <ul>
   *   <li>If it is an absolute path, it is used as it
   *   <li>If it is a single file name, the PATH lookup is performed
   *   <li>If it is a relative path that is not a single file name, the command will attempt to
   *       execute the binary at that path relative to {@code workingDirectory}.
   * </ul>
   *
   * @param commandLineElements elements of raw command line to execute
   * @param environmentVariables environment variables to replace JVM's environment variables; may
   *     be null
   * @param workingDirectory working directory for execution; if null, the VM's current working
   *     directory is used
   * @param timeout timeout; a value less than or equal to 0 is treated as no timeout
   * @throws IllegalArgumentException if commandLine is null or empty
   */
  // TODO(ulfjack): Throw a special exception if there was a timeout.
  public Command(
      String[] commandLineElements,
      @Nullable Map<String, String> environmentVariables,
      @Nullable File workingDirectory,
      Duration timeout) {
    Preconditions.checkNotNull(commandLineElements);
    Preconditions.checkArgument(
        commandLineElements.length != 0, "cannot run an empty command line");

    File executable = new File(commandLineElements[0]);
    if (!executable.isAbsolute() && executable.getParent() != null) {
      commandLineElements = commandLineElements.clone();
      commandLineElements[0] = new File(workingDirectory, commandLineElements[0]).getAbsolutePath();
    }

    this.subprocessBuilder = new SubprocessBuilder();
    subprocessBuilder.setArgv(ImmutableList.copyOf(commandLineElements));
    subprocessBuilder.setEnv(environmentVariables);
    subprocessBuilder.setWorkingDirectory(workingDirectory);
    subprocessBuilder.setTimeoutMillis(timeout.toMillis());
  }

  /** Returns the raw command line elements to be executed */
  public String[] getCommandLineElements() {
    final List<String> elements = subprocessBuilder.getArgv();
    return elements.toArray(new String[elements.size()]);
  }

  /** Returns an (unmodifiable) {@link Map} view of command's environment variables or null. */
  @Nullable public Map<String, String> getEnvironmentVariables() {
    return subprocessBuilder.getEnv();
  }

  /** Returns the working directory to be used for execution, or null. */
  @Nullable public File getWorkingDirectory() {
    return subprocessBuilder.getWorkingDirectory();
  }

  /**
   * Execute this command with no input to stdin, and with the output captured in memory. If the
   * current process is interrupted, then the subprocess is also interrupted. This call blocks until
   * the subprocess completes or an error occurs.
   *
   * <p>This method is a convenience wrapper for <code>executeAsync().get()</code>.
   *
   * @return {@link CommandResult} representing result of the execution
   * @throws ExecFailedException if {@link Runtime#exec(String[])} fails for any reason
   * @throws AbnormalTerminationException if an {@link IOException} is encountered while reading
   *    from the process, or the process was terminated due to a signal
   * @throws BadExitStatusException if the process exits with a non-zero status
   */
  public CommandResult execute() throws CommandException {
    return executeAsync().get();
  }

  /**
   * Execute this command with no input to stdin, and with the output streamed to the given output
   * streams, which must be thread-safe. If the current process is interrupted, then the subprocess
   * is also interrupted. This call blocks until the subprocess completes or an error occurs.
   *
   * <p>Note that the given output streams are never closed by this class.
   *
   * <p>This method is a convenience wrapper for <code>executeAsync(stdOut, stdErr).get()</code>.
   *
   * @return {@link CommandResult} representing result of the execution
   * @throws ExecFailedException if {@link Runtime#exec(String[])} fails for any reason
   * @throws AbnormalTerminationException if an {@link IOException} is encountered while reading
   *    from the process, or the process was terminated due to a signal
   * @throws BadExitStatusException if the process exits with a non-zero status
   */
  public CommandResult execute(OutputStream stdOut, OutputStream stdErr) throws CommandException {
    return doExecute(
        NO_INPUT, Consumers.createStreamingConsumers(stdOut, stdErr), KILL_SUBPROCESS_ON_INTERRUPT)
            .get();
  }

  /**
   * Execute this command with no input to stdin, and with the output captured in memory. If the
   * current process is interrupted, then the subprocess is also interrupted. This call blocks until
   * the subprocess is started or throws an error if that fails, but does not wait for the
   * subprocess to exit.
   *
   * @return {@link CommandResult} representing result of the execution
   * @throws ExecFailedException if {@link Runtime#exec(String[])} fails for any reason
   * @throws AbnormalTerminationException if an {@link IOException} is encountered while reading
   *    from the process, or the process was terminated due to a signal
   * @throws BadExitStatusException if the process exits with a non-zero status
   */
  public FutureCommandResult executeAsync() throws CommandException {
    return doExecute(
        NO_INPUT, Consumers.createAccumulatingConsumers(), KILL_SUBPROCESS_ON_INTERRUPT);
  }

  /**
   * Execute this command with no input to stdin, and with the output streamed to the given output
   * streams, which must be thread-safe. If the current process is interrupted, then the subprocess
   * is also interrupted. This call blocks until the subprocess is started or throws an error if
   * that fails, but does not wait for the subprocess to exit.
   *
   * <p>Note that the given output streams are never closed by this class.
   *
   * @return {@link CommandResult} representing result of the execution
   * @throws ExecFailedException if {@link Runtime#exec(String[])} fails for any reason
   * @throws AbnormalTerminationException if an {@link IOException} is encountered while reading
   *    from the process, or the process was terminated due to a signal
   * @throws BadExitStatusException if the process exits with a non-zero status
   */
  public FutureCommandResult executeAsync(OutputStream stdOut, OutputStream stdErr)
      throws CommandException {
    return doExecute(
        NO_INPUT, Consumers.createStreamingConsumers(stdOut, stdErr), KILL_SUBPROCESS_ON_INTERRUPT);
  }

  /**
   * Execute this command with no input to stdin, and with the output captured in memory. This call
   * blocks until the subprocess is started or throws an error if that fails, but does not wait for
   * the subprocess to exit.
   *
   * @param killSubprocessOnInterrupt whether the subprocess should be killed if the current process
   *     is interrupted
   * @return {@link CommandResult} representing result of the execution
   * @throws ExecFailedException if {@link Runtime#exec(String[])} fails for any reason
   * @throws AbnormalTerminationException if an {@link IOException} is encountered while reading
   *    from the process, or the process was terminated due to a signal
   * @throws BadExitStatusException if the process exits with a non-zero status
   */
  public FutureCommandResult executeAsync(
      InputStream stdinInput, boolean killSubprocessOnInterrupt) throws CommandException {
    return doExecute(
        stdinInput, Consumers.createAccumulatingConsumers(), killSubprocessOnInterrupt);
  }

  /**
   * Execute this command with no input to stdin, and with the output streamed to the given output
   * streams, which must be thread-safe. This call blocks until the subprocess is started or throws
   * an error if that fails, but does not wait for the subprocess to exit.
   *
   * <p>Note that the given output streams are never closed by this class.
   *
   * @param killSubprocessOnInterrupt whether the subprocess should be killed if the current process
   *     is interrupted
   * @return {@link CommandResult} representing result of the execution
   * @throws ExecFailedException if {@link Runtime#exec(String[])} fails for any reason
   * @throws AbnormalTerminationException if an {@link IOException} is encountered while reading
   *    from the process, or the process was terminated due to a signal
   * @throws BadExitStatusException if the process exits with a non-zero status
   */
  public FutureCommandResult executeAsync(
      InputStream stdinInput,
      OutputStream stdOut,
      OutputStream stdErr,
      boolean killSubprocessOnInterrupt)
          throws CommandException {
    return doExecute(
        stdinInput, Consumers.createStreamingConsumers(stdOut, stdErr), killSubprocessOnInterrupt);
  }

  /**
   * A string representation of this command object which includes the arguments, the environment,
   * and the working directory. Avoid relying on the specifics of this format. Note that the size of
   * the result string will reflect the size of the command.
   */
  public String toDebugString() {
    StringBuilder message = new StringBuilder(128);
    message.append("Executing (without brackets):");
    for (String arg : subprocessBuilder.getArgv()) {
      message.append(" [");
      message.append(arg);
      message.append(']');
    }
    message.append("; environment: ");
    message.append(subprocessBuilder.getEnv());
    message.append("; working dir: ");
    File workingDirectory = subprocessBuilder.getWorkingDirectory();
    message.append(workingDirectory == null ?
                   "(current)" :
                   workingDirectory.toString());
    return message.toString();
  }

  private FutureCommandResult doExecute(
      InputStream stdinInput, OutErrConsumers outErrConsumers, boolean killSubprocessOnInterrupt) 
          throws ExecFailedException {
    Preconditions.checkNotNull(stdinInput, "stdinInput");
    logCommand();

    Subprocess process = startProcess();

    outErrConsumers.logConsumptionStrategy();
    outErrConsumers.registerInputs(
        process.getInputStream(), process.getErrorStream(), /* closeStreams= */ false);

    // TODO(ulfjack): This call blocks until all input is written. If stdinInput is large (or
    // unbounded), then the async calls can block for a long time, and the timeout is not properly
    // enforced.
    processInput(stdinInput, process);

    return new FutureCommandResultImpl(this, process, outErrConsumers, killSubprocessOnInterrupt);
  }

  private Subprocess startProcess() throws ExecFailedException {
    try {
      return subprocessBuilder.start();
    } catch (IOException ioe) {
      throw new ExecFailedException(this, ioe);
    }
  }

  private static class NullInputStream extends InputStream {
    @Override
    public int read() {
      return -1;
    }

    @Override
    public int available() {
      return 0;
    }
  }

  private static void processInput(InputStream stdinInput, Subprocess process) {
    if (logger.isLoggable(Level.FINER)) {
      logger.finer(stdinInput.toString());
    }
    try (OutputStream out = process.getOutputStream()) {
      ByteStreams.copy(stdinInput, out);
    } catch (IOException ioe) {
      // Note: this is not an error!  Perhaps the command just isn't hungry for our input and exited
      // with success. Process.waitFor (later) will tell us.
      //
      // (Unlike out/err streams, which are read asynchronously, the input stream is written
      // synchronously, in its entirety, before processInput returns.  If the input is infinite, and
      // is passed through e.g. "cat" subprocess and back into the ByteArrayOutputStream, that will
      // eventually run out of memory, causing the output stream to be closed, "cat" to terminate
      // with SIGPIPE, and processInput to receive an IOException.
    }
  }

  private void logCommand() {
    if (!logger.isLoggable(Level.FINE)) {
      return;
    }
    logger.fine(toDebugString());
  }
}
