【发布时间】:2017-10-20 14:04:26
【问题描述】:
我正在尝试编写一个程序,该程序读取另一个程序的输出并将该程序作为输入写入。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char str[30];
printf("Input string : ");
fflush(stdout);
scanf("%s", &str);
fflush(stdout);
printf("entered string is %s\n", str);
return 0;
}
这个程序 1 是一个从标准输入读取输入并打印输入的字符串的简单程序。 在program2中,我尝试创建2个管道并执行program1。 并读取program1的输出并获取用户输入并将用户输入的字符串传递给program1。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
typedef struct pipe_rw
{
pid_t cpid;
int pipe_r[2];
int pipe_w[2];
} RWPIPE;
char *get_user_input(void)
{
char buf[128];
char *input;
char ch;
int n;
int len = 0;
memset(buf, 0x0, 128);
while((ch = fgetc(stdin)) != 0xa)
{
buf[len] = ch;
len++;
}
input = malloc(sizeof(char) * (len));
strncpy(input, buf, (len));
return input;
}
int pclose_rw(RWPIPE *rwp)
{
int status, ret = 0;
if (rwp)
{
if (rwp->cpid > 0)
{
kill(rwp->cpid, SIGTERM);
do {
ret = waitpid(rwp->cpid, &status, WUNTRACED|WCONTINUED);
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
}
close(rwp->pipe_r[0]);
close(rwp->pipe_w[1]);
free(rwp);
}
return ret;
}
RWPIPE *popen_rw(const char *command)
{
RWPIPE *rwp = (RWPIPE *)malloc(sizeof(*rwp));
if (rwp == NULL)
return NULL;
memset(rwp, 0x00, sizeof(*rwp));
if (pipe(rwp->pipe_r) != 0 || pipe(rwp->pipe_w) != 0)
{
free(rwp);
return NULL;
}
rwp->cpid = fork();
if (rwp->cpid == -1)
{
free(rwp);
return NULL;
}
if (rwp->cpid == 0)
{
dup2(rwp->pipe_w[0], STDIN_FILENO);
dup2(rwp->pipe_r[1], STDOUT_FILENO);
close(rwp->pipe_r[0]);
close(rwp->pipe_r[1]);
close(rwp->pipe_w[0]);
close(rwp->pipe_w[1]);
execl(command, command, NULL);
printf("Error: fail to exec command - %s ..\n", command);
exit (1);
}
else
{
close(rwp->pipe_r[1]);
close(rwp->pipe_w[0]);
}
return rwp;
}
ssize_t read_p(RWPIPE *rwp, void *buf, size_t count)
{
return read(rwp->pipe_r[0], buf, count);
}
ssize_t write_p(RWPIPE *rwp, const void *buf, size_t count)
{
return write(rwp->pipe_w[1], buf, count);
}
int main(void)
{
char rbuf[BUFSIZ], wbuf[BUFSIZ];
int ret, len, n = 0;
char *string;
RWPIPE *rwp = popen_rw("./read_write");
if (rwp == NULL)
{
printf("Error: fail to open command ..\n");
return EXIT_FAILURE;
}
while (1)
{
memset(rbuf, 0x00, sizeof(rbuf));
if (read_p(rwp, rbuf, sizeof(rbuf)) < 1)
{
printf("No more input..\n");
break;
}
printf("%s", rbuf);
string = get_user_input();
len = strlen(string);
ret = write_p(rwp, string, len);
if (ret != len)
{
printf("Write %d bytes (expected %d) ..\n", ret, len);
break;
}
printf("end");
}
pclose_rw(rwp);
return EXIT_SUCCESS;
}
如果运行 program2 成功读取 program1 的输出。 它获取用户输入,但未能将用户输入的字符串提供给program1。
[root@localhost test_code]# ./rw_pipe
Input string : 1234
^C
请给我一些想法,为什么它会这样工作。
【问题讨论】:
-
scanf("%s", &str);是错误的。%s需要一个指向 char 的指针,但您正在传递一个指向 char 数组 30 的指针。只需删除运算符的地址,数组就会在该上下文中转换为指向 char 的指针。与您的问题无关,但无论如何您都应该解决一些问题。 -
input = malloc(sizeof(char) * (len)); strncpy(input, buf, (len));你需要多分配一个字符。在这种特殊情况下,strncpy() 将 not NUL 终止字符串。顺便说一句:sizeof(char)根据定义为 1,而 strncpy() 是一个几乎无用的函数。 -
我改变了 malloc(sizeof(char) * (len));到 malloc(sizeof(char) * (len+1));并添加了一行 input[len] = '\0';在 strncpy() 函数之后。但结果是一样的。
-
您考虑过使用popen(3) 吗?