summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNguyen Dinh Thi <Thi.NguyenDinh@vn.bosch.com>2018-11-29 16:30:32 +0100
committerSaya Sugiura <39760799+ssugiura@users.noreply.github.com>2020-07-08 16:01:00 +0900
commitc78d08d63f47ec2baa08c20f3068adbe8c3cc0ca (patch)
tree5485f250f358e3b875f9a33d4846fe40dbf9b47b
parent6b1781cb5ef5d6586dbe5c06bd973a0957c91813 (diff)
downloadDLT-daemon-c78d08d63f47ec2baa08c20f3068adbe8c3cc0ca.tar.gz
slog2 adapter on QNX
dlt-qnx-system can be used to send syslog on QNX to dlt-daemon using slog2 API. It was be built with setting cmake option WITH_DLT_QNX_SYSTEM to ON. Add markdown manual page for dlt-qnx-system Signed-off-by: Nguyen Dinh Thi (RBVH/ENG2) <Thi.NguyenDinh@vn.bosch.com> Signed-off-by: Le Hoang Ngoc Quynh <Quynh.LeHoangNgoc@vn.bosch.com> Signed-off-by: Sebastian Unger <sunger@de.adit-jv.com> Signed-off-by: Bui Nguyen Quoc Thanh <Thanh.BuiNguyenQuoc@vn.bosch.com> Signed-off-by: Saya Sugiura <ssugiura@jp.adit-jv.com> Signed-off-by: Felix Herrmann <fherrmann@de.adit-jv.com>
-rw-r--r--CMakeLists.txt5
-rw-r--r--README.md1
-rw-r--r--doc/dlt-qnx-system.md102
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/dlt-qnx-system/CMakeLists.txt33
-rw-r--r--src/dlt-qnx-system/dlt-qnx-slogger2-adapter.cpp251
-rw-r--r--src/dlt-qnx-system/dlt-qnx-system.c433
-rw-r--r--src/dlt-qnx-system/dlt-qnx-system.conf25
-rw-r--r--src/dlt-qnx-system/dlt-qnx-system.h109
-rw-r--r--src/dlt-qnx-system/dlt-slog2ctxt.json14
10 files changed, 977 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 710cb15..81fe9ca 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -63,6 +63,7 @@ option(WITH_DLT_SYSTEM "Set to ON to build src/system binaries"
option(WITH_DLT_DBUS "Set to ON to build src/dbus binaries" OFF)
option(WITH_DLT_TESTS "Set to ON to build src/test binaries" ON)
option(WITH_DLT_UNIT_TESTS "Set to ON to build gtest framework and tests/binaries" OFF)
+option(WITH_DLT_QNX_SYSTEM "Set to ON to build QNX system binary dlt-qnx-system" OFF)
set(DLT_IPC "FIFO" CACHE STRING "UNIX_SOCKET,FIFO")
set(DLT_USER "genivi" CACHE STRING "Set user for process not run as root")
@@ -135,6 +136,9 @@ if(WITH_DLT_USE_IPv6)
add_definitions(-DDLT_USE_IPv6)
endif()
+if(WITH_DLT_QNX_SYSTEM AND NOT "${CMAKE_C_COMPILER}" MATCHES "nto-qnx")
+ message(FATAL_ERROR "Can only compile for QNX with a QNX compiler.")
+endif()
if(WITH_GPROF)
add_compile_options(-pg)
@@ -271,6 +275,7 @@ message(STATUS "CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}")
message(STATUS "WITH_DLT_LOGSTORAGE_CTRL_UDEV = ${WITH_DLT_LOGSTORAGE_CTRL_UDEV}")
message(STATUS "DLT_IPC = ${DLT_IPC}(Path: ${DLT_USER_IPC_PATH})")
message(STATUS "WITH_UDP_CONNECTION = ${WITH_UDP_CONNECTION}")
+message(STATUS "WITH_DLT_QNX_SYSTEM = ${WITH_DLT_QNX_SYSTEM})")
message(STATUS "Change a value with: cmake -D<Variable>=<Value>")
message(STATUS "-------------------------------------------------------------------------------")
message(STATUS)
diff --git a/README.md b/README.md
index 384ae5c..e70f787 100644
--- a/README.md
+++ b/README.md
@@ -164,6 +164,7 @@ make doc
- [dlt-passive-node-ctrl(1)](doc/dlt-passive-node-ctrl.1.md)
- [dlt-adaptor-stdin(1)](doc/dlt-adaptor-stdin.1.md)
- [dlt-adaptor-udp(1)](doc/dlt-adaptor-udp.1.md)
+- [dlt-qnx-system(1)](doc/dlt-qnx-system.md)
The man pages are generated with *pandoc*.
diff --git a/doc/dlt-qnx-system.md b/doc/dlt-qnx-system.md
new file mode 100644
index 0000000..ffda347
--- /dev/null
+++ b/doc/dlt-qnx-system.md
@@ -0,0 +1,102 @@
+# dlt-qnx-system
+
+QNX specific logging features of dlt are managed by the ```dlt-qnx-system``` process.
+It currently contains the message forwarder from slogger2 to DLT.
+
+The application listens to the system logs on QNX (slogger2) and sends them to
+DLT. The prerequisite is that dlt-daemon is already started and running.
+dlt-qnx-system loads by default the configuration file ```/etc/dlt-qnx-system.conf```.
+
+> In order to catch all logs via slog2, the syslog needs to forward to slogger2 in [syslog.conf](http://www.qnx.com/developers/docs/7.0.0/index.html#com.qnx.doc.neutrino.utilities/topic/s/syslog.conf.html).
+
+To change the log level, use application ID and context ID set in configuration
+file. ```DLT_INITIAL_LOG_LEVEL``` can be set on startup phase, or control
+message can be sent from DLT client (e.g. dlt-control, DLT Viewer) at runtime.
+Refer to [dlt_for_developers.md](dlt_for_developers.md) for more detail.
+
+
+## Usage
+
+```bash
+dlt-qnx-system [-h] [-d] [-c FILENAME]
+```
+
+-h
+
+: Display a short help text.
+
+-d
+
+: Daemonize. Detach from Terminal and run in background.
+
+-c
+
+: Load an alternative configuration file. By default the configuration file
+ */etc/dlt-qnx-system.conf* is loaded.
+
+
+Non zero is returned in case of failure.
+
+
+## Configuration
+
+By default, the configuration is loaded from */etc/dlt-qnx-system.conf*. It
+contains a few basic options:
+
+- *ApplicationId*: this QNX system log forwarder will have this application ID
+ and appear on DLT client. Default value is *QSYM*.
+- *ApplicationContextID*: the context ID of the above application to appear on
+ DLT client. Default value is *QSYC*.
+- *QnxSlogger2Enable*: when the value is 1 (by default), the QNX slogger2
+ adapter which sends slogger2 to DLT will be started. Otherwise if the value
+ if 0, it won't be started.
+- *QnxSlogger2ContextId*: this will set the context ID of the QNX slogger2
+ adapter. Default value is *QSLA*.
+- *QnxSlogger2UseOriginalTimestamp*: when the value is 1 (by default), slogger2
+ event timestamps will be used as DLT timestamps.
+
+
+
+## Slogger2 adapter
+
+The slogger2 adapter that can be enabled in dlt-qnx-system attaches to slogger2 and converts the messages to dlt messages.
+
+
+### Log level mapping
+
+As the severity levels on QNX system log are different from DLT Log Level, the below table shows how they're converted from the former to the latter.
+
+
+| QNX System Log Level | DLT Log Level |
+|----------------------|--------------------|
+| SLOG2\_SHUTDOWN | DLT\_LOG\_FATAL |
+| SLOG2\_CRITICAL | DLT\_LOG\_FATAL |
+| SLOG2\_ERROR | DLT\_LOG\_ERROR |
+| SLOG2\_WARNING | DLT\_LOG\_WARN |
+| SLOG2\_NOTICE | DLT\_LOG\_INFO |
+| SLOG2\_INFO | DLT\_LOG\_INFO |
+| SLOG2\_DEBUG1 | DLT\_LOG\_DEBUG |
+| SLOG2\_DEBUG2 | DLT\_LOG\_VERBOSE |
+
+
+### Context Mapping
+
+The json file dlt-slog2ctxt.json can be used to map slogger names to dlt-contexts.
+
+#### Example
+
+Here is an example that sets a mapping from the "dumper" process to the DLT Context "DUMP", and the QNX Hypervisor to "QVM".
+The description field is in the registration with libdlt.
+
+```python
+{
+ "DUMP": {
+ "name": "dumper",
+ "description": "Writes core dump files to disk"
+ },
+ "SYSL": {
+ "name": "syslogd",
+ "description": ""
+ }
+}
+```
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4037ef9..e4ff133 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -48,3 +48,7 @@ endif( WITH_DLT_COREDUMPHANDLER )
if( WITH_DLT_KPI )
add_subdirectory( kpi )
endif( WITH_DLT_KPI )
+
+if( WITH_DLT_QNX_SYSTEM )
+ add_subdirectory( dlt-qnx-system )
+endif( WITH_DLT_QNX_SYSTEM )
diff --git a/src/dlt-qnx-system/CMakeLists.txt b/src/dlt-qnx-system/CMakeLists.txt
new file mode 100644
index 0000000..9a9db46
--- /dev/null
+++ b/src/dlt-qnx-system/CMakeLists.txt
@@ -0,0 +1,33 @@
+#######
+# @licence make begin@
+# SPDX license identifier: MPL-2.0
+#
+# Copyright (C) 2018 Advanced Driver Information Technology.
+#
+# This file is part of GENIVI Project DLT - Diagnostic Log and Trace.
+#
+# This Source Code Form is subject to the terms of the
+# Mozilla Public License (MPL), v. 2.0.
+# If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# For further information see http://www.genivi.org/.
+# @licence end@
+#######
+
+if(NOT WITH_DLT_CXX11_EXT)
+ message(FATAL_ERROR "DLT_QNX_SYSTEM needs the C++ features of dlt, please enable the WITH_DLT_CXX11_EXT option.")
+endif()
+
+set(dlt-qnx-system_SRCS dlt-qnx-system.c dlt-qnx-slogger2-adapter.cpp)
+add_executable(dlt-qnx-system ${dlt-qnx-system_SRCS})
+
+target_link_libraries(dlt-qnx-system dlt slog2parse json)
+
+install(TARGETS dlt-qnx-system
+ RUNTIME DESTINATION bin
+ COMPONENT base)
+
+install(FILES dlt-qnx-system.conf dlt-slog2ctxt.json
+ DESTINATION ${CONFIGURATION_FILES_DIR}
+ COMPONENT base)
diff --git a/src/dlt-qnx-system/dlt-qnx-slogger2-adapter.cpp b/src/dlt-qnx-system/dlt-qnx-slogger2-adapter.cpp
new file mode 100644
index 0000000..5ebfc0c
--- /dev/null
+++ b/src/dlt-qnx-system/dlt-qnx-slogger2-adapter.cpp
@@ -0,0 +1,251 @@
+/**
+ * Copyright (C) 2018-2020 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * DLT QNX system functionality source file.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Nguyen Dinh Thi <Thi.NguyenDinh@vn.bosch.com> ADIT 2018
+ * \author Felix Herrmann <fherrmann@de.adit-jv.com> ADIT 2020
+ *
+ * \file: dlt-qnx-slogger2-adapter.cpp
+ * For further information see http://www.genivi.org/.
+ */
+#include <cerrno>
+#include <cstring>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <unordered_map>
+
+#include <pthread.h>
+#include <sys/slog2.h>
+#include <sys/json.h>
+#include <slog2_parse.h>
+
+#include "dlt-qnx-system.h"
+#include "dlt_cpp_extension.hpp"
+
+/* Teach dlt about json_decoder_error_t */
+template<>
+inline int32_t logToDlt(DltContextData &log, const json_decoder_error_t &value)
+{
+ return logToDlt(log, static_cast<int>(value));
+}
+
+extern DltContext dltQnxSystem;
+
+static DltContext dltQnxSlogger2Context;
+
+extern DltQnxSystemThreads g_threads;
+static std::unordered_map<std::string, DltContext*> g_slog2file;
+
+static void dlt_context_map_read(const char *json_filename)
+{
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_VERBOSE,
+ "Loading Slog2Ctxt Map from json file: ", json_filename);
+
+ auto dec = json_decoder_create();
+ if (json_decoder_parse_file(dec, json_filename) != JSON_DECODER_OK) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_ERROR,
+ "Could not load Slog2Ctxt Map from json file: ", json_filename);
+ return;
+ }
+
+ const char *ctxtID, *name, *description;
+
+ /* go to first element in dlt-slog2ctxt.json e.g. "ADIO" */
+ auto ret = json_decoder_push_object(dec, nullptr, false);
+ while (ret == JSON_DECODER_OK) {
+ ctxtID = json_decoder_name(dec);
+
+ /* go into the element e.g. { name: "", description: "" } */
+ ret = json_decoder_push_object(dec, nullptr, false);
+ if (ret != JSON_DECODER_OK) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_WARN, __func__,
+ ": json parser error while descending into context dict. ret=", ret);
+ break;
+ }
+
+ ret = json_decoder_get_string(dec, "name", &name, false);
+ if (ret != JSON_DECODER_OK) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_WARN, __func__,
+ ": json parser error while retrieving 'name' element of ", ctxtID, ". ret=", ret);
+ break;
+ }
+
+ ret = json_decoder_get_string(dec, "description", &description, false);
+ if (ret != JSON_DECODER_OK) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_WARN, __func__,
+ ": json parser error while retrieving 'description' element of ", ctxtID, ". ret=", ret);
+ break;
+ }
+
+ auto ctxt = new DltContext;
+ g_slog2file.emplace(name, ctxt);
+
+ auto search = g_slog2file.find(name);
+ if (search == g_slog2file.end()) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_INFO,
+ "Could not emplace slog2ctxt map key: ", name);
+ } else {
+ dlt_register_context(ctxt, ctxtID, description);
+ }
+
+ ret = json_decoder_pop(dec);
+ }
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_DEBUG,
+ "Added ", g_slog2file.size(), " elements into the mapping table.");
+}
+
+/**
+ * Map the slog2 logfile name to a dlt context
+ * e.g. i2c_service.2948409 -> Context with id "I2CS"
+ */
+static DltContext *dlt_context_from_slog2file(const char *file_name) {
+ auto d = strchr(file_name, '.');
+
+ if (d == nullptr)
+ return &dltQnxSlogger2Context;
+
+ auto name = std::string(file_name).substr(0, d - file_name);
+
+ auto search = g_slog2file.find(name);
+ if (search == g_slog2file.end()) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_VERBOSE,
+ "slog2 filename not found in mapping: ", name.c_str());
+ return &dltQnxSlogger2Context;
+ } else {
+ return search->second;
+ }
+}
+
+/**
+ * Function which is invoked by slog2_parse_all()
+ * See slog2_parse_all api docs on qnx.com for details
+ */
+static int sloggerinfo_callback(slog2_packet_info_t *info, void *payload, void *param)
+{
+ DltQnxSystemConfiguration* conf = (DltQnxSystemConfiguration*) param;
+
+ if (param == NULL)
+ return -1;
+
+ DltLogLevelType loglevel;
+ switch (info->severity)
+ {
+ case SLOG2_SHUTDOWN:
+ case SLOG2_CRITICAL:
+ loglevel = DLT_LOG_FATAL;
+ break;
+ case SLOG2_ERROR:
+ loglevel = DLT_LOG_ERROR;
+ break;
+ case SLOG2_WARNING:
+ loglevel = DLT_LOG_WARN;
+ break;
+ case SLOG2_NOTICE:
+ case SLOG2_INFO:
+ loglevel = DLT_LOG_INFO;
+ break;
+ case SLOG2_DEBUG1:
+ loglevel = DLT_LOG_DEBUG;
+ break;
+ case SLOG2_DEBUG2:
+ loglevel = DLT_LOG_VERBOSE;
+ break;
+ default:
+ loglevel = DLT_LOG_INFO;
+ break;
+ }
+
+ DltContextData log_local; /* Used in DLT_* macros, do not rename */
+ DltContext *ctxt = dlt_context_from_slog2file(info->file_name);
+
+ int ret;
+ ret = dlt_user_log_write_start(ctxt, &log_local, loglevel);
+
+ /* OK means loglevel under threshold */
+ if (ret == DLT_RETURN_OK) {
+ return 0;
+ }
+
+ if (ret != DLT_RETURN_TRUE) {
+ fprintf(stderr, "%s: could not log to DLT status=%d\n", __func__, ret);
+ return -1;
+ }
+
+ if (conf->qnxslogger2.useOriginalTimestamp == 1) {
+ /* convert from ns to .1 ms */
+ log_local.user_timestamp = (uint32_t) (info->timestamp / 100000);
+ log_local.use_timestamp = DLT_USER_TIMESTAMP;
+ } else {
+ DLT_UINT64(info->timestamp);
+ }
+
+ DLT_UINT16(info->sequence_number);
+ DLT_STRING((char *)info->file_name);
+ DLT_STRING((char *)info->buffer_name);
+ DLT_UINT16(info->thread_id);
+ DLT_UINT8(info->severity);
+ DLT_STRING((char *)payload);
+
+ dlt_user_log_write_finish(&log_local);
+
+ return 0;
+}
+
+static void *slogger2_thread(void *v_conf)
+{
+ DltQnxSystemConfiguration *conf = (DltQnxSystemConfiguration *)v_conf;
+
+ if (v_conf == NULL)
+ return reinterpret_cast<void*>(EINVAL);
+
+ slog2_packet_info_t packet_info = SLOG2_PACKET_INFO_INIT;
+
+ DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG,
+ DLT_STRING("dlt-qnx-slogger2-adapter, in thread."));
+ DLT_REGISTER_CONTEXT(dltQnxSlogger2Context, conf->qnxslogger2.contextId,
+ "SLOGGER2 Adapter");
+
+ dlt_context_map_read(CONFIGURATION_FILES_DIR "/dlt-slog2ctxt.json");
+
+ /**
+ * Thread will block inside this function to get new log because
+ * flag = SLOG2_PARSE_FLAGS_DYNAMIC
+ */
+ int ret = slog2_parse_all(
+ SLOG2_PARSE_FLAGS_DYNAMIC, /* live streaming of all buffers merged */
+ NULL, NULL, &packet_info, sloggerinfo_callback, (void*) conf);
+ if (ret == -1) {
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_ERROR,
+ "slog2_parse_all() returned error=", ret);
+ ret = EBADMSG;
+ }
+
+ DLT_LOG_CXX(dltQnxSystem, DLT_LOG_DEBUG, __func__, ": Exited main loop.");
+
+ DLT_UNREGISTER_CONTEXT(dltQnxSlogger2Context);
+
+ /* Send a signal to main thread to wake up sigwait */
+ pthread_kill(g_threads.mainThread, SIGTERM);
+ return reinterpret_cast<void*>(ret);
+}
+
+void start_qnx_slogger2(DltQnxSystemConfiguration *conf)
+{
+ static pthread_attr_t t_attr;
+ static pthread_t pt;
+
+ DLT_LOG_CXX(dltQnxSlogger2Context, DLT_LOG_DEBUG,
+ "dlt-qnx-slogger2-adapter, start syslog");
+ pthread_create(&pt, &t_attr, slogger2_thread, conf);
+ g_threads.threads[g_threads.count++] = pt;
+}
diff --git a/src/dlt-qnx-system/dlt-qnx-system.c b/src/dlt-qnx-system/dlt-qnx-system.c
new file mode 100644
index 0000000..afd34b4
--- /dev/null
+++ b/src/dlt-qnx-system/dlt-qnx-system.c
@@ -0,0 +1,433 @@
+/**
+ * Copyright (C) 2020 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * DLT QNX system functionality source file.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Nguyen Dinh Thi <Thi.NguyenDinh@vn.bosch.com>
+ *
+ * \file: dlt-qnx-system.c
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <string.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <err.h>
+
+#include "dlt.h"
+#include "dlt-qnx-system.h"
+
+DLT_DECLARE_CONTEXT(dltQnxSystem)
+
+/* Global variables */
+volatile DltQnxSystemThreads g_threads;
+
+/* Function prototype */
+static void daemonize();
+static void start_threads(DltQnxSystemConfiguration *config);
+static void join_threads();
+static int read_configuration_file(DltQnxSystemConfiguration *config,
+ const char *file_name);
+static int read_command_line(DltQnxSystemCliOptions *options, int argc, char *argv[]);
+
+int main(int argc, char* argv[])
+{
+ DltQnxSystemCliOptions options;
+ DltQnxSystemConfiguration config;
+ int sigNo = 0;
+ int ret = 0;
+ sigset_t mask;
+ int i;
+
+ if (read_command_line(&options, argc, argv) < 0)
+ {
+ fprintf(stderr, "Failed to read command line!\n");
+ return -1;
+ }
+
+ if (read_configuration_file(&config, options.configurationFileName) < 0)
+ {
+ fprintf(stderr, "Failed to read configuration file!\n");
+ return -1;
+ }
+
+ if (options.daemonize > 0)
+ {
+ daemonize();
+ }
+
+ DLT_REGISTER_APP(config.applicationId, "DLT QNX System");
+ DLT_REGISTER_CONTEXT(dltQnxSystem, config.applicationContextId,
+ "Context of main dlt qnx system manager");
+
+ DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG,
+ DLT_STRING("Setting signals wait for abnormal exit"));
+
+ g_threads.mainThread = pthread_self();
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGTERM);
+ sigaddset(&mask, SIGHUP);
+ sigaddset(&mask, SIGQUIT);
+ sigaddset(&mask, SIGINT);
+ sigaddset(&mask, SIGALRM);
+ if (pthread_sigmask(SIG_BLOCK, &mask, NULL) == -1) {
+ DLT_LOG(dltQnxSystem, DLT_LOG_WARN,
+ DLT_STRING("Failed to block signals!"));
+ DLT_UNREGISTER_APP();
+ return -1;
+ }
+
+ DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG, DLT_STRING("Launching threads."));
+ start_threads(&config);
+
+ ret = sigwait(&mask, &sigNo);
+
+ for (i = 0; i < MAX_THREADS; i++) {
+ pthread_cancel(g_threads.threads[i]);
+ }
+ join_threads();
+
+ if (ret != 0) {
+ DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG,
+ DLT_STRING("sigwait failed with error: "),
+ DLT_INT(ret));
+ DLT_UNREGISTER_APP();
+ return -1;
+ }
+
+ DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG,
+ DLT_STRING("Received signal: "),
+ DLT_STRING(strsignal(sigNo)));
+
+ DLT_UNREGISTER_APP_FLUSH_BUFFERED_LOGS();
+ return 0;
+
+}
+
+/**
+ * Print information how to use this program.
+ */
+static void usage(char *prog_name)
+{
+ char version[255];
+ dlt_get_version(version, 255);
+
+ printf("Usage: %s [options]\n", prog_name);
+ printf("Application to manage QNX system, such as:\n");
+ printf(" - forward slogger2 messages from QNX to DLT) .\n");
+ printf("%s\n", version);
+ printf("Options:\n");
+ printf(" -d Daemonize. Detach from terminal and run in background.\n");
+ printf(" -c filename Use configuration file. \n");
+ printf(" Default: %s\n", DEFAULT_CONF_FILE);
+ printf(" -h This help message.\n");
+}
+
+/**
+ * Initialize command line options with default values.
+ */
+static void init_cli_options(DltQnxSystemCliOptions *options)
+{
+ options->configurationFileName = DEFAULT_CONF_FILE;
+ options->daemonize = 0;
+}
+
+/**
+ * Read command line options and set the values in provided structure
+ */
+static int read_command_line(DltQnxSystemCliOptions *options, int argc, char *argv[])
+{
+ init_cli_options(options);
+ int opt;
+
+ while ((opt = getopt(argc, argv, "c:hd")) != -1)
+ {
+ switch (opt) {
+ case 'd':
+ {
+ options->daemonize = 1;
+ break;
+ }
+ case 'c':
+ {
+ options->configurationFileName = (char *)malloc(strlen(optarg)+1);
+ MALLOC_ASSERT(options->configurationFileName);
+ /**
+ * strcpy unritical here, because size matches exactly the size
+ * to be copied
+ */
+ strcpy(options->configurationFileName, optarg);
+ break;
+ }
+ case 'h':
+ {
+ usage(argv[0]);
+ exit(0);
+ return -1;
+ }
+ default:
+ {
+ fprintf(stderr, "Unknown option '%c'\n", optopt);
+ usage(argv[0]);
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * Initialize configuration to default values.
+ */
+static void init_configuration(DltQnxSystemConfiguration *config)
+{
+ /* Common */
+ config->applicationId = "QSYM";
+ config->applicationContextId = "QSYC";
+
+ /* Slogger2 */
+ config->qnxslogger2.enable = 0;
+ config->qnxslogger2.contextId = "QSLA";
+ config->qnxslogger2.useOriginalTimestamp = 1;
+}
+
+/**
+ * Read options from the configuration file
+ */
+static int read_configuration_file(DltQnxSystemConfiguration *config,
+ const char *file_name)
+{
+ FILE *file;
+ char *line;
+ char *token;
+ char *value;
+ char *pch;
+ int ret = 0;
+
+ init_configuration(config);
+
+ file = fopen(file_name, "r");
+
+ if (file == NULL)
+ {
+ fprintf(stderr,
+ "dlt-qnx-system, could not open configuration file.\n");
+ return -1;
+ }
+
+ line = malloc(MAX_LINE);
+ token = malloc(MAX_LINE);
+ value = malloc(MAX_LINE);
+
+ MALLOC_ASSERT(line);
+ MALLOC_ASSERT(token);
+ MALLOC_ASSERT(value);
+
+ while (fgets(line, MAX_LINE, file) != NULL)
+ {
+ token[0] = 0;
+ value[0] = 0;
+
+ pch = strtok(line, " =\r\n");
+ while (pch != NULL)
+ {
+ if (pch[0] == '#')
+ {
+ break;
+ }
+
+ if (token[0] == 0)
+ {
+ strncpy(token, pch, MAX_LINE-1);
+ token[MAX_LINE-1] = 0;
+ }
+ else
+ {
+ strncpy(value, pch, MAX_LINE);
+ value[MAX_LINE-1] = 0;
+ break;
+ }
+
+ pch = strtok(NULL, " =\r\n");
+ }
+
+ if (token[0] && value[0])
+ {
+ /* Common */
+ if (strcmp(token, "ApplicationId") == 0)
+ {
+ config->applicationId = (char *)malloc(strlen(value) + 1);
+ MALLOC_ASSERT(config->applicationId);
+ /**
+ * strcpy unritical here, because size matches exactly the
+ * size to be copied
+ */
+ strcpy(config->applicationId, value);
+ }
+ else if (strcmp(token, "ApplicationContextID") == 0)
+ {
+ config->applicationContextId = (char *)malloc(strlen(value) + 1);
+ MALLOC_ASSERT(config->applicationContextId);
+ /**
+ * strcpy unritical here, because size matches exactly
+ * the size to be copied
+ */
+ strcpy(config->applicationContextId, value);
+ }
+ /* Slogger2 */
+ else if (strcmp(token, "QnxSlogger2Enable") == 0)
+ {
+ config->qnxslogger2.enable = atoi(value);
+ }
+ else if (strcmp(token, "QnxSlogger2ContextId") == 0)
+ {
+ config->qnxslogger2.contextId = (char *)malloc(strlen(value) + 1);
+ MALLOC_ASSERT(config->qnxslogger2.contextId);
+ /**
+ * strcpy unritical here, because size matches exactly
+ * the size to be copied
+ */
+ strcpy(config->qnxslogger2.contextId, value);
+ }
+ else if (strcmp(token, "QnxSlogger2UseOriginalTimestamp") == 0)
+ {
+ config->qnxslogger2.useOriginalTimestamp = atoi(value);
+ }
+ else
+ {
+ /* Do nothing */
+ }
+ }
+ }
+
+ fclose(file);
+ file = NULL;
+
+ free(value);
+ value = NULL;
+
+ free(token);
+ token = NULL;
+
+ free(line);
+ line = NULL;
+
+ return ret;
+}
+
+static void daemonize()
+{
+ pid_t pid = fork();
+
+ if (pid == -1) {
+ err(-1, "%s failed on fork()", __func__);
+ }
+
+ if (pid > 0) { /* parent process*/
+ exit(0);
+ }
+
+ /* Create a new process group */
+ if (setsid() == -1) {
+ err(-1, "%s failed on setsid()", __func__);
+ }
+
+ /* Point std(in,out,err) to /dev/null */
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
+ close(STDERR_FILENO);
+
+ int fd = open("/dev/null", O_RDWR);
+ if (fd == -1) {
+ err(-1, "%s failed on open() /dev/null", __func__);
+ }
+
+ if ((dup2(fd, STDIN_FILENO) == -1) ||
+ (dup2(fd, STDOUT_FILENO) == -1 ) ||
+ (dup2(fd, STDERR_FILENO) == -1 )) {
+ err(-1, "%s failed on dup2()", __func__);
+ }
+
+ /**
+ * Ignore signals related to child processes and
+ * terminal handling.
+ */
+ signal(SIGCHLD, SIG_IGN);
+ signal(SIGTSTP, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+ signal(SIGTTIN, SIG_IGN);
+}
+
+static void start_threads(DltQnxSystemConfiguration *config)
+{
+ int i = 0;
+
+ /* Check parameter */
+ if (!config)
+ {
+ return;
+ }
+
+ DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG,
+ DLT_STRING("dlt-qnx-system, start threads"));
+
+ g_threads.count = 0;
+ g_threads.shutdown = 0;
+
+ for (i = 0; i < MAX_THREADS; i++)
+ {
+ g_threads.threads[i] = 0;
+ }
+
+ if (config->qnxslogger2.enable)
+ {
+ start_qnx_slogger2(config);
+ }
+}
+
+/**
+ * Wait for threads to exit.
+ */
+static void join_threads()
+{
+ int i = 0;
+ DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG,
+ DLT_STRING("dlt-qnx-system, waiting for threads to exit"));
+
+ if (g_threads.count < 1)
+ {
+ DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG,
+ DLT_STRING("dlt-qnx-system, no threads, waiting for signal."));
+ }
+ else
+ {
+ DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG,
+ DLT_STRING("dlt-qnx-system, thread count: "),
+ DLT_INT(g_threads.count));
+
+ for (i = 0; i < g_threads.count; i++)
+ {
+ pthread_join(g_threads.threads[i], NULL);
+ DLT_LOG(dltQnxSystem, DLT_LOG_DEBUG,
+ DLT_STRING("dlt-qnx-system, thread exit: "),
+ DLT_INT(g_threads.threads[i]));
+ }
+ }
+
+ DLT_UNREGISTER_CONTEXT(dltQnxSystem);
+}
diff --git a/src/dlt-qnx-system/dlt-qnx-system.conf b/src/dlt-qnx-system/dlt-qnx-system.conf
new file mode 100644
index 0000000..8a12e89
--- /dev/null
+++ b/src/dlt-qnx-system/dlt-qnx-system.conf
@@ -0,0 +1,25 @@
+# Configuration file of DLT QNX Slogger2 Manager
+#
+
+########################################################################
+# General configuration
+########################################################################
+
+# The application Id used for the QNX system Manager (Default: QSYM)
+ApplicationId = QSYM
+
+# Context of main dlt QNX system
+ApplicationContextID = QSYC
+
+########################################################################
+# Syslog Adapter configuration
+########################################################################
+
+# Enable the Qnx slogger2 Adapter (Default: 1)
+QnxSlogger2Enable = 1
+
+# The Context Id of the Qnx syslog adapter (Default: QSLA)
+QnxSlogger2ContextId = QSLA
+
+# Use slogger2 event timestamps as DLT timestamps (Default: 1)
+QnxSlogger2UseOriginalTimestamp = 1
diff --git a/src/dlt-qnx-system/dlt-qnx-system.h b/src/dlt-qnx-system/dlt-qnx-system.h
new file mode 100644
index 0000000..270b8be
--- /dev/null
+++ b/src/dlt-qnx-system/dlt-qnx-system.h
@@ -0,0 +1,109 @@
+/**
+ * Copyright (C) 2020 Advanced Driver Information Technology.
+ * This code is developed by Advanced Driver Information Technology.
+ * Copyright of Advanced Driver Information Technology, Bosch and DENSO.
+ *
+ * DLT QNX system functionality header file.
+ *
+ * \copyright
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with
+ * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ *
+ * \author Nguyen Dinh Thi <Thi.NguyenDinh@vn.bosch.com> ADIT 2020
+ *
+ * \file: dlt-qnx-system.h
+ * For further information see http://www.genivi.org/.
+ * @licence end@
+ */
+
+/*******************************************************************************
+** **
+** SRC-MODULE: dlt_qnx-system.h **
+** **
+** TARGET : QNX **
+** **
+** PROJECT : DLT **
+** **
+** AUTHOR : Thi.NguyenDinh@vn.bosch.com **
+** **
+** PURPOSE : **
+** **
+** REMARKS : **
+** **
+** PLATFORM DEPENDANT [yes/no]: yes **
+** **
+** TO BE CHANGED BY USER [yes/no]: no **
+** **
+*******************************************************************************/
+
+/*******************************************************************************
+** Author Identity **
+********************************************************************************
+** **
+** Initials Name Company **
+** -------- ------------------------- ---------------------------------- **
+** ndt Nguyen Dinh Thi ADIT **
+** **
+*******************************************************************************/
+
+#ifndef DLT_QNX_SYSTEM_H_
+#define DLT_QNX_SYSTEM_H_
+
+#include "dlt.h"
+
+/* Constants */
+#define DEFAULT_CONF_FILE ( CONFIGURATION_FILES_DIR "/dlt-qnx-system.conf")
+
+#define MAX_LINE 1024
+#define MAX_THREADS 8
+
+/* Macros */
+#define MALLOC_ASSERT(x)\
+ do\
+ {\
+ if(x == NULL) {\
+ fprintf(stderr, "%s - %d: Out of memory\n", __func__, __LINE__);\
+ abort();\
+ }\
+ }\
+ while (0)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Command line options */
+typedef struct {
+ char *configurationFileName;
+ int daemonize;
+} DltQnxSystemCliOptions;
+
+/* Configuration slogger2 options */
+typedef struct {
+ int enable;
+ char *contextId;
+ int useOriginalTimestamp;
+} Qnxslogger2Options;
+
+typedef struct {
+ char *applicationId;
+ char *applicationContextId;
+ Qnxslogger2Options qnxslogger2;
+} DltQnxSystemConfiguration;
+
+typedef struct {
+ pthread_t threads[MAX_THREADS];
+ pthread_t mainThread;
+ int count;
+ int shutdown;
+} DltQnxSystemThreads;
+
+void start_qnx_slogger2(DltQnxSystemConfiguration *conf);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* DLT_QNX_SYSTEM_H_ */
diff --git a/src/dlt-qnx-system/dlt-slog2ctxt.json b/src/dlt-qnx-system/dlt-slog2ctxt.json
new file mode 100644
index 0000000..6d69ec0
--- /dev/null
+++ b/src/dlt-qnx-system/dlt-slog2ctxt.json
@@ -0,0 +1,14 @@
+{
+ "SRCN": {
+ "name": "screen",
+ "description": ""
+ },
+ "SLM ": {
+ "name": "slm",
+ "description": ""
+ },
+ "SYSL": {
+ "name": "syslogd",
+ "description": ""
+ }
+}