1

My question is this, I am running some adb commands through the terminal. I wrote a tool; that will help make things easier. So back to the question, in order to make the command run, I have to enter a "password" on the terminal. So how do I what do I do to make the "password" part appear on a JOptionPane.showInputDialog box?

Here is what I have so far:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;


public class flash implements ActionListener {
    private File runfile;
    @Override
    public void actionPerformed(ActionEvent arg0) {
        {


            JFileChooser adbflashfile = new JFileChooser("/home/local/ANT/arthm/Desktop/os"); 
           FileNameExtensionFilter filter = new FileNameExtensionFilter(".py", "py");

                adbflashfile.setFileFilter(filter);

            int returnVal = adbflashfile.showOpenDialog(null);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                runfile = adbflashfile.getSelectedFile();

                try {
                    Runtime.getRuntime().exec("sudo python ./flashimage.py");
                } catch (IOException e1) {

                    e1.printStackTrace();
                }
                //This is where a real application would open the file.
                System.out.println("File: " + runfile.getName() + ".");    
            } else {
                JOptionPane.showMessageDialog(null, "Open command cancelled by user.");
            }
            System.out.println(returnVal);
        }
    };
    }

2 Answers2

1

You "could" read the process input and when you "detect" the password prompt, display a JOptionPane and request that the user enter the password.

You "could" prompt the user for the password before you start the process, knowing that you are going to need to send it to the process.

You would probably still need to monitor the output of the process to determine when you need to send the password though.

Let's start with...

Runtime.getRuntime().exec("sudo python ./flashimage.py");

You are ignoring the Process completely. Neither are you processing the output, but you have no means to provide input to the process...

Generally, Runtime#exec is problematic at best. You are far better of using ProcessBuilder....

// Build the command to be executed.  Note that each parameter becomes
// it's own argument, this deals with parameters that contain spaces
// much better then Runtime#exec alone...
ProcessBuilder pb = new ProcessBuilder("sudo", "python", "./flashimage.py");
pb.redirectError();

InputStream is = null;
try {
    Process p = pb.start();
    is = p.getInputStream();
    StringBuilder output = new StringBuilder(80);
    int in = -1;
    while ((in = is.read()) != -1) {
        if (in != '\n') {
            output.append((char)in);
            // You will need to define PASSWORD_PROMPT
            if (PASSWORD_PROMPT.equals(output.toString())) {
                String text = JOptionPane.showInputDialog("Password");
                OutputStream os = p.getOutputStream();
                os.write(text.getBytes());
            }
        } else {
            System.out.println(output.toString());
            output.delete(0, output.length());
        }
    }
} catch (IOException exp) {
    exp.printStackTrace();
} finally {
    try {
        is.close();
    } catch (Exception e) {
    }
}

Now, undoubtedly, someone will point out (at least) two problems with this approach...

  1. JOptionPane.showInputDialog("Password"); will present a normal JTextField, which won't hide the password characters and
  2. String is not the safest way to to store a password...

Instead, we should use a JPasswordField and convert the resulting char array to a byte array...

JPasswordField password = new JPasswordField(10);
JLabel label = new JLabel("Password: ");
JPanel panel = new JPanel();
panel.add(label);
panel.add(password);

int option = JOptionPane.showConfirmDialog(null, panel, "Password", JOptionPane.OK_CANCEL_OPTION);
if (option == JOptionPane.OK_OPTION) {
    char[] userPassword = password.getPassword();
    byte[] bytes = new byte[userPassword.length * 2];
    for (int i = 0; i < userPassword.length; i++) {
        bytes[i * 2] = (byte) (userPassword[i] >> 8);
        bytes[i * 2 + 1] = (byte) userPassword[i];
    }
    os.write(bytes);
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
0

Child process I/O can be redirected, using Process class. You should be able to monitor the output & provide input (the password) into the child process.

See:

Thomas W
  • 13,940
  • 4
  • 58
  • 76