i have a code :
private static String writeCommandToConsole(Process proc, String command, boolean ignoreError) throws Exception {
byte[] tmpArray = new byte[1024];
proc.getOutputStream().write((command + "\n").getBytes());
proc.getOutputStream().flush();
int bytesRead;
if (proc.getErrorStream().available() > 0) {
if ((bytesRead = proc.getErrorStream().read(tmpArray)) > 1) {
Log.e(LOG_TAG, new String(tmpArray, 0, bytesRead));
if (!ignoreError)
throw new Exception(new String(tmpArray, 0, bytesRead));
}
}
if (proc.getInputStream().available() > 0) {
bytesRead = proc.getInputStream().read(tmpArray);
Log.i(LOG_TAG, new String(tmpArray, 0, bytesRead));
}
return new String(tmpArray);
}
public static void Changes(Context con, int fNums, String fNames, int is, boolean bools, String strs) {
final String fNum = String.valueOf(fNums);
final String fName = fNames;
final String i = String.valueOf(is);
final String str = strs;
final String bool = bools ? "true" : "false";
final String path = pathExecutable + " " + fNum + " \"" + fName + "\" " + i + " " + bool + " \"" + str + "\"";
new Thread(new Runnable() {
#Override
public void run() {
try {
if (isRoot) {
Process proc = Runtime.getRuntime().exec(new String[]{"su"});
writeCommandToConsole(proc, path, true);
} else {
Process proc = Runtime.getRuntime().exec(path);
proc.wait();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
}
for root is work well (my phone is rooted) .. but for non root it not work (use parallel space, virtualXposed,etc in non root phone) .. in non root only work in virtual machine which have a root (vmos,x8 sabdbox etc).
i was try use processBuilder but have a same result .. executable lib seem not get into the target ..
how to write a correct runtime.exec to make it work on non root phone (use parallel space or any cloner without virtual machine with root include) ? or is it any way to make it posible to run executable lib without su command ?
solved .. i change non root command into
Process proc = Runtime.getRuntime().exec(new String[]{"sh"});
writeCommandToConsole(proc, path, true);
and it run well in some virtual app ..
Related
I need to write a generic interactive ProcessBuilder client based on commands and breakpoints to interact with the same python script several times.
The idea is that each (n+1) command (except n=0 ofc) will wait to read in the output stream the (n-1) breakpoint.
The client's output will be the output stream from the first command to the last one.
Ex of script:
def show_menu():
print('Select an option:' + '\n')
print('[1] Fullname')
print('[2] Username')
print('[3] Password')
def app_start():
show_menu()
try:
choice = int(input('\n' + 'Your selection: '))
app_start()
except KeyboardInterrupt:
sys.exit(0)
else:
if choice == 1:
input = input("Enter your fullname")
print(f'Your fullname is: {input}')
if choice == 2:
input = input("Enter your Username")
print(f'Your username is: {input}')
if choice == 3:
input = input("Enter your password: ")
print(f'Your password is : {input}')
def main():
app_start()
# Start Here
if __name__ == "__main__":
main()
Example of input to the Process builder client:
[
{
"cmd": "python3 C:\\pathToScript\\script.py",
"breakpoint": "Your selection:"
},
{
"cmd": "3\n",
"breakpoint": "Enter your password: "
},
{
"cmd": "John Doe\n",
"breakpoint": "Your password is: "
}
]
The Output of the client for this case will be:
[1] Fullname
[2] Username
[3] Password
Your selection: 3
Enter your password password123
Your password is: password123
Thanks in advance for any help, I'm new to Java and newer to ProcessBuilder :).
This seems to be working just fine, putting the thread to sleep for 100 ms is prob only a good idea for scripts that don't take long to execute though. If anyone sees caveats on this approach please feel free to leave a comment.
String actionCommands = "[\n" +
" {\n" +
" \"cmd\": \"python3 C:\\pathToScript\\script.py\" +
" \"breakpoint\": \"Your selection:\"\n" +
" },\n" +
" {\n" +
" \"cmd\": \"3\\n\",\n" +
" \"breakpoint\": \"Enter your password:\"\n" +
" },\n" +
" {\n" +
" \"cmd\": \"password123\\n\",\n" +
" \"breakpoint\": \"Your password is: \"\n" +
" }\n" +
" ]";
org.json.JSONArray arrayCmds = new org.json.JSONArray(actionCommands);
System.out.printf("arrayCmds %s\n", arrayCmds.toString());
Process process = null;
org.json.JSONObject objInit = arrayCmds.getJSONObject(0);
String cmdInit = objInit.getString("cmd");
ProcessBuilder processBuilder1 = new ProcessBuilder(cmdInit.split(" "));
processBuilder1.redirectErrorStream(true);
try {
process = processBuilder1.start();
Thread inThread = new Thread((Runnable) new In(process.getInputStream()));
inThread.start();
processBuilder1.inheritIO();
BufferedReader inputStream = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errStream = new BufferedReader(new InputStreamReader(process.getErrorStream()));
OutputStream writeTo = process.getOutputStream();
for (int i = 1 ; i < arrayCmds.length(); i++) {
org.json.JSONObject obj = arrayCmds.getJSONObject(i);
org.json.JSONObject objBrkPt = arrayCmds.getJSONObject(i-1);
String cmd = obj.getString("cmd");
String breakpoint = objBrkPt.getString("breakpoint");
Thread.sleep(100);
while (((inputStream.readLine())!=null && inputStream.readLine()!=breakpoint))
{
writeTo.write(cmd.getBytes());
writeTo.flush();
break;
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
This is the implementation of the In class
public class In implements Runnable {
private InputStream is;
private List<String> out = new ArrayList<String>();
public In(InputStream is) {
this.is = is;
}
public List<String> output() {
return out;
}
#Override
public void run() {
byte[] b = new byte[1024];
int size = 0;
try {
while ((size = is.read(b)) != -1) {
out.add(new String(b));
System.err.println(new String(b));
}
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
there is something wront with implementation as it fails randomly in capturing the last part of the stream that contains the pwd
currently I'm facing an issue where the URL that are outputted in the console is different from the actual URL display in the nav bar. I look at the value that I had regex, it was correct but when put into IE, it is different. The URL in the nav bar would be only a=test instead of a=test&c=import&f=&uid=user1 which is what is shown in the console. May I know how to solve this? Thanks.
Here is the codes for it.
UserID user = new UserID();
public static void main(String[] args) {
String newUrl = replaceUserID(url);
System.out.print("cmd.exe /c start iexplore -k " + newUrl);
try{
Process p = Runtime.getRuntime().exec("cmd.exe /c start iexplore " + newUrl);
try{
p.waitFor();
}
catch( InterruptedException ie ){
System.out.println("InterruptedException " + ie.getMessage());
}
InputStream err = p.getErrorStream();
int ctr = 0;
if ( (ctr = err.available()) > 0 ){
byte[] buf = new byte[ctr];
System.out.println("Process failed with error:\n" + new String(buf, 0, ctr));
}
}
catch(IOException ioe)
{
System.out.println("InterruptedException " + ioe.getMessage());
}
}
public static String checkUserID(){
String username = System.getenv("USERNAME"); //grab user login id for windows
return username;
}
public static String replaceUserID(String oldUrl) {
String params = "http://example.com?a=test&c=import&f=&uid=userid";
String username = checkUserID();
try {
Pattern p = Pattern.compile("uid=([^&%]+)");
Matcher m = p.matcher(params);
while (m.find()) {
// System.out.println(m.group(1).toString());
if(m.group(1).toString() != username) {
//replace url paremeters with correct userID.
String newUrl = params.replace(m.group(1).toString(), username);
return newUrl;
}
else {
System.out.println("The username is the same");
return params;
}
}
} catch (PatternSyntaxException ex) {
// error handling
ex.printStackTrace();
}
return oldUrl;
}
& has a special meaning to the command line (concat commands, see here: How do I run two commands in one line in Windows CMD?).
You need to escape the url or maybe the entire command. If I remember correctly you need to put double quotes around it: "...iexplore -k \"" + newUrl + "\""
I have to execute batch file present at remote machine from my local machine.
I am connecting through ftp to remote machine and try to execute batch file remotely.but not able to do that also not getiing any exception .below is my code
public static void main(String[] args) throws SocketException, IOException,
InterruptedException {
static String server = "192.168.2.133";
static int port = 21;
static String user = "kamal";
static String pass = "12345";
static FTPClient ftpClient;
// TODO Auto-generated method stub
ftpClient = new FTPClient();
ftpClient.connect(server, port);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.changeWorkingDirectory("/");
System.out.println(ftpClient.isConnected());
// ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
System.out.println("ftpClient.printWorkingDirectory() "
+ ftpClient.printWorkingDirectory());
String[] str = ftpClient.listNames(ftpClient.printWorkingDirectory());
for (String string : str) {
System.out.println(string);
}
// ftpClient.changeWorkingDirectory(ftpClient.printWorkingDirectory().concat("demo"));
System.out.println("ftpClient.printWorkingDirectory() "
+ ftpClient.printWorkingDirectory());
String psCommand = "C:/Users/kamlesh.kumar/Downloads/PSTools/PsExec.exe //"
+ server + " -u " + user + " -p " + pass;
psCommand = psCommand + " " + "MEF.bat";
// psCommand = psCommand + " " + commandToRunOnRemoteMachine + " " +
// parameters;
String[] cmd = new String[5];
cmd[0] = "cmd.exe";
cmd[1] = "/C";
cmd[2] = psCommand;
cmd[3] = "";
cmd[4] = "";
// Run remote command
// ftpClient.changeWorkingDirectory(ftpClient.printWorkingDirectory().concat("\\\\192.168.2.135\\demo\\demo"));
// System.out.println(ftpClient.printWorkingDirectory());
File f = new File(ftpClient.printWorkingDirectory());
Process p = null;
try {
p = Runtime.getRuntime().exec(cmd, null, f);
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
int exitStatus = 0;
try {
exitStatus = p.waitFor();
System.out.println("exitStatus in try " + exitStatus);
} catch (Exception e) {
System.out.println("exitStatus" + exitStatus);
System.out.println(e.toString());
e.printStackTrace();
} finally {
System.out.println("exitStatus in finally " + exitStatus);
}
if (exitStatus == 0) {
System.out.println("Done");
}
}
You can get PSEXEC from https://technet.microsoft.com/en-us/sysinternals/pxexec.aspx and what I have done before was make a batch file that would copy the file you want ran on the remote pc to that PC then use PSEXEC to execute it remotly and also delete that file that was made. I do not know if that is what you're looking for but it might be sufficient.
set remotecpu="computer you're sending it to"
robocopy "localpcdrive\location1\scripts\script you want ran" \\%remotecpu%\c$\temp_folder
psexec \\%remotecpu% -u "username" -p "password" -i -d "C:\temp_folder\path to\script you want ran"
And if I am not mistaken that will execute the file for you then just do a del command and remove the temp_folder your script is under. Or use something fancy like
If Exist "%SystemDrive%\temp_folder" (RD/S/Q "%SystemDrive%\temp_folder")
I'm trying to use mysqldump with java to create a dump for my database.
I've done the code but the condition if(processCompleted == 0) never happens for some reason that I can not understand. And I say this because on the console there is no exception but it always prints
"Error doing dump!"
which leads me to conclude that if(processCompleted == 0) is never meet.
Can someone please explain me what I'm doing wrong here?
public boolean backupDatabase(String path, String whichServer)
{
String cmd;
Process runtimeProcess;
if(whichServer.equalsIgnoreCase("local"))
{
cmd = "mysqldump -u " + getSourceUsername() + " -p" + getSourceServerPassword()
+ " --add-drop-database -B " + getSourceDatabase() + " -r " + path;
}
else if(whichServer.equalsIgnoreCase("remote"))
{
cmd = "mysqldump -u " + getDestinationUsername() + " -p" + getDestinationServerPassword()
+ " --add-drop-database -B " + getDestinationDatabase() + " -r " + path;
}
else
{
System.out.println("Input server incorrect");
return false;
}
try{
String[] cmdArray = new String[]{"C:\\wamp\\bin\\mysql\\mysql5.5.24\\bin\\mysqldump.exe", cmd};
System.out.println("Preparing for dump.");
runtimeProcess = Runtime.getRuntime().exec(cmdArray);
int processCompleted = runtimeProcess.waitFor();
if(processCompleted == 0)
{
System.out.println("Dump done!");
return true;
}
else
{
System.out.println("Error doing dump!");
}
} catch(Exception ex)
{
System.out.println("Exception -> " + ex.getMessage());
}
return false;
}
Here's my code using #MadProgrammer suggestion:
public boolean backupDatabase(String path, String whichServer)
{
List<String> args = new ArrayList<String>();
args.add("C:\\wamp\\bin\\mysql\\mysql5.5.24\\bin\\mysqldump.exe");
args.add("-u");
args.add(getSourceUsername());
args.add("-p");
args.add(getSourceServerPassword());
args.add("--add-drop-database");
args.add("-B");
args.add(getSourceDatabase());
args.add("-r");
args.add(path);
try{
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectError();
Process p = pb.start();
InputStream is = p.getInputStream();
int in = -1;
while((in = is.read()) != -1)
{
System.out.println((char) in);
}
int proccessCompleted = p.waitFor();
if(proccessCompleted == 0)
{
System.out.println("Dump done!");
return true;
}
else
{
System.out.println("Error doing dump!");
return false;
}
}
catch(IOException | InterruptedException ex)
{
System.out.println("Exception exportDB -> " + ex.getMessage() + "|" + ex.getLocalizedMessage());
}
return false;
}
PS; where you wrote "//? Is this a single command?" -p is the command for the password and getSourceServerPassword() is the method to get the password.
I suspect because you've separated the cmdArray into only two elements that mysqldump is treating the second array element as a single command line argument.
Also, you've not paying attention to the output of the process which makes it really difficult for your to ascertain what the processing is trying to tell.
You "base" command also includes mysqldump...
"mysqldump -u " + getSourceUsername() + " -p" + getSourceServerPassword()
+ " --add-drop-database -B " + getSourceDatabase() + " -r " + path;
as part of the command, which means you are effectively calling mysqldump mysqldump...
Instead of using a String, place all your commands into some kind of list instead.
Remember, if it's separated by a space on the command line, it's a separate command/element
List<String> args = new ArrayList<String>
args.add("C:\\wamp\\bin\\mysql\\mysql5.5.24\\bin\\mysqldump.exe");
//...
args.add("-u");
args.add(getSourceUsername());
args.add("-p" + getSourceServerPassword()); //?? Is this a single command?
args.add("--add-drop-database");
args.add("-B");
args.add(getSourceDatabase());
args.add("-r");
args.add("path);
//...
Then use ProcessBuilder
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectError();
Process p = pb.start();
InputStream is = p.getInputStream();
int in = -1;
while ((in = is.read()) != -1) {
System.out.print((char)in);
}
int processCompleted = p.waitFor();
Remember, you should never ignore the output from a process, even if you don't care, you should attempt to consume the content from the InputStream as some processes will hang if there output stream is not read.
so I wrote a Java program to change the IP of a machine.
public static void main(String[] args) {
superUserChangeIp(args);
}
public static void superUserChangeIp(String[] args) {
try {
String ethInterface = args[0].toString().trim();
String ip = args[1].toString().trim();
System.out.println(ethInterface + " " + ip);
String[] command = {
"/bin/sh",
"ifconfig " + ethInterface + " " + ip };
Process child = Runtime.getRuntime().exec(command);
changeNetworkInterface(ethInterface, ip);
readOutput(child);
child.destroy();
} catch (IOException e) {
e.printStackTrace();
}
}
I made a simple sh script :
#!/bin/sh
sudo java -jar changeip.jar $1 $2
and I'm getting : /bin/sh: 0: Can't open sudo ifconfig eth0 192.168.217.128 trying to run sh ipconfig.sh eth0 192.168.217.128
Anyone can point me to the right direction?
Note: the method changeNetworkInterface(ethInterface, ip); simply updates the settings found in /etc/network/interfaces, code follows :
protected static void changeNetworkInterface(String ethInterface, String ip) throws IOException {
String oldInterface = File.readFile(NETWORK_INTERFACES_PATH);
StringBuilder builder = new StringBuilder();
Scanner reader = new Scanner(oldInterface);
boolean startReplacing = false;
while (reader.hasNextLine()) {
String currentLine = reader.nextLine();
if (currentLine.contains("iface " + ethInterface)) {
System.out.println("Found interface!");
startReplacing = true;
}
if (startReplacing && currentLine.contains("address")) {
System.out.println("Found IP!");
currentLine = "address " + ip;
startReplacing = false;
}
builder.append(currentLine);
builder.append("\n");
}
System.out.println(builder.toString());
File.writeToFile(NETWORK_INTERFACES_PATH, builder.toString());
}
If you're running the JAR as you described, the application will already have superuser privileges, so you don't need to run sudo inside the app at all.
Really sorry; I just added -c
String[] command = {
"/bin/sh",
"-c", // <--- this bugger right here
"ifconfig " + ethInterface + " " + ip };
And now it works. Thanks everyone.