1*22695Sdist /*
2*22695Sdist **  Sendmail
3*22695Sdist **  Copyright (c) 1983  Eric P. Allman
4*22695Sdist **  Berkeley, California
5*22695Sdist **
6*22695Sdist **  Copyright (c) 1983 Regents of the University of California.
7*22695Sdist **  All rights reserved.  The Berkeley software License Agreement
8*22695Sdist **  specifies the terms and conditions for redistribution.
9*22695Sdist */
10*22695Sdist 
11*22695Sdist #ifndef lint
12*22695Sdist static char	SccsId[] = "@(#)arpadate.c	5.1 (Berkeley) 06/07/85";
13*22695Sdist #endif not lint
14*22695Sdist 
159152Seric # include "conf.h"
1616895Seric # ifdef USG
1716895Seric # include <time.h>
1816895Seric # else
1913587Swnj # include <sys/time.h>
202897Seric # ifndef V6
212897Seric # include <sys/types.h>
222897Seric # include <sys/timeb.h>
2316895Seric # endif V6
2416895Seric # endif USG
254437Seric # include "useful.h"
26293Seric 
27*22695Sdist SCCSID(@(#)arpadate.c	5.1		06/07/85);
28403Seric 
2916895Seric # ifdef V6
3016895Seric # define OLDTIME
3116895Seric # endif V6
3216895Seric # ifdef USG
3316895Seric # define OLDTIME
3416895Seric # endif USG
3516895Seric 
36293Seric /*
37293Seric **  ARPADATE -- Create date in ARPANET format
38293Seric **
39293Seric **	Parameters:
402897Seric **		ud -- unix style date string.  if NULL, one is created.
41293Seric **
42293Seric **	Returns:
43293Seric **		pointer to an ARPANET date field
44293Seric **
45293Seric **	Side Effects:
46293Seric **		none
47293Seric **
48293Seric **	WARNING:
49293Seric **		date is stored in a local buffer -- subsequent
50293Seric **		calls will overwrite.
513185Seric **
523185Seric **	Bugs:
533185Seric **		Timezone is computed from local time, rather than
543185Seric **		from whereever (and whenever) the message was sent.
553185Seric **		To do better is very hard.
564315Seric **
574315Seric **		Some sites are now inserting the timezone into the
584315Seric **		local date.  This routine should figure out what
594315Seric **		the format is and work appropriately.
60293Seric */
61293Seric 
621586Seric char *
632897Seric arpadate(ud)
642897Seric 	register char *ud;
65293Seric {
66293Seric 	register char *p;
672897Seric 	register char *q;
68293Seric 	static char b[40];
691586Seric 	extern char *ctime();
702897Seric 	register int i;
712897Seric 	extern struct tm *localtime();
7215137Seric 	extern bool fconvert();
7316895Seric # ifdef OLDTIME
742897Seric 	long t;
754315Seric 	extern long time();
7616895Seric # else OLDTIME
772897Seric 	struct timeb t;
782897Seric 	extern struct timeb *ftime();
792897Seric 	extern char *timezone();
8016895Seric # endif OLDTIME
8116895Seric # ifdef V6
8216895Seric 	extern char *StdTimezone, *DstTimezone;
8316895Seric # endif V6
8416895Seric # ifdef USG
8516895Seric 	extern char *tzname[2];
8616895Seric # endif USG
87293Seric 
884315Seric 	/*
894315Seric 	**  Get current time.
904315Seric 	**	This will be used if a null argument is passed and
914315Seric 	**	to resolve the timezone.
924315Seric 	*/
934315Seric 
9416895Seric # ifdef OLDTIME
954315Seric 	(void) time(&t);
962897Seric 	if (ud == NULL)
972897Seric 		ud = ctime(&t);
982897Seric # else
992897Seric 	ftime(&t);
1002897Seric 	if (ud == NULL)
1012897Seric 		ud = ctime(&t.time);
10216895Seric # endif OLDTIME
103293Seric 
1044315Seric 	/*
1054315Seric 	**  Crack the UNIX date line in a singularly unoriginal way.
1064315Seric 	*/
1074315Seric 
1082897Seric 	q = b;
1092897Seric 
11013932Seric 	p = &ud[0];		/* Mon */
11113932Seric 	*q++ = *p++;
11213932Seric 	*q++ = *p++;
11313932Seric 	*q++ = *p++;
11413932Seric 	*q++ = ',';
11513932Seric 	*q++ = ' ';
11613932Seric 
117293Seric 	p = &ud[8];		/* 16 */
118293Seric 	if (*p == ' ')
119293Seric 		p++;
1202897Seric 	else
1212897Seric 		*q++ = *p++;
1222897Seric 	*q++ = *p++;
12310251Seric 	*q++ = ' ';
1242897Seric 
1255184Seric 	p = &ud[4];		/* Sep */
1265184Seric 	*q++ = *p++;
1275184Seric 	*q++ = *p++;
1285184Seric 	*q++ = *p++;
12910251Seric 	*q++ = ' ';
1302897Seric 
13113932Seric 	p = &ud[22];		/* 79 */
1325184Seric 	*q++ = *p++;
1335184Seric 	*q++ = *p++;
1342897Seric 	*q++ = ' ';
1352897Seric 
1362897Seric 	p = &ud[11];		/* 01:03:52 */
1375184Seric 	for (i = 8; i > 0; i--)
1382897Seric 		*q++ = *p++;
1392897Seric 
1402897Seric 				/* -PST or -PDT */
1412897Seric # ifdef V6
142293Seric 	if (localtime(&t)->tm_isdst)
1434315Seric 		p = DstTimezone;
144293Seric 	else
1454315Seric 		p = StdTimezone;
1462897Seric # else
14716895Seric # ifdef USG
14816895Seric 	if (localtime(&t)->tm_isdst)
14916895Seric 		p = tzname[1];
15016895Seric 	else
15116895Seric 		p = tzname[0];
15216895Seric # else
1532897Seric 	p = timezone(t.timezone, localtime(&t.time)->tm_isdst);
15416895Seric # endif USG
1552897Seric # endif V6
15615137Seric 	if ((strncmp(p, "GMT", 3) == 0 || strncmp(p, "gmt", 3) == 0) &&
15715137Seric 	    p[3] != '\0')
1582897Seric 	{
1592897Seric 		/* hours from GMT */
1602897Seric 		p += 3;
1612897Seric 		*q++ = *p++;
1622897Seric 		if (p[1] == ':')
1632897Seric 			*q++ = '0';
1642897Seric 		else
1652897Seric 			*q++ = *p++;
1662897Seric 		*q++ = *p++;
1672897Seric 		p++;		/* skip ``:'' */
1682897Seric 		*q++ = *p++;
1692897Seric 		*q++ = *p++;
17015109Skarels 		*q = '\0';
1712897Seric 	}
17215137Seric 	else if (!fconvert(p, q))
1732897Seric 	{
17410251Seric 		*q++ = ' ';
1752897Seric 		*q++ = *p++;
1762897Seric 		*q++ = *p++;
1772897Seric 		*q++ = *p++;
17815109Skarels 		*q = '\0';
1792897Seric 	}
1802897Seric 
181293Seric 	return (b);
182293Seric }
18315137Seric /*
18415137Seric **  FCONVERT -- convert foreign timezones to ARPA timezones
18515137Seric **
18615137Seric **	This routine is essentially from Teus Hagen.
18715137Seric **
18815137Seric **	Parameters:
18915137Seric **		a -- timezone as returned from UNIX.
19015137Seric **		b -- place to put ARPA-style timezone.
19115137Seric **
19215137Seric **	Returns:
19315137Seric **		TRUE -- if a conversion was made (and b was filled in).
19415137Seric **		FALSE -- if this is not a recognized local time.
19515137Seric **
19615137Seric **	Side Effects:
19715137Seric **		none.
19815137Seric */
19915109Skarels 
20015137Seric /* UNIX to arpa conversion table */
20115137Seric struct foreign
20215137Seric {
20315109Skarels 	char *f_from;
20415109Skarels 	char *f_to;
20515109Skarels };
20615109Skarels 
20715137Seric static struct foreign Foreign[] =
20815137Seric {
20916895Seric 	{ "EET",	" -0200" },	/* eastern europe */
21016895Seric 	{ "MET",	" -0100" },	/* middle europe */
21116895Seric 	{ "WET",	" GMT"   },	/* western europe */
21216895Seric 	{ "EET DST",	" -0300" },	/* daylight saving times */
21316895Seric 	{ "MET DST",	" -0200" },
21416895Seric 	{ "WET DST",	" -0100" },
21515137Seric 	{ NULL,		NULL	 }
21615137Seric };
21715109Skarels 
21815137Seric bool
21915137Seric fconvert(a, b)
22015137Seric 	register char *a;
22115137Seric 	char *b;
22215137Seric {
22315137Seric 	register struct foreign *euptr;
22415137Seric 	register char *p;
22515137Seric 
22615137Seric 	for (euptr = Foreign; euptr->f_from != NULL; euptr++)
22715137Seric 	{
22816895Seric 		if (sameword(euptr->f_from, a))
22915137Seric 		{
23015137Seric 			p = euptr->f_to;
23115137Seric 			while (*p)
23215137Seric 				*b++ = *p++;
23315109Skarels 			*b = '\0';
23415137Seric 			return (TRUE);
23515109Skarels 		}
23615137Seric 	}
23715137Seric 	return (FALSE);
23815109Skarels }
239