I've run into a problem while trying to send data through pipes, to be more exact: i do not get non-null file descriptors for pipe.
Here is the code for creation of the pipe:
//PIPE is defined as a "/tmp/my.fifo"
umask(0);
...
mknod(PIPE,S_IFIFO,0);
...
p=fopen(PIPE,"w");
if (p)
{
//fprintf(p,"some message");
fclose(p);
}
else
printf("Could not open the pipe\n");
Here is the code for reading from the pipe:
cos_pipe = fopen(PIPE,"r");
if (cos_pipe)
{
fgets(buffer,80,cos_pipe);
...
fclose(cos_pipe);
}
else
{
printf("Couldn't open the pipe\n");
usleep(300000);
}
Code is compiled into two different bineries that i launch separately. All the output i get is "Couldn't open the pipe".
On somewhat related note: should the program that created pipe delete it later?
The mode argument requires permissions too. Use S_IFIFO|S_IRUSR|S_IWUSR.
Consider using the mkfifo function instead:
mkfifo(PIPE,S_IRUSR|S_IWUSR)
You should remove the pipe when you are done using it. Also, what happens if more than one instance of your program is running at once - you're using a fixed name for the pipe.
Related
Will EXECVP system call supports IO redirections
That means is this give desired output
char *args[]={"cat","A.txt","B.txt",">","C.txt",NULL};
execvp(args[0],args);
I mean will the data in A.txt and B.txt goes to C.txt
If no why ?
UPD : I have asked two doubts in comment please clarify it
This is technically not an answer to your question, that has been answered in the comments. But an explanation to how you can do redirection with execvp
When starting a new program with execvp, it will inherit the current file descriptor. So if you setup file descriptor 1 (which is used for stdout)
to be redirected to "C.txt" before calling execvp, the new program will
write to "C.txt":
// Open "C.txt" for writing, creating it if it doesn't exist, or
// clearing its content if it does exist.
// `mode` should be set as appropriate
//
int fd = creat("C.txt", mode);
if (fd == -1)
{
// Swap out error handling to suit your needs
perror("open failed");
exit(EXIT_FAILURE);
}
// We want new process to have "C.txt" on file descriptor 1
if (dup2(fd, 1) == -1)
{
perror("dup failed");
exit(EXIT_FAILURE);
}
// "C.txt" is now writable on file descriptor 1, so we don't need the
// old one. Actually, the old one could confuse the new executable.
close(fd);
// We can now execute new program. It will inherit current open
// file descriptors and it will see "C.txt" on file descriptor 1
char *args[]={"cat","A.txt","B.txt",NULL};
execvp(args[0],args);
// If we reach this point, `execvp` failed.
perror("execvp failed");
exit(EXIT_FAILURE);
I want to pipe the output of a child process to the parent's stdout. I know there are other ways of doing this, but why can't a pipe's read-end be duplicated to stdout? Why doesn't the program print what is written to the pipes write end?
Here i have a minimal example (without any subprocesses) of what I'm trying to do. Im expecting to see test in the output when running, but the program outputs nothing.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
int fds[2];
if(pipe(fds) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
if(write(fds[1], "test", 5) == -1) {
perror("write");
exit(EXIT_FAILURE);
}
if(dup2(fds[0], STDOUT_FILENO) == -1) {
perror("dup2");
exit(EXIT_FAILURE);
}
return 0;
}
A pipe is two “files” that share a buffer and some locking or control semantics. When you write into the pipe, the data is put into the buffer. When you read from a pipe, the data is taken from a buffer.
There is nothing in the pipe that moves data to some output device.
If you use dup2 to duplicate the read side of the pipe into the standard output file descriptor (number 1), then all you have is the read side of the pipe on file descriptor 1. That means you can issue read operations to file descriptor 1, and the system will give your program data from the pipe.
There is nothing “special” about file descriptor 1 in this regard. Putting any file on file descriptor 1 does not cause that file to be automatically sent anywhere. The way standard output works normally is that you open a terminal or some chosen output file or other device on file descriptor 1, and then you send things to that device or file by writing to file descriptor 1. The operating system does not automatically write things to file descriptor 1; you have to issue write operations.
I want to make a simple program that uses fifo. I compiled this code and when I run it the console is waiting for an input. I tried to put a printf on first line and it doesn t appear on console.
int main(){
char* fifo = "./f";
int x = mkfifo(fifo, 0700);
if ( x == -1){
perror("error open");
exit(EXIT_FAILURE);
}
int f = open (fifo, O_WRONLY);
if ( f == -1){
perror("error open");
exit(EXIT_FAILURE);
}
close(f);
unlink(fifo);
return 0;
}
In console I run it like this
./x
and nothing happens, just the cursor is going next line and is waiting for input.
Why is my program not running?
From the mkfifo() man page:
Opening a FIFO for reading normally blocks until some other process opens the same FIFO for writing, and vice versa. See fifo(7) for nonblocking handling of FIFO special files.
So after your call to open(), your process is put on hold until another process opens the fifo with read access. Which in your case never happens.
I got this problem where i want to read from file using read function, but i cant't.
My code does that. I have a parent proccess and a child process. The child does an exec command and i have redirected the stdout to a file f. The parent waits the child and after that is reads from the file it's content and stores it to a buffer. Then i'm sending this output to a client through socket,using send, but that's not the problem. The problem is that even though the txt has content inside from the exec command, read function won't read anything and from my testing it always reads 0 bytes.
//parent
if (wait(&status2)== -1){ // Wait for child
perror("wait");
}
check_child_exit(status2);
n = read(f, buffer, MAX_BUFF-1);
if (n < 0){
error("ERROR reading from File");
}
printf("\n%d\n",n);
n = send(newsockfd,buffer, MAX_BUFF-1,0);
if (n < 0){
perror("ERROR writing to socket");
break;
}
//child
dup2(f,1);
dup2(f,2);
.
.
.
execvp(words[0],words); // Execute date
perror("execvp");
exit(EXIT_FAILURE)
So as you can see these are the 2 processes. I heard from another article that the problem might be on the opening of the file. But im not sure which options to use or not. I even tried to open with open function and fopen function just to try new things.
Here are the open and fopen call:
f = open("temp133",O_RDWR|O_CREAT|O_TRUNC,0755);
if (f==-1){
error_exit("Error Exit");
}
FILE *fd=fopen("tmp","w+");
thanks in advance
When my program starts, it just creates a fifo and opens it, after that I just want to output some information to the screen, however, nothing gets printed out. Here's a snippet of my code:
void listen(const server_config_t* server_conf)
{
// Create FIFO
if (mkfifo(SERVER_FIFO_PATH, 0660) == -1) {
fprintf(stdout, "server FIFO not created as it already exists. continuing...\n");
}
// Open FIFO (for reading)
int fd;
if ((fd = open(SERVER_FIFO_PATH, O_RDONLY)) == -1) {
// fprintf(stderr, "error: could not open server FIFO\n");
perror("FIFO");
exit(1);
}
// Open dummy FIFO (for writing, prevent busy waiting)
// TODO: find way to wait without another file descriptor?
int fd_dummy;
if ((fd_dummy = open(SERVER_FIFO_PATH, O_WRONLY)) == -1) {
perror("DUMMY FIFO");
exit(1);
}
// TODO: this should print immediately after starting,
// but doesn't for some reason
fprintf(stdout, "server listening... %d %s\n", server_conf->num_threads,
server_conf->password);
fflush(stdout);
.
.
.
}
Here's my output:
I've tried commenting out the fifo creation and opening, and when I do that the message gets printed correctly to the screen.
Opening a FIFO normally blocks until the other end is opened as well, see http://man7.org/linux/man-pages/man7/fifo.7.html. So your program probably waits in open(SERVER_FIFO_PATH, O_RDONLY) and does not reach any other fprintf or perror.
Your attempt to open the FIFO for reading first and then for writing does not work because the first open does not return.
You should be able to see this when you step through your program using a debugger.
BTW: When mkfifo returns -1 you should check if errno is EEXIST. There could be other errors that would also result in return value -1, see https://linux.die.net/man/3/mkfifo
As you can see from your output, there is blocking. That is, your current process cannot go on until the other end of the FIFO is opened for write. You should glance at the man page.
As to your error, there are two cases maybe the directory into which you want to place the FIFO doesn't permit to do that. Second case may be due to a system error. To overcome the issue, you need to change your fprintf as following.
#include <string.h>
#include <stdlib.h>
..
..
fprintf(stderr, "server FIFO not created as it already exists. Error: %s\n", strerror(errno));
exit(EXIT_FAILURE);