javaubuntufreerdp

Output of process in Java is different from normal command


I am trying to write code which runs xfreerdp. When I write like this:

        String usernameWithPrefix = "/u:\""+c.getUsername()+"\"";
        String passwordWithPrefix = "/p:\""+c.getPassword()+"\"";
        String targetIpAdressWithPrefix = "/v:"+targetIpAdress;

        processBuilder.command("xfreerdp",usernameWithPrefix,passwordWithPrefix,targetIpAdressWithPrefix,"+auth-only","/cert:ignore");
        processBuilder.redirectErrorStream(true);
        process = processBuilder.start();
        process.waitFor();
        String res = new String(process.getInputStream().readAllBytes());

Output is like that although credentials is valid:

[00:53:49:700] [161077:161078] [WARN][com.freerdp.core.nla] - SPNEGO received NTSTATUS: STATUS_LOGON_FAILURE [0xC000006D] from server

[00:53:49:700] [161077:161078] [ERROR][com.freerdp.core] - nla_recv_pdu:freerdp_set_last_error_ex ERRCONNECT_LOGON_FAILURE [0x00020014]

[00:53:49:700] [161077:161078] [ERROR][com.freerdp.core.rdp] - rdp_recv_callback: CONNECTION_STATE_NLA - nla_recv_pdu() fail

[00:53:49:700] [161077:161078] [ERROR][com.freerdp.core.transport] - transport_check_fds: transport->ReceiveCallback() - -1

[00:53:49:700] [161077:161078] [ERROR][com.freerdp.core] - Authentication only, exit status 1

[00:53:48:174] [161077:161078] [INFO][com.freerdp.client.x11] - Authentication only. Don't connect to X.

When I run command in terminal, I get normal output which says credentials is valid. Also, when I write code like this:

        String usernameWithPrefix = "/u:\""+c.getUsername()+"\"";
        String passwordWithPrefix = "/p:\""+c.getPassword()+"\"";
        String targetIpAdressWithPrefix = "/v:"+targetIpAdress;

        processBuilder.command("/bin/bash","-c","xfreerdp "+usernameWithPrefix+" "+passwordWithPrefix+" "+targetIpAdressWithPrefix+" +auth-only /cert:ignore");
        processBuilder.redirectErrorStream(true);
        process = processBuilder.start();
        process.waitFor();
        String res = new String(process.getInputStream().readAllBytes());

I am getting normal output again. I solved my problem with "/bin/bash -c command" but I wonder why first version of my code does not work properly.


Solution

  • bash isn't the OS. When you type e.g.:

    xfreerdp /u:"foo"
    

    bash takes that command and goes to town on it. it replaces * with a space separated list of all files, it does variable substitution, and crucially it removes all quotes (double and single) as those are signs to bash to do certain things (double quotes: Don't consider spaces inside them to separate arguments, single quotes: Same, and do not perform certain expansions, such as globs (*) inside them).

    ProcessBuilder/Runtime.exec do not use bash. And bash is not the OS. They send the provided command and args directly to the OS with very little processing. Thus, it literally sends /u:"foo" to the xfreerdp process, whereas bash would remove those quotes.

    solution: Ditch the quotes. There is no need for them - they serve to tell bash not to split args on spaces within, and with processbuilder there is no arg splitting at all - you pass each arg as a separate string already.