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.4 % 624 352
Test Date: 2025-12-12 09:13:23 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              :     const DltDaemonApplication *mi1 = (const DltDaemonApplication *)m1;
     102              :     const DltDaemonApplication *mi2 = (const 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              :     const DltDaemonContext *mi1 = (const DltDaemonContext *)m1;
     114              :     const DltDaemonContext *mi2 = (const 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((size_t)sizeof(DltDaemonApplication) *
     645            0 :                            ((size_t)(user_list->num_applications / DLT_DAEMON_APPL_ALLOC_SIZE) + 1) *
     646              :                            (size_t)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 :                       (size_t)sizeof(DltDaemonApplication) * (size_t)user_list->num_applications);
     657            0 :                 free(old);
     658              :             }
     659              :         }
     660              : 
     661           10 :         application = &(user_list->applications[(size_t)(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              :             int ret = snprintf(filename,
     724              :                             DLT_DAEMON_COMMON_TEXTBUFSIZE,
     725              :                             "%s/dltpipes/dlt%d",
     726              :                             dltFifoBaseDir,
     727              :                             (int)pid);
     728            9 :             if (ret < 0 || ret >= DLT_DAEMON_COMMON_TEXTBUFSIZE) {
     729            0 :                 filename[0] = '\0';
     730              :             }
     731              : 
     732              :             dlt_user_handle = open(filename, O_WRONLY | O_NONBLOCK);
     733              : 
     734            9 :             if (dlt_user_handle < 0) {
     735            0 :                 int prio = (errno == ENOENT) ? LOG_INFO : LOG_WARNING;
     736            0 :                 dlt_vlog(prio, "open() failed to %s, errno=%d (%s)!\n", filename, errno, strerror(errno));
     737              :             } else {
     738              :                 owns_user_handle = true;
     739              :             }
     740              :         }
     741              : #endif
     742              :         /* check if file descriptor was already used, and make it invalid if it
     743              :         * is reused. This prevents sending messages to wrong file descriptor */
     744            9 :         dlt_daemon_applications_invalidate_fd(daemon, ecu, dlt_user_handle, verbose);
     745            9 :         dlt_daemon_contexts_invalidate_fd(daemon, ecu, dlt_user_handle, verbose);
     746              : 
     747            9 :         application->user_handle = dlt_user_handle;
     748            9 :         application->owns_user_handle = owns_user_handle;
     749            9 :         application->pid = pid;
     750              :     }
     751              : 
     752              :     /* Sort */
     753           10 :     if (new_application) {
     754           10 :         qsort(user_list->applications,
     755           10 :               (size_t) user_list->num_applications,
     756              :               sizeof(DltDaemonApplication),
     757              :               dlt_daemon_cmp_apid);
     758              : 
     759              :         /* Find new position of application with apid*/
     760           10 :         application = dlt_daemon_application_find(daemon, apid, ecu, verbose);
     761              :     }
     762              : 
     763              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
     764              :     application->num_context_log_level_settings = 0;
     765              :     application->context_log_level_settings = NULL;
     766              : #endif
     767              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     768              :     if (application->trace_load_settings == NULL) {
     769              :         DltTraceLoadSettings* pre_configured_trace_load_settings = NULL;
     770              :         int num_settings = 0;
     771              :         DltReturnValue find_trace_settings_return_value = dlt_daemon_find_preconfigured_trace_load_settings(
     772              :             daemon,
     773              :             application->apid,
     774              :             NULL /*load settings for all contexts*/,
     775              :             &pre_configured_trace_load_settings,
     776              :             &num_settings,
     777              :             verbose);
     778              : 
     779              :         DltTraceLoadSettings *app_level = NULL;
     780              :         if ((find_trace_settings_return_value == DLT_RETURN_OK) &&
     781              :             (pre_configured_trace_load_settings != NULL) &&
     782              :             (num_settings != 0)) {
     783              :             application->trace_load_settings = pre_configured_trace_load_settings;
     784              :             application->trace_load_settings_count = num_settings;
     785              :             app_level = dlt_find_runtime_trace_load_settings(
     786              :                 application->trace_load_settings,
     787              :                 application->trace_load_settings_count, application->apid,
     788              :                 NULL);
     789              :         }
     790              : 
     791              :         // app is not configured, set daemon defaults
     792              :         if (app_level == NULL) {
     793              :             DltTraceLoadSettings *temp = realloc(application->trace_load_settings,
     794              :                                                  (application->trace_load_settings_count + 1) *
     795              :                                                      sizeof(DltTraceLoadSettings));
     796              : 
     797              :             if (temp != NULL) {
     798              :                 application->trace_load_settings = temp;
     799              :                 ++application->trace_load_settings_count;
     800              : 
     801              :                 app_level = &application->trace_load_settings[application->trace_load_settings_count - 1];
     802              :                 memset(app_level, 0, sizeof(DltTraceLoadSettings));
     803              :                 app_level[0].hard_limit = DLT_TRACE_LOAD_DAEMON_HARD_LIMIT_DEFAULT;
     804              :                 app_level[0].soft_limit = DLT_TRACE_LOAD_DAEMON_SOFT_LIMIT_DEFAULT;
     805              :                 memcpy(&app_level[0].apid, apid, DLT_ID_SIZE);
     806              :                 memset(&app_level[0].tl_stat, 0, sizeof(DltTraceLoadStat));
     807              :             } else {
     808              :                 dlt_vlog(DLT_LOG_FATAL, "Failed to allocate memory for trace load settings\n");
     809              :             }
     810              : 
     811              :             // We inserted the application id at the end, to make sure
     812              :             // Lookups are working properly later on, we have to sort the list again.
     813              :             qsort(application->trace_load_settings,
     814              :                   (size_t)application->trace_load_settings_count,
     815              :                   sizeof(DltTraceLoadSettings),
     816              :                   dlt_daemon_compare_trace_load_settings);
     817              :         }
     818              :     }
     819              : 
     820              : #endif
     821              : 
     822              :     return application;
     823              : }
     824              : 
     825            6 : int dlt_daemon_application_del(DltDaemon *daemon,
     826              :                                DltDaemonApplication *application,
     827              :                                char *ecu,
     828              :                                int verbose)
     829              : {
     830              :     int pos;
     831              :     DltDaemonRegisteredUsers *user_list = NULL;
     832              : 
     833            6 :     PRINT_FUNCTION_VERBOSE(verbose);
     834              : 
     835            6 :     if ((daemon == NULL) || (application == NULL) || (ecu == NULL))
     836              :         return -1;
     837              : 
     838            6 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
     839              : 
     840            6 :     if (user_list == NULL)
     841              :         return -1;
     842              : 
     843            6 :     if (user_list->num_applications > 0) {
     844            6 :         dlt_daemon_application_reset_user_handle(daemon, application, verbose);
     845              : 
     846              :         /* Free description of application to be deleted */
     847            6 :         if (application->application_description) {
     848            6 :             free(application->application_description);
     849            6 :             application->application_description = NULL;
     850              :         }
     851              : 
     852              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
     853              :         if (application->trace_load_settings != NULL) {
     854              :             free(application->trace_load_settings);
     855              :             application->trace_load_settings = NULL;
     856              :             application->trace_load_settings_count = 0;
     857              :         }
     858              : #endif
     859            6 :         pos = (int) (application - (user_list->applications));
     860              : 
     861              :         /* move all applications above pos to pos */
     862            6 :         memmove(&(user_list->applications[pos]),
     863            6 :                 &(user_list->applications[pos + 1]),
     864            6 :                 (size_t)sizeof(DltDaemonApplication) * (size_t)((user_list->num_applications - 1) - pos));
     865              : 
     866              :         /* Clear last application */
     867            6 :          memset(&(user_list->applications[(size_t)(user_list->num_applications - 1)]),
     868              :                 0,
     869              :                 (size_t)sizeof(DltDaemonApplication));
     870              : 
     871            6 :         user_list->num_applications--;
     872              :     }
     873              : 
     874              :     return 0;
     875              : }
     876              : 
     877          149 : DltDaemonApplication *dlt_daemon_application_find(DltDaemon *daemon,
     878              :                                                   char *apid,
     879              :                                                   char *ecu,
     880              :                                                   int verbose)
     881              : {
     882              :     DltDaemonApplication application;
     883              :     DltDaemonRegisteredUsers *user_list = NULL;
     884              : 
     885          149 :     PRINT_FUNCTION_VERBOSE(verbose);
     886              : 
     887          149 :     if ((daemon == NULL) || (daemon->user_list == NULL) || (apid == NULL) ||
     888          149 :         (apid[0] == '\0') || (ecu == NULL))
     889              :         return (DltDaemonApplication *)NULL;
     890              : 
     891          149 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
     892              : 
     893          149 :     if ((user_list == NULL) || (user_list->num_applications == 0))
     894              :         return (DltDaemonApplication *)NULL;
     895              : 
     896              :     /* Check, if apid is smaller than smallest apid or greater than greatest apid */
     897          132 :     if ((memcmp(apid, user_list->applications[0].apid, DLT_ID_SIZE) < 0) ||
     898          132 :         (memcmp(apid,
     899          132 :                 user_list->applications[user_list->num_applications - 1].apid,
     900              :                 DLT_ID_SIZE) > 0))
     901              :         return (DltDaemonApplication *)NULL;
     902              : 
     903          132 :     dlt_set_id(application.apid, apid);
     904          132 :     return (DltDaemonApplication *)bsearch(&application,
     905          132 :                                            user_list->applications,
     906          132 :                                            (size_t) user_list->num_applications,
     907              :                                            sizeof(DltDaemonApplication),
     908              :                                            dlt_daemon_cmp_apid);
     909              : }
     910              : 
     911            9 : int dlt_daemon_applications_load(DltDaemon *daemon, const char *filename, int verbose)
     912              : {
     913              :     FILE *fd;
     914              :     ID4 apid;
     915              :     char buf[DLT_DAEMON_COMMON_TEXTBUFSIZE];
     916              :     char *ret;
     917              :     char *pb;
     918              : 
     919            9 :     PRINT_FUNCTION_VERBOSE(verbose);
     920              : 
     921            9 :     if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
     922              :         return -1;
     923              : 
     924            9 :     fd = fopen(filename, "r");
     925              : 
     926            9 :     if (fd == NULL) {
     927            9 :         dlt_vlog(LOG_WARNING,
     928              :                  "%s: cannot open file %s: %s\n",
     929              :                  __func__,
     930              :                  filename,
     931            9 :                  strerror(errno));
     932              : 
     933            9 :         return -1;
     934              :     }
     935              : 
     936            0 :     while (!feof(fd)) {
     937              :         /* Clear buf */
     938              :         memset(buf, 0, sizeof(buf));
     939              : 
     940              :         /* Get line */
     941              :         ret = fgets(buf, sizeof(buf), fd);
     942              : 
     943            0 :         if (NULL == ret) {
     944              :             /* fgets always null pointer if the last byte of the file is a new line
     945              :              * We need to check here if there was an error or was it feof.*/
     946            0 :             if (ferror(fd)) {
     947            0 :                 dlt_vlog(LOG_WARNING,
     948              :                          "%s: fgets(buf,sizeof(buf),fd) returned NULL. %s\n",
     949              :                          __func__,
     950            0 :                          strerror(errno));
     951            0 :                 fclose(fd);
     952            0 :                 return -1;
     953              :             }
     954            0 :             else if (feof(fd))
     955              :             {
     956            0 :                 fclose(fd);
     957            0 :                 return 0;
     958              :             }
     959              :             else {
     960            0 :                 dlt_vlog(LOG_WARNING,
     961              :                          "%s: fgets(buf,sizeof(buf),fd) returned NULL. Unknown error.\n",
     962              :                          __func__);
     963            0 :                 fclose(fd);
     964            0 :                 return -1;
     965              :             }
     966              :         }
     967              : 
     968            0 :         if (strcmp(buf, "") != 0) {
     969              :             /* Split line */
     970            0 :             pb = strtok(buf, ":");
     971              : 
     972            0 :             if (pb != NULL) {
     973            0 :                 dlt_set_id(apid, pb);
     974            0 :                 pb = strtok(NULL, ":");
     975              : 
     976            0 :                 if (pb != NULL) {
     977              :                     /* pb contains now the description */
     978              :                     /* pid is unknown at loading time */
     979            0 :                     if (dlt_daemon_application_add(daemon,
     980              :                                                    apid,
     981              :                                                    0,
     982              :                                                    pb,
     983              :                                                    -1,
     984            0 :                                                    daemon->ecuid,
     985              :                                                    verbose) == 0) {
     986            0 :                         dlt_vlog(LOG_WARNING,
     987              :                                  "%s: dlt_daemon_application_add failed for %4s\n",
     988              :                                  __func__,
     989              :                                  apid);
     990            0 :                         fclose(fd);
     991            0 :                         return -1;
     992              :                     }
     993              :                 }
     994              :             }
     995              :         }
     996              :     }
     997              : 
     998            0 :     fclose(fd);
     999              : 
    1000            0 :     return 0;
    1001              : }
    1002              : 
    1003            0 : int dlt_daemon_applications_save(DltDaemon *daemon, const char *filename, int verbose)
    1004              : {
    1005              :     FILE *fd;
    1006              :     int i;
    1007              : 
    1008              :     char apid[DLT_ID_SIZE + 1]; /* DLT_ID_SIZE+1, because the 0-termination is required here */
    1009              :     DltDaemonRegisteredUsers *user_list = NULL;
    1010              : 
    1011            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1012              : 
    1013            0 :     if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
    1014              :         return -1;
    1015              : 
    1016              :     memset(apid, 0, sizeof(apid));
    1017              : 
    1018            0 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    1019              : 
    1020            0 :     if (user_list == NULL)
    1021              :         return -1;
    1022              : 
    1023            0 :     if ((user_list->applications != NULL) && (user_list->num_applications > 0)) {
    1024            0 :         fd = fopen(filename, "w");
    1025              : 
    1026            0 :         if (fd != NULL) {
    1027            0 :             for (i = 0; i < user_list->num_applications; i++) {
    1028            0 :                 dlt_set_id(apid, user_list->applications[i].apid);
    1029              : 
    1030            0 :                 if ((user_list->applications[i].application_description) &&
    1031            0 :                     (user_list->applications[i].application_description[0] != '\0'))
    1032              :                     fprintf(fd,
    1033              :                             "%s:%s:\n",
    1034              :                             apid,
    1035              :                             user_list->applications[i].application_description);
    1036              :                 else
    1037              :                     fprintf(fd, "%s::\n", apid);
    1038              :             }
    1039              : 
    1040            0 :             fclose(fd);
    1041              :         }
    1042              :         else {
    1043            0 :             dlt_vlog(LOG_ERR, "%s: open %s failed! No application information stored.\n",
    1044              :                      __func__,
    1045              :                      filename);
    1046              :         }
    1047              :     }
    1048              : 
    1049              :     return 0;
    1050              : }
    1051              : 
    1052           41 : DltDaemonContext *dlt_daemon_context_add(DltDaemon *daemon,
    1053              :                                          char *apid,
    1054              :                                          char *ctid,
    1055              :                                          int8_t log_level,
    1056              :                                          int8_t trace_status,
    1057              :                                          int log_level_pos,
    1058              :                                          int user_handle,
    1059              :                                          char *description,
    1060              :                                          char *ecu,
    1061              :                                          int verbose)
    1062              : {
    1063              :     DltDaemonApplication *application;
    1064              :     DltDaemonContext *context;
    1065              :     DltDaemonContext *old;
    1066              :     int new_context = 0;
    1067              :     DltDaemonRegisteredUsers *user_list = NULL;
    1068              : 
    1069           41 :     PRINT_FUNCTION_VERBOSE(verbose);
    1070              : 
    1071           41 :     if ((daemon == NULL) || (apid == NULL) || (apid[0] == '\0') ||
    1072           41 :         (ctid == NULL) || (ctid[0] == '\0') || (ecu == NULL))
    1073              :         return (DltDaemonContext *)NULL;
    1074              : 
    1075           41 :     if ((log_level < DLT_LOG_DEFAULT) || (log_level > DLT_LOG_VERBOSE))
    1076              :         return (DltDaemonContext *)NULL;
    1077              : 
    1078           41 :     if ((trace_status < DLT_TRACE_STATUS_DEFAULT) || (trace_status > DLT_TRACE_STATUS_ON))
    1079              :         return (DltDaemonContext *)NULL;
    1080              : 
    1081           41 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
    1082              : 
    1083           41 :     if (user_list == NULL)
    1084              :         return (DltDaemonContext *)NULL;
    1085              : 
    1086           41 :     if (user_list->contexts == NULL) {
    1087           10 :         user_list->contexts = (DltDaemonContext *)calloc(1, sizeof(DltDaemonContext) * DLT_DAEMON_CONTEXT_ALLOC_SIZE);
    1088              : 
    1089           10 :         if (user_list->contexts == NULL)
    1090              :             return (DltDaemonContext *)NULL;
    1091              :     }
    1092              : 
    1093              :     /* Check if application [apid] is available */
    1094           41 :     application = dlt_daemon_application_find(daemon, apid, ecu, verbose);
    1095              : 
    1096           41 :     if (application == NULL)
    1097              :         return (DltDaemonContext *)NULL;
    1098              : 
    1099              :     /* Check if context [apid, ctid] is already available */
    1100           41 :     context = dlt_daemon_context_find(daemon, apid, ctid, ecu, verbose);
    1101              : 
    1102           41 :     if (context == NULL) {
    1103           41 :         user_list->num_contexts += 1;
    1104              : 
    1105           41 :         if (user_list->num_contexts != 0) {
    1106           41 :             if ((user_list->num_contexts % DLT_DAEMON_CONTEXT_ALLOC_SIZE) == 0) {
    1107              :                 /* allocate memory for context in steps of DLT_DAEMON_CONTEXT_ALLOC_SIZE, e.g 100 */
    1108            0 :                 old = user_list->contexts;
    1109            0 :                 user_list->contexts = (DltDaemonContext *)calloc(1, (size_t) sizeof(DltDaemonContext) *
    1110            0 :                                                                 ((size_t)(user_list->num_contexts /
    1111              :                                                                 DLT_DAEMON_CONTEXT_ALLOC_SIZE) + 1) *
    1112              :                                                                 (size_t)DLT_DAEMON_CONTEXT_ALLOC_SIZE);
    1113              : 
    1114            0 :                 if (user_list->contexts == NULL) {
    1115            0 :                     user_list->contexts = old;
    1116            0 :                     user_list->num_contexts -= 1;
    1117            0 :                     return (DltDaemonContext *)NULL;
    1118              :                 }
    1119              : 
    1120            0 :                 memcpy(user_list->contexts,
    1121              :                         old,
    1122            0 :                         (size_t) sizeof(DltDaemonContext) * (size_t)user_list->num_contexts);
    1123            0 :                 free(old);
    1124              :             }
    1125              :         }
    1126              : 
    1127           41 :         context = &(user_list->contexts[(size_t)(user_list->num_contexts - 1)]);
    1128              :         memset(context, 0, sizeof(DltDaemonContext));
    1129              : 
    1130           41 :         dlt_set_id(context->apid, apid);
    1131           41 :         dlt_set_id(context->ctid, ctid);
    1132              : 
    1133              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1134              :         context->trace_load_settings = NULL;
    1135              : #endif
    1136              : 
    1137           41 :         application->num_contexts++;
    1138              :         new_context = 1;
    1139              :     }
    1140              : 
    1141              :     /* Set context description */
    1142           41 :     if (context->context_description) {
    1143            0 :         free(context->context_description);
    1144            0 :         context->context_description = NULL;
    1145              :     }
    1146              : 
    1147           41 :     if (description != NULL) {
    1148           41 :         context->context_description = malloc(strlen(description) + 1);
    1149              : 
    1150           41 :         if (context->context_description) {
    1151           41 :             memcpy(context->context_description, description, strlen(description) + 1);
    1152              :         }
    1153              :     }
    1154              : 
    1155              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    1156              :     /* configure initial log level */
    1157              :     DltDaemonContextLogSettings *settings = NULL;
    1158              :     settings = dlt_daemon_find_configured_app_id_ctx_id_settings(
    1159              :             daemon, context->apid, ctid);
    1160              : 
    1161              :     if (settings != NULL) {
    1162              :         /* set log level */
    1163              :         log_level = settings->log_level;
    1164              : 
    1165              :         DltDaemonContextLogSettings *ct_settings = NULL;
    1166              :         ct_settings = dlt_daemon_find_app_log_level_config(application, ctid);
    1167              : 
    1168              :         /* ct_settings != null: context and app id combination already exists */
    1169              :         if (ct_settings == NULL) {
    1170              :           /* copy the configuration into the DltDaemonApplication for faster access later */
    1171              :           DltDaemonContextLogSettings *tmp =
    1172              :               realloc(application->context_log_level_settings,
    1173              :                       (++application->num_context_log_level_settings) *
    1174              :                           sizeof(DltDaemonContextLogSettings));
    1175              :           application->context_log_level_settings = tmp;
    1176              : 
    1177              :           ct_settings =
    1178              :               &application->context_log_level_settings[application->num_context_log_level_settings - 1];
    1179              :           memcpy(ct_settings, settings, sizeof(DltDaemonContextLogSettings));
    1180              :           memcpy(ct_settings->ctid, ctid, DLT_ID_SIZE);
    1181              :       }
    1182              :     }
    1183              : #endif
    1184              : 
    1185           41 :     if ((strncmp(daemon->ecuid, ecu, DLT_ID_SIZE) == 0) && (daemon->force_ll_ts)) {
    1186              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    1187              :         if (log_level > daemon->default_log_level && settings == NULL)
    1188              : #else
    1189            0 :         if (log_level > daemon->default_log_level)
    1190              : #endif
    1191              :             log_level = daemon->default_log_level;
    1192              : 
    1193            0 :         if (trace_status > daemon->default_trace_status)
    1194              :             trace_status = daemon->default_trace_status;
    1195              : 
    1196            0 :         dlt_vlog(LOG_NOTICE,
    1197              :             "Adapting ll_ts for context: %.4s:%.4s with %i %i\n",
    1198              :             apid,
    1199              :             ctid,
    1200              :             log_level,
    1201              :             trace_status);
    1202              :     }
    1203              : 
    1204              :     /* Store log level and trace status,
    1205              :      * if this is a new context, or
    1206              :      * if this is an old context and the runtime cfg was not loaded */
    1207           41 :     if ((new_context == 1) ||
    1208            0 :         ((new_context == 0) && (daemon->runtime_context_cfg_loaded == 0))) {
    1209           41 :         context->log_level = log_level;
    1210           41 :         context->trace_status = trace_status;
    1211              :     }
    1212              : 
    1213           41 :     context->log_level_pos = log_level_pos;
    1214           41 :     context->user_handle = user_handle;
    1215              : 
    1216              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    1217              :     DltTraceLoadSettings* tl_settings = dlt_find_runtime_trace_load_settings(
    1218              :         application->trace_load_settings,
    1219              :         application->trace_load_settings_count,
    1220              :         application->apid,
    1221              :         context->ctid);
    1222              :     if (tl_settings == NULL) {
    1223              :         dlt_vlog(LOG_WARNING, "failed to find trace load settings for application %s context %s\n",
    1224              :                  application->apid, context->ctid);
    1225              :     } else {
    1226              :         context->trace_load_settings = tl_settings;
    1227              :     }
    1228              : #endif
    1229              : 
    1230              : 
    1231              :     /* In case a context is loaded from runtime config file,
    1232              :      * the user_handle is 0 and we mark that context as predefined.
    1233              :      */
    1234           41 :     if (context->user_handle == 0)
    1235            0 :         context->predefined = true;
    1236              :     else
    1237           41 :         context->predefined = false;
    1238              : 
    1239              :     /* Sort */
    1240           41 :     if (new_context) {
    1241           41 :         qsort(user_list->contexts,
    1242           41 :               (size_t) user_list->num_contexts,
    1243              :               sizeof(DltDaemonContext),
    1244              :               dlt_daemon_cmp_apid_ctid);
    1245              : 
    1246              :         /* Find new position of context with apid, ctid */
    1247           41 :         context = dlt_daemon_context_find(daemon, apid, ctid, ecu, verbose);
    1248              :     }
    1249              : 
    1250              :     return context;
    1251              : }
    1252              : 
    1253              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    1254              : static void dlt_daemon_free_context_log_settings(
    1255              :     DltDaemonApplication *application,
    1256              :     DltDaemonContext *context)
    1257              : {
    1258              :     DltDaemonContextLogSettings *ct_settings;
    1259              :     int i;
    1260              :     int skipped = 0;
    1261              : 
    1262              :     ct_settings = dlt_daemon_find_app_log_level_config(application, context->ctid);
    1263              :     if (ct_settings == NULL) {
    1264              :         return;
    1265              :     }
    1266              : 
    1267              :     /* move all data forward */
    1268              :     for (i = 0; i < application->num_context_log_level_settings; ++i) {
    1269              :         /* skip given context to delete it */
    1270              :         if (i + skipped < application->num_context_log_level_settings &&
    1271              :             strncmp(application->context_log_level_settings[i+skipped].ctid, context->ctid, DLT_ID_SIZE) == 0) {
    1272              :             ++skipped;
    1273              :             continue;
    1274              :         }
    1275              : 
    1276              :         memcpy(&application->context_log_level_settings[i-skipped],
    1277              :                 &application->context_log_level_settings[i],
    1278              :                 sizeof(DltDaemonContextLogSettings));
    1279              :     }
    1280              : 
    1281              :     application->num_context_log_level_settings -= skipped;
    1282              : 
    1283              :     /* if size is equal to zero, and ptr is not NULL, then realloc is equivalent to free(ptr) */
    1284              :     application->context_log_level_settings = realloc(application->context_log_level_settings,
    1285              :             sizeof(DltDaemonContextLogSettings) * (application->num_context_log_level_settings));
    1286              : 
    1287              : }
    1288              : #endif
    1289              : 
    1290           37 : int dlt_daemon_context_del(DltDaemon *daemon,
    1291              :                            DltDaemonContext *context,
    1292              :                            char *ecu,
    1293              :                            int verbose)
    1294              : {
    1295              :     int pos;
    1296              :     DltDaemonApplication *application;
    1297              :     DltDaemonRegisteredUsers *user_list = NULL;
    1298              : 
    1299           37 :     PRINT_FUNCTION_VERBOSE(verbose);
    1300              : 
    1301           37 :     if ((daemon == NULL) || (context == NULL) || (ecu == NULL))
    1302              :         return -1;
    1303              : 
    1304           37 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
    1305              : 
    1306           37 :     if (user_list == NULL)
    1307              :         return -1;
    1308              : 
    1309           37 :     if (user_list->num_contexts > 0) {
    1310           37 :         application = dlt_daemon_application_find(daemon, context->apid, ecu, verbose);
    1311              : 
    1312              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    1313              :         dlt_daemon_free_context_log_settings(application, context);
    1314              : #endif
    1315              :         /* Free description of context to be deleted */
    1316           37 :         if (context->context_description) {
    1317           37 :             free(context->context_description);
    1318           37 :             context->context_description = NULL;
    1319              :         }
    1320              : 
    1321           37 :         pos = (int) (context - (user_list->contexts));
    1322              : 
    1323              :         /* move all contexts above pos to pos */
    1324           37 :         memmove(&(user_list->contexts[pos]),
    1325           37 :                 &(user_list->contexts[pos + 1]),
    1326           37 :                 (size_t)sizeof(DltDaemonContext) * (size_t)((user_list->num_contexts - 1) - pos));
    1327              : 
    1328              :         /* Clear last context */
    1329           37 :         memset(&(user_list->contexts[(size_t)(user_list->num_contexts - 1)]),
    1330              :                 0,
    1331              :                 (size_t)sizeof(DltDaemonContext));
    1332              : 
    1333           37 :         user_list->num_contexts--;
    1334              : 
    1335              :         /* Check if application [apid] is available */
    1336           37 :         if (application != NULL)
    1337           37 :             application->num_contexts--;
    1338              :     }
    1339              : 
    1340              :     return 0;
    1341              : }
    1342              : 
    1343          157 : DltDaemonContext *dlt_daemon_context_find(DltDaemon *daemon,
    1344              :                                           char *apid,
    1345              :                                           char *ctid,
    1346              :                                           char *ecu,
    1347              :                                           int verbose)
    1348              : {
    1349              :     DltDaemonContext context;
    1350              :     DltDaemonRegisteredUsers *user_list = NULL;
    1351              : 
    1352          157 :     PRINT_FUNCTION_VERBOSE(verbose);
    1353              : 
    1354          157 :     if ((daemon == NULL) || (apid == NULL) || (apid[0] == '\0') ||
    1355          157 :         (ctid == NULL) || (ctid[0] == '\0') || (ecu == NULL))
    1356              :         return (DltDaemonContext *)NULL;
    1357              : 
    1358          157 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
    1359              : 
    1360          157 :     if ((user_list == NULL) || (user_list->num_contexts == 0))
    1361              :         return (DltDaemonContext *)NULL;
    1362              : 
    1363              :     /* Check, if apid is smaller than smallest apid or greater than greatest apid */
    1364          112 :     if ((memcmp(apid, user_list->contexts[0].apid, DLT_ID_SIZE) < 0) ||
    1365          112 :         (memcmp(apid,
    1366          112 :                 user_list->contexts[user_list->num_contexts - 1].apid,
    1367              :                 DLT_ID_SIZE) > 0))
    1368              :         return (DltDaemonContext *)NULL;
    1369              : 
    1370          112 :     dlt_set_id(context.apid, apid);
    1371          112 :     dlt_set_id(context.ctid, ctid);
    1372              : 
    1373          112 :     return (DltDaemonContext *)bsearch(&context,
    1374          112 :                                        user_list->contexts,
    1375          112 :                                        (size_t) user_list->num_contexts,
    1376              :                                        sizeof(DltDaemonContext),
    1377              :                                        dlt_daemon_cmp_apid_ctid);
    1378              : }
    1379              : 
    1380           15 : int dlt_daemon_contexts_invalidate_fd(DltDaemon *daemon,
    1381              :                                       char *ecu,
    1382              :                                       int fd,
    1383              :                                       int verbose)
    1384              : {
    1385              :     int i;
    1386              :     DltDaemonRegisteredUsers *user_list = NULL;
    1387              : 
    1388           15 :     PRINT_FUNCTION_VERBOSE(verbose);
    1389              : 
    1390           15 :     if ((daemon == NULL) || (ecu == NULL))
    1391              :         return -1;
    1392              : 
    1393           15 :     user_list = dlt_daemon_find_users_list(daemon, ecu, verbose);
    1394              : 
    1395           15 :     if (user_list != NULL) {
    1396           39 :         for (i = 0; i < user_list->num_contexts; i++)
    1397           24 :             if (user_list->contexts[i].user_handle == fd)
    1398            0 :                 user_list->contexts[i].user_handle = DLT_FD_INIT;
    1399              : 
    1400              :         return 0;
    1401              :     }
    1402              : 
    1403              :     return -1;
    1404              : }
    1405              : 
    1406           10 : int dlt_daemon_contexts_clear(DltDaemon *daemon, char *ecu, int verbose)
    1407              : {
    1408              :     int i;
    1409              :     DltDaemonRegisteredUsers *users = NULL;
    1410              : 
    1411           10 :     PRINT_FUNCTION_VERBOSE(verbose);
    1412              : 
    1413           10 :     if ((daemon == NULL) || (ecu == NULL))
    1414              :         return DLT_RETURN_WRONG_PARAMETER;
    1415              : 
    1416           10 :     users = dlt_daemon_find_users_list(daemon, ecu, verbose);
    1417              : 
    1418           10 :     if (users == NULL)
    1419              :         return DLT_RETURN_ERROR;
    1420              : 
    1421           11 :     for (i = 0; i < users->num_contexts; i++)
    1422            1 :         if (users->contexts[i].context_description != NULL) {
    1423            1 :             free(users->contexts[i].context_description);
    1424            1 :             users->contexts[i].context_description = NULL;
    1425              :         }
    1426              : 
    1427           10 :     if (users->contexts) {
    1428            7 :         free(users->contexts);
    1429            7 :         users->contexts = NULL;
    1430              :     }
    1431              : 
    1432           11 :     for (i = 0; i < users->num_applications; i++)
    1433            1 :         users->applications[i].num_contexts = 0;
    1434              : 
    1435           10 :     users->num_contexts = 0;
    1436              : 
    1437           10 :     return 0;
    1438              : }
    1439              : 
    1440            0 : int dlt_daemon_contexts_load(DltDaemon *daemon, const char *filename, int verbose)
    1441              : {
    1442              :     FILE *fd;
    1443              :     ID4 apid, ctid;
    1444              :     char buf[DLT_DAEMON_COMMON_TEXTBUFSIZE];
    1445              :     char *ret;
    1446              :     char *pb;
    1447              :     int ll, ts;
    1448              : 
    1449            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1450              : 
    1451            0 :     if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
    1452              :         return -1;
    1453              : 
    1454            0 :     fd = fopen(filename, "r");
    1455              : 
    1456            0 :     if (fd == NULL) {
    1457            0 :         dlt_vlog(LOG_WARNING,
    1458              :                  "DLT runtime-context load, cannot open file %s: %s\n",
    1459              :                  filename,
    1460            0 :                  strerror(errno));
    1461              : 
    1462            0 :         return -1;
    1463              :     }
    1464              : 
    1465            0 :     while (!feof(fd)) {
    1466              :         /* Clear buf */
    1467              :         memset(buf, 0, sizeof(buf));
    1468              : 
    1469              :         /* Get line */
    1470              :         ret = fgets(buf, sizeof(buf), fd);
    1471              : 
    1472            0 :         if (NULL == ret) {
    1473              :             /* fgets always returns null pointer if the last byte of the file is a new line.
    1474              :              * We need to check here if there was an error or was it feof.*/
    1475            0 :             if (ferror(fd)) {
    1476            0 :                 dlt_vlog(LOG_WARNING,
    1477              :                          "%s fgets(buf,sizeof(buf),fd) returned NULL. %s\n",
    1478              :                          __func__,
    1479            0 :                          strerror(errno));
    1480            0 :                 fclose(fd);
    1481            0 :                 return -1;
    1482              :             }
    1483            0 :             else if (feof(fd))
    1484              :             {
    1485            0 :                 fclose(fd);
    1486            0 :                 return 0;
    1487              :             }
    1488              :             else {
    1489            0 :                 dlt_vlog(LOG_WARNING,
    1490              :                          "%s fgets(buf,sizeof(buf),fd) returned NULL. Unknown error.\n",
    1491              :                          __func__);
    1492            0 :                 fclose(fd);
    1493            0 :                 return -1;
    1494              :             }
    1495              :         }
    1496              : 
    1497            0 :         if (strcmp(buf, "") != 0) {
    1498              :             /* Split line */
    1499            0 :             pb = strtok(buf, ":");
    1500              : 
    1501            0 :             if (pb != NULL) {
    1502            0 :                 dlt_set_id(apid, pb);
    1503            0 :                 pb = strtok(NULL, ":");
    1504              : 
    1505            0 :                 if (pb != NULL) {
    1506            0 :                     dlt_set_id(ctid, pb);
    1507            0 :                     pb = strtok(NULL, ":");
    1508              : 
    1509            0 :                     if (pb != NULL) {
    1510            0 :                         sscanf(pb, "%d", &ll);
    1511            0 :                         pb = strtok(NULL, ":");
    1512              : 
    1513            0 :                         if (pb != NULL) {
    1514            0 :                             sscanf(pb, "%d", &ts);
    1515            0 :                             pb = strtok(NULL, ":");
    1516              : 
    1517            0 :                             if (pb != NULL) {
    1518              :                                 /* pb contains now the description */
    1519              : 
    1520              :                                 /* log_level_pos, and user_handle are unknown at loading time */
    1521            0 :                                 if (dlt_daemon_context_add(daemon,
    1522              :                                                            apid,
    1523              :                                                            ctid,
    1524            0 :                                                            (int8_t)ll,
    1525            0 :                                                            (int8_t)ts,
    1526              :                                                            0,
    1527              :                                                            0,
    1528              :                                                            pb,
    1529            0 :                                                            daemon->ecuid,
    1530              :                                                            verbose) == NULL) {
    1531            0 :                                     dlt_vlog(LOG_WARNING,
    1532              :                                              "%s dlt_daemon_context_add failed\n",
    1533              :                                              __func__);
    1534            0 :                                     fclose(fd);
    1535            0 :                                     return -1;
    1536              :                                 }
    1537              :                             }
    1538              :                         }
    1539              :                     }
    1540              :                 }
    1541              :             }
    1542              :         }
    1543              :     }
    1544              : 
    1545            0 :     fclose(fd);
    1546              : 
    1547            0 :     return 0;
    1548              : }
    1549              : 
    1550            0 : int dlt_daemon_contexts_save(DltDaemon *daemon, const char *filename, int verbose)
    1551              : {
    1552              :     FILE *fd;
    1553              :     int i;
    1554              : 
    1555              :     char apid[DLT_ID_SIZE + 1], ctid[DLT_ID_SIZE + 1]; /* DLT_ID_SIZE+1, because the 0-termination is required here */
    1556              :     DltDaemonRegisteredUsers *user_list = NULL;
    1557              : 
    1558            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1559              : 
    1560            0 :     if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
    1561              :         return -1;
    1562              : 
    1563            0 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    1564              : 
    1565            0 :     if (user_list == NULL)
    1566              :         return -1;
    1567              : 
    1568              :     memset(apid, 0, sizeof(apid));
    1569              :     memset(ctid, 0, sizeof(ctid));
    1570              : 
    1571            0 :     if ((user_list->contexts) && (user_list->num_contexts > 0)) {
    1572            0 :         fd = fopen(filename, "w");
    1573              : 
    1574            0 :         if (fd != NULL) {
    1575            0 :             for (i = 0; i < user_list->num_contexts; i++) {
    1576            0 :                 dlt_set_id(apid, user_list->contexts[i].apid);
    1577            0 :                 dlt_set_id(ctid, user_list->contexts[i].ctid);
    1578              : 
    1579            0 :                 if ((user_list->contexts[i].context_description) &&
    1580            0 :                     (user_list->contexts[i].context_description[0] != '\0'))
    1581            0 :                     fprintf(fd, "%s:%s:%d:%d:%s:\n", apid, ctid,
    1582            0 :                             (int)(user_list->contexts[i].log_level),
    1583            0 :                             (int)(user_list->contexts[i].trace_status),
    1584              :                             user_list->contexts[i].context_description);
    1585              :                 else
    1586            0 :                     fprintf(fd, "%s:%s:%d:%d::\n", apid, ctid,
    1587            0 :                             (int)(user_list->contexts[i].log_level),
    1588            0 :                             (int)(user_list->contexts[i].trace_status));
    1589              :             }
    1590              : 
    1591            0 :             fclose(fd);
    1592              :         }
    1593              :         else {
    1594            0 :             dlt_vlog(LOG_ERR,
    1595              :                      "%s: Cannot open %s. No context information stored\n",
    1596              :                      __func__,
    1597              :                      filename);
    1598              :         }
    1599              :     }
    1600              : 
    1601              :     return 0;
    1602              : }
    1603              : 
    1604            0 : int dlt_daemon_configuration_save(DltDaemon *daemon, const char *filename, int verbose)
    1605              : {
    1606              :     FILE *fd;
    1607              : 
    1608            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1609              : 
    1610            0 :     if ((daemon == NULL) || (filename == NULL) || (filename[0] == '\0'))
    1611              :         return -1;
    1612              : 
    1613            0 :     fd = fopen(filename, "w");
    1614              : 
    1615            0 :     if (fd != NULL) {
    1616              :         fprintf(fd, "# 0 = off, 1 = external, 2 = internal, 3 = both\n");
    1617            0 :         fprintf(fd, "LoggingMode = %d\n", daemon->mode);
    1618              : 
    1619            0 :         fclose(fd);
    1620              :     }
    1621              : 
    1622              :     return 0;
    1623              : }
    1624              : 
    1625            9 : int dlt_daemon_configuration_load(DltDaemon *daemon, const char *filename, int verbose)
    1626              : {
    1627            9 :     if ((daemon == NULL) || (filename == NULL))
    1628              :         return -1;
    1629              : 
    1630              :     FILE *pFile;
    1631              :     char line[1024];
    1632              :     char token[1024];
    1633              :     char value[1024];
    1634              :     char *pch;
    1635              : 
    1636            9 :     PRINT_FUNCTION_VERBOSE(verbose);
    1637              : 
    1638            9 :     pFile = fopen (filename, "r");
    1639              : 
    1640            9 :     if (pFile != NULL) {
    1641              :         while (1) {
    1642              :             /* fetch line from configuration file */
    1643           18 :             if (fgets (line, 1024, pFile) != NULL) {
    1644            9 :                 pch = strtok (line, " =\r\n");
    1645            9 :                 token[0] = 0;
    1646            9 :                 value[0] = 0;
    1647              : 
    1648           18 :                 while (pch != NULL) {
    1649            9 :                     if (strcmp(pch, "#") == 0)
    1650              :                         break;
    1651              : 
    1652            9 :                     if (token[0] == 0) {
    1653              :                         strncpy(token, pch, sizeof(token) - 1);
    1654            9 :                         token[sizeof(token) - 1] = 0;
    1655              :                     }
    1656              :                     else {
    1657              :                         strncpy(value, pch, sizeof(value) - 1);
    1658            0 :                         value[sizeof(value) - 1] = 0;
    1659            0 :                         break;
    1660              :                     }
    1661              : 
    1662            9 :                     pch = strtok (NULL, " =\r\n");
    1663              :                 }
    1664              : 
    1665            9 :                 if (token[0] && value[0]) {
    1666              :                     /* parse arguments here */
    1667            0 :                     if (strcmp(token, "LoggingMode") == 0) {
    1668            0 :                         daemon->mode = atoi(value);
    1669            0 :                         dlt_vlog(LOG_INFO, "Runtime Option: %s=%d\n", token,
    1670              :                                  daemon->mode);
    1671              :                     }
    1672              :                     else {
    1673            0 :                         dlt_vlog(LOG_WARNING, "Unknown option: %s=%s\n", token,
    1674              :                                  value);
    1675              :                     }
    1676              :                 }
    1677              :             }
    1678              :             else {
    1679              :                 break;
    1680              :             }
    1681              :         }
    1682              : 
    1683            9 :         fclose (pFile);
    1684              :     }
    1685              :     else {
    1686            0 :         dlt_vlog(LOG_INFO, "Cannot open configuration file: %s\n", filename);
    1687              :     }
    1688              : 
    1689              :     return 0;
    1690              : }
    1691              : 
    1692           41 : int dlt_daemon_user_send_log_level(DltDaemon *daemon, DltDaemonContext *context, int verbose)
    1693              : {
    1694              :     DltUserHeader userheader;
    1695              :     DltUserControlMsgLogLevel usercontext;
    1696              :     DltReturnValue ret;
    1697              :     DltDaemonApplication *app;
    1698              : 
    1699           41 :     PRINT_FUNCTION_VERBOSE(verbose);
    1700              : 
    1701           41 :     if ((daemon == NULL) || (context == NULL)) {
    1702            0 :         dlt_vlog(LOG_ERR, "NULL parameter in %s", __func__);
    1703            0 :         return -1;
    1704              :     }
    1705              : 
    1706           41 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_LEVEL) < DLT_RETURN_OK) {
    1707            0 :         dlt_vlog(LOG_ERR, "Failed to set userheader in %s", __func__);
    1708            0 :         return -1;
    1709              :     }
    1710              : 
    1711           41 :     if ((context->storage_log_level != DLT_LOG_DEFAULT) &&
    1712           34 :         (daemon->maintain_logstorage_loglevel != DLT_MAINTAIN_LOGSTORAGE_LOGLEVEL_OFF))
    1713           32 :             usercontext.log_level = (uint8_t) (context->log_level >
    1714              :                 context->storage_log_level ? context->log_level : context->storage_log_level);
    1715              :     else /* Storage log level is not updated (is DEFAULT) then  no device is yet connected so ignore */
    1716            9 :         usercontext.log_level =
    1717            9 :             (uint8_t) ((context->log_level == DLT_LOG_DEFAULT) ? daemon->default_log_level : context->log_level);
    1718              : 
    1719           41 :     usercontext.trace_status =
    1720           41 :         (uint8_t) ((context->trace_status == DLT_TRACE_STATUS_DEFAULT) ? daemon->default_trace_status : context->trace_status);
    1721              : 
    1722           41 :     usercontext.log_level_pos = context->log_level_pos;
    1723              : 
    1724           41 :     dlt_vlog(LOG_NOTICE, "Send log-level to context: %.4s:%.4s [%i -> %i] [%i -> %i]\n",
    1725           41 :              context->apid,
    1726           41 :              context->ctid,
    1727           41 :              context->log_level,
    1728           41 :              usercontext.log_level,
    1729              :              context->trace_status,
    1730              :              usercontext.trace_status);
    1731              : 
    1732              :     /* log to FIFO */
    1733           41 :     errno = 0;
    1734           41 :     ret = dlt_user_log_out2_with_timeout(context->user_handle,
    1735              :                             &(userheader), sizeof(DltUserHeader),
    1736              :                             &(usercontext), sizeof(DltUserControlMsgLogLevel));
    1737              : 
    1738           41 :     if (ret < DLT_RETURN_OK) {
    1739            0 :         dlt_vlog(LOG_ERR, "Failed to send data to application in %s: %s",
    1740              :                  __func__,
    1741            0 :                  errno != 0 ? strerror(errno) : "Unknown error");
    1742              : 
    1743            0 :         if (errno == EPIPE || errno == EBADF) {
    1744            0 :             app = dlt_daemon_application_find(daemon, context->apid, daemon->ecuid, verbose);
    1745            0 :             if (app != NULL)
    1746            0 :                 dlt_daemon_application_reset_user_handle(daemon, app, verbose);
    1747              :         }
    1748              :     }
    1749              : 
    1750           41 :     return (ret == DLT_RETURN_OK) ? DLT_RETURN_OK : DLT_RETURN_ERROR;
    1751              : }
    1752              : 
    1753            9 : int dlt_daemon_user_send_log_state(DltDaemon *daemon, DltDaemonApplication *app, int verbose)
    1754              : {
    1755              :     DltUserHeader userheader;
    1756              :     DltUserControlMsgLogState logstate;
    1757              :     DltReturnValue ret;
    1758              : 
    1759            9 :     PRINT_FUNCTION_VERBOSE(verbose);
    1760              : 
    1761            9 :     if ((daemon == NULL) || (app == NULL))
    1762              :         return -1;
    1763              : 
    1764            9 :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_STATE) < DLT_RETURN_OK)
    1765              :         return -1;
    1766              : 
    1767            9 :     logstate.log_state = daemon->connectionState;
    1768              : 
    1769              :     /* log to FIFO */
    1770            9 :     ret = dlt_user_log_out2_with_timeout(app->user_handle,
    1771              :                             &(userheader), sizeof(DltUserHeader),
    1772              :                             &(logstate), sizeof(DltUserControlMsgLogState));
    1773              : 
    1774            9 :     if (ret < DLT_RETURN_OK) {
    1775            0 :         if (errno == EPIPE || errno == EBADF)
    1776            0 :             dlt_daemon_application_reset_user_handle(daemon, app, verbose);
    1777              :     }
    1778              : 
    1779            9 :     return (ret == DLT_RETURN_OK) ? DLT_RETURN_OK : DLT_RETURN_ERROR;
    1780              : }
    1781              : 
    1782            0 : void dlt_daemon_control_reset_to_factory_default(DltDaemon *daemon,
    1783              :                                                  const char *filename,
    1784              :                                                  const char *filename1,
    1785              :                                                  int InitialContextLogLevel,
    1786              :                                                  int InitialContextTraceStatus,
    1787              :                                                  int InitialEnforceLlTsStatus,
    1788              :                                                  int verbose)
    1789              : {
    1790              :     FILE *fd;
    1791              : 
    1792            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1793              : 
    1794            0 :     if ((daemon == NULL) || (filename == NULL) || (filename1 == NULL)) {
    1795            0 :         dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n");
    1796            0 :         return;
    1797              :     }
    1798              : 
    1799            0 :     if ((filename[0] == '\0') || (filename1[0] == '\0')) {
    1800            0 :         dlt_log(LOG_WARNING, "Wrong parameter: Empty string\n");
    1801            0 :         return;
    1802              :     }
    1803              : 
    1804              :     /* Check for runtime cfg file and delete it, if available */
    1805            0 :     fd = fopen(filename, "r");
    1806              : 
    1807            0 :     if (fd != NULL) {
    1808              :         /* Close and delete file */
    1809            0 :         fclose(fd);
    1810            0 :         if (unlink(filename) != 0) {
    1811            0 :             dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n",
    1812            0 :                     __func__, strerror(errno));
    1813              :         }
    1814              :     }
    1815              : 
    1816            0 :     fd = fopen(filename1, "r");
    1817              : 
    1818            0 :     if (fd != NULL) {
    1819              :         /* Close and delete file */
    1820            0 :         fclose(fd);
    1821            0 :         if (unlink(filename1) != 0) {
    1822            0 :             dlt_vlog(LOG_WARNING, "%s: unlink() failed: %s\n",
    1823            0 :                     __func__, strerror(errno));
    1824              :         }
    1825              :     }
    1826              : 
    1827            0 :     daemon->default_log_level = (int8_t) InitialContextLogLevel;
    1828            0 :     daemon->default_trace_status = (int8_t) InitialContextTraceStatus;
    1829            0 :     daemon->force_ll_ts = (int8_t) InitialEnforceLlTsStatus;
    1830              : 
    1831              :     /* Reset all other things (log level, trace status, etc.
    1832              :      *                         to default values             */
    1833              : 
    1834              :     /* Inform user libraries about changed default log level/trace status */
    1835            0 :     dlt_daemon_user_send_default_update(daemon, verbose);
    1836              : }
    1837              : 
    1838            0 : void dlt_daemon_user_send_default_update(DltDaemon *daemon, int verbose)
    1839              : {
    1840              :     int32_t count;
    1841              :     DltDaemonContext *context;
    1842              :     DltDaemonRegisteredUsers *user_list = NULL;
    1843              : 
    1844            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1845              : 
    1846            0 :     if (daemon == NULL) {
    1847            0 :         dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n");
    1848            0 :         return;
    1849              :     }
    1850              : 
    1851            0 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    1852              : 
    1853            0 :     if (user_list == NULL)
    1854              :         return;
    1855              : 
    1856            0 :     for (count = 0; count < user_list->num_contexts; count++) {
    1857            0 :         context = &(user_list->contexts[count]);
    1858              : 
    1859            0 :         if (context != NULL) {
    1860            0 :             if ((context->log_level == DLT_LOG_DEFAULT) ||
    1861            0 :                 (context->trace_status == DLT_TRACE_STATUS_DEFAULT)) {
    1862            0 :                 if (context->user_handle >= DLT_FD_MINIMUM)
    1863            0 :                     if (dlt_daemon_user_send_log_level(daemon,
    1864              :                                                        context,
    1865              :                                                        verbose) == -1)
    1866            0 :                         dlt_vlog(LOG_WARNING, "Cannot update default of %.4s:%.4s\n", context->apid, context->ctid);
    1867              :             }
    1868              :         }
    1869              :     }
    1870              : }
    1871              : 
    1872            0 : void dlt_daemon_user_send_all_log_level_update(DltDaemon *daemon,
    1873              :                                                int enforce_context_ll_and_ts,
    1874              :                                                int8_t context_log_level,
    1875              :                                                int8_t log_level,
    1876              :                                                int verbose)
    1877              : {
    1878              :     int32_t count = 0;
    1879              :     DltDaemonContext *context = NULL;
    1880              :     DltDaemonRegisteredUsers *user_list = NULL;
    1881              : 
    1882            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1883              : 
    1884            0 :     if (daemon == NULL)
    1885              :         return;
    1886              : 
    1887            0 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    1888              : 
    1889            0 :     if (user_list == NULL)
    1890              :         return;
    1891              : 
    1892            0 :     for (count = 0; count < user_list->num_contexts; count++) {
    1893            0 :         context = &(user_list->contexts[count]);
    1894              : 
    1895            0 :         if (context) {
    1896            0 :             if (context->user_handle >= DLT_FD_MINIMUM) {
    1897            0 :                 context->log_level = log_level;
    1898              : 
    1899            0 :                 if (enforce_context_ll_and_ts) {
    1900              : #ifdef DLT_LOG_LEVEL_APP_CONFIG
    1901              :                     DltDaemonContextLogSettings *settings =
    1902              :                         dlt_daemon_find_configured_app_id_ctx_id_settings(
    1903              :                             daemon, context->apid, context->ctid);
    1904              :                     if (settings != NULL) {
    1905              :                         if (log_level > settings->log_level) {
    1906              :                           context->log_level = settings->log_level;
    1907              :                         }
    1908              :                     } else
    1909              : #endif
    1910            0 :                     if (log_level > context_log_level) {
    1911            0 :                         context->log_level = (int8_t)context_log_level;
    1912              :                     }
    1913              :                 }
    1914              : 
    1915            0 :                 if (dlt_daemon_user_send_log_level(daemon,
    1916              :                                                    context,
    1917              :                                                    verbose) == -1)
    1918            0 :                     dlt_vlog(LOG_WARNING,
    1919              :                              "Cannot send log level %.4s:%.4s -> %i\n",
    1920            0 :                              context->apid,
    1921            0 :                              context->ctid,
    1922            0 :                              context->log_level);
    1923              :             }
    1924              :         }
    1925              :     }
    1926              : }
    1927              : 
    1928            0 : void dlt_daemon_user_send_all_trace_status_update(DltDaemon *daemon, int8_t trace_status, int verbose)
    1929              : {
    1930              :     int32_t count = 0;
    1931              :     DltDaemonContext *context = NULL;
    1932              :     DltDaemonRegisteredUsers *user_list = NULL;
    1933              : 
    1934            0 :     PRINT_FUNCTION_VERBOSE(verbose);
    1935              : 
    1936            0 :     if (daemon == NULL)
    1937              :         return;
    1938              : 
    1939            0 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    1940              : 
    1941            0 :     if (user_list == NULL)
    1942              :         return;
    1943              : 
    1944            0 :     dlt_vlog(LOG_NOTICE, "All trace status is updated -> %i\n", trace_status);
    1945              : 
    1946            0 :     for (count = 0; count < user_list->num_contexts; count++) {
    1947            0 :         context = &(user_list->contexts[count]);
    1948              : 
    1949            0 :         if (context) {
    1950            0 :             if (context->user_handle >= DLT_FD_MINIMUM) {
    1951            0 :                 context->trace_status = trace_status;
    1952              : 
    1953            0 :                 if (dlt_daemon_user_send_log_level(daemon, context, verbose) == -1)
    1954            0 :                     dlt_vlog(LOG_WARNING,
    1955              :                              "Cannot send trace status %.4s:%.4s -> %i\n",
    1956            0 :                              context->apid,
    1957            0 :                              context->ctid,
    1958            0 :                              context->trace_status);
    1959              :             }
    1960              :         }
    1961              :     }
    1962              : }
    1963              : 
    1964            5 : void dlt_daemon_user_send_all_log_state(DltDaemon *daemon, int verbose)
    1965              : {
    1966              :     int32_t count;
    1967              :     DltDaemonApplication *app;
    1968              :     DltDaemonRegisteredUsers *user_list = NULL;
    1969              : 
    1970            5 :     PRINT_FUNCTION_VERBOSE(verbose);
    1971              : 
    1972            5 :     if (daemon == NULL) {
    1973            0 :         dlt_log(LOG_WARNING, "Wrong parameter: Null pointer\n");
    1974            0 :         return;
    1975              :     }
    1976              : 
    1977            5 :     user_list = dlt_daemon_find_users_list(daemon, daemon->ecuid, verbose);
    1978              : 
    1979            5 :     if (user_list == NULL)
    1980              :         return;
    1981              : 
    1982            7 :     for (count = 0; count < user_list->num_applications; count++) {
    1983            2 :         app = &(user_list->applications[count]);
    1984              : 
    1985            2 :         if (app != NULL) {
    1986            2 :             if (app->user_handle >= DLT_FD_MINIMUM)
    1987            2 :                 if (dlt_daemon_user_send_log_state(daemon, app, verbose) == -1)
    1988            0 :                     dlt_vlog(LOG_WARNING, "Cannot send log state to Apid: %.4s, PID: %d\n", app->apid, app->pid);
    1989              :         }
    1990              :     }
    1991              : }
    1992              : 
    1993           16 : void dlt_daemon_change_state(DltDaemon *daemon, DltDaemonState newState)
    1994              : {
    1995           16 :     switch (newState) {
    1996            0 :     case DLT_DAEMON_STATE_INIT:
    1997            0 :         dlt_log(LOG_INFO, "Switched to init state.\n");
    1998            0 :         daemon->state = DLT_DAEMON_STATE_INIT;
    1999            0 :         break;
    2000           12 :     case DLT_DAEMON_STATE_BUFFER:
    2001           12 :         dlt_log(LOG_INFO, "Switched to buffer state for socket connections.\n");
    2002           12 :         daemon->state = DLT_DAEMON_STATE_BUFFER;
    2003           12 :         break;
    2004            0 :     case DLT_DAEMON_STATE_BUFFER_FULL:
    2005            0 :         dlt_log(LOG_INFO, "Switched to buffer full state.\n");
    2006            0 :         daemon->state = DLT_DAEMON_STATE_BUFFER_FULL;
    2007            0 :         break;
    2008            2 :     case DLT_DAEMON_STATE_SEND_BUFFER:
    2009            2 :         dlt_log(LOG_INFO, "Switched to send buffer state for socket connections.\n");
    2010            2 :         daemon->state = DLT_DAEMON_STATE_SEND_BUFFER;
    2011            2 :         break;
    2012            2 :     case DLT_DAEMON_STATE_SEND_DIRECT:
    2013            2 :         dlt_log(LOG_INFO, "Switched to send direct state.\n");
    2014            2 :         daemon->state = DLT_DAEMON_STATE_SEND_DIRECT;
    2015            2 :         break;
    2016              :     }
    2017           16 : }
    2018              : 
    2019              : #ifdef DLT_SYSTEMD_WATCHDOG_ENABLE
    2020              : bool dlt_daemon_trigger_systemd_watchdog_if_necessary(DltDaemon *daemon) {
    2021              :     if (daemon->watchdog_trigger_interval == 0) {
    2022              :         return false;
    2023              :     }
    2024              : 
    2025              :     const unsigned int uptime_seconds = dlt_uptime() / 10000;
    2026              :     const unsigned int seconds_since_last_trigger = uptime_seconds - daemon->watchdog_last_trigger_time;
    2027              :     if (seconds_since_last_trigger < daemon->watchdog_trigger_interval) {
    2028              :         return false;
    2029              :     }
    2030              :     if (sd_notify(0, "WATCHDOG=1") < 0) {
    2031              :         dlt_vlog(LOG_WARNING, "%s: Could not reset systemd watchdog\n", __func__);
    2032              :         return false;
    2033              :     }
    2034              :     else
    2035              :         daemon->watchdog_last_trigger_time = uptime_seconds;
    2036              : 
    2037              :     return true;
    2038              : }
    2039              : 
    2040              : #endif
    2041              : 
    2042              : #ifdef DLT_TRACE_LOAD_CTRL_ENABLE
    2043              : int dlt_daemon_user_send_trace_load_config(DltDaemon *const daemon, DltDaemonApplication *app, const int verbose)
    2044              : {
    2045              :     DltUserHeader userheader;
    2046              :     DltUserControlMsgTraceSettingMsg* trace_load_settings_user_msg;
    2047              :     uint32_t trace_load_settings_count;
    2048              :     DltReturnValue ret;
    2049              : 
    2050              : 
    2051              :     PRINT_FUNCTION_VERBOSE(verbose);
    2052              : 
    2053              :     if ((daemon == NULL) || (app == NULL)) return -1;
    2054              : 
    2055              :     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_TRACE_LOAD) < DLT_RETURN_OK) return -1;
    2056              : 
    2057              :     DltTraceLoadSettings* app_settings = app->trace_load_settings;
    2058              : 
    2059              :     if (app_settings != NULL) {
    2060              :         trace_load_settings_count = app->trace_load_settings_count;
    2061              :         trace_load_settings_user_msg = malloc(sizeof(DltUserControlMsgTraceSettingMsg) * trace_load_settings_count);
    2062              :         for (uint32_t i = 0U; i < trace_load_settings_count; i++) {
    2063              :             // App id is not transmitted as the user library only
    2064              :             // has one application ID
    2065              :             memcpy(trace_load_settings_user_msg[i].ctid, app_settings[i].ctid, DLT_ID_SIZE);
    2066              :             trace_load_settings_user_msg[i].soft_limit = app_settings[i].soft_limit;
    2067              :             trace_load_settings_user_msg[i].hard_limit = app_settings[i].hard_limit;
    2068              : 
    2069              :             if (app_settings[i].ctid[0] == '\0') {
    2070              :                 dlt_vlog(LOG_NOTICE, "Sending trace load config to app %.4s, soft limit %u, hard limit %u\n",
    2071              :                          app->apid,
    2072              :                          app_settings[i].soft_limit,
    2073              :                          app_settings[i].hard_limit);
    2074              :             } else {
    2075              :                 dlt_vlog(LOG_NOTICE, "Sending trace load config to app %.4s, ctid %.4s, soft limit %u, hard limit %u\n",
    2076              :                          app->apid,
    2077              :                          app_settings[i].ctid,
    2078              :                          app_settings[i].soft_limit,
    2079              :                          app_settings[i].hard_limit);
    2080              :             }
    2081              : 
    2082              :         }
    2083              :     }
    2084              :     else {
    2085              :         dlt_vlog(LOG_INFO,
    2086              :                  "No trace load settings for application %s, setting daemon defaults.\n", app->apid);
    2087              : 
    2088              :         trace_load_settings_count = 1;
    2089              :         trace_load_settings_user_msg = malloc(sizeof(DltUserControlMsgTraceSettingMsg));
    2090              : 
    2091              :         memset(trace_load_settings_user_msg, 0, sizeof(DltTraceLoadSettings));
    2092              :         trace_load_settings_user_msg[0].soft_limit = DLT_TRACE_LOAD_DAEMON_SOFT_LIMIT_DEFAULT;
    2093              :         trace_load_settings_user_msg[0].hard_limit = DLT_TRACE_LOAD_DAEMON_HARD_LIMIT_DEFAULT;
    2094              :     }
    2095              : 
    2096              :     /* log to FIFO */
    2097              :     ret = dlt_user_log_out3_with_timeout(app->user_handle,
    2098              :                                          &(userheader), sizeof(DltUserHeader),
    2099              :                                          &(trace_load_settings_count), sizeof(uint32_t),
    2100              :                                          trace_load_settings_user_msg, sizeof(DltUserControlMsgTraceSettingMsg) * trace_load_settings_count);
    2101              : 
    2102              :     if (ret < DLT_RETURN_OK) {
    2103              :         if (errno == EPIPE || errno == EBADF)
    2104              :             dlt_daemon_application_reset_user_handle(daemon, app, verbose);
    2105              :     }
    2106              : 
    2107              :     free(trace_load_settings_user_msg);
    2108              : 
    2109              :     return ret;
    2110              : }
    2111              : #endif
        

Generated by: LCOV version 2.0-1