LCOV - code coverage report
Current view: top level - daemon - dlt_daemon_common.c (source / functions) Coverage Total Hit
Test: dlt_final_coverage.info Lines: 56.3 % 623 351
Test Date: 2025-11-25 01:57:00 Functions: 71.9 % 32 23

            Line data    Source code
       1              : /*
       2              :  * SPDX license identifier: MPL-2.0
       3              :  *
       4              :  * Copyright (C) 2011-2015, BMW AG
       5              :  *
       6              :  * This file is part of COVESA Project DLT - Diagnostic Log and Trace.
       7              :  *
       8              :  * This Source Code Form is subject to the terms of the
       9              :  * Mozilla Public License (MPL), v. 2.0.
      10              :  * If a copy of the MPL was not distributed with this file,
      11              :  * You can obtain one at http://mozilla.org/MPL/2.0/.
      12              :  *
      13              :  * For further information see http://www.covesa.org/.
      14              :  */
      15              : 
      16              : /*!
      17              :  * \author Alexander Wenzel <alexander.aw.wenzel@bmw.de>
      18              :  *
      19              :  * \copyright Copyright © 2011-2015 BMW AG. \n
      20              :  * License MPL-2.0: Mozilla Public License version 2.0 http://mozilla.org/MPL/2.0/.
      21              :  *
      22              :  * \file dlt_daemon_common.c
      23              :  */
      24              : 
      25              : /*******************************************************************************
      26              : **                                                                            **
      27              : **  SRC-MODULE: dlt_daemon_common.c                                           **
      28              : **                                                                            **
      29              : **  TARGET    : linux                                                         **
      30              : **                                                                            **
      31              : **  PROJECT   : DLT                                                           **
      32              : **                                                                            **
      33              : **  AUTHOR    : Alexander Wenzel Alexander.AW.Wenzel@bmw.de                   **
      34              : **              Markus Klein                                                  **
      35              : **                                                                            **
      36              : **  PURPOSE   :                                                               **
      37              : **                                                                            **
      38              : **  REMARKS   :                                                               **
      39              : **                                                                            **
      40              : **  PLATFORM DEPENDANT [yes/no]: yes                                          **
      41              : **                                                                            **
      42              : **  TO BE CHANGED BY USER [yes/no]: no                                        **
      43              : **                                                                            **
      44              : *******************************************************************************/
      45              : 
      46              : /*******************************************************************************
      47              : **                      Author Identity                                       **
      48              : ********************************************************************************
      49              : **                                                                            **
      50              : ** Initials     Name                       Company                            **
      51              : ** --------     -------------------------  ---------------------------------- **
      52              : **  aw          Alexander Wenzel           BMW                                **
      53              : **  mk          Markus Klein               Fraunhofer ESK                     **
      54              : *******************************************************************************/
      55              : 
      56              : /*******************************************************************************
      57              : **                      Revision Control History                              **
      58              : *******************************************************************************/
      59              : 
      60              : /*
      61              :  * $LastChangedRevision: 1670 $
      62              :  * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $
      63              :  * $LastChangedBy$
      64              :  * Initials    Date         Comment
      65              :  * aw          13.01.2010   initial
      66              :  */
      67              : 
      68              : #include <stdbool.h>
      69              : #include <stdio.h>
      70              : #include <stdlib.h>
      71              : #include <string.h>
      72              : #include <syslog.h>
      73              : #include <errno.h>
      74              : #include <unistd.h>
      75              : #include <fcntl.h>
      76              : 
      77              : #include <sys/socket.h> /* send() */
      78              : 
      79              : #include "dlt_types.h"
      80              : #include "dlt_log.h"
      81              : #include "dlt_daemon_common.h"
      82              : #include "dlt_daemon_common_cfg.h"
      83              : #include "dlt_user_shared.h"
      84              : #include "dlt_user_shared_cfg.h"
      85              : #include "dlt-daemon.h"
      86              : 
      87              : #include "dlt_daemon_socket.h"
      88              : #include "dlt_daemon_serial.h"
      89              : 
      90              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
      91              : #   include <systemd/sd-daemon.h>
      92              : #endif
      93              : 
      94              : char *app_recv_buffer = NULL; /* pointer to receiver buffer for application msges */
      95              : 
      96            0 : static int dlt_daemon_cmp_apid(const void *m1, const void *m2)
      97              : {
      98          132 :     if ((m1 == NULL) || (m2 == NULL))
      99              :         return -1;
     100              : 
     101              :     DltDaemonApplication *mi1 = (DltDaemonApplication *)m1;
     102              :     DltDaemonApplication *mi2 = (DltDaemonApplication *)m2;
     103              : 
     104          132 :     return memcmp(mi1->apid, mi2->apid, DLT_ID_SIZE);
     105              : }
     106              : 
     107          471 : static int dlt_daemon_cmp_apid_ctid(const void *m1, const void *m2)
     108              : {
     109          471 :     if ((m1 == NULL) || (m2 == NULL))
     110              :         return -1;
     111              : 
     112              :     int ret, cmp;
     113              :     DltDaemonContext *mi1 = (DltDaemonContext *)m1;
     114              :     DltDaemonContext *mi2 = (DltDaemonContext *)m2;
     115              : 
     116          471 :     cmp = memcmp(mi1->apid, mi2->apid, DLT_ID_SIZE);
     117              : 
     118          471 :     if (cmp < 0)
     119              :         ret = -1;
     120          471 :     else if (cmp == 0)
     121          471 :         ret = memcmp(mi1->ctid, mi2->ctid, DLT_ID_SIZE);
     122              :     else
     123              :         ret = 1;
     124              : 
     125              :     return ret;
     126              : }
     127              : 
     128          474 : DltDaemonRegisteredUsers *dlt_daemon_find_users_list(DltDaemon *daemon,
     129              :                                                      char *ecu,
     130              :                                                      int verbose)
     131              : {
     132          474 :     PRINT_FUNCTION_VERBOSE(verbose);
     133              : 
     134              :     int i = 0;
     135              : 
     136          474 :     if ((daemon == NULL) || (ecu == NULL)) {
     137            0 :         dlt_vlog(LOG_ERR, "%s: Wrong parameters", __func__);
     138            0 :         return (DltDaemonRegisteredUsers *)NULL;
     139              :     }
     140              : 
     141          476 :     for (i = 0; i < daemon->num_user_lists; i++)
     142          444 :         if (strncmp(ecu, daemon->user_list[i].ecu, DLT_ID_SIZE) == 0)
     143          442 :             return &daemon->user_list[i];
     144              : 
     145           32 :     dlt_vlog(LOG_ERR, "Cannot find user list for ECU: %4s\n", ecu);
     146           32 :     return (DltDaemonRegisteredUsers *)NULL;
     147              : }
     148              : 
     149              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
     150              : 
     151              : static int dlt_daemon_cmp_log_settings(const void *lhs, const void *rhs) {
     152              :     if ((lhs == NULL) || (rhs == NULL))
     153              :         return -1;
     154              : 
     155              :     DltDaemonContextLogSettings *settings1 = (DltDaemonContextLogSettings *)lhs;
     156              :     DltDaemonContextLogSettings *settings2 = (DltDaemonContextLogSettings *)rhs;
     157              : 
     158              :     int cmp = memcmp(settings1->apid, settings2->apid, DLT_ID_SIZE);
     159              : 
     160              :     if (cmp < 0)
     161              :         return -1;
     162              :     else if (cmp == 0)
     163              :         return memcmp(settings1->ctid, settings2->ctid, DLT_ID_SIZE);
     164              :     else
     165              :         return 1;
     166              : }
     167              : 
     168              : /**
     169              :  * Find configuration for app/ctx id specific log settings configuration
     170              :  * @param daemon pointer to dlt daemon struct
     171              :  * @param apid application id to use
     172              :  * @param ctid context id to use, can be NULL
     173              :  * @return pointer to log settings if found, otherwise NULL
     174              :  */
     175              : DltDaemonContextLogSettings *dlt_daemon_find_configured_app_id_ctx_id_settings(
     176              :     const DltDaemon *daemon, const char *apid, const char *ctid) {
     177              :     DltDaemonContextLogSettings *app_id_settings = NULL;
     178              :     for (int i = 0; i < daemon->num_app_id_log_level_settings; ++i) {
     179              :         DltDaemonContextLogSettings *settings = &daemon->app_id_log_level_settings[i];
     180              : 
     181              :         if (strncmp(apid, settings->apid, DLT_ID_SIZE) != 0) {
     182              :             if (app_id_settings != NULL)
     183              :                 return app_id_settings;
     184              :             continue;
     185              :         }
     186              : 
     187              :         if (strlen(settings->ctid) == 0) {
     188              :             app_id_settings = settings;
     189              :         }
     190              : 
     191              :         if (ctid == NULL || strlen(ctid) == 0) {
     192              :             if (app_id_settings != NULL) {
     193              :                 return app_id_settings;
     194              :             }
     195              :         } else {
     196              :             if (strncmp(ctid, settings->ctid, DLT_ID_SIZE) == 0) {
     197              :                 return settings;
     198              :             }
     199              :         }
     200              :     }
     201              : 
     202              :     return app_id_settings;
     203              : }
     204              : 
     205              : /**
     206              :  * Find configured log levels in a given DltDaemonApplication for the passed context id.
     207              :  * @param app The application settings which contain the previously loaded ap id settings
     208              :  * @param ctid The context id to find.
     209              :  * @return Pointer to DltDaemonApplicationLogSettings containing the log level
     210              :  *         for the requested application or NULL if none found.
     211              :  */
     212              : DltDaemonContextLogSettings *dlt_daemon_find_app_log_level_config(
     213              :     const DltDaemonApplication *const app, const char *const ctid) {
     214              : 
     215              :     if (NULL == ctid)
     216              :         return NULL;
     217              : 
     218              :     DltDaemonContextLogSettings settings;
     219              :     memcpy(settings.apid, app->apid, DLT_ID_SIZE);
     220              :     memcpy(settings.ctid, ctid, DLT_ID_SIZE);
     221              : 
     222              :     DltDaemonContextLogSettings* log_settings = NULL;
     223              :     log_settings =
     224              :         (DltDaemonContextLogSettings *)bsearch(
     225              :             &settings, app->context_log_level_settings,
     226              :             (size_t)app->num_context_log_level_settings,
     227              :             sizeof(DltDaemonContextLogSettings),
     228              :             dlt_daemon_cmp_log_settings);
     229              :     return log_settings;
     230              : }
     231              : 
     232              : #endif
     233              : 
     234              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     235              : int dlt_daemon_compare_trace_load_settings(const void *a, const void *b) {
     236              :     const DltTraceLoadSettings *s1 = (const DltTraceLoadSettings *)a;
     237              :     const DltTraceLoadSettings *s2 = (const DltTraceLoadSettings *)b;
     238              : 
     239              :     int cmp = strncmp(s1->apid, s2->apid, DLT_ID_SIZE);
     240              :     if (cmp != 0) {
     241              :         return cmp;
     242              :     }
     243              : 
     244              :     return strncmp(s1->ctid, s2->ctid, DLT_ID_SIZE);
     245              : }
     246              : 
     247              : DltReturnValue dlt_daemon_find_preconfigured_trace_load_settings(
     248              :     DltDaemon *const daemon, const char *apid, const char *ctid, DltTraceLoadSettings **settings, int *num_settings, int verbose)
     249              : {
     250              :     PRINT_FUNCTION_VERBOSE(verbose);
     251              :     int i;
     252              :     *num_settings = 0;
     253              :     *settings = NULL;
     254              : 
     255              :     if ((daemon == NULL) || (apid == NULL)) {
     256              :         dlt_vlog(LOG_ERR, "%s: Wrong parameters", __func__);
     257              :         return DLT_RETURN_WRONG_PARAMETER;
     258              :     }
     259              : 
     260              :     if (NULL == daemon->preconfigured_trace_load_settings || daemon->preconfigured_trace_load_settings_count == 0) {
     261              :         return DLT_RETURN_OK;
     262              :     }
     263              : 
     264              :     for (i = 0; i < daemon->preconfigured_trace_load_settings_count; ++i) {
     265              :         // check if we can exit already, the trace load settings are sorted
     266              :         // and if the apid does not match anymore, but we already have settings
     267              :         // means we collected all settings
     268              :         if (strncmp(apid, daemon->preconfigured_trace_load_settings[i].apid, DLT_ID_SIZE) != 0) {
     269              :             if ((*num_settings) != 0)
     270              :                 break;
     271              :             continue;
     272              :         }
     273              : 
     274              :         // If a ctid is passed, we only want to return entries where both match
     275              :         if (ctid != NULL && strlen(ctid) > 0) {
     276              :             if (strncmp(ctid, daemon->preconfigured_trace_load_settings[i].ctid, DLT_ID_SIZE) != 0) {
     277              :                 continue;
     278              :             }
     279              :         }
     280              : 
     281              :         // Reallocate memory for the settings array with an additional slot for the new setting
     282              :         DltTraceLoadSettings *temp = realloc(*settings, (*num_settings + 1) * sizeof(DltTraceLoadSettings));
     283              :         if (temp == NULL) {
     284              :             dlt_vlog(LOG_ERR, "Failed to allocate memory for trace load settings\n");
     285              :             free(*settings); // Free any previously allocated memory
     286              :             *settings = NULL;
     287              :             *num_settings = 0;
     288              :             return DLT_RETURN_ERROR;
     289              :         }
     290              :         *settings = temp;
     291              :         // Copy preconfigured trace load settings into the app settings
     292              :         (*settings)[*num_settings] = daemon->preconfigured_trace_load_settings[i];
     293              :         (*num_settings)++;
     294              :     }
     295              : 
     296              :     qsort(*settings, (size_t)*num_settings, sizeof(DltTraceLoadSettings),
     297              :           dlt_daemon_compare_trace_load_settings);
     298              :     return DLT_RETURN_OK;
     299              : }
     300              : #endif
     301              : 
     302            9 : int dlt_daemon_init_runtime_configuration(DltDaemon *daemon, const char *runtime_directory, int verbose)
     303              : {
     304            9 :     PRINT_FUNCTION_VERBOSE(verbose);
     305              :     size_t append_length = 0;
     306              : 
     307            9 :     if (daemon == NULL)
     308              :         return DLT_RETURN_ERROR;
     309              : 
     310              :     /* Default */
     311            9 :     daemon->mode = DLT_USER_MODE_EXTERNAL;
     312              : 
     313            9 :     if (runtime_directory == NULL)
     314              :         return DLT_RETURN_ERROR;
     315              : 
     316              :     /* prepare filenames for configuration */
     317              :     append_length = PATH_MAX - sizeof(DLT_RUNTIME_APPLICATION_CFG);
     318              : 
     319            9 :     if (runtime_directory[0]) {
     320            0 :         strncpy(daemon->runtime_application_cfg, runtime_directory, append_length);
     321            0 :         daemon->runtime_application_cfg[append_length] = 0;
     322              :     }
     323              :     else {
     324            9 :         strncpy(daemon->runtime_application_cfg, DLT_RUNTIME_DEFAULT_DIRECTORY, append_length);
     325            9 :         daemon->runtime_application_cfg[append_length] = 0;
     326              :     }
     327              : 
     328            9 :     strcat(daemon->runtime_application_cfg, DLT_RUNTIME_APPLICATION_CFG); /* strcat uncritical here, because max length already checked */
     329              : 
     330              :     append_length = PATH_MAX - sizeof(DLT_RUNTIME_CONTEXT_CFG);
     331              : 
     332            9 :     if (runtime_directory[0]) {
     333            0 :         strncpy(daemon->runtime_context_cfg, runtime_directory, append_length);
     334            0 :         daemon->runtime_context_cfg[append_length] = 0;
     335              :     }
     336              :     else {
     337            9 :         strncpy(daemon->runtime_context_cfg, DLT_RUNTIME_DEFAULT_DIRECTORY, append_length);
     338            9 :         daemon->runtime_context_cfg[append_length] = 0;
     339              :     }
     340              : 
     341            9 :     strcat(daemon->runtime_context_cfg, DLT_RUNTIME_CONTEXT_CFG); /* strcat uncritical here, because max length already checked */
     342              : 
     343              :     append_length = PATH_MAX - sizeof(DLT_RUNTIME_CONFIGURATION);
     344              : 
     345            9 :     if (runtime_directory[0]) {
     346            0 :         strncpy(daemon->runtime_configuration, runtime_directory, append_length);
     347            0 :         daemon->runtime_configuration[append_length] = 0;
     348              :     }
     349              :     else {
     350            9 :         strncpy(daemon->runtime_configuration, DLT_RUNTIME_DEFAULT_DIRECTORY, append_length);
     351            9 :         daemon->runtime_configuration[append_length] = 0;
     352              :     }
     353              : 
     354            9 :     strcat(daemon->runtime_configuration, DLT_RUNTIME_CONFIGURATION); /* strcat uncritical here, because max length already checked */
     355              : 
     356            9 :     return DLT_RETURN_OK;
     357              : }
     358              : 
     359           17 : int dlt_daemon_init(DltDaemon *daemon,
     360              :                     unsigned long RingbufferMinSize,
     361              :                     unsigned long RingbufferMaxSize,
     362              :                     unsigned long RingbufferStepSize,
     363              :                     const char *runtime_directory,
     364              :                     int InitialContextLogLevel,
     365              :                     int InitialContextTraceStatus,
     366              :                     int ForceLLTS,
     367              :                     int verbose)
     368              : {
     369           17 :     PRINT_FUNCTION_VERBOSE(verbose);
     370              : 
     371           17 :     if ((daemon == NULL) || (runtime_directory == NULL))
     372              :         return -1;
     373              : 
     374           17 :     daemon->user_list = NULL;
     375           17 :     daemon->num_user_lists = 0;
     376              : 
     377           17 :     daemon->default_log_level = (int8_t) InitialContextLogLevel;
     378           17 :     daemon->default_trace_status = (int8_t) InitialContextTraceStatus;
     379           17 :     daemon->force_ll_ts = (int8_t) ForceLLTS;
     380              : 
     381           17 :     daemon->overflow_counter = 0;
     382              : 
     383           17 :     daemon->runtime_context_cfg_loaded = 0;
     384              : 
     385           17 :     daemon->connectionState = 0; /* no logger connected */
     386              : 
     387           17 :     daemon->state = DLT_DAEMON_STATE_INIT; /* initial logging state */
     388              : 
     389              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     390              :     daemon->preconfigured_trace_load_settings = NULL;
     391              :     daemon->bytes_sent = 0;
     392              :     daemon->bytes_recv = 0;
     393              : #endif
     394              : 
     395           17 :     daemon->sendserialheader = 0;
     396           17 :     daemon->timingpackets = 0;
     397              : 
     398           17 :     dlt_set_id(daemon->ecuid, "");
     399              : 
     400              :     /* initialize ring buffer for client connection */
     401           17 :     dlt_vlog(LOG_INFO, "Ringbuffer configuration: %lu/%lu/%lu\n",
     402              :              RingbufferMinSize, RingbufferMaxSize, RingbufferStepSize);
     403              : 
     404           17 :     if (dlt_buffer_init_dynamic(&(daemon->client_ringbuffer),
     405              :                                 (uint32_t) RingbufferMinSize,
     406              :                                 (uint32_t) RingbufferMaxSize,
     407              :                                 (uint32_t) RingbufferStepSize) < DLT_RETURN_OK)
     408              :         return -1;
     409              : 
     410           17 :     daemon->storage_handle = NULL;
     411              : #ifdef DLT_SYSTEMD_WATCHDOG_ENFORCE_MSG_RX_ENABLE
     412              :     daemon->received_message_since_last_watchdog_interval = 0;
     413              : #endif
     414           17 :     return 0;
     415              : }
     416              : 
     417            9 : int dlt_daemon_free(DltDaemon *daemon, int verbose)
     418              : {
     419              :     int i = 0;
     420              :     DltDaemonRegisteredUsers *user_list = NULL;
     421              : 
     422            9 :     PRINT_FUNCTION_VERBOSE(verbose);
     423              : 
     424            9 :     if ((daemon == NULL) || (daemon->user_list == NULL))
     425              :         return -1;
     426              : 
     427              :     /* free all registered user information */
     428           19 :     for (i = 0; i < daemon->num_user_lists; i++) {
     429           10 :         user_list = &daemon->user_list[i];
     430              : 
     431           10 :         if (user_list != NULL) {
     432              :             /* ignore return values */
     433           10 :             dlt_daemon_contexts_clear(daemon, user_list->ecu, verbose);
     434           10 :             dlt_daemon_applications_clear(daemon, user_list->ecu, verbose);
     435              :         }
     436              :     }
     437              : 
     438            9 :     free(daemon->user_list);
     439              : 
     440              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
     441              :     if (daemon->app_id_log_level_settings != NULL) {
     442              :       free(daemon->app_id_log_level_settings);
     443              :     }
     444              : #endif
     445              : 
     446            9 :     if (app_recv_buffer)
     447            9 :         free(app_recv_buffer);
     448              : 
     449              :     /* free ringbuffer */
     450            9 :     dlt_buffer_free_dynamic(&(daemon->client_ringbuffer));
     451              : 
     452            9 :     return 0;
     453              : }
     454              : 
     455           18 : int dlt_daemon_init_user_information(DltDaemon *daemon,
     456              :                                      DltGateway *gateway,
     457              :                                      int gateway_mode,
     458              :                                      int verbose)
     459              : {
     460              :     int nodes = 1;
     461              :     int i = 1;
     462              : 
     463           18 :     PRINT_FUNCTION_VERBOSE(verbose);
     464              : 
     465           18 :     if ((daemon == NULL) || ((gateway_mode == 1) && (gateway == NULL)))
     466              :         return DLT_RETURN_ERROR;
     467              : 
     468           18 :     if (gateway_mode == 0) {
     469              :         /* initialize application list */
     470           17 :         daemon->user_list = calloc((size_t) nodes, sizeof(DltDaemonRegisteredUsers));
     471              : 
     472           17 :         if (daemon->user_list == NULL) {
     473            0 :             dlt_log(LOG_ERR, "Allocating memory for user information");
     474            0 :             return DLT_RETURN_ERROR;
     475              :         }
     476              : 
     477           17 :         dlt_set_id(daemon->user_list[0].ecu, daemon->ecuid);
     478           17 :         daemon->num_user_lists = 1;
     479              :     }
     480              :     else { /* gateway is active */
     481            1 :         nodes += gateway->num_connections;
     482              : 
     483              :         /* initialize application list */
     484            1 :         daemon->user_list = calloc((size_t) nodes, sizeof(DltDaemonRegisteredUsers));
     485              : 
     486            1 :         if (daemon->user_list == NULL) {
     487            0 :             dlt_log(LOG_ERR, "Allocating memory for user information");
     488            0 :             return DLT_RETURN_ERROR;
     489              :         }
     490              : 
     491            1 :         dlt_set_id(daemon->user_list[0].ecu, daemon->ecuid);
     492            1 :         daemon->num_user_lists = nodes;
     493              : 
     494            2 :         for (i = 1; i < nodes; i++)
     495            1 :             dlt_set_id(daemon->user_list[i].ecu, gateway->connections[i - 1].ecuid);
     496              :     }
     497              : 
     498              :     return DLT_RETURN_OK;
     499              : }
     500              : 
     501           15 : int dlt_daemon_applications_invalidate_fd(DltDaemon *daemon,
     502              :                                           char *ecu,
     503              :                                           int fd,
     504              :                                           int verbose)
     505              : {
     506              :     int i;
     507              :     DltDaemonRegisteredUsers *user_list = NULL;
     508              : 
     509           15 :     PRINT_FUNCTION_VERBOSE(verbose);
     510              : 
     511           15 :     if ((daemon == NULL) || (ecu == NULL))
     512              :         return DLT_RETURN_ERROR;
     513              : 
     514           15 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
     515              : 
     516           15 :     if (user_list != NULL) {
     517           26 :         for (i = 0; i < user_list->num_applications; i++)
     518           11 :             if (user_list->applications[i].user_handle == fd)
     519            0 :                 user_list->applications[i].user_handle = DLT_FD_INIT;
     520              : 
     521              :         return DLT_RETURN_OK;
     522              :     }
     523              : 
     524              :     return DLT_RETURN_ERROR;
     525              : }
     526              : 
     527           10 : int dlt_daemon_applications_clear(DltDaemon *daemon, char *ecu, int verbose)
     528              : {
     529              :     int i;
     530              :     DltDaemonRegisteredUsers *user_list = NULL;
     531              : 
     532           10 :     PRINT_FUNCTION_VERBOSE(verbose);
     533              : 
     534           10 :     if ((daemon == NULL) || (daemon->user_list == NULL) || (ecu == NULL))
     535              :         return DLT_RETURN_WRONG_PARAMETER;
     536              : 
     537           10 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
     538              : 
     539           10 :     if (user_list == NULL)
     540              :         return DLT_RETURN_ERROR;
     541              : 
     542           11 :     for (i = 0; i < user_list->num_applications; i++)
     543            1 :         if (user_list->applications[i].application_description != NULL) {
     544              : 
     545              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
     546              :             if (user_list->applications[i].context_log_level_settings)
     547              :                 free(user_list->applications[i].context_log_level_settings);
     548              : #endif
     549              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     550              :             if (user_list->applications[i].trace_load_settings) {
     551              :                 free(user_list->applications[i].trace_load_settings);
     552              :                 user_list->applications[i].trace_load_settings = NULL;
     553              :                 user_list->applications[i].trace_load_settings_count = 0;
     554              :             }
     555              : #endif
     556            1 :             free(user_list->applications[i].application_description);
     557            1 :             user_list->applications[i].application_description = NULL;
     558              :         }
     559              : 
     560           10 :     if (user_list->applications != NULL)
     561            7 :         free(user_list->applications);
     562              : 
     563           10 :     user_list->applications = NULL;
     564           10 :     user_list->num_applications = 0;
     565              : 
     566           10 :     return 0;
     567              : }
     568              : 
     569           15 : static void dlt_daemon_application_reset_user_handle(DltDaemon *daemon,
     570              :                                                      DltDaemonApplication *application,
     571              :                                                      int verbose)
     572              : {
     573              :     DltDaemonRegisteredUsers *user_list;
     574              :     DltDaemonContext *context;
     575              :     int i;
     576              : 
     577           15 :     if (application->user_handle == DLT_FD_INIT)
     578              :         return;
     579              : 
     580            6 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
     581            6 :     if (user_list != NULL) {
     582            6 :         for (i = 0; i < user_list->num_contexts; i++) {
     583            0 :             context = &user_list->contexts[i];
     584            0 :             if (context->user_handle == application->user_handle)
     585            0 :                 context->user_handle = DLT_FD_INIT;
     586              :         }
     587              :     }
     588              : 
     589            6 :     if (application->owns_user_handle)
     590            6 :         close(application->user_handle);
     591              : 
     592            6 :     application->user_handle = DLT_FD_INIT;
     593            6 :     application->owns_user_handle = false;
     594              : }
     595              : 
     596           10 : DltDaemonApplication *dlt_daemon_application_add(DltDaemon *daemon,
     597              :                                                  char *apid,
     598              :                                                  pid_t pid,
     599              :                                                  char *description,
     600              :                                                  int fd,
     601              :                                                  char *ecu,
     602              :                                                  int verbose)
     603              : {
     604              :     DltDaemonApplication *application;
     605              :     DltDaemonApplication *old;
     606              :     int new_application;
     607              :     int dlt_user_handle;
     608              :     bool owns_user_handle;
     609              :     DltDaemonRegisteredUsers *user_list = NULL;
     610              : #ifdef DLT_DAEMON_USE_FIFO_IPC
     611              :     (void)fd;  /* To avoid compiler warning : unused variable */
     612              :     char filename[DLT_DAEMON_COMMON_TEXTBUFSIZE];
     613              : #endif
     614              : 
     615           10 :     if ((daemon == NULL) || (apid == NULL) || (apid[0] == '\0') || (ecu == NULL))
     616              :         return (DltDaemonApplication *)NULL;
     617              : 
     618           10 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
     619              : 
     620           10 :     if (user_list == NULL)
     621              :         return (DltDaemonApplication *)NULL;
     622              : 
     623           10 :     if (user_list->applications == NULL) {
     624           10 :         user_list->applications = (DltDaemonApplication *)
     625           10 :             malloc(sizeof(DltDaemonApplication) * DLT_DAEMON_APPL_ALLOC_SIZE);
     626              : 
     627           10 :         if (user_list->applications == NULL)
     628              :             return (DltDaemonApplication *)NULL;
     629              :     }
     630              : 
     631              :     new_application = 0;
     632              : 
     633              :     /* Check if application [apid] is already available */
     634           10 :     application = dlt_daemon_application_find(daemon, apid, ecu, verbose);
     635              : 
     636           10 :     if (application == NULL) {
     637           10 :         user_list->num_applications += 1;
     638              : 
     639           10 :         if (user_list->num_applications != 0) {
     640           10 :             if ((user_list->num_applications % DLT_DAEMON_APPL_ALLOC_SIZE) == 0) {
     641              :                 /* allocate memory in steps of DLT_DAEMON_APPL_ALLOC_SIZE, e.g. 100 */
     642            0 :                 old = user_list->applications;
     643            0 :                 user_list->applications = (DltDaemonApplication *)
     644            0 :                     malloc(sizeof(DltDaemonApplication) *
     645            0 :                            ((user_list->num_applications / DLT_DAEMON_APPL_ALLOC_SIZE) + 1) *
     646              :                            DLT_DAEMON_APPL_ALLOC_SIZE);
     647              : 
     648            0 :                 if (user_list->applications == NULL) {
     649            0 :                     user_list->applications = old;
     650            0 :                     user_list->num_applications -= 1;
     651            0 :                     return (DltDaemonApplication *)NULL;
     652              :                 }
     653              : 
     654            0 :                 memcpy(user_list->applications,
     655              :                        old,
     656            0 :                        sizeof(DltDaemonApplication) * user_list->num_applications);
     657            0 :                 free(old);
     658              :             }
     659              :         }
     660              : 
     661           10 :         application = &(user_list->applications[user_list->num_applications - 1]);
     662              : 
     663           10 :         dlt_set_id(application->apid, apid);
     664           10 :         application->pid = 0;
     665           10 :         application->application_description = NULL;
     666           10 :         application->num_contexts = 0;
     667           10 :         application->user_handle = DLT_FD_INIT;
     668           10 :         application->owns_user_handle = false;
     669              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     670              :         application->trace_load_settings = NULL;
     671              :         application->trace_load_settings_count = 0;
     672              : #endif
     673              : 
     674              :         new_application = 1;
     675              : 
     676              :     }
     677            0 :     else if ((pid != application->pid) && (application->pid != 0))
     678              :     {
     679              : 
     680            0 :         dlt_vlog(LOG_WARNING,
     681              :                  "Duplicate registration of ApplicationID: '%.4s'; registering from PID %d, existing from PID %d\n",
     682              :                  apid,
     683              :                  pid,
     684              :                  application->pid);
     685              :     }
     686              : 
     687              :     /* Store application description and pid of application */
     688           10 :     if (application->application_description) {
     689            0 :         free(application->application_description);
     690            0 :         application->application_description = NULL;
     691              :     }
     692              : 
     693           10 :     if (description != NULL) {
     694           10 :         application->application_description = malloc(strlen(description) + 1);
     695              : 
     696           10 :         if (application->application_description) {
     697           10 :             memcpy(application->application_description, description, strlen(description) + 1);
     698              :         } else {
     699            0 :             dlt_log(LOG_ERR, "Cannot allocate memory to store application description\n");
     700            0 :             free(application);
     701            0 :             return (DltDaemonApplication *)NULL;
     702              :         }
     703              :     }
     704              : 
     705           10 :     if (application->pid != pid) {
     706            9 :         dlt_daemon_application_reset_user_handle(daemon, application, verbose);
     707            9 :         application->pid = 0;
     708              :     }
     709              : 
     710              :     /* open user pipe only if it is not yet opened */
     711           10 :     if ((application->user_handle == DLT_FD_INIT) && (pid != 0)) {
     712              :         dlt_user_handle = DLT_FD_INIT;
     713              :         owns_user_handle = false;
     714              : 
     715              : #if defined DLT_DAEMON_USE_UNIX_SOCKET_IPC || defined DLT_DAEMON_VSOCK_IPC_ENABLE
     716              :         if (fd >= DLT_FD_MINIMUM) {
     717              :             dlt_user_handle = fd;
     718              :             owns_user_handle = false;
     719              :         }
     720              : #endif
     721              : #ifdef DLT_DAEMON_USE_FIFO_IPC
     722              :         if (dlt_user_handle < DLT_FD_MINIMUM) {
     723              :             snprintf(filename,
     724              :                      DLT_DAEMON_COMMON_TEXTBUFSIZE,
     725              :                      "%s/dltpipes/dlt%d",
     726              :                      dltFifoBaseDir,
     727              :                      pid);
     728              : 
     729              :             dlt_user_handle = open(filename, O_WRONLY | O_NONBLOCK);
     730              : 
     731            9 :             if (dlt_user_handle < 0) {
     732            0 :                 int prio = (errno == ENOENT) ? LOG_INFO : LOG_WARNING;
     733            0 :                 dlt_vlog(prio, "open() failed to %s, errno=%d (%s)!\n", filename, errno, strerror(errno));
     734              :             } else {
     735              :                 owns_user_handle = true;
     736              :             }
     737              :         }
     738              : #endif
     739              :         /* check if file descriptor was already used, and make it invalid if it
     740              :         * is reused. This prevents sending messages to wrong file descriptor */
     741            9 :         dlt_daemon_applications_invalidate_fd(daemon, ecu, dlt_user_handle, verbose);
     742            9 :         dlt_daemon_contexts_invalidate_fd(daemon, ecu, dlt_user_handle, verbose);
     743              : 
     744            9 :         application->user_handle = dlt_user_handle;
     745            9 :         application->owns_user_handle = owns_user_handle;
     746            9 :         application->pid = pid;
     747              :     }
     748              : 
     749              :     /* Sort */
     750           10 :     if (new_application) {
     751           10 :         qsort(user_list->applications,
     752           10 :               (size_t) user_list->num_applications,
     753              :               sizeof(DltDaemonApplication),
     754              :               dlt_daemon_cmp_apid);
     755              : 
     756              :         /* Find new position of application with apid*/
     757           10 :         application = dlt_daemon_application_find(daemon, apid, ecu, verbose);
     758              :     }
     759              : 
     760              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
     761              :     application->num_context_log_level_settings = 0;
     762              :     application->context_log_level_settings = NULL;
     763              : #endif
     764              : #if DLT_TRACE_LOAD_CTRL_ENABLE
     765              :     if (application->trace_load_settings == NULL) {
     766              :         DltTraceLoadSettings* pre_configured_trace_load_settings = NULL;
     767              :         int num_settings = 0;
     768              :         DltReturnValue find_trace_settings_return_value = dlt_daemon_find_preconfigured_trace_load_settings(
     769              :             daemon,
     770              :             application->apid,
     771              :             NULL /*load settings for all contexts*/,
     772              :             &pre_configured_trace_load_settings,
     773              :             &num_settings,
     774              :             verbose);
     775              : 
     776              :         DltTraceLoadSettings *app_level = NULL;
     777              :         if ((find_trace_settings_return_value == DLT_RETURN_OK) &&
     778              :             (pre_configured_trace_load_settings != NULL) &&
     779              :             (num_settings != 0)) {
     780              :             application->trace_load_settings = pre_configured_trace_load_settings;
     781              :             application->trace_load_settings_count = num_settings;
     782              :             app_level = dlt_find_runtime_trace_load_settings(
     783              :                 application->trace_load_settings,
     784              :                 application->trace_load_settings_count, application->apid,
     785              :                 NULL);
     786              :         }
     787              : 
     788              :         // app is not configured, set daemon defaults
     789              :         if (app_level == NULL) {
     790              :             DltTraceLoadSettings *temp = realloc(application->trace_load_settings,
     791              :                                                  (application->trace_load_settings_count + 1) *
     792              :                                                      sizeof(DltTraceLoadSettings));
     793              : 
     794              :             if (temp != NULL) {
     795              :                 application->trace_load_settings = temp;
     796              :                 ++application->trace_load_settings_count;
     797              : 
     798              :                 app_level = &application->trace_load_settings[application->trace_load_settings_count - 1];
     799              :                 memset(app_level, 0, sizeof(DltTraceLoadSettings));
     800              :                 app_level[0].hard_limit = DLT_TRACE_LOAD_DAEMON_HARD_LIMIT_DEFAULT;
     801              :                 app_level[0].soft_limit = DLT_TRACE_LOAD_DAEMON_SOFT_LIMIT_DEFAULT;
     802              :                 memcpy(&app_level[0].apid, apid, DLT_ID_SIZE);
     803              :                 memset(&app_level[0].tl_stat, 0, sizeof(DltTraceLoadStat));
     804              :             } else {
     805              :                 dlt_vlog(DLT_LOG_FATAL, "Failed to allocate memory for trace load settings\n");
     806              :             }
     807              : 
     808              :             // We inserted the application id at the end, to make sure
     809              :             // Lookups are working properly later on, we have to sort the list again.
     810              :             qsort(application->trace_load_settings,
     811              :                   (size_t)application->trace_load_settings_count,
     812              :                   sizeof(DltTraceLoadSettings),
     813              :                   dlt_daemon_compare_trace_load_settings);
     814              :         }
     815              :     }
     816              : 
     817              : #endif
     818              : 
     819              :     return application;
     820              : }
     821              : 
     822            6 : int dlt_daemon_application_del(DltDaemon *daemon,
     823              :                                DltDaemonApplication *application,
     824              :                                char *ecu,
     825              :                                int verbose)
     826              : {
     827              :     int pos;
     828              :     DltDaemonRegisteredUsers *user_list = NULL;
     829              : 
     830            6 :     PRINT_FUNCTION_VERBOSE(verbose);
     831              : 
     832            6 :     if ((daemon == NULL) || (application == NULL) || (ecu == NULL))
     833              :         return -1;
     834              : 
     835            6 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
     836              : 
     837            6 :     if (user_list == NULL)
     838              :         return -1;
     839              : 
     840            6 :     if (user_list->num_applications > 0) {
     841            6 :         dlt_daemon_application_reset_user_handle(daemon, application, verbose);
     842              : 
     843              :         /* Free description of application to be deleted */
     844            6 :         if (application->application_description) {
     845            6 :             free(application->application_description);
     846            6 :             application->application_description = NULL;
     847              :         }
     848              : 
     849              : #if DLT_TRACE_LOAD_CTRL_ENABLE
     850              :         if (application->trace_load_settings != NULL) {
     851              :             free(application->trace_load_settings);
     852              :             application->trace_load_settings = NULL;
     853              :             application->trace_load_settings_count = 0;
     854              :         }
     855              : #endif
     856            6 :         pos = (int) (application - (user_list->applications));
     857              : 
     858              :         /* move all applications above pos to pos */
     859            6 :         memmove(&(user_list->applications[pos]),
     860            6 :                 &(user_list->applications[pos + 1]),
     861            6 :                 sizeof(DltDaemonApplication) * ((user_list->num_applications - 1) - pos));
     862              : 
     863              :         /* Clear last application */
     864            6 :         memset(&(user_list->applications[user_list->num_applications - 1]),
     865              :                0,
     866              :                sizeof(DltDaemonApplication));
     867              : 
     868            6 :         user_list->num_applications--;
     869              :     }
     870              : 
     871              :     return 0;
     872              : }
     873              : 
     874          149 : DltDaemonApplication *dlt_daemon_application_find(DltDaemon *daemon,
     875              :                                                   char *apid,
     876              :                                                   char *ecu,
     877              :                                                   int verbose)
     878              : {
     879              :     DltDaemonApplication application;
     880              :     DltDaemonRegisteredUsers *user_list = NULL;
     881              : 
     882          149 :     PRINT_FUNCTION_VERBOSE(verbose);
     883              : 
     884          149 :     if ((daemon == NULL) || (daemon->user_list == NULL) || (apid == NULL) ||
     885          149 :         (apid[0] == '\0') || (ecu == NULL))
     886              :         return (DltDaemonApplication *)NULL;
     887              : 
     888          149 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
     889              : 
     890          149 :     if ((user_list == NULL) || (user_list->num_applications == 0))
     891              :         return (DltDaemonApplication *)NULL;
     892              : 
     893              :     /* Check, if apid is smaller than smallest apid or greater than greatest apid */
     894          132 :     if ((memcmp(apid, user_list->applications[0].apid, DLT_ID_SIZE) < 0) ||
     895          132 :         (memcmp(apid,
     896          132 :                 user_list->applications[user_list->num_applications - 1].apid,
     897              :                 DLT_ID_SIZE) > 0))
     898              :         return (DltDaemonApplication *)NULL;
     899              : 
     900          132 :     dlt_set_id(application.apid, apid);
     901          132 :     return (DltDaemonApplication *)bsearch(&application,
     902          132 :                                            user_list->applications,
     903          132 :                                            (size_t) user_list->num_applications,
     904              :                                            sizeof(DltDaemonApplication),
     905              :                                            dlt_daemon_cmp_apid);
     906              : }
     907              : 
     908            9 : int dlt_daemon_applications_load(DltDaemon *daemon, const char *filename, int verbose)
     909              : {
     910              :     FILE *fd;
     911              :     ID4 apid;
     912              :     char buf[DLT_DAEMON_COMMON_TEXTBUFSIZE];
     913              :     char *ret;
     914              :     char *pb;
     915              : 
     916            9 :     PRINT_FUNCTION_VERBOSE(verbose);
     917              : 
     918            9 :     if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
     919              :         return -1;
     920              : 
     921            9 :     fd = fopen(filename, "r");
     922              : 
     923            9 :     if (fd == NULL) {
     924            9 :         dlt_vlog(LOG_WARNING,
     925              :                  "%s: cannot open file %s: %s\n",
     926              :                  __func__,
     927              :                  filename,
     928            9 :                  strerror(errno));
     929              : 
     930            9 :         return -1;
     931              :     }
     932              : 
     933            0 :     while (!feof(fd)) {
     934              :         /* Clear buf */
     935              :         memset(buf, 0, sizeof(buf));
     936              : 
     937              :         /* Get line */
     938              :         ret = fgets(buf, sizeof(buf), fd);
     939              : 
     940            0 :         if (NULL == ret) {
     941              :             /* fgets always null pointer if the last byte of the file is a new line
     942              :              * We need to check here if there was an error or was it feof.*/
     943            0 :             if (ferror(fd)) {
     944            0 :                 dlt_vlog(LOG_WARNING,
     945              :                          "%s: fgets(buf,sizeof(buf),fd) returned NULL. %s\n",
     946              :                          __func__,
     947            0 :                          strerror(errno));
     948            0 :                 fclose(fd);
     949            0 :                 return -1;
     950              :             }
     951            0 :             else if (feof(fd))
     952              :             {
     953            0 :                 fclose(fd);
     954            0 :                 return 0;
     955              :             }
     956              :             else {
     957            0 :                 dlt_vlog(LOG_WARNING,
     958              :                          "%s: fgets(buf,sizeof(buf),fd) returned NULL. Unknown error.\n",
     959              :                          __func__);
     960            0 :                 fclose(fd);
     961            0 :                 return -1;
     962              :             }
     963              :         }
     964              : 
     965            0 :         if (strcmp(buf, "") != 0) {
     966              :             /* Split line */
     967            0 :             pb = strtok(buf, ":");
     968              : 
     969            0 :             if (pb != NULL) {
     970            0 :                 dlt_set_id(apid, pb);
     971            0 :                 pb = strtok(NULL, ":");
     972              : 
     973            0 :                 if (pb != NULL) {
     974              :                     /* pb contains now the description */
     975              :                     /* pid is unknown at loading time */
     976            0 :                     if (dlt_daemon_application_add(daemon,
     977              :                                                    apid,
     978              :                                                    0,
     979              :                                                    pb,
     980              :                                                    -1,
     981            0 :                                                    daemon->ecuid,
     982              :                                                    verbose) == 0) {
     983            0 :                         dlt_vlog(LOG_WARNING,
     984              :                                  "%s: dlt_daemon_application_add failed for %4s\n",
     985              :                                  __func__,
     986              :                                  apid);
     987            0 :                         fclose(fd);
     988            0 :                         return -1;
     989              :                     }
     990              :                 }
     991              :             }
     992              :         }
     993              :     }
     994              : 
     995            0 :     fclose(fd);
     996              : 
     997            0 :     return 0;
     998              : }
     999              : 
    1000            0 : int dlt_daemon_applications_save(DltDaemon *daemon, const char *filename, int verbose)
    1001              : {
    1002              :     FILE *fd;
    1003              :     int i;
    1004              : 
    1005              :     char apid[DLT_ID_SIZE + 1]; /* DLT_ID_SIZE+1, because the 0-termination is required here */
    1006              :     DltDaemonRegisteredUsers *user_list = NULL;
    1007              : 
    1008            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1009              : 
    1010            0 :     if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
    1011              :         return -1;
    1012              : 
    1013              :     memset(apid, 0, sizeof(apid));
    1014              : 
    1015            0 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    1016              : 
    1017            0 :     if (user_list == NULL)
    1018              :         return -1;
    1019              : 
    1020            0 :     if ((user_list->applications != NULL) && (user_list->num_applications > 0)) {
    1021            0 :         fd = fopen(filename, "w");
    1022              : 
    1023            0 :         if (fd != NULL) {
    1024            0 :             for (i = 0; i < user_list->num_applications; i++) {
    1025            0 :                 dlt_set_id(apid, user_list->applications[i].apid);
    1026              : 
    1027            0 :                 if ((user_list->applications[i].application_description) &&
    1028            0 :                     (user_list->applications[i].application_description[0] != '\0'))
    1029              :                     fprintf(fd,
    1030              :                             "%s:%s:\n",
    1031              :                             apid,
    1032              :                             user_list->applications[i].application_description);
    1033              :                 else
    1034              :                     fprintf(fd, "%s::\n", apid);
    1035              :             }
    1036              : 
    1037            0 :             fclose(fd);
    1038              :         }
    1039              :         else {
    1040            0 :             dlt_vlog(LOG_ERR, "%s: open %s failed! No application information stored.\n",
    1041              :                      __func__,
    1042              :                      filename);
    1043              :         }
    1044              :     }
    1045              : 
    1046              :     return 0;
    1047              : }
    1048              : 
    1049           41 : DltDaemonContext *dlt_daemon_context_add(DltDaemon *daemon,
    1050              :                                          char *apid,
    1051              :                                          char *ctid,
    1052              :                                          int8_t log_level,
    1053              :                                          int8_t trace_status,
    1054              :                                          int log_level_pos,
    1055              :                                          int user_handle,
    1056              :                                          char *description,
    1057              :                                          char *ecu,
    1058              :                                          int verbose)
    1059              : {
    1060              :     DltDaemonApplication *application;
    1061              :     DltDaemonContext *context;
    1062              :     DltDaemonContext *old;
    1063              :     int new_context = 0;
    1064              :     DltDaemonRegisteredUsers *user_list = NULL;
    1065              : 
    1066           41 :     PRINT_FUNCTION_VERBOSE(verbose);
    1067              : 
    1068           41 :     if ((daemon == NULL) || (apid == NULL) || (apid[0] == '\0') ||
    1069           41 :         (ctid == NULL) || (ctid[0] == '\0') || (ecu == NULL))
    1070              :         return (DltDaemonContext *)NULL;
    1071              : 
    1072           41 :     if ((log_level < DLT_LOG_DEFAULT) || (log_level > DLT_LOG_VERBOSE))
    1073              :         return (DltDaemonContext *)NULL;
    1074              : 
    1075           41 :     if ((trace_status < DLT_TRACE_STATUS_DEFAULT) || (trace_status > DLT_TRACE_STATUS_ON))
    1076              :         return (DltDaemonContext *)NULL;
    1077              : 
    1078           41 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
    1079              : 
    1080           41 :     if (user_list == NULL)
    1081              :         return (DltDaemonContext *)NULL;
    1082              : 
    1083           41 :     if (user_list->contexts == NULL) {
    1084           10 :         user_list->contexts = (DltDaemonContext *)calloc(1, sizeof(DltDaemonContext) * DLT_DAEMON_CONTEXT_ALLOC_SIZE);
    1085              : 
    1086           10 :         if (user_list->contexts == NULL)
    1087              :             return (DltDaemonContext *)NULL;
    1088              :     }
    1089              : 
    1090              :     /* Check if application [apid] is available */
    1091           41 :     application = dlt_daemon_application_find(daemon, apid, ecu, verbose);
    1092              : 
    1093           41 :     if (application == NULL)
    1094              :         return (DltDaemonContext *)NULL;
    1095              : 
    1096              :     /* Check if context [apid, ctid] is already available */
    1097           41 :     context = dlt_daemon_context_find(daemon, apid, ctid, ecu, verbose);
    1098              : 
    1099           41 :     if (context == NULL) {
    1100           41 :         user_list->num_contexts += 1;
    1101              : 
    1102           41 :         if (user_list->num_contexts != 0) {
    1103           41 :             if ((user_list->num_contexts % DLT_DAEMON_CONTEXT_ALLOC_SIZE) == 0) {
    1104              :                 /* allocate memory for context in steps of DLT_DAEMON_CONTEXT_ALLOC_SIZE, e.g 100 */
    1105            0 :                 old = user_list->contexts;
    1106            0 :                 user_list->contexts = (DltDaemonContext *)calloc(1, (size_t) sizeof(DltDaemonContext) *
    1107            0 :                                                                  ((user_list->num_contexts /
    1108            0 :                                                                    DLT_DAEMON_CONTEXT_ALLOC_SIZE) + 1) *
    1109              :                                                                  DLT_DAEMON_CONTEXT_ALLOC_SIZE);
    1110              : 
    1111            0 :                 if (user_list->contexts == NULL) {
    1112            0 :                     user_list->contexts = old;
    1113            0 :                     user_list->num_contexts -= 1;
    1114            0 :                     return (DltDaemonContext *)NULL;
    1115              :                 }
    1116              : 
    1117            0 :                 memcpy(user_list->contexts,
    1118              :                        old,
    1119            0 :                        (size_t) sizeof(DltDaemonContext) * user_list->num_contexts);
    1120            0 :                 free(old);
    1121              :             }
    1122              :         }
    1123              : 
    1124           41 :         context = &(user_list->contexts[user_list->num_contexts - 1]);
    1125              :         memset(context, 0, sizeof(DltDaemonContext));
    1126              : 
    1127           41 :         dlt_set_id(context->apid, apid);
    1128           41 :         dlt_set_id(context->ctid, ctid);
    1129              : 
    1130              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1131              :         context->trace_load_settings = NULL;
    1132              : #endif
    1133              : 
    1134           41 :         application->num_contexts++;
    1135              :         new_context = 1;
    1136              :     }
    1137              : 
    1138              :     /* Set context description */
    1139           41 :     if (context->context_description) {
    1140            0 :         free(context->context_description);
    1141            0 :         context->context_description = NULL;
    1142              :     }
    1143              : 
    1144           41 :     if (description != NULL) {
    1145           41 :         context->context_description = malloc(strlen(description) + 1);
    1146              : 
    1147           41 :         if (context->context_description) {
    1148           41 :             memcpy(context->context_description, description, strlen(description) + 1);
    1149              :         }
    1150              :     }
    1151              : 
    1152              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    1153              :     /* configure initial log level */
    1154              :     DltDaemonContextLogSettings *settings = NULL;
    1155              :     settings = dlt_daemon_find_configured_app_id_ctx_id_settings(
    1156              :             daemon, context->apid, ctid);
    1157              : 
    1158              :     if (settings != NULL) {
    1159              :         /* set log level */
    1160              :         log_level = settings->log_level;
    1161              : 
    1162              :         DltDaemonContextLogSettings *ct_settings = NULL;
    1163              :         ct_settings = dlt_daemon_find_app_log_level_config(application, ctid);
    1164              : 
    1165              :         /* ct_settings != null: context and app id combination already exists */
    1166              :         if (ct_settings == NULL) {
    1167              :           /* copy the configuration into the DltDaemonApplication for faster access later */
    1168              :           DltDaemonContextLogSettings *tmp =
    1169              :               realloc(application->context_log_level_settings,
    1170              :                       (++application->num_context_log_level_settings) *
    1171              :                           sizeof(DltDaemonContextLogSettings));
    1172              :           application->context_log_level_settings = tmp;
    1173              : 
    1174              :           ct_settings =
    1175              :               &application->context_log_level_settings[application->num_context_log_level_settings - 1];
    1176              :           memcpy(ct_settings, settings, sizeof(DltDaemonContextLogSettings));
    1177              :           memcpy(ct_settings->ctid, ctid, DLT_ID_SIZE);
    1178              :       }
    1179              :     }
    1180              : #endif
    1181              : 
    1182           41 :     if ((strncmp(daemon->ecuid, ecu, DLT_ID_SIZE) == 0) && (daemon->force_ll_ts)) {
    1183              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    1184              :         if (log_level > daemon->default_log_level && settings == NULL)
    1185              : #else
    1186            0 :         if (log_level > daemon->default_log_level)
    1187              : #endif
    1188              :             log_level = daemon->default_log_level;
    1189              : 
    1190            0 :         if (trace_status > daemon->default_trace_status)
    1191              :             trace_status = daemon->default_trace_status;
    1192              : 
    1193            0 :         dlt_vlog(LOG_NOTICE,
    1194              :             "Adapting ll_ts for context: %.4s:%.4s with %i %i\n",
    1195              :             apid,
    1196              :             ctid,
    1197              :             log_level,
    1198              :             trace_status);
    1199              :     }
    1200              : 
    1201              :     /* Store log level and trace status,
    1202              :      * if this is a new context, or
    1203              :      * if this is an old context and the runtime cfg was not loaded */
    1204           41 :     if ((new_context == 1) ||
    1205            0 :         ((new_context == 0) && (daemon->runtime_context_cfg_loaded == 0))) {
    1206           41 :         context->log_level = log_level;
    1207           41 :         context->trace_status = trace_status;
    1208              :     }
    1209              : 
    1210           41 :     context->log_level_pos = log_level_pos;
    1211           41 :     context->user_handle = user_handle;
    1212              : 
    1213              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1214              :     DltTraceLoadSettings* tl_settings = dlt_find_runtime_trace_load_settings(
    1215              :         application->trace_load_settings,
    1216              :         application->trace_load_settings_count,
    1217              :         application->apid,
    1218              :         context->ctid);
    1219              :     if (tl_settings == NULL) {
    1220              :         dlt_vlog(LOG_WARNING, "failed to find trace load settings for application %s context %s\n",
    1221              :                  application->apid, context->ctid);
    1222              :     } else {
    1223              :         context->trace_load_settings = tl_settings;
    1224              :     }
    1225              : #endif
    1226              : 
    1227              : 
    1228              :     /* In case a context is loaded from runtime config file,
    1229              :      * the user_handle is 0 and we mark that context as predefined.
    1230              :      */
    1231           41 :     if (context->user_handle == 0)
    1232            0 :         context->predefined = true;
    1233              :     else
    1234           41 :         context->predefined = false;
    1235              : 
    1236              :     /* Sort */
    1237           41 :     if (new_context) {
    1238           41 :         qsort(user_list->contexts,
    1239           41 :               (size_t) user_list->num_contexts,
    1240              :               sizeof(DltDaemonContext),
    1241              :               dlt_daemon_cmp_apid_ctid);
    1242              : 
    1243              :         /* Find new position of context with apid, ctid */
    1244           41 :         context = dlt_daemon_context_find(daemon, apid, ctid, ecu, verbose);
    1245              :     }
    1246              : 
    1247              :     return context;
    1248              : }
    1249              : 
    1250              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    1251              : static void dlt_daemon_free_context_log_settings(
    1252              :     DltDaemonApplication *application,
    1253              :     DltDaemonContext *context)
    1254              : {
    1255              :     DltDaemonContextLogSettings *ct_settings;
    1256              :     int i;
    1257              :     int skipped = 0;
    1258              : 
    1259              :     ct_settings = dlt_daemon_find_app_log_level_config(application, context->ctid);
    1260              :     if (ct_settings == NULL) {
    1261              :         return;
    1262              :     }
    1263              : 
    1264              :     /* move all data forward */
    1265              :     for (i = 0; i < application->num_context_log_level_settings; ++i) {
    1266              :         /* skip given context to delete it */
    1267              :         if (i + skipped < application->num_context_log_level_settings &&
    1268              :             strncmp(application->context_log_level_settings[i+skipped].ctid, context->ctid, DLT_ID_SIZE) == 0) {
    1269              :             ++skipped;
    1270              :             continue;
    1271              :         }
    1272              : 
    1273              :         memcpy(&application->context_log_level_settings[i-skipped],
    1274              :                 &application->context_log_level_settings[i],
    1275              :                 sizeof(DltDaemonContextLogSettings));
    1276              :     }
    1277              : 
    1278              :     application->num_context_log_level_settings -= skipped;
    1279              : 
    1280              :     /* if size is equal to zero, and ptr is not NULL, then realloc is equivalent to free(ptr) */
    1281              :     application->context_log_level_settings = realloc(application->context_log_level_settings,
    1282              :             sizeof(DltDaemonContextLogSettings) * (application->num_context_log_level_settings));
    1283              : 
    1284              : }
    1285              : #endif
    1286              : 
    1287           37 : int dlt_daemon_context_del(DltDaemon *daemon,
    1288              :                            DltDaemonContext *context,
    1289              :                            char *ecu,
    1290              :                            int verbose)
    1291              : {
    1292              :     int pos;
    1293              :     DltDaemonApplication *application;
    1294              :     DltDaemonRegisteredUsers *user_list = NULL;
    1295              : 
    1296           37 :     PRINT_FUNCTION_VERBOSE(verbose);
    1297              : 
    1298           37 :     if ((daemon == NULL) || (context == NULL) || (ecu == NULL))
    1299              :         return -1;
    1300              : 
    1301           37 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
    1302              : 
    1303           37 :     if (user_list == NULL)
    1304              :         return -1;
    1305              : 
    1306           37 :     if (user_list->num_contexts > 0) {
    1307           37 :         application = dlt_daemon_application_find(daemon, context->apid, ecu, verbose);
    1308              : 
    1309              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    1310              :         dlt_daemon_free_context_log_settings(application, context);
    1311              : #endif
    1312              :         /* Free description of context to be deleted */
    1313           37 :         if (context->context_description) {
    1314           37 :             free(context->context_description);
    1315           37 :             context->context_description = NULL;
    1316              :         }
    1317              : 
    1318           37 :         pos = (int) (context - (user_list->contexts));
    1319              : 
    1320              :         /* move all contexts above pos to pos */
    1321           37 :         memmove(&(user_list->contexts[pos]),
    1322           37 :                 &(user_list->contexts[pos + 1]),
    1323           37 :                 sizeof(DltDaemonContext) * ((user_list->num_contexts - 1) - pos));
    1324              : 
    1325              :         /* Clear last context */
    1326           37 :         memset(&(user_list->contexts[user_list->num_contexts - 1]),
    1327              :                0,
    1328              :                sizeof(DltDaemonContext));
    1329              : 
    1330           37 :         user_list->num_contexts--;
    1331              : 
    1332              :         /* Check if application [apid] is available */
    1333           37 :         if (application != NULL)
    1334           37 :             application->num_contexts--;
    1335              :     }
    1336              : 
    1337              :     return 0;
    1338              : }
    1339              : 
    1340          157 : DltDaemonContext *dlt_daemon_context_find(DltDaemon *daemon,
    1341              :                                           char *apid,
    1342              :                                           char *ctid,
    1343              :                                           char *ecu,
    1344              :                                           int verbose)
    1345              : {
    1346              :     DltDaemonContext context;
    1347              :     DltDaemonRegisteredUsers *user_list = NULL;
    1348              : 
    1349          157 :     PRINT_FUNCTION_VERBOSE(verbose);
    1350              : 
    1351          157 :     if ((daemon == NULL) || (apid == NULL) || (apid[0] == '\0') ||
    1352          157 :         (ctid == NULL) || (ctid[0] == '\0') || (ecu == NULL))
    1353              :         return (DltDaemonContext *)NULL;
    1354              : 
    1355          157 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
    1356              : 
    1357          157 :     if ((user_list == NULL) || (user_list->num_contexts == 0))
    1358              :         return (DltDaemonContext *)NULL;
    1359              : 
    1360              :     /* Check, if apid is smaller than smallest apid or greater than greatest apid */
    1361          112 :     if ((memcmp(apid, user_list->contexts[0].apid, DLT_ID_SIZE) < 0) ||
    1362          112 :         (memcmp(apid,
    1363          112 :                 user_list->contexts[user_list->num_contexts - 1].apid,
    1364              :                 DLT_ID_SIZE) > 0))
    1365              :         return (DltDaemonContext *)NULL;
    1366              : 
    1367          112 :     dlt_set_id(context.apid, apid);
    1368          112 :     dlt_set_id(context.ctid, ctid);
    1369              : 
    1370          112 :     return (DltDaemonContext *)bsearch(&context,
    1371          112 :                                        user_list->contexts,
    1372          112 :                                        (size_t) user_list->num_contexts,
    1373              :                                        sizeof(DltDaemonContext),
    1374              :                                        dlt_daemon_cmp_apid_ctid);
    1375              : }
    1376              : 
    1377           15 : int dlt_daemon_contexts_invalidate_fd(DltDaemon *daemon,
    1378              :                                       char *ecu,
    1379              :                                       int fd,
    1380              :                                       int verbose)
    1381              : {
    1382              :     int i;
    1383              :     DltDaemonRegisteredUsers *user_list = NULL;
    1384              : 
    1385           15 :     PRINT_FUNCTION_VERBOSE(verbose);
    1386              : 
    1387           15 :     if ((daemon == NULL) || (ecu == NULL))
    1388              :         return -1;
    1389              : 
    1390           15 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
    1391              : 
    1392           15 :     if (user_list != NULL) {
    1393           39 :         for (i = 0; i < user_list->num_contexts; i++)
    1394           24 :             if (user_list->contexts[i].user_handle == fd)
    1395            0 :                 user_list->contexts[i].user_handle = DLT_FD_INIT;
    1396              : 
    1397              :         return 0;
    1398              :     }
    1399              : 
    1400              :     return -1;
    1401              : }
    1402              : 
    1403           10 : int dlt_daemon_contexts_clear(DltDaemon *daemon, char *ecu, int verbose)
    1404              : {
    1405              :     int i;
    1406              :     DltDaemonRegisteredUsers *users = NULL;
    1407              : 
    1408           10 :     PRINT_FUNCTION_VERBOSE(verbose);
    1409              : 
    1410           10 :     if ((daemon == NULL) || (ecu == NULL))
    1411              :         return DLT_RETURN_WRONG_PARAMETER;
    1412              : 
    1413           10 :     users = dlt_daemon_find_users_list(daemon, ecu, verbose);
    1414              : 
    1415           10 :     if (users == NULL)
    1416              :         return DLT_RETURN_ERROR;
    1417              : 
    1418           11 :     for (i = 0; i < users->num_contexts; i++)
    1419            1 :         if (users->contexts[i].context_description != NULL) {
    1420            1 :             free(users->contexts[i].context_description);
    1421            1 :             users->contexts[i].context_description = NULL;
    1422              :         }
    1423              : 
    1424           10 :     if (users->contexts) {
    1425            7 :         free(users->contexts);
    1426            7 :         users->contexts = NULL;
    1427              :     }
    1428              : 
    1429           11 :     for (i = 0; i < users->num_applications; i++)
    1430            1 :         users->applications[i].num_contexts = 0;
    1431              : 
    1432           10 :     users->num_contexts = 0;
    1433              : 
    1434           10 :     return 0;
    1435              : }
    1436              : 
    1437            0 : int dlt_daemon_contexts_load(DltDaemon *daemon, const char *filename, int verbose)
    1438              : {
    1439              :     FILE *fd;
    1440              :     ID4 apid, ctid;
    1441              :     char buf[DLT_DAEMON_COMMON_TEXTBUFSIZE];
    1442              :     char *ret;
    1443              :     char *pb;
    1444              :     int ll, ts;
    1445              : 
    1446            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1447              : 
    1448            0 :     if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
    1449              :         return -1;
    1450              : 
    1451            0 :     fd = fopen(filename, "r");
    1452              : 
    1453            0 :     if (fd == NULL) {
    1454            0 :         dlt_vlog(LOG_WARNING,
    1455              :                  "DLT runtime-context load, cannot open file %s: %s\n",
    1456              :                  filename,
    1457            0 :                  strerror(errno));
    1458              : 
    1459            0 :         return -1;
    1460              :     }
    1461              : 
    1462            0 :     while (!feof(fd)) {
    1463              :         /* Clear buf */
    1464              :         memset(buf, 0, sizeof(buf));
    1465              : 
    1466              :         /* Get line */
    1467              :         ret = fgets(buf, sizeof(buf), fd);
    1468              : 
    1469            0 :         if (NULL == ret) {
    1470              :             /* fgets always returns null pointer if the last byte of the file is a new line.
    1471              :              * We need to check here if there was an error or was it feof.*/
    1472            0 :             if (ferror(fd)) {
    1473            0 :                 dlt_vlog(LOG_WARNING,
    1474              :                          "%s fgets(buf,sizeof(buf),fd) returned NULL. %s\n",
    1475              :                          __func__,
    1476            0 :                          strerror(errno));
    1477            0 :                 fclose(fd);
    1478            0 :                 return -1;
    1479              :             }
    1480            0 :             else if (feof(fd))
    1481              :             {
    1482            0 :                 fclose(fd);
    1483            0 :                 return 0;
    1484              :             }
    1485              :             else {
    1486            0 :                 dlt_vlog(LOG_WARNING,
    1487              :                          "%s fgets(buf,sizeof(buf),fd) returned NULL. Unknown error.\n",
    1488              :                          __func__);
    1489            0 :                 fclose(fd);
    1490            0 :                 return -1;
    1491              :             }
    1492              :         }
    1493              : 
    1494            0 :         if (strcmp(buf, "") != 0) {
    1495              :             /* Split line */
    1496            0 :             pb = strtok(buf, ":");
    1497              : 
    1498            0 :             if (pb != NULL) {
    1499            0 :                 dlt_set_id(apid, pb);
    1500            0 :                 pb = strtok(NULL, ":");
    1501              : 
    1502            0 :                 if (pb != NULL) {
    1503            0 :                     dlt_set_id(ctid, pb);
    1504            0 :                     pb = strtok(NULL, ":");
    1505              : 
    1506            0 :                     if (pb != NULL) {
    1507            0 :                         sscanf(pb, "%d", &ll);
    1508            0 :                         pb = strtok(NULL, ":");
    1509              : 
    1510            0 :                         if (pb != NULL) {
    1511            0 :                             sscanf(pb, "%d", &ts);
    1512            0 :                             pb = strtok(NULL, ":");
    1513              : 
    1514            0 :                             if (pb != NULL) {
    1515              :                                 /* pb contains now the description */
    1516              : 
    1517              :                                 /* log_level_pos, and user_handle are unknown at loading time */
    1518            0 :                                 if (dlt_daemon_context_add(daemon,
    1519              :                                                            apid,
    1520              :                                                            ctid,
    1521            0 :                                                            (int8_t)ll,
    1522            0 :                                                            (int8_t)ts,
    1523              :                                                            0,
    1524              :                                                            0,
    1525              :                                                            pb,
    1526            0 :                                                            daemon->ecuid,
    1527              :                                                            verbose) == NULL) {
    1528            0 :                                     dlt_vlog(LOG_WARNING,
    1529              :                                              "%s dlt_daemon_context_add failed\n",
    1530              :                                              __func__);
    1531            0 :                                     fclose(fd);
    1532            0 :                                     return -1;
    1533              :                                 }
    1534              :                             }
    1535              :                         }
    1536              :                     }
    1537              :                 }
    1538              :             }
    1539              :         }
    1540              :     }
    1541              : 
    1542            0 :     fclose(fd);
    1543              : 
    1544            0 :     return 0;
    1545              : }
    1546              : 
    1547            0 : int dlt_daemon_contexts_save(DltDaemon *daemon, const char *filename, int verbose)
    1548              : {
    1549              :     FILE *fd;
    1550              :     int i;
    1551              : 
    1552              :     char apid[DLT_ID_SIZE + 1], ctid[DLT_ID_SIZE + 1]; /* DLT_ID_SIZE+1, because the 0-termination is required here */
    1553              :     DltDaemonRegisteredUsers *user_list = NULL;
    1554              : 
    1555            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1556              : 
    1557            0 :     if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
    1558              :         return -1;
    1559              : 
    1560            0 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    1561              : 
    1562            0 :     if (user_list == NULL)
    1563              :         return -1;
    1564              : 
    1565              :     memset(apid, 0, sizeof(apid));
    1566              :     memset(ctid, 0, sizeof(ctid));
    1567              : 
    1568            0 :     if ((user_list->contexts) && (user_list->num_contexts > 0)) {
    1569            0 :         fd = fopen(filename, "w");
    1570              : 
    1571            0 :         if (fd != NULL) {
    1572            0 :             for (i = 0; i < user_list->num_contexts; i++) {
    1573            0 :                 dlt_set_id(apid, user_list->contexts[i].apid);
    1574            0 :                 dlt_set_id(ctid, user_list->contexts[i].ctid);
    1575              : 
    1576            0 :                 if ((user_list->contexts[i].context_description) &&
    1577            0 :                     (user_list->contexts[i].context_description[0] != '\0'))
    1578            0 :                     fprintf(fd, "%s:%s:%d:%d:%s:\n", apid, ctid,
    1579            0 :                             (int)(user_list->contexts[i].log_level),
    1580            0 :                             (int)(user_list->contexts[i].trace_status),
    1581              :                             user_list->contexts[i].context_description);
    1582              :                 else
    1583            0 :                     fprintf(fd, "%s:%s:%d:%d::\n", apid, ctid,
    1584            0 :                             (int)(user_list->contexts[i].log_level),
    1585            0 :                             (int)(user_list->contexts[i].trace_status));
    1586              :             }
    1587              : 
    1588            0 :             fclose(fd);
    1589              :         }
    1590              :         else {
    1591            0 :             dlt_vlog(LOG_ERR,
    1592              :                      "%s: Cannot open %s. No context information stored\n",
    1593              :                      __func__,
    1594              :                      filename);
    1595              :         }
    1596              :     }
    1597              : 
    1598              :     return 0;
    1599              : }
    1600              : 
    1601            0 : int dlt_daemon_configuration_save(DltDaemon *daemon, const char *filename, int verbose)
    1602              : {
    1603              :     FILE *fd;
    1604              : 
    1605            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1606              : 
    1607            0 :     if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
    1608              :         return -1;
    1609              : 
    1610            0 :     fd = fopen(filename, "w");
    1611              : 
    1612            0 :     if (fd != NULL) {
    1613              :         fprintf(fd, "# 0 = off, 1 = external, 2 = internal, 3 = both\n");
    1614            0 :         fprintf(fd, "LoggingMode = %d\n", daemon->mode);
    1615              : 
    1616            0 :         fclose(fd);
    1617              :     }
    1618              : 
    1619              :     return 0;
    1620              : }
    1621              : 
    1622            9 : int dlt_daemon_configuration_load(DltDaemon *daemon, const char *filename, int verbose)
    1623              : {
    1624            9 :     if ((daemon == NULL) || (filename == NULL))
    1625              :         return -1;
    1626              : 
    1627              :     FILE *pFile;
    1628              :     char line[1024];
    1629              :     char token[1024];
    1630              :     char value[1024];
    1631              :     char *pch;
    1632              : 
    1633            9 :     PRINT_FUNCTION_VERBOSE(verbose);
    1634              : 
    1635            9 :     pFile = fopen (filename, "r");
    1636              : 
    1637            9 :     if (pFile != NULL) {
    1638              :         while (1) {
    1639              :             /* fetch line from configuration file */
    1640           18 :             if (fgets (line, 1024, pFile) != NULL) {
    1641            9 :                 pch = strtok (line, " =\r\n");
    1642            9 :                 token[0] = 0;
    1643            9 :                 value[0] = 0;
    1644              : 
    1645           18 :                 while (pch != NULL) {
    1646            9 :                     if (strcmp(pch, "#") == 0)
    1647              :                         break;
    1648              : 
    1649            9 :                     if (token[0] == 0) {
    1650              :                         strncpy(token, pch, sizeof(token) - 1);
    1651            9 :                         token[sizeof(token) - 1] = 0;
    1652              :                     }
    1653              :                     else {
    1654              :                         strncpy(value, pch, sizeof(value) - 1);
    1655            0 :                         value[sizeof(value) - 1] = 0;
    1656            0 :                         break;
    1657              :                     }
    1658              : 
    1659            9 :                     pch = strtok (NULL, " =\r\n");
    1660              :                 }
    1661              : 
    1662            9 :                 if (token[0] && value[0]) {
    1663              :                     /* parse arguments here */
    1664            0 :                     if (strcmp(token, "LoggingMode") == 0) {
    1665            0 :                         daemon->mode = atoi(value);
    1666            0 :                         dlt_vlog(LOG_INFO, "Runtime Option: %s=%d\n", token,
    1667              :                                  daemon->mode);
    1668              :                     }
    1669              :                     else {
    1670            0 :                         dlt_vlog(LOG_WARNING, "Unknown option: %s=%s\n", token,
    1671              :                                  value);
    1672              :                     }
    1673              :                 }
    1674              :             }
    1675              :             else {
    1676              :                 break;
    1677              :             }
    1678              :         }
    1679              : 
    1680            9 :         fclose (pFile);
    1681              :     }
    1682              :     else {
    1683            0 :         dlt_vlog(LOG_INFO, "Cannot open configuration file: %s\n", filename);
    1684              :     }
    1685              : 
    1686              :     return 0;
    1687              : }
    1688              : 
    1689           41 : int dlt_daemon_user_send_log_level(DltDaemon *daemon, DltDaemonContext *context, int verbose)
    1690              : {
    1691              :     DltUserHeader userheader;
    1692              :     DltUserControlMsgLogLevel usercontext;
    1693              :     DltReturnValue ret;
    1694              :     DltDaemonApplication *app;
    1695              : 
    1696           41 :     PRINT_FUNCTION_VERBOSE(verbose);
    1697              : 
    1698           41 :     if ((daemon == NULL) || (context == NULL)) {
    1699            0 :         dlt_vlog(LOG_ERR, "NULL parameter in %s", __func__);
    1700            0 :         return -1;
    1701              :     }
    1702              : 
    1703           41 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_LEVEL) < DLT_RETURN_OK) {
    1704            0 :         dlt_vlog(LOG_ERR, "Failed to set userheader in %s", __func__);
    1705            0 :         return -1;
    1706              :     }
    1707              : 
    1708           41 :     if ((context->storage_log_level != DLT_LOG_DEFAULT) &&
    1709           34 :         (daemon->maintain_logstorage_loglevel != DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_OFF))
    1710           32 :             usercontext.log_level = (uint8_t) (context->log_level >
    1711              :                 context->storage_log_level ? context->log_level : context->storage_log_level);
    1712              :     else /* Storage log level is not updated (is DEFAULT) then  no device is yet connected so ignore */
    1713            9 :         usercontext.log_level =
    1714            9 :             (uint8_t) ((context->log_level == DLT_LOG_DEFAULT) ? daemon->default_log_level : context->log_level);
    1715              : 
    1716           41 :     usercontext.trace_status =
    1717           41 :         (uint8_t) ((context->trace_status == DLT_TRACE_STATUS_DEFAULT) ? daemon->default_trace_status : context->trace_status);
    1718              : 
    1719           41 :     usercontext.log_level_pos = context->log_level_pos;
    1720              : 
    1721           41 :     dlt_vlog(LOG_NOTICE, "Send log-level to context: %.4s:%.4s [%i -> %i] [%i -> %i]\n",
    1722           41 :              context->apid,
    1723           41 :              context->ctid,
    1724           41 :              context->log_level,
    1725           41 :              usercontext.log_level,
    1726              :              context->trace_status,
    1727              :              usercontext.trace_status);
    1728              : 
    1729              :     /* log to FIFO */
    1730           41 :     errno = 0;
    1731           41 :     ret = dlt_user_log_out2_with_timeout(context->user_handle,
    1732              :                             &(userheader), sizeof(DltUserHeader),
    1733              :                             &(usercontext), sizeof(DltUserControlMsgLogLevel));
    1734              : 
    1735           41 :     if (ret < DLT_RETURN_OK) {
    1736            0 :         dlt_vlog(LOG_ERR, "Failed to send data to application in %s: %s",
    1737              :                  __func__,
    1738            0 :                  errno != 0 ? strerror(errno) : "Unknown error");
    1739              : 
    1740            0 :         if (errno == EPIPE || errno == EBADF) {
    1741            0 :             app = dlt_daemon_application_find(daemon, context->apid, daemon->ecuid, verbose);
    1742            0 :             if (app != NULL)
    1743            0 :                 dlt_daemon_application_reset_user_handle(daemon, app, verbose);
    1744              :         }
    1745              :     }
    1746              : 
    1747           41 :     return (ret == DLT_RETURN_OK) ? DLT_RETURN_OK : DLT_RETURN_ERROR;
    1748              : }
    1749              : 
    1750            9 : int dlt_daemon_user_send_log_state(DltDaemon *daemon, DltDaemonApplication *app, int verbose)
    1751              : {
    1752              :     DltUserHeader userheader;
    1753              :     DltUserControlMsgLogState logstate;
    1754              :     DltReturnValue ret;
    1755              : 
    1756            9 :     PRINT_FUNCTION_VERBOSE(verbose);
    1757              : 
    1758            9 :     if ((daemon == NULL) || (app == NULL))
    1759              :         return -1;
    1760              : 
    1761            9 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_STATE) < DLT_RETURN_OK)
    1762              :         return -1;
    1763              : 
    1764            9 :     logstate.log_state = daemon->connectionState;
    1765              : 
    1766              :     /* log to FIFO */
    1767            9 :     ret = dlt_user_log_out2_with_timeout(app->user_handle,
    1768              :                             &(userheader), sizeof(DltUserHeader),
    1769              :                             &(logstate), sizeof(DltUserControlMsgLogState));
    1770              : 
    1771            9 :     if (ret < DLT_RETURN_OK) {
    1772            0 :         if (errno == EPIPE || errno == EBADF)
    1773            0 :             dlt_daemon_application_reset_user_handle(daemon, app, verbose);
    1774              :     }
    1775              : 
    1776            9 :     return (ret == DLT_RETURN_OK) ? DLT_RETURN_OK : DLT_RETURN_ERROR;
    1777              : }
    1778              : 
    1779            0 : void dlt_daemon_control_reset_to_factory_default(DltDaemon *daemon,
    1780              :                                                  const char *filename,
    1781              :                                                  const char *filename1,
    1782              :                                                  int InitialContextLogLevel,
    1783              :                                                  int InitialContextTraceStatus,
    1784              :                                                  int InitialEnforceLlTsStatus,
    1785              :                                                  int verbose)
    1786              : {
    1787              :     FILE *fd;
    1788              : 
    1789            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1790              : 
    1791            0 :     if ((daemon == NULL) || (filename == NULL) || (filename1 == NULL)) {
    1792            0 :         dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n");
    1793            0 :         return;
    1794              :     }
    1795              : 
    1796            0 :     if ((filename[0] == '\0') || (filename1[0] == '\0')) {
    1797            0 :         dlt_log(LOG_WARNING, "Wrong parameter: Empty string\n");
    1798            0 :         return;
    1799              :     }
    1800              : 
    1801              :     /* Check for runtime cfg file and delete it, if available */
    1802            0 :     fd = fopen(filename, "r");
    1803              : 
    1804            0 :     if (fd != NULL) {
    1805              :         /* Close and delete file */
    1806            0 :         fclose(fd);
    1807            0 :         if (unlink(filename) != 0) {
    1808            0 :             dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n",
    1809            0 :                     __func__, strerror(errno));
    1810              :         }
    1811              :     }
    1812              : 
    1813            0 :     fd = fopen(filename1, "r");
    1814              : 
    1815            0 :     if (fd != NULL) {
    1816              :         /* Close and delete file */
    1817            0 :         fclose(fd);
    1818            0 :         if (unlink(filename1) != 0) {
    1819            0 :             dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n",
    1820            0 :                     __func__, strerror(errno));
    1821              :         }
    1822              :     }
    1823              : 
    1824            0 :     daemon->default_log_level = (int8_t) InitialContextLogLevel;
    1825            0 :     daemon->default_trace_status = (int8_t) InitialContextTraceStatus;
    1826            0 :     daemon->force_ll_ts = (int8_t) InitialEnforceLlTsStatus;
    1827              : 
    1828              :     /* Reset all other things (log level, trace status, etc.
    1829              :      *                         to default values             */
    1830              : 
    1831              :     /* Inform user libraries about changed default log level/trace status */
    1832            0 :     dlt_daemon_user_send_default_update(daemon, verbose);
    1833              : }
    1834              : 
    1835            0 : void dlt_daemon_user_send_default_update(DltDaemon *daemon, int verbose)
    1836              : {
    1837              :     int32_t count;
    1838              :     DltDaemonContext *context;
    1839              :     DltDaemonRegisteredUsers *user_list = NULL;
    1840              : 
    1841            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1842              : 
    1843            0 :     if (daemon == NULL) {
    1844            0 :         dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n");
    1845            0 :         return;
    1846              :     }
    1847              : 
    1848            0 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    1849              : 
    1850            0 :     if (user_list == NULL)
    1851              :         return;
    1852              : 
    1853            0 :     for (count = 0; count < user_list->num_contexts; count++) {
    1854            0 :         context = &(user_list->contexts[count]);
    1855              : 
    1856            0 :         if (context != NULL) {
    1857            0 :             if ((context->log_level == DLT_LOG_DEFAULT) ||
    1858            0 :                 (context->trace_status == DLT_TRACE_STATUS_DEFAULT)) {
    1859            0 :                 if (context->user_handle >= DLT_FD_MINIMUM)
    1860            0 :                     if (dlt_daemon_user_send_log_level(daemon,
    1861              :                                                        context,
    1862              :                                                        verbose) == -1)
    1863            0 :                         dlt_vlog(LOG_WARNING, "Cannot update default of %.4s:%.4s\n", context->apid, context->ctid);
    1864              :             }
    1865              :         }
    1866              :     }
    1867              : }
    1868              : 
    1869            0 : void dlt_daemon_user_send_all_log_level_update(DltDaemon *daemon,
    1870              :                                                int enforce_context_ll_and_ts,
    1871              :                                                int8_t context_log_level,
    1872              :                                                int8_t log_level,
    1873              :                                                int verbose)
    1874              : {
    1875              :     int32_t count = 0;
    1876              :     DltDaemonContext *context = NULL;
    1877              :     DltDaemonRegisteredUsers *user_list = NULL;
    1878              : 
    1879            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1880              : 
    1881            0 :     if (daemon == NULL)
    1882              :         return;
    1883              : 
    1884            0 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    1885              : 
    1886            0 :     if (user_list == NULL)
    1887              :         return;
    1888              : 
    1889            0 :     for (count = 0; count < user_list->num_contexts; count++) {
    1890            0 :         context = &(user_list->contexts[count]);
    1891              : 
    1892            0 :         if (context) {
    1893            0 :             if (context->user_handle >= DLT_FD_MINIMUM) {
    1894            0 :                 context->log_level = log_level;
    1895              : 
    1896            0 :                 if (enforce_context_ll_and_ts) {
    1897              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    1898              :                     DltDaemonContextLogSettings *settings =
    1899              :                         dlt_daemon_find_configured_app_id_ctx_id_settings(
    1900              :                             daemon, context->apid, context->ctid);
    1901              :                     if (settings != NULL) {
    1902              :                         if (log_level > settings->log_level) {
    1903              :                           context->log_level = settings->log_level;
    1904              :                         }
    1905              :                     } else
    1906              : #endif
    1907            0 :                     if (log_level > context_log_level) {
    1908            0 :                         context->log_level = (int8_t)context_log_level;
    1909              :                     }
    1910              :                 }
    1911              : 
    1912            0 :                 if (dlt_daemon_user_send_log_level(daemon,
    1913              :                                                    context,
    1914              :                                                    verbose) == -1)
    1915            0 :                     dlt_vlog(LOG_WARNING,
    1916              :                              "Cannot send log level %.4s:%.4s -> %i\n",
    1917            0 :                              context->apid,
    1918            0 :                              context->ctid,
    1919            0 :                              context->log_level);
    1920              :             }
    1921              :         }
    1922              :     }
    1923              : }
    1924              : 
    1925            0 : void dlt_daemon_user_send_all_trace_status_update(DltDaemon *daemon, int8_t trace_status, int verbose)
    1926              : {
    1927              :     int32_t count = 0;
    1928              :     DltDaemonContext *context = NULL;
    1929              :     DltDaemonRegisteredUsers *user_list = NULL;
    1930              : 
    1931            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1932              : 
    1933            0 :     if (daemon == NULL)
    1934              :         return;
    1935              : 
    1936            0 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    1937              : 
    1938            0 :     if (user_list == NULL)
    1939              :         return;
    1940              : 
    1941            0 :     dlt_vlog(LOG_NOTICE, "All trace status is updated -> %i\n", trace_status);
    1942              : 
    1943            0 :     for (count = 0; count < user_list->num_contexts; count++) {
    1944            0 :         context = &(user_list->contexts[count]);
    1945              : 
    1946            0 :         if (context) {
    1947            0 :             if (context->user_handle >= DLT_FD_MINIMUM) {
    1948            0 :                 context->trace_status = trace_status;
    1949              : 
    1950            0 :                 if (dlt_daemon_user_send_log_level(daemon, context, verbose) == -1)
    1951            0 :                     dlt_vlog(LOG_WARNING,
    1952              :                              "Cannot send trace status %.4s:%.4s -> %i\n",
    1953            0 :                              context->apid,
    1954            0 :                              context->ctid,
    1955            0 :                              context->trace_status);
    1956              :             }
    1957              :         }
    1958              :     }
    1959              : }
    1960              : 
    1961            5 : void dlt_daemon_user_send_all_log_state(DltDaemon *daemon, int verbose)
    1962              : {
    1963              :     int32_t count;
    1964              :     DltDaemonApplication *app;
    1965              :     DltDaemonRegisteredUsers *user_list = NULL;
    1966              : 
    1967            5 :     PRINT_FUNCTION_VERBOSE(verbose);
    1968              : 
    1969            5 :     if (daemon == NULL) {
    1970            0 :         dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n");
    1971            0 :         return;
    1972              :     }
    1973              : 
    1974            5 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    1975              : 
    1976            5 :     if (user_list == NULL)
    1977              :         return;
    1978              : 
    1979            7 :     for (count = 0; count < user_list->num_applications; count++) {
    1980            2 :         app = &(user_list->applications[count]);
    1981              : 
    1982            2 :         if (app != NULL) {
    1983            2 :             if (app->user_handle >= DLT_FD_MINIMUM)
    1984            2 :                 if (dlt_daemon_user_send_log_state(daemon, app, verbose) == -1)
    1985            0 :                     dlt_vlog(LOG_WARNING, "Cannot send log state to Apid: %.4s, PID: %d\n", app->apid, app->pid);
    1986              :         }
    1987              :     }
    1988              : }
    1989              : 
    1990           16 : void dlt_daemon_change_state(DltDaemon *daemon, DltDaemonState newState)
    1991              : {
    1992           16 :     switch (newState) {
    1993            0 :     case DLT_DAEMON_STATE_INIT:
    1994            0 :         dlt_log(LOG_INFO, "Switched to init state.\n");
    1995            0 :         daemon->state = DLT_DAEMON_STATE_INIT;
    1996            0 :         break;
    1997           12 :     case DLT_DAEMON_STATE_BUFFER:
    1998           12 :         dlt_log(LOG_INFO, "Switched to buffer state for socket connections.\n");
    1999           12 :         daemon->state = DLT_DAEMON_STATE_BUFFER;
    2000           12 :         break;
    2001            0 :     case DLT_DAEMON_STATE_BUFFER_FULL:
    2002            0 :         dlt_log(LOG_INFO, "Switched to buffer full state.\n");
    2003            0 :         daemon->state = DLT_DAEMON_STATE_BUFFER_FULL;
    2004            0 :         break;
    2005            2 :     case DLT_DAEMON_STATE_SEND_BUFFER:
    2006            2 :         dlt_log(LOG_INFO, "Switched to send buffer state for socket connections.\n");
    2007            2 :         daemon->state = DLT_DAEMON_STATE_SEND_BUFFER;
    2008            2 :         break;
    2009            2 :     case DLT_DAEMON_STATE_SEND_DIRECT:
    2010            2 :         dlt_log(LOG_INFO, "Switched to send direct state.\n");
    2011            2 :         daemon->state = DLT_DAEMON_STATE_SEND_DIRECT;
    2012            2 :         break;
    2013              :     }
    2014           16 : }
    2015              : 
    2016              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
    2017              : bool dlt_daemon_trigger_systemd_watchdog_if_necessary(DltDaemon *daemon) {
    2018              :     if (daemon->watchdog_trigger_interval == 0) {
    2019              :         return false;
    2020              :     }
    2021              : 
    2022              :     const unsigned int uptime_seconds = dlt_uptime() / 10000;
    2023              :     const unsigned int seconds_since_last_trigger = uptime_seconds - daemon->watchdog_last_trigger_time;
    2024              :     if (seconds_since_last_trigger < daemon->watchdog_trigger_interval) {
    2025              :         return false;
    2026              :     }
    2027              :     if (sd_notify(0, "WATCHDOG=1") < 0) {
    2028              :         dlt_vlog(LOG_WARNING, "%s: Could not reset systemd watchdog\n", __func__);
    2029              :         return false;
    2030              :     }
    2031              :     else
    2032              :         daemon->watchdog_last_trigger_time = uptime_seconds;
    2033              : 
    2034              :     return true;
    2035              : }
    2036              : 
    2037              : #endif
    2038              : 
    2039              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    2040              : int dlt_daemon_user_send_trace_load_config(DltDaemon *const daemon, DltDaemonApplication *app, const int verbose)
    2041              : {
    2042              :     DltUserHeader userheader;
    2043              :     DltUserControlMsgTraceSettingMsg* trace_load_settings_user_msg;
    2044              :     uint32_t trace_load_settings_count;
    2045              :     DltReturnValue ret;
    2046              : 
    2047              : 
    2048              :     PRINT_FUNCTION_VERBOSE(verbose);
    2049              : 
    2050              :     if ((daemon == NULL) || (app == NULL)) return -1;
    2051              : 
    2052              :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_TRACE_LOAD) < DLT_RETURN_OK) return -1;
    2053              : 
    2054              :     DltTraceLoadSettings* app_settings = app->trace_load_settings;
    2055              : 
    2056              :     if (app_settings != NULL) {
    2057              :         trace_load_settings_count = app->trace_load_settings_count;
    2058              :         trace_load_settings_user_msg = malloc(sizeof(DltUserControlMsgTraceSettingMsg) * trace_load_settings_count);
    2059              :         for (uint32_t i = 0U; i < trace_load_settings_count; i++) {
    2060              :             // App id is not transmitted as the user library only
    2061              :             // has one application ID
    2062              :             memcpy(trace_load_settings_user_msg[i].ctid, app_settings[i].ctid, DLT_ID_SIZE);
    2063              :             trace_load_settings_user_msg[i].soft_limit = app_settings[i].soft_limit;
    2064              :             trace_load_settings_user_msg[i].hard_limit = app_settings[i].hard_limit;
    2065              : 
    2066              :             if (app_settings[i].ctid[0] == '\0') {
    2067              :                 dlt_vlog(LOG_NOTICE, "Sending trace load config to app %.4s, soft limit %u, hard limit %u\n",
    2068              :                          app->apid,
    2069              :                          app_settings[i].soft_limit,
    2070              :                          app_settings[i].hard_limit);
    2071              :             } else {
    2072              :                 dlt_vlog(LOG_NOTICE, "Sending trace load config to app %.4s, ctid %.4s, soft limit %u, hard limit %u\n",
    2073              :                          app->apid,
    2074              :                          app_settings[i].ctid,
    2075              :                          app_settings[i].soft_limit,
    2076              :                          app_settings[i].hard_limit);
    2077              :             }
    2078              : 
    2079              :         }
    2080              :     }
    2081              :     else {
    2082              :         dlt_vlog(LOG_INFO,
    2083              :                  "No trace load settings for application %s, setting daemon defaults.\n", app->apid);
    2084              : 
    2085              :         trace_load_settings_count = 1;
    2086              :         trace_load_settings_user_msg = malloc(sizeof(DltUserControlMsgTraceSettingMsg));
    2087              : 
    2088              :         memset(trace_load_settings_user_msg, 0, sizeof(DltTraceLoadSettings));
    2089              :         trace_load_settings_user_msg[0].soft_limit = DLT_TRACE_LOAD_DAEMON_SOFT_LIMIT_DEFAULT;
    2090              :         trace_load_settings_user_msg[0].hard_limit = DLT_TRACE_LOAD_DAEMON_HARD_LIMIT_DEFAULT;
    2091              :     }
    2092              : 
    2093              :     /* log to FIFO */
    2094              :     ret = dlt_user_log_out3_with_timeout(app->user_handle,
    2095              :                                          &(userheader), sizeof(DltUserHeader),
    2096              :                                          &(trace_load_settings_count), sizeof(uint32_t),
    2097              :                                          trace_load_settings_user_msg, sizeof(DltUserControlMsgTraceSettingMsg) * trace_load_settings_count);
    2098              : 
    2099              :     if (ret < DLT_RETURN_OK) {
    2100              :         if (errno == EPIPE || errno == EBADF)
    2101              :             dlt_daemon_application_reset_user_handle(daemon, app, verbose);
    2102              :     }
    2103              : 
    2104              :     free(trace_load_settings_user_msg);
    2105              : 
    2106              :     return ret;
    2107              : }
    2108              : #endif
        

Generated by: LCOV version 2.0-1