|
Member
Registered: Apr 2008
Location: HYD, INDIA.
Posts: 102
Original Poster
Rep:
|
Here the context is '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]);
};
}
|