0

I want am trying to use QProcess to launch sftp on a linux system, in my 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;

What I want to do is wait for the "Password:" prompt then inject the password, but bytaryIn is always empty.

I've verified the command line arguments are correctly formatted and output to the console.

I've then used these in a terminal to test and they work as expected.

The command will be formatted as:

    sftp User@HostName -P22

[Edit] I've re-written this code to the following:

    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);

I have a debug statement in the slot, but I never see it, so the signal is not getting emitted.

Botje
  • 26,269
  • 3
  • 31
  • 41
SPlatten
  • 5,334
  • 11
  • 57
  • 128

1 Answers1

1

A quick test shows that sftp accesses the terminal directly to ask the password. You will have to use a wrapper script that enters the password for you.

The alternative is to create a pseudo-tty pair and use that to enter the password, but you would not be able to use any of the QProcess machinery.

Botje
  • 26,269
  • 3
  • 31
  • 41
  • The idea behind the code I'm writing is to automate the login by doing the same thing the script in your link does but using QProcess and managing the data instead of using expect. – SPlatten Aug 01 '19 at 12:11
  • Then you need to convince QProcess to run `sftp` in a pseudo-tty, which is not possible according to the API. If your application is GPL-compatible, take a look at [KPty](https://api.kde.org/frameworks/kpty/html/index.html). – Botje Aug 01 '19 at 12:36
  • Alternatively, use [libssh2](https://www.libssh2.org/examples/) directly and skip all the human-interface stuff. – Botje Aug 01 '19 at 12:41
  • I would do exactly that, but because of problems this is why I went down this road. – SPlatten Aug 01 '19 at 13:26
  • Problems with which approach? I hope I have convinced you that using `QProcess` without any wrapper scripts or pseudo-TTYs is a dead end. – Botje Aug 01 '19 at 13:29
  • 1
    Like [`KPtyProcess`](https://github.com/KDE/kpty/blob/master/src/kptyprocess.cpp#L124-L143) does: subclass QProcess. On initialization, construct a pty with [`openpty`](http://man7.org/linux/man-pages/man3/openpty.3.html). Then override `setupChildProcess` and call [`login_tty`](http://man7.org/linux/man-pages/man3/openpty.3.html) with the slave file descriptor. Finally associate your `QProcess` with the master's file descriptor. If this sounds like too much, do note that KPty is apparently **L**GPL, so I think you are allowed to use it as a dynamic library, even in commercial products. – Botje Aug 01 '19 at 13:49
  • Thank you, I'll give it a go. – SPlatten Aug 01 '19 at 13:58