pull/268/merge
richnetdesign 2020-12-07 10:13:35 +00:00 committed by GitHub
commit ad041cf06c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 167 additions and 37 deletions

204
candump.c
View File

@ -116,9 +116,18 @@ static const int canfd_on = 1;
static const char anichar[MAXANI] = { '|', '/', '-', '\\' }; static const char anichar[MAXANI] = { '|', '/', '-', '\\' };
static const char extra_m_info[4][4] = { "- -", "B -", "- E", "B E" }; static const char extra_m_info[4][4] = { "- -", "B -", "- E", "B E" };
#define MAXLOGNAMESZ 100
static FILE *logfile = NULL;
static char log_filename[MAXLOGNAMESZ];
static unsigned char silent = SILENT_INI;
extern int optind, opterr, optopt; extern int optind, opterr, optopt;
static volatile int running = 1; static volatile int running = 1;
static volatile int flag_reopen_file;
static int is_auto_log_name;
static volatile unsigned long sighup_count;
static void print_usage(char *prg) static void print_usage(char *prg)
{ {
@ -133,7 +142,7 @@ static void print_usage(char *prg)
fprintf(stderr, " -a (enable additional ASCII output)\n"); fprintf(stderr, " -a (enable additional ASCII output)\n");
fprintf(stderr, " -S (swap byte order in printed CAN data[] - marked with '%c' )\n", SWAP_DELIMITER); fprintf(stderr, " -S (swap byte order in printed CAN data[] - marked with '%c' )\n", SWAP_DELIMITER);
fprintf(stderr, " -s <level> (silent mode - %d: off (default) %d: animation %d: silent)\n", SILENT_OFF, SILENT_ANI, SILENT_ON); fprintf(stderr, " -s <level> (silent mode - %d: off (default) %d: animation %d: silent)\n", SILENT_OFF, SILENT_ANI, SILENT_ON);
fprintf(stderr, " -l (log CAN-frames into file. Sets '-s %d' by default)\n", SILENT_ON); fprintf(stderr, " -l <name> (log CAN-frames into file. Sets '-s %d' by default)\n", SILENT_ON);
fprintf(stderr, " -L (use log file format on stdout)\n"); fprintf(stderr, " -L (use log file format on stdout)\n");
fprintf(stderr, " -n <count> (terminate after reception of <count> CAN frames)\n"); fprintf(stderr, " -n <count> (terminate after reception of <count> CAN frames)\n");
fprintf(stderr, " -r <size> (set socket receive buffer to <size>)\n"); fprintf(stderr, " -r <size> (set socket receive buffer to <size>)\n");
@ -171,9 +180,16 @@ static void sigterm(int signo)
running = 0; running = 0;
} }
static void sighup(int signo)
{
if (signo == SIGHUP && running) {
flag_reopen_file = 1;
sighup_count++;
}
}
static int idx2dindex(int ifidx, int socket) static int idx2dindex(int ifidx, int socket)
{ {
int i; int i;
struct ifreq ifr; struct ifreq ifr;
@ -221,6 +237,89 @@ static int idx2dindex(int ifidx, int socket)
return i; return i;
} }
static int sprint_auto_filename_format(char *buffer)
{
time_t currtime;
struct tm now;
if (time(&currtime) == (time_t)-1) {
perror("time");
return 1;
}
localtime_r(&currtime, &now);
sprintf(buffer, "candump-%04d-%02d-%02d_%02d%02d%02d.log",
now.tm_year + 1900,
now.tm_mon + 1,
now.tm_mday,
now.tm_hour,
now.tm_min,
now.tm_sec);
fprintf(stderr, "Enabling Logfile '%s'\n", buffer);
return 0;
}
/* opens file using global var logfile */
static int open_log_file(const char *file_name)
{
if (silent != SILENT_ON)
fprintf(stderr, "Warning: Console output active while logging!\n");
logfile = fopen(file_name, "w");
if (!logfile) {
perror("logfile");
return 1;
}
return 0;
}
static int reopen_file(FILE *file_handle)
{
const char *fopen_opts = (sighup_count > 0 && !is_auto_log_name) ? "a" : "w";
if (!file_handle)
return 1;
if (is_auto_log_name == 1) {
const int errcode = sprint_auto_filename_format(log_filename);
if (errcode != 0) {
return 1;
}
}
/* close existing filehandle, and open new one if necessary */
logfile = freopen(log_filename, fopen_opts, file_handle);
flag_reopen_file = 0;
return logfile == 0;
}
static int process_logname_arg(const char *arg)
{
if (arg != 0) {
const size_t len = strnlen(arg, MAXLOGNAMESZ);
if (len > 0 && len < MAXLOGNAMESZ) {
strncpy(log_filename, arg, MAXLOGNAMESZ - 1);
} else {
return 1;
}
is_auto_log_name = 0;
} else {
is_auto_log_name = 1;
sprint_auto_filename_format(log_filename);
}
return 0;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int fd_epoll; int fd_epoll;
@ -233,7 +332,7 @@ int main(int argc, char **argv)
unsigned char down_causes_exit = 1; unsigned char down_causes_exit = 1;
unsigned char dropmonitor = 0; unsigned char dropmonitor = 0;
unsigned char extra_msg_info = 0; unsigned char extra_msg_info = 0;
unsigned char silent = SILENT_INI;
unsigned char silentani = 0; unsigned char silentani = 0;
unsigned char color = 0; unsigned char color = 0;
unsigned char view = 0; unsigned char view = 0;
@ -257,16 +356,32 @@ int main(int argc, char **argv)
struct ifreq ifr; struct ifreq ifr;
struct timeval tv, last_tv; struct timeval tv, last_tv;
int timeout_ms = -1; /* default to no timeout */ int timeout_ms = -1; /* default to no timeout */
FILE *logfile = NULL;
signal(SIGTERM, sigterm); sigset_t sig_block_mask;
signal(SIGHUP, sigterm); sigset_t sig_empty_mask;
signal(SIGINT, sigterm); struct sigaction sighup_action = { .sa_flags = SA_RESTART };
struct sigaction sigterm_action = { .sa_flags = SA_RESTART, .sa_handler = sigterm };
sigfillset(&sig_block_mask);
sighup_action.sa_mask = sig_block_mask;
sigemptyset(&sig_empty_mask);
sigterm_action.sa_mask = sig_empty_mask;
sigaction (SIGHUP, &sigterm_action, NULL);
sigaction (SIGINT, &sigterm_action, NULL);
last_tv.tv_sec = 0; last_tv.tv_sec = 0;
last_tv.tv_usec = 0; last_tv.tv_usec = 0;
while ((opt = getopt(argc, argv, "t:HciaSs:lDdxLn:r:he8T:?")) != -1) { int getoptargc = argc;
/* Since interface is a required argument, we don't need to parse opt for final arg
* This enabled the -l option to take an optional filename */
if (getoptargc > 0) {
getoptargc = argc - 1;
}
while ((opt = getopt(getoptargc, argv, ":t:HciaSs:l:DdxLn:r:he8T:?")) != -1) {
switch (opt) { switch (opt) {
case 't': case 't':
timestamp = optarg[0]; timestamp = optarg[0];
@ -314,9 +429,32 @@ int main(int argc, char **argv)
} }
break; break;
case ':': //handle flags with optional values
switch (optopt)
{
case 'l':
log = 1;
if (process_logname_arg(optarg) != 0) {
print_usage(basename(argv[0]));
exit(1);
}
break;
default:
fprintf(stderr, "option -%c is missing a required argument\n", optopt);
return EXIT_FAILURE;
}
break;
case 'l': case 'l':
log = 1; log = 1;
if (process_logname_arg(optarg) != 0) {
is_auto_log_name = 0;
print_usage(basename(argv[0]));
exit(1);
}
break; break;
case 'D': case 'D':
@ -371,6 +509,10 @@ int main(int argc, char **argv)
exit(0); exit(0);
} }
/* Configure SIGHUP handler to reopen file if logging */
sighup_action.sa_handler = log ? sighup : sigterm;
sigaction(SIGHUP, &sighup_action, NULL);
if (logfrmt && view) { if (logfrmt && view) {
fprintf(stderr, "Log file format selected: Please disable ASCII/BINARY/SWAP/RAWDLC options!\n"); fprintf(stderr, "Log file format selected: Please disable ASCII/BINARY/SWAP/RAWDLC options!\n");
exit(0); exit(0);
@ -592,35 +734,10 @@ int main(int argc, char **argv)
} }
if (log) { if (log) {
time_t currtime; const int result = open_log_file(log_filename);
struct tm now;
char fname[83]; /* suggested by -Wformat-overflow= */
if (time(&currtime) == (time_t)-1) { if (result != 0)
perror("time");
return 1; return 1;
}
localtime_r(&currtime, &now);
sprintf(fname, "candump-%04d-%02d-%02d_%02d%02d%02d.log",
now.tm_year + 1900,
now.tm_mon + 1,
now.tm_mday,
now.tm_hour,
now.tm_min,
now.tm_sec);
if (silent != SILENT_ON)
fprintf(stderr, "Warning: Console output active while logging!\n");
fprintf(stderr, "Enabling Logfile '%s'\n", fname);
logfile = fopen(fname, "w");
if (!logfile) {
perror("logfile");
return 1;
}
} }
/* these settings are static and can be held out of the hot path */ /* these settings are static and can be held out of the hot path */
@ -631,10 +748,17 @@ int main(int argc, char **argv)
msg.msg_control = &ctrlmsg; msg.msg_control = &ctrlmsg;
while (running) { while (running) {
if ((num_events = epoll_wait(fd_epoll, events_pending, currmax, timeout_ms)) <= 0) { if ((num_events = epoll_wait(fd_epoll, events_pending, currmax, timeout_ms)) <= 0) {
//perror("epoll_wait"); //perror("epoll_wait");
running = 0; if(num_events == -1) {
const int serr = errno;
if (log && flag_reopen_file && serr == EINTR) {
if (reopen_file(logfile) != 0)
return -1;
} else {
running = 0;
}
}
continue; continue;
} }
@ -817,6 +941,12 @@ int main(int argc, char **argv)
out_fflush: out_fflush:
fflush(stdout); fflush(stdout);
} }
if (log && flag_reopen_file == 1) {
if (reopen_file(logfile) != 0) {
return -1;
}
}
} }
for (i = 0; i < currmax; i++) for (i = 0; i < currmax; i++)