diff --git a/samples/mustach.template b/samples/mustach.template index a569a15..3c0db39 100644 --- a/samples/mustach.template +++ b/samples/mustach.template @@ -14,7 +14,7 @@ Subnets:{{#subnets}} backup_percent: {{backup_percent}} status: {{status}} gettimeofday: {{gettimeofday}} - lease_file_mtime: {{lease_file_mtime}} + lease_file_epoch_mtime: {{lease_file_epoch_mtime}} {{/subnets}} Shared-networks:{{#shared-networks}} @@ -30,7 +30,7 @@ Shared-networks:{{#shared-networks}} backup_percent: {{backup_percent}} status: {{status}} gettimeofday: {{gettimeofday}} - lease_file_mtime: {{lease_file_mtime}} + lease_file_epoch_mtime: {{lease_file_epoch_mtime}} {{/shared-networks}} Summary:{{#summary}} @@ -46,5 +46,22 @@ Summary:{{#summary}} backup_percent: {{backup_percent}} status: {{status}} gettimeofday: {{gettimeofday}} - lease_file_mtime: {{lease_file_mtime}} + lease_file_epoch_mtime: {{lease_file_epoch_mtime}} {{/summary}} + +localtime: {{localtime}} +number_of_ranges: {{number_of_ranges}} +number_of_shared_networks: {{number_of_shared_networks}} +version: {{version}} + +conf_file_path: {{conf_file_path}} +conf_file_local_mtime: {{conf_file_local_mtime}} +conf_file_epoch_mtime: {{conf_file_epoch_mtime}} + +lease_file_path: {{lease_file_path}} +lease_file_local_mtime: {{lease_file_local_mtime}} +lease_file_epoch_mtime: {{lease_file_epoch_mtime}} + +template_file_path: {{template_file_path}} +template_file_local_mtime: {{template_file_local_mtime}} +template_file_epoch_mtime: {{template_file_epoch_mtime}} diff --git a/src/mustach-dhcpd-pools.c b/src/mustach-dhcpd-pools.c index 77b240b..a3a7127 100644 --- a/src/mustach-dhcpd-pools.c +++ b/src/mustach-dhcpd-pools.c @@ -45,12 +45,14 @@ #include #include #include +#include #include #include "close-stream.h" #include "dhcpd-pools.h" #include "error.h" #include "mustach.h" +#include "strftime.h" #include "xalloc.h" /*! \struct expl @@ -67,14 +69,109 @@ struct expl { static int must_enter(void *closure, const char *name); static int must_leave(void *closure); -/*! \brief This function can be called when mustach template is invalid. - * In such case either must_put_range or must_put_shnet is tried to call before - * must_enter. */ -static int must_put_err(void *closure __attribute__ ((unused)), - const char *name __attribute__ ((unused)), - int escape __attribute__ ((unused)), FILE *file __attribute__ ((unused))) +static void dp_time_tool(FILE *file, const char *path, int epoch) { - return MUSTACH_ERROR_SYSTEM; + time_t t; + + /* a file or now */ + if (path) { + struct stat st; + + stat(path, &st); + t = st.st_mtime; + } else + t = time(NULL); + /* epoc or iso time stamp */ + if (epoch) + fprintf(file, "%ld", t); + else { + char time_stamp[64]; + struct tm tm; + int len; + + localtime_r(&t, &tm); + len = snprintf(time_stamp, sizeof(time_stamp), "%4d-%.2d-%.2dT%02d:%02d:%02d", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + strftime(time_stamp + len, sizeof(time_stamp) - len, "%z", &tm); + fprintf(file, "%s", time_stamp); + } +} + +/*! \brief Template base level tag parser and printer. */ +static int must_put_base(void *closure, const char *name, int escape + __attribute__ ((unused)), FILE *file) +{ + struct expl *e = closure; + + if (!strcmp(name, "localtime")) { + dp_time_tool(file, NULL, 0); + return 0; + } + if (!strcmp(name, "number_of_ranges")) { + fprintf(file, "%u", e->state->num_ranges); + return 0; + } + if (!strcmp(name, "number_of_shared_networks")) { + static uint32_t num = 0xffffffff; + + if (num == 0xffffffff) { + /* Use of static num ensures this is done only once. */ + struct shared_network_t *shared_p; + + num = 0; + for (shared_p = e->state->shared_net_root->next; shared_p; + shared_p = shared_p->next) + num++; + } + fprintf(file, "%u", num); + return 0; + } + if (!strcmp(name, "version")) { + fprintf(file, "%s", PACKAGE_VERSION); + return 0; + } + /* lease file */ + if (!strcmp(name, "lease_file_path")) { + fprintf(file, "%s", e->state->dhcpdlease_file); + return 0; + } + if (!strcmp(name, "lease_file_local_mtime")) { + dp_time_tool(file, e->state->dhcpdlease_file, 0); + return 0; + } + if (!strcmp(name, "lease_file_epoch_mtime")) { + dp_time_tool(file, e->state->dhcpdlease_file, 1); + return 0; + } + /* conf file */ + if (!strcmp(name, "conf_file_path")) { + fprintf(file, "%s", e->state->dhcpdconf_file); + return 0; + } + if (!strcmp(name, "conf_file_local_mtime")) { + dp_time_tool(file, e->state->dhcpdconf_file, 0); + return 0; + } + if (!strcmp(name, "conf_file_epoch_mtime")) { + dp_time_tool(file, e->state->dhcpdconf_file, 1); + return 0; + } + /* template file */ + if (!strcmp(name, "template_file_path")) { + fprintf(file, "%s", e->state->mustach_template); + return 0; + } + if (!strcmp(name, "template_file_local_mtime")) { + dp_time_tool(file, e->state->mustach_template, 0); + return 0; + } + if (!strcmp(name, "template_file_epoch_mtime")) { + dp_time_tool(file, e->state->mustach_template, 1); + return 0; + } + error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected tag: %s", name); + return 1; } /*! \struct mustach_itf @@ -82,7 +179,7 @@ static int must_put_err(void *closure __attribute__ ((unused)), static struct mustach_itf itf = { .start = NULL, .enter = must_enter, - .put = must_put_err, + .put = must_put_base, .next = NULL, .leave = must_leave }; @@ -153,20 +250,15 @@ static int must_put_range(void *closure, const char *name, int escape return 0; } if (!strcmp(name, "gettimeofday")) { - struct timeval tp; - - gettimeofday(&tp, NULL); - fprintf(file, "%ld", tp.tv_sec); + dp_time_tool(file, NULL, 1); return 0; } - if (!strcmp(name, "lease_file_mtime")) { - struct stat st; - - stat(e->state->dhcpdlease_file, &st); - fprintf(file, "%ld", st.st_mtime); + if (!strcmp(name, "lease_file_epoch_mtime")) { + dp_time_tool(file, e->state->dhcpdlease_file, 1); return 0; } - return 0; + error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected tag: %s", name); + return 1; } /*! \brief Mustach shared networks aka {{#shared-networks}} tag parser and printer. */ @@ -222,20 +314,15 @@ static int must_put_shnet(void *closure, const char *name, int escape return 0; } if (!strcmp(name, "gettimeofday")) { - struct timeval tp; - - gettimeofday(&tp, NULL); - fprintf(file, "%ld", tp.tv_sec); + dp_time_tool(file, NULL, 1); return 0; } - if (!strcmp(name, "lease_file_mtime")) { - struct stat st; - - stat(e->state->dhcpdlease_file, &st); - fprintf(file, "%ld", st.st_mtime); + if (!strcmp(name, "lease_file_epoch_mtime")) { + dp_time_tool(file, e->state->dhcpdlease_file, 1); return 0; } - return 0; + error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected tag: %s", name); + return 1; } /*! \brief A function to move to next range when {{/subnets}} is encountered. */ @@ -302,7 +389,8 @@ static int must_enter(void *closure, const char *name) shnet_output_helper(e->state, &e->oh, e->shnet_p); return 1; } - return 0; + error(EXIT_FAILURE, 0, "mustach_dhcpd_pools: fmustach: unexpected tag: %s", name); + return 1; } /*! \brief Function that is called when all elements within a print loop are outputed. */ @@ -312,6 +400,7 @@ static int must_leave(void *closure) e->shnet_p = e->state->shared_net_root; e->range_p = e->state->ranges; + itf.put = must_put_base; return 0; } diff --git a/tests/expected/mustach b/tests/expected/mustach index 73358a8..dddecb0 100644 --- a/tests/expected/mustach +++ b/tests/expected/mustach @@ -114,6 +114,12 @@ Summary: backup_percent: 2 status: 0 + +number_of_ranges: 5 +number_of_shared_networks: 2 + + + --- skip ok --- Subnets: location: example1 @@ -189,3 +195,9 @@ Summary: backup_percent: 2 status: 0 + +number_of_ranges: 5 +number_of_shared_networks: 2 + + + diff --git a/tests/mustach b/tests/mustach index f99ef81..d893aae 100755 --- a/tests/mustach +++ b/tests/mustach @@ -8,14 +8,16 @@ if [ ! -d tests/outputs ]; then mkdir tests/outputs fi +remove='/gettimeofday:/d; /^localtime:/d; /^conf_file_/d; /lease_file_/d; /^template_file_/d; /^version:/d' + dhcpd-pools -c $top_srcdir/samples/dhcpd.conf -l $top_srcdir/samples/dhcpd.leases \ --mustach $top_srcdir/samples/mustach.template | - sed '/gettimeofday:/d; /lease_file_mtime:/d' >| tests/outputs/$IAM + sed "$remove" >| tests/outputs/$IAM echo "--- skip ok ---" >> tests/outputs/$IAM dhcpd-pools -c $top_srcdir/samples/dhcpd.conf -l $top_srcdir/samples/dhcpd.leases \ --mustach $top_srcdir/samples/mustach.template --skip=ok --warning 44 | - sed '/gettimeofday:/d; /lease_file_mtime:/d' >> tests/outputs/$IAM + sed "$remove" >> tests/outputs/$IAM diff -u $top_srcdir/tests/expected/$IAM tests/outputs/$IAM exit $?