• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 681
  • Last Modified:

how to redirect output of external commands to files

Hey, I'm trying to redirect the output from ls into a file, I'm not quite sure what I'm doing wrong here...

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char **argv, char **envp){

  int fid, rv, n;

  fid = open("/usr/bin/ls" ,O_WRONLY|O_CREAT|O_TRUNC);
  close(1);

  n = open("temp.txt", O_CREAT|O_RDWR);
  rv = execve("/usr/bin/ls", "ls", envp);
  close(n);

  return 0;
}

I got all the information about open, close and dup from die.net.

The way I understand it, when closing, 0 is stdin, 1 is stdout, and 2 is stderr.  So I'm opening ls, then closing stdout, then opening a new file, and running ls again, and closing the file, it should work, right?
0
errang
Asked:
errang
  • 5
  • 4
1 Solution
 
Infinity08Commented:
>> So I'm opening ls

You're opening the executable file, which will not give you the output of the running program.


>> it should work, right?

Not like this, though.


Before continuing, may I ask why it needs to be directed to a file. Do you need the file to be created for some external use ? Or do you need the file, because you need to process the output of ls in the calling program ?

In the latter case (which I assume it is), consider using popen instead. It starts a process, and returns a FILE* to the process's (output) stream, so you can read the process's output as if it was a file. Very handy :

        http://linux.die.net/man/3/popen

For example :
FILE *output = popen("ls", "r");
 
/* now read ls's output just as a file : */
char line[256] = { 0 };
while (fgets(line, 256, output)) {
  /* do something with the line of output ... */
}
 
pclose(output);

Open in new window

0
 
errangAuthor Commented:
I need to have the program's output redirected to a new file and save it, not specifically for any "use" but its what the professor wants... so cant argue with him.. lol =(

0
 
evilrixSenior Software Engineer (Avast)Commented:
Well, you can do this very simply (if not the best way, see what I8 has said above) like this...

system("/usr/bin/ls >> somefile.txt");

Just execute the command that you'd type into the shell using the system function.

http://www.cplusplus.com/reference/clibrary/cstdlib/system/
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
errangAuthor Commented:
Actually, this needs to be done with system calls, just using open(2), close(2), and dup(2).

FILE *output = popen("ls", "r");
 
/* now read ls's output just as a file : */
char line[256] = { 0 };
while (fgets(line, 256, output)) {
  /* do something with the line of output ... */
}
 
pclose(output);

The way the program's setup, if I use fopen, it doesn't have an option to create a non-existing file:
FILE *fopen(const char *path, const char *mode);
FILE *fdopen(int fildes, const char *mode);
FILE *freopen(const char *path, const char *mode, FILE *stream);

Unlike open(2), which has flags to create the file if it doesn't exist... =(

The way my professor explained it to me (not sure if I'm saying this right, please correct me if I'm wrong) there are 3 modes of file input/output, 0, is input, 1 is regular output, and 2 is error... right?

So what I'm supposed to do is, open the program, and shut off the standard output so it doesn't get printed on the screen ( close(1) would do that, right? ), and then, open a new file and then use execve to run that program, and the output will magically get into that file.

The part I don't understand is the part where execve magically puts the output of the program in the new file... and shouldn't we need to run the program to get its output, rather than just opening it?

Sorry about the long post... but could you please explain this part to me?

Thank You.
0
 
Infinity08Commented:
>> Actually, this needs to be done with system calls, just using open(2), close(2), and dup(2).

popen is also a system call.

You can't do it with just open, close and dup - you'd at least need a fork or exec call too.

But then again, popen does all of that for you without any fuss.


>> The way the program's setup, if I use fopen, it doesn't have an option to create a non-existing file:

Sure it does : using the "a" or "w" modes.

        http://www.cplusplus.com/reference/clibrary/cstdio/fopen/


>> there are 3 modes of file input/output, 0, is input, 1 is regular output, and 2 is error... right?

Those are the standard streams that your system already has open (stdin, stdout and stderr resp.).


>> and then, open a new file and then use execve to run that program, and the output will magically get into that file.

Sure. That's a standard way of piping the output of a called application to a file.


>> The part I don't understand is the part where execve magically puts the output of the program in the new file... and shouldn't we need to run the program to get its output, rather than just opening it?

execve replaces the current program memory image with the new program's memory image, but it keeps the open streams.

        http://linux.die.net/man/2/execve

So, if you redirect a standard stream to a file, and then call execve with some program, then that program will still have the redirected standard stream.
0
 
errangAuthor Commented:
>> The way the program's setup, if I use fopen, it doesn't have an option to create a non-existing file:
>>Sure it does : using the "a" or "w" modes.

Ah... ok, I thought that was only if the file existed, it didn't say anything about creating the file if it didn't exist.

So basically, you are saying that when we run a program, and cut off its stdout, and then run execve, it picks up where that program left off and writes to a new file?
0
 
Infinity08Commented:
Something like below redirects the standard output to a file. Note that the old stdout stream is not saved, but you don't need to restore it since you plan to call execve ...
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
 
int ret = 0;
int fout = 0;
 
/* open the output file : */
fout = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0666);
if (fout < 0) {
  perror("open failed");
  exit(1);
}
 
/* redirect the standard output to the given file : */
ret = dup2(fout, fileno(stdout));
if (ret < 0) {
  perror("dup2 failed");
  exit(1);
}
close(fout);
 
fprintf(stdout, "test\n"); /* <--- will write to the file */

Open in new window

0
 
Infinity08Commented:
>> So basically, you are saying that when we run a program, and cut off its stdout, and then run execve, it picks up where that program left off and writes to a new file?

If you redirect stdout to a file, and then call a new program with execve, then the new program will still have its stdout redirected to that file.
0
 
errangAuthor Commented:
Wait... this isn't working for some reason =(

 pid = fork();

      if(pid < 0)
        perror("fork");
      else if(pid == 0){
        fid = open(fourth_string, O_CREAT|O_WRONLY|O_TRUNC, 0666);
        if(fid < 0)
          perror("fid");
        close(1);
        ret = dup(fid);
        if(ret < 0)
          perror("ret");
        close(fid);
      }
      else if(pid > 0){
        case_num = 0;
        wait(NULL);
      }

when I type in echo hi > zzz.txt it puts the prompt in there, instead of hi.
0
 
errangAuthor Commented:
oh... wait, nevermind.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 5
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now