?
Solved

Redirecting stdin/stdout/stderr [Linux]

Posted on 2004-03-20
4
Medium Priority
?
1,619 Views
Last Modified: 2008-02-01
Hello,
i need to run a command-line program, read its stdout/stdin and write its stdin.
In few words i need to do what this python script does:

import popen2
r,w,e = popen2.popen3('mount -t reiserfs ./MyDisks/ecnrypteddisk ./mnt/mydisk -o loop,encryption=AES256,rw -p 0');
w.write('password');
w.close();
for line in e.readlines():
    print 'E: ' + line
for line in r.readlines():
    print 'R: ' + line

r.close();
e.close();

Thank you,
   Luca
0
Comment
Question by:lucat
  • 2
4 Comments
 
LVL 12

Assisted Solution

by:stefan73
stefan73 earned 400 total points
ID: 10642227
Hi lucat,
popen2/popen3 are using a combination of pipe/fork/exec/dup2, basically like this:

pid_t son_pid;
int son_stdin[2];
int son_stdout[2];

son_pid = fork();

pipe(son_stdin);   /* 0 = father end of pipe, 1=son end */
pipe(son_stdout);  /* dito */

if(son_pid>0){ /* Parent process */
    /* Now you have your son's handles in son_stdin[0] and son_stdout[0] */

} else if (son_pid==0){ /* Son process */
    dup2(0,son_stdin[1]);  /* Set son's stdin to pipe */
    dup2(1,son_stdout[1]); /* Same with stdout        */
    exec("your command"); /* Do "apropos exec" and see which exec variant fits best for you here */
} else { /* Error */ }

pipes from the pipe() command are bi-directional, so you could do with only a single pipe - but it fits illustration better to use two of them. And AFAIK you can't do two fdopen() calls for a single fd.

Cheers!

Stefan
0
 
LVL 12

Expert Comment

by:stefan73
ID: 10642234
Ah, popen3 also dups stderr (fd=2). But then it gets messy for your program, as you need non-blocking I/O. You'd better just do a dup2 for stderr, also redirecting it to the stdout pipe.
0
 

Author Comment

by:lucat
ID: 10642302
Hmmm why this doesn't work?
It segfault on me... even thought the "ls" command is correctly executed (i know it because if i write "kwrite" instead than "ls" kwrite shows up).
I believe i am doing something wrong with fscanf (if i comment it out it doesn't give any error).
Is it correct how i use dup2?

Thanx,
   Luca

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

int main()
{
      int fdin[2];
      int fdout[2];
      int fderr[2];
      pid_t pid;
      char s[256];

      pipe(fdin);
      pipe(fdout);
      pipe(fderr);

      pid = fork();
      if (pid == (pid_t) 0) {
            close(fdin[1]);
            close(fdout[1]);
            close(fderr[1]);
            dup2(fdin[0],STDIN_FILENO);
            dup2(fdout[0],STDOUT_FILENO);
            dup2(fderr[0],STDERR_FILENO);
            execlp("ls","ls",0);
      }
      else {
            close(fdin[0]);
            close(fdout[0]);
            close(fderr[0]);
            FILE* streamin;
            FILE* streamout;
            FILE* streamerr;
            streamin = fdopen(fdin[1],"w");
            streamout = fdopen(fdout[1],"r");
            streamerr = fdopen(fderr[1],"r");
            fscanf(streamout,"%[^]",s);
            printf("%s",s);
            close(fdin[1]);
            close(fdout[1]);
            close(fderr[1]);
            waitpid(pid, NULL, 0);
      }

      return 0;
}
0
 
LVL 85

Accepted Solution

by:
ozo earned 600 total points
ID: 10642863
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define put 1
#define take 0
int main()
{
     int fdin[2];
     int fdout[2];
     int fderr[2];
     pid_t pid;
     char s[256];

     pipe(fdin);
     pipe(fdout);
     pipe(fderr);

     pid = fork();
     if (pid == (pid_t) 0) {
          close(fdin[put]);
          close(fdout[take]);
          close(fderr[take]);
          dup2(fdin[take],STDIN_FILENO);
          dup2(fdout[put],STDOUT_FILENO);
          dup2(fderr[put],STDERR_FILENO);
          execlp("ls","ls",0);
     }
     else {
          close(fdin[take]);
          close(fdout[put]);
          close(fderr[put]);
          FILE* streamin;
          FILE* streamout;
          FILE* streamerr;
          streamin = fdopen(fdin[put],"w");
          streamout = fdopen(fdout[take],"r");
          streamerr = fdopen(fderr[take],"r");
          fscanf(streamout,"%255[^]",s);
          printf("%s",s);
          close(fdin[put]);
          close(fdout[take]);
          close(fderr[take]);
          waitpid(pid, NULL, 0);
     }

     return 0;
}
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
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.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
Suggested Courses
Course of the Month16 days, 7 hours left to enroll

850 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