]> git.cameronkatri.com Git - pw-darwin.git/blob - pw/psdate.c
Rework the home directory creation and copy or the skel content to use *at
[pw-darwin.git] / pw / psdate.c
1 /*-
2 * Copyright (C) 1996
3 * David L. Nugent. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #ifndef lint
28 static const char rcsid[] =
29 "$FreeBSD$";
30 #endif /* not lint */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include <xlocale.h>
37 #include <err.h>
38
39 #include "psdate.h"
40
41
42 static int
43 numerics(char const * str)
44 {
45 int rc = isdigit((unsigned char)*str);
46
47 if (rc)
48 while (isdigit((unsigned char)*str) || *str == 'x')
49 ++str;
50 return rc && !*str;
51 }
52
53 static int
54 aindex(char const * arr[], char const ** str, int len)
55 {
56 int l, i;
57 char mystr[32];
58
59 mystr[len] = '\0';
60 l = strlen(strncpy(mystr, *str, len));
61 for (i = 0; i < l; i++)
62 mystr[i] = (char) tolower((unsigned char)mystr[i]);
63 for (i = 0; arr[i] && strcmp(mystr, arr[i]) != 0; i++);
64 if (arr[i] == NULL)
65 i = -1;
66 else { /* Skip past it */
67 while (**str && isalpha((unsigned char)**str))
68 ++(*str);
69 /* And any following whitespace */
70 while (**str && (**str == ',' || isspace((unsigned char)**str)))
71 ++(*str);
72 } /* Return index */
73 return i;
74 }
75
76 static int
77 weekday(char const ** str)
78 {
79 static char const *days[] =
80 {"sun", "mon", "tue", "wed", "thu", "fri", "sat", NULL};
81
82 return aindex(days, str, 3);
83 }
84
85 static void
86 parse_datesub(char const * str, struct tm *t)
87 {
88 struct tm tm;
89 locale_t l;
90 int i;
91 char *ret;
92 const char *valid_formats[] = {
93 "%d-%b-%y",
94 "%d-%b-%Y",
95 "%d-%m-%y",
96 "%d-%m-%Y",
97 "%H:%M %d-%b-%y",
98 "%H:%M %d-%b-%Y",
99 "%H:%M %d-%m-%y",
100 "%H:%M %d-%m-%Y",
101 "%H:%M:%S %d-%b-%y",
102 "%H:%M:%S %d-%b-%Y",
103 "%H:%M:%S %d-%m-%y",
104 "%H:%M:%S %d-%m-%Y",
105 "%d-%b-%y %H:%M",
106 "%d-%b-%Y %H:%M",
107 "%d-%m-%y %H:%M",
108 "%d-%m-%Y %H:%M",
109 "%d-%b-%y %H:%M:%S",
110 "%d-%b-%Y %H:%M:%S",
111 "%d-%m-%y %H:%M:%S",
112 "%d-%m-%Y %H:%M:%S",
113 "%H:%M\t%d-%b-%y",
114 "%H:%M\t%d-%b-%Y",
115 "%H:%M\t%d-%m-%y",
116 "%H:%M\t%d-%m-%Y",
117 "%H:%M\t%S %d-%b-%y",
118 "%H:%M\t%S %d-%b-%Y",
119 "%H:%M\t%S %d-%m-%y",
120 "%H:%M\t%S %d-%m-%Y",
121 "%d-%b-%y\t%H:%M",
122 "%d-%b-%Y\t%H:%M",
123 "%d-%m-%y\t%H:%M",
124 "%d-%m-%Y\t%H:%M",
125 "%d-%b-%y\t%H:%M:%S",
126 "%d-%b-%Y\t%H:%M:%S",
127 "%d-%m-%y\t%H:%M:%S",
128 "%d-%m-%Y\t%H:%M:%S",
129 NULL,
130 };
131
132 l = newlocale(LC_ALL_MASK, "C", NULL);
133
134 memset(&tm, 0, sizeof(tm));
135 for (i=0; valid_formats[i] != NULL; i++) {
136 ret = strptime_l(str, valid_formats[i], &tm, l);
137 if (ret && *ret == '\0') {
138 t->tm_mday = tm.tm_mday;
139 t->tm_mon = tm.tm_mon;
140 t->tm_year = tm.tm_year;
141 t->tm_hour = tm.tm_hour;
142 t->tm_min = tm.tm_min;
143 t->tm_sec = tm.tm_sec;
144 freelocale(l);
145 return;
146 }
147 }
148
149 freelocale(l);
150
151 errx(EXIT_FAILURE, "Invalid date");
152 }
153
154
155 /*-
156 * Parse time must be flexible, it handles the following formats:
157 * nnnnnnnnnnn UNIX timestamp (all numeric), 0 = now
158 * 0xnnnnnnnn UNIX timestamp in hexadecimal
159 * 0nnnnnnnnn UNIX timestamp in octal
160 * 0 Given time
161 * +nnnn[smhdwoy] Given time + nnnn hours, mins, days, weeks, months or years
162 * -nnnn[smhdwoy] Given time - nnnn hours, mins, days, weeks, months or years
163 * dd[ ./-]mmm[ ./-]yy Date }
164 * hh:mm:ss Time } May be combined
165 */
166
167 time_t
168 parse_date(time_t dt, char const * str)
169 {
170 char *p;
171 int i;
172 long val;
173 struct tm *T;
174
175 if (dt == 0)
176 dt = time(NULL);
177
178 while (*str && isspace((unsigned char)*str))
179 ++str;
180
181 if (numerics(str)) {
182 dt = strtol(str, &p, 0);
183 } else if (*str == '+' || *str == '-') {
184 val = strtol(str, &p, 0);
185 switch (*p) {
186 case 'h':
187 case 'H': /* hours */
188 dt += (val * 3600L);
189 break;
190 case '\0':
191 case 'm':
192 case 'M': /* minutes */
193 dt += (val * 60L);
194 break;
195 case 's':
196 case 'S': /* seconds */
197 dt += val;
198 break;
199 case 'd':
200 case 'D': /* days */
201 dt += (val * 86400L);
202 break;
203 case 'w':
204 case 'W': /* weeks */
205 dt += (val * 604800L);
206 break;
207 case 'o':
208 case 'O': /* months */
209 T = localtime(&dt);
210 T->tm_mon += (int) val;
211 i = T->tm_mday;
212 goto fixday;
213 case 'y':
214 case 'Y': /* years */
215 T = localtime(&dt);
216 T->tm_year += (int) val;
217 i = T->tm_mday;
218 fixday:
219 dt = mktime(T);
220 T = localtime(&dt);
221 if (T->tm_mday != i) {
222 T->tm_mday = 1;
223 dt = mktime(T);
224 dt -= (time_t) 86400L;
225 }
226 default: /* unknown */
227 break; /* leave untouched */
228 }
229 } else {
230 char *q, tmp[64];
231
232 /*
233 * Skip past any weekday prefix
234 */
235 weekday(&str);
236 strlcpy(tmp, str, sizeof(tmp));
237 str = tmp;
238 T = localtime(&dt);
239
240 /*
241 * See if we can break off any timezone
242 */
243 while ((q = strrchr(tmp, ' ')) != NULL) {
244 if (strchr("(+-", q[1]) != NULL)
245 *q = '\0';
246 else {
247 int j = 1;
248
249 while (q[j] && isupper((unsigned char)q[j]))
250 ++j;
251 if (q[j] == '\0')
252 *q = '\0';
253 else
254 break;
255 }
256 }
257
258 parse_datesub(tmp, T);
259 dt = mktime(T);
260 }
261 return dt;
262 }