xref: /illumos-gate/usr/src/cmd/sendmail/src/arpadate.c (revision 2a8bcb4efb45d99ac41c94a75c396b362c414f7f)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate  *	All rights reserved.
47c478bd9Sstevel@tonic-gate  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
57c478bd9Sstevel@tonic-gate  * Copyright (c) 1988, 1993
67c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
97c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
107c478bd9Sstevel@tonic-gate  * the sendmail distribution.
117c478bd9Sstevel@tonic-gate  *
127c478bd9Sstevel@tonic-gate  */
137c478bd9Sstevel@tonic-gate 
147c478bd9Sstevel@tonic-gate #include <sendmail.h>
157c478bd9Sstevel@tonic-gate 
16*058561cbSjbeck SM_RCSID("@(#)$Id: arpadate.c,v 8.31 2006/08/15 23:24:55 ca Exp $")
177c478bd9Sstevel@tonic-gate 
187c478bd9Sstevel@tonic-gate /*
197c478bd9Sstevel@tonic-gate **  ARPADATE -- Create date in ARPANET format
207c478bd9Sstevel@tonic-gate **
217c478bd9Sstevel@tonic-gate **	Parameters:
227c478bd9Sstevel@tonic-gate **		ud -- unix style date string.  if NULL, one is created.
237c478bd9Sstevel@tonic-gate **
247c478bd9Sstevel@tonic-gate **	Returns:
257c478bd9Sstevel@tonic-gate **		pointer to an ARPANET date field
267c478bd9Sstevel@tonic-gate **
277c478bd9Sstevel@tonic-gate **	Side Effects:
287c478bd9Sstevel@tonic-gate **		none
297c478bd9Sstevel@tonic-gate **
307c478bd9Sstevel@tonic-gate **	WARNING:
317c478bd9Sstevel@tonic-gate **		date is stored in a local buffer -- subsequent
327c478bd9Sstevel@tonic-gate **		calls will overwrite.
337c478bd9Sstevel@tonic-gate **
347c478bd9Sstevel@tonic-gate **	Bugs:
357c478bd9Sstevel@tonic-gate **		Timezone is computed from local time, rather than
367c478bd9Sstevel@tonic-gate **		from wherever (and whenever) the message was sent.
377c478bd9Sstevel@tonic-gate **		To do better is very hard.
387c478bd9Sstevel@tonic-gate **
397c478bd9Sstevel@tonic-gate **		Some sites are now inserting the timezone into the
407c478bd9Sstevel@tonic-gate **		local date.  This routine should figure out what
417c478bd9Sstevel@tonic-gate **		the format is and work appropriately.
427c478bd9Sstevel@tonic-gate */
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #ifndef TZNAME_MAX
457c478bd9Sstevel@tonic-gate # define TZNAME_MAX	50	/* max size of timezone */
467c478bd9Sstevel@tonic-gate #endif /* ! TZNAME_MAX */
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate /* values for TZ_TYPE */
497c478bd9Sstevel@tonic-gate #define TZ_NONE		0	/* no character timezone support */
507c478bd9Sstevel@tonic-gate #define TZ_TM_NAME	1	/* use tm->tm_name */
517c478bd9Sstevel@tonic-gate #define TZ_TM_ZONE	2	/* use tm->tm_zone */
527c478bd9Sstevel@tonic-gate #define TZ_TZNAME	3	/* use tzname[] */
537c478bd9Sstevel@tonic-gate #define TZ_TIMEZONE	4	/* use timezone() */
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate char *
567c478bd9Sstevel@tonic-gate arpadate(ud)
577c478bd9Sstevel@tonic-gate 	register char *ud;
587c478bd9Sstevel@tonic-gate {
597c478bd9Sstevel@tonic-gate 	register char *p;
607c478bd9Sstevel@tonic-gate 	register char *q;
617c478bd9Sstevel@tonic-gate 	register int off;
627c478bd9Sstevel@tonic-gate 	register int i;
637c478bd9Sstevel@tonic-gate 	register struct tm *lt;
647c478bd9Sstevel@tonic-gate 	time_t t;
657c478bd9Sstevel@tonic-gate 	struct tm gmt;
667c478bd9Sstevel@tonic-gate 	char *tz;
677c478bd9Sstevel@tonic-gate 	static char b[43 + TZNAME_MAX];
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 	/*
707c478bd9Sstevel@tonic-gate 	**  Get current time.
717c478bd9Sstevel@tonic-gate 	**	This will be used if a null argument is passed and
727c478bd9Sstevel@tonic-gate 	**	to resolve the timezone.
737c478bd9Sstevel@tonic-gate 	*/
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate 	/* SM_REQUIRE(ud == NULL || strlen(ud) >= 23); */
767c478bd9Sstevel@tonic-gate 	t = curtime();
777c478bd9Sstevel@tonic-gate 	if (ud == NULL)
787c478bd9Sstevel@tonic-gate 		ud = ctime(&t);
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 	/*
817c478bd9Sstevel@tonic-gate 	**  Crack the UNIX date line in a singularly unoriginal way.
827c478bd9Sstevel@tonic-gate 	*/
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	q = b;
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	p = &ud[0];		/* Mon */
877c478bd9Sstevel@tonic-gate 	*q++ = *p++;
887c478bd9Sstevel@tonic-gate 	*q++ = *p++;
897c478bd9Sstevel@tonic-gate 	*q++ = *p++;
907c478bd9Sstevel@tonic-gate 	*q++ = ',';
917c478bd9Sstevel@tonic-gate 	*q++ = ' ';
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	p = &ud[8];		/* 16 */
947c478bd9Sstevel@tonic-gate 	if (*p == ' ')
957c478bd9Sstevel@tonic-gate 		p++;
967c478bd9Sstevel@tonic-gate 	else
977c478bd9Sstevel@tonic-gate 		*q++ = *p++;
987c478bd9Sstevel@tonic-gate 	*q++ = *p++;
997c478bd9Sstevel@tonic-gate 	*q++ = ' ';
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	p = &ud[4];		/* Sep */
1027c478bd9Sstevel@tonic-gate 	*q++ = *p++;
1037c478bd9Sstevel@tonic-gate 	*q++ = *p++;
1047c478bd9Sstevel@tonic-gate 	*q++ = *p++;
1057c478bd9Sstevel@tonic-gate 	*q++ = ' ';
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	p = &ud[20];		/* 1979 */
1087c478bd9Sstevel@tonic-gate 	*q++ = *p++;
1097c478bd9Sstevel@tonic-gate 	*q++ = *p++;
1107c478bd9Sstevel@tonic-gate 	*q++ = *p++;
1117c478bd9Sstevel@tonic-gate 	*q++ = *p++;
1127c478bd9Sstevel@tonic-gate 	*q++ = ' ';
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate 	p = &ud[11];		/* 01:03:52 */
1157c478bd9Sstevel@tonic-gate 	for (i = 8; i > 0; i--)
1167c478bd9Sstevel@tonic-gate 		*q++ = *p++;
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	/*
1197c478bd9Sstevel@tonic-gate 	**  should really get the timezone from the time in "ud" (which
1207c478bd9Sstevel@tonic-gate 	**  is only different if a non-null arg was passed which is different
1217c478bd9Sstevel@tonic-gate 	**  from the current time), but for all practical purposes, returning
1227c478bd9Sstevel@tonic-gate 	**  the current local zone will do (its all that is ever needed).
1237c478bd9Sstevel@tonic-gate 	*/
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	gmt = *gmtime(&t);
1267c478bd9Sstevel@tonic-gate 	lt = localtime(&t);
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	/* assume that offset isn't more than a day ... */
1317c478bd9Sstevel@tonic-gate 	if (lt->tm_year < gmt.tm_year)
1327c478bd9Sstevel@tonic-gate 		off -= 24 * 60;
1337c478bd9Sstevel@tonic-gate 	else if (lt->tm_year > gmt.tm_year)
1347c478bd9Sstevel@tonic-gate 		off += 24 * 60;
1357c478bd9Sstevel@tonic-gate 	else if (lt->tm_yday < gmt.tm_yday)
1367c478bd9Sstevel@tonic-gate 		off -= 24 * 60;
1377c478bd9Sstevel@tonic-gate 	else if (lt->tm_yday > gmt.tm_yday)
1387c478bd9Sstevel@tonic-gate 		off += 24 * 60;
1397c478bd9Sstevel@tonic-gate 
1407c478bd9Sstevel@tonic-gate 	*q++ = ' ';
1417c478bd9Sstevel@tonic-gate 	if (off == 0)
1427c478bd9Sstevel@tonic-gate 	{
1437c478bd9Sstevel@tonic-gate 		*q++ = 'G';
1447c478bd9Sstevel@tonic-gate 		*q++ = 'M';
1457c478bd9Sstevel@tonic-gate 		*q++ = 'T';
1467c478bd9Sstevel@tonic-gate 	}
1477c478bd9Sstevel@tonic-gate 	else
1487c478bd9Sstevel@tonic-gate 	{
1497c478bd9Sstevel@tonic-gate 		tz = NULL;
1507c478bd9Sstevel@tonic-gate #if TZ_TYPE == TZ_TM_NAME
1517c478bd9Sstevel@tonic-gate 		tz = lt->tm_name;
1527c478bd9Sstevel@tonic-gate #endif /* TZ_TYPE == TZ_TM_NAME */
1537c478bd9Sstevel@tonic-gate #if TZ_TYPE == TZ_TM_ZONE
1547c478bd9Sstevel@tonic-gate 		tz = lt->tm_zone;
1557c478bd9Sstevel@tonic-gate #endif /* TZ_TYPE == TZ_TM_ZONE */
1567c478bd9Sstevel@tonic-gate #if TZ_TYPE == TZ_TZNAME
1577c478bd9Sstevel@tonic-gate 		{
1587c478bd9Sstevel@tonic-gate 			extern char *tzname[];
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 			if (lt->tm_isdst > 0)
1617c478bd9Sstevel@tonic-gate 				tz = tzname[1];
1627c478bd9Sstevel@tonic-gate 			else if (lt->tm_isdst == 0)
1637c478bd9Sstevel@tonic-gate 				tz = tzname[0];
1647c478bd9Sstevel@tonic-gate 			else
1657c478bd9Sstevel@tonic-gate 				tz = NULL;
1667c478bd9Sstevel@tonic-gate 		}
1677c478bd9Sstevel@tonic-gate #endif /* TZ_TYPE == TZ_TZNAME */
1687c478bd9Sstevel@tonic-gate #if TZ_TYPE == TZ_TIMEZONE
1697c478bd9Sstevel@tonic-gate 		{
1707c478bd9Sstevel@tonic-gate 			extern char *timezone();
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 			tz = timezone(off, lt->tm_isdst);
1737c478bd9Sstevel@tonic-gate 		}
1747c478bd9Sstevel@tonic-gate #endif /* TZ_TYPE == TZ_TIMEZONE */
1757c478bd9Sstevel@tonic-gate 		if (off < 0)
1767c478bd9Sstevel@tonic-gate 		{
1777c478bd9Sstevel@tonic-gate 			off = -off;
1787c478bd9Sstevel@tonic-gate 			*q++ = '-';
1797c478bd9Sstevel@tonic-gate 		}
1807c478bd9Sstevel@tonic-gate 		else
1817c478bd9Sstevel@tonic-gate 			*q++ = '+';
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 		if (off >= 24*60)		/* should be impossible */
1847c478bd9Sstevel@tonic-gate 			off = 23*60+59;		/* if not, insert silly value */
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 		*q++ = (off / 600) + '0';
1877c478bd9Sstevel@tonic-gate 		*q++ = (off / 60) % 10 + '0';
1887c478bd9Sstevel@tonic-gate 		off %= 60;
1897c478bd9Sstevel@tonic-gate 		*q++ = (off / 10) + '0';
1907c478bd9Sstevel@tonic-gate 		*q++ = (off % 10) + '0';
1917c478bd9Sstevel@tonic-gate 		if (tz != NULL && *tz != '\0')
1927c478bd9Sstevel@tonic-gate 		{
1937c478bd9Sstevel@tonic-gate 			*q++ = ' ';
1947c478bd9Sstevel@tonic-gate 			*q++ = '(';
195*058561cbSjbeck 			while (*tz != '\0' && q < &b[sizeof(b) - 3])
1967c478bd9Sstevel@tonic-gate 				*q++ = *tz++;
1977c478bd9Sstevel@tonic-gate 			*q++ = ')';
1987c478bd9Sstevel@tonic-gate 		}
1997c478bd9Sstevel@tonic-gate 	}
2007c478bd9Sstevel@tonic-gate 	*q = '\0';
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	return b;
2037c478bd9Sstevel@tonic-gate }
204