added wrapper class NamedPipe to create universal pipe interface for Windows and...
authorVictor Kirhenshtein <victor@netxms.org>
Tue, 12 Sep 2017 08:52:43 +0000 (11:52 +0300)
committerVictor Kirhenshtein <victor@netxms.org>
Tue, 12 Sep 2017 08:52:43 +0000 (11:52 +0300)
include/nxproc.h [new file with mode: 0644]
src/agent/core/extagent.cpp
src/agent/core/nxagentd.h
src/agent/tools/nxapush/.cproject [new file with mode: 0644]
src/agent/tools/nxapush/.project [new file with mode: 0644]
src/libnetxms/Makefile.am
src/libnetxms/libnetxms.h
src/libnetxms/nxproc.cpp [new file with mode: 0644]
src/libnetxms/nxproc_unix.cpp [new file with mode: 0644]

diff --git a/include/nxproc.h b/include/nxproc.h
new file mode 100644 (file)
index 0000000..d127cf9
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef _nxproc_h_
+#define _nxproc_h_
+
+#include <nms_common.h>
+
+/**
+ * Max pipe name length
+ */
+#define MAX_PIPE_NAME_LEN     64
+
+class NamedPipe;
+
+/**
+ * Client request handler
+ */
+typedef void (*NamedPipeRequestHandler)(NamedPipe *pipe, void *userArg);
+
+/**
+ * Named pipe class
+ */
+class LIBNETXMS_EXPORTABLE NamedPipe
+{
+private:
+   TCHAR m_name[MAX_PIPE_NAME_LEN];
+   HPIPE m_handle;
+   bool m_isListener;
+   NamedPipeRequestHandler m_reqHandler;
+   void *m_userArg;
+   THREAD m_serverThread;
+   bool m_stop;
+
+   NamedPipe(const TCHAR *name, HPIPE handle, bool listener, NamedPipeRequestHandler reqHandler = NULL, void *userArg = NULL)
+   {
+      nx_strncpy(m_name, name, MAX_PIPE_NAME_LEN);
+      m_handle = handle;
+      m_isListener = listener;
+      m_reqHandler = reqHandler;
+      m_userArg = userArg;
+      m_serverThread = INVALID_THREAD_HANDLE;
+      m_stop = false;
+   }
+
+   void serverThread();
+   static THREAD_RESULT THREAD_CALL serverThreadStarter(void *arg);
+
+public:
+   ~NamedPipe();
+
+   const TCHAR *name() const { return m_name; }
+   HPIPE handle() { return m_handle; }
+   bool isListener() const { return m_isListener; }
+
+   void startServer();
+   void stopServer();
+
+   static NamedPipe *createListener(const TCHAR *name, NamedPipeRequestHandler reqHandler, void *userArg);
+   static NamedPipe *connectTo(const TCHAR *name);
+};
+
+#endif   /* _nxproc_h_ */
index 2a64397..1ce1a3a 100644 (file)
@@ -35,6 +35,7 @@ ExternalSubagent::ExternalSubagent(const TCHAR *name, const TCHAR *user)
        nx_strncpy(m_name, name, MAX_SUBAGENT_NAME);
        nx_strncpy(m_user, user, MAX_ESA_USER_NAME);
        m_connected = false;
+       m_listener = NULL;
        m_pipe = INVALID_PIPE_HANDLE;
        m_msgQueue = new MsgWaitQueue();
        m_requestId = 1;
@@ -48,6 +49,27 @@ ExternalSubagent::~ExternalSubagent()
 {
        delete m_msgQueue;
        MutexDestroy(m_mutexPipeWrite);
+       delete m_listener;
+}
+
+/**
+ * Pipe request handler
+ */
+static void RequestHandler(NamedPipe *pipe, void *userArg)
+{
+   static_cast<ExternalSubagent*>(userArg)->connect(pipe->handle());
+}
+
+/**
+ * Start listener
+ */
+void ExternalSubagent::startListener()
+{
+   TCHAR name[MAX_PIPE_NAME_LEN];
+   _sntprintf(name, MAX_PIPE_NAME_LEN, _T("nxagentd.subagent.%s"), m_name);
+   m_listener = NamedPipe::createListener(name, RequestHandler, this);
+   if (m_listener != NULL)
+      m_listener->startServer();
 }
 
 /*
@@ -454,199 +476,6 @@ UINT32 ExternalSubagent::getList(const TCHAR *name, StringList *value)
        return rcc;
 }
 
-/**
- * Listener for external subagents
- */
-#ifdef _WIN32
-
-static THREAD_RESULT THREAD_CALL ExternalSubagentConnector(void *arg)
-{
-       ExternalSubagent *subagent = (ExternalSubagent *)arg;
-       SECURITY_ATTRIBUTES sa;
-       PSECURITY_DESCRIPTOR sd = NULL;
-       SID_IDENTIFIER_AUTHORITY sidAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
-       EXPLICIT_ACCESS ea;
-       PSID sidEveryone = NULL;
-       ACL *acl = NULL;
-       TCHAR pipeName[MAX_PATH], errorText[1024];
-
-       // Create a well-known SID for the Everyone group.
-       if(!AllocateAndInitializeSid(&sidAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &sidEveryone))
-       {
-               nxlog_debug(2, _T("ExternalSubagentConnector(%s): AllocateAndInitializeSid failed (%s)"), 
-         subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
-               goto cleanup;
-       }
-
-       // Initialize an EXPLICIT_ACCESS structure for an ACE.
-       // The ACE will allow either Everyone or given user to access pipe
-       ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
-       ea.grfAccessPermissions = (FILE_GENERIC_READ | FILE_GENERIC_WRITE) & ~FILE_CREATE_PIPE_INSTANCE;
-       ea.grfAccessMode = SET_ACCESS;
-       ea.grfInheritance = NO_INHERITANCE;
-       const TCHAR *user = subagent->getUserName();
-       if ((user[0] == 0) || !_tcscmp(user, _T("*")))
-       {
-               ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
-               ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
-               ea.Trustee.ptstrName  = (LPTSTR)sidEveryone;
-               nxlog_debug(2, _T("ExternalSubagentConnector(%s): using \"Everyone\" group"), subagent->getName());
-       }
-       else
-       {
-               ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
-               ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
-               ea.Trustee.ptstrName  = (LPTSTR)user;
-               nxlog_debug(2, _T("ExternalSubagentConnector(%s): using \"%s\" user"), subagent->getName(), user);
-       }
-
-       // Create a new ACL that contains the new ACEs.
-       if (SetEntriesInAcl(1, &ea, NULL, &acl) != ERROR_SUCCESS)
-       {
-               nxlog_debug(2, _T("ExternalSubagentConnector(%s): SetEntriesInAcl failed (%s)"), 
-         subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
-               goto cleanup;
-       }
-
-       sd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
-       if (sd == NULL)
-       {
-               nxlog_debug(2, _T("ExternalSubagentConnector(%s): LocalAlloc failed (%s)"), 
-         subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
-               goto cleanup;
-       }
-
-       if (!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION))
-       {
-               nxlog_debug(2, _T("ExternalSubagentConnector(%s): InitializeSecurityDescriptor failed (%s)"), 
-         subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
-               goto cleanup;
-       }
-
-       // Add the ACL to the security descriptor. 
-   if (!SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE))
-       {
-               nxlog_debug(2, _T("ExternalSubagentConnector(%s): SetSecurityDescriptorDacl failed (%s)"), 
-         subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
-               goto cleanup;
-       }
-
-       sa.nLength = sizeof(SECURITY_ATTRIBUTES);
-       sa.bInheritHandle = FALSE;
-       sa.lpSecurityDescriptor = sd;
-       _sntprintf(pipeName, MAX_PATH, _T("\\\\.\\pipe\\nxagentd.subagent.%s"), subagent->getName());
-       HANDLE hPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 8192, 8192, 0, &sa);
-       if (hPipe == INVALID_HANDLE_VALUE)
-       {
-               nxlog_debug(2, _T("ExternalSubagentConnector(%s): CreateNamedPipe failed (%s)"), 
-         subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
-               goto cleanup;
-       }
-
-       nxlog_debug(2, _T("ExternalSubagentConnector(%s): named pipe created, waiting for connection"), subagent->getName());
-       int connectErrors = 0;
-       while(!(g_dwFlags & AF_SHUTDOWN))
-       {
-               BOOL connected = ConnectNamedPipe(hPipe, NULL);
-               if (connected || (GetLastError() == ERROR_PIPE_CONNECTED))
-               {
-                       subagent->connect(hPipe);
-                       DisconnectNamedPipe(hPipe);
-                       connectErrors = 0;
-               }
-               else
-               {
-                       nxlog_debug(2, _T("ExternalSubagentConnector(%s): ConnectNamedPipe failed (%s)"), 
-            subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
-                       connectErrors++;
-                       if (connectErrors > 10)
-                               break;  // Stop this connector if ConnectNamedPipe fails instantly
-               }
-       }
-
-cleanup:
-       if (hPipe != NULL)
-               CloseHandle(hPipe);
-
-       if (sd != NULL)
-               LocalFree(sd);
-
-       if (acl != NULL)
-               LocalFree(acl);
-
-       if (sidEveryone != NULL)
-               FreeSid(sidEveryone);
-
-       return THREAD_OK;
-}
-
-#else
-
-static THREAD_RESULT THREAD_CALL ExternalSubagentConnector(void *arg)
-{
-       ExternalSubagent *subagent = (ExternalSubagent *)arg;
-       mode_t prevMask = 0;
-
-       int s = socket(AF_UNIX, SOCK_STREAM, 0);
-       if (s == INVALID_SOCKET)
-       {
-               AgentWriteDebugLog(2, _T("ExternalSubagentConnector: socket failed (%s)"), _tcserror(errno));
-               goto cleanup;
-       }
-       
-       struct sockaddr_un addrLocal;
-       addrLocal.sun_family = AF_UNIX;
-#ifdef UNICODE
-   sprintf(addrLocal.sun_path, "/tmp/.nxagentd.subagent.%S", subagent->getName());
-#else
-       sprintf(addrLocal.sun_path, "/tmp/.nxagentd.subagent.%s", subagent->getName());
-#endif
-       unlink(addrLocal.sun_path);
-       prevMask = umask(S_IWGRP | S_IWOTH);
-       if (bind(s, (struct sockaddr *)&addrLocal, SUN_LEN(&addrLocal)) == -1)
-       {
-               AgentWriteDebugLog(2, _T("ExternalSubagentConnector: bind failed (%s)"), _tcserror(errno));
-               umask(prevMask);
-               goto cleanup;
-       }
-       umask(prevMask);
-
-       if (listen(s, 5) == -1)
-       {
-               AgentWriteDebugLog(2, _T("ExternalSubagentConnector: listen failed (%s)"), _tcserror(errno));
-               goto cleanup;
-       }
-       
-       AgentWriteDebugLog(2, _T("ExternalSubagent(%s): UNIX socket created, waiting for connection"), subagent->getName());
-       while(!(g_dwFlags & AF_SHUTDOWN))
-       {
-               struct sockaddr_un addrRemote;
-               socklen_t size = sizeof(struct sockaddr_un);
-               SOCKET cs = accept(s, (struct sockaddr *)&addrRemote, &size);
-               if (cs > 0)
-               {
-                       subagent->connect(cs);
-                       shutdown(cs, 2);
-                       close(cs);
-               }
-               else
-               {
-                       AgentWriteDebugLog(2, _T("ExternalSubagentConnector: accept failed (%s)"), _tcserror(errno));
-               }
-       }
-
-cleanup:
-       if (s != -1)
-       {
-               close(s);
-       }
-
-       AgentWriteDebugLog(2, _T("ExternalSubagentConnector: listener thread stopped"));
-       return THREAD_OK;
-}
-
-#endif
-
 /*
  * Send message to external subagent
  */
@@ -695,7 +524,7 @@ bool AddExternalSubagent(const TCHAR *config)
 
        ExternalSubagent *subagent = new ExternalSubagent(buffer, user);
        s_subagents.add(subagent);
-       ThreadCreate(ExternalSubagentConnector, 0, subagent);
+       subagent->startListener();
        return true;
 }
 
index bc0361e..df0f137 100644 (file)
@@ -32,6 +32,7 @@
 #include <nxlog.h>
 #include <nxcldefs.h>
 #include <nxdbapi.h>
+#include <nxproc.h>
 #include "messages.h"
 #include "nxsnmp.h"
 #include "localdb.h"
@@ -224,6 +225,7 @@ class ExternalSubagent
 private:
        TCHAR m_name[MAX_SUBAGENT_NAME];
        TCHAR m_user[MAX_ESA_USER_NAME];
+       NamedPipe *m_listener;
        HPIPE m_pipe;
        bool m_connected;
        MsgWaitQueue *m_msgQueue;
@@ -241,6 +243,7 @@ public:
        ExternalSubagent(const TCHAR *name, const TCHAR *user);
        ~ExternalSubagent();
 
+       void startListener();
        void connect(HPIPE hPipe);
 
        bool isConnected() { return m_connected; }
diff --git a/src/agent/tools/nxapush/.cproject b/src/agent/tools/nxapush/.cproject
new file mode 100644 (file)
index 0000000..a1d83b8
--- /dev/null
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+       <storageModule moduleId="org.eclipse.cdt.core.settings">
+               <cconfiguration id="cdt.managedbuild.toolchain.gnu.base.708335973">
+                       <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.708335973" moduleId="org.eclipse.cdt.core.settings" name="Default">
+                               <externalSettings/>
+                               <extensions>
+                                       <extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+                                       <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+                                       <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+                               </extensions>
+                       </storageModule>
+                       <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+                               <configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.708335973" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
+                                       <folderInfo id="cdt.managedbuild.toolchain.gnu.base.708335973.1878718594" name="/" resourcePath="">
+                                               <toolChain id="cdt.managedbuild.toolchain.gnu.base.67757022" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
+                                                       <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.GNU_ELF" id="cdt.managedbuild.target.gnu.platform.base.2113799865" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+                                                       <builder id="cdt.managedbuild.target.gnu.builder.base.2106662143" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.base"/>
+                                                       <tool id="cdt.managedbuild.tool.gnu.archiver.base.1176976196" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+                                                       <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.919202034" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+                                                               <option id="gnu.cpp.compiler.option.include.paths.1198755944" name="Include paths (-I)" superClass="gnu.cpp.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
+                                                                       <listOptionValue builtIn="false" value="&quot;${NETXMS_BASE}&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;${NETXMS_BASE}/include&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;${MYSQL_INCLUDE_DIR}&quot;"/>
+                                                               </option>
+                                                               <option id="gnu.cpp.compiler.option.preprocessor.def.1349308897" name="Defined symbols (-D)" superClass="gnu.cpp.compiler.option.preprocessor.def" useByScannerDiscovery="false" valueType="definedSymbols">
+                                                                       <listOptionValue builtIn="false" value="_THREAD_SAFE"/>
+                                                                       <listOptionValue builtIn="false" value="TRE_WCHAR=1"/>
+                                                                       <listOptionValue builtIn="false" value="UNICODE"/>
+                                                                       <listOptionValue builtIn="false" value="_GNU_SOURCE"/>
+                                                               </option>
+                                                               <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1928660912" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+                                                       </tool>
+                                                       <tool id="cdt.managedbuild.tool.gnu.c.compiler.base.952596861" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+                                                               <option id="gnu.c.compiler.option.include.paths.104067224" name="Include paths (-I)" superClass="gnu.c.compiler.option.include.paths" useByScannerDiscovery="false" valueType="includePath">
+                                                                       <listOptionValue builtIn="false" value="&quot;${NETXMS_BASE}&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;${NETXMS_BASE}/include&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;${MYSQL_INCLUDE_DIR}&quot;"/>
+                                                               </option>
+                                                               <option id="gnu.c.compiler.option.preprocessor.def.symbols.679128957" name="Defined symbols (-D)" superClass="gnu.c.compiler.option.preprocessor.def.symbols" useByScannerDiscovery="false" valueType="definedSymbols">
+                                                                       <listOptionValue builtIn="false" value="_THREAD_SAFE"/>
+                                                                       <listOptionValue builtIn="false" value="TRE_WCHAR=1"/>
+                                                                       <listOptionValue builtIn="false" value="UNICODE"/>
+                                                                       <listOptionValue builtIn="false" value="_GNU_SOURCE"/>
+                                                               </option>
+                                                               <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.265300309" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+                                                       </tool>
+                                                       <tool id="cdt.managedbuild.tool.gnu.c.linker.base.1456125579" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+                                                       <tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.2097002689" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+                                                               <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1922428779" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+                                                                       <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+                                                                       <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+                                                               </inputType>
+                                                       </tool>
+                                                       <tool id="cdt.managedbuild.tool.gnu.assembler.base.818417693" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+                                                               <option id="gnu.both.asm.option.include.paths.769224565" name="Include paths (-I)" superClass="gnu.both.asm.option.include.paths" valueType="includePath">
+                                                                       <listOptionValue builtIn="false" value="&quot;${NETXMS_BASE}&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;${NETXMS_BASE}/include&quot;"/>
+                                                                       <listOptionValue builtIn="false" value="&quot;${MYSQL_INCLUDE_DIR}&quot;"/>
+                                                               </option>
+                                                               <inputType id="cdt.managedbuild.tool.gnu.assembler.input.2137838955" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+                                                       </tool>
+                                               </toolChain>
+                                       </folderInfo>
+                               </configuration>
+                       </storageModule>
+                       <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+               </cconfiguration>
+       </storageModule>
+       <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+               <project id="nxapush.null.1812457266" name="nxapush"/>
+       </storageModule>
+       <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+       <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+       <storageModule moduleId="scannerConfiguration">
+               <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+               <scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.708335973;cdt.managedbuild.toolchain.gnu.base.708335973.1878718594;cdt.managedbuild.tool.gnu.cpp.compiler.base.919202034;cdt.managedbuild.tool.gnu.cpp.compiler.input.1928660912">
+                       <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+               </scannerConfigBuildInfo>
+               <scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.708335973;cdt.managedbuild.toolchain.gnu.base.708335973.1878718594;cdt.managedbuild.tool.gnu.c.compiler.base.952596861;cdt.managedbuild.tool.gnu.c.compiler.input.265300309">
+                       <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+               </scannerConfigBuildInfo>
+       </storageModule>
+</cproject>
diff --git a/src/agent/tools/nxapush/.project b/src/agent/tools/nxapush/.project
new file mode 100644 (file)
index 0000000..a93d06f
--- /dev/null
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>nxapush</name>
+       <comment></comment>
+       <projects>
+               <project>libnetxms</project>
+               <project>libnxagent</project>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+                       <triggers>clean,full,incremental,</triggers>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+                       <triggers>full,incremental,</triggers>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.cdt.core.cnature</nature>
+               <nature>org.eclipse.cdt.core.ccnature</nature>
+               <nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+               <nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+       </natures>
+       <filteredResources>
+               <filter>
+                       <id>1505202042143</id>
+                       <name></name>
+                       <type>6</type>
+                       <matcher>
+                               <id>org.eclipse.ui.ide.multiFilter</id>
+                               <arguments>1.0-name-matches-false-false-*.o</arguments>
+                       </matcher>
+               </filter>
+               <filter>
+                       <id>1505202042151</id>
+                       <name></name>
+                       <type>6</type>
+                       <matcher>
+                               <id>org.eclipse.ui.ide.multiFilter</id>
+                               <arguments>1.0-name-matches-false-false-*.lo</arguments>
+                       </matcher>
+               </filter>
+               <filter>
+                       <id>1505202042155</id>
+                       <name></name>
+                       <type>6</type>
+                       <matcher>
+                               <id>org.eclipse.ui.ide.multiFilter</id>
+                               <arguments>1.0-name-matches-false-false-*.la</arguments>
+                       </matcher>
+               </filter>
+       </filteredResources>
+</projectDescription>
index de94863..cd89143 100644 (file)
@@ -3,7 +3,8 @@ SOURCES = array.cpp base64.cpp bytestream.cpp cc_mb.cpp cc_ucs2.cpp \
          dirw_unix.c geolocation.cpp getopt.c dload.cpp hash.cpp \
          hashmapbase.cpp ice.c icmp.cpp icmp6.cpp iconv.cpp inet_pton.c \
          inetaddr.cpp log.cpp lz4.c main.cpp macaddr.cpp md5.cpp message.cpp \
-         msgrecv.cpp msgwq.cpp net.cpp nxcp.cpp pa.cpp parisc_atomic.cpp \
+         msgrecv.cpp msgwq.cpp net.cpp nxcp.cpp nxproc.cpp nxproc_unix.cpp \
+         pa.cpp parisc_atomic.cpp \
           qsort.c queue.cpp rbuffer.cpp rwlock.cpp scandir.c serial.cpp \
          sha1.cpp sha2.cpp solaris9_atomic.c spoll.cpp streamcomp.cpp \
          string.cpp stringlist.cpp strmap.cpp strmapbase.cpp strptime.c \
@@ -50,5 +51,6 @@ EXTRA_DIST = \
        libnetxms.vcproj \
        libnetxms.h diff.h ice.h lz4.h md5.h sha1.h sha2.h strmap-internal.h unicode_cc.h \
        dir.cpp dirw.cpp \
+       nxproc_win32.cpp \
        seh.cpp StackWalker.cpp StackWalker.h \
        ldcw.s
index e3cdfec..eb7e1a4 100644 (file)
@@ -1,7 +1,7 @@
 /* 
 ** NetXMS - Network Management System
 ** Utility Library
-** Copyright (C) 2003-2010 Victor Kirhenshtein
+** Copyright (C) 2003-2017 Victor Kirhenshtein
 **
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
diff --git a/src/libnetxms/nxproc.cpp b/src/libnetxms/nxproc.cpp
new file mode 100644 (file)
index 0000000..f2ea049
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+** NetXMS - Network Management System
+** NetXMS Foundation Library
+** Copyright (C) 2003-2017 Victor Kirhenshtein
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published
+** by the Free Software Foundation; either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** File: nxproc.cpp
+**
+**/
+
+#include "libnetxms.h"
+#include <nxproc.h>
+
+/**
+ * Start named pipe server
+ */
+void NamedPipe::startServer()
+{
+   if (m_serverThread != INVALID_THREAD_HANDLE)
+      return;  // already started
+
+   m_stop = false;
+   m_serverThread = ThreadCreateEx(NamedPipe::serverThreadStarter, 0, this);
+}
+
+/**
+ * Stop named pipe server
+ */
+void NamedPipe::stopServer()
+{
+   m_stop = true;
+   ThreadJoin(m_serverThread);
+   m_serverThread = INVALID_THREAD_HANDLE;
+}
+
+/**
+ * Named pipe server thread starter
+ */
+THREAD_RESULT THREAD_CALL NamedPipe::serverThreadStarter(void *arg)
+{
+   static_cast<NamedPipe*>(arg)->serverThread();
+   return THREAD_OK;
+}
diff --git a/src/libnetxms/nxproc_unix.cpp b/src/libnetxms/nxproc_unix.cpp
new file mode 100644 (file)
index 0000000..ce0dc71
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+** NetXMS - Network Management System
+** NetXMS Foundation Library
+** Copyright (C) 2003-2017 Victor Kirhenshtein
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU Lesser General Public License as published
+** by the Free Software Foundation; either version 3 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU Lesser General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** File: nxproc_unix.cpp
+**
+**/
+
+#include "libnetxms.h"
+#include <nxproc.h>
+
+/**
+ * Create listener end for named pipe
+ */
+NamedPipe *NamedPipe::createListener(const TCHAR *name, NamedPipeRequestHandler reqHandler, void *userArg)
+{
+   mode_t prevMask = 0;
+
+   int s = socket(AF_UNIX, SOCK_STREAM, 0);
+   if (s == INVALID_SOCKET)
+   {
+      nxlog_debug(2, _T("NamedPipe(%s): socket() call failed (%s)"), name, _tcserror(errno));
+      return NULL;
+   }
+
+   struct sockaddr_un addrLocal;
+   addrLocal.sun_family = AF_UNIX;
+#ifdef UNICODE
+   sprintf(addrLocal.sun_path, "/tmp/.%S", name);
+#else
+   sprintf(addrLocal.sun_path, "/tmp/.%s", name);
+#endif
+   unlink(addrLocal.sun_path);
+   prevMask = umask(S_IWGRP | S_IWOTH);
+   if (bind(s, (struct sockaddr *)&addrLocal, SUN_LEN(&addrLocal)) == -1)
+   {
+      nxlog_debug(2, _T("NamedPipe(%s): bind failed (%s)"), name, _tcserror(errno));
+      umask(prevMask);
+      goto failure;
+   }
+   umask(prevMask);
+
+   if (listen(s, 5) == -1)
+   {
+      nxlog_debug(2, _T("NamedPipe(%s): listen() call failed (%s)"), name, _tcserror(errno));
+      goto failure;
+   }
+
+   return new NamedPipe(name, s, true, reqHandler, userArg);
+
+failure:
+   close(s);
+   unlink(addrLocal.sun_path);
+   return NULL;
+}
+
+/**
+ * Create client end for named pipe
+ */
+NamedPipe *NamedPipe::connectTo(const TCHAR *name)
+{
+   int s = socket(AF_UNIX, SOCK_STREAM, 0);
+   if (s == INVALID_SOCKET)
+   {
+      nxlog_debug(2, _T("NamedPipe(%s): socket() call failed (%s)"), name, _tcserror(errno));
+      return NULL;
+   }
+
+   struct sockaddr_un remote;
+   remote.sun_family = AF_UNIX;
+#ifdef UNICODE
+   sprintf(remote.sun_path, "/tmp/.%S", name);
+#else
+   sprintf(remote.sun_path, "/tmp/.%s", name);
+#endif
+   if (connect(s, (struct sockaddr *)&remote, SUN_LEN(&remote)) == -1)
+   {
+      close(s);
+      return NULL;
+   }
+
+   return new NamedPipe(name, s, false);
+}
+
+/**
+ * Pipe destructor
+ */
+NamedPipe::~NamedPipe()
+{
+   close(m_handle);
+   if (m_isListener)
+   {
+      stopServer();
+      char path[MAX_PATH];
+#ifdef UNICODE
+      sprintf(path, "/tmp/.%S", m_name);
+#else
+      sprintf(path, "/tmp/.%s", m_name);
+#endif
+      unlink(path);
+   }
+}
+
+/**
+ * Named pipe server thread
+ */
+void NamedPipe::serverThread()
+{
+   nxlog_debug(2, _T("NamedPipe(%s): waiting for connection"), m_name);
+   while(!m_stop)
+   {
+      struct sockaddr_un addrRemote;
+      socklen_t size = sizeof(struct sockaddr_un);
+      SOCKET cs = accept(m_handle, (struct sockaddr *)&addrRemote, &size);
+      if (cs > 0)
+      {
+         NamedPipe *cp = new NamedPipe(m_name, cs, false);
+         m_reqHandler(cp, m_userArg);
+         delete cp;
+      }
+      else
+      {
+         nxlog_debug(2, _T("NamedPipe(%s): accept failed (%s)"), m_name, _tcserror(errno));
+      }
+   }
+}