2 ** NetXMS multiplatform core agent
3 ** Copyright (C) 2003-2017 Victor Kirhenshtein
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
37 #if HAVE_SYS_UTSNAME_H
38 #include <sys/utsname.h>
42 #include <sys/sysctl.h>
45 #ifdef _WITH_ENCRYPTION
46 #include <openssl/ssl.h>
57 #define DEFAULT_CONFIG_SECTION _T("CORE")
62 THREAD_RESULT THREAD_CALL
ListenerThread(void *);
63 THREAD_RESULT THREAD_CALL
SessionWatchdog(void *);
64 THREAD_RESULT THREAD_CALL
TrapSender(void *);
65 THREAD_RESULT THREAD_CALL
MasterAgentListener(void *arg
);
66 THREAD_RESULT THREAD_CALL
SNMPTrapReceiver(void *);
67 THREAD_RESULT THREAD_CALL
SNMPTrapSender(void *);
68 THREAD_RESULT THREAD_CALL
SyslogReceiver(void *);
69 THREAD_RESULT THREAD_CALL
SyslogSender(void *);
70 THREAD_RESULT THREAD_CALL
TunnelManager(void *);
72 void ShutdownTrapSender();
73 void ShutdownSNMPTrapSender();
75 void ShutdownSyslogSender();
77 void StartLocalDataCollector();
78 void ShutdownLocalDataCollector();
82 int WatchdogMain(DWORD pid
);
84 void InitSessionList();
85 void DestroySessionList();
87 BOOL
RegisterOnServer(const TCHAR
*pszServer
);
89 void UpdatePolicyInventory();
91 void ParseTunnelList(TCHAR
*list
);
94 void InitStaticSubagents();
98 extern TCHAR g_windowsServiceName
[];
99 extern TCHAR g_windowsServiceDisplayName
[];
102 void LIBNXAGENT_EXPORTABLE
InitSubAgentAPI(void (* writeLog
)(int, int, const TCHAR
*),
103 void (* sendTrap1
)(UINT32
, const TCHAR
*, const char *, va_list),
104 void (* sendTrap2
)(UINT32
, const TCHAR
*, int, TCHAR
**),
105 bool (* enumerateSessions
)(EnumerationCallbackResult (*)(AbstractCommSession
*, void *), void*),
106 AbstractCommSession
*(* findServerSession
)(UINT64
),
107 bool (* sendFile
)(void *, UINT32
, const TCHAR
*, long, bool),
108 bool (* pushData
)(const TCHAR
*, const TCHAR
*, UINT32
, time_t),
109 DB_HANDLE (* getLocalDatabaseHandle
)(),
110 CONDITION shutdownCondition
, const TCHAR
*dataDirectory
);
113 * Messages generated by mc.pl (for UNIX version only)
116 extern unsigned int g_dwNumMessages
;
117 extern const TCHAR
*g_szMessages
[];
124 #include <openssl/applink.c>
128 * Valid options for getopt()
131 #define VALID_OPTIONS "c:CdD:e:EfG:hHiIKM:n:N:P:r:RsSUvW:X:Z:"
133 #define VALID_OPTIONS "c:CdD:fg:G:hKM:p:P:r:u:vW:X:Z:"
139 #define ACTION_NONE 0
140 #define ACTION_RUN_AGENT 1
141 #define ACTION_INSTALL_SERVICE 2
142 #define ACTION_REMOVE_SERVICE 3
143 #define ACTION_START_SERVICE 4
144 #define ACTION_STOP_SERVICE 5
145 #define ACTION_CHECK_CONFIG 6
146 #define ACTION_INSTALL_EVENT_SOURCE 7
147 #define ACTION_REMOVE_EVENT_SOURCE 8
148 #define ACTION_CREATE_CONFIG 9
149 #define ACTION_HELP 10
150 #define ACTION_RUN_WATCHDOG 11
151 #define ACTION_SHUTDOWN_EXT_AGENTS 12
156 UINT32 g_dwFlags
= AF_ENABLE_ACTIONS
| AF_ENABLE_AUTOLOAD
| AF_WRITE_FULL_DUMP
;
157 UINT32 g_failFlags
= 0;
158 TCHAR g_szLogFile
[MAX_PATH
] = AGENT_DEFAULT_LOG
;
159 TCHAR g_szSharedSecret
[MAX_SECRET_LENGTH
] = _T("admin");
160 TCHAR g_szConfigFile
[MAX_PATH
] = AGENT_DEFAULT_CONFIG
;
161 TCHAR g_szFileStore
[MAX_PATH
] = AGENT_DEFAULT_FILE_STORE
;
162 TCHAR g_szDataDirectory
[MAX_PATH
] = AGENT_DEFAULT_DATA_DIR
;
163 TCHAR g_szPlatformSuffix
[MAX_PSUFFIX_LENGTH
] = _T("");
164 TCHAR g_szConfigServer
[MAX_DB_STRING
] = _T("not_set");
165 TCHAR g_szRegistrar
[MAX_DB_STRING
] = _T("not_set");
166 TCHAR g_szListenAddress
[MAX_PATH
] = _T("*");
167 TCHAR g_szConfigIncludeDir
[MAX_PATH
] = AGENT_DEFAULT_CONFIG_D
;
168 TCHAR g_szConfigPolicyDir
[MAX_PATH
] = AGENT_DEFAULT_CONFIG_D
;
169 TCHAR g_szLogParserDirectory
[MAX_PATH
] = _T("");
170 TCHAR g_certificateDirectory
[MAX_PATH
] = _T("");
171 TCHAR g_masterAgent
[MAX_PATH
] = _T("not_set");
172 TCHAR g_szSNMPTrapListenAddress
[MAX_PATH
] = _T("*");
173 UINT16 g_wListenPort
= AGENT_LISTEN_PORT
;
174 TCHAR g_systemName
[MAX_OBJECT_NAME
] = _T("");
175 ObjectArray
<ServerInfo
> g_serverList(8, 8, true);
176 UINT32 g_execTimeout
= 2000; // External process execution timeout in milliseconds
177 UINT32 g_snmpTimeout
= 1000;
178 UINT16 g_snmpTrapPort
= 162;
179 time_t g_tmAgentStartTime
;
180 UINT32 g_dwStartupDelay
= 0;
181 UINT32 g_dwMaxSessions
= 0;
182 UINT32 g_longRunningQueryThreshold
= 250;
183 UINT32 g_dcReconciliationBlockSize
= 1024;
184 UINT32 g_dcReconciliationTimeout
= 15000;
185 UINT32 g_dcMaxCollectorPoolSize
= 64;
186 UINT32 g_zoneUIN
= 0;
187 UINT16 g_syslogListenPort
= 514;
189 UINT16 g_sessionAgentPort
= 28180;
191 UINT16 g_sessionAgentPort
= 0;
193 Config
*g_config
= NULL
;
194 UINT32 g_dwIdleTimeout
= 120; // Session idle timeout
197 TCHAR g_szPidFile
[MAX_PATH
] = _T("/var/run/nxagentd.pid");
203 static TCHAR
*m_pszActionList
= NULL
;
204 static TCHAR
*m_pszShellActionList
= NULL
;
205 static TCHAR
*m_pszServerList
= NULL
;
206 static TCHAR
*m_pszControlServerList
= NULL
;
207 static TCHAR
*m_pszMasterServerList
= NULL
;
208 static TCHAR
*m_pszSubagentList
= NULL
;
209 static TCHAR
*s_externalParametersConfig
= NULL
;
210 static TCHAR
*s_externalShellExecParametersConfig
= NULL
;
211 static TCHAR
*s_externalParameterProvidersConfig
= NULL
;
212 static TCHAR
*s_externalListsConfig
= NULL
;
213 static TCHAR
*s_externalTablesConfig
= NULL
;
214 static TCHAR
*s_externalSubAgentsList
= NULL
;
215 static TCHAR
*s_appAgentsList
= NULL
;
216 static TCHAR
*s_serverConnectionList
= NULL
;
217 static UINT32 s_enabledCiphers
= 0xFFFF;
218 static THREAD s_sessionWatchdogThread
= INVALID_THREAD_HANDLE
;
219 static THREAD s_listenerThread
= INVALID_THREAD_HANDLE
;
220 static THREAD s_eventSenderThread
= INVALID_THREAD_HANDLE
;
221 static THREAD s_snmpTrapReceiverThread
= INVALID_THREAD_HANDLE
;
222 static THREAD s_snmpTrapSenderThread
= INVALID_THREAD_HANDLE
;
223 static THREAD s_syslogReceiverThread
= INVALID_THREAD_HANDLE
;
224 static THREAD s_syslogSenderThread
= INVALID_THREAD_HANDLE
;
225 static THREAD s_masterAgentListenerThread
= INVALID_THREAD_HANDLE
;
226 static THREAD s_tunnelManagerThread
= INVALID_THREAD_HANDLE
;
227 static TCHAR s_processToWaitFor
[MAX_PATH
] = _T("");
228 static TCHAR s_dumpDir
[MAX_PATH
] = _T("C:\\");
229 static UINT64 s_maxLogSize
= 16384 * 1024;
230 static UINT32 s_logHistorySize
= 4;
231 static UINT32 s_logRotationMode
= NXLOG_ROTATION_BY_SIZE
;
232 static TCHAR s_dailyLogFileSuffix
[64] = _T("");
233 static TCHAR s_executableName
[MAX_PATH
];
234 static UINT32 s_debugLevel
= (UINT32
)NXCONFIG_UNINITIALIZED_VALUE
;
235 static TCHAR
*s_debugTags
= NULL
;
237 static CONDITION s_subAgentsStopCondition
= INVALID_CONDITION_HANDLE
;
239 static CONDITION s_shutdownCondition
= INVALID_CONDITION_HANDLE
;
247 * Configuration file template
249 static NX_CFG_TEMPLATE m_cfgTemplate
[] =
251 { _T("Action"), CT_STRING_LIST
, '\n', 0, 0, 0, &m_pszActionList
, NULL
},
252 { _T("ActionShellExec"), CT_STRING_LIST
, '\n', 0, 0, 0, &m_pszShellActionList
, NULL
},
253 { _T("AppAgent"), CT_STRING_LIST
, '\n', 0, 0, 0, &s_appAgentsList
, NULL
},
254 { _T("BackgroundLogWriter"), CT_BOOLEAN
, 0, 0, AF_BACKGROUND_LOG_WRITER
, 0, &g_dwFlags
, NULL
},
255 { _T("ControlServers"), CT_STRING_LIST
, ',', 0, 0, 0, &m_pszControlServerList
, NULL
},
256 { _T("CreateCrashDumps"), CT_BOOLEAN
, 0, 0, AF_CATCH_EXCEPTIONS
, 0, &g_dwFlags
, NULL
},
257 { _T("DataCollectionThreadPoolSize"), CT_LONG
, 0, 0, 0, 0, &g_dcMaxCollectorPoolSize
, NULL
},
258 { _T("DataDirectory"), CT_STRING
, 0, 0, MAX_PATH
, 0, g_szDataDirectory
, NULL
},
259 { _T("DataReconciliationBlockSize"), CT_LONG
, 0, 0, 0, 0, &g_dcReconciliationBlockSize
, NULL
},
260 { _T("DataReconciliationTimeout"), CT_LONG
, 0, 0, 0, 0, &g_dcReconciliationTimeout
, NULL
},
261 { _T("DailyLogFileSuffix"), CT_STRING
, 0, 0, 64, 0, s_dailyLogFileSuffix
, NULL
},
262 { _T("DebugLevel"), CT_LONG
, 0, 0, 0, 0, &s_debugLevel
, &s_debugLevel
},
263 { _T("DebugTags"), CT_STRING_LIST
, ',', 0, 0, 0, &s_debugTags
, NULL
},
264 { _T("DisableIPv4"), CT_BOOLEAN
, 0, 0, AF_DISABLE_IPV4
, 0, &g_dwFlags
, NULL
},
265 { _T("DisableIPv6"), CT_BOOLEAN
, 0, 0, AF_DISABLE_IPV6
, 0, &g_dwFlags
, NULL
},
266 { _T("DumpDirectory"), CT_STRING
, 0, 0, MAX_PATH
, 0, s_dumpDir
, NULL
},
267 { _T("EnableActions"), CT_BOOLEAN
, 0, 0, AF_ENABLE_ACTIONS
, 0, &g_dwFlags
, NULL
},
268 { _T("EnabledCiphers"), CT_LONG
, 0, 0, 0, 0, &s_enabledCiphers
, NULL
},
269 { _T("EnableControlConnector"), CT_BOOLEAN
, 0, 0, AF_ENABLE_CONTROL_CONNECTOR
, 0, &g_dwFlags
, NULL
},
270 { _T("EnableProxy"), CT_BOOLEAN
, 0, 0, AF_ENABLE_PROXY
, 0, &g_dwFlags
, NULL
},
271 { _T("EnableSNMPProxy"), CT_BOOLEAN
, 0, 0, AF_ENABLE_SNMP_PROXY
, 0, &g_dwFlags
, NULL
},
272 { _T("EnableSNMPTrapProxy"), CT_BOOLEAN
, 0, 0, AF_ENABLE_SNMP_TRAP_PROXY
, 0, &g_dwFlags
, NULL
},
273 { _T("EnableSyslogProxy"), CT_BOOLEAN
, 0, 0, AF_ENABLE_SYSLOG_PROXY
, 0, &g_dwFlags
, NULL
},
274 { _T("EnableSubagentAutoload"), CT_BOOLEAN
, 0, 0, AF_ENABLE_AUTOLOAD
, 0, &g_dwFlags
, NULL
},
275 { _T("EnableWatchdog"), CT_BOOLEAN
, 0, 0, AF_ENABLE_WATCHDOG
, 0, &g_dwFlags
, NULL
},
276 { _T("EncryptedSharedSecret"), CT_STRING
, 0, 0, MAX_SECRET_LENGTH
, 0, g_szSharedSecret
, NULL
},
277 { _T("ExecTimeout"), CT_LONG
, 0, 0, 0, 0, &g_execTimeout
, NULL
},
278 { _T("ExternalList"), CT_STRING_LIST
, '\n', 0, 0, 0, &s_externalListsConfig
, NULL
},
279 { _T("ExternalMasterAgent"), CT_STRING
, 0, 0, MAX_PATH
, 0, g_masterAgent
, NULL
},
280 { _T("ExternalParameter"), CT_STRING_LIST
, '\n', 0, 0, 0, &s_externalParametersConfig
, NULL
},
281 { _T("ExternalParameterShellExec"), CT_STRING_LIST
, '\n', 0, 0, 0, &s_externalShellExecParametersConfig
, NULL
},
282 { _T("ExternalParametersProvider"), CT_STRING_LIST
, '\n', 0, 0, 0, &s_externalParameterProvidersConfig
, NULL
},
283 { _T("ExternalSubagent"), CT_STRING_LIST
, '\n', 0, 0, 0, &s_externalSubAgentsList
, NULL
},
284 { _T("ExternalTable"), CT_STRING_LIST
, '\n', 0, 0, 0, &s_externalTablesConfig
, NULL
},
285 { _T("FileStore"), CT_STRING
, 0, 0, MAX_PATH
, 0, g_szFileStore
, NULL
},
286 { _T("FullCrashDumps"), CT_BOOLEAN
, 0, 0, AF_WRITE_FULL_DUMP
, 0, &g_dwFlags
, NULL
},
287 { _T("ListenAddress"), CT_STRING
, 0, 0, MAX_PATH
, 0, g_szListenAddress
, NULL
},
288 { _T("ListenPort"), CT_WORD
, 0, 0, 0, 0, &g_wListenPort
, NULL
},
289 { _T("LogFile"), CT_STRING
, 0, 0, MAX_PATH
, 0, g_szLogFile
, NULL
},
290 { _T("LogHistorySize"), CT_LONG
, 0, 0, 0, 0, &s_logHistorySize
, NULL
},
291 { _T("LogRotationMode"), CT_LONG
, 0, 0, 0, 0, &s_logRotationMode
, NULL
},
292 { _T("LogUnresolvedSymbols"), CT_BOOLEAN
, 0, 0, AF_LOG_UNRESOLVED_SYMBOLS
, 0, &g_dwFlags
, NULL
},
293 { _T("LongRunningQueryThreshold"), CT_LONG
, 0, 0, 0, 0, &g_longRunningQueryThreshold
, NULL
},
294 { _T("MasterServers"), CT_STRING_LIST
, ',', 0, 0, 0, &m_pszMasterServerList
, NULL
},
295 { _T("MaxLogSize"), CT_SIZE_BYTES
, 0, 0, 0, 0, &s_maxLogSize
, NULL
},
296 { _T("MaxSessions"), CT_LONG
, 0, 0, 0, 0, &g_dwMaxSessions
, NULL
},
297 { _T("PlatformSuffix"), CT_STRING
, 0, 0, MAX_PSUFFIX_LENGTH
, 0, g_szPlatformSuffix
, NULL
},
298 { _T("RequireAuthentication"), CT_BOOLEAN
, 0, 0, AF_REQUIRE_AUTH
, 0, &g_dwFlags
, NULL
},
299 { _T("RequireEncryption"), CT_BOOLEAN
, 0, 0, AF_REQUIRE_ENCRYPTION
, 0, &g_dwFlags
, NULL
},
300 { _T("ServerConnection"), CT_STRING_LIST
, '\n', 0, 0, 0, &s_serverConnectionList
, NULL
},
301 { _T("Servers"), CT_STRING_LIST
, ',', 0, 0, 0, &m_pszServerList
, NULL
},
302 { _T("SessionIdleTimeout"), CT_LONG
, 0, 0, 0, 0, &g_dwIdleTimeout
, NULL
},
303 { _T("SessionAgentPort"), CT_WORD
, 0, 0, 0, 0, &g_sessionAgentPort
, NULL
},
304 { _T("SharedSecret"), CT_STRING
, 0, 0, MAX_SECRET_LENGTH
, 0, g_szSharedSecret
, NULL
},
305 { _T("SNMPTimeout"), CT_LONG
, 0, 0, 0, 0, &g_snmpTimeout
, NULL
},
306 { _T("SNMPTrapListenAddress"), CT_STRING
, 0, 0, MAX_PATH
, 0, &g_szSNMPTrapListenAddress
, NULL
},
307 { _T("SNMPTrapPort"), CT_WORD
, 0, 0, 0, 0, &g_snmpTrapPort
, NULL
},
308 { _T("StartupDelay"), CT_LONG
, 0, 0, 0, 0, &g_dwStartupDelay
, NULL
},
309 { _T("SubAgent"), CT_STRING_LIST
, '\n', 0, 0, 0, &m_pszSubagentList
, NULL
},
310 { _T("SyslogListenPort"), CT_WORD
, 0, 0, 0, 0, &g_syslogListenPort
, NULL
},
311 { _T("SystemName"), CT_STRING
, 0, 0, MAX_OBJECT_NAME
, 0, g_systemName
, NULL
},
312 { _T("TimeOut"), CT_IGNORE
, 0, 0, 0, 0, NULL
, NULL
},
313 { _T("WaitForProcess"), CT_STRING
, 0, 0, MAX_PATH
, 0, s_processToWaitFor
, NULL
},
314 { _T("ZoneId"), CT_LONG
, 0, 0, 0, 0, &g_zoneUIN
, NULL
}, // for backward compatibility
315 { _T("ZoneUIN"), CT_LONG
, 0, 0, 0, 0, &g_zoneUIN
, NULL
},
316 { _T(""), CT_END_OF_LIST
, 0, 0, 0, 0, NULL
, NULL
}
322 static TCHAR m_szHelpText
[] =
323 _T("Usage: nxagentd [options]\n")
324 _T("Where valid options are:\n")
325 _T(" -c <file> : Use configuration file <file> (default ") AGENT_DEFAULT_CONFIG
_T(")\n")
326 _T(" -C : Load configuration file, dump resulting configuration, and exit\n")
327 _T(" -d : Run as daemon/service\n")
328 _T(" -D <level> : Set debug level (0..9)\n")
330 _T(" -e <name> : Windows event source name\n")
332 _T(" -f : Run in foreground\n")
334 _T(" -g <gid> : Change group ID to <gid> after start\n")
336 _T(" -G <name> : Use alternate global section <name> in configuration file\n")
337 _T(" -h : Display help and exit\n")
339 _T(" -H : Hide agent's window when in standalone mode\n")
340 _T(" -i : Installed Windows service must be interactive\n")
341 _T(" -I : Install Windows service\n")
343 _T(" -K : Shutdown all connected external sub-agents\n")
344 _T(" -M <addr> : Download config from management server <addr>\n")
346 _T(" -n <name> : Service name\n")
347 _T(" -N <name> : Service display name\n")
350 _T(" -p : Path to pid file (default: /var/run/nxagentd.pid)\n")
352 _T(" -P <text> : Set platform suffix to <text>\n")
353 _T(" -r <addr> : Register agent on management server <addr>\n")
355 _T(" -R : Remove Windows service\n")
356 _T(" -s : Start Windows servive\n")
357 _T(" -S : Stop Windows service\n")
360 _T(" -u <uid> : Chhange user ID to <uid> after start\n")
362 _T(" -v : Display version and exit\n")
366 * Server info: constructor
368 ServerInfo
::ServerInfo(const TCHAR
*name
, bool control
, bool master
)
371 m_name
= MBStringFromWideString(name
);
373 m_name
= strdup(name
);
376 char *p
= strchr(m_name
, '/');
381 m_address
= InetAddress
::resolveHostName(m_name
);
382 if (m_address
.isValid())
384 int bits
= strtol(p
, NULL
, 10);
385 if ((bits
>= 0) && (bits
<= ((m_address
.getFamily() == AF_INET
) ?
32 : 128)))
386 m_address
.setMaskBits(bits
);
388 m_redoResolve
= false;
392 m_address
= InetAddress
::resolveHostName(m_name
);
393 m_redoResolve
= true;
398 m_lastResolveTime
= time(NULL
);
399 m_mutex
= MutexCreate();
403 * Server info: destructor
405 ServerInfo
::~ServerInfo()
408 MutexDestroy(m_mutex
);
412 * Server info: resolve hostname if needed
414 void ServerInfo
::resolve()
416 time_t now
= time(NULL
);
417 time_t age
= now
- m_lastResolveTime
;
418 if ((age
>= 3600) || ((age
> 300) && !m_address
.isValid()))
420 m_address
= InetAddress
::resolveHostName(m_name
);
421 m_lastResolveTime
= now
;
426 * Server info: match address
428 bool ServerInfo
::match(const InetAddress
&addr
)
433 bool result
= m_address
.isValid() ? m_address
.contain(addr
) : false;
434 MutexUnlock(m_mutex
);
441 * Get our own console window handle (an alternative to Microsoft's GetConsoleWindow)
443 static HWND
GetConsoleHWND()
445 DWORD cpid
= GetCurrentProcessId();
449 hWnd
= FindWindowEx(NULL
, hWnd
, _T("ConsoleWindowClass"), NULL
);
454 GetWindowThreadProcessId(hWnd
, &wpid
);
463 * Get proc address and write log file
465 static FARPROC
GetProcAddressAndLog(HMODULE hModule
, LPCSTR procName
)
469 ptr
= GetProcAddress(hModule
, procName
);
470 if ((ptr
== NULL
) && (g_dwFlags
& AF_LOG_UNRESOLVED_SYMBOLS
))
471 nxlog_write(MSG_NO_FUNCTION
, EVENTLOG_WARNING_TYPE
, "s", procName
);
476 * Shutdown thread (created by H_RestartAgent)
478 static THREAD_RESULT THREAD_CALL
ShutdownThread(void *pArg
)
480 DebugPrintf(1, _T("Shutdown thread started"));
483 return THREAD_OK
; // Never reached
493 nxlog_debug(1, _T("RestartAgent() called"));
495 RestartExtSubagents();
497 TCHAR platformSuffixOption
[MAX_PSUFFIX_LENGTH
+ 16];
498 if (g_szPlatformSuffix
[0] != 0)
500 _sntprintf(platformSuffixOption
, MAX_PSUFFIX_LENGTH
+ 16, _T("-P \"%s\" "), g_szPlatformSuffix
);
504 platformSuffixOption
[0] = 0;
507 const TCHAR
*configSection
= g_config
->getAlias(_T("agent"));
508 TCHAR configSectionOption
[256];
509 if ((configSection
!= NULL
) && (*configSection
!= 0))
511 _sntprintf(configSectionOption
, 256, _T("-G %s "), configSection
);
515 configSectionOption
[0] = 0;
518 TCHAR szCmdLine
[4096];
520 _sntprintf(szCmdLine
, 4096, _T("\"%s\" -c \"%s\" -n \"%s\" -e \"%s\" %s%s%s%s%s-D %d %s%s-X %u"), s_executableName
,
521 g_szConfigFile
, g_windowsServiceName
, g_windowsEventSourceName
,
522 (g_dwFlags
& AF_DAEMON
) ?
_T("-d ") : _T(""),
523 (g_dwFlags
& AF_HIDE_WINDOW
) ?
_T("-H ") : _T(""),
524 (g_dwFlags
& AF_CENTRAL_CONFIG
) ?
_T("-M ") : _T(""),
525 (g_dwFlags
& AF_CENTRAL_CONFIG
) ? g_szConfigServer
: _T(""),
526 (g_dwFlags
& AF_CENTRAL_CONFIG
) ?
_T(" ") : _T(""),
527 s_debugLevel
, platformSuffixOption
, configSectionOption
,
528 (g_dwFlags
& AF_DAEMON
) ?
0 : GetCurrentProcessId());
529 DebugPrintf(1, _T("Restarting agent with command line '%s'"), szCmdLine
);
533 PROCESS_INFORMATION pi
;
535 // Fill in process startup info structure
536 memset(&si
, 0, sizeof(STARTUPINFO
));
537 si
.cb
= sizeof(STARTUPINFO
);
539 // Create new process
540 if (!CreateProcess(NULL
, szCmdLine
, NULL
, NULL
, FALSE
,
541 (g_dwFlags
& AF_DAEMON
) ?
(CREATE_NO_WINDOW
| DETACHED_PROCESS
) : (CREATE_NEW_CONSOLE
),
542 NULL
, NULL
, &si
, &pi
))
544 nxlog_write(MSG_CREATE_PROCESS_FAILED
, EVENTLOG_ERROR_TYPE
, "se", szCmdLine
, GetLastError());
545 dwResult
= ERR_EXEC_FAILED
;
550 CloseHandle(pi
.hThread
);
551 CloseHandle(pi
.hProcess
);
552 dwResult
= ERR_SUCCESS
;
554 if ((dwResult
== ERR_SUCCESS
) && (!(g_dwFlags
& AF_DAEMON
)))
556 if (g_dwFlags
& AF_HIDE_WINDOW
)
558 ConditionSet(s_shutdownCondition
);
562 ThreadCreate(ShutdownThread
, 0, NULL
);
567 _sntprintf(szCmdLine
, 4096, _T("\"%s\" -c \"%s\" %s%s%s%s-D %d %s%s-X %lu"), s_executableName
,
568 g_szConfigFile
, (g_dwFlags
& AF_DAEMON
) ?
_T("-d ") : _T(""),
569 (g_dwFlags
& AF_CENTRAL_CONFIG
) ?
_T("-M ") : _T(""),
570 (g_dwFlags
& AF_CENTRAL_CONFIG
) ? g_szConfigServer
: _T(""),
571 (g_dwFlags
& AF_CENTRAL_CONFIG
) ?
_T(" ") : _T(""),
572 (int)s_debugLevel
, platformSuffixOption
, configSectionOption
,
573 (unsigned long)s_pid
);
574 DebugPrintf(1, _T("Restarting agent with command line '%s'"), szCmdLine
);
575 return ExecuteCommand(szCmdLine
, NULL
, NULL
);
580 * Handler for Agent.Restart action
582 static LONG
H_RestartAgent(const TCHAR
*action
, StringList
*args
, const TCHAR
*data
, AbstractCommSession
*session
)
584 return RestartAgent();
588 * This function writes message from subagent to agent's log
590 static void WriteSubAgentMsg(int logLevel
, int debugLevel
, const TCHAR
*pszMsg
)
592 if (logLevel
== EVENTLOG_DEBUG_TYPE
)
594 if (debugLevel
<= (int)s_debugLevel
)
595 nxlog_write(MSG_DEBUG
, EVENTLOG_DEBUG_TYPE
, "s", pszMsg
);
599 nxlog_write(MSG_SUBAGENT_MSG
, logLevel
, "s", pszMsg
);
604 * Signal handler for UNIX platforms
608 static THREAD_RESULT THREAD_CALL
SignalHandler(void *pArg
)
611 sigemptyset(&signals
);
612 sigaddset(&signals
, SIGTERM
);
613 sigaddset(&signals
, SIGINT
);
614 sigaddset(&signals
, SIGSEGV
);
615 sigaddset(&signals
, SIGHUP
);
616 sigaddset(&signals
, SIGUSR1
);
617 sigaddset(&signals
, SIGUSR2
);
618 #if !defined(__sun) && !defined(_AIX) && !defined(__hpux)
619 sigaddset(&signals
, SIGPIPE
);
625 if (sigwait(&signals
, &nSignal
) == 0)
646 sigprocmask(SIG_UNBLOCK
, &signals
, NULL
);
653 * Load platform subagent
655 static void LoadPlatformSubagent()
658 LoadSubAgent(_T("WINNT.NSM"));
660 #if HAVE_SYS_UTSNAME_H && !defined(_STATIC_AGENT)
662 TCHAR szName
[MAX_PATH
];
665 if (uname(&un
) != -1)
667 // Convert system name to lowercase
668 for(i
= 0; un
.sysname
[i
] != 0; i
++)
669 un
.sysname
[i
] = tolower(un
.sysname
[i
]);
670 if (!strcmp(un
.sysname
, "hp-ux"))
671 strcpy(un
.sysname
, "hpux");
672 _sntprintf(szName
, MAX_PATH
, _T("%hs.nsm"), un
.sysname
);
673 LoadSubAgent(szName
);
680 * Send file to server (subagent API)
682 static bool SendFileToServer(void *session
, UINT32 requestId
, const TCHAR
*file
, long offset
, bool allowCompression
)
686 return ((CommSession
*)session
)->sendFile(requestId
, file
, offset
, allowCompression
);
692 static void ParseServerList(TCHAR
*serverList
, bool isControl
, bool isMaster
)
696 for(pItem
= pEnd
= serverList
; pEnd
!= NULL
&& *pItem
!= 0; pItem
= pEnd
+ 1)
698 pEnd
= _tcschr(pItem
, _T(','));
703 g_serverList
.add(new ServerInfo(pItem
, isControl
, isMaster
));
709 * Agent initialization
715 if (s_debugLevel
== (UINT32
)NXCONFIG_UNINITIALIZED_VALUE
)
719 if (!nxlog_open((g_dwFlags
& AF_USE_SYSLOG
) ? NXAGENTD_SYSLOG_NAME
: g_szLogFile
,
720 ((g_dwFlags
& AF_USE_SYSLOG
) ? NXLOG_USE_SYSLOG
: 0) |
721 ((g_dwFlags
& AF_BACKGROUND_LOG_WRITER
) ? NXLOG_BACKGROUND_WRITER
: 0) |
722 ((g_dwFlags
& AF_DAEMON
) ?
0 : NXLOG_PRINT_TO_STDOUT
),
725 0, NULL
, MSG_DEBUG
, MSG_DEBUG_TAG
, MSG_SUBAGENT_MSG
))
727 g_dwNumMessages
, g_szMessages
, MSG_DEBUG
, MSG_DEBUG_TAG
, MSG_SUBAGENT_MSG
))
730 //TODO: set flag that log have been opened with errors
732 g_failFlags
|= FAIL_OPEN_LOG
;
733 nxlog_open(NXAGENTD_SYSLOG_NAME
, NXLOG_USE_SYSLOG
|
734 ((g_dwFlags
& AF_BACKGROUND_LOG_WRITER
) ? NXLOG_BACKGROUND_WRITER
: 0) |
735 ((g_dwFlags
& AF_DAEMON
) ?
0 : NXLOG_PRINT_TO_STDOUT
),
738 0, NULL
, MSG_DEBUG
, MSG_DEBUG_TAG
, MSG_SUBAGENT_MSG
);
740 g_dwNumMessages
, g_szMessages
, MSG_DEBUG
, MSG_DEBUG_TAG
, MSG_SUBAGENT_MSG
);
742 _ftprintf(stderr
, _T("ERROR: Cannot open log file, logs will be written to syslog with debug level 1\n"));
747 if (!(g_dwFlags
& AF_USE_SYSLOG
))
749 if (!nxlog_set_rotation_policy((int)s_logRotationMode
, s_maxLogSize
, (int)s_logHistorySize
, s_dailyLogFileSuffix
))
750 if (!(g_dwFlags
& AF_DAEMON
))
751 _tprintf(_T("WARNING: cannot set log rotation policy; using default values\n"));
754 nxlog_write(MSG_AGENT_VERSION
, NXLOG_INFO
, "s", NETXMS_BUILD_TAG
);
755 nxlog_write(MSG_USE_CONFIG_D
, NXLOG_INFO
, "s", g_szConfigIncludeDir
);
756 nxlog_write(MSG_DEBUG_LEVEL
, NXLOG_INFO
, "d", s_debugLevel
);
758 int numTags
= 0, lvl
= 0;
759 TCHAR tagBuffer
[254], lvlBuffer
[2];
762 _tprintf(_T("Taglist: %s\n"), s_debugTags
);
763 TCHAR
**tagList
= SplitString(s_debugTags
, _T(','), &numTags
);
766 for(int i
= 0; i
< numTags
; i
++)
768 ptr
= ExtractWord(tagList
[i
], tagBuffer
);
769 ExtractWord(ptr
, lvlBuffer
);
770 lvl
= _tcstol(lvlBuffer
, NULL
, 0);
772 if(lvl
!= 0 && tagBuffer
!= NULL
)
773 nxlog_set_debug_level_tag(tagBuffer
, lvl
);
780 nxlog_set_debug_level(s_debugLevel
);
782 if (_tcscmp(g_masterAgent
, _T("not_set")))
784 g_dwFlags
|= AF_SUBAGENT_LOADER
;
785 DebugPrintf(1, _T("Switched to external subagent loader mode, master agent address is %s"), g_masterAgent
);
788 DebugPrintf(1, _T("Data directory: %s"), g_szDataDirectory
);
789 CreateFolder(g_szDataDirectory
);
791 DebugPrintf(1, _T("File store: %s"), g_szFileStore
);
792 CreateFolder(g_szFileStore
);
795 nxlog_debug(2, _T("Effective user ID %d"), (int)geteuid());
796 nxlog_debug(2, _T("Effective group ID %d"), (int)getegid());
799 // Initialize log parser policy folder
800 TCHAR tail
= g_szDataDirectory
[_tcslen(g_szDataDirectory
) - 1];
801 _sntprintf(g_szLogParserDirectory
, MAX_PATH
, _T("%s%s%s"), g_szDataDirectory
,
802 ((tail
!= '\\') && (tail
!= '/')) ? FS_PATH_SEPARATOR
: _T(""),
803 LOGPARSER_AP_FOLDER FS_PATH_SEPARATOR
);
804 nxlog_debug(6, _T("Log parser policy directory: %s"), g_szLogParserDirectory
);
805 CreateFolder(g_szLogParserDirectory
);
807 // Initialize certificate directory
808 _sntprintf(g_certificateDirectory
, MAX_PATH
, _T("%s%scertificates") FS_PATH_SEPARATOR
, g_szDataDirectory
,
809 ((tail
!= '\\') && (tail
!= '/')) ? FS_PATH_SEPARATOR
: _T(""));
810 nxlog_debug(6, _T("Certificate directory: %s"), g_certificateDirectory
);
811 CreateFolder(g_certificateDirectory
);
813 nxlog_debug(6, _T("Configuration policy directory: %s"), g_szConfigPolicyDir
);
817 int wrc
= WSAStartup(MAKEWORD(2, 2), &wsaData
);
820 nxlog_write(MSG_WSASTARTUP_FAILED
, NXLOG_ERROR
, "e", wrc
);
825 // Initialize API for subagents
826 s_subAgentsStopCondition
= ConditionCreate(TRUE
);
827 InitSubAgentAPI(WriteSubAgentMsg
, SendTrap
, SendTrap
, EnumerateSessions
, FindServerSession
,
828 SendFileToServer
, PushData
, GetLocalDatabaseHandle
, s_subAgentsStopCondition
, g_szDataDirectory
);
829 nxlog_debug(1, _T("Subagent API initialized"));
831 // Initialize cryptografy
832 if (!InitCryptoLib(s_enabledCiphers
))
834 nxlog_write(MSG_INIT_CRYPTO_FAILED
, EVENTLOG_ERROR_TYPE
, "e", WSAGetLastError());
838 // Initialize libssl - it is not used by core agent
839 // but may be needed by some subagents. Allowing first load of libssl by
840 // subagent via dlopen() may lead to undesired side effects
841 #ifdef _WITH_ENCRYPTION
843 SSL_load_error_strings();
846 DBInit(MSG_DB_LIBRARY
, MSG_SQL_ERROR
);
848 if (!OpenLocalDatabase())
850 nxlog_write(MSG_LOCAL_DB_OPEN_FAILED
, NXLOG_ERROR
, NULL
);
853 // Set system name to host name if not set in config
854 if (g_systemName
[0] == 0)
855 GetLocalHostName(g_systemName
, MAX_OBJECT_NAME
, false);
856 nxlog_debug(2, _T("Using system name \"%s\""), g_systemName
);
858 if (!(g_dwFlags
& AF_SUBAGENT_LOADER
))
860 g_commThreadPool
= ThreadPoolCreate(2, 32, _T("COMM"));
861 if (g_dwFlags
& AF_ENABLE_SNMP_PROXY
)
863 g_snmpProxyThreadPool
= ThreadPoolCreate(2, 128, _T("SNMPPROXY"));
867 // Initialize built-in parameters
868 if (!InitParameterList())
871 // Parse outgoing server connection (tunnel) list
872 if (s_serverConnectionList
!= NULL
)
873 ParseTunnelList(s_serverConnectionList
);
875 // Parse server lists
876 if (m_pszMasterServerList
!= NULL
)
877 ParseServerList(m_pszMasterServerList
, true, true);
878 if (m_pszControlServerList
!= NULL
)
879 ParseServerList(m_pszControlServerList
, true, false);
880 if (m_pszServerList
!= NULL
)
881 ParseServerList(m_pszServerList
, false, false);
883 // Add built-in actions
884 AddAction(_T("Agent.Restart"), AGENT_ACTION_SUBAGENT
, NULL
, H_RestartAgent
, _T("CORE"), _T("Restart agent"));
886 // Load platform subagents
888 InitStaticSubagents();
890 if (g_dwFlags
& AF_ENABLE_AUTOLOAD
)
892 LoadPlatformSubagent();
896 // Wait for external process if requested
897 if (s_processToWaitFor
[0] != 0)
899 DebugPrintf(1, _T("Waiting for process %s"), s_processToWaitFor
);
900 if (!WaitForProcess(s_processToWaitFor
))
901 nxlog_write(MSG_WAITFORPROCESS_FAILED
, EVENTLOG_ERROR_TYPE
, "s", s_processToWaitFor
);
904 // Load other subagents
905 if (m_pszSubagentList
!= NULL
)
907 for(pItem
= pEnd
= m_pszSubagentList
; pEnd
!= NULL
&& *pItem
!= 0; pItem
= pEnd
+ 1)
909 pEnd
= _tcschr(pItem
, _T('\n'));
915 free(m_pszSubagentList
);
919 if (m_pszActionList
!= NULL
)
921 for(pItem
= pEnd
= m_pszActionList
; pEnd
!= NULL
&& *pItem
!= 0; pItem
= pEnd
+ 1)
923 pEnd
= _tcschr(pItem
, _T('\n'));
927 if (!AddActionFromConfig(pItem
, FALSE
))
928 nxlog_write(MSG_ADD_ACTION_FAILED
, EVENTLOG_WARNING_TYPE
, "s", pItem
);
930 free(m_pszActionList
);
932 if (m_pszShellActionList
!= NULL
)
934 for(pItem
= pEnd
= m_pszShellActionList
; pEnd
!= NULL
&& *pItem
!= 0; pItem
= pEnd
+ 1)
936 pEnd
= _tcschr(pItem
, _T('\n'));
941 if (!AddActionFromConfig(pItem
, TRUE
))
942 nxlog_write(MSG_ADD_ACTION_FAILED
, EVENTLOG_WARNING_TYPE
, "s", pItem
);
944 free(m_pszShellActionList
);
947 // Parse external parameters list
948 if (s_externalParametersConfig
!= NULL
)
950 for(pItem
= pEnd
= s_externalParametersConfig
; pEnd
!= NULL
&& *pItem
!= 0; pItem
= pEnd
+ 1)
952 pEnd
= _tcschr(pItem
, _T('\n'));
956 if (!AddExternalParameter(pItem
, FALSE
, FALSE
))
957 nxlog_write(MSG_ADD_EXT_PARAM_FAILED
, EVENTLOG_WARNING_TYPE
, "s", pItem
);
959 free(s_externalParametersConfig
);
961 if (s_externalShellExecParametersConfig
!= NULL
)
963 for(pItem
= pEnd
= s_externalShellExecParametersConfig
; pEnd
!= NULL
&& *pItem
!= 0; pItem
= pEnd
+ 1)
965 pEnd
= _tcschr(pItem
, _T('\n'));
969 if (!AddExternalParameter(pItem
, TRUE
, FALSE
))
970 nxlog_write(MSG_ADD_EXT_PARAM_FAILED
, EVENTLOG_WARNING_TYPE
, "s", pItem
);
972 free(s_externalShellExecParametersConfig
);
975 // Parse external lists
976 if (s_externalListsConfig
!= NULL
)
978 for(pItem
= pEnd
= s_externalListsConfig
; pEnd
!= NULL
&& *pItem
!= 0; pItem
= pEnd
+ 1)
980 pEnd
= _tcschr(pItem
, _T('\n'));
984 if (!AddExternalParameter(pItem
, FALSE
, TRUE
))
985 nxlog_write(MSG_ADD_EXT_LIST_FAILED
, EVENTLOG_WARNING_TYPE
, "s", pItem
);
987 free(s_externalListsConfig
);
990 // Parse external tables
991 if (s_externalTablesConfig
!= NULL
)
993 for(pItem
= pEnd
= s_externalTablesConfig
; pEnd
!= NULL
&& *pItem
!= 0; pItem
= pEnd
+ 1)
995 pEnd
= _tcschr(pItem
, _T('\n'));
999 if (!AddExternalTable(pItem
, false))
1000 nxlog_write(MSG_ADD_EXT_TABLE_FAILED
, EVENTLOG_WARNING_TYPE
, "s", pItem
);
1002 free(s_externalTablesConfig
);
1005 // Parse external parameters providers list
1006 if (s_externalParameterProvidersConfig
!= NULL
)
1008 for(pItem
= pEnd
= s_externalParameterProvidersConfig
; pEnd
!= NULL
&& *pItem
!= 0; pItem
= pEnd
+ 1)
1010 pEnd
= _tcschr(pItem
, _T('\n'));
1014 if (!AddParametersProvider(pItem
))
1015 nxlog_write(MSG_ADD_PARAM_PROVIDER_FAILED
, EVENTLOG_WARNING_TYPE
, "s", pItem
);
1017 free(s_externalParameterProvidersConfig
);
1020 if (!(g_dwFlags
& AF_SUBAGENT_LOADER
))
1022 // Parse external subagents list
1023 if (!(g_dwFlags
& AF_SUBAGENT_LOADER
) && (s_externalSubAgentsList
!= NULL
))
1025 for(pItem
= pEnd
= s_externalSubAgentsList
; pEnd
!= NULL
&& *pItem
!= 0; pItem
= pEnd
+ 1)
1027 pEnd
= _tcschr(pItem
, _T('\n'));
1031 if (!AddExternalSubagent(pItem
))
1032 nxlog_write(MSG_ADD_EXTERNAL_SUBAGENT_FAILED
, EVENTLOG_WARNING_TYPE
, "s", pItem
);
1034 free(s_externalSubAgentsList
);
1037 // Additional external subagents implicitly defined by EXT:* config sections
1038 ObjectArray
<ConfigEntry
> *entries
= g_config
->getSubEntries(_T("/"), _T("EXT:*"));
1039 for(int i
= 0; i
< entries
->size(); i
++)
1041 const TCHAR
*name
= entries
->get(i
)->getName() + 4;
1042 if (!AddExternalSubagent(name
))
1043 nxlog_write(MSG_ADD_EXTERNAL_SUBAGENT_FAILED
, EVENTLOG_WARNING_TYPE
, "s", name
);
1047 // Parse application agents list
1048 if (!(g_dwFlags
& AF_SUBAGENT_LOADER
) && (s_appAgentsList
!= NULL
))
1050 for(pItem
= pEnd
= s_appAgentsList
; pEnd
!= NULL
&& *pItem
!= 0; pItem
= pEnd
+ 1)
1052 pEnd
= _tcschr(pItem
, _T('\n'));
1056 RegisterApplicationAgent(pItem
);
1058 free(s_appAgentsList
);
1064 // If StartupDelay is greater than zero, then wait
1065 if (g_dwStartupDelay
> 0)
1067 if (g_dwFlags
& AF_DAEMON
)
1069 ThreadSleep(g_dwStartupDelay
);
1075 _tprintf(_T("XXXXXX%*s]\rWAIT ["), g_dwStartupDelay
, _T(" "));
1077 for(i
= 0; i
< g_dwStartupDelay
; i
++)
1080 _puttc(_T('.'), stdout
);
1087 StartParamProvidersPoller();
1090 g_tmAgentStartTime
= time(NULL
);
1092 s_eventSenderThread
= ThreadCreateEx(TrapSender
, 0, NULL
);
1094 if (g_dwFlags
& AF_ENABLE_SNMP_TRAP_PROXY
)
1096 s_snmpTrapSenderThread
= ThreadCreateEx(SNMPTrapSender
, 0, NULL
);
1097 s_snmpTrapReceiverThread
= ThreadCreateEx(SNMPTrapReceiver
, 0, NULL
);
1100 if (g_dwFlags
& AF_ENABLE_SYSLOG_PROXY
)
1102 s_syslogSenderThread
= ThreadCreateEx(SyslogSender
, 0, NULL
);
1103 s_syslogReceiverThread
= ThreadCreateEx(SyslogReceiver
, 0, NULL
);
1106 if (g_dwFlags
& AF_SUBAGENT_LOADER
)
1108 s_masterAgentListenerThread
= ThreadCreateEx(MasterAgentListener
, 0, NULL
);
1112 // Start network listener and session watchdog
1113 StartLocalDataCollector();
1114 s_listenerThread
= ThreadCreateEx(ListenerThread
, 0, NULL
);
1115 s_sessionWatchdogThread
= ThreadCreateEx(SessionWatchdog
, 0, NULL
);
1116 StartPushConnector();
1117 StartStorageDiscoveryConnector();
1118 StartSessionAgentConnector();
1119 if (g_dwFlags
& AF_ENABLE_CONTROL_CONNECTOR
)
1121 StartControlConnector();
1124 if (g_dwFlags
& AF_REGISTER
)
1126 RegisterOnServer(g_szRegistrar
);
1129 s_tunnelManagerThread
= ThreadCreateEx(TunnelManager
, 0, NULL
);
1133 s_shutdownCondition
= ConditionCreate(TRUE
);
1137 // Start watchdog process
1138 if (!(g_dwFlags
& AF_SUBAGENT_LOADER
))
1140 if (g_dwFlags
& AF_ENABLE_WATCHDOG
)
1144 // Delete file used for upgrade if exists
1145 TCHAR upgradeFileName
[MAX_PATH
];
1146 ReadRegistryAsString(_T("upgrade.file"), upgradeFileName
, MAX_PATH
, _T(""));
1147 if(upgradeFileName
[0] != 0)
1149 _tremove(upgradeFileName
);
1150 DeleteRegistryEntry(_T("upgrade.file"));
1153 //Update policy inventory according to files that exist on file system
1154 UpdatePolicyInventory();
1164 DebugPrintf(2, _T("Shutdown() called"));
1165 if (g_dwFlags
& AF_ENABLE_WATCHDOG
)
1168 g_dwFlags
|= AF_SHUTDOWN
;
1169 ConditionSet(s_subAgentsStopCondition
);
1171 if (g_dwFlags
& AF_SUBAGENT_LOADER
)
1173 // TODO: shall we inform master agent listener about shutdown?
1174 //ThreadJoin(s_masterAgentListenerThread);
1178 ShutdownLocalDataCollector();
1179 ShutdownTrapSender();
1180 ThreadJoin(s_sessionWatchdogThread
);
1181 ThreadJoin(s_listenerThread
);
1182 ThreadJoin(s_tunnelManagerThread
);
1184 ThreadJoin(s_eventSenderThread
);
1185 if (g_dwFlags
& AF_ENABLE_SNMP_TRAP_PROXY
)
1187 ShutdownSNMPTrapSender();
1188 ThreadJoin(s_snmpTrapReceiverThread
);
1189 ThreadJoin(s_snmpTrapSenderThread
);
1191 if (g_dwFlags
& AF_ENABLE_SYSLOG_PROXY
)
1193 ShutdownSyslogSender();
1194 ThreadJoin(s_syslogReceiverThread
);
1195 ThreadJoin(s_syslogSenderThread
);
1198 DestroySessionList();
1199 MsgWaitQueue
::shutdown();
1201 if (g_dwFlags
& AF_ENABLE_SNMP_PROXY
)
1203 ThreadPoolDestroy(g_snmpProxyThreadPool
);
1205 ThreadPoolDestroy(g_commThreadPool
);
1207 UnloadAllSubAgents();
1208 CloseLocalDatabase();
1209 nxlog_write(MSG_AGENT_STOPPED
, EVENTLOG_INFORMATION_TYPE
, NULL
);
1214 // Notify main thread about shutdown
1216 ConditionSet(s_shutdownCondition
);
1220 #if !defined(_WIN32)
1221 _tremove(g_szPidFile
);
1230 nxlog_write(MSG_AGENT_STARTED
, NXLOG_INFO
, NULL
);
1232 if (g_dwFlags
& AF_DAEMON
)
1235 ConditionWait(s_shutdownCondition
, INFINITE
);
1237 StartMainLoop(SignalHandler
, NULL
);
1243 if (g_dwFlags
& AF_HIDE_WINDOW
)
1247 hWnd
= GetConsoleHWND();
1249 ShowWindow(hWnd
, SW_HIDE
);
1250 ConditionWait(s_shutdownCondition
, INFINITE
);
1255 _tprintf(_T("Agent running. Press ESC to shutdown.\n"));
1261 _tprintf(_T("Agent shutting down...\n"));
1265 _tprintf(_T("Agent running. Press Ctrl+C to shutdown.\n"));
1266 StartMainLoop(SignalHandler
, NULL
);
1267 _tprintf(_T("\nStopping agent...\n"));
1273 * Do necessary actions on agent restart
1275 static void DoRestartActions(UINT32 dwOldPID
)
1282 WaitForService(SERVICE_STOPPED
);
1283 StartAgentService();
1290 hProcess
= OpenProcess(SYNCHRONIZE
| PROCESS_TERMINATE
, FALSE
, dwOldPID
);
1291 if (hProcess
!= NULL
)
1293 if (WaitForSingleObject(hProcess
, 60000) == WAIT_TIMEOUT
)
1295 TerminateProcess(hProcess
, 0);
1297 CloseHandle(hProcess
);
1303 kill(dwOldPID
, SIGTERM
);
1304 for(i
= 0; i
< 30; i
++)
1307 if (kill(dwOldPID
, SIGCONT
) == -1)
1311 // Kill previous instance of agent if it's still running
1313 kill(dwOldPID
, SIGKILL
);
1318 * Create configuration file
1320 static int CreateConfig(const char *pszServer
, const char *pszLogFile
, const char *pszFileStore
,
1321 const char *configIncludeDir
, int iNumSubAgents
, char **ppszSubAgentList
)
1327 if (_taccess(g_szConfigFile
, 0) == 0)
1328 return 0; // File already exist, we shouldn't overwrite it
1330 fp
= _tfopen(g_szConfigFile
, _T("w"));
1333 currTime
= time(NULL
);
1334 _ftprintf(fp
, _T("#\n# NetXMS agent configuration file\n# Created by agent installer at %s#\n\n"),
1335 _tctime(&currTime
));
1336 _ftprintf(fp
, _T("MasterServers = %hs\nConfigIncludeDir = %hs\nLogFile = %hs\nFileStore = %hs\n"),
1337 pszServer
, configIncludeDir
, pszLogFile
, pszFileStore
);
1340 for(i
= 0; i
< iNumSubAgents
; i
++)
1342 if (!strnicmp(ppszSubAgentList
[i
], "EXT:", 4))
1344 extSubAgents
.add(ppszSubAgentList
[i
] + 4);
1348 _ftprintf(fp
, _T("SubAgent = %hs\n"), ppszSubAgentList
[i
]);
1352 for(i
= 0; i
< extSubAgents
.size(); i
++)
1354 char section
[MAX_PATH
];
1355 strncpy(section
, (const char *)extSubAgents
.get(i
), MAX_PATH
);
1356 char *eptr
= strrchr(section
, '.');
1360 _ftprintf(fp
, _T("\n[EXT:%hs]\n"), section
);
1361 _ftprintf(fp
, _T("SubAgent = %hs\n"), (const char *)extSubAgents
.get(i
));
1366 return (fp
!= NULL
) ?
0 : 2;
1372 static void InitConfig(const TCHAR
*configSection
)
1374 g_config
= new Config();
1375 g_config
->setTopLevelTag(_T("config"));
1376 g_config
->setAlias(_T("agent"), configSection
);
1378 // Set default data directory on Windows
1380 if (SHGetFolderPath(NULL
, CSIDL_LOCAL_APPDATA
, NULL
, SHGFP_TYPE_CURRENT
, g_szDataDirectory
) == S_OK
)
1382 _tcscat(g_szDataDirectory
, _T("\\nxagentd"));
1388 * Initiate shutdown of connected external subagents
1390 static void InitiateExtSubagentShutdown()
1393 msg
.setCode(CMD_SHUTDOWN
);
1394 if (SendControlMessage(&msg
))
1395 _tprintf(_T("Control message sent successfully to master agent\n"));
1397 _tprintf(_T("ERROR: Unable to send control message to master agent\n"));
1405 static int GetUserId(const char *name
)
1408 int id
= (int)strtol(name
, &eptr
, 10);
1413 struct passwd
*p
= getpwnam(name
);
1416 _tprintf(_T("Invalid user ID \"%hs\"\n"), name
);
1421 _tprintf(_T("Invalid user ID \"%hs\"\n"), name
);
1429 static int GetGroupId(const char *name
)
1432 int id
= (int)strtol(name
, &eptr
, 10);
1437 struct group
*g
= getgrnam(name
);
1440 _tprintf(_T("Invalid group ID \"%hs\"\n"), name
);
1445 _tprintf(_T("Invalid group ID \"%hs\"\n"), name
);
1453 * Update agent environment from config
1455 static void UpdateEnvironment()
1457 ObjectArray
<ConfigEntry
> *entrySet
= g_config
->getSubEntries(_T("/ENV"), _T("*"));
1458 if (entrySet
== NULL
)
1460 for(int i
= 0; i
< entrySet
->size(); i
++)
1462 ConfigEntry
*e
= entrySet
->get(i
);
1463 size_t len
= _tcslen(e
->getName()) + _tcslen(e
->getValue()) + 2;
1464 char *env
= (char *)malloc(len
);
1468 char *mbName
= MBStringFromWideString(e
->getName());
1469 char *mbValue
= MBStringFromWideString(e
->getValue());
1470 snprintf(env
, len
, "%s=%s", mbName
, mbValue
);
1474 sprintf(env
, "%s=%s", e
->getName(), e
->getValue());
1483 * Application entry point
1485 int main(int argc
, char *argv
[])
1487 int ch
, iExitCode
= 0, iAction
= ACTION_RUN_AGENT
;
1488 BOOL bRestart
= FALSE
;
1489 UINT32 dwOldPID
, dwMainPID
;
1491 TCHAR configSection
[MAX_DB_STRING
] = DEFAULT_CONFIG_SECTION
;
1493 TCHAR szModuleName
[MAX_PATH
];
1498 int uid
= 0, gid
= 0;
1501 InitNetXMSProcess(false);
1503 // Check for alternate config file location
1505 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
, _T("Software\\NetXMS\\Agent"), 0, KEY_QUERY_VALUE
, &hKey
) == ERROR_SUCCESS
)
1507 dwSize
= MAX_PATH
* sizeof(TCHAR
);
1508 RegQueryValueEx(hKey
, _T("ConfigFile"), NULL
, NULL
, (BYTE
*)g_szConfigFile
, &dwSize
);
1509 dwSize
= MAX_PATH
* sizeof(TCHAR
);
1510 RegQueryValueEx(hKey
, _T("ConfigIncludeDir"), NULL
, NULL
, (BYTE
*)g_szConfigIncludeDir
, &dwSize
);
1514 pszEnv
= _tgetenv(_T("NXAGENTD_CONFIG"));
1516 nx_strncpy(g_szConfigFile
, pszEnv
, MAX_PATH
);
1518 pszEnv
= _tgetenv(_T("NXAGENTD_CONFIG_D"));
1520 nx_strncpy(g_szConfigIncludeDir
, pszEnv
, MAX_PATH
);
1523 // Parse command line
1525 iAction
= ACTION_HELP
;
1527 while((ch
= getopt(argc
, argv
, VALID_OPTIONS
)) != -1)
1531 case 'c': // Configuration file
1533 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, optarg
, -1, g_szConfigFile
, MAX_PATH
);
1534 g_szConfigFile
[MAX_PATH
- 1] = 0;
1536 nx_strncpy(g_szConfigFile
, optarg
, MAX_PATH
);
1539 case 'C': // Configuration check only
1540 iAction
= ACTION_CHECK_CONFIG
;
1542 case 'd': // Run as daemon
1543 g_dwFlags
|= AF_DAEMON
;
1545 case 'D': // Turn on debug output
1546 s_debugLevel
= strtoul(optarg
, &eptr
, 0);
1547 if ((*eptr
!= 0) || (s_debugLevel
> 9))
1549 fprintf(stderr
, "Invalid debug level: %s\n", optarg
);
1554 case 'f': // Run in foreground
1555 g_dwFlags
&= ~AF_DAEMON
;
1558 case 'g': // set group ID
1559 gid
= GetGroupId(optarg
);
1564 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, optarg
, -1, configSection
, MAX_DB_STRING
);
1565 configSection
[MAX_DB_STRING
- 1] = 0;
1567 nx_strncpy(configSection
, optarg
, MAX_DB_STRING
);
1570 case 'h': // Display help and exit
1571 iAction
= ACTION_HELP
;
1574 case 'H': // Hide window
1575 g_dwFlags
|= AF_HIDE_WINDOW
;
1578 case 'K': // Shutdown external sub-agents
1579 iAction
= ACTION_SHUTDOWN_EXT_AGENTS
;
1582 case 'p': // PID file
1584 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, optarg
, -1, g_szPidFile
, MAX_PATH
);
1585 g_szPidFile
[MAX_PATH
- 1] = 0;
1587 nx_strncpy(g_szPidFile
, optarg
, MAX_PATH
);
1592 g_dwFlags
|= AF_CENTRAL_CONFIG
;
1594 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, optarg
, -1, g_szConfigServer
, MAX_DB_STRING
);
1595 g_szConfigServer
[MAX_DB_STRING
- 1] = 0;
1597 nx_strncpy(g_szConfigServer
, optarg
, MAX_DB_STRING
);
1601 g_dwFlags
|= AF_REGISTER
;
1603 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, optarg
, -1, g_szRegistrar
, MAX_DB_STRING
);
1604 g_szRegistrar
[MAX_DB_STRING
- 1] = 0;
1606 nx_strncpy(g_szRegistrar
, optarg
, MAX_DB_STRING
);
1609 case 'P': // Platform suffix
1611 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, optarg
, -1, g_szPlatformSuffix
, MAX_PSUFFIX_LENGTH
);
1612 g_szPlatformSuffix
[MAX_PSUFFIX_LENGTH
- 1] = 0;
1614 nx_strncpy(g_szPlatformSuffix
, optarg
, MAX_PSUFFIX_LENGTH
);
1618 case 'u': // set user ID
1619 uid
= GetUserId(optarg
);
1622 case 'v': // Print version and exit
1623 _tprintf(_T("NetXMS Core Agent Version ") NETXMS_VERSION_STRING
_T(" Build ") NETXMS_VERSION_BUILD_STRING
_T(" (") NETXMS_BUILD_TAG
_T(")") IS_UNICODE_BUILD_STRING
_T("\n"));
1624 iAction
= ACTION_NONE
;
1626 case 'W': // Watchdog process
1627 iAction
= ACTION_RUN_WATCHDOG
;
1628 dwMainPID
= strtoul(optarg
, NULL
, 10);
1630 case 'X': // Agent is being restarted
1632 dwOldPID
= strtoul(optarg
, NULL
, 10);
1634 case 'Z': // Create configuration file
1635 iAction
= ACTION_CREATE_CONFIG
;
1637 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, optarg
, -1, g_szConfigFile
, MAX_PATH
);
1638 g_szConfigFile
[MAX_PATH
- 1] = 0;
1640 nx_strncpy(g_szConfigFile
, optarg
, MAX_PATH
);
1645 g_dwFlags
|= AF_INTERACTIVE_SERVICE
;
1647 case 'I': // Install Windows service
1648 iAction
= ACTION_INSTALL_SERVICE
;
1650 case 'R': // Remove Windows service
1651 iAction
= ACTION_REMOVE_SERVICE
;
1653 case 's': // Start Windows service
1654 iAction
= ACTION_START_SERVICE
;
1656 case 'S': // Stop Windows service
1657 iAction
= ACTION_STOP_SERVICE
;
1659 case 'E': // Install Windows event source
1660 iAction
= ACTION_INSTALL_EVENT_SOURCE
;
1662 case 'U': // Remove Windows event source
1663 iAction
= ACTION_REMOVE_EVENT_SOURCE
;
1665 case 'e': // Event source name
1667 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, optarg
, -1, g_windowsEventSourceName
, MAX_PATH
);
1668 g_windowsEventSourceName
[MAX_PATH
- 1] = 0;
1670 nx_strncpy(g_windowsEventSourceName
, optarg
, MAX_PATH
);
1673 case 'n': // Service name
1675 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, optarg
, -1, g_windowsServiceName
, MAX_PATH
);
1676 g_windowsServiceName
[MAX_PATH
- 1] = 0;
1678 nx_strncpy(g_windowsServiceName
, optarg
, MAX_PATH
);
1681 case 'N': // Service display name
1683 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, optarg
, -1, g_windowsServiceDisplayName
, MAX_PATH
);
1684 g_windowsServiceDisplayName
[MAX_PATH
- 1] = 0;
1686 nx_strncpy(g_windowsServiceDisplayName
, optarg
, MAX_PATH
);
1691 iAction
= ACTION_HELP
;
1699 #if !defined(_WIN32)
1700 if (!_tcscmp(g_szConfigFile
, _T("{search}")))
1702 TCHAR path
[MAX_PATH
] = _T("");
1703 const TCHAR
*homeDir
= _tgetenv(_T("NETXMS_HOME"));
1704 if (homeDir
!= NULL
)
1706 _sntprintf(path
, MAX_PATH
, _T("%s/etc/nxagentd.conf"), homeDir
);
1708 if ((path
[0] != 0) && (_taccess(path
, 4) == 0))
1710 _tcscpy(g_szConfigFile
, path
);
1712 else if (_taccess(PREFIX
_T("/etc/nxagentd.conf"), 4) == 0)
1714 _tcscpy(g_szConfigFile
, PREFIX
_T("/etc/nxagentd.conf"));
1716 else if (_taccess(_T("/Database/etc/nxagentd.conf"), 4) == 0) // for ZeroShell
1718 _tcscpy(g_szConfigFile
, _T("/Database/etc/nxagentd.conf"));
1720 else if (_taccess(_T("/usr/etc/nxagentd.conf"), 4) == 0)
1722 _tcscpy(g_szConfigFile
, _T("/usr/etc/nxagentd.conf"));
1726 _tcscpy(g_szConfigFile
, _T("/etc/nxagentd.conf"));
1729 if (!_tcscmp(g_szConfigIncludeDir
, _T("{search}")))
1731 TCHAR path
[MAX_PATH
] = _T("");
1732 const TCHAR
*homeDir
= _tgetenv(_T("NETXMS_HOME"));
1733 if (homeDir
!= NULL
)
1735 _sntprintf(path
, MAX_PATH
, _T("%s/etc/nxagentd.conf.d"), homeDir
);
1737 if ((path
[0] != 0) && (_taccess(path
, 4) == 0))
1739 _tcscpy(g_szConfigIncludeDir
, path
);
1741 else if (_taccess(PREFIX
_T("/etc/nxagentd.conf.d"), 4) == 0)
1743 _tcscpy(g_szConfigIncludeDir
, PREFIX
_T("/etc/nxagentd.conf.d"));
1745 else if (_taccess(_T("/Database/etc/nxagentd.conf.d"), 4) == 0)
1747 _tcscpy(g_szConfigIncludeDir
, _T("/Database/etc/nxagentd.conf.d"));
1749 else if (_taccess(_T("/usr/etc/nxagentd.conf.d"), 4) == 0)
1751 _tcscpy(g_szConfigIncludeDir
, _T("/usr/etc/nxagentd.conf.d"));
1755 _tcscpy(g_szConfigIncludeDir
, _T("/etc/nxagentd.conf.d"));
1759 if (!_tcscmp(g_szConfigFile
, _T("{search}")))
1761 TCHAR path
[MAX_PATH
];
1762 GetNetXMSDirectory(nxDirEtc
, path
);
1763 _tcscat(path
, _T("\\nxagentd.conf"));
1764 if (_taccess(path
, 4) == 0)
1766 _tcscpy(g_szConfigFile
, path
);
1770 _tcscpy(g_szConfigFile
, _T("C:\\nxagentd.conf"));
1773 if (!_tcscmp(g_szConfigIncludeDir
, _T("{search}")))
1775 TCHAR path
[MAX_PATH
];
1776 GetNetXMSDirectory(nxDirEtc
, path
);
1777 _tcscat(path
, _T("\\nxagentd.conf.d"));
1778 if (_taccess(path
, 4) == 0)
1780 _tcscpy(g_szConfigIncludeDir
, path
);
1784 _tcscpy(g_szConfigIncludeDir
, _T("C:\\nxagentd.conf.d"));
1789 if (!_tcscmp(g_szDataDirectory
, _T("{default}")))
1791 GetNetXMSDirectory(nxDirData
, g_szDataDirectory
);
1794 // Initialize config policy folder and load policy based configs
1795 nx_strncpy(g_szConfigPolicyDir
, g_szDataDirectory
, MAX_PATH
- 16);
1796 if (g_szConfigPolicyDir
[_tcslen(g_szConfigPolicyDir
) - 1] != FS_PATH_SEPARATOR_CHAR
)
1797 _tcscat(g_szConfigPolicyDir
, FS_PATH_SEPARATOR
);
1798 _tcscat(g_szConfigPolicyDir
, CONFIG_AP_FOLDER FS_PATH_SEPARATOR
);
1799 CreateFolder(g_szConfigPolicyDir
);
1802 DoRestartActions(dwOldPID
);
1804 InitConfig(configSection
);
1806 // Do requested action
1809 case ACTION_RUN_AGENT
:
1810 // Set default value for session idle timeout based on
1811 // connect() timeout, if possible
1812 #if HAVE_SYSCTLBYNAME && !defined(_IPSO)
1817 nSize
= sizeof(nVal
);
1818 if (sysctlbyname("net.inet.tcp.keepinit", &nVal
, &nSize
, NULL
, 0) == 0)
1820 g_dwIdleTimeout
= nVal
/ 1000 + 15;
1825 if (g_dwFlags
& AF_CENTRAL_CONFIG
)
1827 if (s_debugLevel
> 0)
1828 _tprintf(_T("Downloading configuration from %s...\n"), g_szConfigServer
);
1829 if (DownloadConfig(g_szConfigServer
))
1831 if (s_debugLevel
> 0)
1832 _tprintf(_T("Configuration downloaded successfully\n"));
1836 if (s_debugLevel
> 0)
1837 _tprintf(_T("Configuration download failed\n"));
1841 if (g_config
->loadConfig(g_szConfigFile
, DEFAULT_CONFIG_SECTION
))
1843 const TCHAR
*dir
= g_config
->getValue(_T("/%agent/ConfigIncludeDir"));
1845 nx_strncpy(g_szConfigIncludeDir
, dir
, MAX_PATH
);
1846 g_config
->loadConfigDirectory(g_szConfigIncludeDir
, DEFAULT_CONFIG_SECTION
);
1848 g_config
->loadConfigDirectory(g_szConfigPolicyDir
, DEFAULT_CONFIG_SECTION
);
1850 // Check if master section starts with EXT:
1851 // If yes, switch to external subagent mode
1852 if (!_tcsnicmp(configSection
, _T("EXT:"), 4))
1854 nx_strncpy(g_masterAgent
, &configSection
[4], MAX_PATH
);
1857 if (g_config
->parseTemplate(configSection
, m_cfgTemplate
))
1859 _tprintf(_T("Taglist main: %s\n"), s_debugTags
);
1860 DecryptPassword(_T("netxms"), g_szSharedSecret
, g_szSharedSecret
, MAX_SECRET_LENGTH
);
1862 // try to guess executable path
1864 GetModuleFileName(GetModuleHandle(NULL
), s_executableName
, MAX_PATH
);
1867 char __buffer
[PATH_MAX
];
1869 #define __buffer s_executableName
1871 if (realpath(argv
[0], __buffer
) == NULL
)
1874 TCHAR
*path
= _tgetenv(_T("NETXMS_HOME"));
1877 nx_strncpy(s_executableName
, path
, sizeof(s_executableName
) / sizeof(s_executableName
[0]));
1881 nx_strncpy(s_executableName
, PREFIX
, sizeof(s_executableName
) / sizeof(s_executableName
[0]));
1883 _tcsncat(s_executableName
, _T("/bin/nxagentd"), sizeof(s_executableName
) / sizeof(s_executableName
[0]));
1888 int len
= strlen(__buffer
);
1889 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, __buffer
, len
, s_executableName
, MAX_PATH
);
1894 // Set exception handler
1896 if (g_dwFlags
& AF_CATCH_EXCEPTIONS
)
1897 SetExceptionHandler(SEHServiceExceptionHandler
, SEHServiceExceptionDataWriter
, s_dumpDir
,
1898 _T("nxagentd"), MSG_EXCEPTION
, g_dwFlags
& AF_WRITE_FULL_DUMP
, !(g_dwFlags
& AF_DAEMON
));
1901 if ((!_tcsicmp(g_szLogFile
, _T("{syslog}"))) ||
1902 (!_tcsicmp(g_szLogFile
, _T("{eventlog}"))))
1903 g_dwFlags
|= AF_USE_SYSLOG
;
1906 if (g_dwFlags
& AF_DAEMON
)
1918 ConsolePrintf(_T("Agent initialization failed\n"));
1924 if (g_dwFlags
& AF_DAEMON
)
1926 if (daemon(0, 0) == -1)
1928 perror("Unable to setup itself as a daemon");
1937 const TCHAR
*v
= g_config
->getValue(_T("/%agent/GroupId"));
1942 WideCharToMultiByte(CP_ACP
, WC_DEFAULTCHAR
| WC_COMPOSITECHECK
, v
, -1, vmb
, 64, NULL
, NULL
);
1944 gid
= GetGroupId(vmb
);
1946 gid
= GetGroupId(v
);
1952 const TCHAR
*v
= g_config
->getValue(_T("/%agent/UserId"));
1957 WideCharToMultiByte(CP_ACP
, WC_DEFAULTCHAR
| WC_COMPOSITECHECK
, v
, -1, vmb
, 64, NULL
, NULL
);
1959 uid
= GetUserId(vmb
);
1968 if (setgid(gid
) != 0)
1969 _tprintf(_T("setgid(%d) call failed (%s)\n"), gid
, _tcserror(errno
));
1973 if (setuid(uid
) != 0)
1974 _tprintf(_T("setuid(%d) call failed (%s)\n"), uid
, _tcserror(errno
));
1978 UpdateEnvironment();
1986 fp
= _tfopen(g_szPidFile
, _T("w"));
1989 _ftprintf(fp
, _T("%d"), s_pid
);
1997 ConsolePrintf(_T("Agent initialization failed\n"));
2005 if (s_shutdownCondition
!= INVALID_CONDITION_HANDLE
)
2006 ConditionDestroy(s_shutdownCondition
);
2009 LIBNETXMS_EXCEPTION_HANDLER
2014 ConsolePrintf(_T("Error parsing configuration file\n"));
2020 ConsolePrintf(_T("Error loading configuration file\n"));
2024 case ACTION_CHECK_CONFIG
:
2026 bool validConfig
= g_config
->loadConfig(g_szConfigFile
, DEFAULT_CONFIG_SECTION
, false);
2029 const TCHAR
*dir
= g_config
->getValue(_T("/%agent/ConfigIncludeDir"));
2032 validConfig
= g_config
->loadConfigDirectory(dir
, DEFAULT_CONFIG_SECTION
, false);
2035 ConsolePrintf(_T("Error reading additional configuration files from \"%s\"\n"), dir
);
2042 validConfig
= g_config
->loadConfigDirectory(g_szConfigPolicyDir
, DEFAULT_CONFIG_SECTION
);
2045 ConsolePrintf(_T("Error reading additional configuration files from \"%s\"\n"), g_szConfigPolicyDir
);
2051 g_config
->print(stdout
);
2052 validConfig
= g_config
->parseTemplate(configSection
, m_cfgTemplate
);
2057 ConsolePrintf(_T("Configuration file check failed\n"));
2062 case ACTION_RUN_WATCHDOG
:
2063 iExitCode
= WatchdogMain(dwMainPID
);
2065 case ACTION_CREATE_CONFIG
:
2066 iExitCode
= CreateConfig(CHECK_NULL_A(argv
[optind
]), CHECK_NULL_A(argv
[optind
+ 1]),
2067 CHECK_NULL_A(argv
[optind
+ 2]), CHECK_NULL_A(argv
[optind
+ 3]),
2068 argc
- optind
- 4, &argv
[optind
+ 4]);
2070 case ACTION_SHUTDOWN_EXT_AGENTS
:
2071 InitiateExtSubagentShutdown();
2075 case ACTION_INSTALL_SERVICE
:
2076 GetModuleFileName(GetModuleHandle(NULL
), szModuleName
, MAX_PATH
);
2077 InstallService(szModuleName
, g_szConfigFile
, s_debugLevel
);
2079 case ACTION_REMOVE_SERVICE
:
2082 case ACTION_INSTALL_EVENT_SOURCE
:
2083 GetModuleFileName(GetModuleHandle(NULL
), szModuleName
, MAX_PATH
);
2084 InstallEventSource(szModuleName
);
2086 case ACTION_REMOVE_EVENT_SOURCE
:
2087 RemoveEventSource();
2089 case ACTION_START_SERVICE
:
2090 StartAgentService();
2092 case ACTION_STOP_SERVICE
:
2097 _fputts(m_szHelpText
, stdout
);