2 This file is part of the NoBug debugging library.
5 2007, 2008, Christian Thaeter <ct@pipapo.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, contact Christian Thaeter <ct@pipapo.org>.
20 #define NOBUG_LIBNOBUG_C
32 logdecl_list --> logdecl, any( ',' logdecl_list)
33 logdecl --> flag, opt(limitdecl, any(targetdecl))
34 flag --> "identifier of a flag"
35 limitdecl --> ':', "LIMITNAME"
36 targetdecl --> '@', "targetname", opt(targetopts)
37 targetopts --> '(', "options for target", ')', opt(targetopts)
40 NOBUG_LOG='flag,other' # set the limit of the 'default' target a default limit
41 NOBUG_LOG='flag:DEBUG' # set the limit of the 'default' target to DEBUG
42 NOBUG_LOG='flag:DEBUG@console@syslog' # set console and syslog limits for flag to DEBUG
43 NOBUG_LOG='flag:DEBUG,other:TRACE@ringbuffer'
46 (options) on targets are not yet implemented
56 { ":EMERG", LOG_EMERG
},
57 { ":ALERT", LOG_ALERT
},
58 { ":CRIT", LOG_CRIT
},
60 { ":ERROR", LOG_ERR
},
61 { ":WARNING", LOG_WARNING
},
62 { ":WARN", LOG_WARNING
},
63 { ":NOTICE", LOG_NOTICE
},
64 { ":INFO", LOG_INFO
},
65 { ":DEBUG", LOG_DEBUG
},
66 { ":TRACE", LOG_DEBUG
},
69 const char* nobug_targets
[] =
70 {"@ringbuffer", "@console", "@file", "@syslog", "@application"};
74 nobug_env_parse_string_option (const char** env
, const char* key
, char* value
)
76 char* end
= strchr (*env
, ')');
80 if (!strncasecmp (key
, *env
+1, strlen (key
)))
82 char* delim
= strchr (*env
, '=');
85 if (delim
> end
|| end
-delim
> 256)
87 strncat (value
, delim
+1, end
-delim
-1);
96 nobug_env_parse_size_option (const char** env
, const char* key
, size_t* value
)
98 char* end
= strchr (*env
, ')');
102 if (!strncasecmp (key
, *env
+1, strlen (key
)))
104 char* delim
= strchr (*env
, '=');
105 if (!delim
|| sscanf (delim
+1, "%zi", value
) != 1)
114 nobug_env_parse_flag_option (const char** env
, const char* key
, int* flag
, int mask
)
117 char* end
= strchr (*env
, ')');
121 if (!strncasecmp (key
, *env
+1, strlen (key
)))
123 //char* delim = strchr (*env, '='); TODO =yes =no =true =false =1 =0
124 /*|| !delim || delim > end*/
133 nobug_env_parse_int_option (const char** env
, const char* key
, int* value
)
135 char* end
= strchr (*env
, ')');
136 char* delim
= strchr (*env
, '=');
137 if (!end
|| !delim
|| delim
> end
)
140 if (!strncasecmp (key
, *env
+1, strlen (key
)))
142 if (sscanf (delim
+1, "%i", value
) != 1)
151 nobug_env_parse_drop_option (const char** env
)
153 char* end
= strchr (*env
, ')');
161 nobug_env_parse_flag (const char* env
, struct nobug_flag
* flag
, int default_target
, int default_limit
, const struct nobug_context context
)
164 if (!env
|| !flag
->name
)
166 size_t flaglen
= strlen (flag
->name
);
168 if (flag
!= &nobug_flag_nobug
)
169 nobug_log (&nobug_flag_nobug
, LOG_NOTICE
, "NOBUG", context
, "INIT_FLAG: %s", flag
->name
);
173 if (!strncmp(env
, flag
->name
, flaglen
))
175 /* flagname matches */
179 for (limit
= 0; limit
<11; ++limit
)
181 size_t limitlen
= strlen (nobug_limits
[limit
].name
);
182 if (!strncmp(env
, nobug_limits
[limit
].name
, limitlen
))
190 for (target
= 0; target
<5; ++target
)
192 size_t targetlen
= strlen (nobug_targets
[target
]);
193 if (!strncmp(env
, nobug_targets
[target
], targetlen
))
208 case NOBUG_TARGET_RINGBUFFER
:
209 while (*env
== '(' && given
>= 0)
212 if ((s
= nobug_env_parse_string_option (&env
, "file", name
)))
219 if ((s
= nobug_env_parse_size_option (&env
, "size", &size
)))
225 /* (append) (temp) (keep) */
226 if ((s
= nobug_env_parse_flag_option (&env
, "append",
227 &flags
, NOBUG_RINGBUFFER_APPEND
)))
232 if ((s
= nobug_env_parse_flag_option (&env
, "temp",
233 &flags
, NOBUG_RINGBUFFER_TEMP
)))
238 if ((s
= nobug_env_parse_flag_option (&env
, "keep",
239 &flags
, NOBUG_RINGBUFFER_KEEP
)))
244 if (nobug_env_parse_drop_option (&env
))
251 /* create new ringbuffer for flag */
252 if (flag
->ringbuffer_target
!= &nobug_default_ringbuffer
)
253 nobug_ringbuffer_delete (flag
->ringbuffer_target
);
254 flag
->ringbuffer_target
= nobug_ringbuffer_new (size
, name
, flags
);
257 case NOBUG_TARGET_CONSOLE
:
258 while (*env
== '(' && given
>= 0)
261 if ((s
= nobug_env_parse_int_option (&env
, "fd", &fd
)))
266 if (nobug_env_parse_drop_option (&env
))
273 // open fd for console
274 if (!write (fd
, NULL
, 0) && flag
->console_target
== stderr
)
275 flag
->console_target
= fdopen (fd
, "w");
278 case NOBUG_TARGET_FILE
:
279 while (*env
== '(' && given
>= 0)
282 if ((s
= nobug_env_parse_string_option (&env
, "name", name
)))
289 if ((s
= nobug_env_parse_flag_option (&env
, "append",
290 &flags
, NOBUG_RINGBUFFER_APPEND
)))
295 if (nobug_env_parse_drop_option (&env
))
302 FILE* new = fopen (name
, flags
?"a":"w");
305 if (flag
->file_target
)
306 fclose (flag
->file_target
);
307 flag
->file_target
= new;
311 case NOBUG_TARGET_SYSLOG
:
312 while (*env
== '(' && given
>= 0)
314 /* (facility=name) unimplemented */
315 //given |= nobug_env_parse_string_option (&env, "facility", .. );
318 if ((s
= nobug_env_parse_string_option (&env
, "ident", name
)))
325 if ((s
= nobug_env_parse_flag_option (&env
, "cons",
331 if ((s
= nobug_env_parse_flag_option (&env
, "pid",
337 if ((s
= nobug_env_parse_flag_option (&env
, "perror",
338 &flags
, LOG_PERROR
)))
343 if (nobug_env_parse_drop_option (&env
))
351 openlog (*name
?strdup (name
): NULL
, flags
, LOG_USER
);
354 case NOBUG_TARGET_APPLICATION
:
358 ret
= flag
->limits
[target
] = nobug_limits
[limit
].value
;
364 /* flag:LIMIT with no @target */
365 ret
= flag
->limits
[default_target
] = nobug_limits
[limit
].value
;
371 /* flag with no :LIMIT */
372 ret
= flag
->limits
[default_target
] = default_limit
;
375 env
= strchr(env
, ',');
385 nobug_env_init_flag (struct nobug_flag
* flag
, int default_target
, int default_limit
, const struct nobug_context context
)
390 if (flag
->initialized
)
392 flag
->initialized
= 1;
394 /* set some defaults */
395 flag
->ringbuffer_target
= &nobug_default_ringbuffer
;
396 flag
->console_target
= stderr
;
397 flag
->file_target
= nobug_default_file
;
401 nobug_env_init_flag (flag
->parent
, default_target
, default_limit
, context
);
403 for (i
= NOBUG_TARGET_CONSOLE
; i
<= NOBUG_TARGET_APPLICATION
; ++i
)
405 flag
->limits
[i
] = flag
->parent
->limits
[i
];
407 flag
->ringbuffer_target
= flag
->parent
->ringbuffer_target
;
408 flag
->console_target
= flag
->parent
->console_target
;
409 flag
->file_target
= flag
->parent
->file_target
;
412 /* parse $NOBUG_LOG */
413 int ret
= nobug_env_parse_flag (getenv("NOBUG_LOG"), flag
, default_target
, default_limit
, context
);
415 /* ensure that the ringbuffer is the most verbose */
418 for (max
= i
= NOBUG_TARGET_CONSOLE
; i
<= NOBUG_TARGET_APPLICATION
; ++i
)
420 max
= max
> flag
->limits
[i
] ? max
: flag
->limits
[i
];
423 flag
->limits
[NOBUG_TARGET_RINGBUFFER
] = max
> flag
->limits
[NOBUG_TARGET_RINGBUFFER
]
424 ? max
: flag
->limits
[NOBUG_TARGET_RINGBUFFER
];