SSH связь с использованием каналов и read () write () - PullRequest
0 голосов
/ 04 января 2019

Недавно я пишу фрагмент кода для доступа к внешнему серверу по SSH, а затем общаюсь с интерактивным приложением, похожим на оболочку, к которому я напрямую подключаюсь через него.

Я использую встроенный Linuxдоступны только базовые библиотеки, без возможности использования какого-либо дополнительного программного обеспечения или библиотеки.Кроме того, я должен сделать это с помощью кода C / C ++ внутри приложения.Поэтому я решил использовать pipe и системные вызовы read (), write (), и я бы предпочел придерживаться этого.

Я написал некоторый код, чтобы лучше понять и протестировать концепцию.Но это не работает, как ожидалось.Я использовал фрагмент отсюда .Кажется, работает нормально, но тогда цикл в 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 ~$ 
* 1020Можете ли вы намекнуть, что не так в моем коде?Я хочу прочитать точно такой же вывод, который я вижу во время «обычного» сеанса SSH с терминала, возможно, имея «добавляющий» вывод во время каждого вызова read (), так что я могу легко выполнить некоторую автоматизированную задачу с этим типом интерактивного общения.Обратите внимание, что использование стандартного терминала здесь является лишь примером, в реальном решении я подключаюсь к некоторой программе интерфейса командной строки напрямую, регистрируясь через SSH, без реального доступа к оболочке.

I'mЯ уверен, что здесь что-то не так с правильным использованием write () и read (), но я не эксперт в этом вопросе.

...