Redirecting stdout to pipe in C - c

Here's a program I'm trying to make:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char* argv[])
{
char* arguments[] = {"superabundantes.py", NULL};
int my_pipe[2];
if(pipe(my_pipe) == -1)
{
fprintf(stderr, "Error creating pipe\n");
}
pid_t child_id;
child_id = fork();
if(child_id == -1)
{
fprintf(stderr, "Fork error\n");
}
if(child_id == 0) // child process
{
close(my_pipe[0]); // child doesn't read
dup2(my_pipe[1], 1); // redirect stdout
execvp("cat", arguments);
fprintf(stderr, "Exec failed\n");
}
else
{
close(my_pipe[1]); // parent doesn't write
char reading_buf[1];
while(read(my_pipe[0], reading_buf, 1) > 0)
{
write(1, reading_buf, 1); // 1 -> stdout
}
close(my_pipe[0]);
wait();
}
}
I want to execute the exec in the child redirecting the stdout of the child to the parent (through the pipe). I think the problem might be related to dup2, but I haven't used it before.

You need to also provide argv[0] when you call exec. So your arguments should read:
char* arguments[] = {"cat", "superabundantes.py", NULL};

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char* argv[])
{
//char* arguments[] = {"cat","tricky.txt", NULL};
char* arguments[] = {"./son1", NULL};
int my_pipe[2];
if(pipe(my_pipe) == -1)
{
fprintf(stderr, "Error creating pipe\n");
}
pid_t child_id;
child_id = fork();
if(child_id == -1)
{
fprintf(stderr, "Fork error\n");
}
if(child_id == 0) // child process
{
close(my_pipe[0]); // child doesn't read
dup2(my_pipe[1], 1); // redirect stdout
execvp(arguments[0], arguments);
fprintf(stderr, "Exec failed\n");
}
else
{
close(my_pipe[1]); // parent doesn't write
char reading_buf[1];
while(read(my_pipe[0], reading_buf, 1) > 0)
{
write(1, reading_buf, 1); // 1 -> stdout
}
close(my_pipe[0]);
wait();
}
}
/*
if ./son1 returns
printf() in son1 will be output by write(1 ..) in parent
if son1 is in dead loop then
printf() in son1 will NOT be output by write(1 ..) in parent
void main()
{
printf( "***** son run *****\n\r" );
return;
while(1);
}
any idea?
*/

Related

C - Send input from Parent to Child and return it back

So, I'm pretty new to C programming language and I'm having some difficulty completing this exercise.
Basically, I have to fork(), then send an input string from Parent process to Child, do an uppercase function in the Child process and return it to Parent so it can print.
The pipes are still really "gibberish" but disregarding the uppercase function, I've got this:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define READ_END 0
#define WRITE_END 1
#define BUF_SIZE 256
int main(int argc, char* argv[]) {
int fd[2];
pid_t pid;
if (pipe(fd) < 0) {
perror("pipe error");
exit(EXIT_FAILURE);
}
if ((pid = fork()) < 0) {
perror("fork error");
exit(EXIT_FAILURE);
}
else
if (pid > 0) {
int nbytes;
char line[BUF_SIZE];
/* parent writes to pipe */
close(fd[READ_END]);
snprintf(line, BUF_SIZE,
"Hello child (%d)! I'm your parent pid (%d).\n",
pid, getpid());
if ((nbytes = write(fd[WRITE_END], line, strlen(line))) < 0) {
fprintf(stderr, "Unable to write to pipe: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
close(fd[WRITE_END]);
/* wait for child and exit */
if ( waitpid(pid, NULL, 0) < 0) {
fprintf(stderr, "Unable to catch child exiting: %s\n", strerror(errno)); exit(EXIT_FAILURE);
}
/* return gracefully */
exit(EXIT_SUCCESS);
}
else {
int nbytes;
char line[BUF_SIZE];
/* child reads from pipe */
close(fd[WRITE_END]);
if ((nbytes = read(fd[READ_END], line, BUF_SIZE)) < 0 ) {
fprintf(stderr, "Unable to read from pipe: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
close(fd[READ_END]);
/* write message from parent */
write(STDOUT_FILENO, line, nbytes);
/* return gracefully */
exit(EXIT_SUCCESS);
}
}```

C program hangs after fork

I have made the following program :
The aim is to make 5 child processes and have parent process send a string to each child process
to print. If I pass the argument xyz then this program prints xyz 2 times and then hangs.
Not sure why that is happening.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
int num_processes = 5;
int pipefd[num_processes][2];
pid_t cpid;
char buf;
if (argc != 2)
{
fprintf(stderr, "Usage: %s <string>\n", argv[0]);
exit(EXIT_FAILURE);
}
for (int i = 0; i < num_processes; i++)
{
if (pipe(pipefd[i]) == -1)
{
perror("pipe");
exit(EXIT_FAILURE);
}
}
for (int i = 0; i < num_processes; i++)
{
cpid = fork();
if (cpid == -1)
{
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0)
{ /* Child reads from pipe */
close(pipefd[i][1]); /* Close unused write end */
while (read(pipefd[i][0], &buf, 1) > 0)
write(STDOUT_FILENO, &buf, 1);
write(STDOUT_FILENO, "\n", 1);
close(pipefd[i][0]);
}
else
{ /* Parent writes argv[1] to pipe */
close(pipefd[i][0]); /* Close unused read end */
write(pipefd[i][1], argv[1], strlen(argv[1]));
close(pipefd[i][1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
}
}
_exit(EXIT_SUCCESS);
}

two child process communicating through named pipe

I have main program which creates two children and one named pipe(FIFO). Each children executes a program called “sendSignal" via execv(). One of the argument of the “sendSignal” is the FIFO in the main program.
The children are going to send signal to each other. It decided with an argument in the main (in variable firstShooter)program which signal shoot first.
I want to know how these two children can send each other their pid through this named pipe.
Following is the main program:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
/* this program should be provided with 2 arguments */
int main(int argc, char **argv)
{
char str1[15];
char str2[15];
char fileDescriptor[15];
char *my_args[4];
char *myfifo = "myfifo";
int fd, pipeCheck;
pid_t pid1, pid2, wid;
/* If the user does not provide the argument to determin which child is firing first */
if(argc != 2)
{
fprintf(stderr,"%s: 2 arguments needed, got %d\n",argv[0],argc-1);
exit(1);
}
/* create the FIFO (named pipe) */
pipeCheck = mkfifo(myfifo, 0666);
/* check if the named pipe was created properly if not output an error */
if(pipeCheck == -1)
{
fprintf(stderr, "%s: Error creating named pipe: %s\n",argv[0], strerror(errno));
exit(1);
}
pid1 = fork();
if (pid1 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid1 == 0)
{
my_args[0] = "sendSignal";
my_args[1] = argv[1];
my_args[2] = myfifo; // the named pipe as arguemnt
my_args[3] = NULL;
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by first child...");
exit(-1);
}
pid2 = fork();
if(pid2 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid2 == 0)
{
my_args[0] = "sendSignal";
my_args[1] = argv[1];
my_args[2] = myfifo; // named pipe as arguemnt
my_args[3] = NULL;
// printf("this is converted = %s\n",my_args[1]);
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by second child...");
exit(-1);
}
close(fd);
unlink(myfifo);
wid = wait(NULL);
return 0;
}
here is the sendSignal:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
void sig_handler(int signo)
{
if(signo == SIGUSR1)
printf("signal received\n");
}
int main(int argc, char **argv)
{
char abspath[256] = "";
getcwd(abspath, 256);
strrchr(abspath, '/');
if(signal(SIGUSR1,sig_handler) == SIG_ERR)
printf("\n Cannot catch the signal\n");
char *myfifo = "myfifo";
int firstShooter = atoi(argv[1]); //define the first process to send the signal
int fd;
char str1[15];
char str2[15];
char pid1[15];
char pid2[15];
fd = open(argv[2],O_RDWR);
if(firstShooter == 1)
{
sprintf(pid1,"%d",getpid());
write(fd,pid1,sizeof(pid1));
}
if(firstShooter == 2)
{
sprintf(pid2,"%d",getpid());
write(fd,pid2,sizeof(pid2));
}
read(fd,str1,sizeof(str2));
read(fd,str2,sizeof(str2));
close(fd);
printf("str1 = %s\n",str1);
printf("str2 = %s\n",str2);
return 0;
}
Both of your children processes got the same arguments:
my_args[0] = "sendSignal";
my_args[1] = argv[1];
my_args[2] = myfifo; // the named pipe as argument
my_args[3] = NULL;
firstShooter parameter doesn't make sense as process cannot identify itself as first or second.
I suggest to add one more parameter - process index. sendSignal function logic can be modified this way:
char pid1[15];
char pid2[15];
int processIndex = atoi(argv[3]);
fd = open(argv[2],O_RDWR);
if (processIndex == firstShooter)
{
// Send firstShooter PID
sprintf(pid1,"%d",getpid());
write(fd,pid1,sizeof(pid1));
// Got the other PID
read(fd,pid2,sizeof(pid2));
}
else
{
// Got the firstShooter PID
read(fd,pid1,sizeof(pid1));
// Send the other PID
sprintf(pid2,"%d",getpid());
write(fd, pid2, sizeof(pid2));
}
close(fd);
printf("pid1 = %s\n",pid1);
printf("pid2 = %s\n",pid2);
There are some issues in the way you have implemented.
1.Calling two fork() in the main program will be creating more than two child processes.(3 child processes). So give a condition to check that you are calling the next fork in the context of the parent itself.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
/* this program should be provided with 2 arguments */
int main(int argc, char **argv)
{
int * status;
char str1[15];
char str2[15];
char fileDescriptor[15];
char *my_args[4];
char *myfifo = "myfifo";
int fd, pipeCheck;
pid_t pid1, pid2, wid;
/* If the user does not provide the argument to determin which child is firing first */
if(argc != 2)
{
fprintf(stderr,"%s: 2 arguments needed, got %d\n",argv[0],argc-1);
exit(1);
}
/* create the FIFO (named pipe) */
pipeCheck = mkfifo(myfifo, 0666);
/* check if the named pipe was created properly if not output an error */
if(pipeCheck == -1)
{
fprintf(stderr, "%s: Error creating named pipe: %s\n",argv[0], strerror(errno));
exit(1);
}
pid1 = fork();
if (pid1 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid1 == 0)//child
{
// printf("pid1=0\n");
printf("i am child 1 %d\n",getpid());
my_args[0] = "sendSignal";
my_args[1]=malloc(6);
sprintf(my_args[1] , "%d", getpid());
//my_args[1]="1";
printf("p%s\n",my_args[1]);
my_args[2] = myfifo; // the named pipe as arguemnt
my_args[3] ="1";
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by first child...");
exit(-1);
}
else if(pid1>0)// parent
{
// printf("pid1 %d",pid1);
waitpid(pid1,&status,WIFEXITED(status));
pid2 = fork();
// printf("p:%d",pid2);
if(pid2 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid2 == 0)
{
printf("i am child 2 %d\n",getpid());
my_args[0] = "sendSignal";
my_args[1]=malloc(6);
sprintf(my_args[1] , "%d", getpid());
my_args[2] = myfifo; // named pipe as arguemnt
my_args[3] = "2";
// printf("this is converted = %s\n",my_args[1]);
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by second child...");
exit(-1);
}
printf("done\n");
}
close(fd);
wait(NULL);
fd=open("fifo1", O_RDONLY);
char * space=(char *)malloc(6);
read(fd,space,6);
printf("from fifo1 %s",space);
fd=open("fifo2", O_RDONLY);
//char * space=(char *)malloc(6);
read(fd,space,6);
printf("from fifo2 %s",space);
//unlink(myfifo);
wid = wait(NULL);
unlink(myfifo);
return 0;
}
2. The two child process are accessing the same pipe. Pipe is for one way communication with an end for reading and another for writing. So create two pipes each for a process. I would suggest better not to go for pipes.

Getting return from execlp()

I have a program which I would like to sort the first column in a file, from a child process, and return the output to the parent process. How can I retrieve the response from the execlp and print it? Here is what I have so far:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#define WRITE 1
#define READ 0
int main(int argc, char **argv)
{
int i, k;
int p1[2], p2[2];
int p1[2], p2[2];
pid_t childID;
if (pipe(p1) < 0 || pipe(p2) < 0) {
perror("pipe");
exit(0);
}
childID = fork();
if (childID < 0) {
perror("fork");
exit(0);
}
else if (childID == 0){
close(p1[WRITE]);
close(p2[READ]);
dup2(p1[READ], STDIN_FILENO);
close(p1[READ]);
dup2(p2[WRITE], STDOUT_FILENO);
close(p2[WRITE]);
execlp("sort", "-k1", "-n", "temp.txt", (char *)NULL);
perror("exec");
exit(0);
}
else {
//parent process
//Not sure how to get response from exec
}
}
After call execlp(), the memory image of current process will be replaced by the called progame, so you cannot get what you want through return value. What you can do is let the child process write its result to somehere, such as a temporal file or a pipe, and the parent process read the result from this place.
After proper setup a pipe to communite between parent and child processes, you can write the result of child process in its stdout, and read the result in parent processes from its stdin.
Something like this:
else if (childID == 0){
close(p1[READ]);
dup2(p1[WRITE], STDOUT_FILENO);
close(p1[WRITE]);
execlp("sort", "-k1", "-n", "temp.txt", (char *)NULL);
perror("exec");
exit(0);
}
else {
close(p1[WRITE]);
dup2(p1[READ], STDIN_FILENO);
close(p1[READ]);
while (scanf("%ms ", &l) != EOF) {
printf("%s\n", l);
free(l);
}
}
Here is full code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#define WRITE 1
#define READ 0
int main(int argc, char **argv)
{
int p1[2];
char *l;
pid_t childID;
if (pipe(p1) < 0) {
perror("pipe");
exit(0);
}
childID = fork();
if (childID < 0) {
perror("fork");
exit(0);
}
else if (childID == 0){
close(p1[READ]);
dup2(p1[WRITE], STDOUT_FILENO);
close(p1[WRITE]);
execlp("sort", "-k1", "-n", "temp.txt", (char *)NULL);
perror("exec");
exit(0);
}
else {
close(p1[WRITE]);
dup2(p1[READ], STDIN_FILENO);
close(p1[READ]);
while (scanf("%ms ", &l) != EOF) {
printf("%s\n", l);
free(l);
}
}
return 0;
}
And test file temp.txt:
$ cat temp.txt
a
e
b
d
f
c
Result of a test run:
$ ./a.out
a
b
c
d
e
f

Why does redirecting stdin in C not work?

I'm trying to redirect the stdin from the parent to the child through the pipe "my_pipe", but when I run my program, I do not see the expected results.
When I execute the program, it expects input from the stdin, so why didn't it redirect stdin in dup2?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char* argv[])
{
char* arguments[] = {"sort", NULL};
int my_pipe[2];
if(pipe(my_pipe) == -1)
{
fprintf(stderr, "Error creating pipe\n");
}
pid_t child_id;
child_id = fork();
if(child_id == -1)
{
fprintf(stderr, "Fork error\n");
}
if(child_id == 0) // child process
{
close(my_pipe[1]); // child doesn't write
dup2(0, my_pipe[0]); // redirect stdin
execvp(argv[0], arguments);
fprintf(stderr, "Exec failed\n");
}
else
{
close(my_pipe[0]); // parent doesn't read
char reading_buf[1];
write(my_pipe[1], "hello", strlen("hello"));
write(my_pipe[1], "friend", strlen("friend"));
close(my_pipe[1]);
wait();
}
}
Your arguments to dup2 are backwards. Try dup2(my_pipe[0], STDIN_FILENO)

Resources