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