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/types.h>
25 #include <ctype.h>
26 #include <login_cap.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30
31 static struct
32 {
33 const char *dw;
34 u_char cn;
35 u_char fl;
36 } dws[] =
37 {
38 { "su", 2, LTM_SUN }, { "mo", 2, LTM_MON }, { "tu", 2, LTM_TUE },
39 { "we", 2, LTM_WED }, { "th", 2, LTM_THU }, { "fr", 2, LTM_FRI },
40 { "sa", 2, LTM_SAT }, { "any",3, LTM_ANY }, { "all",3, LTM_ANY },
41 { "wk", 2, LTM_WK }, { "wd", 2, LTM_WD }, { NULL, 0, 0 }
42 };
43
44 static char *
parse_time(char * ptr,u_short * t)45 parse_time(char * ptr, u_short * t)
46 {
47 u_short val;
48
49 for (val = 0; *ptr && isdigit(*ptr); ptr++)
50 val = (u_short)(val * 10 + (*ptr - '0'));
51
52 *t = (u_short)((val / 100) * 60 + (val % 100));
53
54 return (ptr);
55 }
56
57
58 login_time_t
parse_lt(const char * str)59 parse_lt(const char *str)
60 {
61 login_time_t t;
62
63 memset(&t, 0, sizeof t);
64 t.lt_dow = LTM_NONE;
65 if (str && *str && strcmp(str, "Never") != 0 && strcmp(str, "None") != 0) {
66 int i;
67 login_time_t m = t;
68 char *p;
69 char buf[64];
70
71 /* Make local copy and force lowercase to simplify parsing */
72 strlcpy(buf, str, sizeof buf);
73 for (i = 0; buf[i]; i++)
74 buf[i] = (char)tolower(buf[i]);
75 p = buf;
76
77 while (isalpha(*p)) {
78
79 i = 0;
80 while (dws[i].dw && strncmp(p, dws[i].dw, dws[i].cn) != 0)
81 i++;
82 if (dws[i].dw == NULL)
83 break;
84 m.lt_dow |= dws[i].fl;
85 p += dws[i].cn;
86 }
87
88 if (m.lt_dow == LTM_NONE) /* No (valid) prefix, assume any */
89 m.lt_dow |= LTM_ANY;
90
91 if (isdigit(*p))
92 p = parse_time(p, &m.lt_start);
93 else
94 m.lt_start = 0;
95 if (*p == '-')
96 p = parse_time(p + 1, &m.lt_end);
97 else
98 m.lt_end = 1440;
99
100 t = m;
101 }
102 return (t);
103 }
104
105
106 int
in_ltm(const login_time_t * ltm,struct tm * tt,time_t * ends)107 in_ltm(const login_time_t *ltm, struct tm *tt, time_t *ends)
108 {
109 int rc = 0;
110
111 if (tt != NULL) {
112 /* First, examine the day of the week */
113 if ((u_char)(0x01 << tt->tm_wday) & ltm->lt_dow) {
114 /* Convert `current' time to minute of the day */
115 u_short now = (u_short)((tt->tm_hour * 60) + tt->tm_min);
116
117 if (tt->tm_sec > 30)
118 ++now;
119 if (now >= ltm->lt_start && now < ltm->lt_end) {
120 rc = 2;
121 if (ends != NULL) {
122 /* If requested, return ending time for this period */
123 tt->tm_hour = (int)(ltm->lt_end / 60);
124 tt->tm_min = (int)(ltm->lt_end % 60);
125 *ends = mktime(tt);
126 }
127 }
128 }
129 }
130 return (rc);
131 }
132
133
134 int
in_lt(const login_time_t * ltm,time_t * t)135 in_lt(const login_time_t *ltm, time_t *t)
136 {
137
138 return (in_ltm(ltm, localtime(t), t));
139 }
140
141 int
in_ltms(const login_time_t * ltm,struct tm * tm,time_t * t)142 in_ltms(const login_time_t *ltm, struct tm *tm, time_t *t)
143 {
144 int i = 0;
145
146 while (i < LC_MAXTIMES && ltm[i].lt_dow != LTM_NONE) {
147 if (in_ltm(ltm + i, tm, t))
148 return (i);
149 i++;
150 }
151 return (-1);
152 }
153
154 int
in_lts(const login_time_t * ltm,time_t * t)155 in_lts(const login_time_t *ltm, time_t *t)
156 {
157
158 return (in_ltms(ltm, localtime(t), t));
159 }
160