protected boolean returnPath() {
   File tmpDir = new File("/data/local/tmp");
   if (!tmpDir.exists()) {
     doExec(new String[] {"mkdir /data/local/tmp"});
   }
   try {
     InternalVariables.path = new HashSet<String>();
     // Try to read from the file.
     LineNumberReader lnr = null;
     doExec(
         new String[] {
           "dd if=/init.rc of=/data/local/tmp/init.rc", "chmod 0777 /data/local/tmp/init.rc"
         });
     lnr = new LineNumberReader(new FileReader("/data/local/tmp/init.rc"));
     String line;
     while ((line = lnr.readLine()) != null) {
       RootTools.log(line);
       if (line.contains("export PATH")) {
         int tmp = line.indexOf("/");
         InternalVariables.path =
             new HashSet<String>(Arrays.asList(line.substring(tmp).split(":")));
         return true;
       }
     }
     return false;
   } catch (Exception e) {
     if (RootTools.debugMode) {
       RootTools.log("Error: " + e.getMessage());
       e.printStackTrace();
     }
     return false;
   }
 }
  /**
   * Sends several shell command as su (attempts to)
   *
   * @param commands array of commands to send to the shell
   * @param sleepTime time to sleep between each command, delay.
   * @param result injected result object that implements the Result class
   * @return a <code>LinkedList</code> containing each line that was returned by the shell after
   *     executing or while trying to execute the given commands. You must iterate over this list,
   *     it does not allow random access, so no specifying an index of an item you want, not like
   *     you're going to know that anyways.
   * @throws InterruptedException
   * @throws IOException
   * @throws TimeoutException
   */
  synchronized List<String> sendShell(
      String[] commands, int sleepTime, Result result, boolean useRoot, int timeout)
      throws IOException, RootToolsException, TimeoutException {

    RootTools.log(
        "Sending " + commands.length + " shell command" + (commands.length > 1 ? "s" : ""));

    Worker worker = new Worker(this, commands, sleepTime, result, useRoot);
    worker.start();

    try {
      if (timeout == -1) {
        timeout = 300000;
      }

      worker.join(timeout);

      // small pause, let things catch up
      Thread.sleep(RootTools.shellDelay);

      if (worker.exit != -911) return worker.finalResponse;
      else throw new TimeoutException();
    } catch (InterruptedException ex) {
      worker.interrupt();
      Thread.currentThread().interrupt();
      throw new TimeoutException();
    }
  }
  public boolean checkRoot() {
    boolean result = true;

    // No need to do more shell calls if we already did the checks
    if (CHECKED_ROOT && !ROOT_AVAILABLE)
      // We already checked root and it wasn't available
      return false;

    if (!ROOT_AVAILABLE) {
      if (!RootTools.isRootAvailable()) {
        // TODO: Make a new dialog class that explains root access
        RootTools.log("Root access isn't available");
        result = false;
      } else if (!RootTools.isAccessGiven()) {
        RootTools.log("Root access denied by user");
        result = false;
      } else {
        ROOT_AVAILABLE = true;
      }
    }

    CHECKED_ROOT = true;
    return result;
  }
  protected ArrayList<Mount> getMounts() throws FileNotFoundException, IOException {
    LineNumberReader lnr = null;
    try {
      lnr = new LineNumberReader(new FileReader("/proc/mounts"));
      String line;
      ArrayList<Mount> mounts = new ArrayList<Mount>();
      while ((line = lnr.readLine()) != null) {

        RootTools.log(line);

        String[] fields = line.split(" ");
        mounts.add(
            new Mount(
                new File(fields[0]), // device
                new File(fields[1]), // mountPoint
                fields[2], // fstype
                fields[3] // flags
                ));
      }
      return mounts;
    } finally {
      // no need to do anything here.
    }
  }
    public void run() {
      DataOutputStream os = null;
      InputStreamReader osRes = null;
      InputStreamReader osErr = null;

      try {
        if (executer.process == null) {
          Runtime.getRuntime().gc();

          if (RootTools.customShell.equals("")) {
            executer.process = Runtime.getRuntime().exec(useRoot ? "su" : "sh");
            RootTools.log(useRoot ? "Using Root" : "Using sh");
          } else {
            executer.process = Runtime.getRuntime().exec(RootTools.customShell);
            RootTools.log("Using custom shell: " + RootTools.customShell);
          }

          if (null != executer.result) {
            executer.result.setProcess(executer.process);
          }
        }

        os = new DataOutputStream(executer.process.getOutputStream());
        osRes = new InputStreamReader(executer.process.getInputStream());
        osErr = new InputStreamReader(executer.process.getErrorStream());
        BufferedReader reader = new BufferedReader(osRes);
        BufferedReader reader_error = new BufferedReader(osErr);

        List<String> response = null;

        if (null == executer.result) {
          response = new LinkedList<String>();
        }

        try {

          // Doing Stuff ;)
          for (String single : commands) {
            RootTools.log("Shell command: " + single);
            os.writeBytes(single + "\n");
            os.flush();
            Thread.sleep(sleepTime);
          }

          os.writeBytes("exit \n");
          os.flush();

          String line = reader.readLine();
          String line_error = reader_error.readLine();

          while (line != null) {
            if (null == executer.result) {
              response.add(line);
            } else {
              executer.result.process(line);
            }

            RootTools.log("input stream: " + line);

            line = reader.readLine();
          }

          RootTools.log("Done reading input stream");

          while (line_error != null) {
            if (null == executer.result) {
              response.add(line_error);
            } else {
              executer.result.processError(line_error);
            }

            RootTools.log("error stream: " + line_error);
            line_error = reader_error.readLine();
          }

          RootTools.log("Done reading error stream");

        } catch (Exception ex) {
          if (RootTools.debugMode) {
            RootTools.log("Error: " + ex.getMessage());
          }

          if (null != executer.result) {
            executer.result.onFailure(ex);
          }
        } finally {
          RootTools.log("In finally block");

          if (executer.process != null) {
            RootTools.log("Getting Exit");
            finalResponse = response;
            exit = -1;
            exit = executer.process.waitFor();
            RootTools.log("Exit done...");
            RootTools.lastExitCode = exit;

            if (null != executer.result) {
              executer.result.onComplete(exit);
            } else {
              response.add(Integer.toString(exit));
            }
          }
        }
      } catch (InterruptedException ignore) {
        return;
      } catch (Exception e) {
        if (RootTools.debugMode) {
          e.printStackTrace();
          RootTools.log("Error: " + e.getMessage());
        }
      } finally {

        try {

          if (os != null) {
            os.writeBytes("exit \n");
            os.flush();
            os.close();
            os = null;
          }
          if (osRes != null) {
            osRes.close();
            osRes = null;
          }
          if (osErr != null) {
            osErr.close();
            osErr = null;
          }
        } catch (Exception ignore) {
        }

        executer.closeShell();
      }
    }
  /**
   * This will take a path, which can contain the file name as well, and attempt to remount the
   * underlying partition.
   *
   * <p>For example, passing in the following string:
   * "/system/bin/some/directory/that/really/would/never/exist" will result in /system ultimately
   * being remounted. However, keep in mind that the longer the path you supply, the more work this
   * has to do, and the slower it will run.
   *
   * @param file file path
   * @param mountType mount type: pass in RO (Read only) or RW (Read Write)
   * @return a <code>boolean</code> which indicates whether or not the partition has been remounted
   *     as specified.
   */
  protected boolean remount(String file, String mountType) {

    // if the path has a trailing slash get rid of it.
    if (file.endsWith("/") && !file.equals("/")) {
      file = file.substring(0, file.lastIndexOf("/"));
    }
    // Make sure that what we are trying to remount is in the mount list.
    boolean foundMount = false;
    while (!foundMount) {
      try {
        for (Mount mount : RootTools.getMounts()) {
          RootTools.log(mount.getMountPoint().toString());

          if (file.equals(mount.getMountPoint().toString())) {
            foundMount = true;
            break;
          }
        }
      } catch (Exception e) {
        if (RootTools.debugMode) {
          e.printStackTrace();
        }
        return false;
      }
      if (!foundMount) {
        try {
          file = (new File(file).getParent()).toString();
        } catch (Exception e) {
          e.printStackTrace();
          return false;
        }
      }
    }
    Mount mountPoint = findMountPointRecursive(file);

    RootTools.log(
        InternalVariables.TAG,
        "Remounting "
            + mountPoint.getMountPoint().getAbsolutePath()
            + " as "
            + mountType.toLowerCase());
    final boolean isMountMode = mountPoint.getFlags().contains(mountType.toLowerCase());

    if (!isMountMode) {
      // grab an instance of the internal class
      try {
        CommandCapture command =
            new CommandCapture(
                0,
                "busybox mount -o remount,"
                    + mountType.toLowerCase()
                    + " "
                    + mountPoint.getDevice().getAbsolutePath()
                    + " "
                    + mountPoint.getMountPoint().getAbsolutePath(),
                "toolbox mount -o remount,"
                    + mountType.toLowerCase()
                    + " "
                    + mountPoint.getDevice().getAbsolutePath()
                    + " "
                    + mountPoint.getMountPoint().getAbsolutePath(),
                "mount -o remount,"
                    + mountType.toLowerCase()
                    + " "
                    + mountPoint.getDevice().getAbsolutePath()
                    + " "
                    + mountPoint.getMountPoint().getAbsolutePath(),
                "/system/bin/toolbox mount -o remount,"
                    + mountType.toLowerCase()
                    + " "
                    + mountPoint.getDevice().getAbsolutePath()
                    + " "
                    + mountPoint.getMountPoint().getAbsolutePath());

        Shell.startRootShell().add(command);
        command.waitForFinish();

      } catch (Exception e) {
      }

      mountPoint = findMountPointRecursive(file);
    }

    Log.i(InternalVariables.TAG, mountPoint.getFlags() + " AND " + mountType.toLowerCase());
    if (mountPoint.getFlags().contains(mountType.toLowerCase())) {
      RootTools.log(mountPoint.getFlags().toString());
      return true;
    } else {
      RootTools.log(mountPoint.getFlags().toString());
      return false;
    }
  }
  protected void doExec(String[] commands) {
    Process process = null;
    DataOutputStream os = null;
    InputStreamReader osRes = null;

    try {
      process = Runtime.getRuntime().exec("su");
      os = new DataOutputStream(process.getOutputStream());
      osRes = new InputStreamReader(process.getInputStream());
      BufferedReader reader = new BufferedReader(osRes);

      // Doing Stuff ;)
      for (String single : commands) {
        os.writeBytes(single + "\n");
        os.flush();
      }

      os.writeBytes("exit \n");
      os.flush();

      String line = reader.readLine();

      while (line != null) {
        if (commands[0].equals("id")) {
          Set<String> ID = new HashSet<String>(Arrays.asList(line.split(" ")));
          for (String id : ID) {
            if (id.toLowerCase().contains("uid=0")) {
              InternalVariables.accessGiven = true;
              Log.i(InternalVariables.TAG, "Access Given");
              break;
            }
          }
          if (!InternalVariables.accessGiven) {
            Log.i(InternalVariables.TAG, "Access Denied?");
          }
        }
        if (commands[0].equals("df") && line.contains(InternalVariables.getSpaceFor)) {
          InternalVariables.space = line.split(" ");
        }
        RootTools.log(line);

        line = reader.readLine();
      }

      process.waitFor();

    } catch (Exception e) {
      if (RootTools.debugMode) {
        RootTools.log("Error: " + e.getMessage());
        e.printStackTrace();
      }
    } finally {
      try {
        if (os != null) {
          os.close();
        }
        if (osRes != null) {
          osRes.close();
        }
        process.destroy();
      } catch (Exception e) {
        if (RootTools.debugMode) {
          RootTools.log("Error: " + e.getMessage());
          e.printStackTrace();
        }
      }
    }
  }