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