我在C中编写了一个SSH玩具版本,所以我需要将服务器shell的stdin,stdout和stderr重定向到客户端shell(通过使用管道和套接字)。现在我只重定向了stdout。如果我发送ls,netstat等命令没有问题,客户端会收到正确的输出。 但是,如果我编写一个C程序,例如,请求int n并打印1和n之间的数字,并通过客户端调用它我得到这种行为:客户端没有收到带有n的请求的字符串,但如果我在服务器shell上录制n,则客户端会收到请求字符串和数字。 我已尝试将stdout留在服务器shell上,并且在这种情况下它可以正常工作。我试图使用fflush,fsync和setvbuf而不解决它。 另一个奇怪的行为是:如果我通过客户端调用程序httrack而不重定向stdout,则服务器shell会显示正常的向导,它会询问项目名称,URL等。 但是如果我重定向stdout,客户端没有收到向导输出,而是收到httrack帮助页面。
这是执行重定向的代码。正如您所看到的,我使用了系统和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);
}