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