As per the manual of popen
, which says that[emphasis mine]:
The popen() function opens a process by creating a pipe, forking, and invoking the shell. Since a pipe is by definition unidirectional, the type argument may specify only reading or writing, not both; the resulting stream is correspondingly read-only or write-only.
As per the statements above, there is no way to both write and read to the file stream returned by popen
. So I take it for granted that the stdin
of current process would not influence the behaviour of the shell command which is passed as parameter for popen()
.
But it's really out of my expectation when running the program below.
Here is the code snippet code:
//filename pipe_cmd.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int ret = 0;
FILE* file = popen("ssh -t jhone@192.168.1.51 bash -c 'top' ", "r");
int fd = fileno(file);
char buffer[1024*100];
if(NULL != file)
{
while (true) {
memset(buffer, '\0', sizeof(buffer));
int ret_read = read(fd, buffer, sizeof(buffer));
if (ret_read > 0) {
printf("%s", buffer);
} else if (0 == ret_read) {
ret = 0;
break;
} else {
ret = -1;
break;
}
}
}
return ret;
}
The code snippet is compiled by gcc pipe_cmd.c -o pipe_cmd
.
When program named pipe_cmd
is running, I can see the all the information about the processes on the remote computer, which is as expected.
But when I hit h
key, I can see such help message on my local terminal, which is really out of my expectation. Here is what I see:
Help for Interactive Commands - procps-ng version 3.3.9
Window 1:Def: Cumulative mode Off. System: Delay 0.1 secs; Secure mode Off.
Z,B,E,e Global: 'Z' colors; 'B' bold; 'E'/'e' summary/task memory scale
l,t,m Toggle Summary: 'l' load avg; 't' task/cpu stats; 'm' memory info
0,1,2,3,I Toggle: '0' zeros; '1/2/3' cpus or numa node views; 'I' Irix mode
f,F,X Fields: 'f'/'F' add/remove/order/sort; 'X' increase fixed-width
L,&,<,> . Locate: 'L'/'&' find/again; Move sort column: '<'/'>' left/right
R,H,V,J . Toggle: 'R' Sort; 'H' Threads; 'V' Forest view; 'J' Num justify
c,i,S,j . Toggle: 'c' Cmd name/line; 'i' Idle; 'S' Time; 'j' Str justify
x,y . Toggle highlights: 'x' sort field; 'y' running tasks
z,b . Toggle: 'z' color/mono; 'b' bold/reverse (only if 'x' or 'y')
u,U,o,O . Filter by: 'u'/'U' effective/any user; 'o'/'O' other criteria
n,#,^O . Set: 'n'/'#' max tasks displayed; Show: Ctrl+'O' other filter(s)
C,... . Toggle scroll coordinates msg for: up,down,left,right,home,end
k,r Manipulate tasks: 'k' kill; 'r' renice
d or s Set update interval
W,Y Write configuration file 'W'; Inspect other output 'Y'
q Quit
( commands shown with '.' require a visible task display window )
Press 'h' or '?' for help with Windows,
What a surprise! The aforementioned behaviour looks like the top
command is directly called in my local bash, but it's really called by popen
.
I am really confused now. Could somebody shed some light on this matter?
Note:
The IP address(i.e. 192.168.1.51
) in the code snippet is my local computer's IP. But I don't think it's the reason why the program should work in this way.
I will try to run this program on another computer right now.
UPDATED:
Some phenomena when this program runs on another computer whose IP address is different without any modification for the aforementioned code snippet.
How to solve this problem? I don't want the stdin
of current process influence the behaviour of the shell command. One method that I know is to use pipe
& fork
and close the stdin
. Any better way to achieve this goal with popen
?