arpadate.c revision 77349
138032Speter/*
277349Sgshapiro * Copyright (c) 1998, 1999, 2001 Sendmail, Inc. and its suppliers.
364562Sgshapiro *	All rights reserved.
438032Speter * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
538032Speter * Copyright (c) 1988, 1993
638032Speter *	The Regents of the University of California.  All rights reserved.
738032Speter *
838032Speter * By using this file, you agree to the terms and conditions set
938032Speter * forth in the LICENSE file which can be found at the top level of
1038032Speter * the sendmail distribution.
1138032Speter *
1238032Speter */
1338032Speter
1438032Speter#ifndef lint
1577349Sgshapirostatic char id[] = "@(#)$Id: arpadate.c,v 8.23.20.2 2001/05/07 22:07:26 gshapiro Exp $";
1664562Sgshapiro#endif /* ! lint */
1738032Speter
1864562Sgshapiro#include <sendmail.h>
1938032Speter
2038032Speter/*
2138032Speter**  ARPADATE -- Create date in ARPANET format
2238032Speter**
2338032Speter**	Parameters:
2438032Speter**		ud -- unix style date string.  if NULL, one is created.
2538032Speter**
2638032Speter**	Returns:
2738032Speter**		pointer to an ARPANET date field
2838032Speter**
2938032Speter**	Side Effects:
3038032Speter**		none
3138032Speter**
3238032Speter**	WARNING:
3338032Speter**		date is stored in a local buffer -- subsequent
3438032Speter**		calls will overwrite.
3538032Speter**
3638032Speter**	Bugs:
3738032Speter**		Timezone is computed from local time, rather than
3864562Sgshapiro**		from wherever (and whenever) the message was sent.
3938032Speter**		To do better is very hard.
4038032Speter**
4138032Speter**		Some sites are now inserting the timezone into the
4238032Speter**		local date.  This routine should figure out what
4338032Speter**		the format is and work appropriately.
4438032Speter*/
4538032Speter
4638032Speter#ifndef TZNAME_MAX
4738032Speter# define TZNAME_MAX	50	/* max size of timezone */
4864562Sgshapiro#endif /* ! TZNAME_MAX */
4938032Speter
5038032Speter/* values for TZ_TYPE */
5138032Speter#define TZ_NONE		0	/* no character timezone support */
5238032Speter#define TZ_TM_NAME	1	/* use tm->tm_name */
5338032Speter#define TZ_TM_ZONE	2	/* use tm->tm_zone */
5438032Speter#define TZ_TZNAME	3	/* use tzname[] */
5538032Speter#define TZ_TIMEZONE	4	/* use timezone() */
5638032Speter
5738032Speterchar *
5838032Speterarpadate(ud)
5938032Speter	register char *ud;
6038032Speter{
6138032Speter	register char *p;
6238032Speter	register char *q;
6338032Speter	register int off;
6438032Speter	register int i;
6538032Speter	register struct tm *lt;
6638032Speter	time_t t;
6738032Speter	struct tm gmt;
6838032Speter	char *tz;
6938032Speter	static char b[43 + TZNAME_MAX];
7038032Speter
7138032Speter	/*
7238032Speter	**  Get current time.
7338032Speter	**	This will be used if a null argument is passed and
7438032Speter	**	to resolve the timezone.
7538032Speter	*/
7638032Speter
7743730Speter	t = curtime();
7838032Speter	if (ud == NULL)
7938032Speter		ud = ctime(&t);
8038032Speter
8138032Speter	/*
8238032Speter	**  Crack the UNIX date line in a singularly unoriginal way.
8338032Speter	*/
8438032Speter
8538032Speter	q = b;
8638032Speter
8738032Speter	p = &ud[0];		/* Mon */
8838032Speter	*q++ = *p++;
8938032Speter	*q++ = *p++;
9038032Speter	*q++ = *p++;
9138032Speter	*q++ = ',';
9238032Speter	*q++ = ' ';
9338032Speter
9438032Speter	p = &ud[8];		/* 16 */
9538032Speter	if (*p == ' ')
9638032Speter		p++;
9738032Speter	else
9838032Speter		*q++ = *p++;
9938032Speter	*q++ = *p++;
10038032Speter	*q++ = ' ';
10138032Speter
10238032Speter	p = &ud[4];		/* Sep */
10338032Speter	*q++ = *p++;
10438032Speter	*q++ = *p++;
10538032Speter	*q++ = *p++;
10638032Speter	*q++ = ' ';
10738032Speter
10838032Speter	p = &ud[20];		/* 1979 */
10938032Speter	*q++ = *p++;
11038032Speter	*q++ = *p++;
11138032Speter	*q++ = *p++;
11238032Speter	*q++ = *p++;
11338032Speter	*q++ = ' ';
11438032Speter
11538032Speter	p = &ud[11];		/* 01:03:52 */
11638032Speter	for (i = 8; i > 0; i--)
11738032Speter		*q++ = *p++;
11838032Speter
11938032Speter	/*
12077349Sgshapiro	**  should really get the timezone from the time in "ud" (which
12177349Sgshapiro	**  is only different if a non-null arg was passed which is different
12277349Sgshapiro	**  from the current time), but for all practical purposes, returning
12377349Sgshapiro	**  the current local zone will do (its all that is ever needed).
12477349Sgshapiro	*/
12577349Sgshapiro
12638032Speter	gmt = *gmtime(&t);
12738032Speter	lt = localtime(&t);
12838032Speter
12938032Speter	off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min;
13038032Speter
13138032Speter	/* assume that offset isn't more than a day ... */
13238032Speter	if (lt->tm_year < gmt.tm_year)
13338032Speter		off -= 24 * 60;
13438032Speter	else if (lt->tm_year > gmt.tm_year)
13538032Speter		off += 24 * 60;
13638032Speter	else if (lt->tm_yday < gmt.tm_yday)
13738032Speter		off -= 24 * 60;
13838032Speter	else if (lt->tm_yday > gmt.tm_yday)
13938032Speter		off += 24 * 60;
14038032Speter
14138032Speter	*q++ = ' ';
14238032Speter	if (off == 0)
14338032Speter	{
14438032Speter		*q++ = 'G';
14538032Speter		*q++ = 'M';
14638032Speter		*q++ = 'T';
14738032Speter	}
14838032Speter	else
14938032Speter	{
15038032Speter		tz = NULL;
15138032Speter#if TZ_TYPE == TZ_TM_NAME
15238032Speter		tz = lt->tm_name;
15364562Sgshapiro#endif /* TZ_TYPE == TZ_TM_NAME */
15438032Speter#if TZ_TYPE == TZ_TM_ZONE
15538032Speter		tz = lt->tm_zone;
15664562Sgshapiro#endif /* TZ_TYPE == TZ_TM_ZONE */
15738032Speter#if TZ_TYPE == TZ_TZNAME
15838032Speter		{
15938032Speter			extern char *tzname[];
16038032Speter
16143730Speter			if (lt->tm_isdst > 0)
16243730Speter				tz = tzname[1];
16343730Speter			else if (lt->tm_isdst == 0)
16443730Speter				tz = tzname[0];
16543730Speter			else
16643730Speter				tz = NULL;
16738032Speter		}
16864562Sgshapiro#endif /* TZ_TYPE == TZ_TZNAME */
16938032Speter#if TZ_TYPE == TZ_TIMEZONE
17038032Speter		{
17138032Speter			extern char *timezone();
17238032Speter
17338032Speter			tz = timezone(off, lt->tm_isdst);
17438032Speter		}
17564562Sgshapiro#endif /* TZ_TYPE == TZ_TIMEZONE */
17638032Speter		if (off < 0)
17738032Speter		{
17838032Speter			off = -off;
17938032Speter			*q++ = '-';
18038032Speter		}
18138032Speter		else
18238032Speter			*q++ = '+';
18338032Speter
18438032Speter		if (off >= 24*60)		/* should be impossible */
18538032Speter			off = 23*60+59;		/* if not, insert silly value */
18638032Speter
18738032Speter		*q++ = (off / 600) + '0';
18838032Speter		*q++ = (off / 60) % 10 + '0';
18938032Speter		off %= 60;
19038032Speter		*q++ = (off / 10) + '0';
19138032Speter		*q++ = (off % 10) + '0';
19238032Speter		if (tz != NULL && *tz != '\0')
19338032Speter		{
19438032Speter			*q++ = ' ';
19538032Speter			*q++ = '(';
19638032Speter			while (*tz != '\0' && q < &b[sizeof b - 3])
19738032Speter				*q++ = *tz++;
19838032Speter			*q++ = ')';
19938032Speter		}
20038032Speter	}
20138032Speter	*q = '\0';
20238032Speter
20364562Sgshapiro	return b;
20438032Speter}
205