Solved

duplicating stdout to a file as well

Posted on 2000-04-12
10
377 Views
Last Modified: 2010-04-02
I'm writing my own shell, and need to be able to duplicate my output to stdout and a file at the same time for a forked process which then calls execve.  To just change stdout to a file I know you do:
dup2(outf,1);
where outf is the open file.  I'm not sure how to make it do both though...  I tried:
tempf = dup(1);
dup2(outf,tempf);
to no avail.

Please help me shed light on this.
Thanks,
Josh
0
Comment
Question by:jbirk
10 Comments
 
LVL 1

Expert Comment

by:940961sl
Comment Utility
The best way is to write your own logging functions :

void startlog()
{
   //open file with handle LogFile here
}

void stoplog()
{
   //close file with handle LogFile here
}

void vlog(const char *format, va_list args)
{
   vprintf(format, args); //to stdout
   vfprintf(LogFile, format, args); //to file
}

void log(const char *format, ...)
{
   va_list args;

   va_start(args, format);
   vlog(format, args);
   va_end(args);
}

and now use log or vlog instead of printf and vprintf to write to stdout and a file at the same time.
0
 
LVL 8

Author Comment

by:jbirk
Comment Utility
Sorry, that's not possible.  I said it's a shell.  I have no control over what command is used.  I'm using execve to run a completely seperate program, like ls,more,diff,etc...

I suppose if I had to, I could open up the file that was written to, read the data, and write it out again to stdout after the program is done, but that's not really satisfactory either because the programs could be interactive, and the user will need to see the output right away so they know what's going on.

There must be some way to duplicate the output!?

-Josh
0
 
LVL 1

Expert Comment

by:LordDragon
Comment Utility
Assuming UNIX ...

Open a pipe, set that up as the stdout of the process, read the pipe and then copy it to stdout and the file at the same time.

leaving out error checking ...

int fd[2];

pipe(fd);
switch (fork()) {
case 0:   /* in child */
   dup(fd[0], 1);
/* start child */
   break;
default:  /* in parent */
   while (read(fd[1], &ch, 1) > 0) {
      /* write to log file */
      write(1, &ch, 1);
   }
   break;
}
0
 
LVL 3

Expert Comment

by:Laminamia063099
Comment Utility
Look into how some UNIX shells allow for you to enter the command:
   script somefilename
This command copies all output to the file somefilename while at the same time outputting the stdout.  This might be the answer already solved for you.

Laminamia
0
 
LVL 8

Author Comment

by:jbirk
Comment Utility
LordDragon (nice username BTW), how will the parent process know when the child process is done?  Does fd[1] report a different character or something?  I'm using a waitpid command now so it pauses until the child returns.

And yes, you are close to right, I'm using Linux, though it should function the same.

I had hoped this would be a simple solution...  but from the look of things thus far it isn't...  Do I have to use a pipe?  And won't that pipe also just redirect the stdout so it's still not going to the screen?  I guess I'd have to write to the file AND stdout in the parent, won't I?


Laminamia, you're logic is why I assumed it would be some system call I just didn't know.  Since other shells do it, it should be simple, right?  Unfortunately, I won't have the luxury of asking a parent shell or using "system()" to do the work for me since this'll be running in a restricted environment, so I have to figure out how they did it...

Thanks everyone for your help thus far:)
-Josh

0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 1

Accepted Solution

by:
LordDragon earned 50 total points
Comment Utility
I wasn't sure how you wanted to write to the log file, so I just put:

/* write to log file */

where you ned to write to the log file...


Also, when the child application exits, the os will close the stdout for the child and you will get an eof on the pipe (you may have to add:

close(fd[0]);

right in the beginning of the default case in the switch, tho'.)

Anyway, that will work.  You still need to waitpid for the child to exit or you will be creating zombie processes...

0
 
LVL 8

Author Comment

by:jbirk
Comment Utility
Adjusted points from 40 to 50
0
 
LVL 8

Author Comment

by:jbirk
Comment Utility
So this loop:
while (read(fd[1], &ch, 1) > 0) {
                                        /* write to log file */
                                        write(1, &ch, 1);
                                     }
will exit when I get that eof?  Then after the while I should put the waitpid() even though I know the process will already have finished?

Thanks for your help,
-Josh
0
 
LVL 8

Author Comment

by:jbirk
Comment Utility
OK, what do you think about using the shell program tee?  I could launch it, launch the subprogram, and have a pipe setup between them.  This way tee should handle the splitting for me, right?

I'm going to give that a try first, since it sounds like it might be simpler.

-Josh
0
 
LVL 8

Author Comment

by:jbirk
Comment Utility
My thesis advisor wants me to use your solution.  Thanks for the help!  I'll figure it out from here.

-Josh
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

7 Experts available now in Live!

Get 1:1 Help Now