login_times.c revision 184087
11638Srgrimes/*-
21638Srgrimes * Copyright (c) 1996 by
31638Srgrimes * David Nugent <davidn@blaze.net.au>
41638Srgrimes * All rights reserved.
51638Srgrimes *
61638Srgrimes * Redistribution and use in source and binary forms, with or without
71638Srgrimes * modification, is permitted provided that the following conditions
81638Srgrimes * are met:
91638Srgrimes * 1. Redistributions of source code must retain the above copyright
101638Srgrimes *    notice immediately at the beginning of the file, without modification,
111638Srgrimes *    this list of conditions, and the following disclaimer.
121638Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
131638Srgrimes *    notice, this list of conditions and the following disclaimer in the
141638Srgrimes *    documentation and/or other materials provided with the distribution.
151638Srgrimes * 3. This work was done expressly for inclusion into FreeBSD.  Other use
161638Srgrimes *    is permitted provided this notation is included.
171638Srgrimes * 4. Absolutely no warranty of function or purpose is made by the authors.
181638Srgrimes * 5. Modifications may be freely made to this file providing the above
191638Srgrimes *    conditions are met.
201638Srgrimes *
211638Srgrimes * Login period parsing and comparison functions.
221638Srgrimes */
231638Srgrimes
241638Srgrimes#include <sys/cdefs.h>
251638Srgrimes__FBSDID("$FreeBSD: head/lib/libutil/login_times.c 184087 2008-10-20 17:09:50Z des $");
261638Srgrimes
271638Srgrimes#include <sys/types.h>
281638Srgrimes#include <ctype.h>
291638Srgrimes#include <login_cap.h>
301638Srgrimes#include <stdlib.h>
311638Srgrimes#include <string.h>
321638Srgrimes#include <time.h>
3350476Speter
341638Srgrimesstatic struct
351638Srgrimes{
361638Srgrimes    const char	*dw;
371638Srgrimes    u_char       cn;
381638Srgrimes    u_char       fl;
391638Srgrimes} dws[] =
401638Srgrimes{
411638Srgrimes    { "su", 2, LTM_SUN }, { "mo", 2, LTM_MON }, { "tu", 2, LTM_TUE },
421638Srgrimes    { "we", 2, LTM_WED }, { "th", 2, LTM_THU }, { "fr", 2, LTM_FRI },
431638Srgrimes    { "sa", 2, LTM_SAT }, { "any",3, LTM_ANY }, { "all",3, LTM_ANY },
441638Srgrimes    { "wk", 2, LTM_WK  }, { "wd", 2, LTM_WD  }, { NULL, 0, 0       }
451638Srgrimes};
461638Srgrimes
471638Srgrimesstatic char *
48107631Sruparse_time(char * ptr, u_short * t)
49107631Sru{
50107631Sru    u_short	val;
51107631Sru
52107631Sru    for (val = 0; *ptr && isdigit(*ptr); ptr++)
5379727Sschweikh	val = (u_short)(val * 10 + (*ptr - '0'));
5479727Sschweikh
5579727Sschweikh    *t = (u_short)((val / 100) * 60 + (val % 100));
5679727Sschweikh
5779727Sschweikh    return (ptr);
5879727Sschweikh}
5979727Sschweikh
6079727Sschweikh
6179727Sschweikhlogin_time_t
6279727Sschweikhparse_lt(const char *str)
63107631Sru{
641638Srgrimes    login_time_t    t;
651638Srgrimes
661638Srgrimes    memset(&t, 0, sizeof t);
671638Srgrimes    t.lt_dow = LTM_NONE;
681638Srgrimes    if (str && *str && strcmp(str, "Never") != 0 && strcmp(str, "None") != 0) {
691638Srgrimes	int		 i;
70107631Sru	login_time_t	 m = t;
71107631Sru	char		*p;
72107631Sru	char		 buf[64];
73107631Sru
74107631Sru	/* Make local copy and force lowercase to simplify parsing */
7579727Sschweikh	strlcpy(buf, str, sizeof buf);
7679727Sschweikh	for (i = 0; buf[i]; i++)
7779727Sschweikh	    buf[i] = (char)tolower(buf[i]);
7879727Sschweikh	p = buf;
7979727Sschweikh
8079727Sschweikh	while (isalpha(*p)) {
8179727Sschweikh
8279727Sschweikh	    i = 0;
8379727Sschweikh	    while (dws[i].dw && strncmp(p, dws[i].dw, dws[i].cn) != 0)
8479727Sschweikh		i++;
85107631Sru	    if (dws[i].dw == NULL)
861638Srgrimes		break;
871638Srgrimes	    m.lt_dow |= dws[i].fl;
881638Srgrimes	    p += dws[i].cn;
891638Srgrimes	}
901638Srgrimes
911638Srgrimes	if (m.lt_dow == LTM_NONE) /* No (valid) prefix, assume any */
92107631Sru	    m.lt_dow |= LTM_ANY;
93107631Sru
94107631Sru	if (isdigit(*p))
95107631Sru	    p = parse_time(p, &m.lt_start);
96107631Sru	else
9779727Sschweikh	    m.lt_start = 0;
9879727Sschweikh	if (*p == '-')
9979727Sschweikh	    p = parse_time(++p, &m.lt_end);
10079727Sschweikh	else
10179727Sschweikh	    m.lt_end = 1440;
10279727Sschweikh
10379727Sschweikh	t = m;
10479727Sschweikh    }
10579727Sschweikh    return (t);
10679727Sschweikh}
107107631Sru
1081638Srgrimes
1091638Srgrimesint
1101638Srgrimesin_ltm(const login_time_t *ltm, struct tm *tt, time_t *ends)
1111638Srgrimes{
1121638Srgrimes    int	    rc = 0;
1131638Srgrimes
1141638Srgrimes    if (tt != NULL) {
11568962Sru	/* First, examine the day of the week */
1161638Srgrimes	if ((u_char)(0x01 << tt->tm_wday) & ltm->lt_dow) {
1171638Srgrimes	    /* Convert `current' time to minute of the day */
118	    u_short	now = (u_short)((tt->tm_hour * 60) + tt->tm_min);
119
120	    if (tt->tm_sec > 30)
121		++now;
122	    if (now >= ltm->lt_start && now < ltm->lt_end) {
123		rc = 2;
124		if (ends != NULL) {
125		    /* If requested, return ending time for this period */
126		    tt->tm_hour = (int)(ltm->lt_end / 60);
127		    tt->tm_min  = (int)(ltm->lt_end % 60);
128		    *ends = mktime(tt);
129		}
130	    }
131	}
132    }
133    return (rc);
134}
135
136
137int
138in_lt(const login_time_t *ltm, time_t *t)
139{
140
141    return (in_ltm(ltm, localtime(t), t));
142}
143
144int
145in_ltms(const login_time_t *ltm, struct tm *tm, time_t *t)
146{
147    int	    i = 0;
148
149    while (i < LC_MAXTIMES && ltm[i].lt_dow != LTM_NONE) {
150	if (in_ltm(ltm + i, tm, t))
151	    return (i);
152	i++;
153    }
154    return (-1);
155}
156
157int
158in_lts(const login_time_t *ltm, time_t *t)
159{
160
161    return (in_ltms(ltm, localtime(t), t));
162}
163