Недавно я пишу фрагмент кода для доступа к внешнему серверу по 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 (), но я не эксперт в этом вопросе.