1 /* vi:ai:et:ts=8 sw=2
2  */
3 /*
4  * Copyright (c) 1994 Powerdog Industries.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, 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
13  *    in the documentation and/or other materials provided with the
14  *    distribution.
15  * 3. All advertising materials mentioning features or use of this
16  *    software must display the following acknowledgement:
17  *      This product includes software developed by Powerdog Industries.
18  * 4. The name of Powerdog Industries may not be used to endorse or
19  *    promote products derived from this software without specific prior
20  *    written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
23  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
32  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 /** \file
35   * \brief strptime() replacement
36   */
37 
38 
39 #include "wzd_all.h"
40 
41 #include <ctype.h>
42 #include <string.h>
43 #include <time.h>
44 
45 #include "wzd_strptime.h"
46 
47 #ifndef HAVE_STRPTIME
48 
49 extern void ascii_lower(char * s, unsigned int length);
50 #define lowercase_string(x) ascii_lower(x,strlen(x))
51 
52 
53 #define asizeof(a)      (sizeof (a) / sizeof ((a)[0]))
54 
55 
56 #ifndef sun
57 struct dtconv {
58         char    *abbrev_month_names[12];
59         char    *month_names[12];
60         char    *abbrev_weekday_names[7];
61         char    *weekday_names[7];
62         char    *time_format;
63         char    *sdate_format;
64         char    *dtime_format;
65         char    *am_string;
66         char    *pm_string;
67         char    *ldate_format;
68 };
69 #endif
70 
71 static struct dtconv    En_US = {
72         { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
73           "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" },
74         { "January", "February", "March", "April",
75           "May", "June", "July", "August",
76           "September", "October", "November", "December" },
77         { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" },
78         { "Sunday", "Monday", "Tuesday", "Wednesday",
79           "Thursday", "Friday", "Saturday" },
80         "%H:%M:%S",
81         "%m/%d/%y",
82         "%a %b %e %T %Z %Y",
83         "AM",
84         "PM",
85         "%A, %B, %e, %Y"
86 };
87 
88 #ifdef SUNOS4
89 extern int      strncasecmp();
90 #endif
91 
92 char    *
strptime(char * buf,char * fmt,struct tm * tm)93 strptime(char *buf, char *fmt, struct tm *tm)
94 {
95   char    c, *ptr;
96   int     i, j, len;
97 
98   ptr = fmt;
99   while (*ptr != 0) {
100     if (*buf == 0)
101       break;
102 
103     c = *ptr++;
104 
105     if (c != '%') {
106       if (isspace(c))
107         while (*buf != 0 && isspace(*buf))
108           buf++;
109       else if (c != *buf++)
110         return 0;
111       continue;
112     }
113 
114     c = *ptr++;
115     switch (c) {
116       case 0:
117       case '%':
118         if (*buf++ != '%')
119           return 0;
120         break;
121 
122       case 'C':
123         buf = strptime(buf, En_US.ldate_format, tm);
124         if (buf == 0)
125           return 0;
126         break;
127 
128       case 'c':
129         buf = strptime(buf, "%x %X", tm);
130         if (buf == 0)
131           return 0;
132         break;
133 
134       case 'D':
135         buf = strptime(buf, "%m/%d/%y", tm);
136         if (buf == 0)
137           return 0;
138         break;
139 
140       case 'R':
141         buf = strptime(buf, "%H:%M", tm);
142         if (buf == 0)
143           return 0;
144         break;
145 
146       case 'r':
147         buf = strptime(buf, "%I:%M:%S %p", tm);
148         if (buf == 0)
149           return 0;
150         break;
151 
152       case 'T':
153         buf = strptime(buf, "%H:%M:%S", tm);
154         if (buf == 0)
155           return 0;
156         break;
157 
158       case 'X':
159         buf = strptime(buf, En_US.time_format, tm);
160         if (buf == 0)
161           return 0;
162         break;
163 
164       case 'x':
165         buf = strptime(buf, En_US.sdate_format, tm);
166         if (buf == 0)
167           return 0;
168         break;
169 
170       case 'j':
171         if (!isdigit(*buf))
172           return 0;
173 
174         for (i = 0; *buf != 0 && isdigit(*buf); buf++) {
175           i *= 10;
176           i += *buf - '0';
177         }
178         if (i > 365)
179           return 0;
180 
181         tm->tm_yday = i;
182         break;
183 
184       case 'M':
185       case 'S':
186         if (*buf == 0 || isspace(*buf))
187           break;
188 
189         if (!isdigit(*buf))
190           return 0;
191 
192         for (j=0,i = 0; *buf != 0 && isdigit(*buf) && j<2; j++,buf++) {
193           i *= 10;
194           i += *buf - '0';
195         }
196         if (i > 59)
197           return 0;
198 
199         if (c == 'M')
200           tm->tm_min = i;
201         else
202           tm->tm_sec = i;
203 
204         if (*buf != 0 && isspace(*buf))
205           while (*ptr != 0 && !isspace(*ptr))
206             ptr++;
207         break;
208 
209       case 'H':
210       case 'I':
211       case 'k':
212       case 'l':
213         if (!isdigit(*buf))
214           return 0;
215 
216         for (j=0,i = 0; *buf != 0 && isdigit(*buf) && j<2; j++,buf++) {
217           i *= 10;
218           i += *buf - '0';
219         }
220         if (c == 'H' || c == 'k') {
221           if (i > 23)
222             return 0;
223         } else if (i > 11)
224           return 0;
225 
226         tm->tm_hour = i;
227 
228         if (*buf != 0 && isspace(*buf))
229           while (*ptr != 0 && !isspace(*ptr))
230             ptr++;
231         break;
232 
233       case 'p':
234         len = strlen(En_US.am_string);
235         lowercase_string( buf );
236 
237         if (strncmp(buf, En_US.am_string, len) == 0) {
238           if (tm->tm_hour > 12)
239             return 0;
240           if (tm->tm_hour == 12)
241             tm->tm_hour = 0;
242           buf += len;
243           break;
244         }
245 
246         len = strlen(En_US.pm_string);
247 
248         if (strncmp(buf, En_US.pm_string, len) == 0) {
249           if (tm->tm_hour > 12)
250             return 0;
251           if (tm->tm_hour != 12)
252             tm->tm_hour += 12;
253           buf += len;
254           break;
255         }
256 
257         return 0;
258 
259       case 'A':
260       case 'a':
261         for (i = 0; i < asizeof(En_US.weekday_names); i++) {
262           len = strlen(En_US.weekday_names[i]);
263 
264           lowercase_string( buf );
265 
266           if (strncmp(buf,
267                 En_US.weekday_names[i],
268                 len) == 0)
269             break;
270 
271           len = strlen(En_US.abbrev_weekday_names[i]);
272           if (strncmp(buf,
273                 En_US.abbrev_weekday_names[i],
274                 len) == 0)
275             break;
276         }
277         if (i == asizeof(En_US.weekday_names))
278           return 0;
279 
280         tm->tm_wday = i;
281         buf += len;
282         break;
283 
284       case 'd':
285       case 'e':
286         if (!isdigit(*buf))
287           return 0;
288 
289         for (j=0,i = 0; *buf != 0 && isdigit(*buf) && j<2; j++,buf++) {
290           i *= 10;
291           i += *buf - '0';
292         }
293         if (i > 31)
294           return 0;
295 
296         tm->tm_mday = i;
297 
298         if (*buf != 0 && isspace(*buf))
299           while (*ptr != 0 && !isspace(*ptr))
300             ptr++;
301         break;
302 
303       case 'B':
304       case 'b':
305       case 'h':
306         for (i = 0; i < asizeof(En_US.month_names); i++) {
307           len = strlen(En_US.month_names[i]);
308 
309           lowercase_string( buf );
310           if (strncmp(buf, En_US.month_names[i],len) == 0)
311             break;
312 
313           len = strlen(En_US.abbrev_month_names[i]);
314           if (strncmp(buf,
315                 En_US.abbrev_month_names[i],
316                 len) == 0)
317             break;
318         }
319         if (i == asizeof(En_US.month_names))
320           return 0;
321 
322         tm->tm_mon = i;
323         buf += len;
324         break;
325 
326       case 'm':
327         if (!isdigit(*buf))
328           return 0;
329 
330         for (j=0,i = 0; *buf != 0 && isdigit(*buf) && j<2; j++,buf++) {
331           i *= 10;
332           i += *buf - '0';
333         }
334         if (i < 1 || i > 12)
335           return 0;
336 
337         tm->tm_mon = i - 1;
338 
339         if (*buf != 0 && isspace(*buf))
340           while (*ptr != 0 && !isspace(*ptr))
341             ptr++;
342         break;
343 
344       case 'Y':
345       case 'y':
346         if (*buf == 0 || isspace(*buf))
347           break;
348 
349         if (!isdigit(*buf))
350           return 0;
351 
352         for (j=0,i = 0; *buf != 0 && isdigit(*buf) && j<((c=='Y')?4:2); j++,buf++) {
353           i *= 10;
354           i += *buf - '0';
355         }
356 
357         if (c == 'Y')
358           i -= 1900;
359         else if (i < 69) /*c=='y', 00-68 is for 20xx, the rest is for 19xx*/
360           i += 100;
361 
362         if (i < 0)
363           return 0;
364 
365         tm->tm_year = i;
366 
367         if (*buf != 0 && isspace(*buf))
368           while (*ptr != 0 && !isspace(*ptr))
369             ptr++;
370         break;
371     }
372   }
373 
374   return buf;
375 }
376 
377 #endif   /* ndef HAVE_STRPTIME */
378