xref: /illumos-gate/usr/src/cmd/sendmail/src/arpadate.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.
3*7c478bd9Sstevel@tonic-gate  *	All rights reserved.
4*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1988, 1993
6*7c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
7*7c478bd9Sstevel@tonic-gate  *
8*7c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
9*7c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
10*7c478bd9Sstevel@tonic-gate  * the sendmail distribution.
11*7c478bd9Sstevel@tonic-gate  *
12*7c478bd9Sstevel@tonic-gate  */
13*7c478bd9Sstevel@tonic-gate 
14*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
15*7c478bd9Sstevel@tonic-gate 
16*7c478bd9Sstevel@tonic-gate #include <sendmail.h>
17*7c478bd9Sstevel@tonic-gate 
18*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: arpadate.c,v 8.28 2001/02/14 14:45:47 ca Exp $")
19*7c478bd9Sstevel@tonic-gate 
20*7c478bd9Sstevel@tonic-gate /*
21*7c478bd9Sstevel@tonic-gate **  ARPADATE -- Create date in ARPANET format
22*7c478bd9Sstevel@tonic-gate **
23*7c478bd9Sstevel@tonic-gate **	Parameters:
24*7c478bd9Sstevel@tonic-gate **		ud -- unix style date string.  if NULL, one is created.
25*7c478bd9Sstevel@tonic-gate **
26*7c478bd9Sstevel@tonic-gate **	Returns:
27*7c478bd9Sstevel@tonic-gate **		pointer to an ARPANET date field
28*7c478bd9Sstevel@tonic-gate **
29*7c478bd9Sstevel@tonic-gate **	Side Effects:
30*7c478bd9Sstevel@tonic-gate **		none
31*7c478bd9Sstevel@tonic-gate **
32*7c478bd9Sstevel@tonic-gate **	WARNING:
33*7c478bd9Sstevel@tonic-gate **		date is stored in a local buffer -- subsequent
34*7c478bd9Sstevel@tonic-gate **		calls will overwrite.
35*7c478bd9Sstevel@tonic-gate **
36*7c478bd9Sstevel@tonic-gate **	Bugs:
37*7c478bd9Sstevel@tonic-gate **		Timezone is computed from local time, rather than
38*7c478bd9Sstevel@tonic-gate **		from wherever (and whenever) the message was sent.
39*7c478bd9Sstevel@tonic-gate **		To do better is very hard.
40*7c478bd9Sstevel@tonic-gate **
41*7c478bd9Sstevel@tonic-gate **		Some sites are now inserting the timezone into the
42*7c478bd9Sstevel@tonic-gate **		local date.  This routine should figure out what
43*7c478bd9Sstevel@tonic-gate **		the format is and work appropriately.
44*7c478bd9Sstevel@tonic-gate */
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate #ifndef TZNAME_MAX
47*7c478bd9Sstevel@tonic-gate # define TZNAME_MAX	50	/* max size of timezone */
48*7c478bd9Sstevel@tonic-gate #endif /* ! TZNAME_MAX */
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate /* values for TZ_TYPE */
51*7c478bd9Sstevel@tonic-gate #define TZ_NONE		0	/* no character timezone support */
52*7c478bd9Sstevel@tonic-gate #define TZ_TM_NAME	1	/* use tm->tm_name */
53*7c478bd9Sstevel@tonic-gate #define TZ_TM_ZONE	2	/* use tm->tm_zone */
54*7c478bd9Sstevel@tonic-gate #define TZ_TZNAME	3	/* use tzname[] */
55*7c478bd9Sstevel@tonic-gate #define TZ_TIMEZONE	4	/* use timezone() */
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate char *
58*7c478bd9Sstevel@tonic-gate arpadate(ud)
59*7c478bd9Sstevel@tonic-gate 	register char *ud;
60*7c478bd9Sstevel@tonic-gate {
61*7c478bd9Sstevel@tonic-gate 	register char *p;
62*7c478bd9Sstevel@tonic-gate 	register char *q;
63*7c478bd9Sstevel@tonic-gate 	register int off;
64*7c478bd9Sstevel@tonic-gate 	register int i;
65*7c478bd9Sstevel@tonic-gate 	register struct tm *lt;
66*7c478bd9Sstevel@tonic-gate 	time_t t;
67*7c478bd9Sstevel@tonic-gate 	struct tm gmt;
68*7c478bd9Sstevel@tonic-gate 	char *tz;
69*7c478bd9Sstevel@tonic-gate 	static char b[43 + TZNAME_MAX];
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate 	/*
72*7c478bd9Sstevel@tonic-gate 	**  Get current time.
73*7c478bd9Sstevel@tonic-gate 	**	This will be used if a null argument is passed and
74*7c478bd9Sstevel@tonic-gate 	**	to resolve the timezone.
75*7c478bd9Sstevel@tonic-gate 	*/
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate 	/* SM_REQUIRE(ud == NULL || strlen(ud) >= 23); */
78*7c478bd9Sstevel@tonic-gate 	t = curtime();
79*7c478bd9Sstevel@tonic-gate 	if (ud == NULL)
80*7c478bd9Sstevel@tonic-gate 		ud = ctime(&t);
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate 	/*
83*7c478bd9Sstevel@tonic-gate 	**  Crack the UNIX date line in a singularly unoriginal way.
84*7c478bd9Sstevel@tonic-gate 	*/
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate 	q = b;
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate 	p = &ud[0];		/* Mon */
89*7c478bd9Sstevel@tonic-gate 	*q++ = *p++;
90*7c478bd9Sstevel@tonic-gate 	*q++ = *p++;
91*7c478bd9Sstevel@tonic-gate 	*q++ = *p++;
92*7c478bd9Sstevel@tonic-gate 	*q++ = ',';
93*7c478bd9Sstevel@tonic-gate 	*q++ = ' ';
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate 	p = &ud[8];		/* 16 */
96*7c478bd9Sstevel@tonic-gate 	if (*p == ' ')
97*7c478bd9Sstevel@tonic-gate 		p++;
98*7c478bd9Sstevel@tonic-gate 	else
99*7c478bd9Sstevel@tonic-gate 		*q++ = *p++;
100*7c478bd9Sstevel@tonic-gate 	*q++ = *p++;
101*7c478bd9Sstevel@tonic-gate 	*q++ = ' ';
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate 	p = &ud[4];		/* Sep */
104*7c478bd9Sstevel@tonic-gate 	*q++ = *p++;
105*7c478bd9Sstevel@tonic-gate 	*q++ = *p++;
106*7c478bd9Sstevel@tonic-gate 	*q++ = *p++;
107*7c478bd9Sstevel@tonic-gate 	*q++ = ' ';
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate 	p = &ud[20];		/* 1979 */
110*7c478bd9Sstevel@tonic-gate 	*q++ = *p++;
111*7c478bd9Sstevel@tonic-gate 	*q++ = *p++;
112*7c478bd9Sstevel@tonic-gate 	*q++ = *p++;
113*7c478bd9Sstevel@tonic-gate 	*q++ = *p++;
114*7c478bd9Sstevel@tonic-gate 	*q++ = ' ';
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate 	p = &ud[11];		/* 01:03:52 */
117*7c478bd9Sstevel@tonic-gate 	for (i = 8; i > 0; i--)
118*7c478bd9Sstevel@tonic-gate 		*q++ = *p++;
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate 	/*
121*7c478bd9Sstevel@tonic-gate 	**  should really get the timezone from the time in "ud" (which
122*7c478bd9Sstevel@tonic-gate 	**  is only different if a non-null arg was passed which is different
123*7c478bd9Sstevel@tonic-gate 	**  from the current time), but for all practical purposes, returning
124*7c478bd9Sstevel@tonic-gate 	**  the current local zone will do (its all that is ever needed).
125*7c478bd9Sstevel@tonic-gate 	*/
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate 	gmt = *gmtime(&t);
128*7c478bd9Sstevel@tonic-gate 	lt = localtime(&t);
129*7c478bd9Sstevel@tonic-gate 
130*7c478bd9Sstevel@tonic-gate 	off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min;
131*7c478bd9Sstevel@tonic-gate 
132*7c478bd9Sstevel@tonic-gate 	/* assume that offset isn't more than a day ... */
133*7c478bd9Sstevel@tonic-gate 	if (lt->tm_year < gmt.tm_year)
134*7c478bd9Sstevel@tonic-gate 		off -= 24 * 60;
135*7c478bd9Sstevel@tonic-gate 	else if (lt->tm_year > gmt.tm_year)
136*7c478bd9Sstevel@tonic-gate 		off += 24 * 60;
137*7c478bd9Sstevel@tonic-gate 	else if (lt->tm_yday < gmt.tm_yday)
138*7c478bd9Sstevel@tonic-gate 		off -= 24 * 60;
139*7c478bd9Sstevel@tonic-gate 	else if (lt->tm_yday > gmt.tm_yday)
140*7c478bd9Sstevel@tonic-gate 		off += 24 * 60;
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate 	*q++ = ' ';
143*7c478bd9Sstevel@tonic-gate 	if (off == 0)
144*7c478bd9Sstevel@tonic-gate 	{
145*7c478bd9Sstevel@tonic-gate 		*q++ = 'G';
146*7c478bd9Sstevel@tonic-gate 		*q++ = 'M';
147*7c478bd9Sstevel@tonic-gate 		*q++ = 'T';
148*7c478bd9Sstevel@tonic-gate 	}
149*7c478bd9Sstevel@tonic-gate 	else
150*7c478bd9Sstevel@tonic-gate 	{
151*7c478bd9Sstevel@tonic-gate 		tz = NULL;
152*7c478bd9Sstevel@tonic-gate #if TZ_TYPE == TZ_TM_NAME
153*7c478bd9Sstevel@tonic-gate 		tz = lt->tm_name;
154*7c478bd9Sstevel@tonic-gate #endif /* TZ_TYPE == TZ_TM_NAME */
155*7c478bd9Sstevel@tonic-gate #if TZ_TYPE == TZ_TM_ZONE
156*7c478bd9Sstevel@tonic-gate 		tz = lt->tm_zone;
157*7c478bd9Sstevel@tonic-gate #endif /* TZ_TYPE == TZ_TM_ZONE */
158*7c478bd9Sstevel@tonic-gate #if TZ_TYPE == TZ_TZNAME
159*7c478bd9Sstevel@tonic-gate 		{
160*7c478bd9Sstevel@tonic-gate 			extern char *tzname[];
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 			if (lt->tm_isdst > 0)
163*7c478bd9Sstevel@tonic-gate 				tz = tzname[1];
164*7c478bd9Sstevel@tonic-gate 			else if (lt->tm_isdst == 0)
165*7c478bd9Sstevel@tonic-gate 				tz = tzname[0];
166*7c478bd9Sstevel@tonic-gate 			else
167*7c478bd9Sstevel@tonic-gate 				tz = NULL;
168*7c478bd9Sstevel@tonic-gate 		}
169*7c478bd9Sstevel@tonic-gate #endif /* TZ_TYPE == TZ_TZNAME */
170*7c478bd9Sstevel@tonic-gate #if TZ_TYPE == TZ_TIMEZONE
171*7c478bd9Sstevel@tonic-gate 		{
172*7c478bd9Sstevel@tonic-gate 			extern char *timezone();
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 			tz = timezone(off, lt->tm_isdst);
175*7c478bd9Sstevel@tonic-gate 		}
176*7c478bd9Sstevel@tonic-gate #endif /* TZ_TYPE == TZ_TIMEZONE */
177*7c478bd9Sstevel@tonic-gate 		if (off < 0)
178*7c478bd9Sstevel@tonic-gate 		{
179*7c478bd9Sstevel@tonic-gate 			off = -off;
180*7c478bd9Sstevel@tonic-gate 			*q++ = '-';
181*7c478bd9Sstevel@tonic-gate 		}
182*7c478bd9Sstevel@tonic-gate 		else
183*7c478bd9Sstevel@tonic-gate 			*q++ = '+';
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 		if (off >= 24*60)		/* should be impossible */
186*7c478bd9Sstevel@tonic-gate 			off = 23*60+59;		/* if not, insert silly value */
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate 		*q++ = (off / 600) + '0';
189*7c478bd9Sstevel@tonic-gate 		*q++ = (off / 60) % 10 + '0';
190*7c478bd9Sstevel@tonic-gate 		off %= 60;
191*7c478bd9Sstevel@tonic-gate 		*q++ = (off / 10) + '0';
192*7c478bd9Sstevel@tonic-gate 		*q++ = (off % 10) + '0';
193*7c478bd9Sstevel@tonic-gate 		if (tz != NULL && *tz != '\0')
194*7c478bd9Sstevel@tonic-gate 		{
195*7c478bd9Sstevel@tonic-gate 			*q++ = ' ';
196*7c478bd9Sstevel@tonic-gate 			*q++ = '(';
197*7c478bd9Sstevel@tonic-gate 			while (*tz != '\0' && q < &b[sizeof b - 3])
198*7c478bd9Sstevel@tonic-gate 				*q++ = *tz++;
199*7c478bd9Sstevel@tonic-gate 			*q++ = ')';
200*7c478bd9Sstevel@tonic-gate 		}
201*7c478bd9Sstevel@tonic-gate 	}
202*7c478bd9Sstevel@tonic-gate 	*q = '\0';
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 	return b;
205*7c478bd9Sstevel@tonic-gate }
206