122695Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 362522Sbostic * Copyright (c) 1988, 1993 462522Sbostic * The Regents of the University of California. All rights reserved. 533728Sbostic * 642824Sbostic * %sccs.include.redist.c% 733728Sbostic */ 822695Sdist 922695Sdist #ifndef lint 10*67603Seric static char sccsid[] = "@(#)arpadate.c 8.2 (Berkeley) 08/07/94"; 1133728Sbostic #endif /* not lint */ 1222695Sdist 1357589Seric # include "sendmail.h" 14293Seric 15293Seric /* 16293Seric ** ARPADATE -- Create date in ARPANET format 17293Seric ** 18293Seric ** Parameters: 192897Seric ** ud -- unix style date string. if NULL, one is created. 20293Seric ** 21293Seric ** Returns: 22293Seric ** pointer to an ARPANET date field 23293Seric ** 24293Seric ** Side Effects: 25293Seric ** none 26293Seric ** 27293Seric ** WARNING: 28293Seric ** date is stored in a local buffer -- subsequent 29293Seric ** calls will overwrite. 303185Seric ** 313185Seric ** Bugs: 323185Seric ** Timezone is computed from local time, rather than 333185Seric ** from whereever (and whenever) the message was sent. 343185Seric ** To do better is very hard. 354315Seric ** 364315Seric ** Some sites are now inserting the timezone into the 374315Seric ** local date. This routine should figure out what 384315Seric ** the format is and work appropriately. 39293Seric */ 40293Seric 41*67603Seric #ifndef TZNAME_MAX 42*67603Seric # define TZNAME_MAX 50 /* max size of timezone */ 43*67603Seric #endif 44*67603Seric 45*67603Seric /* values for TZ_TYPE */ 46*67603Seric #define TZ_NONE 0 /* no character timezone support */ 47*67603Seric #define TZ_USE_TM_NAME 1 /* use tm->tm_name */ 48*67603Seric #define TZ_USE_TM_ZONE 2 /* use tm->tm_zone */ 49*67603Seric #define TZ_USE_TZNAME 3 /* use tzname[] */ 50*67603Seric #define TZ_USE_TIMEZONE 4 /* use timezone() */ 51*67603Seric 521586Seric char * 532897Seric arpadate(ud) 542897Seric register char *ud; 55293Seric { 56293Seric register char *p; 572897Seric register char *q; 5836529Sbostic register int off; 5936529Sbostic register int i; 6036529Sbostic register struct tm *lt; 6136529Sbostic time_t t; 6236529Sbostic struct tm gmt; 63*67603Seric char *tz; 64*67603Seric static char b[43 + TZNAME_MAX]; 65293Seric 664315Seric /* 674315Seric ** Get current time. 684315Seric ** This will be used if a null argument is passed and 694315Seric ** to resolve the timezone. 704315Seric */ 714315Seric 724315Seric (void) time(&t); 732897Seric if (ud == NULL) 742897Seric ud = ctime(&t); 75293Seric 764315Seric /* 774315Seric ** Crack the UNIX date line in a singularly unoriginal way. 784315Seric */ 794315Seric 802897Seric q = b; 812897Seric 8213932Seric p = &ud[0]; /* Mon */ 8313932Seric *q++ = *p++; 8413932Seric *q++ = *p++; 8513932Seric *q++ = *p++; 8613932Seric *q++ = ','; 8713932Seric *q++ = ' '; 8813932Seric 89293Seric p = &ud[8]; /* 16 */ 90293Seric if (*p == ' ') 91293Seric p++; 922897Seric else 932897Seric *q++ = *p++; 942897Seric *q++ = *p++; 9510251Seric *q++ = ' '; 962897Seric 975184Seric p = &ud[4]; /* Sep */ 985184Seric *q++ = *p++; 995184Seric *q++ = *p++; 1005184Seric *q++ = *p++; 10110251Seric *q++ = ' '; 1022897Seric 10356304Seric p = &ud[20]; /* 1979 */ 1045184Seric *q++ = *p++; 1055184Seric *q++ = *p++; 10656304Seric *q++ = *p++; 10756304Seric *q++ = *p++; 1082897Seric *q++ = ' '; 1092897Seric 1102897Seric p = &ud[11]; /* 01:03:52 */ 1115184Seric for (i = 8; i > 0; i--) 1122897Seric *q++ = *p++; 1132897Seric 11436529Sbostic /* 11536529Sbostic * should really get the timezone from the time in "ud" (which 11636529Sbostic * is only different if a non-null arg was passed which is different 11736529Sbostic * from the current time), but for all practical purposes, returning 11836529Sbostic * the current local zone will do (its all that is ever needed). 11936529Sbostic */ 12036529Sbostic gmt = *gmtime(&t); 12136529Sbostic lt = localtime(&t); 1222897Seric 12336529Sbostic off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min; 12415109Skarels 12536529Sbostic /* assume that offset isn't more than a day ... */ 12636529Sbostic if (lt->tm_year < gmt.tm_year) 12736529Sbostic off -= 24 * 60; 12836529Sbostic else if (lt->tm_year > gmt.tm_year) 12936529Sbostic off += 24 * 60; 13036529Sbostic else if (lt->tm_yday < gmt.tm_yday) 13136529Sbostic off -= 24 * 60; 13236529Sbostic else if (lt->tm_yday > gmt.tm_yday) 13336529Sbostic off += 24 * 60; 13415109Skarels 13536529Sbostic *q++ = ' '; 136*67603Seric if (off == 0) 137*67603Seric { 13836529Sbostic *q++ = 'G'; 13936529Sbostic *q++ = 'M'; 14036529Sbostic *q++ = 'T'; 141*67603Seric } 142*67603Seric else 143*67603Seric { 144*67603Seric tz = NULL; 145*67603Seric #if TZ_TYPE == TZ_USE_TM_NAME 146*67603Seric tz = lt->tm_name; 147*67603Seric #endif 148*67603Seric #if TZ_TYPE == TZ_USE_TM_ZONE 149*67603Seric tz = lt->tm_zone; 150*67603Seric #endif 151*67603Seric #if TZ_TYPE == TZ_USE_TZNAME 152*67603Seric { 153*67603Seric extern char *tzname[]; 154*67603Seric 155*67603Seric tz = tzname[lt->tm_isdst]; 156*67603Seric } 157*67603Seric #endif 158*67603Seric #if TZ_TYPE == TZ_USE_TIMEZONE 159*67603Seric { 160*67603Seric extern char *timezone(); 161*67603Seric 162*67603Seric tz = timezone(off, lt->tm_isdst); 163*67603Seric } 164*67603Seric #endif 165*67603Seric if (off < 0) 166*67603Seric { 16736529Sbostic off = -off; 16836529Sbostic *q++ = '-'; 169*67603Seric } 170*67603Seric else 17136529Sbostic *q++ = '+'; 17215109Skarels 17336529Sbostic if (off >= 24*60) /* should be impossible */ 17436529Sbostic off = 23*60+59; /* if not, insert silly value */ 17515137Seric 17636529Sbostic *q++ = (off / 600) + '0'; 17736529Sbostic *q++ = (off / 60) % 10 + '0'; 17836529Sbostic off %= 60; 17936529Sbostic *q++ = (off / 10) + '0'; 18036529Sbostic *q++ = (off % 10) + '0'; 181*67603Seric if (tz != NULL && *tz != '\0') 182*67603Seric { 183*67603Seric *q++ = ' '; 184*67603Seric *q++ = '('; 185*67603Seric while (*tz != '\0') 186*67603Seric *q++ = *tz++; 187*67603Seric *q++ = ')'; 188*67603Seric } 18915137Seric } 19036529Sbostic *q = '\0'; 19136529Sbostic 19236529Sbostic return (b); 19315109Skarels } 194