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