@@ -116,9 +116,18 @@ static const int canfd_on = 1;
116
116
static const char anichar [MAXANI ] = { '|' , '/' , '-' , '\\' };
117
117
static const char extra_m_info [4 ][4 ] = { "- -" , "B -" , "- E" , "B E" };
118
118
119
+ #define MAXLOGNAMESZ 100
120
+ static FILE * logfile = NULL ;
121
+ static char log_filename [MAXLOGNAMESZ ];
122
+
123
+ static unsigned char silent = SILENT_INI ;
124
+
119
125
extern int optind , opterr , optopt ;
120
126
121
127
static volatile int running = 1 ;
128
+ static volatile int flag_reopen_file ;
129
+ static int is_auto_log_name ;
130
+ static volatile unsigned long sighup_count ;
122
131
123
132
static void print_usage (char * prg )
124
133
{
@@ -133,7 +142,7 @@ static void print_usage(char *prg)
133
142
fprintf (stderr , " -a (enable additional ASCII output)\n" );
134
143
fprintf (stderr , " -S (swap byte order in printed CAN data[] - marked with '%c' )\n" , SWAP_DELIMITER );
135
144
fprintf (stderr , " -s <level> (silent mode - %d: off (default) %d: animation %d: silent)\n" , SILENT_OFF , SILENT_ANI , SILENT_ON );
136
- fprintf (stderr , " -l (log CAN-frames into file. Sets '-s %d' by default)\n" , SILENT_ON );
145
+ fprintf (stderr , " -l <name> (log CAN-frames into file. Sets '-s %d' by default)\n" , SILENT_ON );
137
146
fprintf (stderr , " -L (use log file format on stdout)\n" );
138
147
fprintf (stderr , " -n <count> (terminate after reception of <count> CAN frames)\n" );
139
148
fprintf (stderr , " -r <size> (set socket receive buffer to <size>)\n" );
@@ -171,9 +180,17 @@ static void sigterm(int signo)
171
180
running = 0 ;
172
181
}
173
182
174
- static int idx2dindex (int ifidx , int socket )
183
+
184
+ static void sighup (int signo )
175
185
{
186
+ if (signo == SIGHUP && running ) {
187
+ flag_reopen_file = 1 ;
188
+ sighup_count ++ ;
189
+ }
190
+ }
176
191
192
+ static int idx2dindex (int ifidx , int socket )
193
+ {
177
194
int i ;
178
195
struct ifreq ifr ;
179
196
@@ -221,6 +238,88 @@ static int idx2dindex(int ifidx, int socket)
221
238
return i ;
222
239
}
223
240
241
+ static int sprint_auto_filename_format (char * buffer )
242
+ {
243
+ time_t currtime ;
244
+ struct tm now ;
245
+
246
+ if (time (& currtime ) == (time_t )- 1 ) {
247
+ perror ("time" );
248
+ return 1 ;
249
+ }
250
+
251
+ localtime_r (& currtime , & now );
252
+
253
+ sprintf (buffer , "candump-%04d-%02d-%02d_%02d%02d%02d.log" ,
254
+ now .tm_year + 1900 ,
255
+ now .tm_mon + 1 ,
256
+ now .tm_mday ,
257
+ now .tm_hour ,
258
+ now .tm_min ,
259
+ now .tm_sec );
260
+
261
+ fprintf (stderr , "Enabling Logfile '%s'\n" , buffer );
262
+
263
+ return 0 ;
264
+ }
265
+
266
+ /* opens file using global var logfile */
267
+ static int open_log_file (const char * file_name )
268
+ {
269
+ if (silent != SILENT_ON )
270
+ fprintf (stderr , "Warning: Console output active while logging!\n" );
271
+
272
+ logfile = fopen (file_name , "w" );
273
+
274
+ if (!logfile ) {
275
+ perror ("logfile" );
276
+ return 1 ;
277
+ }
278
+
279
+ return 0 ;
280
+ }
281
+
282
+ static int reopen_file (FILE * file_handle )
283
+ {
284
+ const char * fopen_opts = (sighup_count > 0 && !is_auto_log_name ) ? "a" : "w" ;
285
+
286
+ if (!file_handle )
287
+ return 1 ;
288
+
289
+ if (is_auto_log_name == 1 ) {
290
+ const int errcode = sprint_auto_filename_format (log_filename );
291
+
292
+ if (errcode != 0 ) {
293
+ return 1 ;
294
+ }
295
+ }
296
+
297
+ logfile = freopen (log_filename , fopen_opts , file_handle );
298
+
299
+ flag_reopen_file = 0 ;
300
+
301
+ return logfile == 0 ;
302
+ }
303
+
304
+ static int process_logname_arg (const char * arg )
305
+ {
306
+ if (arg != 0 ) {
307
+ const size_t len = strnlen (arg , MAXLOGNAMESZ );
308
+
309
+ if (len > 0 && len < MAXLOGNAMESZ ) {
310
+ strncpy (log_filename , arg , MAXLOGNAMESZ - 1 );
311
+ } else {
312
+ return 1 ;
313
+ }
314
+ is_auto_log_name = 0 ;
315
+ } else {
316
+ is_auto_log_name = 1 ;
317
+ sprint_auto_filename_format (log_filename );
318
+ }
319
+
320
+ return 0 ;
321
+ }
322
+
224
323
int main (int argc , char * * argv )
225
324
{
226
325
int fd_epoll ;
@@ -233,7 +332,7 @@ int main(int argc, char **argv)
233
332
unsigned char down_causes_exit = 1 ;
234
333
unsigned char dropmonitor = 0 ;
235
334
unsigned char extra_msg_info = 0 ;
236
- unsigned char silent = SILENT_INI ;
335
+
237
336
unsigned char silentani = 0 ;
238
337
unsigned char color = 0 ;
239
338
unsigned char view = 0 ;
@@ -257,16 +356,33 @@ int main(int argc, char **argv)
257
356
struct ifreq ifr ;
258
357
struct timeval tv , last_tv ;
259
358
int timeout_ms = -1 ; /* default to no timeout */
260
- FILE * logfile = NULL ;
261
359
262
- signal (SIGTERM , sigterm );
263
- signal (SIGHUP , sigterm );
264
- signal (SIGINT , sigterm );
360
+ sigset_t sig_block_mask ;
361
+ sigset_t sig_mask ;
362
+ struct sigaction sighup_action = { .sa_flags = SA_RESTART };
363
+ struct sigaction sigterm_action = { .sa_flags = SA_RESTART , .sa_handler = sigterm };
364
+
365
+ sigfillset (& sig_block_mask );
366
+ sigemptyset (& sig_mask );
367
+
368
+ sighup_action .sa_mask = sig_block_mask ;
369
+ sigterm_action .sa_mask = sig_mask ;
370
+
371
+ sigaction (SIGHUP , & sigterm_action , NULL );
372
+ sigaction (SIGINT , & sigterm_action , NULL );
265
373
266
374
last_tv .tv_sec = 0 ;
267
375
last_tv .tv_usec = 0 ;
268
376
269
- while ((opt = getopt (argc , argv , "t:HciaSs:lDdxLn:r:he8T:?" )) != -1 ) {
377
+ int getoptargc = argc ;
378
+
379
+ //Since interface is a required argument, we don't need to parse opt for final arg
380
+ //This enabled the -l option to take an optional filename
381
+ if (getoptargc > 0 ) {
382
+ getoptargc = argc - 1 ;
383
+ }
384
+
385
+ while ((opt = getopt (getoptargc , argv , ":t:HciaSs:l:DdxLn:r:he8T:?" )) != -1 ) {
270
386
switch (opt ) {
271
387
case 't' :
272
388
timestamp = optarg [0 ];
@@ -314,9 +430,35 @@ int main(int argc, char **argv)
314
430
}
315
431
break ;
316
432
433
+ case ':' : //handle flags with optional values
434
+
435
+ switch (optopt )
436
+ {
437
+ case 'l' :
438
+ {
439
+ log = 1 ;
440
+
441
+ if (process_logname_arg (optarg ) != 0 ) {
442
+ print_usage (basename (argv [0 ]));
443
+ exit (1 );
444
+ }
445
+ break ;
446
+ }
447
+ default :
448
+ fprintf (stderr , "option -%c is missing a required argument\n" , optopt );
449
+ return EXIT_FAILURE ;
450
+ }
451
+ break ;
317
452
318
453
case 'l' :
319
454
log = 1 ;
455
+
456
+ if (process_logname_arg (optarg ) != 0 ) {
457
+ is_auto_log_name = 0 ;
458
+ print_usage (basename (argv [0 ]));
459
+ exit (1 );
460
+ }
461
+
320
462
break ;
321
463
322
464
case 'D' :
@@ -371,6 +513,10 @@ int main(int argc, char **argv)
371
513
exit (0 );
372
514
}
373
515
516
+ /* Configure SIGHUP handler to reopen file if logging */
517
+ sighup_action .sa_handler = log ? sighup : sigterm ;
518
+ sigaction (SIGHUP , & sighup_action , NULL );
519
+
374
520
if (logfrmt && view ) {
375
521
fprintf (stderr , "Log file format selected: Please disable ASCII/BINARY/SWAP/RAWDLC options!\n" );
376
522
exit (0 );
@@ -592,35 +738,10 @@ int main(int argc, char **argv)
592
738
}
593
739
594
740
if (log ) {
595
- time_t currtime ;
596
- struct tm now ;
597
- char fname [83 ]; /* suggested by -Wformat-overflow= */
598
-
599
- if (time (& currtime ) == (time_t )- 1 ) {
600
- perror ("time" );
601
- return 1 ;
602
- }
603
-
604
- localtime_r (& currtime , & now );
741
+ const int result = open_log_file (log_filename );
605
742
606
- sprintf (fname , "candump-%04d-%02d-%02d_%02d%02d%02d.log" ,
607
- now .tm_year + 1900 ,
608
- now .tm_mon + 1 ,
609
- now .tm_mday ,
610
- now .tm_hour ,
611
- now .tm_min ,
612
- now .tm_sec );
613
-
614
- if (silent != SILENT_ON )
615
- fprintf (stderr , "Warning: Console output active while logging!\n" );
616
-
617
- fprintf (stderr , "Enabling Logfile '%s'\n" , fname );
618
-
619
- logfile = fopen (fname , "w" );
620
- if (!logfile ) {
621
- perror ("logfile" );
743
+ if (result != 0 )
622
744
return 1 ;
623
- }
624
745
}
625
746
626
747
/* these settings are static and can be held out of the hot path */
@@ -631,10 +752,20 @@ int main(int argc, char **argv)
631
752
msg .msg_control = & ctrlmsg ;
632
753
633
754
while (running ) {
634
-
635
755
if ((num_events = epoll_wait (fd_epoll , events_pending , currmax , timeout_ms )) <= 0 ) {
636
756
//perror("epoll_wait");
637
- running = 0 ;
757
+ if (num_events == -1 ) {
758
+ const int serr = errno ;
759
+ if (serr == EINTR ) {
760
+ if (flag_reopen_file == 1 ) {
761
+ if (reopen_file (logfile ) != 0 ) {
762
+ return -1 ;
763
+ }
764
+ }
765
+ } else {
766
+ running = 0 ;
767
+ }
768
+ }
638
769
continue ;
639
770
}
640
771
@@ -817,6 +948,12 @@ int main(int argc, char **argv)
817
948
out_fflush :
818
949
fflush (stdout );
819
950
}
951
+
952
+ if (flag_reopen_file == 1 ) {
953
+ if (reopen_file (logfile ) != 0 ) {
954
+ return -1 ;
955
+ }
956
+ }
820
957
}
821
958
822
959
for (i = 0 ; i < currmax ; i ++ )
0 commit comments