diff --git a/src/main/java/io/nut/base/os/Beep.java b/src/main/java/io/nut/base/os/Beep.java new file mode 100644 index 0000000..3f717b5 --- /dev/null +++ b/src/main/java/io/nut/base/os/Beep.java @@ -0,0 +1,80 @@ +/* + * Beep.java + * + * Copyright (c) 2022-2024 francitoshi@gmail.com + *- + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Report bugs or new features to: francitoshi@gmail.com + */ +package io.nut.base.os; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author franci + */ +public class Beep +{ + private static final String BEEP = "beep"; + private static final Shell shellUtils = Shell.getInstance(OSName.os); + + public static void beep() + { + try + { + String[] cmds = {BEEP}; + shellUtils.doShellCommand(cmds, null, false, true); + } + catch (Exception ex) + { + Logger.getLogger(Beep.class.getName()).log(Level.SEVERE, null, ex); + } + } + public static void beep(double[] freq, int[] millis) + { + try + { + StringBuilder sb = new StringBuilder(BEEP); + for(int i=0;i0) + { + sb.append(" -n"); + } + sb.append(" -f ").append(freq[i]).append(" -l ").append(millis[i]); + } + String[] cmds = {sb.toString()}; + shellUtils.doShellCommand(cmds, null, false, true); + } + catch (Exception ex) + { + Logger.getLogger(Beep.class.getName()).log(Level.SEVERE, null, ex); + } + } + public static void beep(int freq, int millis) + { + try + { + String[] cmds = {BEEP+" -f "+freq+" -l "+millis}; + shellUtils.doShellCommand(cmds, null, false, true); + } + catch (Exception ex) + { + Logger.getLogger(Beep.class.getName()).log(Level.SEVERE, null, ex); + } + } +} diff --git a/src/main/java/io/nut/base/os/Shell.java b/src/main/java/io/nut/base/os/Shell.java new file mode 100644 index 0000000..20378e7 --- /dev/null +++ b/src/main/java/io/nut/base/os/Shell.java @@ -0,0 +1,287 @@ +/* + * Shell.java + * + * Copyright (c) 2015-2024 francitoshi@gmail.com + *- + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Report bugs or new features to: francitoshi@gmail.com + */ +package io.nut.base.os; + +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.util.StringTokenizer; +import java.util.logging.Level; +import java.util.logging.Logger; + +class AndroidShell extends Shell +{ + private static final Logger logger = Logger.getLogger(AndroidShell.class.getName()); + + @Override + public boolean isRootPossible() + { + try + { + // Check if Superuser.apk exists + File fileSU = new File("/system/app/Superuser.apk"); + if (fileSU.exists()) + { + return true; + } + + fileSU = new File("/system/bin/su"); + if (fileSU.exists()) + { + return true; + } + + //Check for 'su' binary + String[] cmd = { "which su" }; + int exitCode = doShellCommand(null, cmd, new ShellCallback() + { + public void shellOut(String msg) + { + //System.out.print(msg); + } + public void processComplete(int exitValue) + { + // TODO Auto-generated method stub + } + + }, false, true).exitValue(); + + if (exitCode == 0) + { + logger.log(Level.CONFIG, "Can acquire root permissions"); + return true; + } + } + catch (IOException e) + { + //this means that there is no root to be had (normally) so we won't log anything + logger.log(Level.SEVERE, "Error checking for root access", e); + } + catch (Exception e) + { + logger.log(Level.SEVERE, "Error checking for root access", e); + //this means that there is no root to be had (normally) + } + + logger.log(Level.SEVERE, "Could not acquire root permissions"); + + return false; + } +} + +class PosixShell extends Shell +{ + + @Override + public boolean isRootPossible() + { + return false; + } +} + +public abstract class Shell +{ + private static final Logger logger = Logger.getLogger(Shell.class.getName()); + //various console cmds + public final static String SHELL_CMD_CHMOD = "chmod"; + public final static String SHELL_CMD_KILL = "kill -9"; + public final static String SHELL_CMD_RM = "rm"; + public final static String SHELL_CMD_PS = "ps"; + public final static String SHELL_CMD_PIDOF = "pidof"; + + public final static String CHMOD_EXE_VALUE = "700"; + + public interface ShellCallback + { + void shellOut(String shellLine); + void processComplete(int exitValue); + } + + public static Shell getInstance(OSName osName) + { + if (osName.isAndroid()) + { + return new AndroidShell(); + } + return new PosixShell(); + } + + public final static Shell sh = getInstance(OSName.os); + + public abstract boolean isRootPossible(); + + public int findProcessId(String command) + { + int procId = -1; + + try + { + procId = findProcessIdWithPidOf(command); + + if (procId == -1) + { + procId = findProcessIdWithPS(command); + } + } + catch (Exception ex) + { + try + { + procId = findProcessIdWithPS(command); + } + catch (Exception e2) + { + logger.log(Level.SEVERE, "Unable to get proc id for: " + command, e2); + } + } + + return procId; + } + + //use 'pidof' command + public int findProcessIdWithPidOf(String command) throws Exception + { + int procId = -1; + + Runtime r = Runtime.getRuntime(); + + Process procPs; + + String baseName = new File(command).getName(); + + //fix contributed my mikos on 2010.12.10 + procPs = r.exec(new String[] { SHELL_CMD_PIDOF, baseName }); + //procPs = r.exec(SHELL_CMD_PIDOF); + + BufferedReader reader = new BufferedReader(new InputStreamReader(procPs.getInputStream())); + + String line; + while ((line = reader.readLine()) != null) + { + try + { + //this line should just be the process id + procId = Integer.parseInt(line.trim()); + break; + } + catch (NumberFormatException e) + { + logger.log(Level.SEVERE, "unable to parse process pid: " + line, e); + } + } + + return procId; + } + + //use 'ps' command + public int findProcessIdWithPS(String command) throws Exception + { + int procId = -1; + + Runtime r = Runtime.getRuntime(); + + Process procPs = r.exec(SHELL_CMD_PS); + + BufferedReader reader = new BufferedReader(new InputStreamReader(procPs.getInputStream())); + String line; + + while ((line = reader.readLine()) != null) + { + if (line.contains(' ' + command)) + { + + StringTokenizer st = new StringTokenizer(line, " "); + st.nextToken(); //proc owner + + procId = Integer.parseInt(st.nextToken().trim()); + + break; + } + } + return procId; + } + + public int doShellCommand(String[] cmds, ShellCallback sc, boolean runAsRoot, boolean waitFor) throws Exception + { + return doShellCommand(null, cmds, sc, runAsRoot, waitFor).exitValue(); + } + + public Process doShellCommand(Process proc, String[] cmds, ShellCallback sc, boolean runAsRoot, boolean waitFor) throws Exception + { + if (proc == null) + { + proc = Runtime.getRuntime().exec(runAsRoot ? "su" : "sh"); + } + + OutputStreamWriter out = new OutputStreamWriter(proc.getOutputStream()); + + for (String cmd : cmds) + { + logger.log(Level.CONFIG, "executing shell cmd: {0}; runAsRoot={1};waitFor={2}", new Object[] + { + cmd, runAsRoot, waitFor + }); + out.write(cmd); + out.write("\n"); + } + + out.flush(); + out.write("exit\n"); + out.flush(); + + if (waitFor) + { + final char buf[] = new char[20]; + + // Consume the "stdout" + InputStreamReader reader = new InputStreamReader(proc.getInputStream()); + int read = 0; + while ((read = reader.read(buf)) != -1) + { + if (sc != null) + { + sc.shellOut(new String(buf)); + } + } + + // Consume the "stderr" + reader = new InputStreamReader(proc.getErrorStream()); + read = 0; + while ((read = reader.read(buf)) != -1) + { + if (sc != null) + { + sc.shellOut(new String(buf)); + } + } + proc.waitFor(); + } + + if (sc != null) + { + sc.processComplete(proc.exitValue()); + } + + return proc; + } +} diff --git a/src/main/java/io/nut/base/util/Assert.java b/src/main/java/io/nut/base/util/Assert.java index 142ade5..20b4c7d 100644 --- a/src/main/java/io/nut/base/util/Assert.java +++ b/src/main/java/io/nut/base/util/Assert.java @@ -1,4 +1,4 @@ -package io.tea.base.util; +package io.nut.base.util; import java.lang.reflect.Array; import java.util.Arrays;