LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-04-2008, 08:31 PM   #1
john.daker
Member
 
Registered: Jul 2008
Posts: 33

Rep: Reputation: 15
How to send input to ssh which exec-ed by child process ?


Code:
 if ((pid = fork()) < 0) {
        perror("fork error");
    } else if (pid > 0) {     
        /*parent, I want to send cmd like "ls" to clild */
    } else {                /* child */
        execl("/usr/bin/sh","sh","-c","ssh user@host",NULL);
        /*clild,I want to read cmd like "ls" from parent as the input for ssh, something like `expect` */
    }
How to do this?

Thanks
 
Old 11-04-2008, 11:14 PM   #2
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
You need to make a pipe with pipe, dup2 the input end over the standard input descriptor of the fork (pause the fork with raise(SIGSTOP); afterward, close the output descriptor in the fork,) probably fork again and dup2 the output pipe descriptor over that fork's standard output (also pause that fork, close the input descriptor in the fork,) waitpid from the parent to make sure both forks are stopped, then SIGCONT them with kill. You can optionally put them in the same process group before you continue them with setpgid (using the first fork's process ID) and continue them with killpg. You will need to kill the forks with SIGKILL upon any failure in the parent process, or just SIGCONT them and let them fail on their own. The second fork should execvp the ls command and the first fork will still execl the ssh command. Sorry, I don't have time at the moment to come up with an example, but the manpages for these system calls help a lot.
ta0kira

Last edited by ta0kira; 11-04-2008 at 11:16 PM.
 
Old 11-05-2008, 12:03 AM   #3
john.daker
Member
 
Registered: Jul 2008
Posts: 33

Original Poster
Rep: Reputation: 15
Thanks for the reply, but maybe this is not what i'm asking...
After I exec "ssh user@host" in child process, what I type in the console, ie `ls` is sent to parent process, then

parent process send `ls` to child process , but child process is not going to execle `ls` in itself, instead, the `ls` cmd is sent to the user@host and executed there, like i type `ls` after I `ssh user@host` in bash. Like the `expect` send `ls` to remote host.

Sorry for the bad English and bad understanding, maybe I dont catch your point.

If possible, an example is appreciated.

Thanks a lot.
 
Old 11-05-2008, 01:32 AM   #4
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
In that case, fopen the write end in my previous specification and fprintf your commands, e.g. "ls", to it.
ta0kira

PS I will try to come up with an example.

PPS Maybe just make a program that reads from standard input, does something with it, then writes it to standard output, and execute it piping to ssh?

Last edited by ta0kira; 11-05-2008 at 01:34 AM.
 
Old 11-06-2008, 08:08 PM   #5
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Here is a basic example:
Code:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>


int main(int argc, char *argv[])
{
	if (argc < 2)
	{
	fprintf(stderr, "%s [exec args ...]\n", argv[0]);
	return 1;
	}

	//create a pipe with separate input and output descriptors

	int pipes[2] = { -1, -1 };
	if (pipe(pipes) != 0)
	{
	fprintf(stderr, "%s: could not create pipes: %s\n", argv[0], strerror(errno));
	return 1;
	}

	//fork in order to exec the new process

	pid_t new_process = -1;
	if ((new_process = fork()) < 0)
	{
	fprintf(stderr, "%s: fork error: %s\n", argv[0], strerror(errno));
	return 1;
	}


	if (!new_process)
	//forked process
	{
	//replace standard input with the input descriptor
	dup2(pipes[0], STDIN_FILENO);

	//close the other descriptors
	//NOTE: with other than standard ..., check to make sure you aren't
	//closing what you just 'dup2'ed over!
	close(pipes[0]);
	close(pipes[1]);

	//pause until signaled
	raise(SIGSTOP);

	//if 'execvp' returns then that's an error
	int outcome = execvp(argv[1], argv + 1);
	fprintf(stderr, "%s: 'execvp' error: %s\n", argv[0], strerror(errno));
	_exit(outcome);
	}


	//parent process

	//wait for the fork(s) to pause

	int status = 0;
	while (waitpid(new_process, &status, WUNTRACED) == 0 && !WIFSTOPPED(status));
	if (!WIFSTOPPED(status))
	{
	fprintf(stderr, "%s: error synchronizing with fork: %s\n", argv[0], strerror(errno));
	kill(new_process, SIGCONT);
	return 1;
	}


	//put the fork(s) in a new process group for group control
	setpgid(new_process, new_process);

	//the input descriptor isn't needed
	close(pipes[0]);

	//open a stream for output to the fork

	FILE *output = fdopen(pipes[1], "w");
	if (!output)
	{
	fprintf(stderr, "%s: internal communication error: %s\n", argv[0], strerror(errno));
	kill(new_process, SIGCONT);
	return 1;
	}

	//resume the process group all at once (will continue all in the group)
	killpg(new_process, SIGCONT);

	char buffer[256];
	setlinebuf(output);

	//read from standard input until the child exits or input is closed

	while (!ferror(output) && !ferror(stdin) && fgets(buffer, sizeof buffer, stdin))
	{
	fprintf(stderr, "forwarding: %s", buffer);
	fprintf(output, "%s", buffer);
	}


	return 0;
}
Your requirement will probably vary from this, but it's the easiest way I've found to chain input and output of separate commands. You can chain an arbitrary number of processes together with this by replacing the standard output of the most recent fork with a new pipe and replacing the standard input of the next fork with the same pipe, etc.
ta0kira

PS Call the program with a command-line following the program name. Standard input will be echoed and forwarded to the program being exec-ed.

Last edited by ta0kira; 11-06-2008 at 09:25 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
how a father process know which child process send the signal SIGCHLD icoming Programming 10 07-20-2010 07:26 AM
How to redirect the stdin and stdout of child process which exec interactive prog? john.daker Programming 1 11-04-2008 08:27 AM
How to kill a Child and all its subsequent child process in C shayer009 Programming 3 12-04-2007 12:40 AM
Send input to child process cdog Linux - Software 5 02-07-2007 10:00 PM
How to send CTRL-D to child process via a pipe? neo_in_matrix Programming 10 09-15-2005 07:09 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:00 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration