I tried popen()
and it is working well for output with "r"
passed as a second argument; I know you can use "w"
as writing mode and it worked for me (the program was just one scanf()
). My question is how to use the append ("a"
) mode. You can both write and read, how do you know when the program is outputting something and when it's requesting for user input?
Asked
Active
Viewed 1,666 times
1

Drew McGowen
- 11,471
- 1
- 31
- 57

Joe
- 11
- 2
-
On what operating system? – Some programmer dude Aug 06 '14 at 13:15
-
1Oh, and you can *not* use `popen` if you want to both read and write. – Some programmer dude Aug 06 '14 at 13:19
-
You'll need to open two separate pipes - one for the program's `stdin`, one for `stdout` – Drew McGowen Aug 06 '14 at 13:23
-
1Related (not sure whether it helps): http://stackoverflow.com/q/3884103/509868 – anatolyg Aug 06 '14 at 13:26
-
1If you're in windows, try `CreateProcess` api. It can treat both read pipe and write pipe. – ikh Aug 06 '14 at 13:27
-
Are you on a POSIX system ? – fjardon Aug 06 '14 at 13:48
-
I'm on windows, and although MSDN says there's no popen and just _popen - windows mingw says otherwise. And on MSDN there is an "a" mode. – Joe Aug 06 '14 at 14:12
-
@Drew McGowen but when do I know when to use each one ? – Joe Aug 06 '14 at 14:19
-
@Joe it usually depends on the program you're trying to create. For the output pipe, you can periodically "peek" at how much data is available. For the input pipe, however, it's generally not possible to detect when the program is requesting input. – Drew McGowen Aug 06 '14 at 14:21
-
MinGW presents a POSIX API under Windows. `popen` in MinGW is a totally different function from the MSVC++ runtime function `_popen`. – Some programmer dude Aug 07 '14 at 05:00
-
If you want to go the WIN32 route, [use `CreateProcess`](http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425%28v=vs.85%29.aspx). If you want to go the POSIX route then read about [`fork`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html) and [`dup`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html) and [`exec`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html). – Some programmer dude Aug 07 '14 at 05:03
1 Answers
2
popen uses a pipe (that's the "p" in "popen") and pipes are unidirectional. You can either read or write from one end of a pipe, not both. To get both read/write access you should use a socketpair instead. I use this in my programs when I want something like popen, but for read/write:
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>
FILE *sopen(const char *program)
{
int fds[2];
pid_t pid;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0)
return NULL;
switch(pid=vfork()) {
case -1: /* Error */
close(fds[0]);
close(fds[1]);
return NULL;
case 0: /* child */
close(fds[0]);
dup2(fds[1], 0);
dup2(fds[1], 1);
close(fds[1]);
execl("/bin/sh", "sh", "-c", program, NULL);
_exit(127);
}
/* parent */
close(fds[1]);
return fdopen(fds[0], "r+");
}
Note that since it doesn't return the child's pid, you'll have a a zombie process after the child program exits. (Unless you set up SIGCHLD...)

hyc
- 1,387
- 8
- 22
-
Just noticed you're on Windows; there's no socketpair() there. Probably no /bin/sh either. You should probably use CreateProcess like others recommended in above comments. – hyc Aug 07 '14 at 08:47