`
java-mans
  • 浏览: 11461884 次
文章分类
社区版块
存档分类
最新评论

系统调用中与被调用的命令交互方式

 
阅读更多

系统调用中,如果要和系统命令进行多次交互,那么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);

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")){
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的执行码替换进程原来的执行码.
}
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics