2 This file is part of the NoBug debugging library.
5 2007, 2008, 2010, 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, "%zu", 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
))
209 case NOBUG_TARGET_RINGBUFFER
:
210 while (*env
== '(' && given
>= 0)
213 if ((s
= nobug_env_parse_string_option (&env
, "file", name
)))
220 if ((s
= nobug_env_parse_size_option (&env
, "size", &size
)))
227 if ((s
= nobug_env_parse_size_option (&env
, "guard", &guard
)))
233 /* (append) (temp) (keep) */
234 if ((s
= nobug_env_parse_flag_option (&env
, "append",
235 &flags
, NOBUG_RINGBUFFER_APPEND
)))
240 if ((s
= nobug_env_parse_flag_option (&env
, "temp",
241 &flags
, NOBUG_RINGBUFFER_TEMP
)))
246 if ((s
= nobug_env_parse_flag_option (&env
, "keep",
247 &flags
, NOBUG_RINGBUFFER_KEEP
)))
252 if (nobug_env_parse_drop_option (&env
))
259 /* create new ringbuffer for flag */
260 if (flag
->ringbuffer_target
!= &nobug_default_ringbuffer
)
261 nobug_ringbuffer_delete (flag
->ringbuffer_target
);
262 flag
->ringbuffer_target
= nobug_ringbuffer_new (size
, guard
, name
, flags
);
265 case NOBUG_TARGET_CONSOLE
:
266 while (*env
== '(' && given
>= 0)
269 if ((s
= nobug_env_parse_int_option (&env
, "fd", &fd
)))
274 if (nobug_env_parse_drop_option (&env
))
281 // open fd for console
282 if (!write (fd
, NULL
, 0) && flag
->console_target
== stderr
)
283 flag
->console_target
= fdopen (fd
, "w");
286 case NOBUG_TARGET_FILE
:
287 while (*env
== '(' && given
>= 0)
290 if ((s
= nobug_env_parse_string_option (&env
, "name", name
)))
297 if ((s
= nobug_env_parse_flag_option (&env
, "append",
298 &flags
, NOBUG_RINGBUFFER_APPEND
)))
303 if (nobug_env_parse_drop_option (&env
))
310 FILE* new = fopen (name
, flags
?"a":"w");
313 if (flag
->file_target
)
314 fclose (flag
->file_target
);
315 flag
->file_target
= new;
319 case NOBUG_TARGET_SYSLOG
:
320 while (*env
== '(' && given
>= 0)
322 /* (facility=name) unimplemented */
323 //given |= nobug_env_parse_string_option (&env, "facility", .. );
326 if ((s
= nobug_env_parse_string_option (&env
, "ident", name
)))
333 if ((s
= nobug_env_parse_flag_option (&env
, "cons",
339 if ((s
= nobug_env_parse_flag_option (&env
, "pid",
346 if ((s
= nobug_env_parse_flag_option (&env
, "perror",
347 &flags
, LOG_PERROR
)))
353 if (nobug_env_parse_drop_option (&env
))
361 openlog (*name
?strdup (name
): NULL
, flags
, LOG_USER
);
364 case NOBUG_TARGET_APPLICATION
:
368 ret
= flag
->limits
[target
] = nobug_limits
[limit
].value
;
374 /* flag:LIMIT with no @target */
375 ret
= flag
->limits
[default_target
] = nobug_limits
[limit
].value
;
381 /* flag with no :LIMIT */
382 ret
= flag
->limits
[default_target
] = default_limit
;
385 env
= strchr(env
, ',');
395 nobug_env_init_flag (struct nobug_flag
* flag
, int default_target
, int default_limit
, const struct nobug_context context
)
400 if (flag
->initialized
)
402 flag
->initialized
= 1;
404 /* set some defaults */
405 flag
->ringbuffer_target
= &nobug_default_ringbuffer
;
406 flag
->console_target
= stderr
;
407 flag
->file_target
= nobug_default_file
;
411 nobug_env_init_flag (flag
->parent
, default_target
, default_limit
, context
);
413 for (i
= NOBUG_TARGET_CONSOLE
; i
<= NOBUG_TARGET_APPLICATION
; ++i
)
415 flag
->limits
[i
] = flag
->parent
->limits
[i
];
417 flag
->ringbuffer_target
= flag
->parent
->ringbuffer_target
;
418 flag
->console_target
= flag
->parent
->console_target
;
419 flag
->file_target
= flag
->parent
->file_target
;
422 /* parse $NOBUG_LOG */
423 int ret
= nobug_env_parse_flag (getenv("NOBUG_LOG"), flag
, default_target
, default_limit
, context
);
425 /* ensure that the ringbuffer is the most verbose */
428 for (max
= i
= NOBUG_TARGET_CONSOLE
; i
<= NOBUG_TARGET_APPLICATION
; ++i
)
430 max
= max
> flag
->limits
[i
] ? max
: flag
->limits
[i
];
433 flag
->limits
[NOBUG_TARGET_RINGBUFFER
] = max
> flag
->limits
[NOBUG_TARGET_RINGBUFFER
]
434 ? max
: flag
->limits
[NOBUG_TARGET_RINGBUFFER
];