@@ -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,16 @@ static void sigterm(int signo)
171
180
running = 0 ;
172
181
}
173
182
174
- static int idx2dindex (int ifidx , int socket )
183
+ static void sighup (int signo )
175
184
{
185
+ if (signo == SIGHUP && running ) {
186
+ flag_reopen_file = 1 ;
187
+ sighup_count ++ ;
188
+ }
189
+ }
176
190
191
+ static int idx2dindex (int ifidx , int socket )
192
+ {
177
193
int i ;
178
194
struct ifreq ifr ;
179
195
@@ -221,6 +237,89 @@ static int idx2dindex(int ifidx, int socket)
221
237
return i ;
222
238
}
223
239
240
+ static int sprint_auto_filename_format (char * buffer )
241
+ {
242
+ time_t currtime ;
243
+ struct tm now ;
244
+
245
+ if (time (& currtime ) == (time_t )- 1 ) {
246
+ perror ("time" );
247
+ return 1 ;
248
+ }
249
+
250
+ localtime_r (& currtime , & now );
251
+
252
+ sprintf (buffer , "candump-%04d-%02d-%02d_%02d%02d%02d.log" ,
253
+ now .tm_year + 1900 ,
254
+ now .tm_mon + 1 ,
255
+ now .tm_mday ,
256
+ now .tm_hour ,
257
+ now .tm_min ,
258
+ now .tm_sec );
259
+
260
+ fprintf (stderr , "Enabling Logfile '%s'\n" , buffer );
261
+
262
+ return 0 ;
263
+ }
264
+
265
+ /* opens file using global var logfile */
266
+ static int open_log_file (const char * file_name )
267
+ {
268
+ if (silent != SILENT_ON )
269
+ fprintf (stderr , "Warning: Console output active while logging!\n" );
270
+
271
+ logfile = fopen (file_name , "w" );
272
+
273
+ if (!logfile ) {
274
+ perror ("logfile" );
275
+ return 1 ;
276
+ }
277
+
278
+ return 0 ;
279
+ }
280
+
281
+ static int reopen_file (FILE * file_handle )
282
+ {
283
+ const char * fopen_opts = (sighup_count > 0 && !is_auto_log_name ) ? "a" : "w" ;
284
+
285
+ if (!file_handle )
286
+ return 1 ;
287
+
288
+ if (is_auto_log_name == 1 ) {
289
+ const int errcode = sprint_auto_filename_format (log_filename );
290
+
291
+ if (errcode != 0 ) {
292
+ return 1 ;
293
+ }
294
+ }
295
+
296
+ /* close existing filehandle, and open new one if necessary */
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,32 @@ 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_empty_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
+ sighup_action .sa_mask = sig_block_mask ;
367
+ sigemptyset (& sig_empty_mask );
368
+ sigterm_action .sa_mask = sig_empty_mask ;
369
+
370
+ sigaction (SIGHUP , & sigterm_action , NULL );
371
+ sigaction (SIGINT , & sigterm_action , NULL );
265
372
266
373
last_tv .tv_sec = 0 ;
267
374
last_tv .tv_usec = 0 ;
268
375
269
- while ((opt = getopt (argc , argv , "t:HciaSs:lDdxLn:r:he8T:?" )) != -1 ) {
376
+ int getoptargc = argc ;
377
+
378
+ /* Since interface is a required argument, we don't need to parse opt for final arg
379
+ * This enabled the -l option to take an optional filename */
380
+ if (getoptargc > 0 ) {
381
+ getoptargc = argc - 1 ;
382
+ }
383
+
384
+ while ((opt = getopt (getoptargc , argv , ":t:HciaSs:l:DdxLn:r:he8T:?" )) != -1 ) {
270
385
switch (opt ) {
271
386
case 't' :
272
387
timestamp = optarg [0 ];
@@ -314,9 +429,35 @@ int main(int argc, char **argv)
314
429
}
315
430
break ;
316
431
432
+ case ':' : //handle flags with optional values
433
+
434
+ switch (optopt )
435
+ {
436
+ case 'l' :
437
+ {
438
+ log = 1 ;
439
+
440
+ if (process_logname_arg (optarg ) != 0 ) {
441
+ print_usage (basename (argv [0 ]));
442
+ exit (1 );
443
+ }
444
+ break ;
445
+ }
446
+ default :
447
+ fprintf (stderr , "option -%c is missing a required argument\n" , optopt );
448
+ return EXIT_FAILURE ;
449
+ }
450
+ break ;
317
451
318
452
case 'l' :
319
453
log = 1 ;
454
+
455
+ if (process_logname_arg (optarg ) != 0 ) {
456
+ is_auto_log_name = 0 ;
457
+ print_usage (basename (argv [0 ]));
458
+ exit (1 );
459
+ }
460
+
320
461
break ;
321
462
322
463
case 'D' :
@@ -371,6 +512,10 @@ int main(int argc, char **argv)
371
512
exit (0 );
372
513
}
373
514
515
+ /* Configure SIGHUP handler to reopen file if logging */
516
+ sighup_action .sa_handler = log ? sighup : sigterm ;
517
+ sigaction (SIGHUP , & sighup_action , NULL );
518
+
374
519
if (logfrmt && view ) {
375
520
fprintf (stderr , "Log file format selected: Please disable ASCII/BINARY/SWAP/RAWDLC options!\n" );
376
521
exit (0 );
@@ -592,35 +737,10 @@ int main(int argc, char **argv)
592
737
}
593
738
594
739
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 );
740
+ const int result = open_log_file (log_filename );
605
741
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" );
742
+ if (result != 0 )
622
743
return 1 ;
623
- }
624
744
}
625
745
626
746
/* these settings are static and can be held out of the hot path */
@@ -631,10 +751,20 @@ int main(int argc, char **argv)
631
751
msg .msg_control = & ctrlmsg ;
632
752
633
753
while (running ) {
634
-
635
754
if ((num_events = epoll_wait (fd_epoll , events_pending , currmax , timeout_ms )) <= 0 ) {
636
755
//perror("epoll_wait");
637
- running = 0 ;
756
+ if (num_events == -1 ) {
757
+ const int serr = errno ;
758
+ if (serr == EINTR ) {
759
+ if (log && flag_reopen_file ) {
760
+ if (reopen_file (logfile ) != 0 ) {
761
+ return -1 ;
762
+ }
763
+ }
764
+ } else {
765
+ running = 0 ;
766
+ }
767
+ }
638
768
continue ;
639
769
}
640
770
@@ -817,6 +947,12 @@ int main(int argc, char **argv)
817
947
out_fflush :
818
948
fflush (stdout );
819
949
}
950
+
951
+ if (log && flag_reopen_file == 1 ) {
952
+ if (reopen_file (logfile ) != 0 ) {
953
+ return -1 ;
954
+ }
955
+ }
820
956
}
821
957
822
958
for (i = 0 ; i < currmax ; i ++ )
0 commit comments