1

Using fork I created a child and in the child I'm executing the ls command using execl. To send the output to parent,I used pipe and dup. The parent then prints the output. The code gives the expected output, but when I tried to restore back the stdout which I saved initially in stdout_holder, nothing is printed on terminal (when I used printf("hello") or the execl statement below it). However after few observations, it is observed that hello is printed only when nothing is done after redirecting "1" for the first time. (If I don't do anything after dup(fd[1],1) and simply do dup(stdout_holder,1) ) Why is this happening?

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<string.h>
int main()
 {int fd[2],stdout_holder;
 char str;
 pid_t pid;
 pipe(fd);
 pid=fork();
 if(pid==0)
  { stdout_holder=dup(1);
    close(fd[0]);
   printf("stdout_holder=%d\n",stdout_holder); 
   fd[1]=dup2(fd[1],1);
   execl("/bin/ls","ls","-l",NULL);
   stdout_holder=dup2(stdout_holder,1);
   printf("hello\n"); //Terminal doesnt show output.
   execl("/bin/ls","ls","-l",NULL); //Terminal doesnt show output

 }
else
 { close(fd[1]);
   wait(&pid);
   while(read(fd[0],&str,1)>0)
   printf("%c",str);
  } 
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Dv Nikhil
  • 11
  • 2
  • execl() does _not_ return on success, but replaces the process image. You have to fork(). – Ctx Jan 22 '16 at 11:14

3 Answers3

1

As in line 63 of this file you should save stdout file descriptor before changing it:

int moutfd = dup(STDOUT_FILENO);
dup2(fd, STDOUT_FILENO);

// Do the going-to-be-buffered jobs

dup2(moutfd, STDOUT_FILENO);
close(moutfd);
close(fd);
pouyan
  • 307
  • 1
  • 5
0

There are multiple issues:

  1. execl() does not return (except if there is an error), you need to fork() again or use e.g. system(). On execl the buffers are not emptied automatically, so the printf output does (at least for me) not reach stdout.

  2. The first output of printf("stdout_holder= ... and ls goes directly to stdout, not through the pipe (stdout is not replaced). You would need to use dup2() at the first place or close(1) before the dup() call..

jofel
  • 3,297
  • 17
  • 31
  • Thank you :) regarding your second issue(according to what i read and tried), the ls after the printf doesnt go to stdout because dup2 closes the "1" automatically...dup2(fd1,fd2) ..when this is called ,if fd2 is a file descriptor of a file which is open, it automatically closes it(so close(1) is not needed)..thts why the ls went to pipe and i got the output when i printed in parent process. – Dv Nikhil Jan 23 '16 at 08:38
0

Whenever you place a call to the execl(execv, execlp, etc.), it starts the execution of a new program (creates a new process image). The execution of this new program causes the process to forget all about its previous process image. The execl function does not return to the same process image unless it encounters some error.

if(pid==0)
  { stdout_holder=dup(1);
    close(fd[0]);
   printf("stdout_holder=%d\n",stdout_holder); 
   fd[1]=dup2(fd[1],1);
   execl("/bin/ls","ls","-l",NULL); //creates a new process image
   //will never reach here unless there is an error in the execl call
   stdout_holder=dup2(stdout_holder,1);//Line 7
   printf("hello\n");
   execl("/bin/ls","ls","-l",NULL);// Line 9
 }

After the child process finishes the first execl call, it will terminate, and hence will never reach the remaining code (from line 7 to line 9). Executing a new process image completely changes the contents of the memory, copying only the argument and environment strings to the new locations.

Hope this answers your question.

p-kar
  • 37
  • 2
  • 6
  • Thank uu :) i m actually trying to see a example of restoring the stdout...if i replace the execl statement with printf statements (say 2)..they are neither redirected to pipe nor getting printed on the terminal..after i restore the stdout and give one printf statement all the statements appear on the terminal (the 2 previous ones and one given now)..i guess redirecting printf ' s output has a issue..? Thank u so much :) edit : sorry my bad...i forgot commenting out the printing portion in parent process which printed the previous statements. – Dv Nikhil Jan 23 '16 at 08:51