Makes date/time formats configurable.

This commit is contained in:
Ondrej Zajicek 2010-02-03 00:19:24 +01:00
parent 44f26560ec
commit c37e78510f
11 changed files with 97 additions and 65 deletions

View file

@ -80,6 +80,8 @@ config_alloc(byte *name)
cfg_mem = c->mem = l; cfg_mem = c->mem = l;
c->file_name = cfg_strdup(name); c->file_name = cfg_strdup(name);
c->load_time = now; c->load_time = now;
c->tf_base.fmt1 = c->tf_log.fmt1 = "%d-%m-%Y %T";
if (!boot_time) if (!boot_time)
boot_time = now; boot_time = now;
return c; return c;

View file

@ -29,6 +29,11 @@ struct config {
u32 listen_bgp_flags; /* Listening BGP socket should use these flags */ u32 listen_bgp_flags; /* Listening BGP socket should use these flags */
unsigned proto_default_debug; /* Default protocol debug mask */ unsigned proto_default_debug; /* Default protocol debug mask */
unsigned proto_default_mrtdump; /* Default protocol mrtdump mask */ unsigned proto_default_mrtdump; /* Default protocol mrtdump mask */
struct timeformat tf_route; /* Time format for 'show route' */
struct timeformat tf_proto; /* Time format for 'show protocol' */
struct timeformat tf_log; /* Time format for the logfile */
struct timeformat tf_base; /* Time format for other purposes */
int cli_debug; /* Tracing of CLI connections and commands */ int cli_debug; /* Tracing of CLI connections and commands */
char *err_msg; /* Parser error message */ char *err_msg; /* Parser error message */
int err_lino; /* Line containing error */ int err_lino; /* Line containing error */

View file

@ -42,6 +42,7 @@ CF_DECLS
void *g; void *g;
bird_clock_t time; bird_clock_t time;
struct prefix px; struct prefix px;
struct timeformat *tf;
} }
%token END CLI_MARKER INVALID_TOKEN %token END CLI_MARKER INVALID_TOKEN

View file

@ -271,6 +271,31 @@ protocol rip {
listen to IPv6 connections only. This is needed if you want to listen to IPv6 connections only. This is needed if you want to
run both bird and bird6 on the same port. run both bird and bird6 on the same port.
<tag>timeformat route|protocol|base|log "<m/format1/" [<m/limit> "<m/format2/"]</tag>
This option allows to specify a format of date/time used by
BIRD. The first argument specifies for which purpose such
format is used. <cf/route/ is a format used in 'show route'
command output, <cf/protocol/ is used in 'show protocols'
command output, <cf/base/ is used for other commands and
<cf/log/ is used in a log file.
"<m/format1/" is a format string using <i/strftime(3)/
notation (see <i/man strftime/ for details). <m/limit> and
"<m/format2/" allow to specify the second format string for
times in past deeper than <m/limit/ seconds. There are two
shorthands: <cf/iso long/ is a ISO 8601 date/time format
(YYYY-MM-DD hh:mm:ss) that can be also specified using <cf/"%F
%T"/. <cf/iso short/ is a variant of ISO 8601 that uses just
the time format (hh:mm:ss) for near times (up to 20 hours in
the past) and the date format (YYYY-MM-DD) for far times. This
is a shorthand for <cf/"%T" 72000 "%F"/.
By default, BIRD uses an short, ad-hoc format for <cf/route/
and <cf/protocol/ times, and a <cf/iso long/ similar format
(DD-MM-YYYY hh:mm:ss) for <cf/base/ and <cf/log/. These
defaults are here for a compatibility with older versions
and might change in the future.
<tag>table <m/name/</tag> Create a new routing table. The default <tag>table <m/name/</tag> Create a new routing table. The default
routing table is created implicitly, other routing tables have routing table is created implicitly, other routing tables have
to be added by this command. to be added by this command.

View file

@ -18,12 +18,12 @@ cmd_show_status(void)
byte tim[TM_DATETIME_BUFFER_SIZE]; byte tim[TM_DATETIME_BUFFER_SIZE];
cli_msg(-1000, "BIRD " BIRD_VERSION); cli_msg(-1000, "BIRD " BIRD_VERSION);
tm_format_datetime(tim, now); tm_format_datetime(tim, &config->tf_base, now);
cli_msg(-1011, "Router ID is %R", config->router_id); cli_msg(-1011, "Router ID is %R", config->router_id);
cli_msg(-1011, "Current server time is %s", tim); cli_msg(-1011, "Current server time is %s", tim);
tm_format_datetime(tim, boot_time); tm_format_datetime(tim, &config->tf_base, boot_time);
cli_msg(-1011, "Last reboot on %s", tim); cli_msg(-1011, "Last reboot on %s", tim);
tm_format_datetime(tim, config->load_time); tm_format_datetime(tim, &config->tf_base, config->load_time);
cli_msg(-1011, "Last reconfiguration on %s", tim); cli_msg(-1011, "Last reconfiguration on %s", tim);
if (shutting_down) if (shutting_down)
cli_msg(13, "Shutdown in progress"); cli_msg(13, "Shutdown in progress");

View file

@ -730,18 +730,18 @@ proto_state_name(struct proto *p)
static void static void
proto_do_show(struct proto *p, int verbose) proto_do_show(struct proto *p, int verbose)
{ {
byte buf[256], reltime[TM_RELTIME_BUFFER_SIZE]; byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE];
buf[0] = 0; buf[0] = 0;
if (p->proto->get_status) if (p->proto->get_status)
p->proto->get_status(p, buf); p->proto->get_status(p, buf);
tm_format_reltime(reltime, p->last_state_change); tm_format_datetime(tbuf, &config->tf_proto, p->last_state_change);
cli_msg(-1002, "%-8s %-8s %-8s %-5s %-5s %s", cli_msg(-1002, "%-8s %-8s %-8s %-5s %-10s %s",
p->name, p->name,
p->proto->name, p->proto->name,
p->table->name, p->table->name,
proto_state_name(p), proto_state_name(p),
reltime, tbuf,
buf); buf);
if (verbose) if (verbose)
{ {
@ -782,7 +782,7 @@ proto_show(struct symbol *s, int verbose)
cli_msg(9002, "%s is not a protocol", s->name); cli_msg(9002, "%s is not a protocol", s->name);
return; return;
} }
cli_msg(-2002, "name proto table state since info"); cli_msg(-2002, "name proto table state since info");
if (s) if (s)
proto_do_show(((struct proto_config *)s->def)->proto, verbose); proto_do_show(((struct proto_config *)s->def)->proto, verbose);
else else

View file

@ -1114,11 +1114,11 @@ static void
rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa) rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa)
{ {
byte via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH+6]; byte via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH+6];
byte tm[TM_RELTIME_BUFFER_SIZE], info[256]; byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
rta *a = e->attrs; rta *a = e->attrs;
rt_format_via(e, via); rt_format_via(e, via);
tm_format_reltime(tm, e->lastmod); tm_format_datetime(tm, &config->tf_route, e->lastmod);
if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->gw)) if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->gw))
bsprintf(from, " from %I", a->from); bsprintf(from, " from %I", a->from);
else else

View file

@ -14,10 +14,12 @@ CF_HDR
CF_DECLS CF_DECLS
CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT) CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT)
CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, BASE)
%type <i> log_mask log_mask_list log_cat %type <i> log_mask log_mask_list log_cat
%type <g> log_file %type <g> log_file
%type <t> cfg_name %type <t> cfg_name
%type <tf> timeformat_which
CF_GRAMMAR CF_GRAMMAR
@ -75,7 +77,24 @@ mrtdump_base:
} }
; ;
CF_ADDTO(conf, timeformat_base)
timeformat_which:
ROUTE { $$ = &new_config->tf_route; }
| PROTOCOL { $$ = &new_config->tf_proto; }
| BASE { $$ = &new_config->tf_base; }
| LOG { $$ = &new_config->tf_log; }
timeformat_spec:
timeformat_which TEXT { *$1 = (struct timeformat){$2, NULL, 0}; }
| timeformat_which TEXT expr TEXT { *$1 = (struct timeformat){$2, $4, $3}; }
| timeformat_which ISO SHORT { *$1 = (struct timeformat){"%T", "%F", 20*3600}; }
| timeformat_which ISO LONG { *$1 = (struct timeformat){"%F %T", NULL, 0}; }
;
timeformat_base:
TIMEFORMAT timeformat_spec ';'
;
/* Unix specific commands */ /* Unix specific commands */

View file

@ -410,23 +410,22 @@ tm_parse_date(char *x)
return t; return t;
} }
/** static void
* tm_format_date - convert date to textual representation tm_format_reltime(char *x, struct tm *tm, bird_clock_t delta)
* @x: destination buffer of size %TM_DATE_BUFFER_SIZE
* @t: time
*
* This function formats the given relative time value @t to a textual
* date representation (dd-mm-yyyy) in real time..
*/
void
tm_format_date(char *x, bird_clock_t t)
{ {
struct tm *tm; static char *month_names[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
tm = localtime(&t); if (delta < 20*3600)
bsprintf(x, "%02d-%02d-%04d", tm->tm_mday, tm->tm_mon+1, tm->tm_year+1900); bsprintf(x, "%02d:%02d", tm->tm_hour, tm->tm_min);
else if (delta < 360*86400)
bsprintf(x, "%s%02d", month_names[tm->tm_mon], tm->tm_mday);
else
bsprintf(x, "%d", tm->tm_year+1900);
} }
#include "conf/conf.h"
/** /**
* tm_format_datetime - convert date and time to textual representation * tm_format_datetime - convert date and time to textual representation
* @x: destination buffer of size %TM_DATETIME_BUFFER_SIZE * @x: destination buffer of size %TM_DATETIME_BUFFER_SIZE
@ -436,39 +435,25 @@ tm_format_date(char *x, bird_clock_t t)
* date/time representation (dd-mm-yyyy hh:mm:ss) in real time. * date/time representation (dd-mm-yyyy hh:mm:ss) in real time.
*/ */
void void
tm_format_datetime(char *x, bird_clock_t t) tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t)
{ {
const char *fmt_used;
struct tm *tm; struct tm *tm;
bird_clock_t delta = now - t; bird_clock_t delta = now - t;
t = now_real - delta; t = now_real - delta;
tm = localtime(&t); tm = localtime(&t);
if (strftime(x, TM_DATETIME_BUFFER_SIZE, "%d-%m-%Y %H:%M:%S", tm) == TM_DATETIME_BUFFER_SIZE)
strcpy(x, "<too-long>");
}
/** if (fmt_spec->fmt1 == NULL)
* tm_format_reltime - convert date and time to relative textual representation return tm_format_reltime(x, tm, delta);
* @x: destination buffer of size %TM_RELTIME_BUFFER_SIZE
* @t: time
*
* This function formats the given relative time value @t to a short
* textual representation in real time, relative to the current time.
*/
void
tm_format_reltime(char *x, bird_clock_t t)
{
struct tm *tm;
static char *month_names[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
bird_clock_t delta = now - t; if ((fmt_spec->limit == 0) || (delta < fmt_spec->limit))
t = now_real - delta; fmt_used = fmt_spec->fmt1;
tm = localtime(&t);
if (delta < 20*3600)
bsprintf(x, "%02d:%02d", tm->tm_hour, tm->tm_min);
else if (delta < 360*86400)
bsprintf(x, "%s%02d", month_names[tm->tm_mon], tm->tm_mday);
else else
bsprintf(x, "%d", tm->tm_year+1900); fmt_used = fmt_spec->fmt2;
int rv = strftime(x, TM_DATETIME_BUFFER_SIZE, fmt_used, tm);
if (((rv == 0) && fmt_used[0]) || (rv == TM_DATETIME_BUFFER_SIZE))
strcpy(x, "<too-long>");
} }
/** /**

View file

@ -79,21 +79,13 @@ vlog(int class, char *msg, va_list args)
continue; continue;
if (l->fh) if (l->fh)
{ {
time_t now = time(NULL);
struct tm *tm = localtime(&now);
if (l->terminal_flag) if (l->terminal_flag)
fputs("bird: ", l->fh); fputs("bird: ", l->fh);
else else
{ {
fprintf(l->fh, "%02d-%02d-%04d %02d:%02d:%02d <%s> ", byte tbuf[TM_DATETIME_BUFFER_SIZE];
tm->tm_mday, tm_format_datetime(tbuf, &config->tf_log, now);
tm->tm_mon+1, fprintf(l->fh, "%s <%s> ", tbuf, class_names[class]);
tm->tm_year+1900,
tm->tm_hour,
tm->tm_min,
tm->tm_sec,
class_names[class]);
} }
fputs(buf, l->fh); fputs(buf, l->fh);
fputc('\n', l->fh); fputc('\n', l->fh);

View file

@ -33,14 +33,17 @@ void tm_dump_all(void);
extern bird_clock_t now; /* Relative, monotonic time in seconds */ extern bird_clock_t now; /* Relative, monotonic time in seconds */
extern bird_clock_t now_real; /* Time in seconds since fixed known epoch */ extern bird_clock_t now_real; /* Time in seconds since fixed known epoch */
struct timeformat {
char *fmt1, *fmt2;
bird_clock_t limit;
};
bird_clock_t tm_parse_date(char *); /* Convert date to bird_clock_t */ bird_clock_t tm_parse_date(char *); /* Convert date to bird_clock_t */
bird_clock_t tm_parse_datetime(char *); /* Convert date to bird_clock_t */ bird_clock_t tm_parse_datetime(char *); /* Convert date to bird_clock_t */
void tm_format_date(char *, bird_clock_t); /* Convert bird_clock_t to date */
#define TM_DATE_BUFFER_SIZE 12 /* Buffer size required by tm_format_date */ #define TM_DATETIME_BUFFER_SIZE 32 /* Buffer size required by tm_format_datetime */
void tm_format_datetime(char *, bird_clock_t); /* Convert bird_clock_t to date + time */ void
#define TM_DATETIME_BUFFER_SIZE 64 /* Buffer size required by tm_format_datetime */ tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t);
void tm_format_reltime(char *, bird_clock_t); /* Convert bird_clock_t to relative datetime string */
#define TM_RELTIME_BUFFER_SIZE 12 /* Buffer size required by tm_format_reltime */
#ifdef TIME_T_IS_64BIT #ifdef TIME_T_IS_64BIT
#define TIME_INFINITY 0x7fffffffffffffff #define TIME_INFINITY 0x7fffffffffffffff