1 /* 2 * Copyright (c) 1998-2001 Proofpoint, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set 9 * forth in the LICENSE file which can be found at the top level of 10 * the sendmail distribution. 11 * 12 */ 13 14 #include <sendmail.h> 15 16 SM_RCSID("@(#)$Id: arpadate.c,v 8.32 2013-11-22 20:51:55 ca Exp $") 17 18 /* 19 ** ARPADATE -- Create date in ARPANET format 20 ** 21 ** Parameters: 22 ** ud -- unix style date string. if NULL, one is created. 23 ** 24 ** Returns: 25 ** pointer to an ARPANET date field 26 ** 27 ** Side Effects: 28 ** none 29 ** 30 ** WARNING: 31 ** date is stored in a local buffer -- subsequent 32 ** calls will overwrite. 33 ** 34 ** Bugs: 35 ** Timezone is computed from local time, rather than 36 ** from wherever (and whenever) the message was sent. 37 ** To do better is very hard. 38 ** 39 ** Some sites are now inserting the timezone into the 40 ** local date. This routine should figure out what 41 ** the format is and work appropriately. 42 */ 43 44 #ifndef TZNAME_MAX 45 # define TZNAME_MAX 50 /* max size of timezone */ 46 #endif 47 48 /* values for TZ_TYPE */ 49 #define TZ_NONE 0 /* no character timezone support */ 50 #define TZ_TM_NAME 1 /* use tm->tm_name */ 51 #define TZ_TM_ZONE 2 /* use tm->tm_zone */ 52 #define TZ_TZNAME 3 /* use tzname[] */ 53 #define TZ_TIMEZONE 4 /* use timezone() */ 54 55 char * 56 arpadate(ud) 57 register char *ud; 58 { 59 register char *p; 60 register char *q; 61 register int off; 62 register int i; 63 register struct tm *lt; 64 time_t t; 65 struct tm gmt; 66 char *tz; 67 static char b[43 + TZNAME_MAX]; 68 69 /* 70 ** Get current time. 71 ** This will be used if a null argument is passed and 72 ** to resolve the timezone. 73 */ 74 75 /* SM_REQUIRE(ud == NULL || strlen(ud) >= 23); */ 76 t = curtime(); 77 if (ud == NULL) 78 ud = ctime(&t); 79 80 /* 81 ** Crack the UNIX date line in a singularly unoriginal way. 82 */ 83 84 q = b; 85 86 p = &ud[0]; /* Mon */ 87 *q++ = *p++; 88 *q++ = *p++; 89 *q++ = *p++; 90 *q++ = ','; 91 *q++ = ' '; 92 93 p = &ud[8]; /* 16 */ 94 if (*p == ' ') 95 p++; 96 else 97 *q++ = *p++; 98 *q++ = *p++; 99 *q++ = ' '; 100 101 p = &ud[4]; /* Sep */ 102 *q++ = *p++; 103 *q++ = *p++; 104 *q++ = *p++; 105 *q++ = ' '; 106 107 p = &ud[20]; /* 1979 */ 108 *q++ = *p++; 109 *q++ = *p++; 110 *q++ = *p++; 111 *q++ = *p++; 112 *q++ = ' '; 113 114 p = &ud[11]; /* 01:03:52 */ 115 for (i = 8; i > 0; i--) 116 *q++ = *p++; 117 118 /* 119 ** should really get the timezone from the time in "ud" (which 120 ** is only different if a non-null arg was passed which is different 121 ** from the current time), but for all practical purposes, returning 122 ** the current local zone will do (its all that is ever needed). 123 */ 124 125 gmt = *gmtime(&t); 126 lt = localtime(&t); 127 128 off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min; 129 130 /* assume that offset isn't more than a day ... */ 131 if (lt->tm_year < gmt.tm_year) 132 off -= 24 * 60; 133 else if (lt->tm_year > gmt.tm_year) 134 off += 24 * 60; 135 else if (lt->tm_yday < gmt.tm_yday) 136 off -= 24 * 60; 137 else if (lt->tm_yday > gmt.tm_yday) 138 off += 24 * 60; 139 140 *q++ = ' '; 141 if (off == 0) 142 { 143 *q++ = 'G'; 144 *q++ = 'M'; 145 *q++ = 'T'; 146 } 147 else 148 { 149 tz = NULL; 150 #if TZ_TYPE == TZ_TM_NAME 151 tz = lt->tm_name; 152 #endif 153 #if TZ_TYPE == TZ_TM_ZONE 154 tz = lt->tm_zone; 155 #endif 156 #if TZ_TYPE == TZ_TZNAME 157 { 158 extern char *tzname[]; 159 160 if (lt->tm_isdst > 0) 161 tz = tzname[1]; 162 else if (lt->tm_isdst == 0) 163 tz = tzname[0]; 164 else 165 tz = NULL; 166 } 167 #endif /* TZ_TYPE == TZ_TZNAME */ 168 #if TZ_TYPE == TZ_TIMEZONE 169 { 170 extern char *timezone(); 171 172 tz = timezone(off, lt->tm_isdst); 173 } 174 #endif /* TZ_TYPE == TZ_TIMEZONE */ 175 if (off < 0) 176 { 177 off = -off; 178 *q++ = '-'; 179 } 180 else 181 *q++ = '+'; 182 183 if (off >= 24*60) /* should be impossible */ 184 off = 23*60+59; /* if not, insert silly value */ 185 186 *q++ = (off / 600) + '0'; 187 *q++ = (off / 60) % 10 + '0'; 188 off %= 60; 189 *q++ = (off / 10) + '0'; 190 *q++ = (off % 10) + '0'; 191 if (tz != NULL && *tz != '\0') 192 { 193 *q++ = ' '; 194 *q++ = '('; 195 while (*tz != '\0' && q < &b[sizeof(b) - 3]) 196 *q++ = *tz++; 197 *q++ = ')'; 198 } 199 } 200 *q = '\0'; 201 202 return b; 203 } 204