@@ -66,6 +66,23 @@ static bool parse_hex64(const char *s, uint64_t *out) {
6666 return end && *end == ' \0 ' ;
6767}
6868
69+ // / Parse a log level name string to BmSbcLogLevel. Returns -1 on failure.
70+ static int parse_log_level (const char *s) {
71+ if (strcmp (s, " trace" ) == 0 )
72+ return BM_LOG_TRACE ;
73+ if (strcmp (s, " debug" ) == 0 )
74+ return BM_LOG_DEBUG ;
75+ if (strcmp (s, " info" ) == 0 )
76+ return BM_LOG_INFO ;
77+ if (strcmp (s, " warn" ) == 0 )
78+ return BM_LOG_WARN ;
79+ if (strcmp (s, " error" ) == 0 )
80+ return BM_LOG_ERROR ;
81+ if (strcmp (s, " fatal" ) == 0 )
82+ return BM_LOG_FATAL ;
83+ return -1 ;
84+ }
85+
6986// / Load settings from a TOML init file. Values are written into the
7087// / provided output parameters only when present in the file — callers
7188// / should pre-fill defaults before calling.
@@ -76,7 +93,9 @@ static bool parse_hex64(const char *s, uint64_t *out) {
7693static int load_init_file (const char *path, VirtualPortCfg *vpc,
7794 bool *node_id_set, char *cfg_dir, size_t cfg_dir_sz,
7895 char *uart_path, size_t uart_path_sz, int *baud_rate,
79- char *pcap_path, size_t pcap_path_sz) {
96+ char *pcap_path, size_t pcap_path_sz,
97+ char *log_dir, size_t log_dir_sz,
98+ int *log_level, bool *log_stdout) {
8099 toml_result_t res = toml_parse_file_ex (path);
81100 if (!res.ok ) {
82101 fprintf (stderr, " bm_sbc: TOML parse error in %s: %s\n " , path, res.errmsg );
@@ -149,6 +168,31 @@ static int load_init_file(const char *path, VirtualPortCfg *vpc,
149168 pcap_path[pcap_path_sz - 1 ] = ' \0 ' ;
150169 }
151170
171+ // log-dir (string)
172+ d = toml_get (root, " log-dir" );
173+ if (d.type == TOML_STRING ) {
174+ strncpy (log_dir, d.u .s , log_dir_sz - 1 );
175+ log_dir[log_dir_sz - 1 ] = ' \0 ' ;
176+ }
177+
178+ // log-level (string)
179+ d = toml_get (root, " log-level" );
180+ if (d.type == TOML_STRING ) {
181+ int lvl = parse_log_level (d.u .s );
182+ if (lvl < 0 ) {
183+ fprintf (stderr, " bm_sbc: invalid log-level in %s: %s\n " , path, d.u .s );
184+ toml_free (res);
185+ return 1 ;
186+ }
187+ *log_level = lvl;
188+ }
189+
190+ // log-stdout (bool)
191+ d = toml_get (root, " log-stdout" );
192+ if (d.type == TOML_BOOLEAN ) {
193+ *log_stdout = d.u .boolean ;
194+ }
195+
152196 toml_free (res);
153197 return 0 ;
154198}
@@ -181,23 +225,6 @@ static const char *read_device_name() {
181225 return buf;
182226}
183227
184- // / Parse a log level name string to BmSbcLogLevel. Returns -1 on failure.
185- static int parse_log_level (const char *s) {
186- if (strcmp (s, " trace" ) == 0 )
187- return BM_LOG_TRACE ;
188- if (strcmp (s, " debug" ) == 0 )
189- return BM_LOG_DEBUG ;
190- if (strcmp (s, " info" ) == 0 )
191- return BM_LOG_INFO ;
192- if (strcmp (s, " warn" ) == 0 )
193- return BM_LOG_WARN ;
194- if (strcmp (s, " error" ) == 0 )
195- return BM_LOG_ERROR ;
196- if (strcmp (s, " fatal" ) == 0 )
197- return BM_LOG_FATAL ;
198- return -1 ;
199- }
200-
201228int bm_sbc_runtime_init (int argc, char **argv, const char *app_name) {
202229 bm_sbc_app_name_runtime = app_name;
203230 // Make stdout line-buffered so every bm_debug/printf call ending in '\n'
@@ -217,9 +244,19 @@ int bm_sbc_runtime_init(int argc, char **argv, const char *app_name) {
217244 int baud_rate = 115200 ;
218245 char init_path[512 ] = {0 };
219246 char log_dir[256 ] = {0 };
220- int log_level = -1 ; // -1 = not set via CLI
247+ int log_level = -1 ; // -1 = not set
221248 bool log_stdout_flag = false ;
222249
250+ // Seed log vars from environment variables; CLI flags and TOML will override.
251+ {
252+ const char *env = getenv (" BM_SBC_LOG_DIR" );
253+ if (env) strncpy (log_dir, env, sizeof (log_dir) - 1 );
254+ env = getenv (" BM_SBC_LOG_LEVEL" );
255+ if (env) log_level = parse_log_level (env); // -1 if unrecognised
256+ env = getenv (" BM_SBC_LOG_STDOUT" );
257+ if (env && strcmp (env, " 1" ) == 0 ) log_stdout_flag = true ;
258+ }
259+
223260 static const struct option long_opts[] = {
224261 {" init" , required_argument, NULL , ' i' },
225262 {" node-id" , required_argument, NULL , ' n' },
@@ -334,6 +371,10 @@ int bm_sbc_runtime_init(int argc, char **argv, const char *app_name) {
334371 int cli_baud_rate = baud_rate;
335372 char cli_pcap_path[256 ];
336373 strncpy (cli_pcap_path, pcap_path, sizeof (cli_pcap_path));
374+ char cli_log_dir[256 ];
375+ strncpy (cli_log_dir, log_dir, sizeof (cli_log_dir));
376+ int cli_log_level = log_level;
377+ bool cli_log_stdout_flag = log_stdout_flag;
337378
338379 // Reset to defaults before loading from file.
339380 memset (&vpc, 0 , sizeof (vpc));
@@ -344,10 +385,15 @@ int bm_sbc_runtime_init(int argc, char **argv, const char *app_name) {
344385 memset (uart_path, 0 , sizeof (uart_path));
345386 memset (pcap_path, 0 , sizeof (pcap_path));
346387 baud_rate = 115200 ;
388+ memset (log_dir, 0 , sizeof (log_dir));
389+ log_level = -1 ;
390+ log_stdout_flag = false ;
347391
348392 int rc = load_init_file (init_path, &vpc, &node_id_set, cfg_dir,
349393 sizeof (cfg_dir), uart_path, sizeof (uart_path),
350- &baud_rate, pcap_path, sizeof (pcap_path));
394+ &baud_rate, pcap_path, sizeof (pcap_path),
395+ log_dir, sizeof (log_dir),
396+ &log_level, &log_stdout_flag);
351397 if (rc != 0 ) {
352398 return rc;
353399 }
@@ -376,6 +422,15 @@ int bm_sbc_runtime_init(int argc, char **argv, const char *app_name) {
376422 if (cli_pcap_path[0 ] != ' \0 ' ) {
377423 strncpy (pcap_path, cli_pcap_path, sizeof (pcap_path) - 1 );
378424 }
425+ if (cli_log_dir[0 ] != ' \0 ' ) {
426+ strncpy (log_dir, cli_log_dir, sizeof (log_dir) - 1 );
427+ }
428+ if (cli_log_level >= 0 ) {
429+ log_level = cli_log_level;
430+ }
431+ if (cli_log_stdout_flag) {
432+ log_stdout_flag = true ;
433+ }
379434 }
380435
381436 if (!node_id_set) {
@@ -391,23 +446,6 @@ int bm_sbc_runtime_init(int argc, char **argv, const char *app_name) {
391446 }
392447
393448 // --- Logging init -------------------------------------------------------
394- // Environment variables override CLI flags.
395- const char *env_log_dir = getenv (" BM_SBC_LOG_DIR" );
396- if (env_log_dir) {
397- strncpy (log_dir, env_log_dir, sizeof (log_dir) - 1 );
398- }
399- const char *env_log_level = getenv (" BM_SBC_LOG_LEVEL" );
400- if (env_log_level) {
401- int lvl = parse_log_level (env_log_level);
402- if (lvl >= 0 ) {
403- log_level = lvl;
404- }
405- }
406- const char *env_log_stdout = getenv (" BM_SBC_LOG_STDOUT" );
407- if (env_log_stdout && strcmp (env_log_stdout, " 1" ) == 0 ) {
408- log_stdout_flag = true ;
409- }
410-
411449 // Default: also log to stdout when it is a TTY (interactive development).
412450 bool also_stdout = log_stdout_flag || isatty (STDOUT_FILENO );
413451
0 commit comments