@@ -116,9 +116,18 @@ static const int canfd_on = 1;
116116static const char anichar [MAXANI ] = { '|' , '/' , '-' , '\\' };
117117static const char extra_m_info [4 ][4 ] = { "- -" , "B -" , "- E" , "B E" };
118118
119+ #define MAXLOGNAMESZ 100
120+ static FILE * logfile = NULL ;
121+ static char log_filename [MAXLOGNAMESZ ];
122+
123+ static unsigned char silent = SILENT_INI ;
124+
119125extern int optind , opterr , optopt ;
120126
121127static 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 ;
122131
123132static void print_usage (char * prg )
124133{
@@ -133,7 +142,7 @@ static void print_usage(char *prg)
133142 fprintf (stderr , " -a (enable additional ASCII output)\n" );
134143 fprintf (stderr , " -S (swap byte order in printed CAN data[] - marked with '%c' )\n" , SWAP_DELIMITER );
135144 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 );
137146 fprintf (stderr , " -L (use log file format on stdout)\n" );
138147 fprintf (stderr , " -n <count> (terminate after reception of <count> CAN frames)\n" );
139148 fprintf (stderr , " -r <size> (set socket receive buffer to <size>)\n" );
@@ -171,9 +180,16 @@ static void sigterm(int signo)
171180 running = 0 ;
172181}
173182
174- static int idx2dindex (int ifidx , int socket )
183+ static void sighup (int signo )
175184{
185+ if (signo == SIGHUP && running ) {
186+ flag_reopen_file = 1 ;
187+ sighup_count ++ ;
188+ }
189+ }
176190
191+ static int idx2dindex (int ifidx , int socket )
192+ {
177193 int i ;
178194 struct ifreq ifr ;
179195
@@ -221,6 +237,89 @@ static int idx2dindex(int ifidx, int socket)
221237 return i ;
222238}
223239
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+
224323int main (int argc , char * * argv )
225324{
226325 int fd_epoll ;
@@ -233,7 +332,7 @@ int main(int argc, char **argv)
233332 unsigned char down_causes_exit = 1 ;
234333 unsigned char dropmonitor = 0 ;
235334 unsigned char extra_msg_info = 0 ;
236- unsigned char silent = SILENT_INI ;
335+
237336 unsigned char silentani = 0 ;
238337 unsigned char color = 0 ;
239338 unsigned char view = 0 ;
@@ -257,16 +356,32 @@ int main(int argc, char **argv)
257356 struct ifreq ifr ;
258357 struct timeval tv , last_tv ;
259358 int timeout_ms = -1 ; /* default to no timeout */
260- FILE * logfile = NULL ;
261359
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 );
265372
266373 last_tv .tv_sec = 0 ;
267374 last_tv .tv_usec = 0 ;
268375
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 ) {
270385 switch (opt ) {
271386 case 't' :
272387 timestamp = optarg [0 ];
@@ -314,9 +429,32 @@ int main(int argc, char **argv)
314429 }
315430 break ;
316431
432+ case ':' : //handle flags with optional values
433+
434+ switch (optopt )
435+ {
436+ case 'l' :
437+ log = 1 ;
438+
439+ if (process_logname_arg (optarg ) != 0 ) {
440+ print_usage (basename (argv [0 ]));
441+ exit (1 );
442+ }
443+ break ;
444+ default :
445+ fprintf (stderr , "option -%c is missing a required argument\n" , optopt );
446+ return EXIT_FAILURE ;
447+ }
448+ break ;
317449
318450 case 'l' :
319451 log = 1 ;
452+
453+ if (process_logname_arg (optarg ) != 0 ) {
454+ is_auto_log_name = 0 ;
455+ print_usage (basename (argv [0 ]));
456+ exit (1 );
457+ }
320458 break ;
321459
322460 case 'D' :
@@ -371,6 +509,10 @@ int main(int argc, char **argv)
371509 exit (0 );
372510 }
373511
512+ /* Configure SIGHUP handler to reopen file if logging */
513+ sighup_action .sa_handler = log ? sighup : sigterm ;
514+ sigaction (SIGHUP , & sighup_action , NULL );
515+
374516 if (logfrmt && view ) {
375517 fprintf (stderr , "Log file format selected: Please disable ASCII/BINARY/SWAP/RAWDLC options!\n" );
376518 exit (0 );
@@ -592,35 +734,10 @@ int main(int argc, char **argv)
592734 }
593735
594736 if (log ) {
595- time_t currtime ;
596- struct tm now ;
597- char fname [83 ]; /* suggested by -Wformat-overflow= */
737+ const int result = open_log_file (log_filename );
598738
599- if (time (& currtime ) == (time_t )- 1 ) {
600- perror ("time" );
739+ if (result != 0 )
601740 return 1 ;
602- }
603-
604- localtime_r (& currtime , & now );
605-
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" );
622- return 1 ;
623- }
624741 }
625742
626743 /* these settings are static and can be held out of the hot path */
@@ -631,10 +748,17 @@ int main(int argc, char **argv)
631748 msg .msg_control = & ctrlmsg ;
632749
633750 while (running ) {
634-
635751 if ((num_events = epoll_wait (fd_epoll , events_pending , currmax , timeout_ms )) <= 0 ) {
636752 //perror("epoll_wait");
637- running = 0 ;
753+ if (num_events == -1 ) {
754+ const int serr = errno ;
755+ if (log && flag_reopen_file && serr == EINTR ) {
756+ if (reopen_file (logfile ) != 0 )
757+ return -1 ;
758+ } else {
759+ running = 0 ;
760+ }
761+ }
638762 continue ;
639763 }
640764
@@ -817,6 +941,12 @@ int main(int argc, char **argv)
817941 out_fflush :
818942 fflush (stdout );
819943 }
944+
945+ if (log && flag_reopen_file == 1 ) {
946+ if (reopen_file (logfile ) != 0 ) {
947+ return -1 ;
948+ }
949+ }
820950 }
821951
822952 for (i = 0 ; i < currmax ; i ++ )
0 commit comments