基本上我想在C:中实现这样的目标
output=$(echo -n 1234 | md5sum)
1234
是输入,md5sum
是我想要运行的程序。
我已经检查了一些SO问题,但似乎没有一个正是我正在寻找的,或者它们没有提供我可以测试的完整代码示例。
我已经尝试popen
并能够读取或写入其他程序,但显然它不是双向的。
有些帖子似乎建议pipe
使用dup2
或其他一些功能,但他们没有解释如何让它们正常工作。
答案 0 :(得分:1)
D3
可以使用主要问题是它想要实现相当于shell命令:
popen()
并且 可以用C popen()
编写:
output=$(echo -n 1234 | md5sum)
这个输出是:
#include <stdio.h>
int main(void)
{
char output[64];
FILE *fp = popen("echo -n 1234 | md5sum", "r");
if (fp == 0)
{
fprintf(stderr, "failed to create pipeline\n");
return 1;
}
size_t nbytes = fread(output, sizeof(char), sizeof(output), fp);
pclose(fp);
if (nbytes > 0)
{
printf("output=[%.*s]\n", (int)nbytes, output);
return 0;
}
else
{
printf("no output available!\n");
return 1;
}
}
请注意,这相当于以下第一个命令的输出:
output=[4c35fa2227e11ba8c892cbbb5d46417c -
]
(使用$ printf "%s %s\n" -n 1234 | md5sum
4c35fa2227e11ba8c892cbbb5d46417c -
$ printf "%s" 1234 | md5sum
81dc9bdb52d04dc20036dbd8313ed055 -
$
并非完全可移植。有空间认为您期望第二个命令的输出。)
但是,标题中的标题问题表明您希望程序将数据写入echo -n
命令并再次读取响应哈希值。这当然是可行的,但你必须更加努力,md5sum
不再合适。我懒得不使用我首选的错误报告功能,这些功能在SOQ — Stack Overflow Questions存储库的GitHub上可用作LibSOQ目录中的文件popen()
和stderr.c
。当你只是编写测试并在测试指示失败时进行函数调用时,它使错误检查变得更加简单。
stderr.h
示例输出(程序为#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "stderr.h"
static void fd_copy(int ifd, int ofd)
{
char buffer[1024];
ssize_t rbytes;
while ((rbytes = read(ifd, buffer, sizeof(buffer))) > 0)
{
ssize_t wbytes;
if ((wbytes = write(ofd,buffer, (size_t)rbytes)) != rbytes)
err_syserr("short write %zd bytes instead of %zd expected: ", wbytes, rbytes);
}
}
static void be_childish(int *to_child, int *to_parent)
{
if (dup2(to_child[0], STDIN_FILENO) != STDIN_FILENO)
err_syserr("failed to duplicate pipe to standard input: ");
if (dup2(to_parent[1], STDOUT_FILENO) != STDOUT_FILENO)
err_syserr("failed to duplicate pipe to standard output: ");
close(to_child[1]);
close(to_child[1]);
close(to_parent[0]);
close(to_parent[0]);
char *cmd[] = { "md5sum", 0 };
execvp(cmd[0], cmd);
err_syserr("failed to execute command %s: ", cmd[0]);
/*NOTREACHED*/
}
static void be_parental(const char *fname, int *to_child, int *to_parent)
{
close(to_child[0]);
close(to_parent[1]);
int fd = open(fname, O_RDONLY);
if (fd < 0)
err_syserr("failed to open file '%s' for reading: ", fname);
fd_copy(fd, to_child[1]);
close(fd);
close(to_child[1]);
char buffer[128];
ssize_t rbytes = read(to_parent[0], buffer, sizeof(buffer));
close(to_parent[0]);
if (rbytes <= 0)
err_syserr("read error (or unexpected EOF) from hash process: ");
buffer[strspn(buffer, "0123456789abcdefABCDEF")] = '\0';
printf("%s: MD5 %s\n", fname, buffer);
}
static void md5hash(const char *fname)
{
int to_child[2];
int to_parent[2];
if (pipe(to_child) != 0 || pipe(to_parent) != 0)
err_syserr("failed to create 2 pipes: ");
int pid = fork();
if (pid < 0)
err_syserr("failed to fork: ");
if (pid == 0)
be_childish(to_child, to_parent);
else
be_parental(fname, to_child, to_parent);
}
int main(int argc, char **argv)
{
err_setarg0(argv[0]);
if (argc <= 1)
err_usage("file [...]");
for (int i = 1; i < argc; i++)
md5hash(argv[i]);
return 0;
}
):
pop73
这确认文件已正确复制到子项,输出MD5哈希匹配。
我喜欢涉及子进程和父进程的程序的$ pop73 mm*
mm19.c: MD5 1d2207adec878f8f10d12e1ffb8bcc4b
mm23.c: MD5 c3948c5a80107fdbfac9ad755e7e6470
mm53.c: MD5 a0a24610400d900eb18408519678481e
mm59.c: MD5 1a5b1807c331dd1b5b6ce5f6ffed7c59
$ md5sum mm*
1d2207adec878f8f10d12e1ffb8bcc4b mm19.c
c3948c5a80107fdbfac9ad755e7e6470 mm23.c
a0a24610400d900eb18408519678481e mm53.c
1a5b1807c331dd1b5b6ce5f6ffed7c59 mm59.c
$
和be_childish()
函数名称。使用离散作业的函数使代码在长期内更易于理解和维护。另请注意,代码关闭文件描述符的程度是多么小心。
经验法则:如果将管道的一端复制到标准输入或标准输出(或标准错误),则应关闭管道的两个端仍在进行中。
be_parental()
函数举例说明了这一经验法则。在继续执行命令之前,它会关闭它传递的2个管道的所有4个描述符,因为它已将每个管道中的一个描述符复制到其中一个标准流中。
请注意:如果您不将文件描述符复制到其中一个标准通道,则通常不会立即关闭管道的两个文件描述符。您通常会关闭管道的一端 - 当前流程不会使用的末端。但是另一个是开放的,直到你完成数据处理,无论这意味着什么。 be_childish()
函数说明了推论。
答案 1 :(得分:0)
为您的输入提供一些测试用例&amp;输出,你想用echo -n
只有n位数或其他什么来实现?我在下面尝试过一些假设。
xyz@xyz-PC:~/s_flow$ cat m5sum.c
#include<stdio.h>
int main()
{
int n;
printf("enter n :\n");
scanf("%d",&n);
printf("n = %d \n",n);
return 0;
}
xyz@xyz-PC:~/s_flow$ echo 12345 | ./m5sum
enter n :
n = 12345
你想要输出如上所述我们如何使用echo?
echo 12345 | ./m5sum
| | => process1 output will be input for process 2
process1 process2
首先你需要一个pipe
来写作&amp;阅读,条件是process1
不应该在屏幕上显示输出(stdout
)所以为此你应该close(1)
&amp;这应该是process2
的输入,即进程2不应该从用户(stdin
)读取,所以做close(0)
。
这是我的建议
int main()
{
int p[2];
pipe(p);
if(fork()==0)//child
{
close(0);//closing std in
dup(p[0]);//duplicating read end of pipe
close(p[1]);//closing write end of pipe
execlp("process1_cmd","cmd_option",NULL);
}
else
{
close(1);//close stdout
dup(p[1]);// duplicating write end of pipe
close(p[0]);//closing read end of pipe
execlp("process_2","process_2",NULL);
}
}
process_1&amp; process_2可以是任何预定义/用户定义的输入命令。我希望它有助于实现你的目标。