From: Bert Hubert Date: Thu, 7 Mar 2013 09:55:38 +0000 (+0000) Subject: apply variant of code in t714 so we can lauch pipe backend scripts with parameters... X-Git-Tag: rec-3.5-rc3~24 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2f2b01452555786254f457d20524f9a2d96674a6;p=thirdparty%2Fpdns.git apply variant of code in t714 so we can lauch pipe backend scripts with parameters, plus add experimental code that if pipe-command is a unix domain socket, we use that. git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@3111 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- diff --git a/modules/pipebackend/coprocess.cc b/modules/pipebackend/coprocess.cc index cc2b5198e6..1b85a286b0 100644 --- a/modules/pipebackend/coprocess.cc +++ b/modules/pipebackend/coprocess.cc @@ -7,21 +7,26 @@ #include #include #include +#include #include #include +#include +#include +#include +#include CoProcess::CoProcess(const string &command,int timeout, int infd, int outfd) { - const char *argv[2]; - argv[0]=strdup(command.c_str()); - argv[1]=0; + vector v; + split(v, command, is_any_of(" ")); - launch(argv,timeout,infd,outfd); -} + const char *argv[v.size()+1]; + argv[v.size()]=0; -CoProcess::CoProcess(const char **argv, int timeout, int infd, int outfd) -{ - launch(argv,timeout,infd,outfd); + for (size_t n = 0; n < v.size(); n++) + argv[n]=v[n].c_str(); + // we get away with not copying since nobody resizes v + launch(argv, timeout, infd, outfd); } void CoProcess::launch(const char **argv, int timeout, int infd, int outfd) @@ -158,6 +163,58 @@ void CoProcess::sendReceive(const string &snd, string &rcv) receive(rcv); } + +UnixRemote::UnixRemote(const string& path, int timeout) +{ + d_fd = socket(AF_LOCAL, SOCK_STREAM, 0); + if(d_fd < 0) + throw AhuException("Unable to create UNIX domain socket: "+string(strerror(errno))); + + struct sockaddr_un remote; + memset(&remote, 0, sizeof(remote)); + remote.sun_family = AF_UNIX; + memset(remote.sun_path, 0, sizeof(remote.sun_path)); + path.copy(remote.sun_path, sizeof(remote.sun_path), 0); + + // fcntl(fd, F_SETFL, O_NONBLOCK, &sock); + + if(connect(d_fd, (struct sockaddr*)&remote, sizeof(remote)) < 0) + unixDie("Unable to connect to remote '"+path+"' using UNIX domain socket"); + + d_fp = fdopen(d_fd, "r"); +} + +void UnixRemote::send(const string& line) +{ + string nline(line); + nline.append(1, '\n'); + writen2(d_fd, nline); +} + +void UnixRemote::receive(string& line) +{ + line.clear(); + stringfgets(d_fp, line); + trim_right(line); +} + +void UnixRemote::sendReceive(const string &snd, string &rcv) +{ + // checkStatus(); + send(snd); + receive(rcv); +} + +bool isUnixSocket(const string& fname) +{ + struct stat st; + if(stat(fname.c_str(), &st) < 0) + return false; // not a unix socket in any case ;-) + + return (st.st_mode & S_IFSOCK) == S_IFSOCK; +} + + #ifdef TESTDRIVER main() { diff --git a/modules/pipebackend/coprocess.hh b/modules/pipebackend/coprocess.hh index c2cc454d62..a405afc265 100644 --- a/modules/pipebackend/coprocess.hh +++ b/modules/pipebackend/coprocess.hh @@ -5,20 +5,27 @@ #include #include -#include "pdns/namespaces.hh" +#include "pdns/namespaces.hh" -class CoProcess +class CoRemote +{ +public: + virtual void sendReceive(const string &send, string &receive) = 0; + virtual void receive(string &rcv) = 0; + virtual void send(const string &send) = 0; + +}; + +class CoProcess : public CoRemote { public: CoProcess(const string &command,int timeout=0, int infd=0, int outfd=1); - CoProcess(const char **argv, int timeout=0, int infd=0, int outfd=1); ~CoProcess(); - - void launch(const char **argv, int timeout=0, int infd=0, int outfd=1); void sendReceive(const string &send, string &receive); void receive(string &rcv); void send(const string &send); private: + void launch(const char **argv, int timeout=0, int infd=0, int outfd=1); void checkStatus(); int d_fd1[2], d_fd2[2]; int d_pid; @@ -27,4 +34,18 @@ private: int d_timeout; FILE *d_fp; }; + +class UnixRemote : public CoRemote +{ +public: + UnixRemote(const string &path, int timeout=0); + ~UnixRemote(); + void sendReceive(const string &send, string &receive); + void receive(string &rcv); + void send(const string &send); +private: + int d_fd; + FILE *d_fp; +}; +bool isUnixSocket(const string& fname); #endif diff --git a/modules/pipebackend/pipebackend.cc b/modules/pipebackend/pipebackend.cc index 511d9e8af2..daf3876dbe 100644 --- a/modules/pipebackend/pipebackend.cc +++ b/modules/pipebackend/pipebackend.cc @@ -48,7 +48,10 @@ void CoWrapper::launch() if(d_cp) return; - d_cp=new CoProcess(d_command, d_timeout); + if(isUnixSocket(d_command)) + d_cp = new UnixRemote(d_command, d_timeout); + else + d_cp = new CoProcess(d_command, d_timeout); d_cp->send("HELO\t"+lexical_cast(::arg().asNum("pipebackend-abi-version"))); string banner; d_cp->receive(banner); diff --git a/modules/pipebackend/pipebackend.hh b/modules/pipebackend/pipebackend.hh index 94712c870b..6123d27715 100644 --- a/modules/pipebackend/pipebackend.hh +++ b/modules/pipebackend/pipebackend.hh @@ -25,7 +25,7 @@ public: void send(const string &line); void receive(string &line); private: - CoProcess* d_cp; + CoRemote* d_cp; string d_command; void launch(); int d_timeout;