1
by Robert Luberda
Import upstream version 3.23.0 |
1 |
static const char rcsid[] = "$Id: time.c,v 1.28 2004/04/30 17:00:58 will Exp $"; |
2 |
#include "super.h" |
|
3 |
||
4 |
#define ANYDAY 7
|
|
5 |
||
6 |
/* Maximum length of a time field in super.tab. */
|
|
7 |
#define MAX_T_FIELDLEN 80
|
|
8 |
||
9 |
struct weekDay { |
|
10 |
char name[20]; |
|
11 |
char abbr[20]; |
|
12 |
};
|
|
13 |
||
14 |
#ifdef HAVE_LOCALE_H
|
|
15 |
/* We will pick up weekday names dynamically; make the first name a
|
|
16 |
* null string so we know that initialization has yet to be done.
|
|
17 |
*/
|
|
18 |
static struct weekDay weekday[7] = { { "", ""}, }; |
|
19 |
#else
|
|
20 |
static struct weekDay weekday[7] = { |
|
21 |
{ "sunday", "sun", }, |
|
22 |
{ "monday", "mon", }, |
|
23 |
{ "tuesday", "tue", }, |
|
24 |
{ "wednesday", "wed", }, |
|
25 |
{ "thursday", "thu", }, |
|
26 |
{ "friday", "fri", }, |
|
27 |
{ "saturday", "sat" } |
|
28 |
};
|
|
29 |
#endif
|
|
30 |
||
31 |
char * |
|
32 |
dayname(n) |
|
33 |
int n; /* day number: 0..6 = sun..sat; 7 = any */ |
|
34 |
{
|
|
35 |
/* Returns ptr to day of week */
|
|
36 |
static char *anyday="*"; |
|
37 |
||
38 |
#ifdef HAVE_LOCALE_H
|
|
39 |
if (*(weekday[0].name) == '\0') |
|
40 |
readtime_init(); |
|
41 |
#endif
|
|
42 |
||
43 |
if (n < 0 || n > 6) |
|
44 |
return anyday; |
|
45 |
else
|
|
46 |
return weekday[n].name; |
|
47 |
}
|
|
48 |
||
49 |
int
|
|
50 |
daynum(t) |
|
51 |
int t; /* A Unix time */ |
|
52 |
{
|
|
53 |
/* Returns day of week, with 0 = sunday. This routine takes the input
|
|
54 |
* time as given -- it doesn't assume GMT or any such thing -- and
|
|
55 |
* returns the day number: you should use localtime() or gmtime() if
|
|
56 |
* you have them available.
|
|
57 |
*/
|
|
58 |
int jd = (int) (2440587.5 + ((double) t) / 86400.); |
|
59 |
int i = (jd+1) / 7; |
|
60 |
return jd - 7 * i + 1; |
|
61 |
}
|
|
62 |
||
63 |
int
|
|
64 |
InsertTimeList(str, wdlist, tl, timetype, invert) |
|
65 |
char *str; /* Contains one of the time types accepted by readtimerange(), |
|
66 |
* and extended to allow brace-expansion */
|
|
67 |
char **wdlist; /* list-expanded form of str */ |
|
68 |
TimeList *tl; /* Insert time list elements at tl->next */ |
|
69 |
char *timetype; /* "per-cmd" or "global": a string to use in info msgs */ |
|
70 |
int invert; /* Inverts the test */ |
|
71 |
{
|
|
72 |
/* Checks if time is in the range specified by the time string str.
|
|
73 |
* Returns
|
|
74 |
* -1 on syntax error, malloc error, or similar;
|
|
75 |
* 0 otherwise.
|
|
76 |
* Side effect: sets the matches.time field.
|
|
77 |
*/
|
|
78 |
int match; |
|
79 |
int iwd; |
|
80 |
char *tok; |
|
81 |
TimeList *new; |
|
82 |
||
83 |
for (iwd=0, match=0; (tok=wdlist[iwd]); iwd++) { |
|
84 |
new = (TimeList *) malloc(sizeof(TimeList)); |
|
85 |
if (!new) |
|
86 |
return Error(0, 0, "%t\n\tFailed to malloc space for time entry\n"); |
|
87 |
new->next = tl->next; |
|
88 |
new->te.invert = invert; |
|
89 |
/* interpret pat */
|
|
90 |
if (readtimerange(tok, &new->te.begin, &new->te.end, |
|
91 |
&new->te.day) == -1) |
|
92 |
return -1; |
|
93 |
if (debug) |
|
94 |
(void) fprintf(stderr, |
|
95 |
"\tInsert %s time pattern: %stime~%s (min=%d-%d day=%d [dayname=%s])\n", |
|
96 |
timetype, |
|
97 |
invert ? "!" : "", tok, new->te.begin, new->te.end, |
|
98 |
new->te.day, dayname(new->te.day)); |
|
99 |
tl->next = new; |
|
100 |
}
|
|
101 |
return 0; |
|
102 |
}
|
|
103 |
||
104 |
void
|
|
105 |
matchtime(our, tl) |
|
106 |
OurTime *our; /* A time entry to match. Only the "min" and "day" fields |
|
107 |
* will be used, so it's ok if the "start" field doesn't
|
|
108 |
* match them.
|
|
109 |
*/
|
|
110 |
TimeList *tl; /* A list of times to match against; 1st used is tl->next */ |
|
111 |
{
|
|
112 |
/* The time list created by the InsertTimeList function
|
|
113 |
* is in reverse order, so we only need to find the first
|
|
114 |
* entry in the list that is a match (+ or -) and stop there.
|
|
115 |
||
116 |
* But if there are no matches, we scan all entries.
|
|
117 |
||
118 |
* Side effects:
|
|
119 |
* If an entry is matched, matches.time is set to 0 or 1,
|
|
120 |
* according as the entry is/is not inverted. Otherwise unmodified.
|
|
121 |
* If an entry is non-inverted, matches.alltime_invert is set to 0,
|
|
122 |
* otherwise unmodified. Note that this will include all entries
|
|
123 |
* only if there was no match, because scanning stops with a match.
|
|
124 |
||
125 |
*/
|
|
126 |
||
127 |
/* The caller should interpret the returned matches as
|
|
128 |
* follows.
|
|
129 |
* Case 1: Our time 12:30
|
|
130 |
* time~8-17 !time~12-13 time~23-24
|
|
131 |
* a. time~8-17 matches, user allowed.
|
|
132 |
* b. time~12-13 matches, ! means user disallowed.
|
|
133 |
* c. time~23-24 doesn't match, doesn't change allow/disallow.
|
|
134 |
* Therefore user disallowed.
|
|
135 |
||
136 |
* Case 2: Our time 12:30
|
|
137 |
* time~8-17 !time~12-13 !time~23-24
|
|
138 |
* a. time~8-17 matches, user allowed.
|
|
139 |
* b. time~12-13 matches, ! means user disallowed.
|
|
140 |
* c. time~23-24 doesn't match, doesn't change allow/disallow.
|
|
141 |
* Therefore user disallowed.
|
|
142 |
||
143 |
* Case 3: Our time 12:30
|
|
144 |
* !time~23-24
|
|
145 |
* a. time~23-24 doesn't match, doesn't change allow/disallow.
|
|
146 |
* b. Thus fall back on default. Default is
|
|
147 |
* i) allow if _all_ statements are inverted;
|
|
148 |
* ii) else disallow.
|
|
149 |
* Therefore user is allowed.
|
|
150 |
||
151 |
* Case 4: Our time 17:30
|
|
152 |
* time~8-17 !time~12-13 !time~23-24
|
|
153 |
* a. time~8-17 doesn't match, doesn't change allow/disallow.
|
|
154 |
* b. time~12-13 doesn't match, doesn't change allow/disallow.
|
|
155 |
* c. time~23-24 doesn't match, doesn't change allow/disallow.
|
|
156 |
* d. Thus fall back on default. Default is
|
|
157 |
* i) allow if _all_ statements are inverted;
|
|
158 |
* ii) else disallow.
|
|
159 |
* Therefore user is disallowed.
|
|
160 |
*/
|
|
161 |
||
162 |
int match; |
|
163 |
||
164 |
for (tl=tl->next, match=0; tl && !match; tl=tl->next) { |
|
165 |
if (!tl->te.invert) |
|
166 |
matches.allinverted = 0; |
|
167 |
||
168 |
if (our->min >= tl->te.begin && our->min <= tl->te.end && |
|
169 |
(tl->te.day == ANYDAY || our->day == tl->te.day)) { |
|
170 |
/* matches */
|
|
171 |
match = 1; |
|
172 |
matches.time = tl->te.invert ? 0 : 1; |
|
173 |
if (debug || it_came_from_cmdline) { |
|
174 |
(void) fprintf(stderr, "\t%s: %stime~%d:%.2d-%d:%.2d/%s\n", |
|
175 |
tl->te.invert ? "Permission denied" : "Permission allowed", |
|
176 |
tl->te.invert ? "!" : "", |
|
177 |
tl->te.begin/60, tl->te.begin%60, |
|
178 |
tl->te.end/60, tl->te.end%60, |
|
179 |
dayname(tl->te.day)); |
|
180 |
}
|
|
181 |
} else { |
|
182 |
/* Our time is not in the range of this time entry. */
|
|
183 |
if (debug || it_came_from_cmdline) { |
|
184 |
(void) fprintf(stderr, |
|
185 |
"\tNot applicable: %stime~%d:%.2d-%d:%.2d/%s\n", |
|
186 |
tl->te.invert ? "!" : "", |
|
187 |
tl->te.begin/60, tl->te.begin%60, |
|
188 |
tl->te.end/60, tl->te.end%60, |
|
189 |
dayname(tl->te.day)); |
|
190 |
}
|
|
191 |
}
|
|
192 |
}
|
|
193 |
}
|
|
194 |
||
195 |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
196 |
/* Frees all elements in a TimeList, except the one it's given.
|
|
197 |
* The "next" field of that element is set NULL.
|
|
198 |
*/
|
|
199 |
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
200 |
void
|
|
201 |
free_TimeList(tl) |
|
202 |
TimeList *tl; |
|
203 |
{
|
|
204 |
TimeList *tlp; |
|
205 |
||
206 |
if (!tl || !tl->next) |
|
207 |
return; |
|
208 |
tlp = tl->next; |
|
209 |
tl->next = NULL; |
|
210 |
for (tl=tl->next ; tl; tl = tlp) { |
|
211 |
tlp = tl->next; |
|
212 |
free(tl); |
|
213 |
}
|
|
214 |
}
|
|
215 |
#ifdef HAVE_LOCALE_H
|
|
216 |
/* The following function should be invoked each time the locale
|
|
217 |
* is changed (via lang=xxx).
|
|
218 |
*/
|
|
219 |
void
|
|
220 |
readtime_init() |
|
221 |
{
|
|
222 |
struct tm ti; |
|
223 |
int i; |
|
224 |
||
225 |
/* We know the following to be a Sunday */
|
|
226 |
ti.tm_sec = 0; |
|
227 |
ti.tm_min = 0; |
|
228 |
ti.tm_hour = 12; |
|
229 |
ti.tm_mday = 4; |
|
230 |
ti.tm_wday = 0; |
|
231 |
ti.tm_mon = 0; |
|
232 |
ti.tm_year = 70; |
|
233 |
||
234 |
/* Figure out the days of the week in the current locale */
|
|
235 |
if (debug) |
|
236 |
fprintf(stderr, |
|
237 |
"\tInitializing days of week. Full names and official abbr's:\n\t"); |
|
238 |
||
239 |
for (i = 0; i < 7; i++) { |
|
240 |
strftime(weekday[i].name, sizeof(weekday[0].name)-1, "%A", &ti); |
|
241 |
strtolower(weekday[i].name); |
|
242 |
strftime(weekday[i].abbr, sizeof(weekday[0].abbr)-1, "%a", &ti); |
|
243 |
strtolower(weekday[i].abbr); |
|
244 |
if (debug) { |
|
245 |
fprintf(stderr, "%s (%s) ", weekday[i].name, weekday[i].abbr); |
|
246 |
if (i == 3) |
|
247 |
fputs("\n\t", stderr); |
|
248 |
}
|
|
249 |
ti.tm_mday++; |
|
250 |
ti.tm_wday++; |
|
251 |
}
|
|
252 |
||
253 |
if (debug) |
|
254 |
fputs("\n", stderr); |
|
255 |
}
|
|
256 |
#endif
|
|
257 |
||
258 |
int
|
|
259 |
readtimerange(str, t1, t2, d) |
|
260 |
char *str; |
|
261 |
short *t1; /* Returned with 1st time, units=minutes, range = 0..1439 */ |
|
262 |
short *t2; /* Returned with 2nd time, units=minutes, range = 0..1439 */ |
|
263 |
char *d; /* Returned with day number (0=Sunday) or ANYDAY */ |
|
264 |
{
|
|
265 |
/* str is a string containing one of the following patterns:
|
|
266 |
*
|
|
267 |
* "" (implies all days, all hours)
|
|
268 |
* [/]dayname (implies all hours)
|
|
269 |
* hh[:mm]-hh[:mm]/dayname
|
|
270 |
* hh[:mm]-hh[:mm] (implies all days)
|
|
271 |
* xhh[:mm]/dayname (x is one of <, >, <=, >= )
|
|
272 |
* xhh[:mm] (implies all days; x is as above)
|
|
273 |
*
|
|
274 |
* The valid daynames are (case-insensitive) either an official abbreviated
|
|
275 |
* day name in the current locale; a 3-or-more character abbreviation
|
|
276 |
* of the full weekday; or "*", meaning any day.
|
|
277 |
||
278 |
* For convenience, the upper time can be 24:00, but it is converted
|
|
279 |
* to 11:59.
|
|
280 |
||
281 |
* Returns: -1 on invalid time pattern; 0 otherwise.
|
|
282 |
||
283 |
*/
|
|
284 |
char *s, *p; |
|
285 |
int hh1, mm1; |
|
286 |
int hh2, mm2; |
|
287 |
int i, l; |
|
288 |
int has_relop; |
|
289 |
#ifdef HAVE_ENUM
|
|
290 |
enum { LT, LE, GT, GE } relop; |
|
291 |
#else
|
|
292 |
/* No enums! */
|
|
293 |
#define LT 0
|
|
294 |
#define LE 1
|
|
295 |
#define GT 2
|
|
296 |
#define GE 3
|
|
297 |
int relop; |
|
298 |
#endif
|
|
299 |
||
300 |
if (strlen(str) > MAX_T_FIELDLEN) { |
|
301 |
return Error(0, 0, |
|
302 |
"%t\n\tInvalid time range; first %d chars are: <%*.*s>\n", |
|
303 |
MAX_T_FIELDLEN, MAX_T_FIELDLEN, str); |
|
304 |
}
|
|
305 |
||
306 |
#ifdef HAVE_LOCALE_H
|
|
307 |
if (*(weekday[0].name) == '\0') |
|
308 |
readtime_init(); |
|
309 |
#endif
|
|
310 |
||
311 |
s = str; |
|
312 |
has_relop = 0; |
|
313 |
if (*s == '<' || *s == '>') { |
|
314 |
/* Must be xhh[:mm][/dayname] */
|
|
315 |
has_relop = 1; |
|
316 |
switch (*s++) { |
|
317 |
case '<': |
|
318 |
relop = (*s == '=') ? (s++, LE) : LT; |
|
319 |
break; |
|
320 |
case '>': |
|
321 |
relop = (*s == '=') ? (s++, GE) : GT; |
|
322 |
break; |
|
323 |
default: |
|
324 |
return Error(0, 0, "%t\n\tInvalid time range <%s>\n", str); |
|
325 |
}
|
|
326 |
if (!isdigit(*s)) |
|
327 |
return Error(0, 0, |
|
328 |
"%t\n\tInvalid time range <%s> (invalid hour part)\n", |
|
329 |
str); |
|
330 |
||
331 |
hh1 = strtol(s, &p, 10); |
|
332 |
if (p == s || hh1 > 24 || hh1 < 0) |
|
333 |
return Error(0, 0, |
|
334 |
"%t\n\tInvalid time range <%s> (invalid hour part)\n", str); |
|
335 |
||
336 |
s = p; |
|
337 |
if (*s != ':') { |
|
338 |
/* minutes not given */
|
|
339 |
mm1 = 0; |
|
340 |
} else { |
|
341 |
mm1 = strtol(++s, &p, 10); |
|
342 |
if (p == s || mm1 > 59 || mm1 < 0 || (mm1 > 0 && hh1 == 24)) |
|
343 |
return Error(0, 0, |
|
344 |
"%t\n\tInvalid time range <%s> (invalid minute part)\n", str); |
|
345 |
}
|
|
346 |
||
347 |
s = p; |
|
348 |
||
349 |
switch (relop) { |
|
350 |
case LT: |
|
351 |
*t1 = 0; |
|
352 |
*t2 = hh1*60 + mm1 - 1; |
|
353 |
break; |
|
354 |
case LE: |
|
355 |
*t1 = 0; |
|
356 |
*t2 = hh1*60 + mm1; |
|
357 |
break; |
|
358 |
case GT: |
|
359 |
*t1 = hh1*60 + mm1 + 1; |
|
360 |
*t2 = 24*60 - 1; |
|
361 |
break; |
|
362 |
case GE: |
|
363 |
*t1 = hh1*60 + mm1; |
|
364 |
*t2 = 24*60 - 1; |
|
365 |
break; |
|
366 |
default: |
|
367 |
return Error(0, 0, |
|
368 |
"%t\n\tInternal time range error -- relop is %d\n", |
|
369 |
relop); |
|
370 |
}
|
|
371 |
||
372 |
} else if (isdigit(*str)) { |
|
373 |
/* It must begin hh:mm-hh:mm */
|
|
374 |
s = str; |
|
375 |
||
376 |
hh1 = strtol(s, &p, 10); |
|
377 |
if (p == s || hh1 > 24 || hh1 < 0) |
|
378 |
return Error(0, 0, |
|
379 |
"%t\n\tInvalid time range <%s> (invalid first hr)\n", str); |
|
380 |
||
381 |
s = p; |
|
382 |
if (*s != ':') { |
|
383 |
mm1 = 0; |
|
384 |
} else { |
|
385 |
mm1 = strtol(++s, &p, 10); |
|
386 |
if (p == s || mm1 > 59 || mm1 < 0 || (mm1 > 0 && hh1 == 24)) |
|
387 |
return Error(0, 0, |
|
388 |
"%t\n\tInvalid time range <%s> (invalid first min)\n", str); |
|
389 |
}
|
|
390 |
||
391 |
*t1 = hh1*60 + mm1; |
|
392 |
||
393 |
s = p; |
|
394 |
if (*s++ != '-') |
|
395 |
return Error(0, 0, |
|
396 |
"%t\n\tInvalid time range <%s> (expected '-' in hh:mm-hh:mm)\n", |
|
397 |
str); |
|
398 |
||
399 |
hh2 = strtol(s, &p, 10); |
|
400 |
if (p == s || hh2 > 24 || hh2 < 0) |
|
401 |
return Error(0, 0, |
|
402 |
"%t\n\tInvalid time range <%s> (invalid second hr)\n", str); |
|
403 |
||
404 |
s = p; |
|
405 |
if (*s != ':') { |
|
406 |
mm2 = 0; |
|
407 |
} else { |
|
408 |
mm2 = strtol(++s, &p, 10); |
|
409 |
if (p == s || mm2 > 59 || mm2 < 0 || (mm2 > 0 && hh2 == 24)) |
|
410 |
return Error(0, 0, |
|
411 |
"%t\n\tInvalid time range <%s> (invalid second min)\n", |
|
412 |
str); |
|
413 |
}
|
|
414 |
||
415 |
s = p; |
|
416 |
if (*s != '\0' && *s != '/') |
|
417 |
return Error(0, 0, |
|
418 |
"%t\n\tInvalid time range <%s> (invalid char after time range)\n", |
|
419 |
str); |
|
420 |
||
421 |
*t2 = hh2*60 + mm2; |
|
422 |
||
423 |
} else { |
|
424 |
/* We've seen no time part; must be dayname only; time is all hrs */
|
|
425 |
s = str; |
|
426 |
*t1 = 0; |
|
427 |
*t2 = 24 * 60; |
|
428 |
}
|
|
429 |
||
430 |
if (*s == '/') /* Skip field separator, if present */ |
|
431 |
s++; |
|
432 |
||
433 |
if (*s == '\0' || strcmp(s, "*") == 0) { |
|
434 |
*d = ANYDAY; /* all days */ |
|
435 |
} else { |
|
436 |
/* It must be a weekday, expressed in the current locale.
|
|
437 |
* Allow just dayname or /dayname.
|
|
438 |
*/
|
|
439 |
char buf[MAX_T_FIELDLEN+1]; |
|
440 |
strcpy(buf, s); |
|
441 |
strtolower(buf); |
|
442 |
for (i=0; i<7; i++) { |
|
443 |
#if 0
|
|
444 |
fprintf(stderr, "HERE: s=<%s> buf=<%s> day=<%s> abbr=<%s>\n",
|
|
445 |
s, buf, weekday[i].name, weekday[i].abbr);
|
|
446 |
#endif
|
|
447 |
if (strlen(buf) < 3) { |
|
448 |
; /* not accepted -- must be at least three chars */ |
|
449 |
} else if (strncmp(weekday[i].name, buf, (l=strlen(buf))) == 0) { |
|
450 |
*d = i; |
|
451 |
break; |
|
452 |
} else if (strcmp(weekday[i].abbr, buf) == 0) { |
|
453 |
*d = i; |
|
454 |
break; |
|
455 |
}
|
|
456 |
}
|
|
457 |
if (i >= 7) |
|
458 |
return Error(0, 0, |
|
459 |
"%t\n\tInvalid time range <%s> (invalid day field)\n", |
|
460 |
str); |
|
461 |
}
|
|
462 |
/* Convert 24:00 to 23:59 */
|
|
463 |
if (*t1 == 24*60) |
|
464 |
(*t1)--; |
|
465 |
if (*t2 == 24*60) |
|
466 |
(*t2)--; |
|
467 |
if (*t1 < 0 || *t2 < 0 || *t1 > 24*60-1 || *t2 > 24*60-1) |
|
468 |
return Error(0, 0, "%t\n\tInvalid time range <%s>\n", str); |
|
469 |
return 0; |
|
470 |
}
|
|
471 |
||
472 |
int
|
|
473 |
readtime(str, t, d) |
|
474 |
char *str; |
|
475 |
short *t; /* Returned with time, units=minutes, range = 0..1439 */ |
|
476 |
char *d; /* Returned with day number (0=Sunday) */ |
|
477 |
{
|
|
478 |
/* str must be like:
|
|
479 |
*
|
|
480 |
* hh[:mm]/dayname
|
|
481 |
*
|
|
482 |
* The valid daynames are (case-insensitive) either an official abbreviated
|
|
483 |
* day name in the current locale; a 3-or-more character abbreviation
|
|
484 |
* of the full weekday; or "*", meaning any day.
|
|
485 |
||
486 |
* Returns: -1 on invalid time pattern; 0 otherwise.
|
|
487 |
||
488 |
*/
|
|
489 |
char buf[MAX_T_FIELDLEN+1]; |
|
490 |
int hh, mm; |
|
491 |
int i, l; |
|
492 |
||
493 |
#ifdef HAVE_LOCALE_H
|
|
494 |
if (*(weekday[0].name) == '\0') |
|
495 |
readtime_init(); |
|
496 |
#endif
|
|
497 |
||
498 |
if (strlen(str) > sizeof(buf)-1) |
|
499 |
return Error(0, 0, "%t\n\tInvalid time <%s>\n", str); |
|
500 |
if (sscanf(str, "%d:%d/%s", &hh, &mm, buf) != 3) { |
|
501 |
mm = 0; |
|
502 |
if ( (sscanf(str, "%d:/%s", &hh, buf) != 2) && |
|
503 |
(sscanf(str, "%d/%s", &hh, buf) != 2) ) { |
|
504 |
return Error(0, 0, |
|
505 |
"%t\n\tInvalid time <%s>; format must be hh[:mm]/dayname\n", str); |
|
506 |
}
|
|
507 |
}
|
|
508 |
if (hh > 23 || hh < 0) |
|
509 |
return Error(0, 0, "%t\n\tInvalid time <%s> (invalid hr)\n", str); |
|
510 |
if (mm > 59 || mm < 0) |
|
511 |
return Error(0, 0, "%t\n\tInvalid time <%s> (invalid min)\n", str); |
|
512 |
||
513 |
*t = hh*60 + mm; |
|
514 |
||
515 |
/* The dayname must be a weekday, expressed in the current locale. */
|
|
516 |
strtolower(buf); |
|
517 |
for (i=0; i<7; i++) { |
|
518 |
if (strlen(buf) < 3) { |
|
519 |
; /* not accepted -- must be at least three chars */ |
|
520 |
} else if (strncmp(weekday[i].name, buf, (l=strlen(buf))) == 0) { |
|
521 |
*d = i; |
|
522 |
break; |
|
523 |
} else if (strcmp(weekday[i].abbr, buf) == 0) { |
|
524 |
*d = i; |
|
525 |
break; |
|
526 |
}
|
|
527 |
}
|
|
528 |
if (i >= 7) |
|
529 |
return Error(0, 0, "%t\n\tInvalid time <%s> (invalid dayname)\n", str); |
|
530 |
||
531 |
return 0; |
|
532 |
}
|