@@ -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,17 @@ static void sigterm(int signo)
171180 running = 0 ;
172181}
173182
174- static int idx2dindex (int ifidx , int socket )
183+
184+ static void sighup (int signo )
175185{
186+ if (signo == SIGHUP && running ) {
187+ flag_reopen_file = 1 ;
188+ sighup_count ++ ;
189+ }
190+ }
176191
192+ static int idx2dindex (int ifidx , int socket )
193+ {
177194 int i ;
178195 struct ifreq ifr ;
179196
@@ -221,6 +238,88 @@ static int idx2dindex(int ifidx, int socket)
221238 return i ;
222239}
223240
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+
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,33 @@ 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_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 );
265373
266374 last_tv .tv_sec = 0 ;
267375 last_tv .tv_usec = 0 ;
268376
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 ) {
270386 switch (opt ) {
271387 case 't' :
272388 timestamp = optarg [0 ];
@@ -314,9 +430,35 @@ int main(int argc, char **argv)
314430 }
315431 break ;
316432
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 ;
317452
318453 case 'l' :
319454 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+
320462 break ;
321463
322464 case 'D' :
@@ -371,6 +513,10 @@ int main(int argc, char **argv)
371513 exit (0 );
372514 }
373515
516+ /* Configure SIGHUP handler to reopen file if logging */
517+ sighup_action .sa_handler = log ? sighup : sigterm ;
518+ sigaction (SIGHUP , & sighup_action , NULL );
519+
374520 if (logfrmt && view ) {
375521 fprintf (stderr , "Log file format selected: Please disable ASCII/BINARY/SWAP/RAWDLC options!\n" );
376522 exit (0 );
@@ -592,35 +738,10 @@ int main(int argc, char **argv)
592738 }
593739
594740 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 );
605742
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 )
622744 return 1 ;
623- }
624745 }
625746
626747 /* these settings are static and can be held out of the hot path */
@@ -631,10 +752,20 @@ int main(int argc, char **argv)
631752 msg .msg_control = & ctrlmsg ;
632753
633754 while (running ) {
634-
635755 if ((num_events = epoll_wait (fd_epoll , events_pending , currmax , timeout_ms )) <= 0 ) {
636756 //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+ }
638769 continue ;
639770 }
640771
@@ -817,6 +948,12 @@ int main(int argc, char **argv)
817948 out_fflush :
818949 fflush (stdout );
819950 }
951+
952+ if (flag_reopen_file == 1 ) {
953+ if (reopen_file (logfile ) != 0 ) {
954+ return -1 ;
955+ }
956+ }
820957 }
821958
822959 for (i = 0 ; i < currmax ; i ++ )
0 commit comments