122695Sdist /* 2*68839Seric * Copyright (c) 1983, 1995 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*68839Seric static char sccsid[] = "@(#)arpadate.c 8.4 (Berkeley) 04/21/95"; 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 4167603Seric #ifndef TZNAME_MAX 4267603Seric # define TZNAME_MAX 50 /* max size of timezone */ 4367603Seric #endif 4467603Seric 4567603Seric /* values for TZ_TYPE */ 4667603Seric #define TZ_NONE 0 /* no character timezone support */ 4767608Seric #define TZ_TM_NAME 1 /* use tm->tm_name */ 4867608Seric #define TZ_TM_ZONE 2 /* use tm->tm_zone */ 4967608Seric #define TZ_TZNAME 3 /* use tzname[] */ 5067608Seric #define TZ_TIMEZONE 4 /* use timezone() */ 5167603Seric 521586Seric char * arpadate(ud)532897Sericarpadate(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; 6367603Seric char *tz; 6467603Seric 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++ = ' '; 13667603Seric if (off == 0) 13767603Seric { 13836529Sbostic *q++ = 'G'; 13936529Sbostic *q++ = 'M'; 14036529Sbostic *q++ = 'T'; 14167603Seric } 14267603Seric else 14367603Seric { 14467603Seric tz = NULL; 14567608Seric #if TZ_TYPE == TZ_TM_NAME 14667603Seric tz = lt->tm_name; 14767603Seric #endif 14867608Seric #if TZ_TYPE == TZ_TM_ZONE 14967603Seric tz = lt->tm_zone; 15067603Seric #endif 15167608Seric #if TZ_TYPE == TZ_TZNAME 15267603Seric { 15367603Seric extern char *tzname[]; 15467603Seric 15567603Seric tz = tzname[lt->tm_isdst]; 15667603Seric } 15767603Seric #endif 15867608Seric #if TZ_TYPE == TZ_TIMEZONE 15967603Seric { 16067603Seric extern char *timezone(); 16167603Seric 16267603Seric tz = timezone(off, lt->tm_isdst); 16367603Seric } 16467603Seric #endif 16567603Seric if (off < 0) 16667603Seric { 16736529Sbostic off = -off; 16836529Sbostic *q++ = '-'; 16967603Seric } 17067603Seric 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'; 18167603Seric if (tz != NULL && *tz != '\0') 18267603Seric { 18367603Seric *q++ = ' '; 18467603Seric *q++ = '('; 18567603Seric while (*tz != '\0') 18667603Seric *q++ = *tz++; 18767603Seric *q++ = ')'; 18867603Seric } 18915137Seric } 19036529Sbostic *q = '\0'; 19136529Sbostic 19236529Sbostic return (b); 19315109Skarels } 194