1 /*
2 **  Sendmail
3 **  Copyright (c) 1983  Eric P. Allman
4 **  Berkeley, California
5 **
6 **  Copyright (c) 1983 Regents of the University of California.
7 **  All rights reserved.  The Berkeley software License Agreement
8 **  specifies the terms and conditions for redistribution.
9 */
10 
11 #ifndef lint
12 static char	SccsId[] = "@(#)arpadate.c	5.3 (Berkeley) 06/08/85";
13 #endif not lint
14 
15 # include "conf.h"
16 # ifdef USG
17 # include <time.h>
18 # else
19 # include <sys/time.h>
20 # ifndef V6
21 # include <sys/types.h>
22 # include <sys/timeb.h>
23 # endif V6
24 # endif USG
25 # include "useful.h"
26 
27 # ifdef V6
28 # define OLDTIME
29 # endif V6
30 # ifdef USG
31 # define OLDTIME
32 # endif USG
33 
34 /*
35 **  ARPADATE -- Create date in ARPANET format
36 **
37 **	Parameters:
38 **		ud -- unix style date string.  if NULL, one is created.
39 **
40 **	Returns:
41 **		pointer to an ARPANET date field
42 **
43 **	Side Effects:
44 **		none
45 **
46 **	WARNING:
47 **		date is stored in a local buffer -- subsequent
48 **		calls will overwrite.
49 **
50 **	Bugs:
51 **		Timezone is computed from local time, rather than
52 **		from whereever (and whenever) the message was sent.
53 **		To do better is very hard.
54 **
55 **		Some sites are now inserting the timezone into the
56 **		local date.  This routine should figure out what
57 **		the format is and work appropriately.
58 */
59 
60 char *
61 arpadate(ud)
62 	register char *ud;
63 {
64 	register char *p;
65 	register char *q;
66 	static char b[40];
67 	extern char *ctime();
68 	register int i;
69 	extern struct tm *localtime();
70 	extern bool fconvert();
71 # ifdef OLDTIME
72 	long t;
73 	extern long time();
74 # else OLDTIME
75 	struct timeb t;
76 	extern struct timeb *ftime();
77 	extern char *timezone();
78 # endif OLDTIME
79 # ifdef V6
80 	extern char *StdTimezone, *DstTimezone;
81 # endif V6
82 # ifdef USG
83 	extern char *tzname[2];
84 # endif USG
85 
86 	/*
87 	**  Get current time.
88 	**	This will be used if a null argument is passed and
89 	**	to resolve the timezone.
90 	*/
91 
92 # ifdef OLDTIME
93 	(void) time(&t);
94 	if (ud == NULL)
95 		ud = ctime(&t);
96 # else
97 	ftime(&t);
98 	if (ud == NULL)
99 		ud = ctime(&t.time);
100 # endif OLDTIME
101 
102 	/*
103 	**  Crack the UNIX date line in a singularly unoriginal way.
104 	*/
105 
106 	q = b;
107 
108 	p = &ud[0];		/* Mon */
109 	*q++ = *p++;
110 	*q++ = *p++;
111 	*q++ = *p++;
112 	*q++ = ',';
113 	*q++ = ' ';
114 
115 	p = &ud[8];		/* 16 */
116 	if (*p == ' ')
117 		p++;
118 	else
119 		*q++ = *p++;
120 	*q++ = *p++;
121 	*q++ = ' ';
122 
123 	p = &ud[4];		/* Sep */
124 	*q++ = *p++;
125 	*q++ = *p++;
126 	*q++ = *p++;
127 	*q++ = ' ';
128 
129 	p = &ud[22];		/* 79 */
130 	*q++ = *p++;
131 	*q++ = *p++;
132 	*q++ = ' ';
133 
134 	p = &ud[11];		/* 01:03:52 */
135 	for (i = 8; i > 0; i--)
136 		*q++ = *p++;
137 
138 				/* -PST or -PDT */
139 # ifdef V6
140 	if (localtime(&t)->tm_isdst)
141 		p = DstTimezone;
142 	else
143 		p = StdTimezone;
144 # else
145 # ifdef USG
146 	if (localtime(&t)->tm_isdst)
147 		p = tzname[1];
148 	else
149 		p = tzname[0];
150 # else
151 	p = timezone(t.timezone, localtime(&t.time)->tm_isdst);
152 # endif USG
153 # endif V6
154 	if ((strncmp(p, "GMT", 3) == 0 || strncmp(p, "gmt", 3) == 0) &&
155 	    p[3] != '\0')
156 	{
157 		/* hours from GMT */
158 		p += 3;
159 		*q++ = *p++;
160 		if (p[1] == ':')
161 			*q++ = '0';
162 		else
163 			*q++ = *p++;
164 		*q++ = *p++;
165 		p++;		/* skip ``:'' */
166 		*q++ = *p++;
167 		*q++ = *p++;
168 		*q = '\0';
169 	}
170 	else if (!fconvert(p, q))
171 	{
172 		*q++ = ' ';
173 		*q++ = *p++;
174 		*q++ = *p++;
175 		*q++ = *p++;
176 		*q = '\0';
177 	}
178 
179 	return (b);
180 }
181 /*
182 **  FCONVERT -- convert foreign timezones to ARPA timezones
183 **
184 **	This routine is essentially from Teus Hagen.
185 **
186 **	Parameters:
187 **		a -- timezone as returned from UNIX.
188 **		b -- place to put ARPA-style timezone.
189 **
190 **	Returns:
191 **		TRUE -- if a conversion was made (and b was filled in).
192 **		FALSE -- if this is not a recognized local time.
193 **
194 **	Side Effects:
195 **		none.
196 */
197 
198 /* UNIX to arpa conversion table */
199 struct foreign
200 {
201 	char *f_from;
202 	char *f_to;
203 };
204 
205 static struct foreign Foreign[] =
206 {
207 	{ "EET",	" -0200" },	/* eastern europe */
208 	{ "MET",	" -0100" },	/* middle europe */
209 	{ "WET",	" GMT"   },	/* western europe */
210 	{ "EET DST",	" -0300" },	/* daylight saving times */
211 	{ "MET DST",	" -0200" },
212 	{ "WET DST",	" -0100" },
213 	{ NULL,		NULL	 }
214 };
215 
216 bool
217 fconvert(a, b)
218 	register char *a;
219 	char *b;
220 {
221 	register struct foreign *euptr;
222 	register char *p;
223 
224 	for (euptr = Foreign; euptr->f_from != NULL; euptr++)
225 	{
226 		extern bool sameword();
227 
228 		if (sameword(euptr->f_from, a))
229 		{
230 			p = euptr->f_to;
231 			while (*p)
232 				*b++ = *p++;
233 			*b = '\0';
234 			return (TRUE);
235 		}
236 	}
237 	return (FALSE);
238 }
239