LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
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
 
LinkBack Search this Thread
Old 11-06-2009, 02:16 AM   #1
nagendrar
Member
 
Registered: Apr 2008
Location: HYD, INDIA.
Posts: 131

Rep: Reputation: 15
problem in handling pipes concept while passing error and output in two files


I want to run the scripts on remote system using plink. Here I am using pipes concept .I created two pipes And I want to handle the output and error in two different files.

If host key (available in /.putty/sshhostkeys file) is not available or is not match then we will get "Store key in cache? (y/n)" message from child process into error file.

If parent process reads this message then we will send "yes" if not then we will continue to next step and parent process will wait until exit child process .

In this bug case, host key did not match and response came late from child process into error file and parent process took it as host key already available and waiting for exit status of child process using waitpid(). But here "yes" did not send for running commands and exit the child process.Hence it is hanged at waitpid(). Please help me how to solve this issue.

I tried this in following way:

#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <poll.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <stdlib.h>

void strtrimright(char * src, char trim) {
char * end = src;
while (*end) ++end;
--end;
while (end >= src && *end == trim)
*end-- = 0;
}

int talkToPlink(struct pollfd *waitfordata ,int read_stdout,int write_stdin,const char *passwd)
{
char buf[2048];
int pollRes=0;
unsigned long bread = 0;
while(1)
{
pollRes = poll(waitfordata,1,10*1000);

if(pollRes < 0)
{
printf("ReadWithTimeOut: Poll Error:%s",strerror(errno));
return -1; // pipe closed or other failure
}
memset(buf, 0, 2048);
bread = 0;

if(pollRes > 0)
{
if(waitfordata[0].revents > 0 ){
printf("======[%d]=====1\n",waitfordata[0].revents);
if(waitfordata[0].revents == POLLIN)
bread = read(read_stdout, buf, 2047);
else
{
struct stat filestat;
char errBuf[1024];
char *str =NULL;
if(stat("./outputFilename.txt", &filestat)==0){
sleep(8);
FILE *fpOut = fopen("./errFilename.txt", "r");
if(fpOut) {
fread(errBuf, 1, 1023, fpOut);
printf("errBuf[%s]\n",errBuf);

str= strstr(errBuf, "Store key in cache? (y/n) ");
if(str && *str) {

write(write_stdin,"y\n", strlen("y\n"));

sleep(1);
}
fclose(fpOut);
}

}

break;
}
}
}
}
return 1;
}

/* This waits until the child exits or untill timeouts */
int waitWithTimeOut(pid_t pid, int timeout,int &status)
{
time_t deadline = time(0) + timeout;
int state=0;
do {
waitpid(pid, &state,0);
if(WIFEXITED(state))
{
status=WEXITSTATUS(state);
kill(pid, SIGKILL);
waitpid(pid, 0, 0);
return 1;
}
sleep(1);

} while(time(0) < deadline);
kill(pid, SIGKILL);
waitpid(pid, 0, 0);
return -1;
}
//Connect to the host and run a command on it. Capture stdout to a file.
//Caller should close and delete the file afterward.
//Currently uses SSH only, but we could easily support Telnet too.
int main()
{
const char* host="10.0.15.187"; const char* user="all"; const char* passwd="e1q@";
const char* outputFilename="./outputFilename.txt";
const char *errorFilename="./errorFilename.txt"; char *errMesg;
const char *inputFilename="./findBootLoadPass.sh";
int status=0;
//format command
char command[1024]; memset(command, 0, 1024);
char exeName[1024];memset(exeName, 0, 1024);
snprintf(exeName , 1023, "./plink");
char port[16];memset(port,0,16);snprintf(port,15,"22");

char ppkFilePath[1024];
memset(ppkFilePath,0,1024);
char *argv[12] = {(char*)exeName,(char *)host,"-l",(char*)user,"-P", (char*)port,NULL};
argv[6] = "-pw"; argv[7] = (char*)passwd; argv[8] = "-m";
argv[9] = (char *)inputFilename; argv[10] = NULL;

bool ok = true;
int result=0,ret = 0;
int pid=0;
int write_stdin[2], read_stdout[2];
pipe(write_stdin);
pipe(read_stdout);

/* Fork the process */
pid = fork();

switch (pid) {
case 0: /* Child process */
close(write_stdin[1]);
close(read_stdout[0]);

/* Replace stdin and stdout with the new fds */
dup2(write_stdin[0], STDIN_FILENO);
dup2(read_stdout[1], STDERR_FILENO);

close(write_stdin[0]);
close(read_stdout[1]);

int f;
if ((f=creat("./outputFilename.txt", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1){
printf("failed at output file creation outputFilename");
}

int ferror;
if ((ferror=creat("./errFilename.txt", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1){
printf("failed at output file creation errputFilename");
}

dup2(f,STDOUT_FILENO);
dup2(ferror, STDERR_FILENO);


close(ferror); // original not needed after dup2
close(f); // original not needed after dup2

execvp(exeName, argv);
_exit(0);
break;

case -1: /* fork() error */
printf("Fork() error for host:%s, cmd:%s, user:%s", host,cmd,user);
return NULL;
break;

default: /* Parent process */
/* Close unneeded fds */
close(write_stdin[0]);
close(read_stdout[1]);
struct pollfd waitfordata[1];
waitfordata[0].fd=read_stdout[0];
waitfordata[0].events=POLLIN;
sleep(2);

//run the commands
result = talkToPlink(waitfordata,read_stdout[0], write_stdin[1],passwd);
if(result < 0){
kill(pid,SIGKILL);
waitpid(pid, 0, 0);
}
else{
waitWithTimeOut(pid, 300, status);
}
close(write_stdin[1]);
close(read_stdout[0]);
};
 
Old 11-06-2009, 08:11 AM   #2
timmeke
Senior Member
 
Registered: Nov 2005
Location: Belgium
Distribution: Red Hat, Fedora
Posts: 1,515

Rep: Reputation: 61
The delayed write of the output is probably a buffering mechanism.
You should flush the output to file intentionally to disable lazy writing.

But why not put the keys in place once and then forget about writing some code to send "yes"...?
Why do you need to automate this?

And you might want to try out some more advanced scripting, or a thing like "expect" (which can handle interactive prompts like
the yes/no question).
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
examples with 2 pipes+fork+handling error,output in different files nagendrar Programming 4 11-06-2009 06:36 AM
example for redirecting stderr,stdout in seperate files using two way pipes concept nagendrar Programming 0 07-06-2009 06:08 AM
Sed gives output in pipes only when buffer is full jahvascriptmaniac Linux - Software 2 08-31-2006 05:57 PM
Need help w/ shell handling 3 commands/2 pipes sptchamp Programming 3 07-15-2004 09:37 PM


All times are GMT -5. The time now is 10:57 PM.

Main Menu
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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration