#include "Shell.h"
#include <signal.h>
#include <sys/errno.h>
#include <sys/wait.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
using namespace agent;
Shell::Shell(void)
{
}
Shell::~Shell(void)
{
}
int Shell::Execute(const string& strCmd)
{
if(strCmd.empty())
return -1;
int ret = system(strCmd.c_str());
return ret;
}
int Shell::Execute(const string& strCmd,string& strRet)
{
if(strCmd.empty())
return -1;
#ifdef WIN32
FILE* cmdPipe = _popen(strCmd.c_str(), "rt");
#else
FILE* cmdPipe = popen(strCmd.c_str(), "r");
#endif
if(!cmdPipe)
return -1;
signed char tmpStr(0);
while(true)
{
tmpStr = (char)fgetc(cmdPipe);
if(EOF == tmpStr)
{
break;
}
else
{
strRet += tmpStr;
}
}
#ifdef WIN32
_pclose(cmdPipe);
#else
pclose(cmdPipe);
#endif
return 0;
}
int Shell::Execute(const string& strCmd,string& strRet, const int nTimeout,const string strShell)
{
if(strCmd.empty())
return -1;
//signal(SIGCHLD,SIG_IGN);
string cmd = strShell;
std::string::size_type pos = strShell.find_last_of('/');
if(pos != std::string::npos){
cmd = strShell.substr(pos+1);
}
//create pid
int filedes[2];
if(pipe(filedes) < 0)
{
//printf("[Shell::Execute] pipe create error
");
return -1;
}
//设置为非阻塞
fcntl(filedes[0], F_SETFL, O_NONBLOCK);
//fcntl(filedes[1], F_SETFL, O_NONBLOCK);
int nRe = 0;
pid_t pid = fork();
if(pid < 0)
{
//printf("[Shell::Execute] fork error
");
return -1;
}
//child
if(pid == 0)
{
//printf("child-----------my process id is %d
",getpid());
close(filedes[0]);
if (filedes[1] != STDOUT_FILENO)
{
dup2(filedes[1], STDOUT_FILENO);//复制文件句柄用法
dup2(filedes[1], STDERR_FILENO);
close(filedes[1]);
}
if(cmd == "perl"){
execl(strShell.c_str(), cmd.c_str(), "-e", strCmd.c_str(), (char *)0);
}else{
execl(strShell.c_str(), cmd.c_str(), "-c", strCmd.c_str(), (char *)0);
}
//printf("[Shell::Execute] child: execl: %s
", strerror(errno));//转换错误码为对应的错误信息
_exit(127);
}
//parent
close(filedes[1]);
time_t btime = time(NULL);
char buf[10240 + 1] = {0};
while(true)
{
memset(buf,0,sizeof(buf));
int len = read(filedes[0], buf, sizeof(buf)-1);
//printf("[Shell::Execute] len =================: %d
",len);
if (len < 0)
{
if (time(NULL) - btime < nTimeout)
{
usleep(1000);
continue;
}
//printf("[Shell::Execute] parent: kill child pid = %d for timeout %d s
",pid,nTimeout);
char cmd[100] = {0};
sprintf(cmd,"kill -9 %d",pid);
system(cmd);
len = 0;
nRe = 1;
}
//recv finish or timeout -> break
if(len == 0)
{
if(waitpid(pid, NULL, WNOHANG) == 0)
{
continue;
}
//printf("[Shell::Execute] parent: child pid = %d exit
",pid);
break;
}
//printf("[Shell::Execute] parent: %s
",buf);
strRet += buf;
}
close(filedes[0]);
return nRe;
}
int Shell::ExecuteExit(const string& strCmd,string& strRet, const int nTimeout,bool& bExit,const string strShell)
{
if(strCmd.empty())
return -1;
//signal(SIGCHLD,SIG_IGN);
string cmd = strShell;
std::string::size_type pos = strShell.find_last_of('/');
if(pos != std::string::npos){
cmd = strShell.substr(pos+1);
}
//create pid
int filedes[2];
if(pipe(filedes) < 0)
{
//printf("[Shell::Execute] pipe create error
");
return -1;
}
//设置为非阻塞
fcntl(filedes[0], F_SETFL, O_NONBLOCK);
//fcntl(filedes[1], F_SETFL, O_NONBLOCK);
int nRe = 0;
pid_t pid = fork();
if(pid < 0)
{
//printf("[Shell::Execute] fork error
");
return -1;
}
//child
if(pid == 0)
{
//printf("child-----------my process id is %d
",getpid());
close(filedes[0]);
if (filedes[1] != STDOUT_FILENO)
{
dup2(filedes[1], STDOUT_FILENO);//复制文件句柄用法
dup2(filedes[1], STDERR_FILENO);
close(filedes[1]);
}
if(cmd == "perl"){
execl(strShell.c_str(), cmd.c_str(), "-e", strCmd.c_str(), (char *)0);
}else{
execl(strShell.c_str(), cmd.c_str(), "-c", strCmd.c_str(), (char *)0);
}
//printf("[Shell::Execute] child: execl: %s
", strerror(errno));//转换错误码为对应的错误信息
_exit(127);
}
//parent
close(filedes[1]);
time_t btime = time(NULL);
char buf[10240 + 1] = {0};
while(true)
{
memset(buf,0,sizeof(buf));
int len = read(filedes[0], buf, sizeof(buf)-1);
//printf("[Shell::Execute] len =================: %d
",len);
if (len < 0)
{
if (time(NULL) - btime < nTimeout && !bExit)
{
usleep(1000);
continue;
}
//printf("[Shell::Execute] parent: kill child pid = %d for timeout %d s
",pid,nTimeout);
char cmd[100] = {0};
sprintf(cmd,"kill -9 %d",pid);
system(cmd);
len = 0;
nRe = 1;
}
//recv finish or timeout -> break
if(len == 0)
{
if(waitpid(pid, NULL, WNOHANG) == 0)
{
continue;
}
//printf("[Shell::Execute] parent: child pid = %d exit
",pid);
break;
}
//printf("[Shell::Execute] parent: %s
",buf);
strRet += buf;
}
close(filedes[0]);
return nRe;
}