private void log(String tmp, String col) {
   List<String> tl = Arrays.asList(tmp.split("\n"));
   for (String s : tl) {
     logbuffer.add("<font color='" + col + "'>" + s + "</font><br />");
   }
 }
  public VTCommandResult runCommand(String command, VTCallback callback) throws Exception {
    if (shutdown) {
      return new VTCommandResult(
          1, "VirtalTerminal was already shutdown.", "VirtalTerminal was already shutdown.");
    }

    StringBuilder inpStringBuilder = new StringBuilder();
    StringBuilder errStringBuilder = new StringBuilder();

    Log.i(TAGC, command);
    synchronized (WriteLock) {
      inpbuffer.reset();
      errbuffer.reset();
    }

    logbuffer.add("<font color='#0000bb'>" + command + "</font><br />");
    toProcess.writeBytes(command + "; echo :RET=$?");
    toProcess.writeBytes("\n");
    toProcess.flush();
    while (!shutdown) {
      synchronized (ReadLock) {
        boolean doWait;
        synchronized (WriteLock) {
          byte[] inpbyte = inpbuffer.toByteArray();
          String inp = new String(inpbyte);
          Log.i(TAGR, inp);
          inpStringBuilder.append(inp);
          inpbuffer.reset();
          doWait = !inpStringBuilder.toString().contains(":RET=");
          if (callback != null) {
            callback.onProgress(inpStringBuilder, errStringBuilder, toProcess);
          }
        }
        if (doWait) {
          ReadLock.wait();
        }
      }
      synchronized (WriteLock) {
        byte[] inpbyte = inpbuffer.toByteArray();
        byte[] errbyte = errbuffer.toByteArray();

        String tinp = new String(inpbyte);
        String terr = new String(errbyte);

        Log.i(TAGR, tinp);

        inpStringBuilder.append(tinp);
        inpbuffer.reset();
        errStringBuilder.append(terr);
        errbuffer.reset();

        String inp = inpStringBuilder.toString();
        String err = errStringBuilder.toString();

        if (callback != null) {
          callback.onProgress(inpStringBuilder, errStringBuilder, toProcess);
        }

        if (err.contains("Permission denied")) throw new BrokenPipeException();

        if (inp.contains(":RET=")) {
          if (inp.contains(":RET=EOF") || err.contains(":RET=EOF")) throw new BrokenPipeException();
          if (inp.contains(":RET=0")) {
            if (inp.length() < 8) inp = "";
            else inp = inp.substring(0, inp.length() - 8);
            log(inp, "#999999");
            log(err, "#999999");
            return new VTCommandResult(0, inp, err);
          } else {
            log(inp, "#999999");
            log(err, "#999999");
            Log.i(TAGR, err);
            return new VTCommandResult(1, inp, err);
          }
        }
      }
    }
    return new VTCommandResult(-1);
  }