Solved

Redirecting stdin/stdout/stderr [Linux]

Posted on 2004-03-20
4
1,526 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 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

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Details to do the search 56 142
Passing a array as parameter - C 2 77
Line meaning 9 77
Unable to start eclipse ? 17 84
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…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.

706 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

15 Experts available now in Live!

Get 1:1 Help Now