Update from Google.

--
MOE_MIGRATED_REVID=85702957
diff --git a/src/main/java/com/google/devtools/build/lib/shell/TerminationStatus.java b/src/main/java/com/google/devtools/build/lib/shell/TerminationStatus.java
new file mode 100644
index 0000000..73616c4
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/shell/TerminationStatus.java
@@ -0,0 +1,162 @@
+// Copyright 2014 Google Inc. 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;
+
+/**
+ * Represents the termination status of a command.  {@link Process#waitFor} is
+ * not very precisely specified, so this class encapsulates the interpretation
+ * of values returned by it.
+ *
+ * Caveat: due to the lossy encoding, it's not always possible to accurately
+ * distinguish signal and exit cases.  In particular, processes that exit with
+ * a value within the interval [129, 191] will be mistaken for having been
+ * terminated by a signal.
+ *
+ * Instances are immutable.
+ */
+public final class TerminationStatus {
+
+  private final int waitResult;
+
+  /**
+   * Values taken from the glibc strsignal(3) function.
+   */
+  private static final String[] SIGNAL_STRINGS = {
+    null,
+    "Hangup",
+    "Interrupt",
+    "Quit",
+    "Illegal instruction",
+    "Trace/breakpoint trap",
+    "Aborted",
+    "Bus error",
+    "Floating point exception",
+    "Killed",
+    "User defined signal 1",
+    "Segmentation fault",
+    "User defined signal 2",
+    "Broken pipe",
+    "Alarm clock",
+    "Terminated",
+    "Stack fault",
+    "Child exited",
+    "Continued",
+    "Stopped (signal)",
+    "Stopped",
+    "Stopped (tty input)",
+    "Stopped (tty output)",
+    "Urgent I/O condition",
+    "CPU time limit exceeded",
+    "File size limit exceeded",
+    "Virtual timer expired",
+    "Profiling timer expired",
+    "Window changed",
+    "I/O possible",
+    "Power failure",
+    "Bad system call",
+  };
+
+  private static String getSignalString(int signum) {
+    return signum > 0 && signum < SIGNAL_STRINGS.length
+        ? SIGNAL_STRINGS[signum]
+        : "Signal " + signum;
+  }
+
+  /**
+   * Construct a TerminationStatus instance from a Process waitFor code.
+   *
+   * @param waitResult the value returned by {@link java.lang.Process#waitFor}.
+   */
+  public TerminationStatus(int waitResult) {
+    this.waitResult = waitResult;
+  }
+
+  /**
+   * Returns the "raw" result returned by Process.waitFor.
+   */
+  int getRawResult() {
+    return waitResult;
+  }
+
+  /**
+   * Returns true iff the process exited with code 0.
+   */
+  public boolean success() {
+    return exited() && getExitCode() == 0;
+  }
+
+  // We're relying on undocumented behaviour of Process.waitFor, specifically
+  // that waitResult is the exit status when the process returns normally, or
+  // 128+signalnumber when the process is terminated by a signal.  We further
+  // assume that value signal numbers fall in the interval [1, 63].
+  private static final int SIGNAL_1  = 128 + 1;
+  private static final int SIGNAL_63 = 128 + 63;
+
+  /**
+   * Returns true iff the process exited normally.
+   */
+  public boolean exited() {
+    return waitResult < SIGNAL_1 || waitResult > SIGNAL_63;
+  }
+
+  /**
+   * Returns the exit code of the subprocess.  Undefined if exited() is false.
+   */
+  public int getExitCode() {
+    if (!exited()) {
+      throw new IllegalStateException("getExitCode() not defined");
+    }
+    return waitResult;
+  }
+
+  /**
+   * Returns the number of the signal that terminated the process.  Undefined
+   * if exited() returns true.
+   */
+  public int getTerminatingSignal() {
+    if (exited()) {
+      throw new IllegalStateException("getTerminatingSignal() not defined");
+    }
+    return waitResult - SIGNAL_1 + 1;
+  }
+
+  /**
+   * Returns a short string describing the termination status.
+   * e.g. "Exit 1" or "Hangup".
+   */
+  public String toShortString() {
+    return exited()
+      ? ("Exit " + getExitCode())
+      : (getSignalString(getTerminatingSignal()));
+  }
+
+  @Override
+  public String toString() {
+    return exited()
+      ? ("Process exited with status " + getExitCode())
+      : ("Process terminated by signal " + getTerminatingSignal());
+  }
+
+  @Override
+  public int hashCode() {
+    return waitResult;
+  }
+
+  @Override
+  public boolean equals(Object other) {
+    return other instanceof TerminationStatus &&
+      ((TerminationStatus) other).waitResult == this.waitResult;
+  }
+}