Solved

Redirecting stdin/stdout/stderr [Linux]

Posted on 2004-03-20
4
1,566 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
4 Comments
 
LVL 12

Assisted Solution

by:stefan73
stefan73 earned 100 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 84

Accepted Solution

by:
ozo earned 150 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

Technology Partners: 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!

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…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.

705 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