1 /* 2 * Copyright (c) 1998, 1999, 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 #ifndef lint 15 static char id[] = "@(#)$Id: arpadate.c,v 8.23.20.2 2001/05/07 22:07:26 gshapiro Exp $"; 16 #endif /* ! lint */ 17 18 #include <sendmail.h> 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 t = curtime(); 78 if (ud == NULL) 79 ud = ctime(&t); 80 81 /* 82 ** Crack the UNIX date line in a singularly unoriginal way. 83 */ 84 85 q = b; 86 87 p = &ud[0]; /* Mon */ 88 *q++ = *p++; 89 *q++ = *p++; 90 *q++ = *p++; 91 *q++ = ','; 92 *q++ = ' '; 93 94 p = &ud[8]; /* 16 */ 95 if (*p == ' ') 96 p++; 97 else 98 *q++ = *p++; 99 *q++ = *p++; 100 *q++ = ' '; 101 102 p = &ud[4]; /* Sep */ 103 *q++ = *p++; 104 *q++ = *p++; 105 *q++ = *p++; 106 *q++ = ' '; 107 108 p = &ud[20]; /* 1979 */ 109 *q++ = *p++; 110 *q++ = *p++; 111 *q++ = *p++; 112 *q++ = *p++; 113 *q++ = ' '; 114 115 p = &ud[11]; /* 01:03:52 */ 116 for (i = 8; i > 0; i--) 117 *q++ = *p++; 118 119 /* 120 ** should really get the timezone from the time in "ud" (which 121 ** is only different if a non-null arg was passed which is different 122 ** from the current time), but for all practical purposes, returning 123 ** the current local zone will do (its all that is ever needed). 124 */ 125 126 gmt = *gmtime(&t); 127 lt = localtime(&t); 128 129 off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min; 130 131 /* assume that offset isn't more than a day ... */ 132 if (lt->tm_year < gmt.tm_year) 133 off -= 24 * 60; 134 else if (lt->tm_year > gmt.tm_year) 135 off += 24 * 60; 136 else if (lt->tm_yday < gmt.tm_yday) 137 off -= 24 * 60; 138 else if (lt->tm_yday > gmt.tm_yday) 139 off += 24 * 60; 140 141 *q++ = ' '; 142 if (off == 0) 143 { 144 *q++ = 'G'; 145 *q++ = 'M'; 146 *q++ = 'T'; 147 } 148 else 149 { 150 tz = NULL; 151 #if TZ_TYPE == TZ_TM_NAME 152 tz = lt->tm_name; 153 #endif /* TZ_TYPE == TZ_TM_NAME */ 154 #if TZ_TYPE == TZ_TM_ZONE 155 tz = lt->tm_zone; 156 #endif /* TZ_TYPE == TZ_TM_ZONE */ 157 #if TZ_TYPE == TZ_TZNAME 158 { 159 extern char *tzname[]; 160 161 if (lt->tm_isdst > 0) 162 tz = tzname[1]; 163 else if (lt->tm_isdst == 0) 164 tz = tzname[0]; 165 else 166 tz = NULL; 167 } 168 #endif /* TZ_TYPE == TZ_TZNAME */ 169 #if TZ_TYPE == TZ_TIMEZONE 170 { 171 extern char *timezone(); 172 173 tz = timezone(off, lt->tm_isdst); 174 } 175 #endif /* TZ_TYPE == TZ_TIMEZONE */ 176 if (off < 0) 177 { 178 off = -off; 179 *q++ = '-'; 180 } 181 else 182 *q++ = '+'; 183 184 if (off >= 24*60) /* should be impossible */ 185 off = 23*60+59; /* if not, insert silly value */ 186 187 *q++ = (off / 600) + '0'; 188 *q++ = (off / 60) % 10 + '0'; 189 off %= 60; 190 *q++ = (off / 10) + '0'; 191 *q++ = (off % 10) + '0'; 192 if (tz != NULL && *tz != '\0') 193 { 194 *q++ = ' '; 195 *q++ = '('; 196 while (*tz != '\0' && q < &b[sizeof b - 3]) 197 *q++ = *tz++; 198 *q++ = ')'; 199 } 200 } 201 *q = '\0'; 202 203 return b; 204 } 205