]> git.saurik.com Git - apple/libc.git/blame - stdtime/getdate.c
Libc-391.1.21.tar.gz
[apple/libc.git] / stdtime / getdate.c
CommitLineData
59e0d9fe
A
1/*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
59e0d9fe
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include <stdio.h>
25#include <time.h>
26#include <stdlib.h>
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <errno.h>
30
31enum {
32 DATEMSK_NOT_DEFINED = 1,
33 CANT_OPEN,
34 CANT_FSTAT,
35 NOT_FILE,
36 IO_ERROR,
37 OUT_OF_MEMORY,
38 NO_MATCH,
39 INVALID_DATE
40};
41
42#define DATEMSK "DATEMSK"
43#define TM_SEC_SET 0x01
44#define TM_MIN_SET 0x02
45#define TM_HOUR_SET 0x04
46#define TM_MDAY_SET 0x01
47#define TM_MON_SET 0x02
48#define TM_YEAR_SET 0x04
49#define UNDEFINED -1
50
51static struct tm tmundef = {
52 UNDEFINED,
53 UNDEFINED,
54 UNDEFINED,
55 UNDEFINED,
56 UNDEFINED,
57 UNDEFINED,
58 UNDEFINED
59};
60
61int getdate_err;
62
63/*
64 * getdate
65 *
66 * Call strptime() on each line of the DATEMSK file, and manipulate the
67 * resulting tm structure.
68 */
69struct tm *
70getdate(const char *str)
71{
72 static struct tm tm, *now, *result = NULL;
73 time_t t;
74 FILE *fp;
75 int bufsiz, offset, len, dateset, timeset, saveerrno, wday_set;
76 char *buf;
77 struct stat st;
78 char *file = getenv(DATEMSK);
79
80 if(!file || !*file) {
81 getdate_err = DATEMSK_NOT_DEFINED;
82 return NULL;
83 }
84 saveerrno = errno;
85 if((fp = fopen(file, "r")) == NULL) {
86 getdate_err = CANT_OPEN;
87 errno = saveerrno;
88 return NULL;
89 }
90 do {
91 if(fstat(fileno(fp), &st) < 0) {
92 getdate_err = CANT_FSTAT;
93 break;
94 }
95 if((st.st_mode & S_IFMT) != S_IFREG) {
96 getdate_err = NOT_FILE;
97 break;
98 }
99 if((buf = malloc(bufsiz = BUFSIZ)) == NULL) {
100 getdate_err = OUT_OF_MEMORY;
101 break;
102 }
103 do {
104 offset = 0;
105 for(;;) {
106 if(fgets(buf + offset, bufsiz - offset, fp) == NULL) {
107 if(ferror(fp)) {
108 getdate_err = IO_ERROR;
109 break;
110 }
111 if(offset == 0) {
112 getdate_err = NO_MATCH;
113 break;
114 }
115 len = strlen(buf);
116 } else if((len = strlen(buf)) == bufsiz - 1
117 && buf[len - 1] != '\n') {
118 char *newptr = realloc(buf, (bufsiz += BUFSIZ));
119 if(newptr == NULL) {
120 getdate_err = OUT_OF_MEMORY;
121 break;
122 }
123 buf = newptr;
124 offset = len;
125 continue;
126 }
127 if(buf[len - 1] == '\n')
128 buf[len - 1] = 0;
129 tm = tmundef;
130 if(strptime(str, buf, &tm) == NULL) {
131 offset = 0;
132 continue;
133 }
134 time(&t);
135 now = localtime(&t);
136 dateset = timeset = 0;
137 if(tm.tm_sec != UNDEFINED)
138 timeset |= TM_SEC_SET;
139 if(tm.tm_min != UNDEFINED)
140 timeset |= TM_MIN_SET;
141 if(tm.tm_hour != UNDEFINED)
142 timeset |= TM_HOUR_SET;
143 if(tm.tm_mday != UNDEFINED)
144 dateset |= TM_MDAY_SET;
145 if(tm.tm_mon != UNDEFINED)
146 dateset |= TM_MON_SET;
147 if(tm.tm_year != UNDEFINED)
148 dateset |= TM_YEAR_SET;
149 wday_set = tm.tm_wday;
150
151 switch(timeset) {
152 case 0:
153 tm.tm_sec = now->tm_sec;
154 tm.tm_min = now->tm_min;
155 tm.tm_hour = now->tm_hour;
156 break;
157
158 case TM_SEC_SET:
159 tm.tm_hour = now->tm_hour;
160 tm.tm_min = now->tm_min;
161 if(tm.tm_sec < now->tm_sec)
162 tm.tm_min++;
163 break;
164
165 case TM_MIN_SET:
166 tm.tm_hour = now->tm_hour;
167 if(tm.tm_min < now->tm_min)
168 tm.tm_hour++;
169 tm.tm_sec = 0;
170 break;
171
172 case TM_MIN_SET | TM_SEC_SET:
173 tm.tm_hour = now->tm_hour;
174 if((60 * tm.tm_min + tm.tm_sec)
175 < (60 * now->tm_min + now->tm_sec))
176 tm.tm_hour++;
177 break;
178
179 case TM_HOUR_SET:
180 tm.tm_min = 0;
181 tm.tm_sec = 0;
182 break;
183
184 case TM_HOUR_SET | TM_SEC_SET:
185 tm.tm_min = 0;
186 break;
187
188 case TM_HOUR_SET | TM_MIN_SET:
189 tm.tm_sec = 0;
190 break;
191 }
192
193 switch(dateset) {
194 case 0:
195 tm.tm_mday = now->tm_mday;
196 if(tm.tm_hour < now->tm_hour)
197 tm.tm_mday++;
198 tm.tm_mon = now->tm_mon;
199 tm.tm_year = now->tm_year;
200 break;
201
202 case TM_MDAY_SET:
203 tm.tm_year = now->tm_year;
204 tm.tm_mon = now->tm_mon;
205 if(tm.tm_mday < now->tm_mday)
206 tm.tm_mon++;
207 break;
208
209 case TM_MON_SET:
210 case TM_MON_SET | TM_MDAY_SET:
211 tm.tm_year = now->tm_year;
212 if(tm.tm_mon < now->tm_mon)
213 tm.tm_year++;
214 if(!(dateset & TM_MDAY_SET))
215 tm.tm_mday = 1;
216 break;
217
218 case TM_YEAR_SET:
219 case TM_YEAR_SET | TM_MON_SET:
220 if(!(dateset & TM_MON_SET))
221 tm.tm_mon = 1;
222 tm.tm_mday = 1;
223 break;
224
225 case TM_YEAR_SET | TM_MDAY_SET:
226 tm.tm_mon = now->tm_mon;
227 if(tm.tm_mday < now->tm_mday)
228 tm.tm_mon++;
229 break;
230 }
231
232 tm.tm_wday = now->tm_wday;
233 tm.tm_gmtoff = now->tm_gmtoff; /* XXX: can't grok timezones */
234 tm.tm_isdst = -1;
235
236 if(mktime(&tm) == (time_t)-1) {
237 getdate_err = INVALID_DATE;
238 break;
239 }
240 if(wday_set != UNDEFINED) {
241 int delta = wday_set - tm.tm_wday;
242 if(delta && (dateset & TM_MDAY_SET)) {
243 getdate_err = INVALID_DATE;
244 break;
245 }
246 if(delta < 0)
247 delta += 7;
248 tm.tm_mday += delta;
249 if(mktime(&tm) == (time_t)-1) {
250 getdate_err = INVALID_DATE;
251 break;
252 }
253 }
254 result = &tm;
255 }
256 } while(0);
257
258 free(buf);
259 } while(0);
260
261 fclose(fp);
262 errno = saveerrno;
263 return result;
264}