sel_subs.c revision 46684
11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1992 Keith Muller.
31556Srgrimes * Copyright (c) 1992, 1993
41556Srgrimes *	The Regents of the University of California.  All rights reserved.
51556Srgrimes *
61556Srgrimes * This code is derived from software contributed to Berkeley by
71556Srgrimes * Keith Muller of the University of California, San Diego.
81556Srgrimes *
91556Srgrimes * Redistribution and use in source and binary forms, with or without
101556Srgrimes * modification, are permitted provided that the following conditions
111556Srgrimes * are met:
121556Srgrimes * 1. Redistributions of source code must retain the above copyright
131556Srgrimes *    notice, this list of conditions and the following disclaimer.
141556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
151556Srgrimes *    notice, this list of conditions and the following disclaimer in the
161556Srgrimes *    documentation and/or other materials provided with the distribution.
171556Srgrimes * 3. All advertising materials mentioning features or use of this software
181556Srgrimes *    must display the following acknowledgement:
191556Srgrimes *	This product includes software developed by the University of
201556Srgrimes *	California, Berkeley and its contributors.
211556Srgrimes * 4. Neither the name of the University nor the names of its contributors
221556Srgrimes *    may be used to endorse or promote products derived from this software
231556Srgrimes *    without specific prior written permission.
241556Srgrimes *
251556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
261556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
271556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
281556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
291556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
301556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
311556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
321556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
331556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
341556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
351556Srgrimes * SUCH DAMAGE.
361556Srgrimes */
371556Srgrimes
381556Srgrimes#ifndef lint
3936049Scharnier#if 0
4036049Scharnierstatic char sccsid[] = "@(#)sel_subs.c	8.1 (Berkeley) 5/31/93";
4136049Scharnier#endif
4236049Scharnierstatic const char rcsid[] =
4346684Skris	"$Id: sel_subs.c,v 1.9 1998/05/15 06:27:46 charnier Exp $";
441556Srgrimes#endif /* not lint */
451556Srgrimes
461556Srgrimes#include <sys/types.h>
471556Srgrimes#include <sys/time.h>
481556Srgrimes#include <sys/stat.h>
491556Srgrimes#include <pwd.h>
501556Srgrimes#include <grp.h>
511556Srgrimes#include <stdio.h>
521556Srgrimes#include <string.h>
531556Srgrimes#include <strings.h>
541556Srgrimes#include <unistd.h>
551556Srgrimes#include <stdlib.h>
561556Srgrimes#include "pax.h"
571556Srgrimes#include "sel_subs.h"
581556Srgrimes#include "extern.h"
591556Srgrimes
601556Srgrimesstatic int str_sec __P((register char *, time_t *));
611556Srgrimesstatic int usr_match __P((register ARCHD *));
621556Srgrimesstatic int grp_match __P((register ARCHD *));
631556Srgrimesstatic int trng_match __P((register ARCHD *));
641556Srgrimes
651556Srgrimesstatic TIME_RNG *trhead = NULL;		/* time range list head */
661556Srgrimesstatic TIME_RNG *trtail = NULL;		/* time range list tail */
671556Srgrimesstatic USRT **usrtb = NULL;		/* user selection table */
681556Srgrimesstatic GRPT **grptb = NULL;		/* group selection table */
691556Srgrimes
701556Srgrimes/*
711556Srgrimes * Routines for selection of archive members
721556Srgrimes */
731556Srgrimes
741556Srgrimes/*
751556Srgrimes * sel_chk()
7646684Skris *	check if this file matches a specified uid, gid or time range
771556Srgrimes * Return:
781556Srgrimes *	0 if this archive member should be processed, 1 if it should be skipped
791556Srgrimes */
801556Srgrimes
811556Srgrimes#if __STDC__
821556Srgrimesint
831556Srgrimessel_chk(register ARCHD *arcn)
841556Srgrimes#else
851556Srgrimesint
861556Srgrimessel_chk(arcn)
871556Srgrimes	register ARCHD *arcn;
881556Srgrimes#endif
891556Srgrimes{
901556Srgrimes	if (((usrtb != NULL) && usr_match(arcn)) ||
911556Srgrimes	    ((grptb != NULL) && grp_match(arcn)) ||
921556Srgrimes	    ((trhead != NULL) && trng_match(arcn)))
931556Srgrimes		return(1);
941556Srgrimes	return(0);
951556Srgrimes}
961556Srgrimes
971556Srgrimes/*
981556Srgrimes * User/group selection routines
991556Srgrimes *
1001556Srgrimes * Routines to handle user selection of files based on the file uid/gid. To
1011556Srgrimes * add an entry, the user supplies either then name or the uid/gid starting with
10246684Skris * a # on the command line. A \# will escape the #.
1031556Srgrimes */
1041556Srgrimes
1051556Srgrimes/*
1061556Srgrimes * usr_add()
1071556Srgrimes *	add a user match to the user match hash table
1081556Srgrimes * Return:
1091556Srgrimes *	0 if added ok, -1 otherwise;
1101556Srgrimes */
1111556Srgrimes
1121556Srgrimes#if __STDC__
1131556Srgrimesint
1141556Srgrimesusr_add(register char *str)
1151556Srgrimes#else
1161556Srgrimesint
1171556Srgrimesusr_add(str)
1181556Srgrimes	register char *str;
1191556Srgrimes#endif
1201556Srgrimes{
1211556Srgrimes	register u_int indx;
1221556Srgrimes	register USRT *pt;
1231556Srgrimes	register struct passwd *pw;
1241556Srgrimes	register uid_t uid;
1251556Srgrimes
1261556Srgrimes	/*
1271556Srgrimes	 * create the table if it doesn't exist
1281556Srgrimes	 */
1291556Srgrimes	if ((str == NULL) || (*str == '\0'))
1301556Srgrimes		return(-1);
1311556Srgrimes	if ((usrtb == NULL) &&
1321556Srgrimes 	    ((usrtb = (USRT **)calloc(USR_TB_SZ, sizeof(USRT *))) == NULL)) {
13328904Ssos                pax_warn(1, "Unable to allocate memory for user selection table");
1341556Srgrimes                return(-1);
1351556Srgrimes	}
1361556Srgrimes
1371556Srgrimes	/*
1381556Srgrimes	 * figure out user spec
1391556Srgrimes	 */
1401556Srgrimes	if (str[0] != '#') {
1411556Srgrimes		/*
1421556Srgrimes		 * it is a user name, \# escapes # as first char in user name
1431556Srgrimes		 */
1441556Srgrimes		if ((str[0] == '\\') && (str[1] == '#'))
1451556Srgrimes			++str;
1461556Srgrimes		if ((pw = getpwnam(str)) == NULL) {
14728904Ssos                	pax_warn(1, "Unable to find uid for user: %s", str);
1481556Srgrimes                	return(-1);
1491556Srgrimes		}
1501556Srgrimes		uid = (uid_t)pw->pw_uid;
1511556Srgrimes        } else
1521556Srgrimes#		ifdef NET2_STAT
1531556Srgrimes		uid = (uid_t)atoi(str+1);
1541556Srgrimes#		else
1551556Srgrimes		uid = (uid_t)strtoul(str+1, (char **)NULL, 10);
1561556Srgrimes#		endif
1571556Srgrimes	endpwent();
1581556Srgrimes
1591556Srgrimes	/*
1601556Srgrimes	 * hash it and go down the hash chain (if any) looking for it
1611556Srgrimes	 */
1621556Srgrimes	indx = ((unsigned)uid) % USR_TB_SZ;
1631556Srgrimes	if ((pt = usrtb[indx]) != NULL) {
1641556Srgrimes                while (pt != NULL) {
1651556Srgrimes                        if (pt->uid == uid)
1661556Srgrimes				return(0);
1671556Srgrimes                        pt = pt->fow;
1681556Srgrimes                }
1691556Srgrimes	}
1701556Srgrimes
1711556Srgrimes	/*
1721556Srgrimes	 * uid is not yet in the table, add it to the front of the chain
1731556Srgrimes	 */
1741556Srgrimes	if ((pt = (USRT *)malloc(sizeof(USRT))) != NULL) {
1751556Srgrimes		pt->uid = uid;
1761556Srgrimes		pt->fow = usrtb[indx];
1771556Srgrimes		usrtb[indx] = pt;
1781556Srgrimes		return(0);
1791556Srgrimes	}
18028904Ssos        pax_warn(1, "User selection table out of memory");
1811556Srgrimes        return(-1);
1821556Srgrimes}
1831556Srgrimes
1841556Srgrimes/*
1851556Srgrimes * usr_match()
1861556Srgrimes *	check if this files uid matches a selected uid.
1871556Srgrimes * Return:
1881556Srgrimes *	0 if this archive member should be processed, 1 if it should be skipped
1891556Srgrimes */
1901556Srgrimes
1911556Srgrimes#if __STDC__
1921556Srgrimesstatic int
1931556Srgrimesusr_match(register ARCHD *arcn)
1941556Srgrimes#else
1951556Srgrimesstatic int
1961556Srgrimesusr_match(arcn)
1971556Srgrimes	register ARCHD *arcn;
1981556Srgrimes#endif
1991556Srgrimes{
2001556Srgrimes	register USRT *pt;
2011556Srgrimes
2021556Srgrimes	/*
2031556Srgrimes	 * hash and look for it in the table
2041556Srgrimes	 */
2051556Srgrimes	pt = usrtb[((unsigned)arcn->sb.st_uid) % USR_TB_SZ];
2061556Srgrimes	while (pt != NULL) {
2071556Srgrimes		if (pt->uid == arcn->sb.st_uid)
2081556Srgrimes			return(0);
2091556Srgrimes		pt = pt->fow;
2101556Srgrimes	}
2111556Srgrimes
2121556Srgrimes	/*
2131556Srgrimes	 * not found
2141556Srgrimes	 */
2151556Srgrimes	return(1);
2161556Srgrimes}
2171556Srgrimes
2181556Srgrimes/*
2191556Srgrimes * grp_add()
2201556Srgrimes *	add a group match to the group match hash table
2211556Srgrimes * Return:
2221556Srgrimes *	0 if added ok, -1 otherwise;
2231556Srgrimes */
2241556Srgrimes
2251556Srgrimes#if __STDC__
2261556Srgrimesint
2271556Srgrimesgrp_add(register char *str)
2281556Srgrimes#else
2291556Srgrimesint
2301556Srgrimesgrp_add(str)
2311556Srgrimes	register char *str;
2321556Srgrimes#endif
2331556Srgrimes{
2341556Srgrimes	register u_int indx;
2351556Srgrimes	register GRPT *pt;
2361556Srgrimes	register struct group *gr;
2371556Srgrimes	register gid_t gid;
2381556Srgrimes
2391556Srgrimes	/*
2401556Srgrimes	 * create the table if it doesn't exist
2411556Srgrimes	 */
2421556Srgrimes	if ((str == NULL) || (*str == '\0'))
2431556Srgrimes		return(-1);
2441556Srgrimes	if ((grptb == NULL) &&
2451556Srgrimes 	    ((grptb = (GRPT **)calloc(GRP_TB_SZ, sizeof(GRPT *))) == NULL)) {
24628904Ssos                pax_warn(1, "Unable to allocate memory fo group selection table");
2471556Srgrimes                return(-1);
2481556Srgrimes	}
2491556Srgrimes
2501556Srgrimes	/*
2511556Srgrimes	 * figure out user spec
2521556Srgrimes	 */
2531556Srgrimes	if (str[0] != '#') {
2541556Srgrimes		/*
2551556Srgrimes		 * it is a group name, \# escapes # as first char in group name
2561556Srgrimes		 */
2571556Srgrimes		if ((str[0] == '\\') && (str[1] == '#'))
2581556Srgrimes			++str;
2591556Srgrimes		if ((gr = getgrnam(str)) == NULL) {
26028904Ssos                	pax_warn(1,"Cannot determine gid for group name: %s", str);
2611556Srgrimes                	return(-1);
2621556Srgrimes		}
2631556Srgrimes		gid = (gid_t)gr->gr_gid;
2641556Srgrimes        } else
2651556Srgrimes#		ifdef NET2_STAT
2661556Srgrimes		gid = (gid_t)atoi(str+1);
2671556Srgrimes#		else
2681556Srgrimes		gid = (gid_t)strtoul(str+1, (char **)NULL, 10);
2691556Srgrimes#		endif
2701556Srgrimes	endgrent();
2711556Srgrimes
2721556Srgrimes	/*
2731556Srgrimes	 * hash it and go down the hash chain (if any) looking for it
2741556Srgrimes	 */
2751556Srgrimes	indx = ((unsigned)gid) % GRP_TB_SZ;
2761556Srgrimes	if ((pt = grptb[indx]) != NULL) {
2771556Srgrimes                while (pt != NULL) {
2781556Srgrimes                        if (pt->gid == gid)
2791556Srgrimes				return(0);
2801556Srgrimes                        pt = pt->fow;
2811556Srgrimes                }
2821556Srgrimes	}
2831556Srgrimes
2841556Srgrimes	/*
2851556Srgrimes	 * gid not in the table, add it to the front of the chain
2861556Srgrimes	 */
2871556Srgrimes	if ((pt = (GRPT *)malloc(sizeof(GRPT))) != NULL) {
2881556Srgrimes		pt->gid = gid;
2891556Srgrimes		pt->fow = grptb[indx];
2901556Srgrimes		grptb[indx] = pt;
2911556Srgrimes		return(0);
2921556Srgrimes	}
29328904Ssos        pax_warn(1, "Group selection table out of memory");
2941556Srgrimes        return(-1);
2951556Srgrimes}
2961556Srgrimes
2971556Srgrimes/*
2981556Srgrimes * grp_match()
2991556Srgrimes *	check if this files gid matches a selected gid.
3001556Srgrimes * Return:
3011556Srgrimes *	0 if this archive member should be processed, 1 if it should be skipped
3021556Srgrimes */
3031556Srgrimes
3041556Srgrimes#if __STDC__
3051556Srgrimesstatic int
3061556Srgrimesgrp_match(register ARCHD *arcn)
3071556Srgrimes#else
3081556Srgrimesstatic int
3091556Srgrimesgrp_match(arcn)
3101556Srgrimes	register ARCHD *arcn;
3111556Srgrimes#endif
3121556Srgrimes{
3131556Srgrimes	register GRPT *pt;
3141556Srgrimes
3151556Srgrimes	/*
3161556Srgrimes	 * hash and look for it in the table
3171556Srgrimes	 */
3181556Srgrimes	pt = grptb[((unsigned)arcn->sb.st_gid) % GRP_TB_SZ];
3191556Srgrimes	while (pt != NULL) {
3201556Srgrimes		if (pt->gid == arcn->sb.st_gid)
3211556Srgrimes			return(0);
3221556Srgrimes		pt = pt->fow;
3231556Srgrimes	}
3241556Srgrimes
3251556Srgrimes	/*
3261556Srgrimes	 * not found
3271556Srgrimes	 */
3281556Srgrimes	return(1);
3291556Srgrimes}
3301556Srgrimes
3311556Srgrimes/*
3321556Srgrimes * Time range selection routines
3331556Srgrimes *
3341556Srgrimes * Routines to handle user selection of files based on the modification and/or
3351556Srgrimes * inode change time falling within a specified time range (the non-standard
3361556Srgrimes * -T flag). The user may specify any number of different file time ranges.
3371556Srgrimes * Time ranges are checked one at a time until a match is found (if at all).
3381556Srgrimes * If the file has a mtime (and/or ctime) which lies within one of the time
3391556Srgrimes * ranges, the file is selected. Time ranges may have a lower and/or a upper
3401556Srgrimes * value. These ranges are inclusive. When no time ranges are supplied to pax
3411556Srgrimes * with the -T option, all members in the archive will be selected by the time
3421556Srgrimes * range routines. When only a lower range is supplied, only files with a
3431556Srgrimes * mtime (and/or ctime) equal to or younger are selected. When only a upper
3441556Srgrimes * range is supplied, only files with a mtime (and/or ctime) equal to or older
3451556Srgrimes * are selected. When the lower time range is equal to the upper time range,
3461556Srgrimes * only files with a mtime (or ctime) of exactly that time are selected.
3471556Srgrimes */
3481556Srgrimes
3491556Srgrimes/*
3501556Srgrimes * trng_add()
3511556Srgrimes *	add a time range match to the time range list.
3521556Srgrimes *	This is a non-standard pax option. Lower and upper ranges are in the
3531556Srgrimes *	format: [yy[mm[dd[hh]]]]mm[.ss] and are comma separated.
3541556Srgrimes *	Time ranges are based on current time, so 1234 would specify a time of
3551556Srgrimes *	12:34 today.
3561556Srgrimes * Return:
3571556Srgrimes *	0 if the time range was added to the list, -1 otherwise
3581556Srgrimes */
3591556Srgrimes
3601556Srgrimes#if __STDC__
3611556Srgrimesint
3621556Srgrimestrng_add(register char *str)
3631556Srgrimes#else
3641556Srgrimesint
3651556Srgrimestrng_add(str)
3661556Srgrimes	register char *str;
3671556Srgrimes#endif
3681556Srgrimes{
3691556Srgrimes	register TIME_RNG *pt;
3701556Srgrimes	register char *up_pt = NULL;
3711556Srgrimes	register char *stpt;
3721556Srgrimes	register char *flgpt;
3731556Srgrimes	register int dot = 0;
3741556Srgrimes
3751556Srgrimes	/*
3761556Srgrimes	 * throw out the badly formed time ranges
3771556Srgrimes	 */
3781556Srgrimes	if ((str == NULL) || (*str == '\0')) {
37928904Ssos		pax_warn(1, "Empty time range string");
3801556Srgrimes		return(-1);
3811556Srgrimes	}
3821556Srgrimes
3831556Srgrimes	/*
3841556Srgrimes	 * locate optional flags suffix /{cm}.
3851556Srgrimes	 */
3861556Srgrimes	if ((flgpt = rindex(str, '/')) != NULL)
3871556Srgrimes		*flgpt++ = '\0';
3881556Srgrimes
3891556Srgrimes	for (stpt = str; *stpt != '\0'; ++stpt) {
3901556Srgrimes		if ((*stpt >= '0') && (*stpt <= '9'))
3911556Srgrimes			continue;
3921556Srgrimes		if ((*stpt == ',') && (up_pt == NULL)) {
3931556Srgrimes			*stpt = '\0';
3941556Srgrimes			up_pt = stpt + 1;
3951556Srgrimes			dot = 0;
3961556Srgrimes			continue;
3971556Srgrimes		}
3981556Srgrimes
3991556Srgrimes		/*
4001556Srgrimes		 * allow only one dot per range (secs)
4011556Srgrimes		 */
4021556Srgrimes		if ((*stpt == '.') && (!dot)) {
4031556Srgrimes			++dot;
4041556Srgrimes			continue;
4051556Srgrimes		}
40628904Ssos		pax_warn(1, "Improperly specified time range: %s", str);
4071556Srgrimes		goto out;
4081556Srgrimes	}
4091556Srgrimes
4101556Srgrimes	/*
4111556Srgrimes	 * allocate space for the time range and store the limits
4121556Srgrimes	 */
4131556Srgrimes	if ((pt = (TIME_RNG *)malloc(sizeof(TIME_RNG))) == NULL) {
41428904Ssos		pax_warn(1, "Unable to allocate memory for time range");
4151556Srgrimes		return(-1);
4161556Srgrimes	}
4171556Srgrimes
4181556Srgrimes	/*
4191556Srgrimes	 * by default we only will check file mtime, but usee can specify
4201556Srgrimes	 * mtime, ctime (inode change time) or both.
4211556Srgrimes	 */
4221556Srgrimes	if ((flgpt == NULL) || (*flgpt == '\0'))
4231556Srgrimes		pt->flgs = CMPMTME;
4241556Srgrimes	else {
4251556Srgrimes		pt->flgs = 0;
4261556Srgrimes		while (*flgpt != '\0') {
4271556Srgrimes			switch(*flgpt) {
4281556Srgrimes			case 'M':
4291556Srgrimes			case 'm':
4301556Srgrimes				pt->flgs |= CMPMTME;
4311556Srgrimes				break;
4321556Srgrimes			case 'C':
4331556Srgrimes			case 'c':
4341556Srgrimes				pt->flgs |= CMPCTME;
4351556Srgrimes				break;
4361556Srgrimes			default:
43728904Ssos				pax_warn(1, "Bad option %c with time range %s",
4381556Srgrimes				    *flgpt, str);
4391556Srgrimes				goto out;
4401556Srgrimes			}
4411556Srgrimes			++flgpt;
4421556Srgrimes		}
4431556Srgrimes	}
4441556Srgrimes
4451556Srgrimes	/*
4461556Srgrimes	 * start off with the current time
4471556Srgrimes	 */
4481556Srgrimes	pt->low_time = pt->high_time = time((time_t *)NULL);
4491556Srgrimes	if (*str != '\0') {
4501556Srgrimes		/*
4511556Srgrimes		 * add lower limit
4521556Srgrimes		 */
4531556Srgrimes		if (str_sec(str, &(pt->low_time)) < 0) {
45428904Ssos			pax_warn(1, "Illegal lower time range %s", str);
4551556Srgrimes			(void)free((char *)pt);
4561556Srgrimes			goto out;
4571556Srgrimes		}
4581556Srgrimes		pt->flgs |= HASLOW;
4591556Srgrimes	}
4601556Srgrimes
4611556Srgrimes	if ((up_pt != NULL) && (*up_pt != '\0')) {
4621556Srgrimes		/*
4631556Srgrimes		 * add upper limit
4641556Srgrimes		 */
4651556Srgrimes		if (str_sec(up_pt, &(pt->high_time)) < 0) {
46628904Ssos			pax_warn(1, "Illegal upper time range %s", up_pt);
4671556Srgrimes			(void)free((char *)pt);
4681556Srgrimes			goto out;
4691556Srgrimes		}
4701556Srgrimes		pt->flgs |= HASHIGH;
4711556Srgrimes
4721556Srgrimes		/*
4731556Srgrimes		 * check that the upper and lower do not overlap
4741556Srgrimes		 */
4751556Srgrimes		if (pt->flgs & HASLOW) {
4761556Srgrimes			if (pt->low_time > pt->high_time) {
47728904Ssos				pax_warn(1, "Upper %s and lower %s time overlap",
4781556Srgrimes					up_pt, str);
4791556Srgrimes				(void)free((char *)pt);
4801556Srgrimes				return(-1);
4811556Srgrimes			}
4821556Srgrimes		}
4831556Srgrimes	}
4841556Srgrimes
4851556Srgrimes	pt->fow = NULL;
4861556Srgrimes	if (trhead == NULL) {
4871556Srgrimes		trtail = trhead = pt;
4881556Srgrimes		return(0);
4891556Srgrimes	}
4901556Srgrimes	trtail->fow = pt;
4911556Srgrimes	trtail = pt;
4921556Srgrimes	return(0);
4931556Srgrimes
4941556Srgrimes    out:
49528904Ssos	pax_warn(1, "Time range format is: [yy[mm[dd[hh]]]]mm[.ss][/[c][m]]");
4961556Srgrimes	return(-1);
4971556Srgrimes}
4981556Srgrimes
4991556Srgrimes/*
5001556Srgrimes * trng_match()
5011556Srgrimes *	check if this files mtime/ctime falls within any supplied time range.
5021556Srgrimes * Return:
5031556Srgrimes *	0 if this archive member should be processed, 1 if it should be skipped
5041556Srgrimes */
5051556Srgrimes
5061556Srgrimes#if __STDC__
5071556Srgrimesstatic int
5081556Srgrimestrng_match(register ARCHD *arcn)
5091556Srgrimes#else
5101556Srgrimesstatic int
5111556Srgrimestrng_match(arcn)
5121556Srgrimes	register ARCHD *arcn;
5131556Srgrimes#endif
5141556Srgrimes{
5151556Srgrimes	register TIME_RNG *pt;
5161556Srgrimes
5171556Srgrimes	/*
5181556Srgrimes	 * have to search down the list one at a time looking for a match.
5191556Srgrimes	 * remember time range limits are inclusive.
5201556Srgrimes	 */
5211556Srgrimes	pt = trhead;
5221556Srgrimes	while (pt != NULL) {
5231556Srgrimes		switch(pt->flgs & CMPBOTH) {
5241556Srgrimes		case CMPBOTH:
5251556Srgrimes			/*
5261556Srgrimes			 * user wants both mtime and ctime checked for this
5271556Srgrimes			 * time range
5281556Srgrimes			 */
5291556Srgrimes			if (((pt->flgs & HASLOW) &&
5301556Srgrimes			    (arcn->sb.st_mtime < pt->low_time) &&
5311556Srgrimes			    (arcn->sb.st_ctime < pt->low_time)) ||
5321556Srgrimes			    ((pt->flgs & HASHIGH) &&
5331556Srgrimes			    (arcn->sb.st_mtime > pt->high_time) &&
5341556Srgrimes			    (arcn->sb.st_ctime > pt->high_time))) {
5351556Srgrimes				pt = pt->fow;
5361556Srgrimes				continue;
5371556Srgrimes			}
5381556Srgrimes			break;
5391556Srgrimes		case CMPCTME:
5401556Srgrimes			/*
5411556Srgrimes			 * user wants only ctime checked for this time range
5421556Srgrimes			 */
5431556Srgrimes			if (((pt->flgs & HASLOW) &&
5441556Srgrimes			    (arcn->sb.st_ctime < pt->low_time)) ||
5451556Srgrimes			    ((pt->flgs & HASHIGH) &&
5461556Srgrimes			    (arcn->sb.st_ctime > pt->high_time))) {
5471556Srgrimes				pt = pt->fow;
5481556Srgrimes				continue;
5491556Srgrimes			}
5501556Srgrimes			break;
5511556Srgrimes		case CMPMTME:
5521556Srgrimes		default:
5531556Srgrimes			/*
5541556Srgrimes			 * user wants only mtime checked for this time range
5551556Srgrimes			 */
5561556Srgrimes			if (((pt->flgs & HASLOW) &&
5571556Srgrimes			    (arcn->sb.st_mtime < pt->low_time)) ||
5581556Srgrimes			    ((pt->flgs & HASHIGH) &&
5591556Srgrimes			    (arcn->sb.st_mtime > pt->high_time))) {
5601556Srgrimes				pt = pt->fow;
5611556Srgrimes				continue;
5621556Srgrimes			}
5631556Srgrimes			break;
5641556Srgrimes		}
5651556Srgrimes		break;
5661556Srgrimes	}
5671556Srgrimes
5681556Srgrimes	if (pt == NULL)
5691556Srgrimes		return(1);
5701556Srgrimes	return(0);
5711556Srgrimes}
5721556Srgrimes
5731556Srgrimes/*
5741556Srgrimes * str_sec()
5751556Srgrimes *	Convert a time string in the format of [yy[mm[dd[hh]]]]mm[.ss] to gmt
5761556Srgrimes *	seconds. Tval already has current time loaded into it at entry.
5771556Srgrimes * Return:
5781556Srgrimes *	0 if converted ok, -1 otherwise
5791556Srgrimes */
5801556Srgrimes
5811556Srgrimes#if __STDC__
5821556Srgrimesstatic int
5831556Srgrimesstr_sec(register char *str, time_t *tval)
5841556Srgrimes#else
5851556Srgrimesstatic int
5861556Srgrimesstr_sec(str, tval)
5871556Srgrimes	register char *str;
5881556Srgrimes	time_t *tval;
5891556Srgrimes#endif
5901556Srgrimes{
5911556Srgrimes	register struct tm *lt;
5921556Srgrimes	register char *dot = NULL;
5931556Srgrimes
5941556Srgrimes	lt = localtime(tval);
5951556Srgrimes	if ((dot = index(str, '.')) != NULL) {
5961556Srgrimes		/*
5971556Srgrimes		 * seconds (.ss)
5981556Srgrimes		 */
5991556Srgrimes		*dot++ = '\0';
6001556Srgrimes		if (strlen(dot) != 2)
6011556Srgrimes			return(-1);
6021556Srgrimes		if ((lt->tm_sec = ATOI2(dot)) > 61)
6031556Srgrimes			return(-1);
6041556Srgrimes	} else
6051556Srgrimes		lt->tm_sec = 0;
6061556Srgrimes
6071556Srgrimes	switch (strlen(str)) {
6081556Srgrimes	case 10:
6091556Srgrimes		/*
6101556Srgrimes		 * year (yy)
6111556Srgrimes		 * watch out for year 2000
6121556Srgrimes		 */
6131556Srgrimes		if ((lt->tm_year = ATOI2(str)) < 69)
6141556Srgrimes			lt->tm_year += 100;
6151556Srgrimes		str += 2;
6161556Srgrimes		/* FALLTHROUGH */
6171556Srgrimes	case 8:
6181556Srgrimes		/*
6191556Srgrimes		 * month (mm)
6201556Srgrimes		 * watch out months are from 0 - 11 internally
6211556Srgrimes		 */
6221556Srgrimes		if ((lt->tm_mon = ATOI2(str)) > 12)
6231556Srgrimes			return(-1);
6241556Srgrimes		--lt->tm_mon;
6251556Srgrimes		str += 2;
6261556Srgrimes		/* FALLTHROUGH */
6271556Srgrimes	case 6:
6281556Srgrimes		/*
6291556Srgrimes		 * day (dd)
6301556Srgrimes		 */
6311556Srgrimes		if ((lt->tm_mday = ATOI2(str)) > 31)
6321556Srgrimes			return(-1);
6331556Srgrimes		str += 2;
6341556Srgrimes		/* FALLTHROUGH */
6351556Srgrimes	case 4:
6361556Srgrimes		/*
6371556Srgrimes		 * hour (hh)
6381556Srgrimes		 */
6391556Srgrimes		if ((lt->tm_hour = ATOI2(str)) > 23)
6401556Srgrimes			return(-1);
6411556Srgrimes		str += 2;
6421556Srgrimes		/* FALLTHROUGH */
6431556Srgrimes	case 2:
6441556Srgrimes		/*
6451556Srgrimes		 * minute (mm)
6461556Srgrimes		 */
6471556Srgrimes		if ((lt->tm_min = ATOI2(str)) > 59)
6481556Srgrimes			return(-1);
6491556Srgrimes		break;
6501556Srgrimes	default:
6511556Srgrimes		return(-1);
6521556Srgrimes	}
6531556Srgrimes	/*
6541556Srgrimes	 * convert broken-down time to GMT clock time seconds
6551556Srgrimes	 */
6561556Srgrimes	if ((*tval = mktime(lt)) == -1)
6571556Srgrimes		return(-1);
6581556Srgrimes	return(0);
6591556Srgrimes}
660