xref: /dragonfly/lib/libutil/login_times.c (revision d316f7c95d4b8b07a5557eb0a39cfa39b7114297)
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  * $FreeBSD: head/lib/libutil/login_times.c 252376 2013-06-29 15:52:48Z kientzle $
24  */
25 
26 #include <sys/types.h>
27 #include <ctype.h>
28 #include <login_cap.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <time.h>
32 
33 static struct
34 {
35     const char      *dw;
36     u_char      cn;
37     u_char      fl;
38 } dws[] =
39 {
40     { "su", 2, LTM_SUN }, { "mo", 2, LTM_MON }, { "tu", 2, LTM_TUE },
41     { "we", 2, LTM_WED }, { "th", 2, LTM_THU }, { "fr", 2, LTM_FRI },
42     { "sa", 2, LTM_SAT }, { "any",3, LTM_ANY }, { "all",3, LTM_ANY },
43     { "wk", 2, LTM_WK  }, { "wd", 2, LTM_WD  }, { NULL, 0, 0       }
44 };
45 
46 static char *
parse_time(char * ptr,u_short * t)47 parse_time(char * ptr, u_short * t)
48 {
49     u_short         val;
50 
51     for (val = 0; *ptr && isdigit(*ptr); ptr++)
52           val = (u_short)(val * 10 + (*ptr - '0'));
53 
54     *t = (u_short)((val / 100) * 60 + (val % 100));
55 
56     return (ptr);
57 }
58 
59 
60 login_time_t
parse_lt(const char * str)61 parse_lt(const char *str)
62 {
63     login_time_t    t;
64 
65     memset(&t, 0, sizeof t);
66     t.lt_dow = LTM_NONE;
67     if (str && *str && strcmp(str, "Never") != 0 && strcmp(str, "None") != 0) {
68           int                 i;
69           login_time_t        m = t;
70           char                *p;
71           char                buf[64];
72 
73           /* Make local copy and force lowercase to simplify parsing */
74           strlcpy(buf, str, sizeof buf);
75           for (i = 0; buf[i]; i++)
76               buf[i] = (char)tolower(buf[i]);
77           p = buf;
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 + 1, &m.lt_end);
99           else
100               m.lt_end = 1440;
101 
102           t = m;
103     }
104     return (t);
105 }
106 
107 
108 int
in_ltm(const login_time_t * ltm,struct tm * tt,time_t * ends)109 in_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 
136 int
in_lt(const login_time_t * ltm,time_t * t)137 in_lt(const login_time_t *ltm, time_t *t)
138 {
139 
140     return (in_ltm(ltm, localtime(t), t));
141 }
142 
143 int
in_ltms(const login_time_t * ltm,struct tm * tm,time_t * t)144 in_ltms(const login_time_t *ltm, struct tm *tm, time_t *t)
145 {
146     int       i = 0;
147 
148     while (i < LC_MAXTIMES && ltm[i].lt_dow != LTM_NONE) {
149           if (in_ltm(ltm + i, tm, t))
150               return (i);
151           i++;
152     }
153     return (-1);
154 }
155 
156 int
in_lts(const login_time_t * ltm,time_t * t)157 in_lts(const login_time_t *ltm, time_t *t)
158 {
159 
160     return (in_ltms(ltm, localtime(t), t));
161 }
162