使用管道和read()write()进行SSH通信

时间:2019-01-03 21:42:32

标签: c linux ssh pipe

我最近正在编写一段代码,以使用SSH访问外部服务器,然后与我直接通过它连接到的交互式外壳式应用程序进行通信。

我正在使用仅提供基本库的嵌入式Linux,无法使用任何其他软件或库。另外,我必须通过应用程序内部的C / C ++代码来完成此操作。因此,我决定使用管道和read(),write()系统调用,而我会坚持使用。

我写了一些代码来更好地理解和测试这个概念。但是它没有按预期工作。我使用了一个片段from here。似乎工作正常,但是main中的循环表现不如预期

#include <string.h>
#include <signal.h>
#include <unistd.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>


static bool
start_subprocess(char *const command[], int *pid, int *infd, int *outfd)
{
    int p1[2], p2[2];

    if (!pid || !infd || !outfd)
        return false;

    if (pipe(p1) == -1)
        goto err_pipe1;
    if (pipe(p2) == -1)
        goto err_pipe2;
    if ((*pid = fork()) == -1)
        goto err_fork;

    if (*pid) {
        /* Parent process. */
        *infd = p1[1];
        *outfd = p2[0];
        close(p1[0]);
        close(p2[1]);
        return true;
    } else {
        /* Child process. */
        dup2(p1[0], STDIN_FILENO);
        dup2(p2[1], STDOUT_FILENO);
        close(p1[0]);
        close(p1[1]);
        close(p2[0]);
        close(p2[1]);
        execvp(*command, command);
        /* Error occured. */
        fprintf(stderr, "error running %s: %s", *command, strerror(errno));
        abort();
    }

err_fork:
    close(p2[1]);
    close(p2[0]);
err_pipe2:
    close(p1[1]);
    close(p1[0]);
err_pipe1:
    return false;
}

int main() {
    char *cmd[4];
    cmd[0] = "/usr/bin/ssh";
    cmd[1] = "-tt";
    cmd[2] = "user@localhost";
    cmd[3] = NULL;

    char buf[65535];
    char msg[65535];

    int pid, infd, outfd;
    start_subprocess(cmd, &pid, &infd, &outfd);


    printf ("Started app %s as %d\n\n", *cmd, pid);

    while(1) {
        read(outfd, buf, 65535);
        printf(">>> %s\n", buf);
        printf("<<< ");
        scanf("%s", msg);
        if(strcmp(msg, "exit") == 0) break;

        write(infd, msg, strlen(msg));
    }

    return 0;
}

我已经尝试了各种SSH -t设置,并且似乎在某种程度上启用了-tt选项(据我所知,它强制使用伪终端),没有它,我会得到

Pseudo-terminal will not be allocated because stdin is not a terminal.

所以我认为 -tt 在这里是正确的。但是这种行为很奇怪。我想通过SSH连接,然后发出ls命令并查看输出,该输出应与普通SSH相似:

user@xubuntuLTS ~/dev/cpp/pipes$ ssh localhost
>>>> WELCOME TO SSH SERVER <<<<
Last login: Thu Jan  3 22:34:35 2019 from 127.0.0.1
user@xubuntuLTS ~$ ls
Desktop  dev  Documents  Downloads  Music  Pictures  Public  Templates  TEST_FILE  Videos
user@xubuntuLTS ~$ 

但是请注意,我的应用程序是这样的:

user@xubuntuLTS ~/dev/cpp/pipes$ ./a.out 
Started app /usr/bin/ssh as 18393

>>>> WELCOME TO SSH SERVER <<<<
>>> Last login: Thu Jan  3 22:35:28 2019 from 127.0.0.1

<<< ls
>>> user@xubuntuLTS ~$ 
<<< 
ls
>>> ls0;user@xubuntuLTS: ~user@xubuntuLTS ~$ 
<<< ls
>>> ls0;user@xubuntuLTS: ~user@xubuntuLTS ~$ 

您能提示我代码中的错误吗?我想从终端读取与在“正常” SSH会话期间看到的输出完全相同的输出,可能在每个read()调用期间具有“附加”输出,因此我可以通过这种类型的交互式通信轻松地执行一些自动化任务。请注意,这里使用标准终端只是一个示例,在实际解决方案中,我直接通过SSH登录来连接某种命令行界面程序,而无需实际访问shell。

我很确定这里正确使用write()和read()会出问题,但是我不是这方面的专家。

0 个答案:

没有答案