系统调用中,如果要和系统命令进行多次交互,那么system函数和popen都不能胜任,popen是单向管道.
要么从中获取标准出,要么向其写入标准输入.所以用fork子进程和父进程利用pipe来进行双向通讯才
能解决.
以修改用户密码为例,当然直接执行echo mypwd|passwd myname --stdin是可以的,但为了说明
向被调用的子进程传递输入,我让子进程执行 passwd my name --stdin,然后从标准输入中获取密码.
父进程通过管道向其输入密码.然后等待子进程执行完成后,获取子进程的标准输出.来判断是否更新成功.
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
char passwd[] = "abcd1234/n";
main()
{
int mypipe[2];
char buf[256];
pid_t pid;
int stat_loc,i;
pipe(mypipe);//任何向mypipe[1]中写入的数据可以从mypipe[0]中获取
if ((pid = fork()) != 0)
{
close(0); //父进程不需要使用标准输入.这里没有必要关闭,但为了说明
//因为要printf所以不能close(1);来重定向输出
write(mypipe[1],passwd,strlen(passwd));
//向管道写入密码后等待子进程的执行,如果是多次交互,应该使用
//状态标记来控制父子进程之间每一步的执行步骤.
waitpid(pid,&stat_loc,0);
//子进程执行完成后读取子进程的标准输出判断是否成功.
for(i=0;i<100;i++)
{
read(mypipe[0],buf,sizeof(buf));//开始读出系统的密码
//这里可以通过在上面重定向管道输入来从标准输入中读取
if(strstr(buf,"all authentication tokens updated successfully"))//如果能找到这样的输出,证明OK 了
{
printf("OK/n");
break;
}
}
exit(0);
}
else
{ //开辟子进程
close(0); //关闭原来的标准输入!!!!!!!!
dup(mypipe[0]); //将管理输入重定向到标准输入
close(1); //关闭原来的标准输出!!!!!!!!
dup(mypipe[1]); //将管理输出重定向到标准输出
close(mypipe[0]);
close(mypipe[1]);
execlp("passwd","passwd", "axman","--stdin",0);
//以下代码不会执行,execlp将当前进程的执行码直接跳转到passwd开始处执行.但进程的所有状态不
//变,即从此处开始用passwd的执行码替换进程原来的执行码.
}
}
这里用到了 pipe 管道函数:
int pipe(int file_descriptor[2]);
函数 pipe 填充的两个整数的含义是两个文件描述符,任何向 file_descriptor[1] 写入的数据,可以从 file_descriptor[0] 中读取,并且写入的数据符合先入先出的规则.
cpp 管道 pipe
最新推荐文章于 2024-09-09 11:01:19 发布