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