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