Permalink
Browse files

apply variant of code in t714 so we can lauch pipe backend scripts wi…

…th 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
  • Loading branch information...
1 parent 9566683 commit 2f2b01452555786254f457d20524f9a2d96674a6 @ahupowerdns ahupowerdns committed Mar 7, 2013
@@ -7,21 +7,26 @@
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <sys/un.h>
#include <pdns/misc.hh>
#include <pdns/ahuexception.hh>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <boost/algorithm/string.hpp>
+#include <vector>
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 <string> 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()
{
@@ -5,20 +5,27 @@
#include <stdio.h>
#include <string>
-#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
@@ -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<string>(::arg().asNum("pipebackend-abi-version")));
string banner;
d_cp->receive(banner);
@@ -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;

0 comments on commit 2f2b014

Please sign in to comment.