C++ shell命令提示输入密码

问题描述:

我想通过一个非常小的C++程序调用一些shell命令。C++ shell命令提示输入密码

诸如“git clone”或“rsync”等需要密码的命令。 例如,由于git使用SSH,这是交互式的,我无法提供密码给它。

我的程序到目前为止如下:

#include <iostream> 
#include <string> 

std::string ExecuteShellCommand(const std::string& cmd) 
{ 
    FILE* pipe = popen(cmd.c_str(), "r"); 

    if (!pipe) 
    return std::string("ERROR"); 

    char buffer[128]; 
    std::string result = ""; 

    while(!feof(pipe)) 
    { 
    if(fgets(buffer, 128, pipe) != NULL) 
     result += buffer; 
    } 

    pclose(pipe); 
    return result; 
} 

int main() 
{ 
    ExecuteShellCommand("git clone ssh://someurl/somerepo.git"); 
    return 0; 
} 

输出:

ssh_askpass:EXEC(在/ usr /的libexec/SSH-askpass):没有这样的文件或目录

ssh_askpass: exec(/ usr/libexec/ssh-askpass):没有这样的文件或目录

ssh_askpass:exec(/ usr/libexec/ssh-askpass):没有这样的文件或目录

有没有办法让进程提示输入密码,就像直接从命令提示符执行命令一样?

谢谢!理想情况下,我要么直接在Python或Shell中执行,但我的程序需要在C++中读取不同的结构(python绑定会有点矫枉过正),所以为什么我要用C++来做到这一点。

+1

考虑使用shell的脚本语言,比如batch和sh。 – orlp

+1

@nightcracker:这是我的第一个意图,但看到我的编辑。 – zedxz

你有两种选择。

首先,对于那些有一个,你可以使用每个程序的方法来解决这个问题。例如,git具有GIT_ASKPASS,并且ssh具有基于密钥的认证。

其次,您可以使用pty与这些程序进行通信。您可以使用程序(如expect)或使用您自己的代码(请参阅posix_openpt命令)执行此操作。

+0

hummm我现在正在看posix_openpt,这对我来说有点不清楚,我应该如何使用文件描述符来打开新进程? – zedxz

+0

在fork后,将slave pty复制到孩子的标准输入上并关闭主设备。将密码写入主站点。父母和孩子之间的pty行为类似于[管道](http://www.cs.uleth.ca/~holzmann/C/system/pipeforkexec.html) - 除了对孩子来说似乎它是一个终端。 Python有[pty.spawn和pty.fork](http://readthedocs.org/docs/python/en/latest/library/pty.html),它为你做了大部分工作。 –

+0

我真的建议你采取大卫的使用期望的建议,尤其是在这种情况下,你应该看看libexpect http://www.tcl.tk/man/expect5.31/libexpect.3.html。它将为您处理所有这些复杂问题,并为您提供与流程沟通的直接API。有很多问题可能出现,你可能不会马上意识到,比如I/O缓冲。期待是所有这些问题的经过充分尝试的解决方案。 – frankc