系統調用中,如果要和系統命令進行多次互動,那麼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的執行碼替換進程原來的執行碼.
}
}