Solved

Redirecting stdin/stdout/stderr [Linux]

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

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
My eclipse editor won't start ? 4 154
voltage to force translation ? 8 99
Understanding the meaning of Portability in Embedded System Programming 8 146
UPD maximums on Red Hat 6 115
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
Examines three attack vectors, specifically, the different types of malware used in malicious attacks, web application attacks, and finally, network based attacks.  Concludes by examining the means of securing and protecting critical systems and inf…
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them 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.

803 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