1 | /* |
2 | * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") |
3 | * Copyright (c) 1999 by Internet Software Consortium. |
4 | * |
5 | * Permission to use, copy, modify, and distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above |
7 | * copyright notice and this permission notice appear in all copies. |
8 | * |
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES |
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR |
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
15 | * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | */ |
17 | |
18 | #if !defined(_LIBC) && !defined(lint) |
19 | static const char rcsid[] = "$Id$" ; |
20 | #endif |
21 | |
22 | /* Import. */ |
23 | |
24 | #include <arpa/nameser.h> |
25 | |
26 | #include <ctype.h> |
27 | #include <errno.h> |
28 | #include <stdio.h> |
29 | #include <string.h> |
30 | #include <time.h> |
31 | |
32 | #define SPRINTF(x) ((size_t)sprintf x) |
33 | |
34 | /* Forward. */ |
35 | |
36 | static int datepart(const char *, int, int, int, int *); |
37 | |
38 | /* Public. */ |
39 | |
40 | /*% |
41 | * Convert a date in ASCII into the number of seconds since |
42 | * 1 January 1970 (GMT assumed). Format is yyyymmddhhmmss, all |
43 | * digits required, no spaces allowed. |
44 | */ |
45 | |
46 | u_int32_t |
47 | ns_datetosecs(const char *cp, int *errp) { |
48 | struct tm time; |
49 | u_int32_t result; |
50 | int mdays, i; |
51 | static const int days_per_month[12] = |
52 | {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
53 | |
54 | if (strlen(cp) != 14U) { |
55 | *errp = 1; |
56 | return (0); |
57 | } |
58 | *errp = 0; |
59 | |
60 | memset(&time, 0, sizeof time); |
61 | time.tm_year = datepart(cp + 0, 4, 1990, 9999, errp) - 1900; |
62 | time.tm_mon = datepart(cp + 4, 2, 01, 12, errp) - 1; |
63 | time.tm_mday = datepart(cp + 6, 2, 01, 31, errp); |
64 | time.tm_hour = datepart(cp + 8, 2, 00, 23, errp); |
65 | time.tm_min = datepart(cp + 10, 2, 00, 59, errp); |
66 | time.tm_sec = datepart(cp + 12, 2, 00, 59, errp); |
67 | if (*errp) /*%< Any parse errors? */ |
68 | return (0); |
69 | |
70 | /* |
71 | * OK, now because timegm() is not available in all environments, |
72 | * we will do it by hand. Roll up sleeves, curse the gods, begin! |
73 | */ |
74 | |
75 | #define SECS_PER_DAY ((u_int32_t)24*60*60) |
76 | #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) |
77 | |
78 | result = time.tm_sec; /*%< Seconds */ |
79 | result += time.tm_min * 60; /*%< Minutes */ |
80 | result += time.tm_hour * (60*60); /*%< Hours */ |
81 | result += (time.tm_mday - 1) * SECS_PER_DAY; /*%< Days */ |
82 | /* Months are trickier. Look without leaping, then leap */ |
83 | mdays = 0; |
84 | for (i = 0; i < time.tm_mon; i++) |
85 | mdays += days_per_month[i]; |
86 | result += mdays * SECS_PER_DAY; /*%< Months */ |
87 | if (time.tm_mon > 1 && isleap(1900+time.tm_year)) |
88 | result += SECS_PER_DAY; /*%< Add leapday for this year */ |
89 | /* First figure years without leapdays, then add them in. */ |
90 | /* The loop is slow, FIXME, but simple and accurate. */ |
91 | result += (time.tm_year - 70) * (SECS_PER_DAY*365); /*%< Years */ |
92 | for (i = 70; i < time.tm_year; i++) |
93 | if (isleap(1900+i)) |
94 | result += SECS_PER_DAY; /*%< Add leapday for prev year */ |
95 | return (result); |
96 | } |
97 | |
98 | /* Private. */ |
99 | |
100 | /*% |
101 | * Parse part of a date. Set error flag if any error. |
102 | * Don't reset the flag if there is no error. |
103 | */ |
104 | static int |
105 | datepart(const char *buf, int size, int min, int max, int *errp) { |
106 | int result = 0; |
107 | int i; |
108 | |
109 | for (i = 0; i < size; i++) { |
110 | if (!isdigit((unsigned char)(buf[i]))) |
111 | *errp = 1; |
112 | result = (result * 10) + buf[i] - '0'; |
113 | } |
114 | if (result < min) |
115 | *errp = 1; |
116 | if (result > max) |
117 | *errp = 1; |
118 | return (result); |
119 | } |
120 | |
121 | /*! \file */ |
122 | |