1 /* 2 * Copyright (c) 1998 Sendmail, Inc. All rights reserved. 3 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * By using this file, you agree to the terms and conditions set 8 * forth in the LICENSE file which can be found at the top level of 9 * the sendmail distribution. 10 * 11 */ 12 13 #ifndef lint 14 static char sccsid[] = "@(#)arpadate.c 8.14 (Berkeley) 2/2/1999"; 15 #endif /* not lint */ 16 17 # include "sendmail.h" 18 19 /* 20 ** ARPADATE -- Create date in ARPANET format 21 ** 22 ** Parameters: 23 ** ud -- unix style date string. if NULL, one is created. 24 ** 25 ** Returns: 26 ** pointer to an ARPANET date field 27 ** 28 ** Side Effects: 29 ** none 30 ** 31 ** WARNING: 32 ** date is stored in a local buffer -- subsequent 33 ** calls will overwrite. 34 ** 35 ** Bugs: 36 ** Timezone is computed from local time, rather than 37 ** from whereever (and whenever) the message was sent. 38 ** To do better is very hard. 39 ** 40 ** Some sites are now inserting the timezone into the 41 ** local date. This routine should figure out what 42 ** the format is and work appropriately. 43 */ 44 45 #ifndef TZNAME_MAX 46 # define TZNAME_MAX 50 /* max size of timezone */ 47 #endif 48 49 /* values for TZ_TYPE */ 50 #define TZ_NONE 0 /* no character timezone support */ 51 #define TZ_TM_NAME 1 /* use tm->tm_name */ 52 #define TZ_TM_ZONE 2 /* use tm->tm_zone */ 53 #define TZ_TZNAME 3 /* use tzname[] */ 54 #define TZ_TIMEZONE 4 /* use timezone() */ 55 56 char * 57 arpadate(ud) 58 register char *ud; 59 { 60 register char *p; 61 register char *q; 62 register int off; 63 register int i; 64 register struct tm *lt; 65 time_t t; 66 struct tm gmt; 67 char *tz; 68 static char b[43 + TZNAME_MAX]; 69 70 /* 71 ** Get current time. 72 ** This will be used if a null argument is passed and 73 ** to resolve the timezone. 74 */ 75 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 gmt = *gmtime(&t); 125 lt = localtime(&t); 126 127 off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min; 128 129 /* assume that offset isn't more than a day ... */ 130 if (lt->tm_year < gmt.tm_year) 131 off -= 24 * 60; 132 else if (lt->tm_year > gmt.tm_year) 133 off += 24 * 60; 134 else if (lt->tm_yday < gmt.tm_yday) 135 off -= 24 * 60; 136 else if (lt->tm_yday > gmt.tm_yday) 137 off += 24 * 60; 138 139 *q++ = ' '; 140 if (off == 0) 141 { 142 *q++ = 'G'; 143 *q++ = 'M'; 144 *q++ = 'T'; 145 } 146 else 147 { 148 tz = NULL; 149 #if TZ_TYPE == TZ_TM_NAME 150 tz = lt->tm_name; 151 #endif 152 #if TZ_TYPE == TZ_TM_ZONE 153 tz = lt->tm_zone; 154 #endif 155 #if TZ_TYPE == TZ_TZNAME 156 { 157 extern char *tzname[]; 158 159 if (lt->tm_isdst > 0) 160 tz = tzname[1]; 161 else if (lt->tm_isdst == 0) 162 tz = tzname[0]; 163 else 164 tz = NULL; 165 } 166 #endif 167 #if TZ_TYPE == TZ_TIMEZONE 168 { 169 extern char *timezone(); 170 171 tz = timezone(off, lt->tm_isdst); 172 } 173 #endif 174 if (off < 0) 175 { 176 off = -off; 177 *q++ = '-'; 178 } 179 else 180 *q++ = '+'; 181 182 if (off >= 24*60) /* should be impossible */ 183 off = 23*60+59; /* if not, insert silly value */ 184 185 *q++ = (off / 600) + '0'; 186 *q++ = (off / 60) % 10 + '0'; 187 off %= 60; 188 *q++ = (off / 10) + '0'; 189 *q++ = (off % 10) + '0'; 190 if (tz != NULL && *tz != '\0') 191 { 192 *q++ = ' '; 193 *q++ = '('; 194 while (*tz != '\0' && q < &b[sizeof b - 3]) 195 *q++ = *tz++; 196 *q++ = ')'; 197 } 198 } 199 *q = '\0'; 200 201 return (b); 202 } 203