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.
|
- 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.
|
- 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: ###
|
### Bugs Fixed: ###
|
||||||
|
|
||||||
- PACLEN configuration item no longer restricts length of received frames.
|
- 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.
|
- 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: ###
|
### 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->gpsnmea_port, "", sizeof(p_misc_config->gpsnmea_port));
|
||||||
strlcpy (p_misc_config->waypoint_port, "", sizeof(p_misc_config->waypoint_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. */
|
/* 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) {
|
else if (strcasecmp(t, "logdir") == 0) {
|
||||||
t = split(NULL,0);
|
t = split(NULL,0);
|
||||||
|
@ -4293,7 +4294,12 @@ void config_init (char *fname, struct audio_s *p_audio_config,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
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);
|
t = split(NULL,0);
|
||||||
if (t != NULL) {
|
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
|
* 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 */
|
#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_configured; /* TRUE if SmartBeaconing is configured. */
|
||||||
int sb_fast_speed; /* MPH */
|
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;
|
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. */
|
int r_opt = 0, n_opt = 0, b_opt = 0, B_opt = 0, D_opt = 0; /* Command line options. */
|
||||||
char P_opt[16];
|
char P_opt[16];
|
||||||
char l_opt[80];
|
char l_opt_logdir[80];
|
||||||
|
char L_opt_logfile[80];
|
||||||
char input_file[80];
|
char input_file[80];
|
||||||
// char timestamp[16];
|
// 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_tx_opt = 0; /* "-E n" Error rate % for clobbering trasmit frames. */
|
||||||
int E_rx_opt = 0; /* "-E Rn" Error rate % for clobbering receive 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));
|
strlcpy(P_opt, "", sizeof(P_opt));
|
||||||
|
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
|
@ -356,7 +358,7 @@ int main (int argc, char *argv[])
|
||||||
|
|
||||||
/* ':' following option character means arg is required. */
|
/* ':' 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);
|
long_options, &option_index);
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
break;
|
break;
|
||||||
|
@ -532,11 +534,17 @@ int main (int argc, char *argv[])
|
||||||
exit (0);
|
exit (0);
|
||||||
break;
|
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;
|
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. */
|
case 'S': /* Print symbol tables and exit. */
|
||||||
|
|
||||||
symbols_init ();
|
symbols_init ();
|
||||||
|
@ -674,8 +682,19 @@ int main (int argc, char *argv[])
|
||||||
audio_config.recv_error_rate = E_rx_opt;
|
audio_config.recv_error_rate = E_rx_opt;
|
||||||
|
|
||||||
|
|
||||||
if (strlen(l_opt) > 0) {
|
if (strlen(l_opt_logdir) > 0 && strlen(L_opt_logfile) > 0) {
|
||||||
strlcpy (misc_config.logdir, l_opt, sizeof(misc_config.logdir));
|
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;
|
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 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);
|
mheard_init (d_m_opt);
|
||||||
beacon_init (&audio_config, &misc_config, &igate_config);
|
beacon_init (&audio_config, &misc_config, &igate_config);
|
||||||
|
|
||||||
|
|
Binary file not shown.
243
log.c
243
log.c
|
@ -28,6 +28,13 @@
|
||||||
* unreadable, format, write separated properties into
|
* unreadable, format, write separated properties into
|
||||||
* CSV format for easy reading and later processing.
|
* 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.
|
* 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.
|
* Use "." for current directory.
|
||||||
* Empty string disables feature.
|
* 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.
|
* 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.
|
* 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 FILE *g_log_fp;
|
||||||
static char g_open_fname[20];
|
static char g_open_fname[20];
|
||||||
|
|
||||||
|
|
||||||
void log_init (char *path)
|
void log_init (int daily_names, char *path)
|
||||||
{
|
{
|
||||||
struct stat st;
|
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;
|
g_log_fp = NULL;
|
||||||
strlcpy (g_open_fname, "", sizeof(g_open_fname));
|
strlcpy (g_open_fname, "", sizeof(g_open_fname));
|
||||||
|
|
||||||
|
@ -118,42 +138,57 @@ void log_init (char *path)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stat(path,&st) == 0) {
|
if (g_daily_names) {
|
||||||
// Exists, but is it a directory?
|
|
||||||
if (S_ISDIR(st.st_mode)) {
|
// Original strategy. Automatic daily file names.
|
||||||
// Specified directory exists.
|
|
||||||
strlcpy (g_log_dir, path, sizeof(g_log_dir));
|
if (stat(path,&st) == 0) {
|
||||||
|
// Exists, but is it a directory?
|
||||||
|
if (S_ISDIR(st.st_mode)) {
|
||||||
|
// Specified directory exists.
|
||||||
|
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_path, ".", sizeof(g_log_path));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
// Doesn't exist. Try to create it.
|
||||||
dw_printf ("Log file location \"%s\" is not a directory.\n", path);
|
// parent directory must exist.
|
||||||
dw_printf ("Using current working directory \".\" instead.\n");
|
// We don't create multiple levels like "mkdir -p"
|
||||||
strlcpy (g_log_dir, ".", sizeof(g_log_dir));
|
#if __WIN32__
|
||||||
|
if (_mkdir (path) == 0) {
|
||||||
|
#else
|
||||||
|
if (mkdir (path, 0777) == 0) {
|
||||||
|
#endif
|
||||||
|
// Success.
|
||||||
|
text_color_set(DW_COLOR_INFO);
|
||||||
|
dw_printf ("Log file location \"%s\" has been created.\n", path);
|
||||||
|
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_path, ".", sizeof(g_log_path));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Doesn't exist. Try to create it.
|
|
||||||
// parent directory must exist.
|
// Added in version 1.5. Single file.
|
||||||
// We don't create multiple levels like "mkdir -p"
|
// Typically logrotate would be used to keep size under control.
|
||||||
#if __WIN32__
|
|
||||||
if (_mkdir (path) == 0) {
|
text_color_set(DW_COLOR_INFO);
|
||||||
#else
|
dw_printf ("Log file is \"%s\"\n", path);
|
||||||
if (mkdir (path, 0777) == 0) {
|
strlcpy (g_log_path, path, sizeof(g_log_path));
|
||||||
#endif
|
|
||||||
// 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));
|
|
||||||
}
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
} /* end log_init */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -177,71 +212,119 @@ void log_init (char *path)
|
||||||
|
|
||||||
void log_write (int chan, decode_aprs_t *A, packet_t pp, alevel_t alevel, retry_t retries)
|
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 ???
|
time_t now;
|
||||||
char fname[20];
|
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
|
|
||||||
|
|
||||||
if (strlen(g_log_dir) == 0) return;
|
if (strlen(g_log_path) == 0) return;
|
||||||
|
|
||||||
// Generate the file name from current date, UTC.
|
now = time(NULL); // Get current time.
|
||||||
|
|
||||||
now = time(NULL);
|
|
||||||
(void)gmtime_r (&now, &tm);
|
(void)gmtime_r (&now, &tm);
|
||||||
|
|
||||||
// Microsoft doesn't recognize %F as equivalent to %Y-%m-%d
|
|
||||||
|
|
||||||
strftime (fname, sizeof(fname), "%Y-%m-%d.log", &tm);
|
if (g_daily_names) {
|
||||||
|
|
||||||
// Close current file if name has changed
|
// Original strategy. Automatic daily file names.
|
||||||
|
|
||||||
if (g_log_fp != NULL && strcmp(fname, g_open_fname) != 0) {
|
char fname[20];
|
||||||
log_term ();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open for append if not already open.
|
// Generate the file name from current date, UTC.
|
||||||
|
// 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.
|
||||||
|
|
||||||
if (g_log_fp == NULL) {
|
// Microsoft doesn't recognize %F as equivalent to %Y-%m-%d
|
||||||
char full_path[120];
|
|
||||||
struct stat st;
|
|
||||||
int already_there;
|
|
||||||
|
|
||||||
strlcpy (full_path, g_log_dir, sizeof(full_path));
|
strftime (fname, sizeof(fname), "%Y-%m-%d.log", &tm);
|
||||||
|
|
||||||
|
// Close current file if name has changed
|
||||||
|
|
||||||
|
if (g_log_fp != NULL && strcmp(fname, g_open_fname) != 0) {
|
||||||
|
log_term ();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open for append if not already open.
|
||||||
|
|
||||||
|
if (g_log_fp == NULL) {
|
||||||
|
char full_path[120];
|
||||||
|
struct stat st;
|
||||||
|
int already_there;
|
||||||
|
|
||||||
|
strlcpy (full_path, g_log_path, sizeof(full_path));
|
||||||
#if __WIN32__
|
#if __WIN32__
|
||||||
strlcat (full_path, "\\", sizeof(full_path));
|
strlcat (full_path, "\\", sizeof(full_path));
|
||||||
#else
|
#else
|
||||||
strlcat (full_path, "/", sizeof(full_path));
|
strlcat (full_path, "/", sizeof(full_path));
|
||||||
#endif
|
#endif
|
||||||
strlcat (full_path, fname, sizeof(full_path));
|
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.
|
// 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);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf("Opening log file \"%s\".\n", fname);
|
dw_printf("Opening log file \"%s\".\n", fname);
|
||||||
|
|
||||||
g_log_fp = fopen (full_path, "a");
|
g_log_fp = fopen (full_path, "a");
|
||||||
|
|
||||||
if (g_log_fp != NULL) {
|
if (g_log_fp != NULL) {
|
||||||
strlcpy (g_open_fname, fname, sizeof(g_open_fname));
|
strlcpy (g_open_fname, fname, sizeof(g_open_fname));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf("Can't open log file \"%s\" for write.\n", full_path);
|
dw_printf("Can't open log file \"%s\" for write.\n", full_path);
|
||||||
dw_printf ("%s\n", strerror(errno));
|
dw_printf ("%s\n", strerror(errno));
|
||||||
strlcpy (g_open_fname, "", sizeof(g_open_fname));
|
strlcpy (g_open_fname, "", sizeof(g_open_fname));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write a header suitable for importing into a spreadsheet
|
// Write a header suitable for importing into a spreadsheet
|
||||||
// only if this will be the first line.
|
// only if this will be the first line.
|
||||||
|
|
||||||
if ( ! already_there) {
|
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");
|
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) {
|
if (g_log_fp != NULL) {
|
||||||
|
|
||||||
|
@ -439,7 +522,13 @@ void log_term (void)
|
||||||
if (g_log_fp != NULL) {
|
if (g_log_fp != NULL) {
|
||||||
|
|
||||||
text_color_set(DW_COLOR_INFO);
|
text_color_set(DW_COLOR_INFO);
|
||||||
dw_printf("Closing log file \"%s\".\n", g_open_fname);
|
|
||||||
|
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);
|
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);
|
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.
|
Read configuration file from specified location rather than the default locations.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "-l " "dir"
|
.BI "-l " "logdir"
|
||||||
Generate log files in specified directory. Use "." for current directory.
|
Generate daily log files in specified directory. Use "." for current directory.
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BI "-L " "logfile"
|
||||||
|
Generate single log file with fixed name.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.BI "-r " "n"
|
.BI "-r " "n"
|
||||||
|
|
Loading…
Reference in New Issue