Handle alternate access method flag in ls.
[exim.git] / src / src / tod.c
CommitLineData
059ec3d9
PH
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
0a49a7a4 5/* Copyright (c) University of Cambridge 1995 - 2009 */
059ec3d9
PH
6/* See the file NOTICE for conditions of use and distribution. */
7
8/* A function for returning the time of day in various formats */
9
10
11#include "exim.h"
12
13/* #define TESTING_LOG_DATESTAMP */
14
15
16static uschar timebuf[sizeof("www, dd-mmm-yyyy hh:mm:ss +zzzz")];
17
18
19/*************************************************
20* Return timestamp *
21*************************************************/
22
23/* The log timestamp format is dd-mmm-yy so as to be non-confusing on both
24sides of the Atlantic. We calculate an explicit numerical offset from GMT for
25the full datestamp and BSD inbox datestamp. Note that on some systems
26localtime() and gmtime() re-use the same store, so we must save the local time
27values before calling gmtime(). If timestamps_utc is set, don't use
28localtime(); all times are then in UTC (with offset +0000).
29
30There are also some contortions to get the day of the month without
31a leading zero for the full stamp, since Ustrftime() doesn't provide this
32option.
33
34Argument: type of timestamp required:
f1e5fef5
PP
35 tod_bsdin BSD inbox format
36 tod_epoch Unix epoch format
37 tod_full full date and time
38 tod_log log file data line format,
39 with zone if log_timezone is TRUE
40 tod_log_bare always without zone
41 tod_log_datestamp_daily for log file names when datestamped daily
42 tod_log_datestamp_monthly for log file names when datestamped monthly
43 tod_log_zone always with zone
44 tod_mbx MBX inbox format
45 tod_zone just the timezone offset
46 tod_zulu time in 8601 zulu format
059ec3d9
PH
47
48Returns: pointer to fixed buffer containing the timestamp
49*/
50
51uschar *
52tod_stamp(int type)
53{
54time_t now = time(NULL);
55struct tm *t;
56
57/* Vary log type according to timezone requirement */
58
59if (type == tod_log) type = log_timezone? tod_log_zone : tod_log_bare;
60
61/* Styles that don't need local time */
62
63else if (type == tod_epoch)
64 {
65 (void) sprintf(CS timebuf, "%d", (int)now); /* Unix epoch format */
66 return timebuf;
67 }
68
69else if (type == tod_zulu)
70 {
71 t = gmtime(&now);
72 (void) sprintf(CS timebuf, "%04d%02d%02d%02d%02d%02dZ",
73 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min,
74 t->tm_sec);
75 return timebuf;
76 }
77
78/* Convert to local time or UTC */
79
80t = timestamps_utc? gmtime(&now) : localtime(&now);
81
82switch(type)
83 {
84 case tod_log_bare: /* Format used in logging without timezone */
85 (void) sprintf(CS timebuf, "%04d-%02d-%02d %02d:%02d:%02d",
86 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday,
87 t->tm_hour, t->tm_min, t->tm_sec);
88 break;
89
90 /* Format used as suffix of log file name when 'log_datestamp' is active. For
91 testing purposes, it changes the file every second. */
92
059ec3d9 93 #ifdef TESTING_LOG_DATESTAMP
f1e5fef5
PP
94 case tod_log_datestamp_daily:
95 case tod_log_datestamp_monthly:
059ec3d9
PH
96 (void) sprintf(CS timebuf, "%04d%02d%02d%02d%02d",
97 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min);
f1e5fef5
PP
98 break;
99
059ec3d9 100 #else
f1e5fef5 101 case tod_log_datestamp_daily:
059ec3d9
PH
102 (void) sprintf(CS timebuf, "%04d%02d%02d",
103 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday);
059ec3d9
PH
104 break;
105
f1e5fef5
PP
106 case tod_log_datestamp_monthly:
107 (void) sprintf(CS timebuf, "%04d%02d",
108 1900 + t->tm_year, 1 + t->tm_mon);
109 break;
110 #endif
111
059ec3d9
PH
112 /* Format used in BSD inbox separator lines. Sort-of documented in RFC 976
113 ("UUCP Mail Interchange Format Standard") but only by example, not by
114 explicit definition. The examples show no timezone offsets, and some MUAs
115 appear to be sensitive to this, so Exim has been changed to remove the
116 timezone offsets that originally appeared. */
117
118 case tod_bsdin:
119 {
120 int len = Ustrftime(timebuf, sizeof(timebuf), "%a %b %d %H:%M:%S", t);
121 Ustrftime(timebuf + len, sizeof(timebuf) - len, " %Y", t);
122 }
123 break;
124
125 /* Other types require the GMT offset to be calculated, or just set up in the
126 case of UTC timestamping. We need to take a copy of the local time first. */
127
128 default:
129 {
130 int diff_hour, diff_min;
131 struct tm local;
132 memcpy(&local, t, sizeof(struct tm));
133
134 if (timestamps_utc)
135 {
136 diff_hour = diff_min = 0;
137 }
138 else
139 {
140 struct tm *gmt = gmtime(&now);
141 diff_min = 60*(local.tm_hour - gmt->tm_hour) + local.tm_min - gmt->tm_min;
142 if (local.tm_year != gmt->tm_year)
143 diff_min += (local.tm_year > gmt->tm_year)? 1440 : -1440;
144 else if (local.tm_yday != gmt->tm_yday)
145 diff_min += (local.tm_yday > gmt->tm_yday)? 1440 : -1440;
146 diff_hour = diff_min/60;
147 diff_min = abs(diff_min - diff_hour*60);
148 }
149
150 switch(type)
151 {
152 case tod_log_zone: /* Format used in logging with timezone */
153 (void) sprintf(CS timebuf, "%04d-%02d-%02d %02d:%02d:%02d %+03d%02d",
154 1900 + local.tm_year, 1 + local.tm_mon, local.tm_mday,
155 local.tm_hour, local.tm_min, local.tm_sec,
156 diff_hour, diff_min);
157 break;
158
159 case tod_zone: /* Just the timezone offset */
160 (void) sprintf(CS timebuf, "%+03d%02d", diff_hour, diff_min);
161 break;
162
163 /* tod_mbx: format used in MBX mailboxes - subtly different to tod_full */
164
165 #ifdef SUPPORT_MBX
166 case tod_mbx:
167 {
168 int len;
169 (void) sprintf(CS timebuf, "%02d-", local.tm_mday);
170 len = Ustrlen(timebuf);
171 len += Ustrftime(timebuf + len, sizeof(timebuf) - len, "%b-%Y %H:%M:%S",
172 &local);
173 (void) sprintf(CS timebuf + len, " %+03d%02d", diff_hour, diff_min);
174 }
175 break;
176 #endif
177
178 /* tod_full: format used in Received: headers (use as default just in case
179 called with a junk type value) */
180
181 default:
182 {
183 int len = Ustrftime(timebuf, sizeof(timebuf), "%a, ", &local);
184 (void) sprintf(CS timebuf + len, "%02d ", local.tm_mday);
185 len += Ustrlen(timebuf + len);
186 len += Ustrftime(timebuf + len, sizeof(timebuf) - len, "%b %Y %H:%M:%S",
187 &local);
188 (void) sprintf(CS timebuf + len, " %+03d%02d", diff_hour, diff_min);
189 }
190 break;
191 }
192 }
193 break;
194 }
195
196return timebuf;
197}
198
199/* End of tod.c */