"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "modules/remotebackend/pipeconnector.cc" between
pdns-auth-4.1.13.tar.gz and pdns-auth-4.2.0.tar.gz

About: PowerDNS Authoritative Nameserver is a versatile nameserver which supports a large number of backends (that can either be plain zone files or be more dynamic in nature).

pipeconnector.cc  (pdns-auth-4.1.13):pipeconnector.cc  (pdns-auth-4.2.0)
skipping to change at line 27 skipping to change at line 27
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
#include "remotebackend.hh" #include "remotebackend.hh"
PipeConnector::PipeConnector(std::map<std::string,std::string> optionsMap) { PipeConnector::PipeConnector(std::map<std::string,std::string> optionsMap): d_pi d(-1) {
if (optionsMap.count("command") == 0) { if (optionsMap.count("command") == 0) {
L<<Logger::Error<<"Cannot find 'command' option in connection string"<<endl; g_log<<Logger::Error<<"Cannot find 'command' option in connection string"<<e ndl;
throw PDNSException(); throw PDNSException();
} }
this->command = optionsMap.find("command")->second; this->command = optionsMap.find("command")->second;
this->options = optionsMap; this->options = optionsMap;
d_timeout=2000; d_timeout=2000;
if (optionsMap.find("timeout") != optionsMap.end()) { if (optionsMap.find("timeout") != optionsMap.end()) {
d_timeout = std::stoi(optionsMap.find("timeout")->second); d_timeout = std::stoi(optionsMap.find("timeout")->second);
} }
d_pid = -1;
d_fp = NULL;
d_fd1[0] = d_fd1[1] = -1; d_fd1[0] = d_fd1[1] = -1;
d_fd2[0] = d_fd2[1] = -1; d_fd2[0] = d_fd2[1] = -1;
} }
PipeConnector::~PipeConnector(){ PipeConnector::~PipeConnector(){
int status; int status;
// just in case... // just in case...
if (d_pid == -1) return; if (d_pid == -1) return;
if(!waitpid(d_pid, &status, WNOHANG)) { if(!waitpid(d_pid, &status, WNOHANG)) {
kill(d_pid, 9); kill(d_pid, 9);
waitpid(d_pid, &status, 0); waitpid(d_pid, &status, 0);
} }
close(d_fd1[1]); if (d_fd1[1]) {
if (d_fp != NULL) fclose(d_fp); close(d_fd1[1]);
}
} }
void PipeConnector::launch() { void PipeConnector::launch() {
// no relaunch // no relaunch
if (d_pid > 0 && checkStatus()) return; if (d_pid > 0 && checkStatus()) return;
std::vector <std::string> v; std::vector <std::string> v;
split(v, command, is_any_of(" ")); split(v, command, is_any_of(" "));
const char *argv[v.size()+1]; std::vector<const char *>argv(v.size()+1);
argv[v.size()]=0; argv[v.size()]=0;
for (size_t n = 0; n < v.size(); n++) for (size_t n = 0; n < v.size(); n++)
argv[n]=v[n].c_str(); argv[n]=v[n].c_str();
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
if(access(argv[0],X_OK)) // check before fork so we can throw if(access(argv[0],X_OK)) // check before fork so we can throw
throw PDNSException("Command '"+string(argv[0])+"' cannot be executed: "+str ingerror()); throw PDNSException("Command '"+string(argv[0])+"' cannot be executed: "+str ingerror());
if(pipe(d_fd1)<0 || pipe(d_fd2)<0) if(pipe(d_fd1)<0 || pipe(d_fd2)<0)
throw PDNSException("Unable to open pipe for coprocess: "+string(strerror(er rno))); throw PDNSException("Unable to open pipe for coprocess: "+string(strerror(er rno)));
if((d_pid=fork())<0) if((d_pid=fork())<0)
throw PDNSException("Unable to fork for coprocess: "+stringerror()); throw PDNSException("Unable to fork for coprocess: "+stringerror());
else if(d_pid>0) { // parent speaking else if(d_pid>0) { // parent speaking
close(d_fd1[0]); close(d_fd1[0]);
setCloseOnExec(d_fd1[1]); setCloseOnExec(d_fd1[1]);
close(d_fd2[1]); close(d_fd2[1]);
setCloseOnExec(d_fd2[0]); setCloseOnExec(d_fd2[0]);
if(!(d_fp=fdopen(d_fd2[0],"r"))) if(!(d_fp=std::unique_ptr<FILE, int(*)(FILE*)>(fdopen(d_fd2[0],"r"), fclose) ))
throw PDNSException("Unable to associate a file pointer with pipe: "+strin gerror()); throw PDNSException("Unable to associate a file pointer with pipe: "+strin gerror());
if (d_timeout) if (d_timeout)
setbuf(d_fp,0); // no buffering please, confuses poll setbuf(d_fp.get(),0); // no buffering please, confuses poll
} }
else if(!d_pid) { // child else if(!d_pid) { // child
signal(SIGCHLD, SIG_DFL); // silence a warning from perl signal(SIGCHLD, SIG_DFL); // silence a warning from perl
close(d_fd1[1]); close(d_fd1[1]);
close(d_fd2[0]); close(d_fd2[0]);
if(d_fd1[0]!= 0) { if(d_fd1[0]!= 0) {
dup2(d_fd1[0], 0); dup2(d_fd1[0], 0);
close(d_fd1[0]); close(d_fd1[0]);
} }
if(d_fd2[1]!= 1) { if(d_fd2[1]!= 1) {
dup2(d_fd2[1], 1); dup2(d_fd2[1], 1);
close(d_fd2[1]); close(d_fd2[1]);
} }
// stdin & stdout are now connected, fire up our coprocess! // stdin & stdout are now connected, fire up our coprocess!
if(execv(argv[0], const_cast<char * const *>(argv))<0) // now what if(execv(argv[0], const_cast<char * const *>(argv.data()))<0) // now what
exit(123); exit(123);
/* not a lot we can do here. We shouldn't return because that will leave a f orked process around. /* not a lot we can do here. We shouldn't return because that will leave a f orked process around.
no way to log this either - only thing we can do is make sure that our pa rent catches this soonest! */ no way to log this either - only thing we can do is make sure that our pa rent catches this soonest! */
} }
Json::array parameters; Json::array parameters;
Json msg = Json(Json::object{ Json msg = Json(Json::object{
{ "method", "initialize" }, { "method", "initialize" },
{ "parameters", Json(options) }, { "parameters", Json(options) },
}); });
this->send(msg); this->send(msg);
msg = nullptr; msg = nullptr;
if (this->recv(msg)==false) { if (this->recv(msg)==false) {
L<<Logger::Error<<"Failed to initialize coprocess"<<std::endl; g_log<<Logger::Error<<"Failed to initialize coprocess"<<std::endl;
} }
} }
int PipeConnector::send_message(const Json& input) int PipeConnector::send_message(const Json& input)
{ {
auto line = input.dump(); auto line = input.dump();
launch(); launch();
line.append(1,'\n'); line.append(1,'\n');
skipping to change at line 161 skipping to change at line 160
int PipeConnector::recv_message(Json& output) int PipeConnector::recv_message(Json& output)
{ {
std::string receive; std::string receive;
std::string err; std::string err;
std::string s_output; std::string s_output;
launch(); launch();
while(1) { while(1) {
receive.clear(); receive.clear();
if(d_timeout) { if(d_timeout) {
int ret=waitForData(fileno(d_fp), 0, d_timeout * 1000); int ret=waitForData(fileno(d_fp.get()), 0, d_timeout * 1000);
if(ret<0) if(ret<0)
throw PDNSException("Error waiting on data from coprocess: "+stringerro r()); throw PDNSException("Error waiting on data from coprocess: "+stringerro r());
if(!ret) if(!ret)
throw PDNSException("Timeout waiting for data from coprocess"); throw PDNSException("Timeout waiting for data from coprocess");
} }
if(!stringfgets(d_fp, receive)) if(!stringfgets(d_fp.get(), receive))
throw PDNSException("Child closed pipe"); throw PDNSException("Child closed pipe");
s_output.append(receive); s_output.append(receive);
// see if it can be parsed // see if it can be parsed
output = Json::parse(s_output, err); output = Json::parse(s_output, err);
if (output != nullptr) return s_output.size(); if (output != nullptr) return s_output.size();
} }
return 0; return 0;
} }
 End of changes. 11 change blocks. 
13 lines changed or deleted 12 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)