Unsolved Qt, implementing an SFTP client
-
@splatten
You are (presumably) using some third-partysftp.exe
client? This is what I had to do in another (non-Qt) product. You should not have to parse output for things like host, port, username & password prompting. Look at the documentation for thesftp.exe
you intend to use, there should/is likely to be command-line, or possibly take-from-file, for these? -
@JonB , the sftp I'm using in present in the linux distribution on the device.
-
@splatten
OK, well I don't know about that! What aboutman sftp
(host, port, user at least on command line)? On, say, Ubuntu I see:The final usage format allows for automated sessions using the -b option. In such cases, it is necessary to configure non-interactive authentica‐ tion to obviate the need to enter a password at connection time (see sshd(8) and ssh-keygen(1) for details).
Anyway, you use
QProcess
methods like https://doc.qt.io/qt-5/qprocess.html#readAllStandardOutput or (better) https://doc.qt.io/qt-5/qprocess.html#readyReadStandardOutput signal to read from/write to the subprocess. You'll want to deal with all of stdin, stdout, & stderr, plus error signals, for proper control of your sub-process. -
Here is my sample code:
QProcess* pProc = new QProcess(this); QString strHost = clsMainWnd::strGetHostName() ,strPort = clsMainWnd::strGetPort() ,strUsername = clsMainWnd::strGetUsername(); QStringList slstCmdArgs; slstCmdArgs << (strUsername + QString("@") + strHost) << (QString("-P") + strPort); pProc->start("sftp", slstCmdArgs); while( pProc->waitForStarted() != true ) { } QByteArray bytaryIn = pProc->readAllStandardOutput(); qDebug() << bytaryIn;
I've grabbed the content of slstCmdArgs and tried it in a terminal and it works, but in code I never see anything in "bytaryIn".
An example of what the code above does:
sftp User@HostName -P22
What I am expecting to see is:
User@HostName's password:
[Edit] I've now re-written this code to:
QString strHost = clsMainWnd::strGetHostName() ,strPort = clsMainWnd::strGetPort() ,strUsername = clsMainWnd::strGetUsername(); QStringList slstCmdArgs; slstCmdArgs << (strUsername + QString("@") + strHost) << (QString("-P") + strPort); mpSFTP = new QProcess(this); connect(mpSFTP, SIGNAL(readyReadStandardOutput()) ,this, SLOT(readSFTPoutput())); mpSFTP->start("sftp", slstCmdArgs);
-
@splatten said in Qt, implementing an SFTP client:
QByteArray bytaryIn = pProc->readAllStandardOutput();
Don't do it like this - you don't know whether there is already anything to read. Use https://doc.qt.io/qt-5/qprocess.html#readyReadStandardOutput signal instead.
-
@jsulm, having re-written the code, my slot never gets called, meaning the signal can't be emitted.
-
@splatten
Which is why I said to use https://doc.qt.io/qt-5/qprocess.html#readyReadStandardOutput for better/proper behaviour....There is a wrinkle you may have to face. It is possible that your command-line
sftp
executable will not prompt for password if it detects that the user is not in an interactive terminal (stdin). E.g. its code may quite possibly haveif (isatty(0)) prompt_for_password(); else // do not prompt for password
That will be problematic if it is the case. You could try in a terminal
sftp < /dev/null
orsftp < file
: if that does not still prompt for password you have a (potential) problem.... -
@JonB , would this help:
mpSFTP->setProcessChannelMode(QProcess::MergedChannels);
-
@splatten
Help what, in what way? If thesftp
requires a terminal stdin for password prompt, then no, if, say, you have a purely interactive Qt application. You can try it. But the first thing to test is whether yoursftp
behaves differently if its stdin is not attached to a terminal? -
Now the slot gets called and in my slot I have:
qDebug() << "readAllStandardOutput:"; qDebug() << mpSFTP->readAllStandardOutput(); qDebug() << "readChannel:"; qDebug() << mpSFTP->readChannel();
In the output I see:
readAllStandardOutput: "ssh_askpass: exec(/usr/local/libexec/ssh-askpass): No such file or directory " readChannel: 0
-
@splatten What happens if you execute exact same command manually in a terminal?
Also connect a slot to the error signal from QProcess and check whether you get any errors. -
@jsulm , When I execute "sftp" with the command line arguments, it works without any issues.
-
@splatten
As I have said before, so last time now:ssh_askpass: exec(/usr/local/libexec/ssh-askpass): No such file or directory
This is because your sftp is not willing/able to access stdin to get a password. Try what I said about seeing how your
sftp
behaves with input/output redirected when run from a terminal. I will not comment again, and leave it to you. -
ssh_askpass is not available on this linux distribution.
-
@splatten
Yes, so you can't use it. -
@JonB, I've tried everything you have suggested so far and not been able to make any progress due to either incorrect syntax or missing commands.
-
@splatten
I am suggesting yoursftp
client will not work to prompt for a password if you do not run it from a terminal. It will not work when you try redirection from a parent process like Qt.The man page for my
sftp
under Ubuntu at least is pretty explicit about requiring either an "interactive" session for authentication, or must usessh
facilities for non-password authentication. Does your system haveman sftp
for you to read through?