login_times.c revision 183989
1/*-
2 * Copyright (c) 1996 by
3 * David Nugent <davidn@blaze.net.au>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, is permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice immediately at the beginning of the file, without modification,
11 *    this list of conditions, and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. This work was done expressly for inclusion into FreeBSD.  Other use
16 *    is permitted provided this notation is included.
17 * 4. Absolutely no warranty of function or purpose is made by the authors.
18 * 5. Modifications may be freely made to this file providing the above
19 *    conditions are met.
20 *
21 * Login period parsing and comparison functions.
22 */
23
24#include <sys/cdefs.h>
25__FBSDID("$FreeBSD: head/lib/libutil/login_times.c 183989 2008-10-17 21:21:14Z delphij $");
26
27#include <sys/types.h>
28#include <ctype.h>
29#include <login_cap.h>
30#include <stdlib.h>
31#include <string.h>
32#include <time.h>
33
34static struct
35{
36    const char	*dw;
37    u_char      cn;
38    u_char      fl;
39} dws[] =
40{
41    { "su", 2, LTM_SUN }, { "mo", 2, LTM_MON }, { "tu", 2, LTM_TUE },
42    { "we", 2, LTM_WED }, { "th", 2, LTM_THU }, { "fr", 2, LTM_FRI },
43    { "sa", 2, LTM_SAT }, { "any",3, LTM_ANY }, { "all",3, LTM_ANY },
44    { "wk", 2, LTM_WK  }, { "wd", 2, LTM_WD  }, { NULL, 0, 0       }
45};
46
47static char *
48parse_time(char * ptr, u_short * t)
49{
50    u_short	val;
51
52    for (val = 0; *ptr && isdigit(*ptr); ptr++)
53	val = (u_short)(val * 10 + (*ptr - '0'));
54
55    *t = (u_short)((val / 100) * 60 + (val % 100));
56
57    return ptr;
58}
59
60
61login_time_t
62parse_lt(const char * str)
63{
64    login_time_t    t;
65
66    memset(&t, 0, sizeof t);
67    t.lt_dow = LTM_NONE;
68    if (str && *str && strcmp(str, "Never") != 0 && strcmp(str, "None") != 0) {
69	int		i;
70	login_time_t	m = t;
71	char		*p;
72	char		buf[64];
73
74	/* Make local copy and force lowercase to simplify parsing */
75	p = strlcpy(buf, str, sizeof buf);
76	for (i = 0; buf[i]; i++)
77	    buf[i] = (char)tolower(buf[i]);
78
79	while (isalpha(*p)) {
80
81	    i = 0;
82	    while (dws[i].dw && strncmp(p, dws[i].dw, dws[i].cn) != 0)
83		i++;
84	    if (dws[i].dw == NULL)
85		break;
86	    m.lt_dow |= dws[i].fl;
87	    p += dws[i].cn;
88	}
89
90	if (m.lt_dow == LTM_NONE) /* No (valid) prefix, assume any */
91	    m.lt_dow |= LTM_ANY;
92
93	if (isdigit(*p))
94	    p = parse_time(p, &m.lt_start);
95	else
96	    m.lt_start = 0;
97	if (*p == '-')
98	    p = parse_time(++p, &m.lt_end);
99	else
100	    m.lt_end = 1440;
101
102	t = m;
103    }
104    return t;
105}
106
107
108int
109in_ltm(const login_time_t * ltm, struct tm * tt, time_t * ends)
110{
111    int	    rc = 0;
112
113    if (tt != NULL) {
114	/* First, examine the day of the week */
115	if ((u_char)(0x01 << tt->tm_wday) & ltm->lt_dow) {
116	    /* Convert `current' time to minute of the day */
117	    u_short	now = (u_short)((tt->tm_hour * 60) + tt->tm_min);
118
119	    if (tt->tm_sec > 30)
120		++now;
121	    if (now >= ltm->lt_start && now < ltm->lt_end) {
122		rc = 2;
123		if (ends != NULL) {
124		    /* If requested, return ending time for this period */
125		    tt->tm_hour = (int)(ltm->lt_end / 60);
126		    tt->tm_min  = (int)(ltm->lt_end % 60);
127		    *ends = mktime(tt);
128		}
129	    }
130	}
131    }
132    return rc;
133}
134
135
136int
137in_lt(const login_time_t * ltm, time_t * t)
138{
139    return in_ltm(ltm, localtime(t), t);
140}
141
142int
143in_ltms(const login_time_t * ltm, struct tm * tm, time_t * t)
144{
145    int	    i = 0;
146
147    while (i < LC_MAXTIMES && ltm[i].lt_dow != LTM_NONE) {
148	if (in_ltm(ltm + i, tm, t))
149	    return i;
150	i++;
151    }
152    return -1;
153}
154
155int
156in_lts(const login_time_t * ltm, time_t * t)
157{
158    return in_ltms(ltm, localtime(t), t);
159}
160
161