xref: /freebsd/lib/libutil/login_times.c (revision 0ebec5d3c836a1a8ba2d3b4b06c57c5ecb104485)
168bbf3adSDavid Nugent /*-
268bbf3adSDavid Nugent  * Copyright (c) 1996 by
368bbf3adSDavid Nugent  * David Nugent <davidn@blaze.net.au>
468bbf3adSDavid Nugent  * All rights reserved.
568bbf3adSDavid Nugent  *
668bbf3adSDavid Nugent  * Redistribution and use in source and binary forms, with or without
768bbf3adSDavid Nugent  * modification, is permitted provided that the following conditions
868bbf3adSDavid Nugent  * are met:
968bbf3adSDavid Nugent  * 1. Redistributions of source code must retain the above copyright
1068bbf3adSDavid Nugent  *    notice immediately at the beginning of the file, without modification,
1168bbf3adSDavid Nugent  *    this list of conditions, and the following disclaimer.
1268bbf3adSDavid Nugent  * 2. Redistributions in binary form must reproduce the above copyright
1368bbf3adSDavid Nugent  *    notice, this list of conditions and the following disclaimer in the
1468bbf3adSDavid Nugent  *    documentation and/or other materials provided with the distribution.
1568bbf3adSDavid Nugent  * 3. This work was done expressly for inclusion into FreeBSD.  Other use
1668bbf3adSDavid Nugent  *    is permitted provided this notation is included.
1768bbf3adSDavid Nugent  * 4. Absolutely no warranty of function or purpose is made by the authors.
1868bbf3adSDavid Nugent  * 5. Modifications may be freely made to this file providing the above
1968bbf3adSDavid Nugent  *    conditions are met.
2068bbf3adSDavid Nugent  *
2168bbf3adSDavid Nugent  * Login period parsing and comparison functions.
2268bbf3adSDavid Nugent  */
2368bbf3adSDavid Nugent 
248719c58fSMatthew Dillon #include <sys/cdefs.h>
258719c58fSMatthew Dillon __FBSDID("$FreeBSD$");
268719c58fSMatthew Dillon 
270ebec5d3SMark Murray #include <sys/types.h>
280ebec5d3SMark Murray #include <ctype.h>
290ebec5d3SMark Murray #include <login_cap.h>
3068bbf3adSDavid Nugent #include <stdlib.h>
3168bbf3adSDavid Nugent #include <string.h>
3268bbf3adSDavid Nugent #include <time.h>
3368bbf3adSDavid Nugent 
3468bbf3adSDavid Nugent static struct
3568bbf3adSDavid Nugent {
3668bbf3adSDavid Nugent     const char	*dw;
3768bbf3adSDavid Nugent     u_char      cn;
3868bbf3adSDavid Nugent     u_char      fl;
3968bbf3adSDavid Nugent } dws[] =
4068bbf3adSDavid Nugent {
4168bbf3adSDavid Nugent     { "su", 2, LTM_SUN }, { "mo", 2, LTM_MON }, { "tu", 2, LTM_TUE },
4268bbf3adSDavid Nugent     { "we", 2, LTM_WED }, { "th", 2, LTM_THU }, { "fr", 2, LTM_FRI },
4368bbf3adSDavid Nugent     { "sa", 2, LTM_SAT }, { "any",3, LTM_ANY }, { "all",3, LTM_ANY },
4468bbf3adSDavid Nugent     { "wk", 2, LTM_WK  }, { "wd", 2, LTM_WD  }, { NULL, 0, 0       }
4568bbf3adSDavid Nugent };
4668bbf3adSDavid Nugent 
4768bbf3adSDavid Nugent static char *
4868bbf3adSDavid Nugent parse_time(char * ptr, u_short * t)
4968bbf3adSDavid Nugent {
5068bbf3adSDavid Nugent     u_short	val;
5168bbf3adSDavid Nugent 
5268bbf3adSDavid Nugent     for (val = 0; *ptr && isdigit(*ptr); ptr++)
5368bbf3adSDavid Nugent 	val = (u_short)(val * 10 + (*ptr - '0'));
5468bbf3adSDavid Nugent 
5568bbf3adSDavid Nugent     *t = (u_short)((val / 100) * 60 + (val % 100));
5656c04344SDavid Nugent 
5768bbf3adSDavid Nugent     return ptr;
5868bbf3adSDavid Nugent }
5968bbf3adSDavid Nugent 
6056c04344SDavid Nugent 
6168bbf3adSDavid Nugent login_time_t
6268bbf3adSDavid Nugent parse_lt(const char * str)
6368bbf3adSDavid Nugent {
6468bbf3adSDavid Nugent     login_time_t    t;
6568bbf3adSDavid Nugent 
6668bbf3adSDavid Nugent     memset(&t, 0, sizeof t);
6768bbf3adSDavid Nugent     t.lt_dow = LTM_NONE;
6856c04344SDavid Nugent     if (str && *str && strcmp(str, "Never") != 0 && strcmp(str, "None") != 0) {
6968bbf3adSDavid Nugent 	int		i;
7068bbf3adSDavid Nugent 	login_time_t	m = t;
7168bbf3adSDavid Nugent 	char		*p;
7268bbf3adSDavid Nugent 	char		buf[64];
7368bbf3adSDavid Nugent 
7456c04344SDavid Nugent 	/* Make local copy and force lowercase to simplify parsing */
7568bbf3adSDavid Nugent 	p = strncpy(buf, str, sizeof buf);
7668bbf3adSDavid Nugent 	buf[sizeof buf - 1] = '\0';
7768bbf3adSDavid Nugent 	for (i = 0; buf[i]; i++)
7868bbf3adSDavid Nugent 	    buf[i] = (char)tolower(buf[i]);
7968bbf3adSDavid Nugent 
8056c04344SDavid Nugent 	while (isalpha(*p)) {
8156c04344SDavid Nugent 
8256c04344SDavid Nugent 	    i = 0;
8356c04344SDavid Nugent 	    while (dws[i].dw && strncmp(p, dws[i].dw, dws[i].cn) != 0)
8456c04344SDavid Nugent 		i++;
8568bbf3adSDavid Nugent 	    if (dws[i].dw == NULL)
8668bbf3adSDavid Nugent 		break;
8768bbf3adSDavid Nugent 	    m.lt_dow |= dws[i].fl;
8868bbf3adSDavid Nugent 	    p += dws[i].cn;
8968bbf3adSDavid Nugent 	}
9068bbf3adSDavid Nugent 
9168bbf3adSDavid Nugent 	if (m.lt_dow == LTM_NONE) /* No (valid) prefix, assume any */
9268bbf3adSDavid Nugent 	    m.lt_dow |= LTM_ANY;
9368bbf3adSDavid Nugent 
9468bbf3adSDavid Nugent 	if (isdigit(*p))
9568bbf3adSDavid Nugent 	    p = parse_time(p, &m.lt_start);
9668bbf3adSDavid Nugent 	else
9768bbf3adSDavid Nugent 	    m.lt_start = 0;
9868bbf3adSDavid Nugent 	if (*p == '-')
9968bbf3adSDavid Nugent 	    p = parse_time(++p, &m.lt_end);
10068bbf3adSDavid Nugent 	else
10168bbf3adSDavid Nugent 	    m.lt_end = 1440;
10268bbf3adSDavid Nugent 
10368bbf3adSDavid Nugent 	t = m;
10468bbf3adSDavid Nugent     }
10568bbf3adSDavid Nugent     return t;
10668bbf3adSDavid Nugent }
10768bbf3adSDavid Nugent 
10868bbf3adSDavid Nugent 
10968bbf3adSDavid Nugent int
11068bbf3adSDavid Nugent in_ltm(const login_time_t * ltm, struct tm * tt, time_t * ends)
11168bbf3adSDavid Nugent {
11268bbf3adSDavid Nugent     int	    rc = 0;
11368bbf3adSDavid Nugent 
11456c04344SDavid Nugent     if (tt != NULL) {
11556c04344SDavid Nugent 	/* First, examine the day of the week */
11656c04344SDavid Nugent 	if ((u_char)(0x01 << tt->tm_wday) & ltm->lt_dow) {
11756c04344SDavid Nugent 	    /* Convert `current' time to minute of the day */
11868bbf3adSDavid Nugent 	    u_short	now = (u_short)((tt->tm_hour * 60) + tt->tm_min);
11956c04344SDavid Nugent 
12068bbf3adSDavid Nugent 	    if (tt->tm_sec > 30)
12168bbf3adSDavid Nugent 		++now;
12256c04344SDavid Nugent 	    if (now >= ltm->lt_start && now < ltm->lt_end) {
12368bbf3adSDavid Nugent 		rc = 2;
12456c04344SDavid Nugent 		if (ends != NULL) {
12556c04344SDavid Nugent 		    /* If requested, return ending time for this period */
12668bbf3adSDavid Nugent 		    tt->tm_hour = (int)(ltm->lt_end / 60);
12768bbf3adSDavid Nugent 		    tt->tm_min  = (int)(ltm->lt_end % 60);
12868bbf3adSDavid Nugent 		    *ends = mktime(tt);
12968bbf3adSDavid Nugent 		}
13068bbf3adSDavid Nugent 	    }
13168bbf3adSDavid Nugent 	}
13268bbf3adSDavid Nugent     }
13368bbf3adSDavid Nugent     return rc;
13468bbf3adSDavid Nugent }
13568bbf3adSDavid Nugent 
13656c04344SDavid Nugent 
13768bbf3adSDavid Nugent int
13868bbf3adSDavid Nugent in_lt(const login_time_t * ltm, time_t * t)
13968bbf3adSDavid Nugent {
14068bbf3adSDavid Nugent     return in_ltm(ltm, localtime(t), t);
14168bbf3adSDavid Nugent }
14268bbf3adSDavid Nugent 
14368bbf3adSDavid Nugent int
14468bbf3adSDavid Nugent in_ltms(const login_time_t * ltm, struct tm * tm, time_t * t)
14568bbf3adSDavid Nugent {
14668bbf3adSDavid Nugent     int	    i = 0;
14768bbf3adSDavid Nugent 
14856c04344SDavid Nugent     while (i < LC_MAXTIMES && ltm[i].lt_dow != LTM_NONE) {
14968bbf3adSDavid Nugent 	if (in_ltm(ltm + i, tm, t))
15068bbf3adSDavid Nugent 	    return i;
15168bbf3adSDavid Nugent 	i++;
15268bbf3adSDavid Nugent     }
15368bbf3adSDavid Nugent     return -1;
15468bbf3adSDavid Nugent }
15568bbf3adSDavid Nugent 
15668bbf3adSDavid Nugent int
15768bbf3adSDavid Nugent in_lts(const login_time_t * ltm, time_t * t)
15868bbf3adSDavid Nugent {
15968bbf3adSDavid Nugent     return in_ltms(ltm, localtime(t), t);
16068bbf3adSDavid Nugent }
16168bbf3adSDavid Nugent 
162