comparison libpurple/util.c @ 21613:31101e7d275f

'man 3 ctime' says of localtime() (and friends): "The return value points to a statically allocated struct which might be overwritten by subsequent calls to any of the date and time functions. The localtime_r() function does the same, but stores the data in a user-supplied struct." purple_str_to_time() had multiple calls to date and time functions, although I didn't experience any problems in my testing I figured it would be better to use localtime_r() and provide our own struct. I hope I got this right. At least 'make check' still works :)
author Stu Tomlinson <stu@nosnilmot.com>
date Thu, 22 Nov 2007 16:45:38 +0000
parents 18fb032a602a
children b2aa68cdc8b9
comparison
equal deleted inserted replaced
21612:18fb032a602a 21613:31101e7d275f
751 time_t 751 time_t
752 purple_str_to_time(const char *timestamp, gboolean utc, 752 purple_str_to_time(const char *timestamp, gboolean utc,
753 struct tm *tm, long *tz_off, const char **rest) 753 struct tm *tm, long *tz_off, const char **rest)
754 { 754 {
755 time_t retval = 0; 755 time_t retval = 0;
756 struct tm *t; 756 static struct tm t;
757 const char *c = timestamp; 757 const char *c = timestamp;
758 int year = 0; 758 int year = 0;
759 long tzoff = PURPLE_NO_TZ_OFF; 759 long tzoff = PURPLE_NO_TZ_OFF;
760 760
761 time(&retval); 761 time(&retval);
762 t = localtime(&retval); 762 localtime_r(&retval, &t);
763 763
764 /* 4 digit year */ 764 /* 4 digit year */
765 if (sscanf(c, "%04d", &year) && year > 1900) 765 if (sscanf(c, "%04d", &year) && year > 1900)
766 { 766 {
767 c += 4; 767 c += 4;
768 if (*c == '-') 768 if (*c == '-')
769 c++; 769 c++;
770 t->tm_year = year - 1900; 770 t.tm_year = year - 1900;
771 } 771 }
772 772
773 /* 2 digit month */ 773 /* 2 digit month */
774 if (!sscanf(c, "%02d", &t->tm_mon)) 774 if (!sscanf(c, "%02d", &t.tm_mon))
775 { 775 {
776 if (rest != NULL && *c != '\0') 776 if (rest != NULL && *c != '\0')
777 *rest = c; 777 *rest = c;
778 return 0; 778 return 0;
779 } 779 }
780 c += 2; 780 c += 2;
781 if (*c == '-' || *c == '/') 781 if (*c == '-' || *c == '/')
782 c++; 782 c++;
783 t->tm_mon -= 1; 783 t.tm_mon -= 1;
784 784
785 /* 2 digit day */ 785 /* 2 digit day */
786 if (!sscanf(c, "%02d", &t->tm_mday)) 786 if (!sscanf(c, "%02d", &t.tm_mday))
787 { 787 {
788 if (rest != NULL && *c != '\0') 788 if (rest != NULL && *c != '\0')
789 *rest = c; 789 *rest = c;
790 return 0; 790 return 0;
791 } 791 }
792 c += 2; 792 c += 2;
793 if (*c == '/') 793 if (*c == '/')
794 { 794 {
795 c++; 795 c++;
796 796
797 if (!sscanf(c, "%04d", &t->tm_year)) 797 if (!sscanf(c, "%04d", &t.tm_year))
798 { 798 {
799 if (rest != NULL && *c != '\0') 799 if (rest != NULL && *c != '\0')
800 *rest = c; 800 *rest = c;
801 return 0; 801 return 0;
802 } 802 }
803 t->tm_year -= 1900; 803 t.tm_year -= 1900;
804 } 804 }
805 else if (*c == 'T' || *c == '.') 805 else if (*c == 'T' || *c == '.')
806 { 806 {
807 c++; 807 c++;
808 /* we have more than a date, keep going */ 808 /* we have more than a date, keep going */
809 809
810 /* 2 digit hour */ 810 /* 2 digit hour */
811 if ((sscanf(c, "%02d:%02d:%02d", &t->tm_hour, &t->tm_min, &t->tm_sec) == 3 && (c = c + 8)) || 811 if ((sscanf(c, "%02d:%02d:%02d", &t.tm_hour, &t.tm_min, &t.tm_sec) == 3 && (c = c + 8)) ||
812 (sscanf(c, "%02d%02d%02d", &t->tm_hour, &t->tm_min, &t->tm_sec) == 3 && (c = c + 6))) 812 (sscanf(c, "%02d%02d%02d", &t.tm_hour, &t.tm_min, &t.tm_sec) == 3 && (c = c + 6)))
813 { 813 {
814 gboolean offset_positive = FALSE; 814 gboolean offset_positive = FALSE;
815 int tzhrs; 815 int tzhrs;
816 int tzmins; 816 int tzmins;
817 817
818 t->tm_isdst = -1; 818 t.tm_isdst = -1;
819 819
820 if (*c == '.') { 820 if (*c == '.') {
821 do { 821 do {
822 c++; 822 c++;
823 } while (*c >= '0' && *c <= '9'); /* dealing with precision we don't care about */ 823 } while (*c >= '0' && *c <= '9'); /* dealing with precision we don't care about */
831 tzoff = tzhrs*60*60 + tzmins*60; 831 tzoff = tzhrs*60*60 + tzmins*60;
832 if (offset_positive) 832 if (offset_positive)
833 tzoff *= -1; 833 tzoff *= -1;
834 /* We don't want the C library doing DST calculations 834 /* We don't want the C library doing DST calculations
835 * if we know the UTC offset already. */ 835 * if we know the UTC offset already. */
836 t->tm_isdst = 0; 836 t.tm_isdst = 0;
837 } 837 }
838 else if (utc) 838 else if (utc)
839 { 839 {
840 struct tm *tmptm; 840 static struct tm tmptm;
841 time_t tmp; 841 time_t tmp;
842 tmp = mktime(t); 842 tmp = mktime(&t);
843 /* we care about whether it *was* dst, and the offset, here on this 843 /* we care about whether it *was* dst, and the offset, here on this
844 * date, not whether we are currently observing dst locally *now*. 844 * date, not whether we are currently observing dst locally *now*.
845 * This isn't perfect, because we would need to know in advance the 845 * This isn't perfect, because we would need to know in advance the
846 * offset we are trying to work out in advance to be sure this 846 * offset we are trying to work out in advance to be sure this
847 * works for times around dst transitions but it'll have to do. */ 847 * works for times around dst transitions but it'll have to do. */
848 tmptm = localtime(&tmp); 848 localtime_r(&tmp, &tmptm);
849 t->tm_isdst = tmptm->tm_isdst; 849 t.tm_isdst = tmptm.tm_isdst;
850 #ifdef HAVE_TM_GMTOFF 850 #ifdef HAVE_TM_GMTOFF
851 t->tm_gmtoff = tmptm->tm_gmtoff; 851 t.tm_gmtoff = tmptm.tm_gmtoff;
852 #endif 852 #endif
853 } 853 }
854 854
855 if (rest != NULL && *c != '\0') 855 if (rest != NULL && *c != '\0')
856 { 856 {
876 tzoff = PURPLE_NO_TZ_OFF; 876 tzoff = PURPLE_NO_TZ_OFF;
877 else 877 else
878 tzoff += sys_tzoff; 878 tzoff += sys_tzoff;
879 #else 879 #else
880 #ifdef HAVE_TM_GMTOFF 880 #ifdef HAVE_TM_GMTOFF
881 tzoff += t->tm_gmtoff; 881 tzoff += t.tm_gmtoff;
882 #else 882 #else
883 # ifdef HAVE_TIMEZONE 883 # ifdef HAVE_TIMEZONE
884 tzset(); /* making sure */ 884 tzset(); /* making sure */
885 tzoff -= timezone; 885 tzoff -= timezone;
886 # endif 886 # endif
895 } 895 }
896 } 896 }
897 897
898 if (tm != NULL) 898 if (tm != NULL)
899 { 899 {
900 *tm = *t; 900 memcpy(tm, &t, sizeof(struct tm));
901 tm->tm_isdst = -1; 901 tm->tm_isdst = -1;
902 mktime(tm); 902 mktime(tm);
903 } 903 }
904 904
905 retval = mktime(t); 905 retval = mktime(&t);
906 if (tzoff != PURPLE_NO_TZ_OFF) 906 if (tzoff != PURPLE_NO_TZ_OFF)
907 retval += tzoff; 907 retval += tzoff;
908 908
909 if (tz_off != NULL) 909 if (tz_off != NULL)
910 *tz_off = tzoff; 910 *tz_off = tzoff;