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