SAH_Trace  1.1.0
SAHTRACE Module
mod_main.c
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** SPDX-License-Identifier: BSD-2-Clause-Patent
4 **
5 ** SPDX-FileCopyrightText: Copyright (c) 2023 SoftAtHome
6 **
7 ** Redistribution and use in source and binary forms, with or without modification,
8 ** are permitted provided that the following conditions are met:
9 **
10 ** 1. Redistributions of source code must retain the above copyright notice,
11 ** this list of conditions and the following disclaimer.
12 **
13 ** 2. Redistributions in binary form must reproduce the above copyright notice,
14 ** this list of conditions and the following disclaimer in the documentation
15 ** and/or other materials provided with the distribution.
16 **
17 ** Subject to the terms and conditions of this license, each copyright holder
18 ** and contributor hereby grants to those receiving rights under this license
19 ** a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
20 ** (except for failure to satisfy the conditions of this license) patent license
21 ** to make, have made, use, offer to sell, sell, import, and otherwise transfer
22 ** this software, where such license applies only to those patent claims, already
23 ** acquired or hereafter acquired, licensable by such copyright holder or contributor
24 ** that are necessarily infringed by:
25 **
26 ** (a) their Contribution(s) (the licensed copyrights of copyright holders and
27 ** non-copyrightable additions of contributors, in source or binary form) alone;
28 ** or
29 **
30 ** (b) combination of their Contribution(s) with the work of authorship to which
31 ** such Contribution(s) was added by such copyright holder or contributor, if,
32 ** at the time the Contribution is added, such addition causes such combination
33 ** to be necessarily infringed. The patent license shall not apply to any other
34 ** combinations which include the Contribution.
35 **
36 ** Except as expressly stated above, no rights or licenses from any copyright
37 ** holder or contributor is granted under this license, whether expressly, by
38 ** implication, estoppel or otherwise.
39 **
40 ** DISCLAIMER
41 **
42 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
46 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
51 ** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 **
53 ****************************************************************************/
54 
55 #ifndef _GNU_SOURCE
56 #define _GNU_SOURCE
57 #endif
58 
59 #include <string.h>
60 #include <stdlib.h>
61 #include <stdio.h>
62 #include <sys/stat.h>
63 #include <unistd.h>
64 #include <syslog.h>
65 
66 #include <debug/sahtrace.h>
67 #include <debug/sahtrace_macros.h>
68 
69 #include <amxc/amxc.h>
70 #include <amxp/amxp.h>
71 #include <amxd/amxd_dm.h>
72 #include <amxo/amxo.h>
73 
74 #include <amxd/amxd_object.h>
75 #include <amxc/amxc_macros.h>
76 #include <amxo/amxo_save.h>
77 
78 #include "mod_main.h"
79 
80 #define UNUSED __attribute__((unused))
81 
82 static char* identity = NULL;
83 amxo_parser_t* trace_parser = NULL;
84 
85 int _main(int reason,
86  amxd_dm_t* dm,
87  amxo_parser_t* parser);
88 
89 static sah_trace_type mod_sahtrace_type_to_id(const char* type, bool daemon) {
90  static const char* types[] = {
91  "syslog",
92  "stdout",
93  "stderr",
94  "file",
95  "auto",
96  NULL
97  };
98  sah_trace_type type_id = TRACE_TYPE_SYSLOG;
99  int i = 0;
100 
101  for(i = 0; types[i] != NULL; i++) {
102  if(strcmp(type, types[i]) == 0) {
103  break;
104  }
105  }
106 
107  if(types[i] != NULL) {
108  if(i == 4) {
109  type_id = daemon? TRACE_TYPE_SYSLOG:TRACE_TYPE_STDERR;
110  } else {
111  type_id = (sah_trace_type) i;
112  }
113  }
114 
115  return type_id;
116 }
117 
118 static uint32_t mod_sahtrace_get_default_log_level(void) {
119  uint32_t default_log_level = GET_UINT32(&trace_parser->config, "default_log_level");
120  return default_log_level != 0 ? default_log_level : 200;
121 }
122 
124  uint32_t default_trace_zone_level = GET_UINT32(&trace_parser->config, "default_trace_zone_level");
125  return default_trace_zone_level != 0 ? default_trace_zone_level : 200;
126 }
127 
128 static amxc_var_t* mod_sahtrace_get(amxc_var_t* opts,
129  amxc_var_t* sahtrace_opts,
130  const char* opt_name,
131  const char* alt_name) {
132  amxc_var_t* var = amxc_var_get_key(sahtrace_opts,
133  opt_name,
134  AMXC_VAR_FLAG_DEFAULT);
135  if(var == NULL) {
136  var = amxc_var_get_key(opts,
137  alt_name,
138  AMXC_VAR_FLAG_DEFAULT);
139  }
140 
141  return var;
142 }
143 
144 static void mod_sahtrace_open(const char* name,
145  const char* type_name,
146  amxc_var_t* file_var,
147  bool daemon) {
148  sah_trace_type type_id = mod_sahtrace_type_to_id(type_name, daemon);
149  if(type_id != TRACE_TYPE_FILE) {
150  sahTraceOpen(name, type_id);
151  } else {
152  if(amxc_var_type_of(file_var) == AMXC_VAR_ID_CSTRING) {
153  const char* file_name = amxc_var_constcast(cstring_t, file_var);
154  sahTraceOpenFile(name, file_name);
155  }
156  }
157 }
158 
159 static void mod_sahtrace_init(amxc_var_t* options) {
160  const char* name = GET_CHAR(options, "name");
161  const char* type_name = "auto";
162  amxc_var_t* sahtrace_opts = amxc_var_get_key(options,
163  "sahtrace",
164  AMXC_VAR_FLAG_DEFAULT);
165  amxc_var_t* type_var = mod_sahtrace_get(options, sahtrace_opts,
166  "type", "log-type");
167  amxc_var_t* level_var = mod_sahtrace_get(options, sahtrace_opts,
168  "level", "log-level");
169  amxc_var_t* file_var = mod_sahtrace_get(options, sahtrace_opts,
170  "file", "log-file");
171  bool daemon = GET_BOOL(options, "daemon");
173 
174  if((type_var != NULL) &&
175  ( amxc_var_type_of(type_var) == AMXC_VAR_ID_CSTRING)) {
176  type_name = amxc_var_constcast(cstring_t, type_var);
177  }
178 
179  if(identity == NULL) {
180  identity = strdup(name == NULL ? "mod_sahtrace" : name);
181  mod_sahtrace_open(identity, type_name, file_var, daemon);
182  }
183 
184  if(level_var != NULL) {
185  level = amxc_var_dyncast(uint32_t, level_var);
186  }
187  sahTraceSetLevel(level);
188 }
189 
190 
191 static void mod_sahtrace_add_zones(amxc_var_t* options) {
192  amxc_var_t* zones_var = mod_sahtrace_get(options, options,
193  "trace-zones", "log-zones");
194  amxc_var_t* sahtrace_opts = amxc_var_get_key(options,
195  "sahtrace",
196  AMXC_VAR_FLAG_DEFAULT);
197  amxc_var_t* level_var = mod_sahtrace_get(options, sahtrace_opts,
198  "level", "log-level");
200 
201  when_null(zones_var, exit);
202 
203  if(level_var != NULL) {
204  level = amxc_var_dyncast(uint32_t, level_var);
205  }
206 
207  if(amxc_var_type_of(zones_var) == AMXC_VAR_ID_LIST) {
208  amxc_var_for_each(zone, zones_var) {
209  const char* zone_name = amxc_var_constcast(cstring_t, zone);
210  if(amxc_var_type_of(zone) != AMXC_VAR_ID_CSTRING) {
211  continue;
212  }
213  sahTraceAddZone(level, zone_name);
214  }
215  }
216 
217  if(amxc_var_type_of(zones_var) == AMXC_VAR_ID_HTABLE) {
218  const amxc_htable_t* zones = amxc_var_constcast(amxc_htable_t, zones_var);
219  amxc_htable_for_each(it, zones) {
220  const char* zone_name = amxc_htable_it_get_key(it);
221  amxc_var_t* var_level = amxc_var_from_htable_it(it);
222  uint32_t zone_level = amxc_var_dyncast(uint32_t, var_level);
223  sahTraceAddZone(zone_level, zone_name);
224  }
225  }
226 
227 exit:
228  return;
229 }
230 
231 static int mod_sahtrace_save_config(void) {
232  const char* path = GETP_CHAR(&trace_parser->config, "config-storage-file");
233  amxd_status_t status = amxd_status_unknown_error;
234  amxc_var_t* trace_zones = NULL;
235  amxc_var_t config;
236 
237  amxc_var_init(&config);
238  amxc_var_set_type(&config, AMXC_VAR_ID_HTABLE);
239  trace_zones = amxc_var_add_key(amxc_htable_t, &config, "trace-zones", NULL);
240  amxc_var_copy(trace_zones, GET_ARG(&trace_parser->config, "trace-zones"));
241 
242  status = amxo_parser_save_config(trace_parser, path, &config, false);
243  when_failed_trace(status, exit, ERROR, "Failed to save parser config file: %s", path);
244 
245 exit:
246  amxc_var_clean(&config);
247  return status;
248 }
249 
250 amxd_status_t set_trace_zone(UNUSED amxd_object_t* object,
251  UNUSED amxd_function_t* func,
252  amxc_var_t* args,
253  UNUSED amxc_var_t* ret) {
254  const char* zone = GET_CHAR(args, "zone");
255  uint32_t level = GET_UINT32(args, "level");
256  uint32_t log_levels[] = {0, 100, 200, 300, 350, 400, 500};
257  int length = sizeof(log_levels) / sizeof(log_levels[0]);
258  amxd_status_t status = amxd_status_unknown_error;
259  amxc_var_t trace_table;
260  amxc_var_t* current_zone = NULL;
261  amxc_var_t* var = amxo_parser_get_config(trace_parser, "trace-zones");
262  amxc_var_init(&trace_table);
263 
264  if(var == NULL) {
265  amxc_var_set_type(&trace_table, AMXC_VAR_ID_HTABLE);
266  } else {
267  amxc_var_copy(&trace_table, var);
268  }
269 
270  for(int i = 0; i < length; i++) {
271  if(level == log_levels[i]) {
272  status = amxd_status_ok;
273  break;
274  }
275  }
276  when_failed_trace(status, exit, ERROR, "Invalid level value: %d", level);
277 
278  current_zone = GET_ARG(&trace_table, zone);
279  if(current_zone == NULL) {
280  amxc_var_add_key(uint32_t, &trace_table, zone, level);
281  } else {
282  amxc_var_set(uint32_t, current_zone, level);
283  }
284 
285  status = amxo_parser_set_config(trace_parser, "trace-zones", &trace_table);
286  when_failed_trace(status, exit, ERROR, "Failed to add zone to config: %s %d", zone, level);
287  when_failed(mod_sahtrace_save_config(), exit);
289 exit:
290  amxc_var_clean(&trace_table);
291  return status;
292 }
293 
294 
295 amxd_status_t list_trace_zone(UNUSED amxd_object_t* object,
296  UNUSED amxd_function_t* func,
297  UNUSED amxc_var_t* args,
298  amxc_var_t* ret) {
299  amxd_status_t rc = amxd_status_unknown_error;
300  amxc_var_set_type(ret, AMXC_VAR_ID_HTABLE);
301  amxc_var_t* var = amxo_parser_get_config(trace_parser, "trace-zones");
302  amxc_var_copy(ret, var);
303 
304  rc = amxd_status_ok;
305  return rc;
306 }
307 
309  amxd_status_t rc = amxd_status_unknown_error;
310  amxd_function_t* set_function = NULL;
311  amxd_function_t* list_function = NULL;
312  amxd_object_t* object = amxd_object_get_base(amxd_dm_get_root(dm));
313  amxd_object_fn_t set_impl = set_trace_zone;
314  amxd_object_fn_t list_impl = list_trace_zone;
315  amxc_var_t def_val;
316 
317  amxc_var_init(&def_val);
318  amxc_var_set(uint32_t, &def_val, mod_sahtrace_get_default_trace_zone_level());
319 
320  when_null(object, exit);
321 
322  rc = amxd_function_new(&set_function, "set_trace_zone", AMXC_VAR_ID_NULL, set_impl);
323  when_failed(rc, exit);
324 
325  rc = amxd_function_new(&list_function, "list_trace_zones", AMXC_VAR_ID_HTABLE, list_impl);
326  when_failed(rc, exit);
327 
328  rc = amxd_function_new_arg(set_function, "zone", AMXC_VAR_ID_CSTRING, NULL);
329  when_failed(rc, exit);
330  amxd_function_arg_set_attr(set_function, "zone", amxd_aattr_in, true);
331  rc = amxd_function_new_arg(set_function, "level", AMXC_VAR_ID_UINT32, &def_val);
332  when_failed(rc, exit);
333  amxd_function_arg_set_attr(set_function, "level", amxd_aattr_in, true);
334 
335  rc = amxd_object_add_function(object, set_function);
336  when_failed(rc, exit);
337 
338  rc = amxd_object_add_function(object, list_function);
339  when_failed(rc, exit);
340 
341 exit:
342  amxc_var_clean(&def_val);
343  if(rc != amxd_status_ok) {
344  amxd_function_delete(&set_function);
345  amxd_function_delete(&list_function);
346  }
347  return rc;
348 }
349 
350 
351 int _main(int reason,
352  amxd_dm_t* dm,
353  amxo_parser_t* parser) {
354 
355  switch(reason) {
356  case 0: // START
357  trace_parser = parser;
358  amxd_object_t* root = amxd_dm_get_root(dm);
359  const char* dir = GET_CHAR(&parser->config, "config-storage-dir");
360  const char* path = GET_CHAR(&parser->config, "config-storage-file");
361 
362  if((dir != NULL) && (*dir != 0)) {
363  struct stat stats;
364  int rv = stat(dir, &stats);
365 
366  // Check for dir existence
367  if((rv != 0) || !S_ISDIR(stats.st_mode)) {
368  syslog(LOG_USER | LOG_WARNING, "Trace config folder not found: %s", dir);
369  }
370  }
371 
372  amxo_parser_parse_file(trace_parser, path, root);
373 
374  mod_sahtrace_init(&parser->config);
375  mod_sahtrace_add_zones(&parser->config);
377  break;
378  case 1: // STOP
379  sahTraceClose();
380  free(identity);
381  identity = NULL;
382  break;
383  default:
384  break;
385  }
386 
387  return 0;
388 }
static void mod_sahtrace_open(const char *name, const char *type_name, amxc_var_t *file_var, bool daemon)
Definition: mod_main.c:144
static void mod_sahtrace_init(amxc_var_t *options)
Definition: mod_main.c:159
amxo_parser_t * trace_parser
Definition: mod_main.c:83
int _main(int reason, amxd_dm_t *dm, amxo_parser_t *parser)
Definition: mod_main.c:351
static char * identity
Definition: mod_main.c:82
static uint32_t mod_sahtrace_get_default_trace_zone_level(void)
Definition: mod_main.c:123
static int mod_sahtrace_save_config(void)
Definition: mod_main.c:231
static void mod_sahtrace_add_zones(amxc_var_t *options)
Definition: mod_main.c:191
amxd_status_t set_trace_zone(__attribute__((unused)) amxd_object_t *object, __attribute__((unused)) amxd_function_t *func, amxc_var_t *args, __attribute__((unused)) amxc_var_t *ret)
Definition: mod_main.c:250
static sah_trace_type mod_sahtrace_type_to_id(const char *type, bool daemon)
Definition: mod_main.c:89
static amxc_var_t * mod_sahtrace_get(amxc_var_t *opts, amxc_var_t *sahtrace_opts, const char *opt_name, const char *alt_name)
Definition: mod_main.c:128
#define UNUSED
Definition: mod_main.c:80
amxd_status_t list_trace_zone(__attribute__((unused)) amxd_object_t *object, __attribute__((unused)) amxd_function_t *func, __attribute__((unused)) amxc_var_t *args, amxc_var_t *ret)
Definition: mod_main.c:295
int mod_sahtrace_add_sahtrace_functions(amxd_dm_t *dm)
Definition: mod_main.c:308
static uint32_t mod_sahtrace_get_default_log_level(void)
Definition: mod_main.c:118
config
Definition: mod_sahtrace.odl:5
global config storage dir
Definition: mod_sahtrace.odl:7