diff options
-rw-r--r-- | libical/ChangeLog | 8 | ||||
-rw-r--r-- | libical/src/libical/icaltime.c | 62 |
2 files changed, 51 insertions, 19 deletions
diff --git a/libical/ChangeLog b/libical/ChangeLog index 6d116aa4a3..dc5a51af9a 100644 --- a/libical/ChangeLog +++ b/libical/ChangeLog @@ -1,3 +1,11 @@ +2001-01-24 Damon Chaplin <damon@helixcode.com> + + * src/libical/icaltime.c (set_tz): + (unset_tz): rewrote to fix problems with freeing the environment + string after calling putenv() and to fix memory leaks. (We save a + pointer to the last TZ env var we set, so we free it after the next + time we set TZ.) + 2001-01-23 JP Rosevear <jpr@ximian.com> * configure.in: Don't AC_INIT on an autogenerated file that does not diff --git a/libical/src/libical/icaltime.c b/libical/src/libical/icaltime.c index 22212a801b..81f2de6835 100644 --- a/libical/src/libical/icaltime.c +++ b/libical/src/libical/icaltime.c @@ -74,37 +74,56 @@ icaltime_from_timet(time_t tm, int is_date) return tt; } +/* This will hold the last "TZ=XXX" string we used with putenv(). After we + call putenv() again to set a new TZ string, we can free the previous one. + As far as I know, no libc implementations actually free the memory used in + the environment variables (how could they know if it is a static string or + a malloc'ed string?), so we have to free it ourselves. */ +static char* saved_tz = NULL; + + +/* If you use set_tz(), you must call unset_tz() some time later to restore the + original TZ. Pass unset_tz() the string that set_tz() returns. */ char* set_tz(const char* tzid) { - char *tzstr = 0; - char *tmp; + char *old_tz, *old_tz_copy = NULL, *new_tz; - /* Put the new time zone into the environment */ - if(getenv("TZ") != 0){ - tzstr = (char*)strdup(getenv("TZ")); + /* Get the old TZ setting and save a copy of it to return. */ + old_tz = getenv("TZ"); + if(old_tz){ + old_tz_copy = (char*)malloc(strlen (old_tz) + 4); - if(tzstr == 0){ + if(old_tz_copy == 0){ icalerror_set_errno(ICAL_NEWFAILED_ERROR); return 0; } + + strcpy (old_tz_copy, "TZ="); + strcpy (old_tz_copy + 3, old_tz); } - tmp = (char*)malloc(1024); + /* Create the new TZ string. */ + new_tz = (char*)malloc(strlen (tzid) + 4); - if(tmp == 0){ + if(new_tz == 0){ icalerror_set_errno(ICAL_NEWFAILED_ERROR); return 0; } - snprintf(tmp,1024,"TZ=%s",tzid); + strcpy (new_tz, "TZ="); + strcpy (new_tz + 3, tzid); - /* HACK. In some libc versions, putenv gives the string to the - system and in some it gives a copy, so the following might be a - memory leak. THe linux man page says that glibc2.1.2 take - ownership ( no leak) while BSD4.4 uses a copy ( A leak ) */ - putenv(tmp); + /* Add the new TZ to the environment. */ + putenv(new_tz); - return tzstr; /* This will be zero if the TZ env var was not set */ + /* Free any previous TZ environment string we have used. */ + if (saved_tz) + free (saved_tz); + + /* Save a pointer to the TZ string we just set, so we can free it later. */ + saved_tz = new_tz; + + return old_tz_copy; /* This will be zero if the TZ env var was not set */ } void unset_tz(char* tzstr) @@ -112,13 +131,18 @@ void unset_tz(char* tzstr) /* restore the original environment */ if(tzstr!=0){ - char temp[1024]; - snprintf(temp,1024,"TZ=%s",tzstr); - putenv(temp); - free(tzstr); + putenv(tzstr); } else { putenv("TZ"); /* Delete from environment */ } + + /* Free any previous TZ environment string we have used. */ + if (saved_tz) + free (saved_tz); + + /* Save a pointer to the TZ string we just set, so we can free it later. + (This can possibly be NULL if there was no TZ to restore.) */ + saved_tz = tzstr; } time_t icaltime_as_timet(struct icaltimetype tt) |