xref: /386bsd/usr/src/usr.sbin/sendmail/src/arpadate.c (revision a2142627)
1 /*
2  * Copyright (c) 1983 Eric P. Allman
3  * Copyright (c) 1988, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *	This product includes software developed by the University of
17  *	California, Berkeley and its contributors.
18  * 4. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #ifndef lint
36 static char sccsid[] = "@(#)arpadate.c	8.1 (Berkeley) 6/7/93";
37 #endif /* not lint */
38 
39 # include "sendmail.h"
40 
41 /*
42 **  ARPADATE -- Create date in ARPANET format
43 **
44 **	Parameters:
45 **		ud -- unix style date string.  if NULL, one is created.
46 **
47 **	Returns:
48 **		pointer to an ARPANET date field
49 **
50 **	Side Effects:
51 **		none
52 **
53 **	WARNING:
54 **		date is stored in a local buffer -- subsequent
55 **		calls will overwrite.
56 **
57 **	Bugs:
58 **		Timezone is computed from local time, rather than
59 **		from whereever (and whenever) the message was sent.
60 **		To do better is very hard.
61 **
62 **		Some sites are now inserting the timezone into the
63 **		local date.  This routine should figure out what
64 **		the format is and work appropriately.
65 */
66 
67 char *
arpadate(ud)68 arpadate(ud)
69 	register char *ud;
70 {
71 	register char *p;
72 	register char *q;
73 	register int off;
74 	register int i;
75 	register struct tm *lt;
76 	time_t t;
77 	struct tm gmt;
78 	static char b[40];
79 
80 	/*
81 	**  Get current time.
82 	**	This will be used if a null argument is passed and
83 	**	to resolve the timezone.
84 	*/
85 
86 	(void) time(&t);
87 	if (ud == NULL)
88 		ud = ctime(&t);
89 
90 	/*
91 	**  Crack the UNIX date line in a singularly unoriginal way.
92 	*/
93 
94 	q = b;
95 
96 	p = &ud[0];		/* Mon */
97 	*q++ = *p++;
98 	*q++ = *p++;
99 	*q++ = *p++;
100 	*q++ = ',';
101 	*q++ = ' ';
102 
103 	p = &ud[8];		/* 16 */
104 	if (*p == ' ')
105 		p++;
106 	else
107 		*q++ = *p++;
108 	*q++ = *p++;
109 	*q++ = ' ';
110 
111 	p = &ud[4];		/* Sep */
112 	*q++ = *p++;
113 	*q++ = *p++;
114 	*q++ = *p++;
115 	*q++ = ' ';
116 
117 	p = &ud[20];		/* 1979 */
118 	*q++ = *p++;
119 	*q++ = *p++;
120 	*q++ = *p++;
121 	*q++ = *p++;
122 	*q++ = ' ';
123 
124 	p = &ud[11];		/* 01:03:52 */
125 	for (i = 8; i > 0; i--)
126 		*q++ = *p++;
127 
128 	/*
129 	 * should really get the timezone from the time in "ud" (which
130 	 * is only different if a non-null arg was passed which is different
131 	 * from the current time), but for all practical purposes, returning
132 	 * the current local zone will do (its all that is ever needed).
133 	 */
134 	gmt = *gmtime(&t);
135 	lt = localtime(&t);
136 
137 	off = (lt->tm_hour - gmt.tm_hour) * 60 + lt->tm_min - gmt.tm_min;
138 
139 	/* assume that offset isn't more than a day ... */
140 	if (lt->tm_year < gmt.tm_year)
141 		off -= 24 * 60;
142 	else if (lt->tm_year > gmt.tm_year)
143 		off += 24 * 60;
144 	else if (lt->tm_yday < gmt.tm_yday)
145 		off -= 24 * 60;
146 	else if (lt->tm_yday > gmt.tm_yday)
147 		off += 24 * 60;
148 
149 	*q++ = ' ';
150 	if (off == 0) {
151 		*q++ = 'G';
152 		*q++ = 'M';
153 		*q++ = 'T';
154 	} else {
155 		if (off < 0) {
156 			off = -off;
157 			*q++ = '-';
158 		} else
159 			*q++ = '+';
160 
161 		if (off >= 24*60)		/* should be impossible */
162 			off = 23*60+59;		/* if not, insert silly value */
163 
164 		*q++ = (off / 600) + '0';
165 		*q++ = (off / 60) % 10 + '0';
166 		off %= 60;
167 		*q++ = (off / 10) + '0';
168 		*q++ = (off % 10) + '0';
169 	}
170 	*q = '\0';
171 
172 	return (b);
173 }
174