summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Hassler <sven_hassler@mentor.com>2015-11-19 14:20:11 +0100
committerLutz Helwing <lutz_helwing@mentor.com>2015-12-16 17:20:39 +0100
commit96439591a8be7e3e10a5de9488dde245777318c8 (patch)
treeeb547483f683e5a202cb58f4e16d511a7cc432eb
parent472615cfec47da92a14f48417040a561ffdd3649 (diff)
downloadDLT-daemon-96439591a8be7e3e10a5de9488dde245777318c8.tar.gz
First implementation of dlt-procfs
This tool logs the following information to dlt-daemon: - PID, parent's PID, commandline when new processes appear, maked by "NEW" - PID when processes stop, marked by "STP" - PID, CPU-Time (ms), RSS (bytes), CTX-switches, I/O (bytes), I/O-wait (ms) for all processes that consume CPU time, marked as "ACT" - PID, commandline in a regular time-interval, marked as "CHK" - The number of interrupts on each CPU in a regular time interval, marked as "IRQ" A configuration file, called dlt-procfs.conf allows configuring the time intervals of the updated processes, the command-line updates and the interrupts as well as the preferred log level.
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/procfs/CMakeLists.txt29
-rw-r--r--src/procfs/dlt-procfs-common.c68
-rw-r--r--src/procfs/dlt-procfs-common.h40
-rw-r--r--src/procfs/dlt-procfs-interrupt.c147
-rw-r--r--src/procfs/dlt-procfs-interrupt.h35
-rw-r--r--src/procfs/dlt-procfs-options.c259
-rw-r--r--src/procfs/dlt-procfs-process-list.c288
-rw-r--r--src/procfs/dlt-procfs-process-list.h54
-rw-r--r--src/procfs/dlt-procfs-process.c467
-rw-r--r--src/procfs/dlt-procfs-process.h56
-rw-r--r--src/procfs/dlt-procfs.c503
-rw-r--r--src/procfs/dlt-procfs.conf18
-rw-r--r--src/procfs/dlt-procfs.h61
15 files changed, 2031 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 52edb51..28c1b18 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -73,6 +73,7 @@ option(WITH_DLT_COREDUMPHANDLER "EXPERIMENTAL! Set to ON to build src/core_d
option(WITH_DLT_LOGSTORAGE_CTRL_UDEV "PROTOTYPE! Set to ON to build logstorage control application with udev support" OFF)
option(WITH_DLT_LOGSTORAGE_CTRL_PROP "PROTOTYPE! Set to ON to build logstorage control application with proprietary support" OFF)
option(WITH_DLT_USE_IPv6 "Set to ON for IPv6 support" ON)
+option(WITH_DLT_PROCFS "Set to ON to build src/procfs binaries" ON)
# RPM settings
set( GENIVI_RPM_RELEASE "1")#${DLT_REVISION}")
set( LICENSE "Mozilla Public License Version 2.0" )
@@ -206,6 +207,7 @@ message( STATUS "WITH_DLT_SHM_ENABLE = ${WITH_DLT_SHM_ENABLE}" )
message( STATUS "WITH_DLTTEST = ${WITH_DLTTEST}" )
message( STATUS "WITH_DLT_CXX11_EXT = ${WITH_DLT_CXX11_EXT}" )
message( STATUS "WITH_DLT_COREDUMPHANDLER = ${WITH_DLT_COREDUMPHANDLER}" )
+message( STATUS "WITH_DLT_PROCFS = ${WITH_DLT_PROCFS}" )
message( STATUS "WITH_CHECK_CONFIG_FILE = ${WITH_CHECK_CONFIG_FILE}" )
message( STATUS "WITH_TESTSCRIPTS = ${WITH_TESTSCRIPTS}" )
message( STATUS "WITH_GPROF = ${WITH_GPROF}" )
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 6fd8a64..f30932a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -46,3 +46,7 @@ endif( WITH_DLT_DBUS )
if( WITH_DLT_COREDUMPHANDLER )
add_subdirectory( core_dump_handler )
endif( WITH_DLT_COREDUMPHANDLER )
+
+if( WITH_DLT_PROCFS )
+ add_subdirectory( procfs )
+endif( WITH_DLT_PROCFS )
diff --git a/src/procfs/CMakeLists.txt b/src/procfs/CMakeLists.txt
new file mode 100644
index 0000000..bbe3d49
--- /dev/null
+++ b/src/procfs/CMakeLists.txt
@@ -0,0 +1,29 @@
+#######
+# @licence make begin@
+# SPDX license identifier: MPL-2.0
+#
+# Copyright (C) 2011-2015, BMW AG
+#
+# 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@
+#######
+
+set (dlt_procfs_SRCS dlt-procfs.c dlt-procfs-options.c dlt-procfs-process.c dlt-procfs-process-list.c dlt-procfs-common.c dlt-procfs-interrupt.c)
+add_executable (dlt-procfs ${dlt_procfs_SRCS})
+target_link_libraries (dlt-procfs dlt)
+set_target_properties(dlt-procfs PROPERTIES LINKER_LANGUAGE C)
+
+install(TARGETS dlt-procfs
+ RUNTIME DESTINATION bin
+ COMPONENT base)
+
+INSTALL(FILES dlt-procfs.conf
+ DESTINATION ${CONFIGURATION_FILES_DIR}
+ COMPONENT base)
diff --git a/src/procfs/dlt-procfs-common.c b/src/procfs/dlt-procfs-common.c
new file mode 100644
index 0000000..c7e490d
--- /dev/null
+++ b/src/procfs/dlt-procfs-common.c
@@ -0,0 +1,68 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2011-2015, BMW AG
+ *
+ * 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@
+ */
+
+/*!
+ * \author Sven Hassler <sven_hassler@mentor.com>
+ *
+ * \copyright Copyright © 2011-2015 BMW AG. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt-procfs-common.c
+ */
+
+#include "dlt-procfs-common.h"
+
+DltReturnValue dlt_procfs_read_file_compact(char *filename, char **target)
+{
+ char buffer[BUFFER_SIZE];
+ int ret = dlt_procfs_read_file(filename, buffer, BUFFER_SIZE);
+ if(ret < DLT_RETURN_OK)
+ return ret;
+
+ if((*target = malloc(strlen(buffer) + 1)) == NULL)
+ {
+ fprintf(stderr, "Out of memory!\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ memcpy(*target, buffer, strlen(buffer) + 1);
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_read_file(char* filename, char* buffer, uint maxLength)
+{
+ if(filename == NULL || buffer == NULL)
+ {
+ fprintf(stderr, "Nullpointer parameter!\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ FILE* file = fopen(filename, "r");
+ if(file == NULL)
+ {
+ // fprintf(stderr, "Could not read file %s\n", filename);
+ return DLT_RETURN_ERROR;
+ }
+
+ int buflen = fread(buffer, 1, maxLength-1, file);
+ buffer[buflen] = '\0';
+
+ fclose(file);
+
+ return DLT_RETURN_OK;
+}
diff --git a/src/procfs/dlt-procfs-common.h b/src/procfs/dlt-procfs-common.h
new file mode 100644
index 0000000..ed7f096
--- /dev/null
+++ b/src/procfs/dlt-procfs-common.h
@@ -0,0 +1,40 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2011-2015, BMW AG
+ *
+ * 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@
+ */
+
+/*!
+ * \author Sven Hassler <sven_hassler@mentor.com>
+ *
+ * \copyright Copyright © 2011-2015 BMW AG. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt-procfs-common.h
+ */
+
+#ifndef SRC_PROCFS_DLT_PROCFS_COMMON_H_
+#define SRC_PROCFS_DLT_PROCFS_COMMON_H_
+
+#include <dlt_types.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define BUFFER_SIZE 4096
+
+DltReturnValue dlt_procfs_read_file(char* filename, char* buffer, uint maxLength);
+DltReturnValue dlt_procfs_read_file_compact(char *filename, char **target);
+
+#endif /* SRC_PROCFS_DLT_PROCFS_COMMON_H_ */
diff --git a/src/procfs/dlt-procfs-interrupt.c b/src/procfs/dlt-procfs-interrupt.c
new file mode 100644
index 0000000..10d8823
--- /dev/null
+++ b/src/procfs/dlt-procfs-interrupt.c
@@ -0,0 +1,147 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2011-2015, BMW AG
+ *
+ * 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@
+ */
+
+/*!
+ * \author Sven Hassler <sven_hassler@mentor.com>
+ *
+ * \copyright Copyright © 2011-2015 BMW AG. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt-procfs-interrupt.c
+ */
+
+#include "dlt-procfs-interrupt.h"
+
+DltReturnValue dlt_procfs_log_interrupts(DltContext *ctx, DltLogLevelType log_level)
+{
+ if(ctx == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_log_interrupts(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ char buffer[BUFFER_SIZE];
+ *buffer = '\0';
+
+ char file_buffer[BUFFER_SIZE];
+ char *token, *delim = " \t", *delim2 = " \t\n", *check;
+ int head_line = 1, first_row = 1, cpu_count = 0, column = 0, buffer_offset = 0;
+ DltReturnValue ret;
+
+ if((ret = dlt_procfs_read_file("/proc/interrupts", file_buffer, BUFFER_SIZE)) < DLT_RETURN_OK) return ret;
+
+ token = strtok(file_buffer, delim);
+ while(token != NULL)
+ {
+ if(head_line)
+ {
+ if(strlen(token) > 3 && token[0]=='C' && token[1]=='P' && token[2]=='U')
+ cpu_count++;
+ else if(cpu_count <= 0)
+ {
+ fprintf(stderr, "dlt_procfs_log_interrupts: Could not parse CPU count\n");
+ return DLT_RETURN_ERROR;
+ }
+ else if(strcmp(token, "\n") == 0)
+ head_line = 0;
+
+ token = strtok(NULL, delim);
+ }
+ else
+ {
+ int tokenlen = strlen(token);
+ if(token[tokenlen - 1] == ':')
+ {
+ column = 0;
+
+ if(first_row)
+ first_row = 0;
+ else
+ buffer_offset += snprintf(buffer + buffer_offset, BUFFER_SIZE - buffer_offset, "\n");
+ }
+
+ if(column == 0) // IRQ number
+ {
+ buffer_offset += snprintf(buffer + buffer_offset, BUFFER_SIZE - buffer_offset, "%.*s;", tokenlen-1, token);
+ }
+ else if(column <= cpu_count)
+ {
+ long int interrupt_count = strtol(token, &check, 10);
+ if(*check != '\0')
+ {
+ fprintf(stderr, "dlt_procfs_log_interrupts: Could not parse interrupt count for CPU %d\n", column - 1);
+ return DLT_RETURN_ERROR;
+ }
+
+ buffer_offset += snprintf(buffer + buffer_offset, BUFFER_SIZE - buffer_offset, "cpu%d:%ld;", column - 1, interrupt_count);
+ }
+
+ column++;
+
+ token = strtok(NULL, delim2);
+ }
+ }
+
+ DltContextData ctx_data;
+ if((ret = dlt_user_log_write_start(ctx, &ctx_data, log_level)) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "dlt_procfs_log_interrupts(): dlt_user_log_write_start() returned error\n");
+ return ret;
+ }
+
+ if((ret = dlt_user_log_write_string(&ctx_data, "IRQ")) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "dlt_procfs_log_interrupts(): dlt_user_log_write_string() returned error\n");
+ return ret;
+ }
+
+ token = strtok(buffer, "\n");
+ while(token != NULL)
+ {
+ if(dlt_user_log_write_string(&ctx_data, token) < DLT_RETURN_OK)
+ {
+ /* message buffer full, start new one */
+ if((ret = dlt_user_log_write_finish(&ctx_data)) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "dlt_procfs_log_interrupts(): dlt_user_log_write_finish() returned error\n");
+ return ret;
+ }
+
+ if((ret = dlt_user_log_write_start(ctx, &ctx_data, log_level)) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "dlt_procfs_log_interrupts(): dlt_user_log_write_start() returned error\n");
+ return ret;
+ }
+
+ if((ret = dlt_user_log_write_string(&ctx_data, "IRQ")) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "dlt_procfs_log_interrupts(): dlt_user_log_write_string() returned error\n");
+ return ret;
+ }
+ }
+ else
+ token = strtok(NULL, "\n");
+ }
+
+ if((ret = dlt_user_log_write_finish(&ctx_data)) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "dlt_procfs_log_interrupts(): dlt_user_log_write_finish() returned error\n");
+ return ret;
+ }
+
+ return DLT_RETURN_OK;
+}
diff --git a/src/procfs/dlt-procfs-interrupt.h b/src/procfs/dlt-procfs-interrupt.h
new file mode 100644
index 0000000..48a3a6d
--- /dev/null
+++ b/src/procfs/dlt-procfs-interrupt.h
@@ -0,0 +1,35 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2011-2015, BMW AG
+ *
+ * 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@
+ */
+
+/*!
+ * \author Sven Hassler <sven_hassler@mentor.com>
+ *
+ * \copyright Copyright © 2011-2015 BMW AG. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt-procfs-interrupt.h
+ */
+
+#ifndef SRC_PROCFS_DLT_PROCFS_INTERRUPT_H_
+#define SRC_PROCFS_DLT_PROCFS_INTERRUPT_H_
+
+#include "dlt.h"
+#include "dlt-procfs-common.h"
+
+DltReturnValue dlt_procfs_log_interrupts(DltContext *ctx, DltLogLevelType log_level);
+
+#endif /* SRC_PROCFS_DLT_PROCFS_INTERRUPT_H_ */
diff --git a/src/procfs/dlt-procfs-options.c b/src/procfs/dlt-procfs-options.c
new file mode 100644
index 0000000..d2aa3af
--- /dev/null
+++ b/src/procfs/dlt-procfs-options.c
@@ -0,0 +1,259 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2011-2015, BMW AG
+ *
+ * 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@
+ */
+
+/*!
+ * \author Sven Hassler <sven_hassler@mentor.com>
+ *
+ * \copyright Copyright © 2011-2015 BMW AG. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt-procfs-options.c
+ */
+
+#include "dlt-procfs.h"
+
+/**
+ * Print information how to use this program.
+ */
+void usage(char *prog_name)
+{
+ char version[255];
+ dlt_get_version(version,255);
+
+ printf("Usage: %s [options]\n", prog_name);
+ printf("Application to forward information from the /proc/ file system 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.
+ */
+void dlt_procfs_init_cli_options(DltProcfsOptions *options)
+{
+ options->configurationFileName = DEFAULT_CONF_FILE;
+ options->customConfigFile = 0;
+}
+
+void dlt_procfs_free_cli_options(DltProcfsOptions *options)
+{
+ if(options->customConfigFile)
+ free(options->configurationFileName);
+}
+
+DltReturnValue dlt_procfs_read_command_line(DltProcfsOptions *options, int argc, char **argv)
+{
+ if(options == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_read_command_line(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+ dlt_procfs_init_cli_options(options);
+ int opt;
+
+ while((opt = getopt(argc, argv, "c:h")) != -1)
+ {
+ switch(opt) {
+ case 'c':
+ {
+ if((options->configurationFileName = malloc(strlen(optarg)+1)) == 0)
+ {
+ fprintf(stderr, "Out of memory!\n");
+ return DLT_RETURN_ERROR;
+ }
+ strcpy(options->configurationFileName, optarg); /* strcpy unritical here, because size matches exactly the size to be copied */
+ options->customConfigFile = 1;
+ break;
+ }
+ case 'h':
+ {
+ usage(argv[0]);
+ exit(0);
+ return -1;//for parasoft
+ }
+ default:
+ {
+ fprintf(stderr, "Unknown option: %c\n", optopt);
+ usage(argv[0]);
+ return DLT_RETURN_ERROR;
+ }
+ }
+ }
+
+ return DLT_RETURN_OK;
+}
+
+/**
+ * Initialize configuration to default values.
+ */
+void dlt_procfs_init_configuration(DltProcfsConfig *config)
+{
+ config->process_log_interval = 1000;
+ config->irq_log_interval = 1000;
+ config->log_level = DLT_LOG_DEFAULT;
+}
+
+/**
+ * Read options from the configuration file
+ */
+DltReturnValue dlt_procfs_read_configuration_file(DltProcfsConfig *config, char *file_name)
+{
+ FILE *file;
+ char *line, *token, *value, *pch, *strchk;
+ int tmp;
+
+ if(config == NULL || file_name == NULL)
+ {
+ fprintf(stderr, "Nullpointer parameter!\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ dlt_procfs_init_configuration(config);
+
+ file = fopen(file_name, "r");
+
+ if(file == NULL)
+ {
+ fprintf(stderr, "Could not open configuration file!\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ if((line = malloc(COMMAND_LINE_SIZE)) == 0)
+ {
+ fprintf(stderr, "Out of memory!\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ if((token = malloc(COMMAND_LINE_SIZE)) == 0)
+ {
+ fprintf(stderr, "Out of memory!\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ if((value = malloc(COMMAND_LINE_SIZE)) == 0)
+ {
+ fprintf(stderr, "Out of memory!\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ while(fgets(line, COMMAND_LINE_SIZE, 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, COMMAND_LINE_SIZE-1);
+ token[COMMAND_LINE_SIZE-1] = '\0';
+ }
+ else
+ {
+ strncpy(value, pch, COMMAND_LINE_SIZE-1);
+ value[COMMAND_LINE_SIZE-1] = '\0';
+ break;
+ }
+
+ pch = strtok(NULL, " =\r\n");
+ }
+
+ if(token[0] != '\0' && value[0] != '\0')
+ {
+ if(strcmp(token, "process_interval") == '\0')
+ {
+ tmp = strtol(value, &strchk, 10);
+
+ if(strchk[0] == '\0' && tmp > 0)
+ config->process_log_interval = tmp;
+ else
+ fprintf(stderr, "Error reading configuration file: %s is not a valid value for %s\n", value, token);
+ }
+ else if(strcmp(token, "irq_interval") == '\0')
+ {
+ tmp = strtol(value, &strchk, 10);
+
+ if(strchk[0] == '\0' && tmp > 0)
+ config->irq_log_interval = tmp;
+ else
+ fprintf(stderr, "Error reading configuration file: %s is not a valid value for %s\n", value, token);
+ }
+ else if(strcmp(token, "check_interval") == '\0')
+ {
+ tmp = strtol(value, &strchk, 10);
+
+ if(strchk[0] == '\0' && tmp > 0)
+ config->check_log_interval = tmp;
+ else
+ fprintf(stderr, "Error reading configuration file: %s is not a valid value for %s\n", value, token);
+ }
+ else if(strcmp(token, "log_level") == '\0')
+ {
+ tmp = strtol(value, &strchk, 10);
+
+ if(strchk[0] == '\0' && tmp >= -1 && tmp <= 6)
+ config->log_level = tmp;
+ else
+ fprintf(stderr, "Error reading configuration file: %s is not a valid value for %s\n", value, token);
+ }
+ }
+ }
+
+ fclose(file);
+ free(value);
+ free(token);
+ free(line);
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_init(int argc, char **argv, DltProcfsConfig *config)
+{
+ DltProcfsOptions options;
+
+ DltReturnValue ret;
+
+ if(config == NULL)
+ {
+ fprintf(stderr, "Nullpointer parameter!");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ if((ret = dlt_procfs_read_command_line(&options, argc, argv)) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "Failed to read command line!");
+ return ret;
+ }
+
+ if((ret = dlt_procfs_read_configuration_file(config, options.configurationFileName)) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "Failed to read configuration file!");
+ return ret;
+ }
+
+ dlt_procfs_free_cli_options(&options);
+
+ return DLT_RETURN_OK;
+}
diff --git a/src/procfs/dlt-procfs-process-list.c b/src/procfs/dlt-procfs-process-list.c
new file mode 100644
index 0000000..9c98bdc
--- /dev/null
+++ b/src/procfs/dlt-procfs-process-list.c
@@ -0,0 +1,288 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2011-2015, BMW AG
+ *
+ * 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@
+ */
+
+/*!
+ * \author Sven Hassler <sven_hassler@mentor.com>
+ *
+ * \copyright Copyright © 2011-2015 BMW AG. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt-procfs-process-list.c
+ */
+
+#include "dlt-procfs-process-list.h"
+
+DltProcfsProcessList *dlt_procfs_create_process_list()
+{
+ DltProcfsProcessList *new_list = malloc(sizeof(DltProcfsProcessList));
+ if(new_list == NULL)
+ {
+ fprintf(stderr, "Cannot create process list, out of memory\n");
+ return NULL;
+ }
+
+ memset(new_list, 0, sizeof(DltProcfsProcessList));
+ new_list->start = new_list->cursor = NULL;
+
+ return new_list;
+}
+
+DltReturnValue dlt_procfs_free_process_list_soft(DltProcfsProcessList *list)
+{
+ if(list == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_free_process_list_soft: Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ free(list);
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_free_process_list(DltProcfsProcessList *list)
+{
+ if(list == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_free_process_list: Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ DltProcfsProcess *tmp;
+
+ list->cursor = list->start;
+ while(list->cursor != NULL)
+ {
+ tmp = list->cursor->next;
+ dlt_procfs_free_process(list->cursor);
+ list->cursor = tmp;
+ }
+
+ return dlt_procfs_free_process_list_soft(list);
+}
+
+DltProcfsProcess *dlt_procfs_get_process_at_cursor(DltProcfsProcessList *list)
+{
+ if(list == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_get_process_at_cursor(): Nullpointer parameter\n");
+ return NULL;
+ }
+
+ return list->cursor;
+}
+
+DltReturnValue dlt_procfs_reset_cursor(DltProcfsProcessList *list)
+{
+ if(list == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_reset_cursor(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ list->cursor = list->start;
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_set_cursor_at_end(DltProcfsProcessList *list)
+{
+ if(list == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_set_cursor_at_end(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ list->cursor = list->start;
+ if(list->cursor == NULL)
+ return DLT_RETURN_OK;
+
+ while(list->cursor->next != NULL)
+ dlt_procfs_increment_cursor(list);
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_increment_cursor(DltProcfsProcessList *list)
+{
+ if(list == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_set_cursor_at_end(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ if(list->cursor == NULL)
+ return DLT_RETURN_ERROR;
+
+ list->cursor = list->cursor->next;
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_decrement_cursor(DltProcfsProcessList *list)
+{
+ if(list == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_set_cursor_at_end(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ if(list->cursor == NULL)
+ return DLT_RETURN_ERROR;
+
+ list->cursor = list->cursor->prev;
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_add_process_at_start(DltProcfsProcessList *list, DltProcfsProcess *process)
+{
+ if(list == NULL || process == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_add_process_at_start(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ if(list->start != NULL)
+ list->start->prev = process;
+
+ process->next = list->start;
+ list->start = process;
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_add_process_before_cursor(DltProcfsProcessList *list, DltProcfsProcess *process)
+{
+ if(list == NULL || process == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_add_process_before_cursor(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ if(list->start == NULL) // Empty list?
+ {
+ DltReturnValue ret = dlt_procfs_add_process_at_start(list, process);
+ list->cursor = NULL;
+ return ret;
+ }
+ else if(list->cursor == NULL)
+ {
+ dlt_procfs_set_cursor_at_end(list);
+ DltReturnValue ret = dlt_procfs_add_process_after_cursor(list, process);
+ list->cursor = NULL;
+ return ret;
+ }
+
+ if(list->cursor->prev != NULL)
+ list->cursor->prev->next = process;
+ else
+ list->start = process;
+
+ process->next = list->cursor;
+ process->prev = list->cursor->prev;
+ list->cursor->prev = process;
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_add_process_after_cursor(DltProcfsProcessList *list, DltProcfsProcess *process)
+{
+ if(list == NULL || process == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_add_process_after_cursor: Nullpointer parameter\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ if(list->cursor == NULL)
+ return dlt_procfs_add_process_at_start(list, process);
+
+ if(list->cursor->next != NULL)
+ list->cursor->next->prev = process;
+
+ process->next = list->cursor->next;
+ process->prev = list->cursor;
+ list->cursor->next = process;
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_remove_process_at_cursor_soft(DltProcfsProcessList *list)
+{
+ if(list == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_set_cursor_at_end(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ if(list->cursor == NULL)
+ {
+ fprintf(stderr, "Could not remove process from list - cursor is NULL!\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ DltProcfsProcess *tmp = list->cursor;
+
+ if(tmp->prev != NULL)
+ {
+ if(tmp->next != NULL)
+ {
+ tmp->prev->next = tmp->next;
+ tmp->next->prev = tmp->prev;
+ }
+ else
+ tmp->prev->next = NULL;
+ }
+ else
+ {
+ if(tmp->next != NULL)
+ {
+ tmp->next->prev = NULL;
+ list->start = tmp->next;
+ }
+ else
+ list->start = NULL;
+ }
+
+ list->cursor = tmp->next; // becomes NULL if list is at end
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_remove_process_at_cursor(DltProcfsProcessList *list)
+{
+ if(list == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_set_cursor_at_end(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ if(list->cursor == NULL)
+ {
+ fprintf(stderr, "Could not remove process from list - cursor is NULL!\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ DltProcfsProcess *tmp = list->cursor;
+ DltReturnValue ret = dlt_procfs_remove_process_at_cursor_soft(list);
+ if(ret < DLT_RETURN_OK)
+ return ret;
+
+ dlt_procfs_free_process(tmp);
+
+ return DLT_RETURN_OK;
+}
+
diff --git a/src/procfs/dlt-procfs-process-list.h b/src/procfs/dlt-procfs-process-list.h
new file mode 100644
index 0000000..1545ab3
--- /dev/null
+++ b/src/procfs/dlt-procfs-process-list.h
@@ -0,0 +1,54 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2011-2015, BMW AG
+ *
+ * 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@
+ */
+
+/*!
+ * \author Sven Hassler <sven_hassler@mentor.com>
+ *
+ * \copyright Copyright © 2011-2015 BMW AG. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt-procfs-process-list.h
+ */
+
+#ifndef SRC_PROCFS_DLT_PROCFS_PROCESS_LIST_H_
+#define SRC_PROCFS_DLT_PROCFS_PROCESS_LIST_H_
+
+#include "dlt-procfs-common.h"
+#include "dlt-procfs-process.h"
+
+typedef struct
+{
+ struct DltProcfsProcess *start, *cursor;
+} DltProcfsProcessList;
+
+DltProcfsProcessList *dlt_procfs_create_process_list();
+DltReturnValue dlt_procfs_free_process_list_soft(DltProcfsProcessList *list);
+DltReturnValue dlt_procfs_free_process_list(DltProcfsProcessList *list);
+DltProcfsProcess *dlt_procfs_get_process_at_cursor(DltProcfsProcessList *list);
+DltReturnValue dlt_procfs_increment_cursor(DltProcfsProcessList *list);
+DltReturnValue dlt_procfs_decrement_cursor(DltProcfsProcessList *list);
+DltReturnValue dlt_procfs_reset_cursor(DltProcfsProcessList *list);
+DltReturnValue dlt_procfs_add_process_at_start(DltProcfsProcessList *list, DltProcfsProcess *process);
+DltReturnValue dlt_procfs_add_process_before_cursor(DltProcfsProcessList *list, DltProcfsProcess *process);
+DltReturnValue dlt_procfs_add_process_after_cursor(DltProcfsProcessList *list, DltProcfsProcess *process);
+DltReturnValue dlt_procfs_remove_process_at_cursor_soft(DltProcfsProcessList *list);
+DltReturnValue dlt_procfs_remove_process_at_cursor(DltProcfsProcessList *list);
+
+// DltReturnValue dlt_procfs_remove_process_after_cursor(DltProcfsProcessList *list);
+// DltReturnValue dlt_procfs_remove_first_process(DltProcfsProcessList *list);
+
+#endif /* SRC_PROCFS_DLT_PROCFS_PROCESS_LIST_H_ */
diff --git a/src/procfs/dlt-procfs-process.c b/src/procfs/dlt-procfs-process.c
new file mode 100644
index 0000000..7bb815f
--- /dev/null
+++ b/src/procfs/dlt-procfs-process.c
@@ -0,0 +1,467 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2011-2015, BMW AG
+ *
+ * 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@
+ */
+
+/*!
+ * \author Sven Hassler <sven_hassler@mentor.com>
+ *
+ * \copyright Copyright © 2011-2015 BMW AG. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt-procfs-process.c
+ */
+
+#include "dlt-procfs-process.h"
+#include <pthread.h>
+#include <unistd.h>
+
+DltReturnValue dlt_procfs_read_process_file_to_str(pid_t pid, char **target_str, char *subdir);
+unsigned long int dlt_procfs_read_process_stat_to_ulong(pid_t pid, unsigned int index);
+DltReturnValue dlt_procfs_read_process_stat_cmdline(pid_t pid, char **buffer);
+
+DltReturnValue dlt_procfs_process_update_io_wait(DltProcfsProcess *process, unsigned long int time_dif_ms)
+{
+ if(process == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_process_update_io_wait(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ unsigned long int total_io_wait = dlt_procfs_read_process_stat_to_ulong(process->pid, 42);
+
+ process->io_wait = (total_io_wait - process->last_io_wait) * 1000 / sysconf(_SC_CLK_TCK); // busy milliseconds since last update
+ if(time_dif_ms > 0)
+ process->io_wait = process->io_wait * 1000 / time_dif_ms; // busy milliseconds per second
+
+ process->last_io_wait = total_io_wait;
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_process_update_cpu_time(DltProcfsProcess *process, unsigned long int time_dif_ms)
+{
+ if(process == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_process_update_cpu_time(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ unsigned long int utime = dlt_procfs_read_process_stat_to_ulong(process->pid, 14);
+ unsigned long int stime = dlt_procfs_read_process_stat_to_ulong(process->pid, 15);
+
+ unsigned long total_cpu_time = utime + stime;
+
+ process->cpu_time = (total_cpu_time - process->last_cpu_time) * 1000 / sysconf(_SC_CLK_TCK); // busy milliseconds since last update
+ if(time_dif_ms > 0)
+ process->cpu_time = process->cpu_time * 1000 / time_dif_ms; // busy milliseconds per second
+
+ process->last_cpu_time = total_cpu_time;
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_process_update_rss(DltProcfsProcess *process)
+{
+ if(process == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_process_update_rss(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ process->rss = dlt_procfs_read_process_stat_to_ulong(process->pid, 24);
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_process_update_ctx_switches(DltProcfsProcess *process)
+{
+ if(process == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_process_update_ctx_switches(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ char *buffer, *tok, *last_tok;
+ char *delim = " :\t\n";
+ last_tok = NULL;
+
+ DltReturnValue ret;
+ if((ret = dlt_procfs_read_process_file_to_str(process->pid, &buffer, "status")) < DLT_RETURN_OK) return ret;
+
+ process->ctx_switches = 0;
+
+ tok = strtok(buffer, delim);
+ while(tok != NULL)
+ {
+ if(last_tok != NULL)
+ {
+ if(strcmp(last_tok, "voluntary_ctxt_switches") == 0 || strcmp(last_tok, "nonvoluntary_ctxt_switches") == 0)
+ {
+ char *chk;
+ process->ctx_switches += strtol(tok, &chk, 10);
+
+ if(*chk != '\0')
+ {
+ fprintf(stderr, "Could not parse ctx_switches info from /proc/%d/status", process->pid);
+ free(buffer);
+ return DLT_RETURN_ERROR;
+ }
+ }
+ }
+
+ last_tok = tok;
+ tok = strtok(NULL, delim);
+ }
+
+ free(buffer);
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_process_update_io_bytes(DltProcfsProcess *process)
+{
+ if(process == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_process_update_io_bytes: Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ char *buffer, *tok, *last_tok;
+ char *delim = " :\t\n";
+ last_tok = NULL;
+
+ DltReturnValue ret;
+ if((ret = dlt_procfs_read_process_file_to_str(process->pid, &buffer, "io")) < DLT_RETURN_OK)
+ return ret;
+
+ process->io_bytes = 0;
+
+ tok = strtok(buffer, delim);
+ while(tok != NULL)
+ {
+ if(last_tok != NULL)
+ {
+ if(strcmp(last_tok, "rchar") == 0 || strcmp(last_tok, "wchar") == 0)
+ {
+ char *chk;
+ process->io_bytes += strtoul(tok, &chk, 10);
+
+ if(*chk != '\0')
+ {
+ fprintf(stderr, "Could not parse io_bytes info from /proc/%d/io", process->pid);
+ free(buffer);
+ return DLT_RETURN_ERROR;
+ }
+ }
+ }
+
+ last_tok = tok;
+ tok = strtok(NULL, delim);
+ }
+
+ free(buffer);
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_update_process(DltProcfsProcess *process, unsigned long int time_dif_ms)
+{
+ dlt_procfs_process_update_io_wait(process, time_dif_ms);
+ dlt_procfs_process_update_cpu_time(process, time_dif_ms);
+ dlt_procfs_process_update_rss(process);
+ dlt_procfs_process_update_ctx_switches(process);
+ dlt_procfs_process_update_io_bytes(process);
+
+ return DLT_RETURN_OK;
+}
+
+DltProcfsProcess *dlt_procfs_create_process(int pid)
+{
+ DltProcfsProcess *new_process = malloc(sizeof(DltProcfsProcess));
+ memset(new_process, 0, sizeof(DltProcfsProcess));
+
+ new_process->pid = pid;
+ new_process->ppid = (pid_t)dlt_procfs_read_process_stat_to_ulong(pid, 4);
+
+ dlt_procfs_read_process_file_to_str(pid, &(new_process->command_line), "cmdline");
+ if(new_process->command_line != NULL)
+ if(strlen(new_process->command_line) == 0)
+ {
+ free(new_process->command_line);
+ dlt_procfs_read_process_stat_cmdline(pid, &(new_process->command_line));
+ }
+
+ dlt_procfs_update_process(new_process, 0);
+
+ return new_process;
+}
+
+DltProcfsProcess *dlt_procfs_clone_process(DltProcfsProcess *original)
+{
+ if(original == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_clone_process: Nullpointer parameter\n");
+ return NULL;
+ }
+
+ // DltProcfsProcess *new_process = dlt_procfs_create_process(original->pid);
+ DltProcfsProcess *new_process = malloc(sizeof(DltProcfsProcess));
+ if(new_process == NULL)
+ {
+ fprintf(stderr, "Out of memory\n");
+ return NULL;
+ }
+
+ memcpy(new_process, original, sizeof(DltProcfsProcess));
+
+ if(original->command_line != NULL)
+ {
+ new_process->command_line = malloc(strlen(original->command_line) + 1);
+ if(new_process->command_line == NULL)
+ {
+ fprintf(stderr, "Out of memory\n");
+ return NULL;
+ }
+ strncpy(new_process->command_line, original->command_line, strlen(original->command_line) + 1);
+ }
+ else
+ new_process->command_line = NULL;
+
+ new_process->next = new_process->prev = NULL;
+
+ return new_process;
+}
+
+DltReturnValue dlt_procfs_free_process(DltProcfsProcess *process)
+{
+ if(process == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_free_process: Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ if(process->command_line != NULL)
+ free(process->command_line);
+
+ free(process);
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_print_process(DltProcfsProcess *process)
+{
+ if(process == NULL)
+ {
+ fprintf(stderr, "Error: Nullpointer parameter\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ printf("[PID %d]\n", process->pid);
+ printf(" > PPID : %d\n", process->ppid);
+ printf(" > CMDLINE : %s\n", process->command_line);
+ printf(" > CPUTIME : %lu (busy ms/s)\n", process->cpu_time);
+ printf(" > RSS : %ld\n", process->rss);
+ printf(" > CTXSWTC : %ld\n", process->ctx_switches);
+ printf(" > IOBYTES : %lu\n", process->io_bytes);
+ printf(" > IOWAIT : %ld (%ld)\n", process->io_wait, process->last_io_wait);
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_read_process_file_to_str(pid_t pid, char **target_str, char *subdir)
+{
+ if(target_str == NULL)
+ {
+ fprintf(stderr, "Error: Nullpointer parameter\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ *target_str = NULL;
+
+ if(pid <= 0)
+ {
+ fprintf(stderr, "Error: Invalid PID\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ if(subdir == NULL)
+ {
+ fprintf(stderr, "Error: Nullpointer parameter\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ char filename[BUFFER_SIZE];
+ snprintf(filename, BUFFER_SIZE, "/proc/%d/%s", pid, subdir);
+
+ return dlt_procfs_read_file_compact(filename, target_str);
+}
+
+unsigned long int dlt_procfs_read_process_stat_to_ulong(pid_t pid, unsigned int index)
+{
+ if(pid <= 0)
+ {
+ fprintf(stderr, "dlt_procfs_read_process_stat_to_ulong(): Invalid PID\n");
+ return 0;
+ }
+
+ char *buffer = NULL;
+ DltReturnValue tmp = dlt_procfs_read_process_file_to_str(pid, &buffer, "stat");
+ if(tmp < DLT_RETURN_OK)
+ {
+ if(buffer != NULL)
+ free(buffer);
+
+ return tmp;
+ }
+
+ char *tok = strtok(buffer, " \t\n");
+ unsigned int i = 1, found = 0;
+
+ while(tok != NULL)
+ {
+ if(i == index)
+ {
+ found = 1;
+ break;
+ }
+ i++;
+ tok = strtok(NULL, " \t\n");
+ }
+
+ unsigned long int ret = 0;
+
+ if(found)
+ {
+ char *check = NULL;
+ ret = strtoul(tok, &check, 10);
+ if(*check != '\0')
+ {
+ fprintf(stderr, "dlt_procfs_read_process_stat_to_ulong(): Could not extract token\n");
+ ret = 0;
+ }
+ }
+ else
+ fprintf(stderr, "dlt_procfs_read_process_stat_to_ulong(): Index not found\n");
+
+ free(buffer);
+
+ return ret;
+}
+
+DltReturnValue dlt_procfs_read_process_stat_cmdline(pid_t pid, char **buffer)
+{
+ if(pid <= 0)
+ {
+ fprintf(stderr, "dlt_procfs_read_process_stat_cmdline(): Invalid PID\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ if(buffer == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_read_process_stat_cmdline(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ char *tmp_buffer = NULL;
+ DltReturnValue tmp = dlt_procfs_read_process_file_to_str(pid, &tmp_buffer, "stat");
+ if(tmp < DLT_RETURN_OK)
+ {
+ if(tmp_buffer != NULL)
+ free(tmp_buffer);
+
+ return tmp;
+ }
+
+ char *tok = strtok(tmp_buffer, " \t\n");
+ unsigned int i = 1;
+
+ while(tok != NULL)
+ {
+ if(i == 2)
+ {
+ break;
+ }
+ i++;
+ tok = strtok(NULL, " \t\n");
+ }
+
+ if(i == 2)
+ {
+ (*buffer) = malloc(strlen(tok) + 1);
+ strncpy(*buffer, tok, strlen(tok) + 1);
+ }
+ else
+ {
+ fprintf(stderr, "dlt_procfs_read_process_stat_cmdline(): cmdline entry not found\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ free(tmp_buffer);
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_get_msg_process_update(DltProcfsProcess *process, char *buffer, int maxlen)
+{
+ if(process == NULL || buffer == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_log_process_new(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ snprintf(buffer, maxlen, "%d;%lu;%ld;%ld;%lu;%lu", process->pid, process->cpu_time, process->rss, process->ctx_switches, process->io_bytes, process->io_wait);
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_get_msg_process_new(DltProcfsProcess *process, char *buffer, int maxlen)
+{
+ if(process == NULL || buffer == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_log_process_new(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ snprintf(buffer, maxlen, "%d;%d;%s", process->pid, process->ppid, process->command_line);
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_get_msg_process_stop(DltProcfsProcess *process, char *buffer, int maxlen)
+{
+ if(process == NULL || buffer == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_log_process_new(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ snprintf(buffer, maxlen, "%d", process->pid);
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_get_msg_process_commandline(DltProcfsProcess *process, char *buffer, int maxlen)
+{
+ if(process == NULL || buffer == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_log_process_new(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ snprintf(buffer, maxlen, "%d;%s", process->pid, process->command_line);
+
+ return DLT_RETURN_OK;
+}
diff --git a/src/procfs/dlt-procfs-process.h b/src/procfs/dlt-procfs-process.h
new file mode 100644
index 0000000..92c32db
--- /dev/null
+++ b/src/procfs/dlt-procfs-process.h
@@ -0,0 +1,56 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2011-2015, BMW AG
+ *
+ * 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@
+ */
+
+/*!
+ * \author Sven Hassler <sven_hassler@mentor.com>
+ *
+ * \copyright Copyright © 2011-2015 BMW AG. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt-procfs-process.h
+ */
+
+#ifndef SRC_PROCFS_DLT_PROCFS_PROCESS_H_
+#define SRC_PROCFS_DLT_PROCFS_PROCESS_H_
+
+#include "dlt.h"
+#include "dlt-procfs-common.h"
+#include <stdlib.h>
+
+typedef struct DltProcfsEventWatch DltProcfsEventWatch; // forward declaration
+
+typedef struct DltProcfsProcess
+{
+ pid_t pid, ppid;
+ char *command_line;
+ unsigned long int cpu_time, last_cpu_time, io_wait, last_io_wait, io_bytes;
+ long int rss, ctx_switches;
+
+ struct DltProcfsProcess *next, *prev;
+} DltProcfsProcess;
+
+DltProcfsProcess *dlt_procfs_create_process();
+DltProcfsProcess *dlt_procfs_clone_process(DltProcfsProcess *original);
+DltReturnValue dlt_procfs_free_process(DltProcfsProcess *process);
+DltReturnValue dlt_procfs_print_process(DltProcfsProcess *process);
+DltReturnValue dlt_procfs_update_process(DltProcfsProcess *process, unsigned long int time_dif_ms);
+DltReturnValue dlt_procfs_get_msg_process_new(DltProcfsProcess *process, char *buffer, int maxlen);
+DltReturnValue dlt_procfs_get_msg_process_stop(DltProcfsProcess *process, char *buffer, int maxlen);
+DltReturnValue dlt_procfs_get_msg_process_update(DltProcfsProcess *process, char *buffer, int maxlen);
+DltReturnValue dlt_procfs_get_msg_process_commandline(DltProcfsProcess *process, char *buffer, int maxlen);
+
+#endif /* SRC_PROCFS_DLT_PROCFS_PROCESS_H_ */
diff --git a/src/procfs/dlt-procfs.c b/src/procfs/dlt-procfs.c
new file mode 100644
index 0000000..4396c27
--- /dev/null
+++ b/src/procfs/dlt-procfs.c
@@ -0,0 +1,503 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2011-2015, BMW AG
+ *
+ * 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@
+ */
+
+/*!
+ * \author Sven Hassler <sven_hassler@mentor.com>
+ *
+ * \copyright Copyright © 2011-2015 BMW AG. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt-procfs.c
+ */
+
+#include "dlt-procfs.h"
+#include <signal.h>
+#include <dirent.h>
+#include <time.h>
+#include <unistd.h>
+#include <pthread.h>
+
+DLT_DECLARE_CONTEXT(procfs_ctx);
+
+DltProcfsConfig config;
+
+static volatile sig_atomic_t stop_loop = 0;
+static DltProcfsProcessList *list, *new_process_list, *stopped_process_list, *update_process_list;
+static struct timespec _tmp_time;
+static pthread_mutex_t process_list_mutex;
+
+void dlt_procfs_stop_loops(int sig);
+void dlt_procfs_init_sigterm_handler();
+DltReturnValue dlt_procfs_init_process_lists();
+DltReturnValue dlt_procfs_free_process_lists();
+void *dlt_procfs_start_process_thread();
+DltReturnValue dlt_procfs_process_loop();
+DltReturnValue dlt_procfs_update_process_list(DltProcfsProcessList *list, unsigned long int time_dif_ms);
+void *dlt_procfs_start_irq_thread();
+DltReturnValue dlt_procfs_irq_loop();
+void *dlt_procfs_start_check_thread();
+DltReturnValue dlt_procfs_check_loop();
+DltReturnValue dlt_procfs_log_check_commandlines();
+
+unsigned long int timespec_to_millis(struct timespec *time)
+{
+ return (time->tv_sec) * 1000 + (time->tv_nsec / 1000000);
+}
+
+unsigned long int get_millis()
+{
+ clock_gettime(CLOCK_REALTIME, &_tmp_time);
+ return timespec_to_millis(&_tmp_time);
+}
+
+int main(int argc, char **argv)
+{
+ printf("Launching dlt-procfs...\n");
+
+ if(dlt_procfs_init(argc, argv, &config) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "Initialization error!\n");
+ return -1;
+ }
+
+ dlt_procfs_init_sigterm_handler();
+
+ if(dlt_procfs_init_process_lists() < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "Error occurred initializing process lists\n");
+ return -1;
+ }
+
+ if(pthread_mutex_init(&process_list_mutex, NULL) < 0)
+ {
+ fprintf(stderr, "Error occurred initializing mutex\n");
+ return -1;
+ }
+
+ DLT_REGISTER_APP("PROC", "/proc/-filesystem logger application");
+ DLT_REGISTER_CONTEXT_LL_TS(procfs_ctx, "PROC", "/proc/-filesystem logger context", config.log_level, 0);
+
+ pthread_t process_thread;
+ pthread_t irq_thread;
+ pthread_t check_thread;
+
+ if(pthread_create(&process_thread, NULL, &dlt_procfs_start_process_thread, NULL) != 0)
+ {
+ fprintf(stderr, "Could not create thread\n");
+ return -1;
+ }
+ if(pthread_create(&irq_thread, NULL, &dlt_procfs_start_irq_thread, NULL) != 0)
+ {
+ fprintf(stderr, "Could not create thread\n");
+ return -1;
+ }
+ if(pthread_create(&check_thread, NULL, &dlt_procfs_start_check_thread, NULL) != 0)
+ {
+ fprintf(stderr, "Could not create thread\n");
+ return -1;
+ }
+
+ pthread_join(process_thread, NULL);
+ pthread_join(irq_thread, NULL);
+ pthread_join(check_thread, NULL);
+
+ DLT_UNREGISTER_CONTEXT(procfs_ctx);
+ DLT_UNREGISTER_APP();
+
+ pthread_mutex_destroy(&process_list_mutex);
+
+ dlt_procfs_free_process_lists();
+
+ printf("Done.\n");
+}
+
+void dlt_procfs_init_sigterm_handler()
+{
+ struct sigaction action;
+ memset(&action, 0, sizeof(struct sigaction));
+ action.sa_handler = dlt_procfs_stop_loops;
+
+ sigaction(SIGTERM, &action, NULL);
+}
+
+void dlt_procfs_stop_loops(int sig)
+{
+ if(sig > -1)
+ fprintf(stderr, "dlt-procfs is now terminating due to signal %d...\n", sig);
+ else
+ fprintf(stderr, "dlt-procfs is now terminating due to an error...\n");
+
+ stop_loop = 1;
+}
+
+DltReturnValue dlt_procfs_init_process_lists()
+{
+ if((list = dlt_procfs_create_process_list()) == NULL) return DLT_RETURN_ERROR;
+ if((new_process_list = dlt_procfs_create_process_list()) == NULL) return DLT_RETURN_ERROR;
+ if((stopped_process_list = dlt_procfs_create_process_list()) == NULL) return DLT_RETURN_ERROR;
+ if((update_process_list = dlt_procfs_create_process_list()) == NULL) return DLT_RETURN_ERROR;
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_free_process_lists()
+{
+ DltReturnValue ret = DLT_RETURN_OK;
+
+ if(dlt_procfs_free_process_list(list) < DLT_RETURN_OK)
+ ret = DLT_RETURN_ERROR;
+
+ if(dlt_procfs_free_process_list(new_process_list) < DLT_RETURN_OK)
+ ret = DLT_RETURN_ERROR;
+
+ if(dlt_procfs_free_process_list(stopped_process_list) < DLT_RETURN_OK)
+ ret = DLT_RETURN_ERROR;
+
+ if(dlt_procfs_free_process_list(update_process_list) < DLT_RETURN_OK)
+ ret = DLT_RETURN_ERROR;
+
+ return ret;
+}
+
+void *dlt_procfs_start_process_thread()
+{
+ if(dlt_procfs_process_loop() < DLT_RETURN_OK)
+ dlt_procfs_stop_loops(-1);
+
+ return NULL;
+}
+
+DltReturnValue dlt_procfs_process_loop()
+{
+ static unsigned long int old_millis, sleep_millis, dif_millis;
+
+ old_millis = get_millis();
+
+ while(!stop_loop)
+ {
+ /*DltReturnValue ret = */ dlt_procfs_update_process_list(list, config.process_log_interval);
+ //if(ret < DLT_RETURN_OK)
+ // return ret;
+
+ dif_millis = get_millis() - old_millis;
+
+ if(dif_millis >= (unsigned long)(config.process_log_interval))
+ sleep_millis = 0;
+ else
+ sleep_millis = config.process_log_interval - dif_millis;
+
+ usleep(sleep_millis * 1000);
+
+ old_millis = get_millis();
+ }
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_log_list(DltProcfsProcessList *list, DltReturnValue(*process_callback)(DltProcfsProcess*, char*, int), char *title, int delete_elements)
+{
+ if(list == NULL || process_callback == NULL || title == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_log_list(): Nullpointer parameter\n");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ dlt_procfs_reset_cursor(list);
+ if(list->cursor == NULL)
+ return DLT_RETURN_OK; // list empty; nothing to do
+
+ DltReturnValue ret;
+ DltContextData data;
+
+ char buffer[BUFFER_SIZE];
+ buffer[0] = '\0';
+
+ if((ret = dlt_user_log_write_start(&procfs_ctx, &data, config.log_level)) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "dlt_procfs_log_list(): dlt_user_log_write_start() returned error.\n");
+ return ret;
+ }
+
+ if((ret = dlt_user_log_write_string(&data, title)) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "dlt_procfs_log_list(): dlt_user_log_write_string() returned error.\n");
+ return ret;
+ }
+
+ do
+ {
+ if((ret = (*process_callback)(list->cursor, buffer, sizeof(buffer) - 1)) < DLT_RETURN_OK)
+ return ret;
+
+ if((ret = dlt_user_log_write_string(&data, buffer)) < DLT_RETURN_OK)
+ {
+ /* Log buffer full => Write log and start new one*/
+ if((ret = dlt_user_log_write_finish(&data)) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "dlt_procfs_log_list(): dlt_user_log_write_finish() returned error.\n");
+ return ret;
+ }
+
+ if((ret = dlt_user_log_write_start(&procfs_ctx, &data, config.log_level)) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "dlt_procfs_log_list(): dlt_user_log_write_start() returned error.\n");
+ return ret;
+ }
+
+ if((ret = dlt_user_log_write_string(&data, title)) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "dlt_procfs_log_list(): dlt_user_log_write_string() returned error.\n");
+ return ret;
+ }
+ }
+ else if(delete_elements)
+ {
+ if((ret = dlt_procfs_remove_process_at_cursor(list)) < DLT_RETURN_OK)
+ return ret;
+ }
+ else
+ {
+ list->cursor = list->cursor->next;
+ }
+ }
+ while(list->cursor != NULL);
+
+ if((ret = dlt_user_log_write_finish(&data)) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "dlt_procfs_log_list(): dlt_user_log_write_finish() returned error.\n");
+ return ret;
+ }
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_update_process_list(DltProcfsProcessList *list, unsigned long int time_dif_ms)
+{
+ static char *strchk;
+ static DltReturnValue tmp_ret;
+ static struct dirent *current_dir;
+ static pid_t current_dir_pid;
+
+ if(list == NULL)
+ {
+ fprintf(stderr, "dlt_procfs_update_process_list(): Nullpointer parameter");
+ return DLT_RETURN_WRONG_PARAMETER;
+ }
+
+ DIR *proc_dir = opendir("/proc");
+ if(proc_dir == NULL)
+ {
+ dlt_log(LOG_ERR, "Could not open /proc/ !\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ current_dir = readdir(proc_dir);
+ dlt_procfs_reset_cursor(list);
+
+ int debug_process_count = 0;
+
+ if(pthread_mutex_lock(&process_list_mutex) < 0)
+ {
+ fprintf(stderr, "Can't lock mutex\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ while(1)
+ {
+ if(current_dir == NULL)
+ {
+ /* no more active processes.. delete all remaining processes in the list */
+ if(list->cursor != NULL)
+ while(list->cursor != NULL)
+ {
+ if((tmp_ret = dlt_procfs_add_process_after_cursor(stopped_process_list, dlt_procfs_clone_process(list->cursor))) < DLT_RETURN_OK)
+ return tmp_ret;
+
+ dlt_procfs_remove_process_at_cursor(list);
+ }
+
+ break;
+ }
+
+ current_dir_pid = strtol(current_dir->d_name, &strchk, 10);
+ if(*strchk != '\0' || current_dir_pid <= 0)
+ {
+ /* no valid PID */
+ current_dir = readdir(proc_dir); // next process in proc-fs
+ continue;
+ }
+
+ /* compare the /proc/-filesystem with our process-list */
+ if(list->cursor == NULL || current_dir_pid < list->cursor->pid) // New Process
+ {
+ DltProcfsProcess *new_process = dlt_procfs_create_process(current_dir_pid);
+ if(new_process == NULL)
+ {
+ fprintf(stderr, "Error: Could not create process (out of memory?)\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ if((tmp_ret = dlt_procfs_add_process_before_cursor(list, new_process)) < DLT_RETURN_OK)
+ return tmp_ret;
+
+ if((tmp_ret = dlt_procfs_add_process_before_cursor(new_process_list, dlt_procfs_clone_process(new_process))) < DLT_RETURN_OK)
+ return tmp_ret;
+
+ current_dir = readdir(proc_dir); // next process in proc-fs
+ debug_process_count++;
+ }
+ else if(current_dir_pid > list->cursor->pid) // Process ended
+ {
+ if((tmp_ret = dlt_procfs_add_process_after_cursor(stopped_process_list, dlt_procfs_clone_process(list->cursor))) < DLT_RETURN_OK)
+ return tmp_ret;
+
+ if((tmp_ret = dlt_procfs_remove_process_at_cursor(list)) < DLT_RETURN_OK)
+ return tmp_ret;
+ }
+ else if(current_dir_pid == list->cursor->pid) // Staying process
+ {
+ /* update data */
+ if((tmp_ret = dlt_procfs_update_process(list->cursor, time_dif_ms)) < DLT_RETURN_OK)
+ return tmp_ret;
+
+ if(list->cursor->cpu_time > 0) // only log active processes
+ if((tmp_ret = dlt_procfs_add_process_after_cursor(update_process_list, dlt_procfs_clone_process(list->cursor))) < DLT_RETURN_OK)
+ {
+ fprintf(stderr, "dlt_procfs_update_process_list: Can't add process to list updateProcessList\n");
+ return tmp_ret;
+ }
+
+ if((tmp_ret = dlt_procfs_increment_cursor(list)) < DLT_RETURN_OK) // next process in list
+ return tmp_ret;
+
+ current_dir = readdir(proc_dir); // next process in proc-fs
+ debug_process_count++;
+ }
+ }
+
+ if(pthread_mutex_unlock(&process_list_mutex) < 0)
+ {
+ fprintf(stderr, "Can't unlock mutex\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ /* Log new processes */
+ if((tmp_ret = dlt_procfs_log_list(new_process_list, &dlt_procfs_get_msg_process_new, "NEW", 1)) < DLT_RETURN_OK)
+ return tmp_ret;
+
+ /* Log stopped processes */
+ if((tmp_ret = dlt_procfs_log_list(stopped_process_list, &dlt_procfs_get_msg_process_stop, "STP", 1)) < DLT_RETURN_OK)
+ return tmp_ret;
+
+ /* Log active processes */
+ if((tmp_ret = dlt_procfs_log_list(update_process_list, &dlt_procfs_get_msg_process_update, "ACT", 1)) < DLT_RETURN_OK)
+ return tmp_ret;
+
+ if(closedir(proc_dir) < 0)
+ fprintf(stderr, "Could not close /proc/ directory\n");
+
+ return DLT_RETURN_OK;
+}
+
+void *dlt_procfs_start_irq_thread()
+{
+ if(dlt_procfs_irq_loop() < DLT_RETURN_OK)
+ dlt_procfs_stop_loops(-1);
+
+ return NULL;
+}
+
+DltReturnValue dlt_procfs_irq_loop()
+{
+ static unsigned long int old_millis, sleep_millis, dif_millis;
+
+ old_millis = get_millis();
+
+ while(!stop_loop)
+ {
+ /*DltReturnValue ret = */ dlt_procfs_log_interrupts(&procfs_ctx, config.log_level);
+ //if(ret < DLT_RETURN_OK)
+ // return ret;
+
+ dif_millis = get_millis() - old_millis;
+
+ if(dif_millis >= (unsigned long)(config.irq_log_interval))
+ sleep_millis = 0;
+ else
+ sleep_millis = config.irq_log_interval - dif_millis;
+
+ usleep(sleep_millis * 1000);
+
+ old_millis = get_millis();
+ }
+
+ return DLT_RETURN_OK;
+}
+
+void *dlt_procfs_start_check_thread()
+{
+ if(dlt_procfs_check_loop() < DLT_RETURN_OK)
+ dlt_procfs_stop_loops(-1);
+
+ return NULL;
+}
+
+DltReturnValue dlt_procfs_check_loop()
+{
+ static unsigned long int old_millis, sleep_millis, dif_millis;
+
+ old_millis = get_millis();
+
+ while(!stop_loop)
+ {
+ /*DltReturnValue ret = */ dlt_procfs_log_check_commandlines();
+ //if(ret < DLT_RETURN_OK)
+ // return ret;
+
+ dif_millis = get_millis() - old_millis;
+
+ if(dif_millis >= (unsigned long)(config.check_log_interval))
+ sleep_millis = 0;
+ else
+ sleep_millis = config.check_log_interval - dif_millis;
+
+ usleep(sleep_millis * 1000);
+
+ old_millis = get_millis();
+ }
+
+ return DLT_RETURN_OK;
+}
+
+DltReturnValue dlt_procfs_log_check_commandlines()
+{
+ if(pthread_mutex_lock(&process_list_mutex) < 0)
+ {
+ fprintf(stderr, "Can't lock mutex\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ DltReturnValue ret = dlt_procfs_log_list(list, dlt_procfs_get_msg_process_commandline, "CHK", 0);
+
+ if(pthread_mutex_unlock(&process_list_mutex) < 0)
+ {
+ fprintf(stderr, "Can't unlock mutex\n");
+ return DLT_RETURN_ERROR;
+ }
+
+ return ret;
+}
diff --git a/src/procfs/dlt-procfs.conf b/src/procfs/dlt-procfs.conf
new file mode 100644
index 0000000..5abd2a7
--- /dev/null
+++ b/src/procfs/dlt-procfs.conf
@@ -0,0 +1,18 @@
+# Configuration file for DLT /proc/-filesystem logger
+#
+
+########################################################################
+# General configuration
+########################################################################
+
+# The interval in milliseconds of how often process updates should be logged. (Default: 1000)
+process_interval = 1000
+
+# The interval in milliseconds of how often interrupt stats should be logged. (Default: 3000)
+irq_interval = 3000
+
+# The interval in milliseconds of how often the commandlines of all processes should be logged. (Default: 10000)
+check_interval = 10000
+
+# The used log level. -1 = DEFAULT, 0 = OFF, [...], 6 = VERBOSE (Default: 4)
+log_level = 4 \ No newline at end of file
diff --git a/src/procfs/dlt-procfs.h b/src/procfs/dlt-procfs.h
new file mode 100644
index 0000000..637aecb
--- /dev/null
+++ b/src/procfs/dlt-procfs.h
@@ -0,0 +1,61 @@
+/*
+ * @licence app begin@
+ * SPDX license identifier: MPL-2.0
+ *
+ * Copyright (C) 2011-2015, BMW AG
+ *
+ * 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@
+ */
+
+/*!
+ * \author Sven Hassler <sven_hassler@mentor.com>
+ *
+ * \copyright Copyright © 2011-2015 BMW AG. \n
+ * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
+ *
+ * \file dlt-procfs.h
+ */
+
+#ifndef SRC_PROCFS_DLT_PROCFS_H_
+#define SRC_PROCFS_DLT_PROCFS_H_
+
+#include "dlt.h"
+#include "dlt-procfs-common.h"
+#include "dlt-procfs-process.h"
+#include "dlt-procfs-process-list.h"
+#include "dlt-procfs-interrupt.h"
+#include <syslog.h>
+
+// CONSTANT DEFINITIONS
+#define DEFAULT_CONF_FILE ( CONFIGURATION_FILES_DIR "/dlt-procfs.conf")
+
+#define COMMAND_LINE_SIZE 1024
+
+// STRUCTURES
+typedef struct
+{
+ char *configurationFileName;
+ int customConfigFile;
+} DltProcfsOptions;
+
+typedef struct
+{
+ int process_log_interval, irq_log_interval, check_log_interval;
+ DltLogLevelType log_level;
+} DltProcfsConfig;
+
+// FUNCTION DECLARATIONS:
+DltReturnValue dlt_procfs_read_command_line(DltProcfsOptions *options, int argc, char **argv);
+DltReturnValue dlt_procfs_read_configuration_file(DltProcfsConfig *config, char *file_name);
+void dlt_procfs_free_cli_options(DltProcfsOptions *options);
+DltReturnValue dlt_procfs_init(int argc, char **argv, DltProcfsConfig *config);
+
+#endif /* SRC_PROCFS_DLT_PROCFS_H_ */