NAME
popen, pclose - pipe stream to or from a processSYNOPSIS
#include <stdio.h>FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
popen(), pclose(): _POSIX_C_SOURCE >= 2 || _XOPEN_SOURCE || _POSIX_SOURCE _BSD_SOURCE || _SVID_SOURCE
DESCRIPTION
The popen() function opens a process by creating a pipe, forking, and invoking the shell. Since a pipe is by definition unidirectional, the type argument may specify only reading or writing, not both; the resulting stream
is correspondingly read-only or write-only.
Hoert sich ja eigentlich ganz interessant an, wenn da nicht ein Problem waere:
The type argument is a pointer to a null-terminated string which must contain either the letter 'r' for reading or the letter 'w' for writing.
Man kann entweder lesen oder schreiben, von stderr ganz zu schweigen.
In Perl wuerde popen() in etwa so aussehen:
1 #!/usr/bin/perl 2 3 use strict; 4 5 open F, "ls |"; 6 7 while (<F>) { 8 print; 9 }
Das Problem ist jedoch das gleiche.
Mein 3-way popen kann stdin, stdout und stderr gleichzeitig:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <unistd.h> 5 #include <fcntl.h> 6 #include <sys/select.h> 7 8 9 int max(int a, int b) 10 { 11 return a > b ? a : b; 12 } 13 14 void serv_proc(int stin, int stout, int sterr) 15 { 16 int n, i; 17 char buf[100]; 18 fd_set rfds; 19 20 21 FD_ZERO(&rfds); 22 FD_SET(stout, &rfds); 23 FD_SET(sterr, &rfds); 24 25 write(stin, "/bin/ls\n", 8); 26 write(stin, "echo bla > /dev/stderr\n", 23); 27 write(stin, "/bin/ls /\n", 10); 28 write(stin, "a=5\n", 4); 29 write(stin, "echo $a > /dev/stderr\n", 24); 30 31 32 while (select(max(stout, sterr)+1, &rfds, NULL, NULL, NULL) > 0) 33 { 34 if (FD_ISSET(stout, &rfds)) 35 { 36 n=read(stout, buf, 100); 37 printf("---> STDOUT: \n"); 38 for (i = 0; i < n; i++) 39 printf("%c", buf[i]); 40 printf("\n"); 41 //FD_CLR(stout, &rfds); 42 } 43 if (FD_ISSET(sterr, &rfds)) 44 { 45 n=read(sterr, buf, 100); 46 printf("---> STDERR: \n"); 47 for (i = 0; i < n; i++) 48 printf("%c", buf[i]); 49 printf("\n"); 50 } 51 FD_SET(stout, &rfds); 52 FD_SET(sterr, &rfds); 53 } 54 55 close(stout); 56 close(sterr); 57 close(stin); 58 } 59 60 61 void client_proc(int stin, int stout, int sterr) 62 { 63 dup2(stin, STDIN_FILENO); 64 dup2(stout, STDOUT_FILENO); 65 dup2(sterr, STDERR_FILENO); 66 67 fcntl(STDIN_FILENO, F_SETFD, 0); 68 fcntl(STDOUT_FILENO, F_SETFD, 0); 69 fcntl(STDERR_FILENO, F_SETFD, 0); 70 71 sleep(1); 72 73 execl("/bin/bash", "sh", NULL); 74 75 close(stin); 76 close(stout); 77 close(sterr); 78 79 80 } 81 82 83 int main() 84 { 85 int stin[2], stout[2], sterr[2]; 86 pipe(stout); 87 pipe(sterr); 88 pipe(stin); 89 90 switch (fork()) 91 { 92 case -1: 93 exit(-1); 94 case 0: 95 close(stin[1]); 96 close(stout[0]); 97 close(sterr[0]); 98 client_proc(stin[0], stout[1], sterr[1]); 99 break; 100 default: 101 close(stin[0]); 102 close(stout[1]); 103 close(sterr[1]); 104 serv_proc(stin[1], stout[0], sterr[0]); 105 break; 106 } 107 108 return 0; 109 }


