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)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;
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