Timers: Parse and format functions for microsecond times
Date/time output (e.g. in logs, show commands) can use %f to specify subsecond time. By default, millisecond precision is used in output.
This commit is contained in:
parent
025525266f
commit
f047271cb9
21 changed files with 244 additions and 193 deletions
|
@ -102,9 +102,9 @@ config_alloc(const char *name)
|
||||||
c->pool = p;
|
c->pool = p;
|
||||||
c->mem = l;
|
c->mem = l;
|
||||||
c->file_name = ndup;
|
c->file_name = ndup;
|
||||||
c->load_time = now;
|
c->load_time = current_time();
|
||||||
c->tf_route = c->tf_proto = (struct timeformat){"%T", "%F", 20*3600};
|
c->tf_route = c->tf_proto = TM_ISO_SHORT_MS;
|
||||||
c->tf_base = c->tf_log = (struct timeformat){"%F %T", NULL, 0};
|
c->tf_base = c->tf_log = TM_ISO_LONG_MS;
|
||||||
c->gr_wait = DEFAULT_GR_WAIT;
|
c->gr_wait = DEFAULT_GR_WAIT;
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
|
|
|
@ -57,7 +57,7 @@ struct config {
|
||||||
struct config *fallback; /* Link to regular config for CLI parsing */
|
struct config *fallback; /* Link to regular config for CLI parsing */
|
||||||
int obstacle_count; /* Number of items blocking freeing of this config */
|
int obstacle_count; /* Number of items blocking freeing of this config */
|
||||||
int shutdown; /* This is a pseudo-config for daemon shutdown */
|
int shutdown; /* This is a pseudo-config for daemon shutdown */
|
||||||
bird_clock_t load_time; /* When we've got this configuration */
|
btime load_time; /* When we've got this configuration */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Please don't use these variables in protocols. Use proto_config->global instead. */
|
/* Please don't use these variables in protocols. Use proto_config->global instead. */
|
||||||
|
|
|
@ -14,7 +14,7 @@ CF_HDR
|
||||||
#include "conf/conf.h"
|
#include "conf/conf.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
#include "lib/socket.h"
|
#include "lib/socket.h"
|
||||||
#include "sysdep/unix/timer.h"
|
#include "lib/timer.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
#include "nest/iface.h"
|
#include "nest/iface.h"
|
||||||
|
@ -60,7 +60,7 @@ CF_DECLS
|
||||||
struct lsadb_show_data *ld;
|
struct lsadb_show_data *ld;
|
||||||
struct iface *iface;
|
struct iface *iface;
|
||||||
void *g;
|
void *g;
|
||||||
bird_clock_t time;
|
btime time;
|
||||||
struct f_prefix px;
|
struct f_prefix px;
|
||||||
struct proto_spec ps;
|
struct proto_spec ps;
|
||||||
struct channel_limit cl;
|
struct channel_limit cl;
|
||||||
|
@ -81,7 +81,7 @@ CF_DECLS
|
||||||
|
|
||||||
%type <i> expr bool pxlen4
|
%type <i> expr bool pxlen4
|
||||||
%type <i32> expr_us
|
%type <i32> expr_us
|
||||||
%type <time> datetime
|
%type <time> time
|
||||||
%type <a> ipa
|
%type <a> ipa
|
||||||
%type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
|
%type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
|
||||||
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_
|
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_
|
||||||
|
@ -308,11 +308,11 @@ label_stack:
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
datetime:
|
time:
|
||||||
TEXT {
|
TEXT {
|
||||||
$$ = tm_parse_datetime($1);
|
$$ = tm_parse_time($1);
|
||||||
if (!$$)
|
if (!$$)
|
||||||
cf_error("Invalid date and time");
|
cf_error("Invalid date/time");
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -456,24 +456,26 @@ protocol rip {
|
||||||
used for other commands and <cf/log/ is used in a log file.
|
used for other commands and <cf/log/ is used in a log file.
|
||||||
|
|
||||||
"<m/format1/" is a format string using <it/strftime(3)/ notation (see
|
"<m/format1/" is a format string using <it/strftime(3)/ notation (see
|
||||||
<it/man strftime/ for details). <m/limit> and "<m/format2/" allow to
|
<it/man strftime/ for details). It is extended to support sub-second
|
||||||
specify the second format string for times in past deeper than <m/limit/
|
time part with variable precision (up to microseconds) using "%f"
|
||||||
seconds. There are few shorthands: <cf/iso long/ is a ISO 8601 date/time
|
conversion code (e.g., "%T.%3f" is hh:mm:ss.sss time). <m/limit/ and
|
||||||
format (YYYY-MM-DD hh:mm:ss) that can be also specified using <cf/"%F %T"/.
|
"<m/format2/" allow to specify the second format string for times in
|
||||||
|
past deeper than <m/limit/ seconds.
|
||||||
|
|
||||||
|
There are several 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"/. Similarly, <cf/iso long ms/ and <cf/iso long us/ are ISO 8601
|
||||||
|
date/time formats with millisecond or microsecond precision.
|
||||||
<cf/iso short/ is a variant of ISO 8601 that uses just the time format
|
<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
|
(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
|
format (YYYY-MM-DD) for far times. This is a shorthand for <cf/"%T"
|
||||||
<cf/"%T" 72000 "%F"/.
|
72000 "%F"/. And there are also <cf/iso short ms/ and <cf/iso short us/
|
||||||
|
high-precision variants of that.
|
||||||
|
|
||||||
By default, BIRD uses the <cf/iso short/ format for <cf/route/ and
|
By default, BIRD uses the <cf/iso short ms/ format for <cf/route/ and
|
||||||
<cf/protocol/ times, and the <cf/iso long/ format for <cf/base/ and
|
<cf/protocol/ times, and the <cf/iso long ms/ format for <cf/base/ and
|
||||||
<cf/log/ times.
|
<cf/log/ times.
|
||||||
|
|
||||||
In pre-1.4.0 versions, BIRD used 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 timeformats could be set by
|
|
||||||
<cf/old short/ and <cf/old long/ compatibility shorthands.
|
|
||||||
|
|
||||||
<tag><label id="opt-table">table <m/name/ [sorted]</tag>
|
<tag><label id="opt-table">table <m/name/ [sorted]</tag>
|
||||||
Create a new routing table. The default routing table is created
|
Create a new routing table. The default routing table is created
|
||||||
implicitly, other routing tables have to be added by this command.
|
implicitly, other routing tables have to be added by this command.
|
||||||
|
|
135
lib/timer.c
135
lib/timer.c
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
|
@ -222,3 +223,137 @@ timer_init(void)
|
||||||
timers_init(&main_timeloop, &root_pool);
|
timers_init(&main_timeloop, &root_pool);
|
||||||
timeloop_init_current();
|
timeloop_init_current();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tm_parse_time - parse a date and time
|
||||||
|
* @x: time string
|
||||||
|
*
|
||||||
|
* tm_parse_time() takes a textual representation of a date and time
|
||||||
|
* (yyyy-mm-dd[ hh:mm:ss[.sss]]) and converts it to the corresponding value of
|
||||||
|
* type &btime.
|
||||||
|
*/
|
||||||
|
btime
|
||||||
|
tm_parse_time(char *x)
|
||||||
|
{
|
||||||
|
struct tm tm;
|
||||||
|
int usec, n1, n2, n3, r;
|
||||||
|
|
||||||
|
r = sscanf(x, "%d-%d-%d%n %d:%d:%d%n.%d%n",
|
||||||
|
&tm.tm_year, &tm.tm_mon, &tm.tm_mday, &n1,
|
||||||
|
&tm.tm_hour, &tm.tm_min, &tm.tm_sec, &n2,
|
||||||
|
&usec, &n3);
|
||||||
|
|
||||||
|
if ((r == 3) && !x[n1])
|
||||||
|
tm.tm_hour = tm.tm_min = tm.tm_sec = usec = 0;
|
||||||
|
else if ((r == 6) && !x[n2])
|
||||||
|
usec = 0;
|
||||||
|
else if ((r == 7) && !x[n3])
|
||||||
|
{
|
||||||
|
/* Convert subsecond digits to proper precision */
|
||||||
|
int digits = n3 - n2 - 1;
|
||||||
|
if ((usec < 0) || (usec > 999999) || (digits < 1) || (digits > 6))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (digits++ < 6)
|
||||||
|
usec *= 10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
tm.tm_mon--;
|
||||||
|
tm.tm_year -= 1900;
|
||||||
|
s64 ts = mktime(&tm);
|
||||||
|
if ((ts == (s64) (time_t) -1) || (ts < 0) || (ts > ((s64) 1 << 40)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return ts S + usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tm_format_time - convert date and time to textual representation
|
||||||
|
* @x: destination buffer of size %TM_DATETIME_BUFFER_SIZE
|
||||||
|
* @fmt: specification of resulting textual representation of the time
|
||||||
|
* @t: time
|
||||||
|
*
|
||||||
|
* This function formats the given relative time value @t to a textual
|
||||||
|
* date/time representation (dd-mm-yyyy hh:mm:ss) in real time.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
tm_format_time(char *x, struct timeformat *fmt, btime t)
|
||||||
|
{
|
||||||
|
btime dt = current_time() - t;
|
||||||
|
btime rt = current_real_time() - dt;
|
||||||
|
int v1 = !fmt->limit || (dt < fmt->limit);
|
||||||
|
|
||||||
|
tm_format_real_time(x, v1 ? fmt->fmt1 : fmt->fmt2, rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Replace %f in format string with usec scaled to requested precision */
|
||||||
|
static int
|
||||||
|
strfusec(char *buf, int size, const char *fmt, uint usec)
|
||||||
|
{
|
||||||
|
char *str = buf;
|
||||||
|
int parity = 0;
|
||||||
|
|
||||||
|
while (*fmt)
|
||||||
|
{
|
||||||
|
if (!size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((fmt[0] == '%') && (!parity) &&
|
||||||
|
((fmt[1] == 'f') || (fmt[1] >= '1') && (fmt[1] <= '6') && (fmt[2] == 'f')))
|
||||||
|
{
|
||||||
|
int digits = (fmt[1] == 'f') ? 6 : (fmt[1] - '0');
|
||||||
|
uint d = digits, u = usec;
|
||||||
|
|
||||||
|
/* Convert microseconds to requested precision */
|
||||||
|
while (d++ < 6)
|
||||||
|
u /= 10;
|
||||||
|
|
||||||
|
int num = bsnprintf(str, size, "%0*u", digits, u);
|
||||||
|
if (num < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fmt += (fmt[1] == 'f') ? 2 : 3;
|
||||||
|
ADVANCE(str, size, num);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Handle '%%' expression */
|
||||||
|
parity = (*fmt == '%') ? !parity : 0;
|
||||||
|
*str++ = *fmt++;
|
||||||
|
size--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!size)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*str = 0;
|
||||||
|
return str - buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
tm_format_real_time(char *x, const char *fmt, btime t)
|
||||||
|
{
|
||||||
|
s64 t1 = t TO_S;
|
||||||
|
s64 t2 = t - t1 S;
|
||||||
|
|
||||||
|
time_t ts = t1;
|
||||||
|
struct tm tm;
|
||||||
|
if (!localtime_r(&ts, &tm))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
byte tbuf[TM_DATETIME_BUFFER_SIZE];
|
||||||
|
if (!strfusec(tbuf, TM_DATETIME_BUFFER_SIZE, fmt, t2))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (!strftime(x, TM_DATETIME_BUFFER_SIZE, tbuf, &tm))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
err:
|
||||||
|
strcpy(x, "<error>");
|
||||||
|
}
|
||||||
|
|
19
lib/timer.h
19
lib/timer.h
|
@ -105,4 +105,23 @@ void timers_fire(struct timeloop *loop);
|
||||||
void timer_init(void);
|
void timer_init(void);
|
||||||
|
|
||||||
|
|
||||||
|
struct timeformat {
|
||||||
|
char *fmt1, *fmt2;
|
||||||
|
btime limit;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TM_ISO_SHORT_S (struct timeformat){"%T", "%F", (s64) (20*3600) S_}
|
||||||
|
#define TM_ISO_SHORT_MS (struct timeformat){"%T.%3f", "%F", (s64) (20*3600) S_}
|
||||||
|
#define TM_ISO_SHORT_US (struct timeformat){"%T.%6f", "%F", (s64) (20*3600) S_}
|
||||||
|
|
||||||
|
#define TM_ISO_LONG_S (struct timeformat){"%F %T", NULL, 0}
|
||||||
|
#define TM_ISO_LONG_MS (struct timeformat){"%F %T.%3f", NULL, 0}
|
||||||
|
#define TM_ISO_LONG_US (struct timeformat){"%F %T.%6f", NULL, 0}
|
||||||
|
|
||||||
|
#define TM_DATETIME_BUFFER_SIZE 32 /* Buffer size required by tm_format_time() */
|
||||||
|
|
||||||
|
btime tm_parse_time(char *x);
|
||||||
|
void tm_format_time(char *x, struct timeformat *fmt, btime t);
|
||||||
|
void tm_format_real_time(char *x, const char *fmt, btime t);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -25,12 +25,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, &config->tf_base, now);
|
tm_format_time(tim, &config->tf_base, current_time());
|
||||||
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, &config->tf_base, boot_time TO_S);
|
tm_format_time(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->tf_base, config->load_time);
|
tm_format_time(tim, &config->tf_base, config->load_time);
|
||||||
cli_msg(-1011, "Last reconfiguration on %s", tim);
|
cli_msg(-1011, "Last reconfiguration on %s", tim);
|
||||||
|
|
||||||
graceful_restart_show_status();
|
graceful_restart_show_status();
|
||||||
|
|
|
@ -73,6 +73,7 @@ CF_KEYWORDS(ALGORITHM, KEYED, HMAC, MD5, SHA1, SHA256, SHA384, SHA512)
|
||||||
CF_KEYWORDS(PRIMARY, STATS, COUNT, BY, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE)
|
CF_KEYWORDS(PRIMARY, STATS, COUNT, BY, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE)
|
||||||
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
|
CF_KEYWORDS(LISTEN, BGP, V6ONLY, DUAL, ADDRESS, PORT, PASSWORDS, DESCRIPTION, SORTED)
|
||||||
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
|
CF_KEYWORDS(RELOAD, IN, OUT, MRTDUMP, MESSAGES, RESTRICT, MEMORY, IGP_METRIC, CLASS, DSCP)
|
||||||
|
CF_KEYWORDS(TIMEFORMAT, ISO, SHORT, LONG, ROUTE, PROTOCOL, BASE, LOG, S, MS, US)
|
||||||
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS)
|
CF_KEYWORDS(GRACEFUL, RESTART, WAIT, MAX, FLUSH, AS)
|
||||||
|
|
||||||
/* For r_args_channel */
|
/* For r_args_channel */
|
||||||
|
@ -295,6 +296,7 @@ limit_spec:
|
||||||
| OFF { $$ = (struct channel_limit){}; }
|
| OFF { $$ = (struct channel_limit){}; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
CF_ADDTO(conf, debug_default)
|
CF_ADDTO(conf, debug_default)
|
||||||
|
|
||||||
debug_default:
|
debug_default:
|
||||||
|
@ -304,6 +306,31 @@ debug_default:
|
||||||
|
|
||||||
/* MRTDUMP PROTOCOLS is in systep/unix/config.Y */
|
/* MRTDUMP PROTOCOLS is in systep/unix/config.Y */
|
||||||
|
|
||||||
|
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, (s64) $3 S_}; }
|
||||||
|
| timeformat_which ISO SHORT { *$1 = TM_ISO_SHORT_S; }
|
||||||
|
| timeformat_which ISO SHORT MS { *$1 = TM_ISO_SHORT_MS; }
|
||||||
|
| timeformat_which ISO SHORT US { *$1 = TM_ISO_SHORT_US; }
|
||||||
|
| timeformat_which ISO LONG { *$1 = TM_ISO_LONG_S; }
|
||||||
|
| timeformat_which ISO LONG MS { *$1 = TM_ISO_LONG_MS; }
|
||||||
|
| timeformat_which ISO LONG US { *$1 = TM_ISO_LONG_US; }
|
||||||
|
;
|
||||||
|
|
||||||
|
timeformat_base:
|
||||||
|
TIMEFORMAT timeformat_spec ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
/* Interface patterns */
|
/* Interface patterns */
|
||||||
|
|
||||||
iface_patt_node_init:
|
iface_patt_node_init:
|
||||||
|
@ -462,12 +489,12 @@ password_item_begin:
|
||||||
|
|
||||||
password_item_params:
|
password_item_params:
|
||||||
/* empty */ { }
|
/* empty */ { }
|
||||||
| GENERATE FROM datetime ';' password_item_params { this_p_item->genfrom = $3; }
|
| GENERATE FROM time ';' password_item_params { this_p_item->genfrom = $3; }
|
||||||
| GENERATE TO datetime ';' password_item_params { this_p_item->gento = $3; }
|
| GENERATE TO time ';' password_item_params { this_p_item->gento = $3; }
|
||||||
| ACCEPT FROM datetime ';' password_item_params { this_p_item->accfrom = $3; }
|
| ACCEPT FROM time ';' password_item_params { this_p_item->accfrom = $3; }
|
||||||
| ACCEPT TO datetime ';' password_item_params { this_p_item->accto = $3; }
|
| ACCEPT TO time ';' password_item_params { this_p_item->accto = $3; }
|
||||||
| FROM datetime ';' password_item_params { this_p_item->genfrom = this_p_item->accfrom = $2; }
|
| FROM time ';' password_item_params { this_p_item->genfrom = this_p_item->accfrom = $2; }
|
||||||
| TO datetime ';' password_item_params { this_p_item->gento = this_p_item->accto = $2; }
|
| TO time ';' password_item_params { this_p_item->gento = this_p_item->accto = $2; }
|
||||||
| ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); }
|
| ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); }
|
||||||
| ALGORITHM password_algorithm ';' password_item_params { this_p_item->alg = $2; }
|
| ALGORITHM password_algorithm ';' password_item_params { this_p_item->alg = $2; }
|
||||||
;
|
;
|
||||||
|
|
|
@ -19,12 +19,13 @@ password_find(list *l, int first_fit)
|
||||||
{
|
{
|
||||||
struct password_item *pi;
|
struct password_item *pi;
|
||||||
struct password_item *pf = NULL;
|
struct password_item *pf = NULL;
|
||||||
|
btime now_ = current_real_time();
|
||||||
|
|
||||||
if (l)
|
if (l)
|
||||||
{
|
{
|
||||||
WALK_LIST(pi, *l)
|
WALK_LIST(pi, *l)
|
||||||
{
|
{
|
||||||
if ((pi->genfrom < now_real) && (pi->gento > now_real))
|
if ((pi->genfrom < now_) && (pi->gento > now_))
|
||||||
{
|
{
|
||||||
if (first_fit)
|
if (first_fit)
|
||||||
return pi;
|
return pi;
|
||||||
|
@ -41,12 +42,13 @@ struct password_item *
|
||||||
password_find_by_id(list *l, uint id)
|
password_find_by_id(list *l, uint id)
|
||||||
{
|
{
|
||||||
struct password_item *pi;
|
struct password_item *pi;
|
||||||
|
btime now_ = current_real_time();
|
||||||
|
|
||||||
if (!l)
|
if (!l)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
WALK_LIST(pi, *l)
|
WALK_LIST(pi, *l)
|
||||||
if ((pi->id == id) && (pi->accfrom <= now_real) && (now_real < pi->accto))
|
if ((pi->id == id) && (pi->accfrom <= now_) && (now_ < pi->accto))
|
||||||
return pi;
|
return pi;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -56,12 +58,13 @@ struct password_item *
|
||||||
password_find_by_value(list *l, char *pass, uint size)
|
password_find_by_value(list *l, char *pass, uint size)
|
||||||
{
|
{
|
||||||
struct password_item *pi;
|
struct password_item *pi;
|
||||||
|
btime now_ = current_real_time();
|
||||||
|
|
||||||
if (!l)
|
if (!l)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
WALK_LIST(pi, *l)
|
WALK_LIST(pi, *l)
|
||||||
if (password_verify(pi, pass, size) && (pi->accfrom <= now_real) && (now_real < pi->accto))
|
if (password_verify(pi, pass, size) && (pi->accfrom <= now_) && (now_ < pi->accto))
|
||||||
return pi;
|
return pi;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -10,15 +10,13 @@
|
||||||
#ifndef PASSWORD_H
|
#ifndef PASSWORD_H
|
||||||
#define PASSWORD_H
|
#define PASSWORD_H
|
||||||
|
|
||||||
#include "sysdep/unix/timer.h"
|
|
||||||
|
|
||||||
struct password_item {
|
struct password_item {
|
||||||
node n;
|
node n;
|
||||||
char *password; /* Key data, null terminated */
|
char *password; /* Key data, null terminated */
|
||||||
uint length; /* Key length, without null */
|
uint length; /* Key length, without null */
|
||||||
uint id; /* Key ID */
|
uint id; /* Key ID */
|
||||||
uint alg; /* MAC algorithm */
|
uint alg; /* MAC algorithm */
|
||||||
bird_clock_t accfrom, accto, genfrom, gento;
|
btime accfrom, accto, genfrom, gento;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct password_item *last_password_item;
|
extern struct password_item *last_password_item;
|
||||||
|
|
10
nest/proto.c
10
nest/proto.c
|
@ -162,7 +162,7 @@ proto_add_channel(struct proto *p, struct channel_config *cf)
|
||||||
|
|
||||||
c->channel_state = CS_DOWN;
|
c->channel_state = CS_DOWN;
|
||||||
c->export_state = ES_DOWN;
|
c->export_state = ES_DOWN;
|
||||||
c->last_state_change = now;
|
c->last_state_change = current_time();
|
||||||
c->reloadable = 1;
|
c->reloadable = 1;
|
||||||
|
|
||||||
CALL(c->channel->init, c, cf);
|
CALL(c->channel->init, c, cf);
|
||||||
|
@ -341,7 +341,7 @@ channel_set_state(struct channel *c, uint state)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
c->channel_state = state;
|
c->channel_state = state;
|
||||||
c->last_state_change = now;
|
c->last_state_change = current_time();
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
|
@ -672,7 +672,7 @@ proto_init(struct proto_config *c, node *n)
|
||||||
struct proto *p = pr->init(c);
|
struct proto *p = pr->init(c);
|
||||||
|
|
||||||
p->proto_state = PS_DOWN;
|
p->proto_state = PS_DOWN;
|
||||||
p->last_state_change = now;
|
p->last_state_change = current_time();
|
||||||
insert_node(&p->n, n);
|
insert_node(&p->n, n);
|
||||||
|
|
||||||
p->event = ev_new(proto_pool);
|
p->event = ev_new(proto_pool);
|
||||||
|
@ -1500,7 +1500,7 @@ proto_notify_state(struct proto *p, uint state)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
p->proto_state = state;
|
p->proto_state = state;
|
||||||
p->last_state_change = now;
|
p->last_state_change = current_time();
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
|
@ -1631,7 +1631,7 @@ proto_cmd_show(struct proto *p, uint verbose, int cnt)
|
||||||
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_datetime(tbuf, &config->tf_proto, p->last_state_change);
|
tm_format_time(tbuf, &config->tf_proto, p->last_state_change);
|
||||||
cli_msg(-1002, "%-8s %-8s %-8s %-5s %-10s %s",
|
cli_msg(-1002, "%-8s %-8s %-8s %-5s %-10s %s",
|
||||||
p->name,
|
p->name,
|
||||||
p->proto->name,
|
p->proto->name,
|
||||||
|
|
|
@ -159,7 +159,7 @@ struct proto {
|
||||||
byte down_sched; /* Shutdown is scheduled for later (PDS_*) */
|
byte down_sched; /* Shutdown is scheduled for later (PDS_*) */
|
||||||
byte down_code; /* Reason for shutdown (PDC_* codes) */
|
byte down_code; /* Reason for shutdown (PDC_* codes) */
|
||||||
u32 hash_key; /* Random key used for hashing of neighbors */
|
u32 hash_key; /* Random key used for hashing of neighbors */
|
||||||
bird_clock_t last_state_change; /* Time of last state transition */
|
btime last_state_change; /* Time of last state transition */
|
||||||
char *last_state_name_announced; /* Last state name we've announced to the user */
|
char *last_state_name_announced; /* Last state name we've announced to the user */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -508,7 +508,7 @@ struct channel {
|
||||||
u8 gr_lock; /* Graceful restart mechanism should wait for this channel */
|
u8 gr_lock; /* Graceful restart mechanism should wait for this channel */
|
||||||
u8 gr_wait; /* Route export to channel is postponed until graceful restart */
|
u8 gr_wait; /* Route export to channel is postponed until graceful restart */
|
||||||
|
|
||||||
bird_clock_t last_state_change; /* Time of last state transition */
|
btime last_state_change; /* Time of last state transition */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -159,8 +159,8 @@ typedef struct rtable {
|
||||||
* obstacle from this routing table.
|
* obstacle from this routing table.
|
||||||
*/
|
*/
|
||||||
struct event *rt_event; /* Routing table event */
|
struct event *rt_event; /* Routing table event */
|
||||||
|
btime gc_time; /* Time of last GC */
|
||||||
int gc_counter; /* Number of operations since last GC */
|
int gc_counter; /* Number of operations since last GC */
|
||||||
bird_clock_t gc_time; /* Time of last GC */
|
|
||||||
byte prune_state; /* Table prune state, 1 -> scheduled, 2-> running */
|
byte prune_state; /* Table prune state, 1 -> scheduled, 2-> running */
|
||||||
byte hcu_scheduled; /* Hostcache update is scheduled */
|
byte hcu_scheduled; /* Hostcache update is scheduled */
|
||||||
byte nhu_state; /* Next Hop Update state */
|
byte nhu_state; /* Next Hop Update state */
|
||||||
|
@ -213,7 +213,7 @@ typedef struct rte {
|
||||||
byte flags; /* Flags (REF_...) */
|
byte flags; /* Flags (REF_...) */
|
||||||
byte pflags; /* Protocol-specific flags */
|
byte pflags; /* Protocol-specific flags */
|
||||||
word pref; /* Route preference */
|
word pref; /* Route preference */
|
||||||
bird_clock_t lastmod; /* Last modified */
|
btime lastmod; /* Last modified */
|
||||||
union { /* Protocol-dependent data (metrics etc.) */
|
union { /* Protocol-dependent data (metrics etc.) */
|
||||||
#ifdef CONFIG_RIP
|
#ifdef CONFIG_RIP
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -39,7 +39,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
|
||||||
void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs);
|
void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs);
|
||||||
struct nexthop *nh;
|
struct nexthop *nh;
|
||||||
|
|
||||||
tm_format_datetime(tm, &config->tf_route, e->lastmod);
|
tm_format_time(tm, &config->tf_route, e->lastmod);
|
||||||
if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->nh.gw))
|
if (ipa_nonzero(a->from) && !ipa_equal(a->from, a->nh.gw))
|
||||||
bsprintf(from, " from %I", a->from);
|
bsprintf(from, " from %I", a->from);
|
||||||
else
|
else
|
||||||
|
|
|
@ -1173,7 +1173,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
new->lastmod = now;
|
new->lastmod = current_time();
|
||||||
|
|
||||||
/* Log the route change */
|
/* Log the route change */
|
||||||
if (p->debug & D_ROUTES)
|
if (p->debug & D_ROUTES)
|
||||||
|
@ -1201,7 +1201,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src)
|
||||||
|
|
||||||
if (!net->routes &&
|
if (!net->routes &&
|
||||||
(table->gc_counter++ >= table->config->gc_max_ops) &&
|
(table->gc_counter++ >= table->config->gc_max_ops) &&
|
||||||
(table->gc_time + table->config->gc_min_time <= now))
|
(table->gc_time + table->config->gc_min_time <= current_time()))
|
||||||
rt_schedule_prune(table);
|
rt_schedule_prune(table);
|
||||||
|
|
||||||
if (old_ok && p->rte_remove)
|
if (old_ok && p->rte_remove)
|
||||||
|
@ -1497,7 +1497,7 @@ rte_dump(rte *e)
|
||||||
{
|
{
|
||||||
net *n = e->net;
|
net *n = e->net;
|
||||||
debug("%-1N ", n->n.addr);
|
debug("%-1N ", n->n.addr);
|
||||||
debug("KF=%02x PF=%02x pref=%d lm=%d ", n->n.flags, e->pflags, e->pref, now-e->lastmod);
|
debug("KF=%02x PF=%02x pref=%d ", n->n.flags, e->pflags, e->pref);
|
||||||
rta_dump(e->attrs);
|
rta_dump(e->attrs);
|
||||||
if (e->attrs->src->proto->proto->dump_attrs)
|
if (e->attrs->src->proto->proto->dump_attrs)
|
||||||
e->attrs->src->proto->proto->dump_attrs(e);
|
e->attrs->src->proto->proto->dump_attrs(e);
|
||||||
|
@ -1609,7 +1609,7 @@ rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf)
|
||||||
t->rt_event = ev_new(p);
|
t->rt_event = ev_new(p);
|
||||||
t->rt_event->hook = rt_event;
|
t->rt_event->hook = rt_event;
|
||||||
t->rt_event->data = t;
|
t->rt_event->data = t;
|
||||||
t->gc_time = now;
|
t->gc_time = current_time();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1708,7 +1708,7 @@ again:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tab->gc_counter = 0;
|
tab->gc_counter = 0;
|
||||||
tab->gc_time = now;
|
tab->gc_time = current_time();
|
||||||
|
|
||||||
/* state change 2->0, 3->1 */
|
/* state change 2->0, 3->1 */
|
||||||
tab->prune_state &= 1;
|
tab->prune_state &= 1;
|
||||||
|
|
|
@ -145,6 +145,7 @@ bfd_session_update_state(struct bfd_session *s, uint state, uint diag)
|
||||||
bfd_lock_sessions(p);
|
bfd_lock_sessions(p);
|
||||||
s->loc_state = state;
|
s->loc_state = state;
|
||||||
s->loc_diag = diag;
|
s->loc_diag = diag;
|
||||||
|
s->last_state_change = current_time();
|
||||||
|
|
||||||
notify = !NODE_VALID(&s->n);
|
notify = !NODE_VALID(&s->n);
|
||||||
if (notify)
|
if (notify)
|
||||||
|
@ -438,7 +439,7 @@ bfd_add_session(struct bfd_proto *p, ip_addr addr, ip_addr local, struct iface *
|
||||||
bfd_session_control_tx_timer(s, 1);
|
bfd_session_control_tx_timer(s, 1);
|
||||||
|
|
||||||
init_list(&s->request_list);
|
init_list(&s->request_list);
|
||||||
s->last_state_change = now;
|
s->last_state_change = current_time();
|
||||||
|
|
||||||
TRACE(D_EVENTS, "Session to %I added", s->addr);
|
TRACE(D_EVENTS, "Session to %I added", s->addr);
|
||||||
|
|
||||||
|
@ -879,9 +880,6 @@ bfd_notify_hook(sock *sk, uint len UNUSED)
|
||||||
diag = s->loc_diag;
|
diag = s->loc_diag;
|
||||||
bfd_unlock_sessions(p);
|
bfd_unlock_sessions(p);
|
||||||
|
|
||||||
/* FIXME: convert to btime and move to bfd_session_update_state() */
|
|
||||||
s->last_state_change = now;
|
|
||||||
|
|
||||||
s->notify_running = 1;
|
s->notify_running = 1;
|
||||||
WALK_LIST_DELSAFE(n, nn, s->request_list)
|
WALK_LIST_DELSAFE(n, nn, s->request_list)
|
||||||
bfd_request_notify(SKIP_BACK(struct bfd_request, n, n), state, diag);
|
bfd_request_notify(SKIP_BACK(struct bfd_request, n, n), state, diag);
|
||||||
|
@ -1105,7 +1103,7 @@ bfd_show_sessions(struct proto *P)
|
||||||
timeout = (MAX(s->req_min_rx_int, s->rem_min_tx_int) TO_MS) * s->rem_detect_mult;
|
timeout = (MAX(s->req_min_rx_int, s->rem_min_tx_int) TO_MS) * s->rem_detect_mult;
|
||||||
|
|
||||||
state = (state < 4) ? state : 0;
|
state = (state < 4) ? state : 0;
|
||||||
tm_format_datetime(tbuf, &config->tf_proto, s->last_state_change);
|
tm_format_time(tbuf, &config->tf_proto, s->last_state_change);
|
||||||
|
|
||||||
cli_msg(-1020, "%-25I %-10s %-10s %-10s %3u.%03u %3u.%03u",
|
cli_msg(-1020, "%-25I %-10s %-10s %-10s %3u.%03u %3u.%03u",
|
||||||
s->addr, ifname, bfd_state_names[state], tbuf,
|
s->addr, ifname, bfd_state_names[state], tbuf,
|
||||||
|
|
|
@ -144,7 +144,7 @@ struct bfd_session
|
||||||
timer2 *hold_timer; /* Timer for session down detection time */
|
timer2 *hold_timer; /* Timer for session down detection time */
|
||||||
|
|
||||||
list request_list; /* List of client requests (struct bfd_request) */
|
list request_list; /* List of client requests (struct bfd_request) */
|
||||||
bird_clock_t last_state_change; /* Time of last state change */
|
btime last_state_change; /* Time of last state change */
|
||||||
u8 notify_running; /* 1 if notify hooks are running */
|
u8 notify_running; /* 1 if notify hooks are running */
|
||||||
|
|
||||||
u8 rx_csn_known; /* Received crypto sequence number is known */
|
u8 rx_csn_known; /* Received crypto sequence number is known */
|
||||||
|
|
|
@ -14,8 +14,7 @@ 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, OLD, SHORT, LONG, BASE, NAME, CONFIRM, UNDO, CHECK, TIMEOUT)
|
CF_KEYWORDS(NAME, CONFIRM, UNDO, CHECK, TIMEOUT, DEBUG, LATENCY, LIMIT, WATCHDOG, WARNING)
|
||||||
CF_KEYWORDS(DEBUG, LATENCY, LIMIT, WATCHDOG, WARNING, TIMEOUT)
|
|
||||||
|
|
||||||
%type <i> log_mask log_mask_list log_cat cfg_timeout
|
%type <i> log_mask log_mask_list log_cat cfg_timeout
|
||||||
%type <g> log_file
|
%type <g> log_file
|
||||||
|
@ -85,29 +84,6 @@ 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_which OLD SHORT { *$1 = (struct timeformat){NULL, NULL, 0}; }
|
|
||||||
| timeformat_which OLD LONG { *$1 = (struct timeformat){"%d-%m-%Y %T", NULL, 0}; }
|
|
||||||
;
|
|
||||||
|
|
||||||
timeformat_base:
|
|
||||||
TIMEFORMAT timeformat_spec ';'
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
CF_ADDTO(conf, debug_unix)
|
CF_ADDTO(conf, debug_unix)
|
||||||
|
|
||||||
debug_unix:
|
debug_unix:
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "lib/timer.h"
|
#include "lib/timer.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
#include "nest/iface.h"
|
#include "nest/iface.h"
|
||||||
|
#include "conf/conf.h"
|
||||||
|
|
||||||
#include "sysdep/unix/unix.h"
|
#include "sysdep/unix/unix.h"
|
||||||
#include CONFIG_INCLUDE_SYSIO_H
|
#include CONFIG_INCLUDE_SYSIO_H
|
||||||
|
@ -385,102 +386,6 @@ tm_shot(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* tm_parse_datetime - parse a date and time
|
|
||||||
* @x: datetime string
|
|
||||||
*
|
|
||||||
* tm_parse_datetime() takes a textual representation of
|
|
||||||
* a date and time (dd-mm-yyyy hh:mm:ss)
|
|
||||||
* and converts it to the corresponding value of type &bird_clock_t.
|
|
||||||
*/
|
|
||||||
bird_clock_t
|
|
||||||
tm_parse_datetime(char *x)
|
|
||||||
{
|
|
||||||
struct tm tm;
|
|
||||||
int n;
|
|
||||||
time_t t;
|
|
||||||
|
|
||||||
if (sscanf(x, "%d-%d-%d %d:%d:%d%n", &tm.tm_mday, &tm.tm_mon, &tm.tm_year, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &n) != 6 || x[n])
|
|
||||||
return tm_parse_date(x);
|
|
||||||
tm.tm_mon--;
|
|
||||||
tm.tm_year -= 1900;
|
|
||||||
t = mktime(&tm);
|
|
||||||
if (t == (time_t) -1)
|
|
||||||
return 0;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* tm_parse_date - parse a date
|
|
||||||
* @x: date string
|
|
||||||
*
|
|
||||||
* tm_parse_date() takes a textual representation of a date (dd-mm-yyyy)
|
|
||||||
* and converts it to the corresponding value of type &bird_clock_t.
|
|
||||||
*/
|
|
||||||
bird_clock_t
|
|
||||||
tm_parse_date(char *x)
|
|
||||||
{
|
|
||||||
struct tm tm;
|
|
||||||
int n;
|
|
||||||
time_t t;
|
|
||||||
|
|
||||||
if (sscanf(x, "%d-%d-%d%n", &tm.tm_mday, &tm.tm_mon, &tm.tm_year, &n) != 3 || x[n])
|
|
||||||
return 0;
|
|
||||||
tm.tm_mon--;
|
|
||||||
tm.tm_year -= 1900;
|
|
||||||
tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
|
|
||||||
t = mktime(&tm);
|
|
||||||
if (t == (time_t) -1)
|
|
||||||
return 0;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
tm_format_reltime(char *x, struct tm *tm, bird_clock_t delta)
|
|
||||||
{
|
|
||||||
static char *month_names[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
||||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
|
||||||
|
|
||||||
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
|
|
||||||
bsprintf(x, "%d", tm->tm_year+1900);
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "conf/conf.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* tm_format_datetime - convert date and time to textual representation
|
|
||||||
* @x: destination buffer of size %TM_DATETIME_BUFFER_SIZE
|
|
||||||
* @fmt_spec: specification of resulting textual representation of the time
|
|
||||||
* @t: time
|
|
||||||
*
|
|
||||||
* This function formats the given relative time value @t to a textual
|
|
||||||
* date/time representation (dd-mm-yyyy hh:mm:ss) in real time.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t)
|
|
||||||
{
|
|
||||||
const char *fmt_used;
|
|
||||||
struct tm *tm;
|
|
||||||
bird_clock_t delta = now - t;
|
|
||||||
t = now_real - delta;
|
|
||||||
tm = localtime(&t);
|
|
||||||
|
|
||||||
if (fmt_spec->fmt1 == NULL)
|
|
||||||
return tm_format_reltime(x, tm, delta);
|
|
||||||
|
|
||||||
if ((fmt_spec->limit == 0) || (delta < fmt_spec->limit))
|
|
||||||
fmt_used = fmt_spec->fmt1;
|
|
||||||
else
|
|
||||||
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>");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Time clock
|
* Time clock
|
||||||
|
|
|
@ -120,7 +120,7 @@ log_commit(int class, buffer *buf)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
byte tbuf[TM_DATETIME_BUFFER_SIZE];
|
byte tbuf[TM_DATETIME_BUFFER_SIZE];
|
||||||
tm_format_datetime(tbuf, &config->tf_log, now);
|
tm_format_real_time(tbuf, config->tf_log.fmt1, current_real_time());
|
||||||
fprintf(l->fh, "%s <%s> ", tbuf, class_names[class]);
|
fprintf(l->fh, "%s <%s> ", tbuf, class_names[class]);
|
||||||
}
|
}
|
||||||
fputs(buf->start, l->fh);
|
fputs(buf->start, l->fh);
|
||||||
|
|
|
@ -45,18 +45,6 @@ static inline timer * tm_new_set(pool *p, void (*hook)(timer *), void *data, uin
|
||||||
{ return tm2_new_init(p, hook, data, rec S_, rand S_); }
|
{ return tm2_new_init(p, hook, data, rec S_, rand S_); }
|
||||||
|
|
||||||
|
|
||||||
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_datetime(char *); /* Convert date to bird_clock_t */
|
|
||||||
|
|
||||||
#define TM_DATETIME_BUFFER_SIZE 32 /* Buffer size required by tm_format_datetime */
|
|
||||||
void
|
|
||||||
tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t);
|
|
||||||
|
|
||||||
#define TIME_INFINITY ((s64) 0x7fffffffffffffff)
|
#define TIME_INFINITY ((s64) 0x7fffffffffffffff)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue