mirror of https://github.com/wb2osz/direwolf.git
Allow single log file with fixed name rather than starting a new one each day.
This commit is contained in:
parent
647d698656
commit
52927ce54a
|
@ -9,10 +9,11 @@ This is a snapshot of ongoing development towards version of 1.5. Some features
|
|||
|
||||
- Time slots for beaconing.
|
||||
|
||||
- V20 configuration item for listing stations known not to understaand AX.25 v2.2. This will speed up connection by going right to SABM and not trying SABME first and failing.
|
||||
|
||||
- Documentation updates describing cheap SDR frequency inaccuracy and how to compensate for it.
|
||||
|
||||
- Allow single log file with fixed name rather than starting a new one each day.
|
||||
|
||||
|
||||
### Bugs Fixed: ###
|
||||
|
||||
- PACLEN configuration item no longer restricts length of received frames.
|
||||
|
@ -31,7 +32,7 @@ This is a snapshot of ongoing development towards version of 1.5. Some features
|
|||
|
||||
- decode_aprs utility can now accept KISS frames and AX.25 frames as series of two digit hexadecimal numbers.
|
||||
|
||||
- New configuration option, V20, for listing stations known to not understand AX.25 v2.2.
|
||||
- New configuration option, V20, for listing stations known to not understand AX.25 v2.2. This will speed up connection by going right to SABM and not trying SABME first and failing.
|
||||
|
||||
|
||||
### Bugs Fixed: ###
|
||||
|
|
37
config.c
37
config.c
|
@ -877,7 +877,8 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
strlcpy (p_misc_config->gpsnmea_port, "", sizeof(p_misc_config->gpsnmea_port));
|
||||
strlcpy (p_misc_config->waypoint_port, "", sizeof(p_misc_config->waypoint_port));
|
||||
|
||||
strlcpy (p_misc_config->logdir, "", sizeof(p_misc_config->logdir));
|
||||
p_misc_config->log_daily_names = 0;
|
||||
strlcpy (p_misc_config->log_path, "", sizeof(p_misc_config->log_path));
|
||||
|
||||
/* connected mode. */
|
||||
|
||||
|
@ -4283,7 +4284,7 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
}
|
||||
|
||||
/*
|
||||
* LOGDIR - Directory name for storing log files. Use "." for current working directory.
|
||||
* LOGDIR - Directory name for automatically named daily log files. Use "." for current working directory.
|
||||
*/
|
||||
else if (strcasecmp(t, "logdir") == 0) {
|
||||
t = split(NULL,0);
|
||||
|
@ -4293,7 +4294,12 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
continue;
|
||||
}
|
||||
else {
|
||||
strlcpy (p_misc_config->logdir, t, sizeof(p_misc_config->logdir));
|
||||
if (strlen(p_misc_config->log_path) > 0) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: LOGDIR on line %d is replacing an earlier LOGDIR or LOGFILE.\n", line);
|
||||
}
|
||||
p_misc_config->log_daily_names = 1;
|
||||
strlcpy (p_misc_config->log_path, t, sizeof(p_misc_config->log_path));
|
||||
}
|
||||
t = split(NULL,0);
|
||||
if (t != NULL) {
|
||||
|
@ -4302,6 +4308,31 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* LOGFILE - Log file name, including any directory part.
|
||||
*/
|
||||
else if (strcasecmp(t, "logfile") == 0) {
|
||||
t = split(NULL,0);
|
||||
if (t == NULL) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: Missing file name for LOGFILE on line %d.\n", line);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if (strlen(p_misc_config->log_path) > 0) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: LOGFILE on line %d is replacing an earlier LOGDIR or LOGFILE.\n", line);
|
||||
}
|
||||
p_misc_config->log_daily_names = 0;
|
||||
strlcpy (p_misc_config->log_path, t, sizeof(p_misc_config->log_path));
|
||||
}
|
||||
t = split(NULL,0);
|
||||
if (t != NULL) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Config file: LOGFILE on line %d should have file name and nothing more.\n", line);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* BEACON channel delay every message
|
||||
*
|
||||
|
|
4
config.h
4
config.h
|
@ -77,7 +77,9 @@ struct misc_config_s {
|
|||
#define WPT_FORMAT_KENWOOD 0x08 /* K $PKWDWPL */
|
||||
|
||||
|
||||
char logdir[80]; /* Directory for saving activity logs. */
|
||||
int log_daily_names; /* True to generate new log file each day. */
|
||||
|
||||
char log_path[80]; /* Either directory or full file name depending on above. */
|
||||
|
||||
int sb_configured; /* TRUE if SmartBeaconing is configured. */
|
||||
int sb_fast_speed; /* MPH */
|
||||
|
|
35
direwolf.c
35
direwolf.c
|
@ -194,7 +194,8 @@ int main (int argc, char *argv[])
|
|||
struct igate_config_s igate_config;
|
||||
int r_opt = 0, n_opt = 0, b_opt = 0, B_opt = 0, D_opt = 0; /* Command line options. */
|
||||
char P_opt[16];
|
||||
char l_opt[80];
|
||||
char l_opt_logdir[80];
|
||||
char L_opt_logfile[80];
|
||||
char input_file[80];
|
||||
// char timestamp[16];
|
||||
|
||||
|
@ -215,7 +216,8 @@ int main (int argc, char *argv[])
|
|||
int E_tx_opt = 0; /* "-E n" Error rate % for clobbering trasmit frames. */
|
||||
int E_rx_opt = 0; /* "-E Rn" Error rate % for clobbering receive frames. */
|
||||
|
||||
strlcpy(l_opt, "", sizeof(l_opt));
|
||||
strlcpy(l_opt_logdir, "", sizeof(l_opt_logdir));
|
||||
strlcpy(L_opt_logfile, "", sizeof(L_opt_logfile));
|
||||
strlcpy(P_opt, "", sizeof(P_opt));
|
||||
|
||||
#if __WIN32__
|
||||
|
@ -356,7 +358,7 @@ int main (int argc, char *argv[])
|
|||
|
||||
/* ':' following option character means arg is required. */
|
||||
|
||||
c = getopt_long(argc, argv, "P:B:D:c:pxr:b:n:d:q:t:Ul:Sa:E:",
|
||||
c = getopt_long(argc, argv, "P:B:D:c:pxr:b:n:d:q:t:Ul:L:Sa:E:",
|
||||
long_options, &option_index);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
@ -532,11 +534,17 @@ int main (int argc, char *argv[])
|
|||
exit (0);
|
||||
break;
|
||||
|
||||
case 'l': /* -l for log file directory name */
|
||||
case 'l': /* -l for log directory with daily files */
|
||||
|
||||
strlcpy (l_opt, optarg, sizeof(l_opt));
|
||||
strlcpy (l_opt_logdir, optarg, sizeof(l_opt_logdir));
|
||||
break;
|
||||
|
||||
case 'L': /* -L for log file name with full path */
|
||||
|
||||
strlcpy (L_opt_logfile, optarg, sizeof(L_opt_logfile));
|
||||
break;
|
||||
|
||||
|
||||
case 'S': /* Print symbol tables and exit. */
|
||||
|
||||
symbols_init ();
|
||||
|
@ -674,8 +682,19 @@ int main (int argc, char *argv[])
|
|||
audio_config.recv_error_rate = E_rx_opt;
|
||||
|
||||
|
||||
if (strlen(l_opt) > 0) {
|
||||
strlcpy (misc_config.logdir, l_opt, sizeof(misc_config.logdir));
|
||||
if (strlen(l_opt_logdir) > 0 && strlen(L_opt_logfile) > 0) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Logging options -l and -L can't be used together. Pick one or the other.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strlen(L_opt_logfile) > 0) {
|
||||
misc_config.log_daily_names = 0;
|
||||
strlcpy (misc_config.log_path, L_opt_logfile, sizeof(misc_config.log_path));
|
||||
}
|
||||
else if (strlen(l_opt_logdir) > 0) {
|
||||
misc_config.log_daily_names = 1;
|
||||
strlcpy (misc_config.log_path, l_opt_logdir, sizeof(misc_config.log_path));
|
||||
}
|
||||
|
||||
misc_config.enable_kiss_pt = enable_pseudo_terminal;
|
||||
|
@ -794,7 +813,7 @@ int main (int argc, char *argv[])
|
|||
* log the tracker beacon transmissions with fake channel 999.
|
||||
*/
|
||||
|
||||
log_init(misc_config.logdir);
|
||||
log_init(misc_config.log_daily_names, misc_config.log_path);
|
||||
mheard_init (d_m_opt);
|
||||
beacon_init (&audio_config, &misc_config, &igate_config);
|
||||
|
||||
|
|
Binary file not shown.
125
log.c
125
log.c
|
@ -28,6 +28,13 @@
|
|||
* unreadable, format, write separated properties into
|
||||
* CSV format for easy reading and later processing.
|
||||
*
|
||||
* There are two alternatives here.
|
||||
*
|
||||
* -L logfile Specify full file path.
|
||||
*
|
||||
* -l logdir Daily names will be created here.
|
||||
*
|
||||
* Use one or the other but not both.
|
||||
*
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
|
@ -91,26 +98,39 @@ static void quote_for_csv (char *out, size_t outsize, const char *in) {
|
|||
*
|
||||
* Purpose: Initialization at start of application.
|
||||
*
|
||||
* Inputs: path - Path of log file directory.
|
||||
* Inputs: daily_names - True if daily names should be generated.
|
||||
* In this case path is a directory.
|
||||
* When false, path would be the file name.
|
||||
*
|
||||
* path - Log file name or just directory.
|
||||
* Use "." for current directory.
|
||||
* Empty string disables feature.
|
||||
*
|
||||
* Global Out: g_log_dir - Save directory here for later use.
|
||||
* Global Out: g_daily_names - True if daily names should be generated.
|
||||
*
|
||||
* g_log_path - Save directory or full name here for later use.
|
||||
*
|
||||
* g_log_fp - File pointer for writing.
|
||||
* Note that file is kept open.
|
||||
* We don't open/close for every new item.
|
||||
*
|
||||
* g_open_fname - Name of currently open file.
|
||||
* Applicable only when g_daily_names is true.
|
||||
*
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
static char g_log_dir[80];
|
||||
static int g_daily_names;
|
||||
static char g_log_path[80];
|
||||
static FILE *g_log_fp;
|
||||
static char g_open_fname[20];
|
||||
|
||||
|
||||
void log_init (char *path)
|
||||
void log_init (int daily_names, char *path)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
strlcpy (g_log_dir, "", sizeof(g_log_dir));
|
||||
g_daily_names = daily_names;
|
||||
strlcpy (g_log_path, "", sizeof(g_log_path));
|
||||
g_log_fp = NULL;
|
||||
strlcpy (g_open_fname, "", sizeof(g_open_fname));
|
||||
|
||||
|
@ -118,17 +138,21 @@ void log_init (char *path)
|
|||
return;
|
||||
}
|
||||
|
||||
if (g_daily_names) {
|
||||
|
||||
// Original strategy. Automatic daily file names.
|
||||
|
||||
if (stat(path,&st) == 0) {
|
||||
// Exists, but is it a directory?
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
// Specified directory exists.
|
||||
strlcpy (g_log_dir, path, sizeof(g_log_dir));
|
||||
strlcpy (g_log_path, path, sizeof(g_log_path));
|
||||
}
|
||||
else {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Log file location \"%s\" is not a directory.\n", path);
|
||||
dw_printf ("Using current working directory \".\" instead.\n");
|
||||
strlcpy (g_log_dir, ".", sizeof(g_log_dir));
|
||||
strlcpy (g_log_path, ".", sizeof(g_log_path));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -143,17 +167,28 @@ void log_init (char *path)
|
|||
// Success.
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
dw_printf ("Log file location \"%s\" has been created.\n", path);
|
||||
strlcpy (g_log_dir, path, sizeof(g_log_dir));
|
||||
strlcpy (g_log_path, path, sizeof(g_log_path));
|
||||
}
|
||||
else {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Failed to create log file location \"%s\".\n", path);
|
||||
dw_printf ("%s\n", strerror(errno));
|
||||
dw_printf ("Using current working directory \".\" instead.\n");
|
||||
strlcpy (g_log_dir, ".", sizeof(g_log_dir));
|
||||
strlcpy (g_log_path, ".", sizeof(g_log_path));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// Added in version 1.5. Single file.
|
||||
// Typically logrotate would be used to keep size under control.
|
||||
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
dw_printf ("Log file is \"%s\"\n", path);
|
||||
strlcpy (g_log_path, path, sizeof(g_log_path));
|
||||
}
|
||||
|
||||
} /* end log_init */
|
||||
|
||||
|
||||
|
||||
|
@ -177,17 +212,25 @@ void log_init (char *path)
|
|||
|
||||
void log_write (int chan, decode_aprs_t *A, packet_t pp, alevel_t alevel, retry_t retries)
|
||||
{
|
||||
time_t now; // make 'now' a parameter so we can process historical data ???
|
||||
char fname[20];
|
||||
time_t now;
|
||||
struct tm tm;
|
||||
|
||||
|
||||
if (strlen(g_log_dir) == 0) return;
|
||||
if (strlen(g_log_path) == 0) return;
|
||||
|
||||
now = time(NULL); // Get current time.
|
||||
(void)gmtime_r (&now, &tm);
|
||||
|
||||
|
||||
if (g_daily_names) {
|
||||
|
||||
// Original strategy. Automatic daily file names.
|
||||
|
||||
char fname[20];
|
||||
|
||||
// Generate the file name from current date, UTC.
|
||||
|
||||
now = time(NULL);
|
||||
(void)gmtime_r (&now, &tm);
|
||||
// Why UTC rather than local time? I don't recall the reasoning.
|
||||
// It's been there a few years and no on complained so leave it alone for now.
|
||||
|
||||
// Microsoft doesn't recognize %F as equivalent to %Y-%m-%d
|
||||
|
||||
|
@ -206,7 +249,7 @@ void log_write (int chan, decode_aprs_t *A, packet_t pp, alevel_t alevel, retry_
|
|||
struct stat st;
|
||||
int already_there;
|
||||
|
||||
strlcpy (full_path, g_log_dir, sizeof(full_path));
|
||||
strlcpy (full_path, g_log_path, sizeof(full_path));
|
||||
#if __WIN32__
|
||||
strlcat (full_path, "\\", sizeof(full_path));
|
||||
#else
|
||||
|
@ -214,10 +257,10 @@ void log_write (int chan, decode_aprs_t *A, packet_t pp, alevel_t alevel, retry_
|
|||
#endif
|
||||
strlcat (full_path, fname, sizeof(full_path));
|
||||
|
||||
// See if it already exists.
|
||||
// See if file already exists and not empty.
|
||||
// This is used later to write a header if it did not exist already.
|
||||
|
||||
already_there = stat(full_path,&st) == 0;
|
||||
already_there = (stat(full_path,&st) == 0) && (st.st_size > 0);
|
||||
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
dw_printf("Opening log file \"%s\".\n", fname);
|
||||
|
@ -242,6 +285,46 @@ void log_write (int chan, decode_aprs_t *A, packet_t pp, alevel_t alevel, retry_
|
|||
fprintf (g_log_fp, "chan,utime,isotime,source,heard,level,error,dti,name,symbol,latitude,longitude,speed,course,altitude,frequency,offset,tone,system,status,telemetry,comment\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// Added in version 1.5. Single file.
|
||||
|
||||
// Open for append if not already open.
|
||||
|
||||
if (g_log_fp == NULL) {
|
||||
struct stat st;
|
||||
int already_there;
|
||||
|
||||
// See if file already exists and not empty.
|
||||
// This is used later to write a header if it did not exist already.
|
||||
|
||||
already_there = (stat(g_log_path,&st) == 0) && (st.st_size > 0);
|
||||
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
dw_printf("Opening log file \"%s\"\n", g_log_path);
|
||||
|
||||
g_log_fp = fopen (g_log_path, "a");
|
||||
|
||||
if (g_log_fp == NULL) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf("Can't open log file \"%s\" for write.\n", g_log_path);
|
||||
dw_printf ("%s\n", strerror(errno));
|
||||
strlcpy (g_log_path, "", sizeof(g_log_path));
|
||||
return;
|
||||
}
|
||||
|
||||
// Write a header suitable for importing into a spreadsheet
|
||||
// only if this will be the first line.
|
||||
|
||||
if ( ! already_there) {
|
||||
fprintf (g_log_fp, "chan,utime,isotime,source,heard,level,error,dti,name,symbol,latitude,longitude,speed,course,altitude,frequency,offset,tone,system,status,telemetry,comment\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add line to file if it is now open.
|
||||
|
||||
if (g_log_fp != NULL) {
|
||||
|
||||
|
@ -439,7 +522,13 @@ void log_term (void)
|
|||
if (g_log_fp != NULL) {
|
||||
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
|
||||
if (g_daily_names) {
|
||||
dw_printf("Closing log file \"%s\".\n", g_open_fname);
|
||||
}
|
||||
else {
|
||||
dw_printf("Closing log file \"%s\".\n", g_log_path);
|
||||
}
|
||||
|
||||
fclose (g_log_fp);
|
||||
|
||||
|
|
2
log.h
2
log.h
|
@ -10,7 +10,7 @@
|
|||
|
||||
|
||||
|
||||
void log_init (char *path);
|
||||
void log_init (int daily_names, char *path);
|
||||
|
||||
void log_write (int chan, decode_aprs_t *A, packet_t pp, alevel_t alevel, retry_t retries);
|
||||
|
||||
|
|
|
@ -27,8 +27,12 @@ RMS Express, and many others.
|
|||
Read configuration file from specified location rather than the default locations.
|
||||
|
||||
.TP
|
||||
.BI "-l " "dir"
|
||||
Generate log files in specified directory. Use "." for current directory.
|
||||
.BI "-l " "logdir"
|
||||
Generate daily log files in specified directory. Use "." for current directory.
|
||||
|
||||
.TP
|
||||
.BI "-L " "logfile"
|
||||
Generate single log file with fixed name.
|
||||
|
||||
.TP
|
||||
.BI "-r " "n"
|
||||
|
|
Loading…
Reference in New Issue