From e269f09438ad1bfaef044c5781615cba45ab7690 Mon Sep 17 00:00:00 2001
From: Lukas Fleischer <calcurse@cryptocrack.de>
Date: Thu, 22 Nov 2012 22:23:58 +0100
Subject: Replace localtime() with localtime_r()

Since the result of localtime() is stored in a statically allocated
structure, data was overwritten when a context switch occurred during
(or shortly after) the execution of localtime(), potentially resulting
in critical data corruption. BUG#7 and BUG#8 are likely related.

This patch converts all usages of localtime() with localtime_r(), which
is thread-safe.

Reported-by: Baptiste Jonglez <baptiste@jonglez.org>
Reported-by: Erik Saule <esaule@bmi.osu.edu>
Signed-off-by: Lukas Fleischer <calcurse@cryptocrack.de>
---
 src/apoint.c   | 29 ++++++++++-----------
 src/args.c     | 10 ++++----
 src/calendar.c | 44 +++++++++++++++----------------
 src/day.c      |  6 ++---
 src/event.c    | 13 ++++------
 src/io.c       |  6 ++---
 src/notify.c   |  8 +++---
 src/pcal.c     |  2 +-
 src/recur.c    | 60 +++++++++++++++++++++----------------------
 src/utils.c    | 81 ++++++++++++++++++++++++++++++++++------------------------
 10 files changed, 133 insertions(+), 126 deletions(-)

(limited to 'src')

diff --git a/src/apoint.c b/src/apoint.c
index 1483beb..03ccb36 100644
--- a/src/apoint.c
+++ b/src/apoint.c
@@ -337,39 +337,39 @@ unsigned apoint_inday(struct apoint *i, long start)
 
 void apoint_sec2str(struct apoint *o, long day, char *start, char *end)
 {
-  struct tm *lt;
+  struct tm lt;
   time_t t;
 
   if (o->start < day)
     strncpy(start, "..:..", 6);
   else {
     t = o->start;
-    lt = localtime(&t);
-    snprintf(start, HRMIN_SIZE, "%02u:%02u", lt->tm_hour, lt->tm_min);
+    localtime_r(&t, &lt);
+    snprintf(start, HRMIN_SIZE, "%02u:%02u", lt.tm_hour, lt.tm_min);
   }
   if (o->start + o->dur > day + DAYINSEC)
     strncpy(end, "..:..", 6);
   else {
     t = o->start + o->dur;
-    lt = localtime(&t);
-    snprintf(end, HRMIN_SIZE, "%02u:%02u", lt->tm_hour, lt->tm_min);
+    localtime_r(&t, &lt);
+    snprintf(end, HRMIN_SIZE, "%02u:%02u", lt.tm_hour, lt.tm_min);
   }
 }
 
 void apoint_write(struct apoint *o, FILE * f)
 {
-  struct tm *lt;
+  struct tm lt;
   time_t t;
 
   t = o->start;
-  lt = localtime(&t);
-  fprintf(f, "%02u/%02u/%04u @ %02u:%02u", lt->tm_mon + 1, lt->tm_mday,
-          1900 + lt->tm_year, lt->tm_hour, lt->tm_min);
+  localtime_r(&t, &lt);
+  fprintf(f, "%02u/%02u/%04u @ %02u:%02u", lt.tm_mon + 1, lt.tm_mday,
+          1900 + lt.tm_year, lt.tm_hour, lt.tm_min);
 
   t = o->start + o->dur;
-  lt = localtime(&t);
-  fprintf(f, " -> %02u/%02u/%04u @ %02u:%02u ", lt->tm_mon + 1, lt->tm_mday,
-          1900 + lt->tm_year, lt->tm_hour, lt->tm_min);
+  localtime_r(&t, &lt);
+  fprintf(f, " -> %02u/%02u/%04u @ %02u:%02u ", lt.tm_mon + 1, lt.tm_mday,
+          1900 + lt.tm_year, lt.tm_hour, lt.tm_min);
 
   if (o->note != NULL)
     fprintf(f, ">%s ", o->note);
@@ -386,10 +386,7 @@ struct apoint *apoint_scan(FILE * f, struct tm start, struct tm end, char state,
                            char *note)
 {
   char buf[BUFSIZ], *newline;
-  time_t tstart, tend, t;
-
-  t = time(NULL);
-  localtime(&t);
+  time_t tstart, tend;
 
   /* Read the appointment description */
   if (!fgets(buf, sizeof buf, f))
diff --git a/src/args.c b/src/args.c
index c87a970..01f24e9 100644
--- a/src/args.c
+++ b/src/args.c
@@ -271,11 +271,11 @@ static void arg_print_date(long date)
 {
   char date_str[BUFSIZ];
   time_t t;
-  struct tm *lt;
+  struct tm lt;
 
   t = date;
-  lt = localtime(&t);
-  strftime(date_str, BUFSIZ, conf.output_datefmt, lt);
+  localtime_r(&t, &lt);
+  strftime(date_str, BUFSIZ, conf.output_datefmt, &lt);
   fputs(date_str, stdout);
   fputs(":\n", stdout);
 }
@@ -469,7 +469,7 @@ date_arg(const char *ddate, int add_line, const char *fmt_apt,
      * to format the output correctly.
      */
     timer = time(NULL);
-    t = *localtime(&timer);
+    localtime_r(&timer, &t);
     display_app(&t, numdays, add_line, fmt_apt, fmt_rapt, fmt_ev, fmt_rev,
                 regex);
   } else {                      /* a date was entered */
@@ -515,7 +515,7 @@ date_arg_extended(const char *startday, const char *range, int add_line,
       numdays = atoi(range);
   }
   timer = time(NULL);
-  t = *localtime(&timer);
+  localtime_r(&timer, &t);
   if (startday != NULL) {
     if (parse_date(startday, conf.input_datefmt, (int *)&t.tm_year,
                    (int *)&t.tm_mon, (int *)&t.tm_mday, NULL)) {
diff --git a/src/calendar.c b/src/calendar.c
index a157caa..48ac84d 100644
--- a/src/calendar.c
+++ b/src/calendar.c
@@ -140,15 +140,15 @@ void calendar_stop_date_thread(void)
 void calendar_set_current_date(void)
 {
   time_t timer;
-  struct tm *tm;
+  struct tm tm;
 
   timer = time(NULL);
-  tm = localtime(&timer);
+  localtime_r(&timer, &tm);
 
   pthread_mutex_lock(&date_thread_mutex);
-  today.dd = tm->tm_mday;
-  today.mm = tm->tm_mon + 1;
-  today.yyyy = tm->tm_year + 1900;
+  today.dd = tm.tm_mday;
+  today.mm = tm.tm_mon + 1;
+  today.yyyy = tm.tm_year + 1900;
   pthread_mutex_unlock(&date_thread_mutex);
 }
 
@@ -684,16 +684,16 @@ void calendar_move(enum move move, int count)
 long calendar_start_of_year(void)
 {
   time_t timer;
-  struct tm *tm;
+  struct tm tm;
 
   timer = time(NULL);
-  tm = localtime(&timer);
-  tm->tm_mon = 0;
-  tm->tm_mday = 1;
-  tm->tm_hour = 0;
-  tm->tm_min = 0;
-  tm->tm_sec = 0;
-  timer = mktime(tm);
+  localtime_r(&timer, &tm);
+  tm.tm_mon = 0;
+  tm.tm_mday = 1;
+  tm.tm_hour = 0;
+  tm.tm_min = 0;
+  tm.tm_sec = 0;
+  timer = mktime(&tm);
 
   return (long)timer;
 }
@@ -701,17 +701,17 @@ long calendar_start_of_year(void)
 long calendar_end_of_year(void)
 {
   time_t timer;
-  struct tm *tm;
+  struct tm tm;
 
   timer = time(NULL);
-  tm = localtime(&timer);
-  tm->tm_mon = 0;
-  tm->tm_mday = 1;
-  tm->tm_hour = 0;
-  tm->tm_min = 0;
-  tm->tm_sec = 0;
-  tm->tm_year++;
-  timer = mktime(tm);
+  localtime_r(&timer, &tm);
+  tm.tm_mon = 0;
+  tm.tm_mday = 1;
+  tm.tm_hour = 0;
+  tm.tm_min = 0;
+  tm.tm_sec = 0;
+  tm.tm_year++;
+  timer = mktime(&tm);
 
   return (long)(timer - 1);
 }
diff --git a/src/day.c b/src/day.c
index e013df5..29c03e4 100644
--- a/src/day.c
+++ b/src/day.c
@@ -730,7 +730,7 @@ static void update_rept(struct rpt **rpt, const long start)
       newuntil = 0;
       date_entered = 1;
     } else {
-      struct tm *lt;
+      struct tm lt;
       time_t t;
       struct date new_date;
       int newmonth, newday, newyear;
@@ -738,11 +738,11 @@ static void update_rept(struct rpt **rpt, const long start)
       if (parse_date(timstr, conf.input_datefmt, &newyear, &newmonth,
                      &newday, calendar_get_slctd_day())) {
         t = start;
-        lt = localtime(&t);
+        localtime_r(&t, &lt);
         new_date.dd = newday;
         new_date.mm = newmonth;
         new_date.yyyy = newyear;
-        newuntil = date2sec(new_date, lt->tm_hour, lt->tm_min);
+        newuntil = date2sec(new_date, lt.tm_hour, lt.tm_min);
         if (newuntil < start) {
           status_mesg(msg_wrong_time, msg_enter);
           wgetch(win[STA].p);
diff --git a/src/event.c b/src/event.c
index f460ded..203af44 100644
--- a/src/event.c
+++ b/src/event.c
@@ -112,13 +112,13 @@ unsigned event_inday(struct event *i, long start)
 /* Write to file the event in user-friendly format */
 void event_write(struct event *o, FILE * f)
 {
-  struct tm *lt;
+  struct tm lt;
   time_t t;
 
   t = o->day;
-  lt = localtime(&t);
-  fprintf(f, "%02u/%02u/%04u [%d] ", lt->tm_mon + 1, lt->tm_mday,
-          1900 + lt->tm_year, o->id);
+  localtime_r(&t, &lt);
+  fprintf(f, "%02u/%02u/%04u [%d] ", lt.tm_mon + 1, lt.tm_mday,
+          1900 + lt.tm_year, o->id);
   if (o->note != NULL)
     fprintf(f, ">%s ", o->note);
   fprintf(f, "%s\n", o->mesg);
@@ -128,10 +128,7 @@ void event_write(struct event *o, FILE * f)
 struct event *event_scan(FILE * f, struct tm start, int id, char *note)
 {
   char buf[BUFSIZ], *nl;
-  time_t tstart, t;
-
-  t = time(NULL);
-  localtime(&t);
+  time_t tstart;
 
   /* Read the event description */
   if (!fgets(buf, sizeof buf, f))
diff --git a/src/io.c b/src/io.c
index 9bffe1a..0af8b02 100644
--- a/src/io.c
+++ b/src/io.c
@@ -454,7 +454,7 @@ void io_load_app(void)
 {
   FILE *data_file;
   int c, is_appointment, is_event, is_recursive;
-  struct tm start, end, until, *lt;
+  struct tm start, end, until, lt;
   llist_t exc;
   time_t t;
   int id = 0;
@@ -463,8 +463,8 @@ void io_load_app(void)
   char note[MAX_NOTESIZ + 1], *notep;
 
   t = time(NULL);
-  lt = localtime(&t);
-  start = end = until = *lt;
+  localtime_r(&t, &lt);
+  start = end = until = lt;
 
   data_file = fopen(path_apts, "r");
   EXIT_IF(data_file == NULL, _("failed to open appointment file"));
diff --git a/src/notify.c b/src/notify.c
index a057c2f..10bc0f7 100644
--- a/src/notify.c
+++ b/src/notify.c
@@ -310,18 +310,18 @@ static void *notify_main_thread(void *arg)
   const unsigned check_app = MININSEC;
   int elapse = 0;
   int got_app;
-  struct tm *ntime;
+  struct tm ntime;
   time_t ntimer;
 
   elapse = 0;
 
   for (;;) {
     ntimer = time(NULL);
-    ntime = localtime(&ntimer);
+    localtime_r(&ntimer, &ntime);
     pthread_mutex_lock(&notify.mutex);
     pthread_mutex_lock(&nbar.mutex);
-    strftime(notify.time, NOTIFY_FIELD_LENGTH, nbar.timefmt, ntime);
-    strftime(notify.date, NOTIFY_FIELD_LENGTH, nbar.datefmt, ntime);
+    strftime(notify.time, NOTIFY_FIELD_LENGTH, nbar.timefmt, &ntime);
+    strftime(notify.date, NOTIFY_FIELD_LENGTH, nbar.datefmt, &ntime);
     pthread_mutex_unlock(&nbar.mutex);
     pthread_mutex_unlock(&notify.mutex);
     notify_update_bar();
diff --git a/src/pcal.c b/src/pcal.c
index c4f731d..4c00ddc 100644
--- a/src/pcal.c
+++ b/src/pcal.c
@@ -64,7 +64,7 @@ foreach_date_dump(const long date_end, struct rpt *rpt, llist_t * exc,
   time_t t;
 
   t = item_first_date;
-  lt = *localtime(&t);
+  localtime_r(&t, &lt);
   lt.tm_hour = lt.tm_min = lt.tm_sec = 0;
   lt.tm_isdst = -1;
   date = mktime(&lt);
diff --git a/src/recur.c b/src/recur.c
index e8ddffc..5c32bca 100644
--- a/src/recur.c
+++ b/src/recur.c
@@ -318,17 +318,17 @@ int recur_char2def(char type)
 static void recur_write_exc(llist_t * lexc, FILE * f)
 {
   llist_item_t *i;
-  struct tm *lt;
+  struct tm lt;
   time_t t;
   int st_mon, st_day, st_year;
 
   LLIST_FOREACH(lexc, i) {
     struct excp *exc = LLIST_GET_DATA(i);
     t = exc->st;
-    lt = localtime(&t);
-    st_mon = lt->tm_mon + 1;
-    st_day = lt->tm_mday;
-    st_year = lt->tm_year + 1900;
+    localtime_r(&t, &lt);
+    st_mon = lt.tm_mon + 1;
+    st_day = lt.tm_mday;
+    st_year = lt.tm_year + 1900;
     fprintf(f, " !%02u/%02u/%04u", st_mon, st_day, st_year);
   }
 }
@@ -415,27 +415,27 @@ struct recur_event *recur_event_scan(FILE * f, struct tm start, int id,
 /* Writting of a recursive appointment into file. */
 void recur_apoint_write(struct recur_apoint *o, FILE * f)
 {
-  struct tm *lt;
+  struct tm lt;
   time_t t;
 
   t = o->start;
-  lt = localtime(&t);
-  fprintf(f, "%02u/%02u/%04u @ %02u:%02u", lt->tm_mon + 1, lt->tm_mday,
-          1900 + lt->tm_year, lt->tm_hour, lt->tm_min);
+  localtime_r(&t, &lt);
+  fprintf(f, "%02u/%02u/%04u @ %02u:%02u", lt.tm_mon + 1, lt.tm_mday,
+          1900 + lt.tm_year, lt.tm_hour, lt.tm_min);
 
   t = o->start + o->dur;
-  lt = localtime(&t);
-  fprintf(f, " -> %02u/%02u/%04u @ %02u:%02u", lt->tm_mon + 1, lt->tm_mday,
-          1900 + lt->tm_year, lt->tm_hour, lt->tm_min);
+  localtime_r(&t, &lt);
+  fprintf(f, " -> %02u/%02u/%04u @ %02u:%02u", lt.tm_mon + 1, lt.tm_mday,
+          1900 + lt.tm_year, lt.tm_hour, lt.tm_min);
 
   t = o->rpt->until;
   if (t == 0) {                 /* We have an endless recurrent appointment. */
     fprintf(f, " {%d%c", o->rpt->freq, recur_def2char(o->rpt->type));
   } else {
-    lt = localtime(&t);
+    localtime_r(&t, &lt);
     fprintf(f, " {%d%c -> %02u/%02u/%04u", o->rpt->freq,
-            recur_def2char(o->rpt->type), lt->tm_mon + 1, lt->tm_mday,
-            1900 + lt->tm_year);
+            recur_def2char(o->rpt->type), lt.tm_mon + 1, lt.tm_mday,
+            1900 + lt.tm_year);
   }
   recur_write_exc(&o->exc, f);
   fputs("} ", f);
@@ -451,25 +451,25 @@ void recur_apoint_write(struct recur_apoint *o, FILE * f)
 /* Writting of a recursive event into file. */
 void recur_event_write(struct recur_event *o, FILE * f)
 {
-  struct tm *lt;
+  struct tm lt;
   time_t t;
   int st_mon, st_day, st_year;
   int end_mon, end_day, end_year;
 
   t = o->day;
-  lt = localtime(&t);
-  st_mon = lt->tm_mon + 1;
-  st_day = lt->tm_mday;
-  st_year = lt->tm_year + 1900;
+  localtime_r(&t, &lt);
+  st_mon = lt.tm_mon + 1;
+  st_day = lt.tm_mday;
+  st_year = lt.tm_year + 1900;
   t = o->rpt->until;
   if (t == 0) {                 /* We have an endless recurrent event. */
     fprintf(f, "%02u/%02u/%04u [%d] {%d%c", st_mon, st_day, st_year, o->id,
             o->rpt->freq, recur_def2char(o->rpt->type));
   } else {
-    lt = localtime(&t);
-    end_mon = lt->tm_mon + 1;
-    end_day = lt->tm_mday;
-    end_year = lt->tm_year + 1900;
+    localtime_r(&t, &lt);
+    end_mon = lt.tm_mon + 1;
+    end_day = lt.tm_mday;
+    end_year = lt.tm_year + 1900;
     fprintf(f, "%02u/%02u/%04u [%d] {%d%c -> %02u/%02u/%04u", st_mon,
             st_day, st_year, o->id, o->rpt->freq,
             recur_def2char(o->rpt->type), end_mon, end_day, end_year);
@@ -581,10 +581,10 @@ recur_item_find_occurrence(long item_start, long item_dur, llist_t * item_exc,
     return 0;
 
   t = day_start;
-  lt_day = *localtime(&t);
+  localtime_r(&t, &lt_day);
 
   t = item_start;
-  lt_item = *localtime(&t);
+  localtime_r(&t, &lt_item);
 
   lt_item_day = lt_item;
   lt_item_day.tm_sec = lt_item_day.tm_min = lt_item_day.tm_hour = 0;
@@ -632,7 +632,7 @@ recur_item_find_occurrence(long item_start, long item_dur, llist_t * item_exc,
   if (rpt_until != 0 && t > rpt_until)
     return 0;
 
-  lt_item_day = *localtime(&t);
+  localtime_r(&t, &lt_item_day);
   diff = diff_days(lt_item_day, lt_day);
 
   if (diff <= span) {
@@ -791,7 +791,7 @@ recur_apoint_erase(long start, unsigned num, unsigned delete_whole,
  */
 void recur_repeat_item(void)
 {
-  struct tm *lt;
+  struct tm lt;
   time_t t;
   int date_entered = 0;
   int year = 0, month = 0, day = 0;
@@ -876,11 +876,11 @@ void recur_repeat_item(void)
         if (parse_date(user_input, conf.input_datefmt,
                        &year, &month, &day, calendar_get_slctd_day())) {
           t = p->start;
-          lt = localtime(&t);
+          localtime_r(&t, &lt);
           until_date.dd = day;
           until_date.mm = month;
           until_date.yyyy = year;
-          until = date2sec(until_date, lt->tm_hour, lt->tm_min);
+          until = date2sec(until_date, lt.tm_hour, lt.tm_min);
           if (until < p->start) {
             status_mesg(mesg_older, wrong_type_2);
             wgetch(win[STA].p);
diff --git a/src/utils.c b/src/utils.c
index 14de867..da8eade 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -337,18 +337,26 @@ long get_item_time(long date)
 
 int get_item_hour(long date)
 {
-  return (localtime((time_t *) & date))->tm_hour;
+  struct tm lt;
+
+  localtime_r((time_t *)&date, &lt);
+  return lt.tm_hour;
 }
 
 int get_item_min(long date)
 {
-  return (localtime((time_t *) & date))->tm_min;
+  struct tm lt;
+
+  localtime_r((time_t *)&date, &lt);
+  return lt.tm_min;
 }
 
 long date2sec(struct date day, unsigned hour, unsigned min)
 {
   time_t t = now();
-  struct tm start = *(localtime(&t));
+  struct tm start;
+
+  localtime_r(&t, &start);
 
   start.tm_mon = day.mm - 1;
   start.tm_mday = day.dd;
@@ -367,14 +375,14 @@ long date2sec(struct date day, unsigned hour, unsigned min)
 /* Return a string containing the date, given a date in seconds. */
 char *date_sec2date_str(long sec, const char *datefmt)
 {
-  struct tm *lt;
+  struct tm lt;
   char *datestr = (char *)mem_calloc(BUFSIZ, sizeof(char));
 
   if (sec == 0)
     strncpy(datestr, "0", BUFSIZ);
   else {
-    lt = localtime((time_t *) & sec);
-    strftime(datestr, BUFSIZ, datefmt, lt);
+    localtime_r((time_t *)&sec, &lt);
+    strftime(datestr, BUFSIZ, datefmt, &lt);
   }
 
   return datestr;
@@ -389,8 +397,9 @@ void date_sec2date_fmt(long sec, const char *fmt, char *datef)
   setlocale (LC_ALL, "C");
 #endif
 
-  struct tm *lt = localtime((time_t *)&sec);
-  strftime(datef, BUFSIZ, fmt, lt);
+  struct tm lt;
+  localtime_r((time_t *)&sec, &lt);
+  strftime(datef, BUFSIZ, fmt, &lt);
 
 #if ENABLE_NLS
   setlocale (LC_ALL, locale_old);
@@ -403,15 +412,15 @@ void date_sec2date_fmt(long sec, const char *fmt, char *datef)
  */
 long date_sec_change(long date, int delta_month, int delta_day)
 {
-  struct tm *lt;
+  struct tm lt;
   time_t t;
 
   t = date;
-  lt = localtime(&t);
-  lt->tm_mon += delta_month;
-  lt->tm_mday += delta_day;
-  lt->tm_isdst = -1;
-  t = mktime(lt);
+  localtime_r(&t, &lt);
+  lt.tm_mon += delta_month;
+  lt.tm_mday += delta_day;
+  lt.tm_isdst = -1;
+  t = mktime(&lt);
   EXIT_IF(t == -1, _("failure in mktime"));
 
   return t;
@@ -423,14 +432,14 @@ long date_sec_change(long date, int delta_month, int delta_day)
  */
 long update_time_in_date(long date, unsigned hr, unsigned mn)
 {
-  struct tm *lt;
+  struct tm lt;
   time_t t, new_date;
 
   t = date;
-  lt = localtime(&t);
-  lt->tm_hour = hr;
-  lt->tm_min = mn;
-  new_date = mktime(lt);
+  localtime_r(&t, &lt);
+  lt.tm_hour = hr;
+  lt.tm_min = mn;
+  new_date = mktime(&lt);
   EXIT_IF(new_date == -1, _("error in mktime"));
 
   return new_date;
@@ -442,7 +451,7 @@ long update_time_in_date(long date, unsigned hr, unsigned mn)
  */
 long get_sec_date(struct date date)
 {
-  struct tm *ptrtime;
+  struct tm ptrtime;
   time_t timer;
   long long_date;
   char current_day[] = "dd ";
@@ -451,10 +460,10 @@ long get_sec_date(struct date date)
 
   if (date.yyyy == 0 && date.mm == 0 && date.dd == 0) {
     timer = time(NULL);
-    ptrtime = localtime(&timer);
-    strftime(current_day, strlen(current_day), "%d", ptrtime);
-    strftime(current_month, strlen(current_month), "%m", ptrtime);
-    strftime(current_year, strlen(current_year), "%Y", ptrtime);
+    localtime_r(&timer, &ptrtime);
+    strftime(current_day, strlen(current_day), "%d", &ptrtime);
+    strftime(current_month, strlen(current_month), "%m", &ptrtime);
+    strftime(current_year, strlen(current_year), "%Y", &ptrtime);
     date.mm = atoi(current_month);
     date.dd = atoi(current_day);
     date.yyyy = atoi(current_year);
@@ -518,16 +527,16 @@ item_in_popup(const char *saved_a_start, const char *saved_a_end,
 /* Returns the beginning of current day in seconds from 1900. */
 long get_today(void)
 {
-  struct tm *lt;
+  struct tm lt;
   time_t current_time;
   long current_day;
   struct date day;
 
   current_time = time(NULL);
-  lt = localtime(&current_time);
-  day.mm = lt->tm_mon + 1;
-  day.dd = lt->tm_mday;
-  day.yyyy = lt->tm_year + 1900;
+  localtime_r(&current_time, &lt);
+  day.mm = lt.tm_mon + 1;
+  day.dd = lt.tm_mday;
+  day.yyyy = lt.tm_year + 1900;
   current_day = date2sec(day, 0, 0);
 
   return current_day;
@@ -541,10 +550,12 @@ long now(void)
 
 char *nowstr(void)
 {
+  struct tm lt;
   static char buf[BUFSIZ];
   time_t t = now();
 
-  strftime(buf, sizeof buf, "%a %b %d %T %Y", localtime(&t));
+  localtime_r(&t, &lt);
+  strftime(buf, sizeof buf, "%a %b %d %T %Y", &lt);
 
   return buf;
 }
@@ -1183,15 +1194,17 @@ static void print_date(long date, long day, const char *extformat)
     printf("%ld", date);
   else {
     time_t t = date;
-    struct tm *lt = localtime((time_t *) & t);
+    struct tm lt;
+
+    localtime_r((time_t *)&t, &lt);
 
     if (extformat[0] == '\0' || !strcmp(extformat, "default")) {
       if (date >= day && date <= day + DAYINSEC)
-        strftime(buf, BUFSIZ, "%H:%M", lt);
+        strftime(buf, BUFSIZ, "%H:%M", &lt);
       else
-        strftime(buf, BUFSIZ, "..:..", lt);
+        strftime(buf, BUFSIZ, "..:..", &lt);
     } else {
-      strftime(buf, BUFSIZ, extformat, lt);
+      strftime(buf, BUFSIZ, extformat, &lt);
     }
 
     printf("%s", buf);
-- 
cgit v1.2.3-70-g09d2