3

我正在用 C 语言编写 SSH 的玩具版本,因此我需要将服务器 shell 的 stdin、stdout 和 stderr 重定向到客户端 shell(通过使用管道和套接字)。现在我只重定向了标准输出。如果我发送 ls、netstat 等命令没有问题,客户端会收到正确的输出。但是,如果我编写一个 C 程序,例如,请求一个 int n 并打印 1 和 n 之间的数字,并通过客户端调用它,我会得到这种行为:客户端没有收到带有 n 请求的字符串,但是如果我在服务器外壳上录制 n ,客户端会收到请求字符串和数字。我已经尝试过将标准输出留在服务器外壳上的相同方法,在这种情况下它可以正常工作。我尝试使用 fflush、fsync 和 setvbuf 却没有解决它。另一个奇怪的行为是:

这是执行重定向的代码。如您所见,我同时使用了 system 和 execlp 调用,但行为是相同的。

pipe(pipefd);
    if(fork() > 0)
    {
        close(pipefd[1]);
        *_result = fdopen(pipefd[0], "r");
        return 0;
    }
    else
    {
        close(pipefd[0]);
        close(1);
        dup(pipefd[1]);
        system(buf);
        //execlp(buf, buf, NULL);
        exit(0);
    }

编辑:在此之后,我调用这个函数来读取与管道读取端关联的流并将其放在套接字上。其他参数由 AES 和日志文件使用。sock_send 加密缓冲区并通过 sock_write 将其写入套接字。sock_write(_wsock, NULL, 0) 仅表示输出结束。无论如何,正如我之前指出的那样,ls 等命令的输出是可以的。

void write_result(int _wsock, aes_context *_enc_ctx, unsigned char *_iv, FILE *_result, char *_ip_addr)
{
    unsigned char buf[BUF_SIZE];
    char lstr[MAX_LOG_LEN];

    while(fgets(buf, BUF_SIZE * sizeof(char), _result) != NULL)
    {
        //li scrivo sulla socket
        if(sock_send(_wsock, _enc_ctx, buf, strlen(buf) + 1, _iv) == -1)
        {
            sprintf(lstr, WRITE_SOCK_ERR, _ip_addr);
            log_str(lstr);
            close_connection(_wsock, _ip_addr);
        }
    }
    sock_write(_wsock, NULL, 0);
    fclose(_result);
}
4

0 回答 0