I want to send a character from a c program to a shell program. I am using a named pipe to send the letter 'a' whenever it is requsted. I should only have to open the pipe once. Here's an example:
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
int main(){
int fd;
mkfifo("/tmp/test", 0666);
fd = open("/tmp/test", O_WRONLY);
printf("Opened\n");
char * a = "a";
while(1){
printf("Writing to pipe...\n");
write(fd,a,1);
sleep(1);
}
}
And the shell executes this command as many times as it wants...
head -c 1 /tmp/test
The issue is after one head, the c will endlessly stream into the pipe, even if nobody's there.
I noticed that open() blocks until someone is on the other end. How to I tell write() to block until somebody is reading?
I would rather have this feature on write() than read(), as I think there's lots of overhead on opening the file for each request.
Thanks!
UPDATE
This is how I'm handling it in Java, it waits until I have somebody listening on this pipe before it continues on. Maybe just because it's a higher level language.
public static void writeToPipe(int val, String pipename){
try{
pipe_out = new PrintStream("/tmp/" + pipename);
}catch(Exception e){
System.out.println("Could not open a pipe for output!");
e.printStackTrace();
}
try{
pipe_out.println(val);
}catch(Exception e){
System.out.println("Could not write to pipe!");
e.printStackTrace();
}
try{
pipe_out.close();
}catch(Exception e){
System.out.println("Could not close the output pipe!");
e.printStackTrace();
}
}
UPDATE #2 - THIS IS THE SOLUTION
Here is my code based on David's idea, it's rough, but it works. I'm not checking if the named pipe exists and just supressing it from quitting.
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(int argc, char **argv){
mkfifo("/tmp/test", 0666);
while(1){
int fd, status;
if ((fd = open ("/tmp/test", O_WRONLY)) == -1) {
perror ("open failed");
return 1;
}
printf("Opened Pipe\n");
char a = 'a';
int f = fork();
if(f == -1){
perror("fork");
exit(1);
}else if(f == 0){
//This is by the child process
if (write (fd, &a, 1) == -1) {
close(fd);
perror ("open failed");
return 1;
}
}else{
//This is the parent process
int w = waitpid(f, &status, WUNTRACED | WCONTINUED);
if (w == -1){
perror("waitpid");
exit(EXIT_FAILURE);
}
}
}
}