2 This file is part of the NoBug debugging library.
4 Copyright (C) 2007, 2008, Christian Thaeter <chth@gmx.net>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, contact Christian Thaeter <ct@pipapo.org>.
19 #define NOBUG_LIBNOBUG_C
31 logdecl_list --> logdecl, any( ',' logdecl_list)
32 logdecl --> flag, opt(limitdecl, any(targetdecl))
33 flag --> "identifier of a flag"
34 limitdecl --> ':', "LIMITNAME"
35 targetdecl --> '@', "targetname", opt(targetopts)
36 targetopts --> '(', "options for target", ')', opt(targetopts)
39 NOBUG_LOG='flag,other' # set the limit of the 'default' target a default limit
40 NOBUG_LOG='flag:DEBUG' # set the limit of the 'default' target to DEBUG
41 NOBUG_LOG='flag:DEBUG@console@syslog' # set console and syslog limits for flag to DEBUG
42 NOBUG_LOG='flag:DEBUG,other:TRACE@ringbuffer'
45 (options) on targets are not yet implemented
55 { ":EMERG", LOG_EMERG
},
56 { ":ALERT", LOG_ALERT
},
57 { ":CRIT", LOG_CRIT
},
59 { ":ERROR", LOG_ERR
},
60 { ":WARNING", LOG_WARNING
},
61 { ":WARN", LOG_WARNING
},
62 { ":NOTICE", LOG_NOTICE
},
63 { ":INFO", LOG_INFO
},
64 { ":DEBUG", LOG_DEBUG
},
65 { ":TRACE", LOG_DEBUG
},
68 const char* nobug_targets
[] =
69 {"@ringbuffer", "@console", "@file", "@syslog", "@application"};
73 nobug_env_parse_string_option (const char** env
, const char* key
, char* value
)
75 char* end
= strchr (*env
, ')');
79 if (!strncasecmp (key
, *env
+1, strlen (key
)))
81 char* delim
= strchr (*env
, '=');
84 if (delim
> end
|| end
-delim
> 256)
86 strncat (value
, delim
+1, end
-delim
-1);
95 nobug_env_parse_size_option (const char** env
, const char* key
, size_t* value
)
97 char* end
= strchr (*env
, ')');
101 if (!strncasecmp (key
, *env
+1, strlen (key
)))
103 char* delim
= strchr (*env
, '=');
104 if (!delim
|| sscanf (delim
+1, "%zi", value
) != 1)
113 nobug_env_parse_flag_option (const char** env
, const char* key
, int* flag
, int mask
)
116 char* end
= strchr (*env
, ')');
120 if (!strncasecmp (key
, *env
+1, strlen (key
)))
122 //char* delim = strchr (*env, '='); TODO =yes =no =true =false =1 =0
123 /*|| !delim || delim > end*/
132 nobug_env_parse_int_option (const char** env
, const char* key
, int* value
)
134 char* end
= strchr (*env
, ')');
135 char* delim
= strchr (*env
, '=');
136 if (!end
|| !delim
|| delim
> end
)
139 if (!strncasecmp (key
, *env
+1, strlen (key
)))
141 if (sscanf (delim
+1, "%i", value
) != 1)
150 nobug_env_parse_drop_option (const char** env
)
152 char* end
= strchr (*env
, ')');
160 nobug_env_parse_flag (const char* env
, struct nobug_flag
* flag
, int default_target
, int default_limit
)
163 if (!env
|| !flag
->name
)
165 size_t flaglen
= strlen (flag
->name
);
167 if (flag
!= &nobug_flag_nobug
)
168 nobug_log (&nobug_flag_nobug
, LOG_NOTICE
, "%.10llu: NOBUG: INIT_FLAG: %s", ++nobug_counter
, flag
->name
);
172 if (!strncmp(env
, flag
->name
, flaglen
))
174 /* flagname matches */
178 for (limit
= 0; limit
<11; ++limit
)
180 size_t limitlen
= strlen (nobug_limits
[limit
].name
);
181 if (!strncmp(env
, nobug_limits
[limit
].name
, limitlen
))
189 for (target
= 0; target
<5; ++target
)
191 size_t targetlen
= strlen (nobug_targets
[target
]);
192 if (!strncmp(env
, nobug_targets
[target
], targetlen
))
207 case NOBUG_TARGET_RINGBUFFER
:
208 while (*env
== '(' && given
>= 0)
211 if ((s
= nobug_env_parse_string_option (&env
, "file", name
)))
218 if ((s
= nobug_env_parse_size_option (&env
, "size", &size
)))
224 /* (append) (temp) (keep) */
225 if ((s
= nobug_env_parse_flag_option (&env
, "append",
226 &flags
, NOBUG_RINGBUFFER_APPEND
)))
231 if ((s
= nobug_env_parse_flag_option (&env
, "temp",
232 &flags
, NOBUG_RINGBUFFER_TEMP
)))
237 if ((s
= nobug_env_parse_flag_option (&env
, "keep",
238 &flags
, NOBUG_RINGBUFFER_KEEP
)))
243 if (nobug_env_parse_drop_option (&env
))
250 /* create new ringbuffer for flag */
251 if (flag
->ringbuffer_target
!= &nobug_default_ringbuffer
)
252 nobug_ringbuffer_delete (flag
->ringbuffer_target
);
253 flag
->ringbuffer_target
= nobug_ringbuffer_new (size
, name
, flags
);
256 case NOBUG_TARGET_CONSOLE
:
257 while (*env
== '(' && given
>= 0)
260 if ((s
= nobug_env_parse_int_option (&env
, "fd", &fd
)))
265 if (nobug_env_parse_drop_option (&env
))
272 // open fd for console
273 if (!write (fd
, NULL
, 0) && flag
->console_target
== stderr
)
274 flag
->console_target
= fdopen (fd
, "w");
277 case NOBUG_TARGET_FILE
:
278 while (*env
== '(' && given
>= 0)
281 if ((s
= nobug_env_parse_string_option (&env
, "name", name
)))
288 if ((s
= nobug_env_parse_flag_option (&env
, "append",
289 &flags
, NOBUG_RINGBUFFER_APPEND
)))
294 if (nobug_env_parse_drop_option (&env
))
301 FILE* new = fopen (name
, flags
?"a":"w");
304 if (flag
->file_target
)
305 fclose (flag
->file_target
);
306 flag
->file_target
= new;
310 case NOBUG_TARGET_SYSLOG
:
311 while (*env
== '(' && given
>= 0)
313 /* (facility=name) unimplemented */
314 //given |= nobug_env_parse_string_option (&env, "facility", .. );
317 if ((s
= nobug_env_parse_string_option (&env
, "ident", name
)))
324 if ((s
= nobug_env_parse_flag_option (&env
, "cons",
330 if ((s
= nobug_env_parse_flag_option (&env
, "pid",
336 if ((s
= nobug_env_parse_flag_option (&env
, "perror",
337 &flags
, LOG_PERROR
)))
342 if (nobug_env_parse_drop_option (&env
))
350 openlog (*name
?strdup (name
): NULL
, flags
, LOG_USER
);
353 case NOBUG_TARGET_APPLICATION
:
357 ret
= flag
->limits
[target
] = nobug_limits
[limit
].value
;
363 /* flag:LIMIT with no @target */
364 ret
= flag
->limits
[default_target
] = nobug_limits
[limit
].value
;
370 /* flag with no :LIMIT */
371 ret
= flag
->limits
[default_target
] = default_limit
;
374 env
= strchr(env
, ',');
384 nobug_env_init_flag (struct nobug_flag
* flag
, int default_target
, int default_limit
)
389 if (flag
->initialized
)
391 flag
->initialized
= 1;
393 /* set some defaults */
394 flag
->ringbuffer_target
= &nobug_default_ringbuffer
;
395 flag
->console_target
= stderr
;
396 flag
->file_target
= nobug_default_file
;
400 nobug_env_init_flag (flag
->parent
, default_target
, default_limit
);
402 for (i
= NOBUG_TARGET_CONSOLE
; i
<= NOBUG_TARGET_APPLICATION
; ++i
)
404 flag
->limits
[i
] = flag
->parent
->limits
[i
];
406 flag
->ringbuffer_target
= flag
->parent
->ringbuffer_target
;
407 flag
->console_target
= flag
->parent
->console_target
;
408 flag
->file_target
= flag
->parent
->file_target
;
411 /* parse $NOBUG_LOG */
412 int ret
= nobug_env_parse_flag (getenv("NOBUG_LOG"), flag
, default_target
, default_limit
);
414 /* ensure that the ringbuffer is the most verbose */
417 for (max
= i
= NOBUG_TARGET_CONSOLE
; i
<= NOBUG_TARGET_APPLICATION
; ++i
)
419 max
= max
> flag
->limits
[i
] ? max
: flag
->limits
[i
];
422 flag
->limits
[NOBUG_TARGET_RINGBUFFER
] = max
> flag
->limits
[NOBUG_TARGET_RINGBUFFER
]
423 ? max
: flag
->limits
[NOBUG_TARGET_RINGBUFFER
];