ce0dc711e41ec144d24f977f950e43d58079894a
[public/netxms.git] / src / libnetxms / nxproc_unix.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** NetXMS Foundation Library
4 ** Copyright (C) 2003-2017 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published
8 ** by the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: nxproc_unix.cpp
21 **
22 **/
23
24 #include "libnetxms.h"
25 #include <nxproc.h>
26
27 /**
28 * Create listener end for named pipe
29 */
30 NamedPipe *NamedPipe::createListener(const TCHAR *name, NamedPipeRequestHandler reqHandler, void *userArg)
31 {
32 mode_t prevMask = 0;
33
34 int s = socket(AF_UNIX, SOCK_STREAM, 0);
35 if (s == INVALID_SOCKET)
36 {
37 nxlog_debug(2, _T("NamedPipe(%s): socket() call failed (%s)"), name, _tcserror(errno));
38 return NULL;
39 }
40
41 struct sockaddr_un addrLocal;
42 addrLocal.sun_family = AF_UNIX;
43 #ifdef UNICODE
44 sprintf(addrLocal.sun_path, "/tmp/.%S", name);
45 #else
46 sprintf(addrLocal.sun_path, "/tmp/.%s", name);
47 #endif
48 unlink(addrLocal.sun_path);
49 prevMask = umask(S_IWGRP | S_IWOTH);
50 if (bind(s, (struct sockaddr *)&addrLocal, SUN_LEN(&addrLocal)) == -1)
51 {
52 nxlog_debug(2, _T("NamedPipe(%s): bind failed (%s)"), name, _tcserror(errno));
53 umask(prevMask);
54 goto failure;
55 }
56 umask(prevMask);
57
58 if (listen(s, 5) == -1)
59 {
60 nxlog_debug(2, _T("NamedPipe(%s): listen() call failed (%s)"), name, _tcserror(errno));
61 goto failure;
62 }
63
64 return new NamedPipe(name, s, true, reqHandler, userArg);
65
66 failure:
67 close(s);
68 unlink(addrLocal.sun_path);
69 return NULL;
70 }
71
72 /**
73 * Create client end for named pipe
74 */
75 NamedPipe *NamedPipe::connectTo(const TCHAR *name)
76 {
77 int s = socket(AF_UNIX, SOCK_STREAM, 0);
78 if (s == INVALID_SOCKET)
79 {
80 nxlog_debug(2, _T("NamedPipe(%s): socket() call failed (%s)"), name, _tcserror(errno));
81 return NULL;
82 }
83
84 struct sockaddr_un remote;
85 remote.sun_family = AF_UNIX;
86 #ifdef UNICODE
87 sprintf(remote.sun_path, "/tmp/.%S", name);
88 #else
89 sprintf(remote.sun_path, "/tmp/.%s", name);
90 #endif
91 if (connect(s, (struct sockaddr *)&remote, SUN_LEN(&remote)) == -1)
92 {
93 close(s);
94 return NULL;
95 }
96
97 return new NamedPipe(name, s, false);
98 }
99
100 /**
101 * Pipe destructor
102 */
103 NamedPipe::~NamedPipe()
104 {
105 close(m_handle);
106 if (m_isListener)
107 {
108 stopServer();
109 char path[MAX_PATH];
110 #ifdef UNICODE
111 sprintf(path, "/tmp/.%S", m_name);
112 #else
113 sprintf(path, "/tmp/.%s", m_name);
114 #endif
115 unlink(path);
116 }
117 }
118
119 /**
120 * Named pipe server thread
121 */
122 void NamedPipe::serverThread()
123 {
124 nxlog_debug(2, _T("NamedPipe(%s): waiting for connection"), m_name);
125 while(!m_stop)
126 {
127 struct sockaddr_un addrRemote;
128 socklen_t size = sizeof(struct sockaddr_un);
129 SOCKET cs = accept(m_handle, (struct sockaddr *)&addrRemote, &size);
130 if (cs > 0)
131 {
132 NamedPipe *cp = new NamedPipe(m_name, cs, false);
133 m_reqHandler(cp, m_userArg);
134 delete cp;
135 }
136 else
137 {
138 nxlog_debug(2, _T("NamedPipe(%s): accept failed (%s)"), m_name, _tcserror(errno));
139 }
140 }
141 }