@@ -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