プロセス間通信,リダイレクション,パイプ処理等によりpopen,pclose 関数を実装する例題です.main 関数内での mypopen, mypclose 関数の利用例はそのまま popen, pclose でも利用可能です.プロセスへの読込み,書込みの両方の例題を含みます.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> #include <sys/types.h> #define NMAXPOPEN 10 static struct fp_list { pid_t fils; FILE *flux; } p_fplist[NMAXPOPEN]; static int fplookup(FILE *f) { int i; for(i=0;i<NMAXPOPEN;i++){ if(p_fplist[i].flux==f) return i; } return -1; } FILE *mypopen(const char *command,const char *type) { int tube[2]; FILE *flux; pid_t fils; int place,on_id,off_id; if(*type!='r' && *type!='w') return NULL; place = fplookup(NULL); if(place==-1) return NULL; if(pipe(tube)==-1) return NULL; if((fils=fork())==-1) { close(tube[0]); close(tube[1]); return NULL; } switch(*type){ case 'r': on_id = 0; off_id = 1; break; case 'w': on_id = 1; off_id = 0; break; } switch(fils) { case 0: close(tube[on_id]); close(off_id); dup(tube[off_id]); close(tube[off_id]); execlp("/bin/sh","sh","-c",command,NULL); perror("execlp"); exit(EXIT_FAILURE); default: close(tube[off_id]); flux = fdopen(tube[on_id],type); break; } if(flux==NULL) { kill(fils,SIGUSR1); } p_fplist[place].fils = fils; p_fplist[place].flux = flux; return flux; } int mypclose(FILE *flux) { int place,statut; place = fplookup(flux); if(place==-1) return -1; fflush(p_fplist[place].flux); fclose(flux); waitpid(p_fplist[place].fils,&statut,0); p_fplist[place].flux = NULL; return statut; } int main(int argc,char *argv[]) { FILE *f1,*f2; char cmd[256],buf[256]; f1 = mypopen("file *","r"); if(f1==NULL){ perror("f1"); return 1; } f2 = mypopen("tr [a-z] [A-Z]","w"); if(f2==NULL){ mypclose(f1); perror("f2"); return 1; } while(fgets(buf,sizeof(buf),f1)!=NULL) { fputs(buf,f2); } mypclose(f1); mypclose(f2); return 0; } |
Gami[28]% ./list78.exe MAKEFILE: ASCII MAKE COMMANDS TEXT LIST_78.C: ASCII C PROGRAM TEXT LIST_78.EXE: MS-DOS EXECUTABLE (EXE), OS/2 OR MS WINDOWS LIST_78.O: 80386 COFF EXECUTABLE NOT STRIPPED - VERSION 30821 Gami[29]% |