Executing another program, redirecting its output to a file, and returning control.

This is a discussion on Executing another program, redirecting its output to a file, and returning control. within the C Programming forums, part of the General Programming Boards category; Okay, so basically I'm trying to write a program that I can use to convert video files and transfer them ...

  1. #1
    Registered User
    Join Date
    Jun 2009
    Posts
    9

    Unhappy Executing another program, redirecting its output to a file, and returning control.

    Okay, so basically I'm trying to write a program that I can use to convert video files and transfer them to my mp3 player.

    The basic part worked fine initially, using system(), I would call ffmpeg, have it convert the file, then use system again to call mtp-sendtr. The problem is, I need to specify the length of the video in seconds to mtp-sendtr. I can check the length myself and input it manually, and that works, but since ffmpeg displays the length as it converts, it seems I could use this data somehow.

    First, I tried simply piping the output from ffmpeg to a text file like "ffmpeg blah blah blah > output.txt" but that doesn't work, the file ends up being blank.

    So I did this (I've replaced ffmpeg with ls just to simplify things):

    Code:
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdio.h>
    
    
    int main(int argc, char *argv)
    {
    int fd; /*file descriptor to the file we will redirect ls's output*/
    
    if((fd = open("dirlist.txt", O_RDWR | O_CREAT))==-1){ /*open the file */
      perror("open");
      return 1;
    }
    
    
    dup2(fd,STDOUT_FILENO); /*copy the file descriptor fd into standard output*/
    
    dup2(fd,STDERR_FILENO); /* same, for the standard error */
    
    
    close(fd); /* close the file descriptor as we don't need it more  */
    
    /*execl ls */
     execl("/bin/ls", "ls", (char *) 0);
    
    printf("All done.\n");
    
    return 0;
    }
    That works, of course, but then the program just ends. I don't know much about forks and dup2 and all that, and I'm trying to learn, but I can't find anything that seems to answer my questions.

    I have a feeling I'm going about this in a convoluted way, and I'd LOVE to have someone explain to me what I need to do to make this work.

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Read up on popen(), it will be easier for what you are trying to do, vis tapping the output from ffmpeg.

    Quote Originally Posted by IanKoro View Post
    I have a feeling I'm going about this in a convoluted way, and I'd LOVE to have someone explain to me what I need to do to make this work.
    Yes, no matter how you slice it using C to do this is convoluted. It would be better done in a shell script, but if you are more comfortable programming in C than for bash you might as well try.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,183
    You need to fork somewhere.

    execl() replaces the process image, so it will never return.

    You need to first create pipes (using pipe()) for I/O, and then fork. In the child process, dup2() stdin and stdout to 2 ends of the pipes, close the unneeded ends, and call exec(). In the parent, close the unneeded ends (should be the opposite ends to the ones closed by the child), and then you can read/write from/to the pipes.

    I have recently written a C++ wrapper for this. You may want to have a look.
    Code review for a class that spawns a new process and allows IPC
    (final code on the last post)
    The AppInstance::start() function in particular.

    OR, if you only need to read OR write to the child process (as opposed to both read AND write), you can just use popen().

    As for shell redirection not working, maybe it writes to stderr? (People do that because stderr is usually not buffered, whereas stdout usually is)

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by cyberfish View Post
    You need to fork somewhere.

    execl() replaces the process image, so it will never return.

    You need to first create pipes (using pipe()) for I/O, and then fork. In the child process, dup2() stdin and stdout to 2 ends of the pipes, close the unneeded ends, and call exec().
    This is what popen() does and it does it properly. Just use popen().
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,183
    Life would be so good if popen supports "rw" mode...

    But yes, for this application, popen() is easier, since you presumably don't need to write to ffmpeg.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,853
    > Life would be so good if popen supports "rw" mode...
    IIRC, some versions do (or at least I recall someone saying they do)
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  7. #7
    Registered User
    Join Date
    Jun 2009
    Posts
    9
    Ahh... well, I figured out how to fork it, thank you very much... I found an example that cleared things up tremendously.

    I know C is a convoluted way of doing this, but I'm mostly trying to teach myself stuff.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. fopen returning "Bad File Pointer"
    By jprukop in forum C Programming
    Replies: 4
    Last Post: 04-17-2009, 04:01 PM
  2. Problems passing a file pointer to functions
    By smitchell in forum C Programming
    Replies: 4
    Last Post: 09-30-2008, 03:29 PM
  3. Problems with returning a char* to fprint.
    By qubit67 in forum C Programming
    Replies: 5
    Last Post: 08-09-2007, 12:28 AM
  4. Why does this program not work on my laptop?!
    By Eddie K in forum C Programming
    Replies: 1
    Last Post: 03-11-2006, 04:34 PM
  5. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 07:39 AM

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21