Fix FTBFS for x86_64
[profile/ivi/dlt-daemon.git] / src / daemon / dlt_daemon_common.c
1 /**
2  * @licence app begin@
3  * Copyright (C) 2012  BMW AG
4  *
5  * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps.
6  *
7  * Contributions are licensed to the GENIVI Alliance under one or more
8  * Contribution License Agreements.
9  *
10  * \copyright
11  * This Source Code Form is subject to the terms of the
12  * Mozilla Public License, v. 2.0. If a  copy of the MPL was not distributed with
13  * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
14  *
15  *
16  * \author Alexander Wenzel <alexander.aw.wenzel@bmw.de> BMW 2011-2012
17  *
18  * \file dlt_daemon_common.c
19  * For further information see http://www.genivi.org/.
20  * @licence end@
21  */
22
23 /*******************************************************************************
24 **                                                                            **
25 **  SRC-MODULE: dlt_daemon_common.c                                           **
26 **                                                                            **
27 **  TARGET    : linux                                                         **
28 **                                                                            **
29 **  PROJECT   : DLT                                                           **
30 **                                                                            **
31 **  AUTHOR    : Alexander Wenzel Alexander.AW.Wenzel@bmw.de                   **
32 **              Markus Klein                                                  **
33 **                                                                            **
34 **  PURPOSE   :                                                               **
35 **                                                                            **
36 **  REMARKS   :                                                               **
37 **                                                                            **
38 **  PLATFORM DEPENDANT [yes/no]: yes                                          **
39 **                                                                            **
40 **  TO BE CHANGED BY USER [yes/no]: no                                        **
41 **                                                                            **
42 *******************************************************************************/
43
44 /*******************************************************************************
45 **                      Author Identity                                       **
46 ********************************************************************************
47 **                                                                            **
48 ** Initials     Name                       Company                            **
49 ** --------     -------------------------  ---------------------------------- **
50 **  aw          Alexander Wenzel           BMW                                **
51 **  mk          Markus Klein               Fraunhofer ESK                     **
52 *******************************************************************************/
53
54 /*******************************************************************************
55 **                      Revision Control History                              **
56 *******************************************************************************/
57
58 /*
59  * $LastChangedRevision: 1670 $
60  * $LastChangedDate: 2011-04-08 15:12:06 +0200 (Fr, 08. Apr 2011) $
61  * $LastChangedBy$
62  Initials    Date         Comment
63  aw          13.01.2010   initial
64  */
65
66 #include <stdio.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <syslog.h>
70 #include <errno.h>
71 #include <unistd.h>
72 #include <fcntl.h>
73
74 #include <sys/types.h>  /* send() */
75 #include <sys/socket.h> /* send() */
76
77 #include "dlt_types.h"
78 #include "dlt_daemon_common.h"
79 #include "dlt_daemon_common_cfg.h"
80 #include "dlt_user_shared.h"
81 #include "dlt_user_shared_cfg.h"
82 #include "dlt-daemon.h"
83
84 #include "dlt_daemon_socket.h"
85 #include "dlt_daemon_serial.h"
86
87 static char str[DLT_DAEMON_COMMON_TEXTBUFSIZE];
88
89 sem_t dlt_daemon_mutex;
90
91 static int dlt_daemon_cmp_apid(const void *m1, const void *m2)
92 {
93     DltDaemonApplication *mi1 = (DltDaemonApplication *) m1;
94     DltDaemonApplication *mi2 = (DltDaemonApplication *) m2;
95
96     return memcmp(mi1->apid, mi2->apid, DLT_ID_SIZE);
97 }
98
99 static int dlt_daemon_cmp_apid_ctid(const void *m1, const void *m2)
100 {
101
102     int ret, cmp;
103     DltDaemonContext *mi1 = (DltDaemonContext *) m1;
104     DltDaemonContext *mi2 = (DltDaemonContext *) m2;
105
106     cmp=memcmp(mi1->apid, mi2->apid, DLT_ID_SIZE);
107     if (cmp<0)
108     {
109         ret=-1;
110     }
111     else if (cmp==0)
112     {
113         ret=memcmp(mi1->ctid, mi2->ctid, DLT_ID_SIZE);
114     }
115     else
116     {
117         ret=1;
118     }
119
120     return ret;
121 }
122
123 int dlt_daemon_init(DltDaemon *daemon,unsigned long RingbufferMinSize,unsigned long RingbufferMaxSize,unsigned long RingbufferStepSize,const char *runtime_directory, int verbose)
124 {
125     PRINT_FUNCTION_VERBOSE(verbose);
126
127     if (daemon==0)
128     {
129         return -1;
130     }
131
132     int append_length = 0;
133     daemon->num_contexts = 0;
134     daemon->contexts = 0;
135
136     daemon->num_applications = 0;
137     daemon->applications = 0;
138
139     daemon->default_log_level = DLT_DAEMON_INITIAL_LOG_LEVEL ;
140     daemon->default_trace_status = DLT_DAEMON_INITIAL_TRACE_STATUS ;
141
142     daemon->overflow_counter = 0;
143
144     daemon->runtime_context_cfg_loaded = 0;
145     
146     daemon->mode = DLT_USER_MODE_EXTERNAL;
147
148     daemon->connectionState = 0; /* no logger connected */
149
150     daemon->state = DLT_DAEMON_STATE_INIT; /* initial logging state */
151
152     /* prepare filenames for configuration */
153
154     append_length = PATH_MAX - sizeof(DLT_RUNTIME_APPLICATION_CFG);
155     if(runtime_directory[0])
156     {
157         strncpy(daemon->runtime_application_cfg,runtime_directory,append_length);
158         daemon->runtime_application_cfg[append_length]=0;
159     }
160     else
161     {
162         strncpy(daemon->runtime_application_cfg,DLT_RUNTIME_DEFAULT_DIRECTORY,append_length);
163         daemon->runtime_application_cfg[append_length]=0;
164     }
165     strcat(daemon->runtime_application_cfg,DLT_RUNTIME_APPLICATION_CFG); /* strcat uncritical here, because max length already checked */
166
167     append_length = PATH_MAX - sizeof(DLT_RUNTIME_CONTEXT_CFG);
168     if(runtime_directory[0])
169     {
170         strncpy(daemon->runtime_context_cfg,runtime_directory,append_length);
171         daemon->runtime_context_cfg[append_length]=0;
172     }
173     else
174     {
175         strncpy(daemon->runtime_context_cfg,DLT_RUNTIME_DEFAULT_DIRECTORY,append_length);
176         daemon->runtime_context_cfg[append_length]=0;
177     }
178     strcat(daemon->runtime_context_cfg,DLT_RUNTIME_CONTEXT_CFG); /* strcat uncritical here, because max length already checked */
179
180     append_length = PATH_MAX - sizeof(DLT_RUNTIME_CONFIGURATION);
181     if(runtime_directory[0])
182     {
183         strncpy(daemon->runtime_configuration,runtime_directory,append_length);
184         daemon->runtime_configuration[append_length]=0;
185     }
186     else
187     {
188         strncpy(daemon->runtime_configuration,DLT_RUNTIME_DEFAULT_DIRECTORY,append_length);
189         daemon->runtime_configuration[append_length]=0;
190     }
191     strcat(daemon->runtime_configuration,DLT_RUNTIME_CONFIGURATION); /* strcat uncritical here, because max length already checked */
192
193     /* Check for runtime cfg, if it is loadable, load it! */
194     if ((dlt_daemon_applications_load(daemon,daemon->runtime_application_cfg, verbose)==0) &&
195             (dlt_daemon_contexts_load(daemon,daemon->runtime_context_cfg, verbose)==0))
196     {
197         daemon->runtime_context_cfg_loaded = 1;
198     }
199     
200     /* load configuration if available */
201     dlt_daemon_configuration_load(daemon,daemon->runtime_configuration, verbose);
202     
203     daemon->sendserialheader = 0;
204     daemon->timingpackets = 0;
205
206     dlt_set_id(daemon->ecuid,"");
207
208     /* initialize ring buffer for client connection */
209     snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE,"Ringbuffer configuration: %lu/%lu/%lu\n", RingbufferMinSize,RingbufferMaxSize,RingbufferStepSize );
210     dlt_log(LOG_INFO, str);
211     if (dlt_buffer_init_dynamic(&(daemon->client_ringbuffer), RingbufferMinSize,RingbufferMaxSize,RingbufferStepSize)==-1)
212     {
213         return -1;
214     }
215
216     return 0;
217 }
218
219 int dlt_daemon_free(DltDaemon *daemon,int verbose)
220 {
221     PRINT_FUNCTION_VERBOSE(verbose);
222
223     if (daemon==0)
224     {
225         return -1;
226     }
227
228     /* Free contexts */
229     if (dlt_daemon_contexts_clear(daemon, verbose)==-1)
230     {
231                 return -1;
232     }
233
234     /* Free applications */
235     if (dlt_daemon_applications_clear(daemon, verbose)==-1)
236         {
237                 return -1;
238     }
239
240         /* free ringbuffer */
241         dlt_buffer_free_dynamic(&(daemon->client_ringbuffer));
242
243     return 0;
244 }
245
246 int dlt_daemon_applications_invalidate_fd(DltDaemon *daemon,int fd,int verbose)
247 {
248     int i;
249
250     PRINT_FUNCTION_VERBOSE(verbose);
251
252     if (daemon==0)
253     {
254         return -1;
255     }
256
257     for (i=0; i<daemon->num_applications; i++)
258     {
259         if (daemon->applications[i].user_handle==fd)
260         {
261                 daemon->applications[i].user_handle = DLT_FD_INIT;
262         }
263     }
264
265     return 0;
266 }
267
268 int dlt_daemon_applications_clear(DltDaemon *daemon,int verbose)
269 {
270     int i;
271
272     PRINT_FUNCTION_VERBOSE(verbose);
273
274     if (daemon==0)
275     {
276         return -1;
277     }
278
279     for (i=0; i<daemon->num_applications; i++)
280     {
281         if (daemon->applications[i].application_description!=0)
282         {
283             free(daemon->applications[i].application_description);
284             daemon->applications[i].application_description = 0;
285         }
286     }
287
288     if (daemon->applications)
289     {
290         free(daemon->applications);
291     }
292
293     daemon->applications = 0;
294     daemon->num_applications = 0;
295
296     return 0;
297 }
298
299 DltDaemonApplication* dlt_daemon_application_add(DltDaemon *daemon,char *apid,pid_t pid,char *description, int verbose)
300 {
301     DltDaemonApplication *application;
302         DltDaemonApplication *old;
303     int new_application;
304     int dlt_user_handle;
305         char filename[DLT_DAEMON_COMMON_TEXTBUFSIZE];
306
307     if ((daemon==0) || (apid==0) || (apid[0]=='\0'))
308     {
309         return (DltDaemonApplication*) 0;
310     }
311
312     if (daemon->applications == 0)
313     {
314         daemon->applications = (DltDaemonApplication*) malloc(sizeof(DltDaemonApplication)*DLT_DAEMON_APPL_ALLOC_SIZE);
315         if (daemon->applications==0)
316         {
317                 return (DltDaemonApplication*) 0;
318         }
319     }
320
321     new_application=0;
322
323     /* Check if application [apid] is already available */
324     application = dlt_daemon_application_find(daemon, apid, verbose);
325     if (application==0)
326     {
327         daemon->num_applications += 1;
328
329         if (daemon->num_applications!=0)
330         {
331             if ((daemon->num_applications%DLT_DAEMON_APPL_ALLOC_SIZE)==0)
332             {
333                 /* allocate memory in steps of DLT_DAEMON_APPL_ALLOC_SIZE, e.g. 100 */
334                 old = daemon->applications;
335                 daemon->applications = (DltDaemonApplication*) malloc(sizeof(DltDaemonApplication)*
336                                        ((daemon->num_applications/DLT_DAEMON_APPL_ALLOC_SIZE)+1)*DLT_DAEMON_APPL_ALLOC_SIZE);
337                                 if (daemon->applications==0)
338                                 {
339                                         daemon->applications = old;
340                                         daemon->num_applications -= 1;
341                                         return (DltDaemonApplication*) 0;
342                                 }
343                 memcpy(daemon->applications,old,sizeof(DltDaemonApplication)*daemon->num_applications);
344                 free(old);
345             }
346         }
347
348         application = &(daemon->applications[daemon->num_applications-1]);
349
350         dlt_set_id(application->apid,apid);
351         application->pid = 0;
352         application->application_description = 0;
353         application->num_contexts = 0;
354         application->user_handle = DLT_FD_INIT;
355
356         new_application = 1;
357
358     } else {
359
360                 snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "Duplicate registration of AppId: %s\n",apid);
361                 dlt_log(LOG_ERR, str);
362
363     }
364
365     /* Store application description and pid of application */
366     if (application->application_description)
367     {
368         free(application->application_description);
369         application->application_description=0;
370     }
371
372     if (description)
373     {
374         application->application_description = malloc(strlen(description)+1);
375         if (application->application_description)
376         {
377             strncpy(application->application_description,description,strlen(description));
378             application->application_description[strlen(description)]='\0';
379         }
380     }
381
382     if( application->user_handle != DLT_FD_INIT )
383     {
384         if( application->pid != pid )
385         {
386                 if ( close(application->user_handle) < 0 )
387                 {
388                         snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "close() failed to %s, errno=%d (%s)!\n",filename,errno,strerror(errno)); /* errno 2: ENOENT - No such file or directory */
389                     dlt_log(LOG_ERR, str);
390                 }
391
392                 application->user_handle = DLT_FD_INIT;
393                 application->pid = 0;
394         }
395     }
396
397     /* open user pipe only if it is not yet opened */
398     if (application->user_handle==DLT_FD_INIT && pid!=0)
399     {
400         snprintf(filename,DLT_DAEMON_COMMON_TEXTBUFSIZE,"%s/dlt%d",DLT_USER_DIR,pid);
401
402         dlt_user_handle = open(filename, O_WRONLY|O_NONBLOCK);
403         if ( dlt_user_handle < 0 )
404         {
405             snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "open() failed to %s, errno=%d (%s)!\n",filename,errno,strerror(errno)); /* errno 2: ENOENT - No such file or directory */
406             dlt_log(LOG_ERR, str);
407         } /* if */
408
409         /* check if file file descriptor was already used, and make it invalid if it is reused */
410         /* This prevents sending messages to wrong file descriptor */
411         dlt_daemon_applications_invalidate_fd(daemon,dlt_user_handle,verbose);
412         dlt_daemon_contexts_invalidate_fd(daemon,dlt_user_handle,verbose);
413
414         application->pid = pid;
415         application->user_handle = dlt_user_handle;
416     }
417
418     /* Sort */
419     if (new_application)
420     {
421         qsort(daemon->applications,daemon->num_applications,sizeof(DltDaemonApplication),dlt_daemon_cmp_apid);
422
423         /* Find new position of application with apid*/
424         application = dlt_daemon_application_find(daemon, apid, verbose);
425     }
426
427     return application;
428 }
429
430 int dlt_daemon_application_del(DltDaemon *daemon, DltDaemonApplication *application, int verbose)
431 {
432     int pos;
433
434     PRINT_FUNCTION_VERBOSE(verbose);
435
436     if ((daemon==0) || (application==0))
437     {
438         return -1;
439     }
440
441     if (daemon->num_applications>0)
442     {
443         /* Check if user handle is open; if yes, close it */
444         if (application->user_handle >= DLT_FD_MINIMUM)
445         {
446             close(application->user_handle);
447             application->user_handle=DLT_FD_INIT;
448         }
449
450         /* Free description of application to be deleted */
451         if (application->application_description)
452         {
453             free(application->application_description);
454             application->application_description = 0;
455         }
456
457         pos = application-(daemon->applications);
458
459         /* move all applications above pos to pos */
460         memmove(&(daemon->applications[pos]),&(daemon->applications[pos+1]), sizeof(DltDaemonApplication)*((daemon->num_applications-1)-pos));
461
462         /* Clear last application */
463         memset(&(daemon->applications[daemon->num_applications-1]),0,sizeof(DltDaemonApplication));
464
465         daemon->num_applications--;
466
467     }
468
469     return 0;
470 }
471
472 DltDaemonApplication* dlt_daemon_application_find(DltDaemon *daemon,char *apid,int verbose)
473 {
474     DltDaemonApplication application;
475
476     PRINT_FUNCTION_VERBOSE(verbose);
477
478     if ((daemon==0) || (apid==0) || (apid[0]=='\0') || (daemon->num_applications==0))
479     {
480         return (DltDaemonApplication*) 0;
481     }
482
483     /* Check, if apid is smaller than smallest apid or greater than greatest apid */
484     if ((memcmp(apid,daemon->applications[0].apid,DLT_ID_SIZE)<0) ||
485             (memcmp(apid,daemon->applications[daemon->num_applications-1].apid,DLT_ID_SIZE)>0))
486     {
487         return (DltDaemonApplication*) 0;
488     }
489
490     dlt_set_id(application.apid,apid);
491     return (DltDaemonApplication*)bsearch(&application,daemon->applications,daemon->num_applications,sizeof(DltDaemonApplication),dlt_daemon_cmp_apid);
492 }
493
494 int dlt_daemon_applications_load(DltDaemon *daemon,const char *filename, int verbose)
495 {
496     FILE *fd;
497     ID4 apid;
498     char buf[DLT_DAEMON_COMMON_TEXTBUFSIZE];
499     char *ret;
500     char *pb;
501
502     PRINT_FUNCTION_VERBOSE(verbose);
503
504     if ((daemon==0) || (filename==0) || (filename[0]=='\0'))
505     {
506         return -1;
507     }
508
509     fd=fopen(filename, "r");
510
511     if (fd==0)
512     {
513         snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "DLT runtime-application load, cannot open file %s: %s\n", filename, strerror(errno));
514         dlt_log(LOG_WARNING, str);
515
516         return -1;
517     }
518
519     while (!feof(fd))
520     {
521         /* Clear buf */
522         memset(buf, 0, sizeof(buf));
523
524         /* Get line */
525         ret=fgets(buf,sizeof(buf),fd);
526         if (NULL == ret)
527         {
528             /* fgets always null pointer if the last byte of the file is a new line
529              * We need to check here if there was an error or was it feof.*/
530             if(ferror(fd))
531             {
532                 snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "dlt_daemon_applications_load fgets(buf,sizeof(buf),fd) returned NULL. %s\n",
533                          strerror(errno));
534                 dlt_log(LOG_ERR, str);
535                 fclose(fd);
536                 return -1;
537             }
538             else if(feof(fd))
539             {
540                 fclose(fd);
541                 return 0;
542             }
543             else {
544                 snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "dlt_daemon_applications_load fgets(buf,sizeof(buf),fd) returned NULL. Unknown error.\n");
545                 dlt_log(LOG_ERR, str);
546                 fclose(fd);
547                 return -1;
548             }
549         }
550
551         if (strcmp(buf,"")!=0)
552         {
553             /* Split line */
554             pb=strtok(buf,":");
555             if( pb != 0 )
556             {
557                                 dlt_set_id(apid,pb);
558                                 pb=strtok(NULL,":");
559                                 if( pb != 0 )
560                                 {
561                                         /* pb contains now the description */
562                                         /* pid is unknown at loading time */
563                                         if (dlt_daemon_application_add(daemon,apid,0,pb,verbose)==0)
564                                         {
565                                                 dlt_log(LOG_ERR, "dlt_daemon_applications_load dlt_daemon_application_add failed\n");
566                                                 fclose(fd);
567                                                 return -1;
568                                         }
569                                 }
570             }
571         }
572     }
573     fclose(fd);
574
575     return 0;
576 }
577
578 int dlt_daemon_applications_save(DltDaemon *daemon,const char *filename, int verbose)
579 {
580     FILE *fd;
581     int i;
582
583     char apid[DLT_ID_SIZE+1]; /* DLT_ID_SIZE+1, because the 0-termination is required here */
584
585     PRINT_FUNCTION_VERBOSE(verbose);
586
587     if ((daemon==0) || (filename==0) || (filename[0]=='\0'))
588     {
589         return -1;
590     }
591
592     memset(apid,0, sizeof(apid));
593
594     if ((daemon->applications) && (daemon->num_applications>0))
595     {
596         fd=fopen(filename, "w");
597         if (fd!=0)
598         {
599             for (i=0; i<daemon->num_applications; i++)
600             {
601                 dlt_set_id(apid,daemon->applications[i].apid);
602
603                 if ((daemon->applications[i].application_description) &&
604                         (daemon->applications[i].application_description!='\0'))
605                 {
606                     fprintf(fd,"%s:%s:\n",apid, daemon->applications[i].application_description);
607                 }
608                 else
609                 {
610                     fprintf(fd,"%s::\n",apid);
611                 }
612             }
613             fclose(fd);
614         }
615     }
616
617     return 0;
618 }
619
620 DltDaemonContext* dlt_daemon_context_add(DltDaemon *daemon,char *apid,char *ctid,int8_t log_level,int8_t trace_status,int log_level_pos, int user_handle,char *description,int verbose)
621 {
622     DltDaemonApplication *application;
623     DltDaemonContext *context;
624     DltDaemonContext *old;
625     int new_context=0;
626
627     PRINT_FUNCTION_VERBOSE(verbose);
628
629     if ((daemon==0) || (apid==0) || (apid[0]=='\0') || (ctid==0) || (ctid[0]=='\0'))
630     {
631         return (DltDaemonContext*) 0;
632     }
633
634     if ((log_level<DLT_LOG_DEFAULT) || (log_level>DLT_LOG_VERBOSE))
635     {
636         return (DltDaemonContext*) 0;
637     }
638
639     if ((trace_status<DLT_TRACE_STATUS_DEFAULT) || (trace_status>DLT_TRACE_STATUS_ON))
640     {
641         return (DltDaemonContext*) 0;
642     }
643
644     if (daemon->contexts == 0)
645     {
646         daemon->contexts = (DltDaemonContext*) malloc(sizeof(DltDaemonContext)*DLT_DAEMON_CONTEXT_ALLOC_SIZE);
647         if (daemon->contexts==0)
648         {
649                         return (DltDaemonContext*) 0;
650         }
651     }
652
653     /* Check if application [apid] is available */
654     application = dlt_daemon_application_find(daemon, apid, verbose);
655     if (application==0)
656     {
657         return (DltDaemonContext*) 0;
658     }
659
660     /* Check if context [apid, ctid] is already available */
661     context = dlt_daemon_context_find(daemon, apid, ctid, verbose);
662     if (context==0)
663     {
664         daemon->num_contexts += 1;
665
666         if (daemon->num_contexts!=0)
667         {
668             if ((daemon->num_contexts%DLT_DAEMON_CONTEXT_ALLOC_SIZE)==0)
669             {
670                 /* allocate memory for context in steps of DLT_DAEMON_CONTEXT_ALLOC_SIZE, e.g 100 */
671                 old = daemon->contexts;
672                 daemon->contexts = (DltDaemonContext*) malloc(sizeof(DltDaemonContext)*
673                                    ((daemon->num_contexts/DLT_DAEMON_CONTEXT_ALLOC_SIZE)+1)*DLT_DAEMON_CONTEXT_ALLOC_SIZE);
674                                 if (daemon->contexts==0)
675                                 {
676                                         daemon->contexts = old;
677                                         daemon->num_contexts -= 1;
678                                         return (DltDaemonContext*) 0;
679                                 }
680                 memcpy(daemon->contexts,old,sizeof(DltDaemonContext)*daemon->num_contexts);
681                 free(old);
682             }
683         }
684
685         context = &(daemon->contexts[daemon->num_contexts-1]);
686
687         dlt_set_id(context->apid,apid);
688         dlt_set_id(context->ctid,ctid);
689         context->context_description = 0;
690
691         application->num_contexts++;
692         new_context =1;
693     }
694
695     /* Set context description */
696     if (context->context_description)
697     {
698         free(context->context_description);
699         context->context_description=0;
700     }
701
702     if (description)
703     {
704         context->context_description = malloc(strlen(description)+1);
705
706         if (context->context_description)
707         {
708             strncpy(context->context_description,description,strlen(description));
709             context->context_description[strlen(description)]='\0';
710         }
711     }
712
713     /* Store log level and trace status,
714        if this is a new context, or
715        if this is an old context and the runtime cfg was not loaded */
716
717     if ((new_context==1) ||
718             ((new_context==0) && (daemon->runtime_context_cfg_loaded==0)))
719     {
720         context->log_level = log_level;
721         context->trace_status = trace_status;
722     }
723
724     context->log_level_pos = log_level_pos;
725     context->user_handle = user_handle;
726
727     /* Sort */
728     if (new_context)
729     {
730         qsort(daemon->contexts,daemon->num_contexts, sizeof(DltDaemonContext),dlt_daemon_cmp_apid_ctid);
731
732         /* Find new position of context with apid, ctid */
733         context = dlt_daemon_context_find(daemon, apid, ctid, verbose);
734     }
735
736     return context;
737 }
738
739 int dlt_daemon_context_del(DltDaemon *daemon, DltDaemonContext* context, int verbose)
740 {
741     int pos;
742     DltDaemonApplication *application;
743
744     PRINT_FUNCTION_VERBOSE(verbose);
745
746     if ((daemon==0) || (context==0))
747     {
748         return -1;
749     }
750
751     if (daemon->num_contexts>0)
752     {
753         application = dlt_daemon_application_find(daemon, context->apid, verbose);
754
755         /* Free description of context to be deleted */
756         if (context->context_description)
757         {
758             free(context->context_description);
759             context->context_description = 0;
760         }
761
762         pos = context-(daemon->contexts);
763
764         /* move all contexts above pos to pos */
765         memmove(&(daemon->contexts[pos]),&(daemon->contexts[pos+1]), sizeof(DltDaemonContext)*((daemon->num_contexts-1)-pos));
766
767         /* Clear last context */
768         memset(&(daemon->contexts[daemon->num_contexts-1]),0,sizeof(DltDaemonContext));
769
770         daemon->num_contexts--;
771
772         /* Check if application [apid] is available */
773         if (application)
774         {
775             application->num_contexts--;
776         }
777     }
778
779     return 0;
780 }
781
782 DltDaemonContext* dlt_daemon_context_find(DltDaemon *daemon,char *apid,char *ctid,int verbose)
783 {
784     DltDaemonContext context;
785
786     PRINT_FUNCTION_VERBOSE(verbose);
787
788     if ((daemon==0) || (apid==0) || (apid[0]=='\0') || (ctid==0) || (ctid[0]=='\0') || (daemon->num_contexts==0))
789     {
790         return (DltDaemonContext*) 0;
791     }
792
793     /* Check, if apid is smaller than smallest apid or greater than greatest apid */
794     if ((memcmp(apid,daemon->contexts[0].apid,DLT_ID_SIZE)<0) ||
795             (memcmp(apid,daemon->contexts[daemon->num_contexts-1].apid,DLT_ID_SIZE)>0))
796     {
797         return (DltDaemonContext*) 0;
798     }
799
800     dlt_set_id(context.apid,apid);
801     dlt_set_id(context.ctid,ctid);
802
803     return (DltDaemonContext*)bsearch(&context,daemon->contexts,daemon->num_contexts,sizeof(DltDaemonContext),dlt_daemon_cmp_apid_ctid);
804 }
805
806 int dlt_daemon_contexts_invalidate_fd(DltDaemon *daemon,int fd,int verbose)
807 {
808     int i;
809
810     PRINT_FUNCTION_VERBOSE(verbose);
811
812     if (daemon==0)
813     {
814         return -1;
815     }
816
817     for (i=0; i<daemon->num_contexts; i++)
818     {
819         if (daemon->contexts[i].user_handle==fd)
820         {
821                 daemon->contexts[i].user_handle = DLT_FD_INIT;
822         }
823     }
824
825     return 0;
826 }
827
828 int dlt_daemon_contexts_clear(DltDaemon *daemon,int verbose)
829 {
830     int i;
831
832     PRINT_FUNCTION_VERBOSE(verbose);
833
834     if (daemon==0)
835     {
836         return -1;
837     }
838
839     for (i=0; i<daemon->num_contexts; i++)
840     {
841         if (daemon->contexts[i].context_description!=0)
842         {
843             free(daemon->contexts[i].context_description);
844             daemon->contexts[i].context_description = 0;
845         }
846     }
847
848     if (daemon->contexts)
849     {
850         free(daemon->contexts);
851     }
852
853     daemon->contexts = 0;
854
855     for (i=0; i<daemon->num_applications; i++)
856     {
857         daemon->applications[i].num_contexts = 0;
858     }
859
860     daemon->num_contexts = 0;
861
862     return 0;
863 }
864
865 int dlt_daemon_contexts_load(DltDaemon *daemon,const char *filename, int verbose)
866 {
867     FILE *fd;
868     ID4 apid, ctid;
869     char buf[DLT_DAEMON_COMMON_TEXTBUFSIZE];
870     char *ret;
871     char *pb;
872     int ll, ts;
873
874     PRINT_FUNCTION_VERBOSE(verbose);
875
876     if ((daemon==0) || (filename==0) ||( filename[0]=='\0'))
877     {
878         return -1;
879     }
880
881     fd=fopen(filename, "r");
882
883     if (fd==0)
884     {
885         snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "DLT runtime-context load, cannot open file %s: %s\n", filename, strerror(errno));
886         dlt_log(LOG_WARNING, str);
887
888         return -1;
889     }
890
891     while (!feof(fd))
892     {
893         /* Clear buf */
894         memset(buf, 0, sizeof(buf));
895
896         /* Get line */
897         ret=fgets(buf,sizeof(buf),fd);
898         if (NULL == ret)
899         {
900             /* fgets always returns null pointer if the last byte of the file is a new line.
901              * We need to check here if there was an error or was it feof.*/
902             if(ferror(fd))
903             {
904                 snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "dlt_daemon_contexts_load fgets(buf,sizeof(buf),fd) returned NULL. %s\n",
905                          strerror(errno));
906                 dlt_log(LOG_ERR, str);
907                 fclose(fd);
908                 return -1;
909             }
910             else if(feof(fd))
911             {
912                 fclose(fd);
913                 return 0;
914             }
915             else {
916                 snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE, "dlt_daemon_contexts_load fgets(buf,sizeof(buf),fd) returned NULL. Unknown error.\n");
917                 dlt_log(LOG_ERR, str);
918                 fclose(fd);
919                 return -1;
920             }
921         }
922
923         if (strcmp(buf,"")!=0)
924         {
925             /* Split line */
926             pb=strtok(buf,":");
927             if(pb!=0)
928             {
929                                 dlt_set_id(apid,pb);
930                                 pb=strtok(NULL,":");
931                     if(pb!=0)
932                     {
933                                         dlt_set_id(ctid,pb);
934                                         pb=strtok(NULL,":");
935                             if(pb!=0)
936                             {
937                                                 sscanf(pb,"%d",&ll);
938                                                 pb=strtok(NULL,":");
939                                     if(pb!=0)
940                                     {
941                                                         sscanf(pb,"%d",&ts);
942                                                         pb=strtok(NULL,":");
943                                             if(pb!=0)
944                                             {
945                                                                 /* pb contains now the description */
946
947                                                                 /* log_level_pos, and user_handle are unknown at loading time */
948                                                                 if (dlt_daemon_context_add(daemon,apid,ctid,(int8_t)ll,(int8_t)ts,0,0,pb,verbose)==0)
949                                                                 {
950                                                                         dlt_log(LOG_ERR, "dlt_daemon_contexts_load dlt_daemon_context_add failed\n");
951                                                                         fclose(fd);
952                                                                         return -1;
953                                                                 }
954                                             }
955                                     }
956                             }
957                     }
958             }
959         }
960     }
961     fclose(fd);
962
963     return 0;
964 }
965
966 int dlt_daemon_contexts_save(DltDaemon *daemon,const char *filename, int verbose)
967 {
968     FILE *fd;
969     int i;
970
971     char apid[DLT_ID_SIZE+1], ctid[DLT_ID_SIZE+1]; /* DLT_ID_SIZE+1, because the 0-termination is required here */
972
973     PRINT_FUNCTION_VERBOSE(verbose);
974
975     if ((daemon==0) || (filename==0) ||( filename[0]=='\0'))
976     {
977         return -1;
978     }
979
980     memset(apid,0, sizeof(apid));
981     memset(ctid,0, sizeof(ctid));
982
983     if ((daemon->contexts) && (daemon->num_contexts>0))
984     {
985         fd=fopen(filename, "w");
986         if (fd!=0)
987         {
988             for (i=0; i<daemon->num_contexts; i++)
989             {
990                 dlt_set_id(apid,daemon->contexts[i].apid);
991                 dlt_set_id(ctid,daemon->contexts[i].ctid);
992
993                 if ((daemon->contexts[i].context_description) &&
994                         (daemon->contexts[i].context_description[0]!='\0'))
995                 {
996                     fprintf(fd,"%s:%s:%d:%d:%s:\n",apid,ctid,
997                             (int)(daemon->contexts[i].log_level),
998                             (int)(daemon->contexts[i].trace_status),
999                             daemon->contexts[i].context_description);
1000                 }
1001                 else
1002                 {
1003                     fprintf(fd,"%s:%s:%d:%d::\n",apid,ctid,
1004                             (int)(daemon->contexts[i].log_level),
1005                             (int)(daemon->contexts[i].trace_status));
1006                 }
1007             }
1008             fclose(fd);
1009         }
1010     }
1011
1012     return 0;
1013 }
1014
1015 int dlt_daemon_configuration_save(DltDaemon *daemon,const char *filename, int verbose)
1016 {
1017     FILE *fd;
1018
1019     PRINT_FUNCTION_VERBOSE(verbose);
1020
1021     if ((daemon==0) || (filename==0) ||( filename[0]=='\0'))
1022     {
1023         return -1;
1024     }
1025
1026         fd=fopen(filename, "w");
1027         if (fd!=0)
1028         {
1029                 fprintf(fd,"# 0 = off, 1 = external, 2 = internal, 3 = both\n");
1030                 fprintf(fd,"LoggingMode = %d\n",daemon->mode);
1031
1032                 fclose(fd);
1033         }
1034
1035     return 0;
1036 }
1037
1038 int dlt_daemon_configuration_load(DltDaemon *daemon,const char *filename, int verbose)
1039 {
1040         FILE * pFile;
1041         char line[1024];
1042         char token[1024];
1043         char value[1024];
1044     char *pch;
1045
1046     PRINT_FUNCTION_VERBOSE(verbose);
1047
1048         pFile = fopen (filename,"r");
1049
1050         if (pFile!=NULL)
1051         {
1052                 while(1)
1053                 {
1054                         /* fetch line from configuration file */
1055                         if ( fgets (line , 1024 , pFile) != NULL )
1056                         {
1057                                   pch = strtok (line," =\r\n");
1058                                   token[0]=0;
1059                                   value[0]=0;
1060                                   
1061                                   while (pch != NULL)
1062                                   {
1063                                         if(strcmp(pch,"#")==0)
1064                                                 break;
1065
1066                                         if(token[0]==0)
1067                                         {
1068                                                 strncpy(token,pch,sizeof(token)-1);
1069                                                 token[sizeof(token)-1]=0;
1070                                         }
1071                                         else
1072                                         {
1073                                                 strncpy(value,pch,sizeof(value)-1);
1074                                                 value[sizeof(value)-1]=0;
1075                                                 break;
1076                                         }
1077
1078                                         pch = strtok (NULL, " =\r\n");
1079                                   }
1080                                   
1081                                   if(token[0] && value[0])
1082                                   {
1083                                                 /* parse arguments here */
1084                                                 if(strcmp(token,"LoggingMode")==0)
1085                                                 {
1086                                                         daemon->mode = atoi(value);
1087                                                         snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE,"Runtime Option: %s=%d\n",token,daemon->mode);
1088                                                         dlt_log(LOG_INFO, str);
1089                                                 }
1090                                                 else
1091                                                 {
1092                                                         snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE,"Unknown option: %s=%s\n",token,value);
1093                                                         dlt_log(LOG_ERR, str);
1094                                                 }
1095                                         }
1096                         }
1097                         else
1098                         {
1099                                 break;
1100                         }
1101                 }
1102                 fclose (pFile);
1103         }
1104         else
1105         {
1106         snprintf(str,DLT_DAEMON_COMMON_TEXTBUFSIZE,"Cannot open configuration file: %s\n",filename);
1107         dlt_log(LOG_WARNING, str);
1108         }       
1109         
1110     return 0;
1111 }
1112
1113 int dlt_daemon_user_send_log_level(DltDaemon *daemon,DltDaemonContext *context,int verbose)
1114 {
1115     DltUserHeader userheader;
1116     DltUserControlMsgLogLevel usercontext;
1117     DltReturnValue ret;
1118
1119     PRINT_FUNCTION_VERBOSE(verbose);
1120
1121     if ((daemon==0) || (context==0))
1122     {
1123         return -1;
1124     }
1125
1126     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_LEVEL)==-1)
1127     {
1128         return -1;
1129     }
1130
1131     usercontext.log_level = ((context->log_level == DLT_LOG_DEFAULT)?daemon->default_log_level:context->log_level);
1132     usercontext.trace_status = ((context->trace_status == DLT_TRACE_STATUS_DEFAULT)?daemon->default_trace_status:context->trace_status);
1133
1134     usercontext.log_level_pos = context->log_level_pos;
1135
1136     /* log to FIFO */
1137     ret = dlt_user_log_out2(context->user_handle, &(userheader), sizeof(DltUserHeader),  &(usercontext), sizeof(DltUserControlMsgLogLevel));
1138
1139     if (ret!=DLT_RETURN_OK)
1140     {
1141         if (errno==EPIPE)
1142         {
1143             /* Close connection */
1144             close(context->user_handle);
1145             context->user_handle=DLT_FD_INIT;
1146         }
1147     }
1148
1149     return ((ret==DLT_RETURN_OK)?0:-1);
1150 }
1151
1152 int dlt_daemon_user_send_log_state(DltDaemon *daemon,DltDaemonApplication *app,int verbose)
1153 {
1154     DltUserHeader userheader;
1155     DltUserControlMsgLogState logstate;
1156     DltReturnValue ret;
1157
1158     PRINT_FUNCTION_VERBOSE(verbose);
1159
1160     if ((daemon==0) || (app==0))
1161     {
1162         return -1;
1163     }
1164
1165     if (dlt_user_set_userheader(&userheader, DLT_USER_MESSAGE_LOG_STATE)==-1)
1166     {
1167         return -1;
1168     }
1169
1170     logstate.log_state = daemon->connectionState;
1171
1172     /* log to FIFO */
1173     ret = dlt_user_log_out2(app->user_handle, &(userheader), sizeof(DltUserHeader),  &(logstate), sizeof(DltUserControlMsgLogState));
1174
1175     if (ret!=DLT_RETURN_OK)
1176     {
1177         if (errno==EPIPE)
1178         {
1179             /* Close connection */
1180             close(app->user_handle);
1181             app->user_handle=DLT_FD_INIT;
1182         }
1183     }
1184
1185     return ((ret==DLT_RETURN_OK)?0:-1);
1186 }
1187
1188 void dlt_daemon_control_reset_to_factory_default(DltDaemon *daemon,const char *filename, const char *filename1, int verbose)
1189 {
1190     FILE *fd;
1191
1192     PRINT_FUNCTION_VERBOSE(verbose);
1193
1194     if ((daemon==0) || (filename==0) || (filename1==0) || (filename[0]=='\0') || (filename1[0]=='\0'))
1195     {
1196         return;
1197     }
1198
1199     /* Check for runtime cfg file and delete it, if available */
1200     fd=fopen(filename, "r");
1201
1202     if (fd!=0)
1203     {
1204         /* Close and delete file */
1205         fclose(fd);
1206         unlink(filename);
1207     }
1208
1209     fd=fopen(filename1, "r");
1210
1211     if (fd!=0)
1212     {
1213         /* Close and delete file */
1214         fclose(fd);
1215         unlink(filename1);
1216     }
1217
1218     daemon->default_log_level = DLT_DAEMON_INITIAL_LOG_LEVEL ;
1219     daemon->default_trace_status = DLT_DAEMON_INITIAL_TRACE_STATUS ;
1220
1221     /* Reset all other things (log level, trace status, etc.
1222                                                    to default values             */
1223
1224     /* Inform user libraries about changed default log level/trace status */
1225     dlt_daemon_user_send_default_update(daemon, verbose);
1226 }
1227
1228 void dlt_daemon_user_send_default_update(DltDaemon *daemon, int verbose)
1229 {
1230     int32_t count;
1231     DltDaemonContext *context;
1232
1233     PRINT_FUNCTION_VERBOSE(verbose);
1234
1235     if (daemon==0)
1236     {
1237         return;
1238     }
1239
1240     for (count=0;count<daemon->num_contexts; count ++)
1241     {
1242         context = &(daemon->contexts[count]);
1243
1244         if (context)
1245         {
1246             if ((context->log_level == DLT_LOG_DEFAULT) ||
1247                     (context->trace_status == DLT_TRACE_STATUS_DEFAULT))
1248             {
1249                 if (context->user_handle >= DLT_FD_MINIMUM)
1250                 {
1251                     if (dlt_daemon_user_send_log_level(daemon, context, verbose)==-1)
1252                     {
1253                         return;
1254                     }
1255                 }
1256             }
1257         }
1258     }
1259 }
1260
1261 void dlt_daemon_user_send_all_log_state(DltDaemon *daemon, int verbose)
1262 {
1263     int32_t count;
1264     DltDaemonApplication *app;
1265
1266     PRINT_FUNCTION_VERBOSE(verbose);
1267
1268     if (daemon==0)
1269     {
1270         return;
1271     }
1272
1273     for (count=0;count<daemon->num_applications; count ++)
1274     {
1275         app = &(daemon->applications[count]);
1276
1277         if (app)
1278         {
1279                         if (app->user_handle >= DLT_FD_MINIMUM)
1280                         {
1281                                 if (dlt_daemon_user_send_log_state(daemon, app, verbose)==-1)
1282                                 {
1283                                         return;
1284                                 }
1285                         }
1286         }
1287     }
1288 }
1289
1290 void dlt_daemon_change_state(DltDaemon *daemon, DltDaemonState newState)
1291 {
1292         switch(newState)
1293         {
1294                 case DLT_DAEMON_STATE_INIT:
1295                 dlt_log(LOG_INFO,"Switched to init state.\n");
1296                         daemon->state = DLT_DAEMON_STATE_INIT;
1297                         break;
1298                 case DLT_DAEMON_STATE_BUFFER:
1299                 dlt_log(LOG_INFO,"Switched to buffer state.\n");
1300                         daemon->state = DLT_DAEMON_STATE_BUFFER;
1301                         break;
1302                 case DLT_DAEMON_STATE_BUFFER_FULL:
1303                 dlt_log(LOG_INFO,"Switched to buffer full state.\n");
1304                         daemon->state = DLT_DAEMON_STATE_BUFFER_FULL;
1305                         break;
1306                 case DLT_DAEMON_STATE_SEND_BUFFER:
1307                 dlt_log(LOG_INFO,"Switched to send buffer state.\n");
1308                         daemon->state = DLT_DAEMON_STATE_SEND_BUFFER;
1309                         break;
1310                 case DLT_DAEMON_STATE_SEND_DIRECT:
1311                 dlt_log(LOG_INFO,"Switched to send direct state.\n");
1312                         daemon->state = DLT_DAEMON_STATE_SEND_DIRECT;
1313                         break;
1314         }
1315
1316 }
1317
1318
1319