*BSD News Article 61014


Return to BSD News archive

Newsgroups: comp.bugs.2bsd
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!news.cs.su.oz.au!inferno.mpx.com.au!news.unimelb.EDU.AU!munnari.OZ.AU!news.hawaii.edu!ames!usenet.kornet.nm.kr!news.kreonet.re.kr!usenet.seri.re.kr!news.cais.net!ringer.cs.utsa.edu!swrinde!cssun.mathcs.emory.edu!gatech!news.mathworks.com!uunet!in2.uu.net!news.new-york.net!wlbr!sms
From: sms@wlv.iipo.gtegsc.com (Steven M. Schultz)
Subject: mount(8) options, !/etc/mtab, libkern.a, MANY others (#295 part 4 of 8)
Sender: news@wlbr.iipo.gtegsc.com (Steven M. Schultz)
Organization: GTE Government Systems, Thousand Oaks CA USA
Message-ID: <DM4rqv.M2x@wlbr.iipo.gtegsc.com>
X-Nntp-Posting-Host: wlv.iipo.gtegsc.com
Date: Fri, 2 Feb 1996 04:13:43 GMT
Lines: 2853

Subject: mount(8) options, !/etc/mtab, libkern.a, MANY others (#295 part 4 of 8)
Index:	many/many 2.11BSD

Description:
	Mount(8) does not pass options other than 'readonly' thru to the
	kernel even though the kernel understands many more options than
	that.

	/etc/mtab is not needed any longer because applications (mount, umount,
	others) can obtain the list of mounted filesystems via getmntinfo(3),
	or getfsstat(2)

	There are copies of 15 libc routines in the kernel directories.  These
	are invariant but nevertheless are always being recompiled/assembled
	whenever a kernel is built.

Repeat-By:
	It sounds inadequate, but, "observation".

Fix:
	This is #295 (part 4 of 8).

	Please refer to part 1 (#292) for detailed instructions and a
	description of contents.

----------------------------cut here-------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	/usr/src/lib/libc/string
#	/usr/src/lib/libkern
#	/usr/src/etc/quotacheck
#	/usr/src/etc/edquota.c
#	/usr/src/etc/quotaon.c
#	/usr/src/etc/repquota.c
# This archive created: Tue Jan 30 21:08:08 1996
export PATH; PATH=/bin:/usr/bin:$PATH
if test ! -d '/usr/src/lib/libc/string'
then
	mkdir '/usr/src/lib/libc/string'
fi
cd '/usr/src/lib/libc/string'
if test -f 'strcspn.c'
then
	echo shar: "will not over-write existing file 'strcspn.c'"
else
sed 's/^X//' << \SHAR_EOF > 'strcspn.c'
X/*-
X * Copyright (c) 1990, 1993
X *	The Regents of the University of California.  All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Chris Torek.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)strcspn.c	8.1.1 (2.11BSD) 1996/1/11";
X#endif /* LIBC_SCCS and not lint */
X
X#include <sys/types.h>
X#include <string.h>
X
X/*
X * Span the complement of string s2.
X */
Xsize_t
Xstrcspn(s1, s2)
X	char *s1;
X	char *s2;
X{
X	register char *p, *spanp;
X	register char c, sc;
X
X	/*
X	 * Stop as soon as we find any character from s2.  Note that there
X	 * must be a NUL in s2; it suffices to stop when we find that, too.
X	 */
X	for (p = s1;;) {
X		c = *p++;
X		spanp = s2;
X		do {
X			if ((sc = *spanp++) == c)
X				return (p - 1 - s1);
X		} while (sc != 0);
X	}
X	/* NOTREACHED */
X}
SHAR_EOF
chmod 644 'strcspn.c'
fi
if test -f 'strpbrk.c'
then
	echo shar: "will not over-write existing file 'strpbrk.c'"
else
sed 's/^X//' << \SHAR_EOF > 'strpbrk.c'
X/*
X * Copyright (c) 1985, 1993
X *	The Regents of the University of California.  All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)strpbrk.c	8.1.1 (2.11BSD) 1996/1/11";
X#endif /* LIBC_SCCS and not lint */
X
X#include <sys/types.h>
X#include <string.h>
X#include <stdio.h>	/* for NULL */
X
X/*
X * Find the first occurrence in s1 of a character in s2 (excluding NUL).
X */
Xchar *
Xstrpbrk(s1, s2)
X	register char *s1;
X	char	*s2;
X{
X	register char *scanp;
X	register int c;
X	int	sc;
X
X	while ((c = *s1++) != 0) {
X		for (scanp = s2; (sc = *scanp++) != 0;)
X			if (sc == c)
X				return ((char *)(s1 - 1));
X	}
X	return (NULL);
X}
SHAR_EOF
chmod 644 'strpbrk.c'
fi
if test -f 'strsep.c'
then
	echo shar: "will not over-write existing file 'strsep.c'"
else
sed 's/^X//' << \SHAR_EOF > 'strsep.c'
X/*-
X * Copyright (c) 1990, 1993
X *	The Regents of the University of California.  All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#include <sys/types.h>
X#include <string.h>
X#include <stdio.h>
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)strsep.c	8.1.1 (2.11BSD) 1996/1/11";
X#endif /* LIBC_SCCS and not lint */
X
X/*
X * Get next token from string *stringp, where tokens are possibly-empty
X * strings separated by characters from delim.  
X *
X * Writes NULs into the string at *stringp to end tokens.
X * delim need not remain constant from call to call.
X * On return, *stringp points past the last NUL written (if there might
X * be further tokens), or is NULL (if there are definitely no more tokens).
X *
X * If *stringp is NULL, strsep returns NULL.
X */
Xchar *
Xstrsep(stringp, delim)
X	register char **stringp;
X	char *delim;
X{
X	register char *s;
X	register char *spanp;
X	int c, sc;
X	char *tok;
X
X	if ((s = *stringp) == NULL)
X		return (NULL);
X	for (tok = s;;) {
X		c = *s++;
X		spanp = delim;
X		do {
X			if ((sc = *spanp++) == c) {
X				if (c == 0)
X					s = NULL;
X				else
X					s[-1] = 0;
X				*stringp = s;
X				return (tok);
X			}
X		} while (sc != 0);
X	}
X	/* NOTREACHED */
X}
SHAR_EOF
chmod 644 'strsep.c'
fi
if test -f 'strspn.c'
then
	echo shar: "will not over-write existing file 'strspn.c'"
else
sed 's/^X//' << \SHAR_EOF > 'strspn.c'
X/*
X * Copyright (c) 1989, 1993
X *	The Regents of the University of California.  All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)strspn.c	8.1.1 (2.11BSD) 1996/1/11";
X#endif /* LIBC_SCCS and not lint */
X
X#include <sys/types.h>
X#include <string.h>
X
X/*
X * Span the string s2 (skip characters that are in s2).
X */
Xsize_t
Xstrspn(s1, s2)
X	char *s1;
X	char *s2;
X{
X	register char *p = s1, *spanp;
X	register char c, sc;
X
X	/*
X	 * Skip any characters in s2, excluding the terminating \0.
X	 */
Xcont:
X	c = *p++;
X	for (spanp = s2; (sc = *spanp++) != 0;)
X		if (sc == c)
X			goto cont;
X	return (p - 1 - s1);
X}
SHAR_EOF
chmod 644 'strspn.c'
fi
if test -f 'strtok.c'
then
	echo shar: "will not over-write existing file 'strtok.c'"
else
sed 's/^X//' << \SHAR_EOF > 'strtok.c'
X/*
X * Copyright (c) 1988, 1993
X *	The Regents of the University of California.  All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)strtok.c	8.1.1 (2.11BSD) 1996/1/11";
X#endif /* LIBC_SCCS and not lint */
X
X#include <string.h>
X#include <stdio.h>
X
Xchar *
Xstrtok(s, delim)
X	register char *s;
X	register char *delim;
X{
X	register char *spanp;
X	int c, sc;
X	char *tok;
X	static char *last;
X
X
X	if (s == NULL && (s = last) == NULL)
X		return (NULL);
X
X	/*
X	 * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
X	 */
Xcont:
X	c = *s++;
X	for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
X		if (c == sc)
X			goto cont;
X	}
X
X	if (c == 0) {		/* no non-delimiter characters */
X		last = NULL;
X		return (NULL);
X	}
X	tok = s - 1;
X
X	/*
X	 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
X	 * Note that delim must have one NUL; we stop if we see that, too.
X	 */
X	for (;;) {
X		c = *s++;
X		spanp = (char *)delim;
X		do {
X			if ((sc = *spanp++) == c) {
X				if (c == 0)
X					s = NULL;
X				else
X					s[-1] = 0;
X				last = s;
X				return (tok);
X			}
X		} while (sc != 0);
X	}
X	/* NOTREACHED */
X}
SHAR_EOF
chmod 644 'strtok.c'
fi
if test ! -d 'profiled'
then
	mkdir 'profiled'
fi
cd 'profiled'
chmod 755 .
cd ..
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X#
X#	@(#)Makefile	1.1 (2.11BSD GTE) 1995/1/15
X#
X# This is the Makefile for the 'string' functions.  New routines ported from 
X# 4.4BSD's libc/string directory go here but existing libc/gen files are 
X# being left where they are.
X#
X
XDEFS=
XCFLAGS=	 -O ${DEFS}
XCC=	cc
X
XSRCS=	strcspn.c strpbrk.c strsep.c strspn.c strstr.c strtok.c
XOBJS=	strcspn.o strpbrk.o strsep.o strspn.o strstr.o strtok.o
X
X.c.o:
X	${CC} -p ${CFLAGS} -c $*.c
X	ld -X -r $*.o
X	mv a.out profiled/$*.o
X	${CC} ${CFLAGS} -c $*.c
X	ld -X -r $*.o
X	mv a.out $*.o
X
Xall: stringlib stringlib_p
X
Xstringlib stringlib_p: ${OBJS}
X	@echo "building profiled stringlib"
X	@cd profiled; ar cru ../stringlib_p ${OBJS}
X	@echo "building normal stringlib"
X	@ar cru stringlib ${OBJS}
X
Xclean:
X	rm -f ${OBJS} profiled/*.o tags Makefile.bak stringlib stringlib_p
X
Xdepend: ${SRCS}
X	mkdep ${CFLAGS} ${SRCS}
X
Xtags:
X	cwd=`pwd`; \
X	for i in ${SRCS}; do \
X		ctags -a -f ${TAGSFILE} $$cwd/$$i; \
X	done
X
X# DO NOT DELETE THIS LINE -- mkdep uses it.
X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
SHAR_EOF
chmod 644 'Makefile'
fi
if test -f 'strstr.c'
then
	echo shar: "will not over-write existing file 'strstr.c'"
else
sed 's/^X//' << \SHAR_EOF > 'strstr.c'
X/*-
X * Copyright (c) 1990, 1993
X *	The Regents of the University of California.  All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Chris Torek.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)strstr.c	8.1.1 (2.11BSD) 1996/1/15";
X#endif /* LIBC_SCCS and not lint */
X
X#include <string.h>
X
X/*
X * Find the first occurrence of find in s.
X */
Xchar *
Xstrstr(s, find)
X	register char *s, *find;
X{
X	register char c;
X	char	sc;
X	size_t	len;
X
X	if ((c = *find++) != 0) {
X		len = strlen(find);
X		do {
X			do {
X				if ((sc = *s++) == 0)
X					return (NULL);
X			} while (sc != c);
X		} while (strncmp(s, find, len) != 0);
X		s--;
X	}
X	return ((char *)s);
X}
SHAR_EOF
chmod 440 'strstr.c'
fi
chmod 755 .
cd ..
if test ! -d '/usr/src/lib/libkern'
then
	mkdir '/usr/src/lib/libkern'
fi
cd '/usr/src/lib/libkern'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X#
X#	@(#)Makefile	1.0 (2.11BSD GTE) 1995/1/10
X#
X# This is the Makefile for 'libkern.a'.  These are the specially compiled
X# versions of libc.a routines which the kernel and network use.
X#
X# There are no source files in this directory.  The VPATH capability is
X# used instead.  libkern.a needs to be installed only once (usually when the 
X# C library is installed) rather than compiling the sources each time 
X# a kernel is compiled..
X
XDEFS=	-DKERNEL
XCFLAGS=	 -O ${DEFS}
XCPP=	/lib/cpp -P ${DEFS}
XAS=	/bin/as -u
XPREFIX=	/usr/src/lib/libc
XVPATH= ${PREFIX}/pdp/crt:${PREFIX}/pdp/gen:${PREFIX}/pdp/net
X
XSRCS=	bcmp.s bcopy.s bzero.s ffs.s htonl.s htons.s insque.s \
X	ldiv.s lmul.s lrem.s remque.s strlen.s udiv.s uldiv.s ulsh.s
X
XOBJS=	bcmp.o bcopy.o bzero.o ffs.o htonl.o htons.o insque.o \
X	ldiv.o lmul.o lrem.o remque.o strlen.o udiv.o uldiv.o ulsh.o
X
X.c.o:
X	${CC} ${CFLAGS} $*.c
X	ld -X -r $*.o
X	mv a.out $*.o
X
X.s.o:
X	${CPP} $*.s | ${AS} -o $*.o
X	ld -X -r $*.o
X	mv a.out $*.o
X
Xall: libkern.a
X
Xlibkern.a: ${OBJS}
X	rm -f libkern.a
X	ar rv libkern.a ${OBJS}
X
Xclean:
X	rm -f ${OBJS} libkern.a
X
Xdepend: ${SRCS}
X	mkdep ${CFLAGS} ${SRCS}
X
Xinstall: libkern.a
X	install -o root -g bin -m 644 libkern.a ${DESTDIR}/usr/lib/libkern.a
X	ranlib ${DESTDIR}/usr/lib/libkern.a
X
X# DO NOT DELETE THIS LINE -- mkdep uses it.
X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
SHAR_EOF
chmod 644 'Makefile'
fi
chmod 755 .
cd ..
if test ! -d '/usr/src/etc/quotacheck'
then
	mkdir '/usr/src/etc/quotacheck'
fi
cd '/usr/src/etc/quotacheck'
if test -f 'preen.c'
then
	echo shar: "will not over-write existing file 'preen.c'"
else
sed 's/^X//' << \SHAR_EOF > 'preen.c'
X/*
X * Copyright (c) 1990, 1993
X *	The Regents of the University of California.  All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if	!defined(lint) && defined(DOSCCS)
Xstatic char sccsid[] = "@(#)preen.c	8.1.1 (2.11BSD) 1996/1/23";
X#endif /* not lint */
X
X#include <sys/param.h>
X#include <sys/stat.h>
X#include <sys/wait.h>
X#include <fstab.h>
X#include <string.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <ctype.h>
X
Xchar	*rawname(), *unrawname(), *blockcheck();
X
Xstruct part {
X	struct	part *next;		/* forward link of partitions on disk */
X	char	*name;			/* device name */
X	char	*fsname;		/* mounted filesystem name */
X	int	auxdata;		/* auxillary data for application */
X} *badlist, **badnext = &badlist;
X
Xstruct disk {
X	char	*name;			/* disk base name */
X	struct	disk *next;		/* forward link for list of disks */
X	struct	part *part;		/* head of list of partitions on disk */
X	int	pid;			/* If != 0, pid of proc working on */
X} *disks;
X
Xint	nrun, ndisks;
Xchar	hotroot;
X
Xcheckfstab(preen, maxrun, docheck, chkit)
X	int preen, maxrun;
X	int (*docheck)(), (*chkit)();
X{
X	register struct fstab *fsp;
X	register struct disk *dk, *nextdisk;
X	struct part *pt;
X	int ret, pid, retcode, passno, sumstatus;
X	union	wait status;
X	int auxdata;
X	char *name;
X
X	sumstatus = 0;
X	for (passno = 1; passno <= 2; passno++) {
X		if (setfsent() == 0) {
X			warn("Can't open %s\n", _PATH_FSTAB);
X			return (8);
X		}
X		while ((fsp = getfsent()) != 0) {
X			if ((auxdata = (*docheck)(fsp)) == 0)
X				continue;
X			if (preen == 0 || passno == 1 && fsp->fs_passno == 1) {
X				if (name = blockcheck(fsp->fs_spec)) {
X					if (sumstatus = (*chkit)(name,
X					    fsp->fs_file, auxdata, 0))
X						return (sumstatus);
X				} else if (preen)
X					return (8);
X			} else if (passno == 2 && fsp->fs_passno > 1) {
X				if ((name = blockcheck(fsp->fs_spec)) == NULL) {
X					warn("BAD DISK NAME %s\n",fsp->fs_spec);
X					sumstatus |= 8;
X					continue;
X				}
X				addpart(name, fsp->fs_file, auxdata);
X			}
X		}
X		if (preen == 0)
X			return (0);
X	}
X	if (preen) {
X		if (maxrun == 0)
X			maxrun = ndisks;
X		if (maxrun > ndisks)
X			maxrun = ndisks;
X		nextdisk = disks;
X		for (passno = 0; passno < maxrun; ++passno) {
X			while (ret = startdisk(nextdisk, chkit) && nrun > 0)
X				sleep(10);
X			if (ret)
X				return (ret);
X			nextdisk = nextdisk->next;
X		}
X		while ((pid = wait(&status)) != -1) {
X			for (dk = disks; dk; dk = dk->next)
X				if (dk->pid == pid)
X					break;
X			if (dk == 0) {
X				warn("Unknown pid %d\n", pid);
X				continue;
X			}
X			if (WIFEXITED(status))
X				retcode = WEXITSTATUS(status);
X			else
X				retcode = 0;
X			if (WIFSIGNALED(status)) {
X				warn("%s (%s): EXITED WITH SIGNAL %d\n",
X					dk->part->name, dk->part->fsname,
X					status.w_termsig);
X				retcode = 8;
X			}
X			if (retcode != 0) {
X				sumstatus |= retcode;
X				*badnext = dk->part;
X				badnext = &dk->part->next;
X				dk->part = dk->part->next;
X				*badnext = NULL;
X			} else
X				dk->part = dk->part->next;
X			dk->pid = 0;
X			nrun--;
X			if (dk->part == NULL)
X				ndisks--;
X
X			if (nextdisk == NULL) {
X				if (dk->part) {
X					while (ret = startdisk(dk, chkit) &&
X					    nrun > 0)
X						sleep(10);
X					if (ret)
X						return (ret);
X				}
X			} else if (nrun < maxrun && nrun < ndisks) {
X				for ( ;; ) {
X					if ((nextdisk = nextdisk->next) == NULL)
X						nextdisk = disks;
X					if (nextdisk->part != NULL &&
X					    nextdisk->pid == 0)
X						break;
X				}
X				while (ret = startdisk(nextdisk, chkit) &&
X				    nrun > 0)
X					sleep(10);
X				if (ret)
X					return (ret);
X			}
X		}
X	}
X	(void)endfsent();
X	if (badlist) {
X		warn("FOLLOWING FILE SYSTEM%s HAD AN %s\n\t",
X			badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:");
X		for (pt = badlist; pt; pt = pt->next)
X			warn("%s (%s)%s", pt->name, pt->fsname,
X			    pt->next ? ", " : "\n");
X	}
X	return(sumstatus);
X}
X
Xstruct disk *
Xfinddisk(name)
X	char *name;
X{
X	register struct disk *dk, **dkp;
X	register char *p;
X	size_t len;
X
X	for (p = name + strlen(name) - 1; p >= name; --p)
X		if (isdigit(*p)) {
X			len = p - name + 1;
X			break;
X		}
X	if (p < name)
X		len = strlen(name);
X
X	for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) {
X		if (strncmp(dk->name, name, len) == 0 &&
X		    dk->name[len] == 0)
X			return (dk);
X	}
X	if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL)
X		nomem();
X	dk = *dkp;
X	if ((dk->name = (char *)malloc(len + 1)) == NULL)
X		nomem();
X	(void)strncpy(dk->name, name, len);
X	dk->name[len] = '\0';
X	dk->part = NULL;
X	dk->next = NULL;
X	dk->pid = 0;
X	ndisks++;
X	return (dk);
X}
X
Xaddpart(name, fsname, auxdata)
X	char *name, *fsname;
X	int auxdata;
X{
X	struct disk *dk = finddisk(name);
X	register struct part *pt, **ppt = &dk->part;
X
X	for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next)
X		if (strcmp(pt->name, name) == 0) {
X			warn("%s in fstab more than once!\n", name);
X			return;
X		}
X	if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL)
X		nomem();
X	pt = *ppt;
X	if ((pt->name = (char *)malloc(strlen(name) + 1)) == NULL)
X		nomem();
X	(void)strcpy(pt->name, name);
X	if ((pt->fsname = (char *)malloc(strlen(fsname) + 1)) == NULL)
X		nomem();
X	(void)strcpy(pt->fsname, fsname);
X	pt->next = NULL;
X	pt->auxdata = auxdata;
X}
X
Xstartdisk(dk, checkit)
X	register struct disk *dk;
X	int (*checkit)();
X{
X	register struct part *pt = dk->part;
X
X	dk->pid = fork();
X	if (dk->pid < 0) {
X		perror("fork");
X		return (8);
X	}
X	if (dk->pid == 0)
X		exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1));
X	nrun++;
X	return (0);
X}
X
Xchar *
Xblockcheck(name)
X	char *name;
X{
X	struct stat stslash, stblock, stchar;
X	char *raw;
X	int retried = 0;
X
X	hotroot = 0;
X	if (stat("/", &stslash) < 0) {
X		perror("/");
X		warn("Can't stat root\n");
X		return (0);
X	}
Xretry:
X	if (stat(name, &stblock) < 0) {
X		perror(name);
X		warn("Can't stat %s\n", name);
X		return (0);
X	}
X	if ((stblock.st_mode & S_IFMT) == S_IFBLK) {
X		if (stslash.st_dev == stblock.st_rdev)
X			hotroot++;
X		raw = rawname(name);
X		if (stat(raw, &stchar) < 0) {
X			perror(raw);
X			warn("Can't stat %s\n", raw);
X			return (name);
X		}
X		if ((stchar.st_mode & S_IFMT) == S_IFCHR) {
X			return (raw);
X		} else {
X			warn("%s not a character device\n", raw);
X			return (name);
X		}
X	} else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) {
X		name = unrawname(name);
X		retried++;
X		goto retry;
X	}
X	warn("Can't make sense of name %s\n", name);
X	return (0);
X}
X
Xchar *
Xunrawname(name)
X	char *name;
X{
X	char *dp;
X	struct stat stb;
X
X	if ((dp = rindex(name, '/')) == 0)
X		return (name);
X	if (stat(name, &stb) < 0)
X		return (name);
X	if ((stb.st_mode & S_IFMT) != S_IFCHR)
X		return (name);
X	if (dp[1] != 'r')
X		return (name);
X	(void)strcpy(&dp[1], &dp[2]);
X	return (name);
X}
X
Xchar *
Xrawname(name)
X	char *name;
X{
X	static char rawbuf[32];
X	char *dp;
X
X	if ((dp = rindex(name, '/')) == 0)
X		return (0);
X	*dp = 0;
X	(void)strcpy(rawbuf, name);
X	*dp = '/';
X	(void)strcat(rawbuf, "/r");
X	(void)strcat(rawbuf, &dp[1]);
X	return (rawbuf);
X}
X
Xnomem()
X	{
X	err(8, "out of memory");
X	/* NOTREACHED */
X	}
SHAR_EOF
chmod 644 'preen.c'
fi
if test -f 'quotacheck.c'
then
	echo shar: "will not over-write existing file 'quotacheck.c'"
else
sed 's/^X//' << \SHAR_EOF > 'quotacheck.c'
X/*
X * Copyright (c) 1980, 1990, 1993
X *	The Regents of the University of California.  All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Robert Elz at The University of Melbourne.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if	!defined(lint) && defined(DOSCCS)
Xstatic char copyright[] =
X"@(#) Copyright (c) 1980, 1990, 1993\n\
X	The Regents of the University of California.  All rights reserved.\n";
X
Xstatic char sccsid[] = "@(#)quotacheck.c	8.3.1 (2.11BSD) 1996/1/23";
X#endif /* not lint */
X
X/*
X * Fix up / report on disk quotas & usage
X */
X#include <sys/param.h>
X#include <sys/stat.h>
X
X#include <sys/inode.h>
X#include <sys/quota.h>
X#include <sys/fs.h>
X
X#include <fcntl.h>
X#include <fstab.h>
X#include <pwd.h>
X#include <grp.h>
X#include <errno.h>
X#include <unistd.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X
Xchar *qfname = QUOTAFILENAME;
Xchar *quotagroup = QUOTAGROUP;
X
Xunion {
X	struct	fs	sblk;
X	char	dummy[MAXBSIZE];
X} un;
X#define	sblock	un.sblk
Xino_t maxino;
X
Xstruct quotaname {
X	char	flags;
X	char	usrqfname[MAXPATHLEN + 1];
X};
X#define	HASUSR	1
X
Xstruct fileusage {
X	struct	fileusage *fu_next;
X	ino_t	fu_curinodes;
X	u_long	fu_curblocks;
X	uid_t	fu_id;
X	char	fu_name[1];
X	/* actually bigger */
X};
X#define FUHASH 256	/* must be power of two */
Xstruct fileusage *fuhead[FUHASH];
X
Xint	aflag;			/* all file systems */
Xint	vflag;			/* verbose */
Xint	fi;			/* open disk file descriptor */
Xuid_t	highid;			/* highest addid()'ed identifier */
X
Xstruct fileusage *addid();
Xchar	*blockcheck();
Xvoid	bread();
Xint	chkquota();
Xvoid	freeinodebuf();
Xstruct	dinode *getnextinode();
Xgid_t	 getquotagid();
Xint	 hasquota();
Xstruct fileusage *lookup();
Xvoid	*needchk();
Xint	 oneof();
Xvoid	 resetinodebuf();
Xint	 update();
Xvoid	 usage();
X
Xint
Xmain(argc, argv)
X	int argc;
X	char *argv[];
X{
X	register struct fstab *fs;
X	register struct passwd *pw;
X	struct quotaname *auxdata;
X	int i, argnum, maxrun, errs, ch;
X	long done = 0;
X	char *name;
X
X	errs = maxrun = 0;
X	while ((ch = getopt(argc, argv, "avl:")) != EOF) {
X		switch(ch) {
X		case 'a':
X			aflag++;
X			break;
X		case 'v':
X			vflag++;
X			break;
X		case 'l':
X			maxrun = atoi(optarg);
X			break;
X		default:
X			usage();
X		}
X	}
X	argc -= optind;
X	argv += optind;
X	if ((argc == 0 && !aflag) || (argc > 0 && aflag))
X		usage();
X
X	setpwent();
X	while ((pw = getpwent()) != 0)
X		(void) addid(pw->pw_uid, pw->pw_name);
X	endpwent();
X
X	if (aflag)
X		exit(checkfstab(1, maxrun, needchk, chkquota));
X	if (setfsent() == 0)
X		err(1, "can't open %s", FSTAB);
X	while ((fs = getfsent()) != NULL) {
X		if (((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
X		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) &&
X		    (auxdata = (struct quotaname *)needchk(fs)) &&
X		    (name = blockcheck(fs->fs_spec))) {
X			done |= 1 << argnum;
X			errs += chkquota(name, fs->fs_file, auxdata);
X		}
X	}
X	endfsent();
X	for (i = 0; i < argc; i++)
X		if ((done & (1 << i)) == 0)
X			warn("%s not found in %s", argv[i], FSTAB);
X	exit(errs);
X}
X
Xvoid
Xusage()
X{
X	(void)err(1, "usage:\t%s\n\t%s\n",
X		"quotacheck -a [-v] [-l num]",
X		"quotacheck [-v] filesys ...");
X/* NOTREACHED */
X}
X
Xvoid *
Xneedchk(fs)
X	register struct fstab *fs;
X{
X	register struct quotaname *qnp;
X	char *qfnp;
X
X	if (strcmp(fs->fs_vfstype, "ufs") ||
X	    (strcmp(fs->fs_type, FSTAB_RW) && strcmp(fs->fs_type, FSTAB_RQ)))
X		return ((void *)NULL);
X	if ((qnp = (struct quotaname *)malloc(sizeof(*qnp))) == NULL)
X		nomem();
X	qnp->flags = 0;
X	if (hasquota(fs, &qfnp)) {
X		strcpy(qnp->usrqfname, qfnp);
X		qnp->flags |= HASUSR;
X	}
X	if (qnp->flags)
X		return ((void *)qnp);
X	free(qnp);
X	return ((void *)NULL);
X}
X
X/*
X * Scan the specified filesystem to check quota(s) present on it.
X */
Xint
Xchkquota(fsname, mntpt, qnp)
X	char *fsname, *mntpt;
X	register struct quotaname *qnp;
X{
X	register struct fileusage *fup;
X	register struct dinode *dp;
X	int mode, errs = 0;
X	ino_t ino;
X
X	if ((fi = open(fsname, O_RDONLY, 0)) < 0) {
X		perror(fsname);
X		return (1);
X	}
X	if (vflag)
X		(void)printf("*** Checking quotas for %s (%s)\n", 
X			fsname, mntpt);
X	sync();
X	bread(SBLOCK, (char *)&sblock, SBSIZE);
X	maxino = (sblock.fs_isize - 2) * INOPB;
X	resetinodebuf();
X	for (ino = ROOTINO; ino < maxino; ino++) {
X		if ((dp = getnextinode(ino)) == NULL)
X			continue;
X		if ((mode = dp->di_mode & IFMT) == 0)
X			continue;
X		if (qnp->flags & HASUSR) {
X			fup = addid(dp->di_uid, (char *)0);
X			fup->fu_curinodes++;
X			if (mode == IFREG || mode == IFDIR || mode == IFLNK)
X				fup->fu_curblocks += dp->di_size;
X		}
X	}
X	freeinodebuf();
X	if (qnp->flags & HASUSR)
X		errs += update(fsname, mntpt, qnp->usrqfname);
X	close(fi);
X	return (errs);
X}
X
X/*
X * Update a specified quota file.
X */
Xint
Xupdate(fsdev, fsname, quotafile)
X	char *fsdev, *fsname, *quotafile;
X{
X	register struct fileusage *fup;
X	register FILE *qfi, *qfo;
X	uid_t id, lastid;
X	struct dqblk dqbuf;
X	struct stat  statb;
X	struct dqusage dqu;
X	dev_t  quotadev;
X	static int warned = 0;
X	static struct dqblk zerodqbuf;
X	static struct fileusage zerofileusage;
X
X	if ((qfo = fopen(quotafile, "r+")) == NULL) {
X		if (errno == ENOENT)
X			qfo = fopen(quotafile, "w+");
X		if (qfo) {
X			(void) warn("creating quota file %s", quotafile);
X			(void) fchown(fileno(qfo), getuid(), getquotagid());
X			(void) fchmod(fileno(qfo), 0640);
X		} else {
X			(void) warn("%s: %s", quotafile, strerror(errno));
X			return (1);
X		}
X	}
X	if ((qfi = fopen(quotafile, "r")) == NULL) {
X		(void) warn("%s: %s", quotafile, strerror(errno));
X		(void) fclose(qfo);
X		return (1);
X	}
X/*
X * We check that the quota file resides in the filesystem being checked.  This
X * restriction is imposed by the kernel for now.
X*/
X	fstat(fileno(qfi), &statb);
X	quotadev = statb.st_dev;
X	if (stat(unrawname(fsdev), &statb) < 0) {
X		warn("Can't stat %s", fsname);
X		fclose(qfi);
X		fclose(qfo);
X		return(1);
X	}
X	if (quotadev != statb.st_rdev)  {
X		warn("%s dev (0x%x) mismatch %s dev (0x%x)", quotafile, 
X			quotadev, fsname, statb.st_rdev);
X		fclose(qfi);
X		fclose(qfo);
X		return(1);
X	}
X	if (quota(Q_SYNC, 0, quotadev, 0) < 0 &&
X	    errno == EOPNOTSUPP && !warned && vflag) {
X		warned++;
X		(void)printf("*** Warning: %s\n",
X		    "Quotas are not compiled into this kernel");
X	}
X	for (lastid = highid, id = 0; id <= lastid; id++) {
X		if (fread((char *)&dqbuf, sizeof(struct dqblk), 1, qfi) == 0)
X			dqbuf = zerodqbuf;
X		if ((fup = lookup(id)) == 0)
X			fup = &zerofileusage;
X		if (dqbuf.dqb_curinodes == fup->fu_curinodes &&
X		    dqbuf.dqb_curblocks == fup->fu_curblocks) {
X			fup->fu_curinodes = 0;
X			fup->fu_curblocks = 0;
X			fseek(qfo, (long)sizeof(struct dqblk), 1);
X			continue;
X		}
X		if (vflag) {
X			if (aflag)
X				printf("%s: ", fsname);
X			printf("%-8s fixed:", fup->fu_name);
X			if (dqbuf.dqb_curinodes != fup->fu_curinodes)
X				(void)printf("\tinodes %u -> %u",
X					dqbuf.dqb_curinodes, fup->fu_curinodes);
X			if (dqbuf.dqb_curblocks != fup->fu_curblocks)
X				(void)printf("\tbytes %ld -> %ld",
X					dqbuf.dqb_curblocks, fup->fu_curblocks);
X			(void)printf("\n");
X		}
X		dqbuf.dqb_curinodes = fup->fu_curinodes;
X		dqbuf.dqb_curblocks = fup->fu_curblocks;
X		fwrite((char *)&dqbuf, sizeof(struct dqblk), 1, qfo);
X/*
X * Need to convert from bytes to blocks for system call interface.
X */
X		dqu.du_curblocks = btodb(fup->fu_curblocks);
X		dqu.du_curinodes = fup->fu_curinodes;
X		(void) quota(Q_SETDUSE, id, quotadev, &dqu);
X		fup->fu_curinodes = 0;
X		fup->fu_curblocks = 0;
X	}
X	fclose(qfi);
X	fflush(qfo);
X	ftruncate(fileno(qfo), (off_t)(highid + 1) * sizeof(struct dqblk));
X	fclose(qfo);
X	return (0);
X}
X
X/*
X * Check to see if target appears in list of size cnt.
X */
Xint
Xoneof(target, list, cnt)
X	register char *target, *list[];
X	int cnt;
X{
X	register int i;
X
X	for (i = 0; i < cnt; i++)
X		if (strcmp(target, list[i]) == 0)
X			return (i);
X	return (-1);
X}
X
X/*
X * Determine the group identifier for quota files.
X */
Xgid_t
Xgetquotagid()
X{
X	struct group *gr;
X
X	if (gr = getgrnam(quotagroup))
X		return (gr->gr_gid);
X	return (-1);
X}
X
X/*
X * Check to see if a particular quota is to be enabled.
X */
Xhasquota(fs, qfnamep)
X	register struct fstab *fs;
X	char **qfnamep;
X{
X	register char *opt;
X	char *cp;
X	static char initname, usrname[100];
X	static char buf[BUFSIZ];
X
X	if (!initname) {
X		strcpy(usrname, qfname);
X		initname = 1;
X	}
X	strcpy(buf, fs->fs_mntops);
X	for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
X		if (cp = index(opt, '='))
X			*cp++ = '\0';
X		if (strcmp(opt, usrname) == 0)
X			break;
X		if (strcmp(opt, FSTAB_RQ) == 0)	/* XXX compatibility */
X			break;
X	}
X	if (!opt)
X		return (0);
X	if (cp) {
X		*qfnamep = cp;
X		return (1);
X	}
X	(void) sprintf(buf, "%s/%s", fs->fs_file, qfname);
X	*qfnamep = buf;
X	return (1);
X}
X
X/*
X * Routines to manage the file usage table.
X *
X * Lookup an id.
X */
Xstruct fileusage *
Xlookup(id)
X	uid_t id;
X{
X	register struct fileusage *fup;
X
X	for (fup = fuhead[id & (FUHASH-1)]; fup != 0; fup = fup->fu_next)
X		if (fup->fu_id == id)
X			return (fup);
X	return (NULL);
X}
X
X/*
X * Add a new file usage id if it does not already exist.
X */
Xstruct fileusage *
Xaddid(id, name)
X	uid_t id;
X	char *name;
X{
X	register struct fileusage *fup, **fhp;
X	int len;
X
X	if (fup = lookup(id))
X		return (fup);
X	if (name)
X		len = strlen(name);
X	else
X		len = 10;
X	if ((fup = (struct fileusage *)calloc(1, sizeof(*fup) + len)) == NULL)
X		err("%s", strerror(errno));
X	fhp = &fuhead[id & (FUHASH - 1)];
X	fup->fu_next = *fhp;
X	*fhp = fup;
X	fup->fu_id = id;
X	if (id > highid)
X		highid = id;
X	if (name)
X		bcopy(name, fup->fu_name, len + 1);
X	else
X		(void)sprintf(fup->fu_name, "%u", id);
X	return (fup);
X}
X
X/*
X * Special purpose version of ginode used to optimize pass
X * over all the inodes in numerical order.
X */
Xino_t nextino;
Xlong lastinum;
Xint inobufsize;
Xstruct dinode *inodebuf;
X#define	INOBUFSIZE	128	/* number of inodes to read at a time */
X
Xstruct dinode *
Xgetnextinode(inumber)
X	ino_t inumber;
X{
X	daddr_t dblk;
X	static struct dinode *dp;
X
X	if (inumber != nextino++ || inumber >= maxino)
X		err(1, "bad inode number %d to nextinode", inumber);
X	if (inumber > lastinum) {
X		dblk = itod(inumber);
X		lastinum += INOBUFSIZE;
X		bread(dblk, (char *)inodebuf, inobufsize);
X		dp = inodebuf;
X	}
X	return (dp++);
X}
X
X/*
X * Prepare to scan a set of inodes.
X */
Xvoid
Xresetinodebuf()
X{
X
X	nextino = 1;
X	lastinum = 0;
X	inobufsize = INOBUFSIZE * sizeof (struct dinode);
X	if (inodebuf == NULL && 
X		(inodebuf = (struct dinode *)malloc(inobufsize)) == NULL)
X		nomem();
X	while (nextino < ROOTINO)
X		getnextinode(nextino);
X}
X
X/*
X * Free up data structures used to scan inodes.
X */
Xvoid
Xfreeinodebuf()
X{
X
X	if (inodebuf != NULL)
X		free(inodebuf);
X	inodebuf = NULL;
X}
X
X/*
X * Read specified disk blocks.
X */
Xvoid
Xbread(bno, buf, cnt)
X	daddr_t bno;
X	char *buf;
X	int cnt;
X{
X
X	if (lseek(fi, (off_t)bno * DEV_BSIZE, 0) == -1 ||
X	    read(fi, buf, cnt) != cnt)
X		err(1, "block %ld", bno);
X}
SHAR_EOF
chmod 644 'quotacheck.c'
fi
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X#
X# Public Domain.  1996/1/23 - Steven Schultz
X#
X#	@(#)Makefile	1.0 (2.11BSD GTE) 1996/1/23
X#
XCFLAGS=	 -O
XSEPFLAG= -i
XSRCS=	quotacheck.c preen.c
XOBJS=	quotacheck.o preen.o
XMAN=	quotacheck.0
XMANSRC=	quotacheck.8
X
Xall: quotacheck quotacheck.0
X
Xquotacheck: ${OBJS}
X	${CC} ${CFLAGS} ${SEPFLAG} -o $@ ${OBJS}
X
Xquotacheck.0: ${MANSRC}
X	/usr/man/manroff ${MANSRC} > ${MAN}
X
Xclean:
X	rm -f ${OBJS} ${MAN} quotacheck tags 
X
Xdepend: ${SRCS}
X	mkdep ${CFLAGS} ${SRCS}
X
Xinstall: all
X	install -c -o bin -g bin -m 444 ${MAN} ${DESTDIR}/usr/man/cat8
X	install -s -o root -g bin -m 755 quotacheck ${DESTDIR}/etc/quotacheck
X
Xlint: ${SRCS}
X	lint -hax ${SRCS}
X
Xtags: ${SRCS}
X	ctags ${SRCS}
X# DO NOT DELETE THIS LINE -- mkdep uses it.
X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
SHAR_EOF
chmod 644 'Makefile'
fi
if test -f 'quotacheck.8'
then
	echo shar: "will not over-write existing file 'quotacheck.8'"
else
sed 's/^X//' << \SHAR_EOF > 'quotacheck.8'
X.\" Copyright (c) 1983, 1990, 1991, 1993
X.\"	The Regents of the University of California.  All rights reserved.
X.\"
X.\" This code is derived from software contributed to Berkeley by
X.\" Robert Elz at The University of Melbourne.
X.\"
X.\" Redistribution and use in source and binary forms, with or without
X.\" modification, are permitted provided that the following conditions
X.\" are met:
X.\" 1. Redistributions of source code must retain the above copyright
X.\"    notice, this list of conditions and the following disclaimer.
X.\" 2. Redistributions in binary form must reproduce the above copyright
X.\"    notice, this list of conditions and the following disclaimer in the
X.\"    documentation and/or other materials provided with the distribution.
X.\" 3. All advertising materials mentioning features or use of this software
X.\"    must display the following acknowledgement:
X.\"	This product includes software developed by the University of
X.\"	California, Berkeley and its contributors.
X.\" 4. Neither the name of the University nor the names of its contributors
X.\"    may be used to endorse or promote products derived from this software
X.\"    without specific prior written permission.
X.\"
X.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X.\" SUCH DAMAGE.
X.\"
X.\"     @(#)quotacheck.8	8.1.1 (2.11BSD) 1996/1/24
X.\"
X.TH QUOTACHECK 8 "January 24, 1996"
X.UC 5
X.SH NAME
X\fBquotacheck\fP \- filesystem quota consistency checker
X.SH SYNOPSIS
X.B quotacheck
X[ \fB\-v\fP ]
X.I filesystem ...
X.br
X.B quotacheck
X[ \fB\-v\fP ]
X\fB\-a\fP
X.SH DESCRIPTION
X.B Quotacheck
Xexamines each filesystem,
Xbuilds a table of current disk usage,
Xand compares this table against that recorded
Xin the disk quota file for the filesystem.
XIf any inconsistencies are detected, both the
Xquota file and the current system copy of the
Xincorrect quotas are updated (the latter only
Xoccurs if an active filesystem is checked).
X.PP
XAvailable options:
X.sp
X.TP 15
X\fB\-a\fP
XIf the
X\fB\-a\fP
Xflag is supplied in place of any filesystem names,
X\fBquotacheck\fP
Xwill check all the filesystems indicated in
X\fI/etc/fstab\fP
Xto be read-write with disk quotas.
X.TP 15
X\fB\-v\fP
X\fBquotacheck\fP
Xreports discrepancies between the
Xcalculated and recorded disk quotas.
X.PP
XParallel passes are run on the filesystems required,
Xusing the pass numbers in
X.I /etc/fstab
Xin an identical fashion to
Xfsck(8).
X.PP
XNormally
X.B quotacheck
Xoperates silently.
X.PP
X.B Quotacheck
Xexpects each filesystem to be checked to have a
Xquota files named
X.I quotas
Xlocated at the root of the associated file system.
XThese defaults may be overridden in
X.IR /etc/fstab .
XIf a file is not present, 
X.B quotacheck
Xwill create it.
X.PP
X.B Quotacheck
Xis normally run at boot time from the
X.I /etc/rc.local
Xfile, see
Xrc(8),
Xbefore enabling disk quotas with
Xquotaon(8).
X.PP
X.B Quotacheck
Xaccesses the raw device in calculating the actual
Xdisk usage for each user.
XThus, the filesystems
Xchecked should be quiescent while
X.B quotacheck
Xis running.
X.SH FILES
X.TP 15
X.I quotas
Xat the filesystem root
X.TP 15
X.I /etc/fstab
Xdefault filesystems
X.SH BUGS
XThe \fIquotas\fP file may be named arbitrarily but \fBmust\fP reside in
Xthe filesystem for which it contains quota information.
X.B Quotacheck
Xwill give the error:
X.sp
X.in +0.5i
X.I %s dev (0x%x) mismatch %s (0x%x)
X.sp
X.in -0.5i
Xif the \fIquotas\fP file is not in the filesystem being checked.  This
Xrestriction is enforced by the kernel but may be lifted in the future.
X.SH SEE ALSO
Xquota(1),
Xquotactl(2),
Xfstab(5),
Xedquota(8),
Xfsck(8),
Xquotaon(8),
Xrepquota(8)
X.SH HISTORY
XThe
X.B quotacheck
Xcommand appeared in 4.2BSD.
SHAR_EOF
chmod 644 'quotacheck.8'
fi
chmod 755 .
cd ..
if test -f '/usr/src/etc/edquota.c'
then
	echo shar: "will not over-write existing file '/usr/src/etc/edquota.c'"
else
sed 's/^X//' << \SHAR_EOF > '/usr/src/etc/edquota.c'
X/*
X * Copyright (c) 1980, 1990, 1993
X *	The Regents of the University of California.  All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Robert Elz at The University of Melbourne.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if	!defined(lint) && defined(DOSCCS)
Xstatic char copyright[] =
X"@(#) Copyright (c) 1980, 1990, 1993\n\
X	The Regents of the University of California.  All rights reserved.\n";
X
Xstatic char sccsid[] = "@(#)edquota.c	8.1.1 (2.11BSD) 1996/1/21";
X#endif /* not lint */
X
X/*
X * Disk quota editor.
X */
X#include <sys/param.h>
X#include <sys/stat.h>
X#include <sys/file.h>
X#include <sys/wait.h>
X#include <sys/quota.h>
X#include <errno.h>
X#include <fstab.h>
X#include <pwd.h>
X#include <ctype.h>
X#include <stdio.h>
X#include <string.h>
X#include <unistd.h>
X#include <paths.h>
X
Xchar *qfname = "quotas";
Xchar tmpfil[] = "/tmp/EdP.aXXXXXX";
X
Xstruct quotause {
X	struct	quotause *next;
X	short	flags;
X	struct	dqblk dqblk;
X	char	fsname[MAXPATHLEN + 1];
X	char	qfname[1];	/* actually longer */
X} *getprivs();
X#define	FOUND	0x01
X
X	uid_t	getentry();
X
Xmain(argc, argv)
X	register char **argv;
X	int argc;
X{
X	register struct quotause *protoprivs, *curprivs;
X	extern char *optarg;
X	extern int optind;
X	uid_t id, protoid;
X	int tmpfd;
X	char *protoname, ch;
X	int pflag = 0;
X
X	if (argc < 2)
X		usage();
X	if (getuid()) {
X		fprintf(stderr, "edquota: permission denied\n");
X		exit(1);
X	}
X	while ((ch = getopt(argc, argv, "p:")) != EOF) {
X		switch(ch) {
X		case 'p':
X			protoname = optarg;
X			pflag++;
X			break;
X		default:
X			usage();
X		}
X	}
X	argc -= optind;
X	argv += optind;
X	if (pflag) {
X		if ((protoid = getentry(protoname)) == -1)
X			exit(1);
X		protoprivs = getprivs(protoid);
X		while (argc-- > 0) {
X			if ((id = getentry(*argv++)) < 0)
X				continue;
X			putprivs(id, protoprivs);
X		}
X		exit(0);
X	}
X	tmpfd = mkstemp(tmpfil);
X	fchown(tmpfd, getuid(), getgid());
X	for ( ; argc > 0; argc--, argv++) {
X		if ((id = getentry(*argv)) == -1)
X			continue;
X		curprivs = getprivs(id);
X		if (writeprivs(curprivs, tmpfd, *argv) == 0)
X			continue;
X		if (editit(tmpfil) && readprivs(curprivs, tmpfd))
X			putprivs(id, curprivs);
X		freeprivs(curprivs);
X	}
X	close(tmpfd);
X	unlink(tmpfil);
X	exit(0);
X}
X
Xusage()
X{
X	fputs("Usage: edquota [-p username] username ...\n", stderr);
X	exit(1);
X}
X
X/*
X * This routine converts a name for a particular quota type to
X * an identifier. This routine must agree with the kernel routine
X * getinoquota as to the interpretation of quota types.
X */
Xuid_t
Xgetentry(name)
X	char *name;
X{
X	struct passwd *pw;
X
X	if (alldigits(name))
X		return (atoi(name));
X	if (pw = getpwnam(name))
X		return (pw->pw_uid);
X	fprintf(stderr, "%s: no such user\n", name);
X	sleep(1);
X	return (-1);
X}
X
X/*
X * Collect the requested quota information.
X */
Xstruct quotause *
Xgetprivs(id)
X	u_int id;
X{
X	register struct fstab *fs;
X	register struct quotause *qup, *quptail;
X	struct	dqblk *dq;
X	struct quotause *quphead;
X	struct	stat	statb;
X	dev_t	fsdev;
X	int qupsize, fd;
X	char *qfpathname;
X	static int warned = 0;
X	extern int errno;
X
X	setfsent();
X	quphead = (struct quotause *)0;
X	while (fs = getfsent()) {
X		if (stat(fs->fs_spec, &statb) < 0)
X			continue;
X		if (strcmp(fs->fs_vfstype, "ufs"))
X			continue;
X		if (!hasquota(fs, &qfpathname))
X			continue;
X/*
X * See the comments in quota.c about the check below.
X*/
X		fsdev = statb.st_rdev;
X		if (stat(qfpathname, &statb) < 0 || statb.st_dev != fsdev)
X			continue;
X		qupsize = sizeof(*qup) + strlen(qfpathname);
X		if ((qup = (struct quotause *)malloc(qupsize)) == NULL) {
X			fprintf(stderr, "edquota: out of memory\n");
X			exit(2);
X		}
X		if (quota(Q_GETDLIM, id, fsdev, &qup->dqblk) != 0) {
X	    		if (errno == EOPNOTSUPP && !warned) {
X				warned++;
X				fprintf(stderr, "Warning: %s\n",
X				    "Quotas are not compiled into this kernel");
X				sleep(3);
X			}
X			if ((fd = open(qfpathname, O_RDONLY)) < 0) {
X				fd = open(qfpathname, O_RDWR|O_CREAT, 0640);
X				if (fd < 0 && errno != ENOENT) {
X					perror(qfpathname);
X					free(qup);
X					continue;
X				}
X				fprintf(stderr, "Creating quota file %s\n",
X				    qfpathname);
X				sleep(3);
X				(void) fchown(fd, getuid(), -1);
X				(void) fchmod(fd, 0640);
X			}
X			lseek(fd, (long)(id * sizeof(struct dqblk)), L_SET);
X			switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) {
X			case 0:			/* EOF */
X				/*
X				 * Convert implicit 0 quota (EOF)
X				 * into an explicit one (zero'ed dqblk)
X				 */
X				bzero((caddr_t)&qup->dqblk,
X				    sizeof(struct dqblk));
X				break;
X
X			case sizeof(struct dqblk):	/* OK */
X/*
X * We have to convert from bytes to disc blocks because the quotas file 
X * entries use bytes like the kernel does.
X*/
X				dq = &qup->dqblk;
X				dq->dqb_curblocks = btodb(dq->dqb_curblocks);
X				dq->dqb_bhardlimit = btodb(dq->dqb_bhardlimit);
X				dq->dqb_bsoftlimit = btodb(dq->dqb_bsoftlimit);
X				break;
X
X			default:		/* ERROR */
X				fprintf(stderr, "edquota: read error in ");
X				perror(qfpathname);
X				close(fd);
X				free(qup);
X				continue;
X			}
X			close(fd);
X		}
X		strcpy(qup->qfname, qfpathname);
X		strcpy(qup->fsname, fs->fs_file);
X		if (quphead == NULL)
X			quphead = qup;
X		else
X			quptail->next = qup;
X		quptail = qup;
X		qup->next = 0;
X	}
X	endfsent();
X	return (quphead);
X}
X
X/*
X * Store the requested quota information.
X */
Xputprivs(id, quplist)
X	uid_t id;
X	struct quotause *quplist;
X{
X	register struct quotause *qup;
X	struct stat sb;
X	int fd;
X	register struct dqblk *dq;
X
X	for (qup = quplist; qup; qup = qup->next) {
X		if (stat(qup->qfname, &sb) < 0) {
X			fprintf(stderr,"edquota: can't stat %s\n",qup->qfname);
X			continue;
X		}
X
X		if (quota(Q_SETDLIM, id, sb.st_dev, &qup->dqblk) == 0)
X			continue;
X/*
X * Have to convert from blocks to bytes now to be compatible with the kernel
X*/
X		dq = &qup->dqblk;
X		dq->dqb_bhardlimit = dbtob(dq->dqb_bhardlimit);
X		dq->dqb_bsoftlimit = dbtob(dq->dqb_bsoftlimit);
X		dq->dqb_curblocks = dbtob(dq->dqb_curblocks);
X
X		if ((fd = open(qup->qfname, O_WRONLY)) < 0) {
X			perror(qup->qfname);
X		} else {
X			lseek(fd, (long)id * (long)sizeof (struct dqblk), 0);
X			if (write(fd, &qup->dqblk, sizeof (struct dqblk)) !=
X			    sizeof (struct dqblk)) {
X				fprintf(stderr, "edquota: ");
X				perror(qup->qfname);
X			}
X			close(fd);
X		}
X	}
X}
X
X/*
X * Take a list of priviledges and get it edited.
X */
Xeditit(tmpfile)
X	char *tmpfile;
X{
X	long omask;
X	pid_t pid;
X	union wait stat;
X	extern char *getenv();
X
X	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
X top:
X	if ((pid = vfork()) < 0) {
X		extern int errno;
X
X		if (errno == EPROCLIM) {
X			fprintf(stderr, "You have too many processes\n");
X			return(0);
X		}
X		if (errno == EAGAIN) {
X			sleep(1);
X			goto top;
X		}
X		perror("fork");
X		return (0);
X	}
X	if (pid == 0) {
X		register char *ed;
X
X		sigsetmask(omask);
X		setgid(getgid());
X		setuid(getuid());
X		if ((ed = getenv("EDITOR")) == (char *)0)
X			ed = _PATH_VI;
X		execlp(ed, ed, tmpfile, 0);
X		perror(ed);
X		exit(1);
X	}
X	waitpid(pid, &stat, 0);
X	sigsetmask(omask);
X	if (!WIFEXITED(stat) || WEXITSTATUS(stat) != 0)
X		return (0);
X	return (1);
X}
X
X/*
X * Convert a quotause list to an ASCII file.
X */
Xwriteprivs(quplist, outfd, name)
X	struct quotause *quplist;
X	int outfd;
X	char *name;
X{
X	register struct quotause *qup;
X	register FILE *fd;
X
X	ftruncate(outfd, (off_t)0);
X	lseek(outfd, (off_t)0, L_SET);
X	if ((fd = fdopen(dup(outfd), "w")) == NULL) {
X		fprintf(stderr, "edquota: ");
X		perror(tmpfil);
X		exit(1);
X	}
X	fprintf(fd, "Quotas for %s:\n", name);
X	for (qup = quplist; qup; qup = qup->next) {
X		fprintf(fd, "%s: %s %ld, limits (soft = %ld, hard = %ld)\n",
X		    qup->fsname, "blocks in use:",
X		    qup->dqblk.dqb_curblocks,
X		    qup->dqblk.dqb_bsoftlimit,
X		    qup->dqblk.dqb_bhardlimit);
X		fprintf(fd, "%s %u, limits (soft = %u, hard = %u)\n",
X		    "\tinodes in use:", qup->dqblk.dqb_curinodes,
X		    qup->dqblk.dqb_isoftlimit, qup->dqblk.dqb_ihardlimit);
X	}
X	fclose(fd);
X	return (1);
X}
X
X/*
X * Merge changes to an ASCII file into a quotause list.
X */
Xreadprivs(quplist, infd)
X	struct quotause *quplist;
X	int infd;
X{
X	register struct quotause *qup;
X	FILE *fd;
X	int cnt;
X	register char *cp;
X	struct dqblk dqblk;
X	char *fsp, line1[BUFSIZ], line2[BUFSIZ];
X
X	lseek(infd, (off_t)0, L_SET);
X	fd = fdopen(dup(infd), "r");
X	if (fd == NULL) {
X		fprintf(stderr, "Can't re-read temp file!!\n");
X		return (0);
X	}
X	/*
X	 * Discard title line, then read pairs of lines to process.
X	 */
X	(void) fgets(line1, sizeof (line1), fd);
X	while (fgets(line1, sizeof (line1), fd) != NULL &&
X	       fgets(line2, sizeof (line2), fd) != NULL) {
X		if ((fsp = strtok(line1, " \t:")) == NULL) {
X			fprintf(stderr, "%s: bad format\n", line1);
X			return (0);
X		}
X		if ((cp = strtok((char *)0, "\n")) == NULL) {
X			fprintf(stderr, "%s: %s: bad format\n", fsp,
X			    &fsp[strlen(fsp) + 1]);
X			return (0);
X		}
X		cnt = sscanf(cp,
X		    " blocks in use: %ld, limits (soft = %ld, hard = %ld)",
X		    &dqblk.dqb_curblocks, &dqblk.dqb_bsoftlimit,
X		    &dqblk.dqb_bhardlimit);
X		if (cnt != 3) {
X			fprintf(stderr, "%s:%s: bad format\n", fsp, cp);
X			return (0);
X		}
X		if ((cp = strtok(line2, "\n")) == NULL) {
X			fprintf(stderr, "%s: %s: bad format\n", fsp, line2);
X			return (0);
X		}
X		cnt = sscanf(cp,
X		    "\tinodes in use: %u, limits (soft = %u, hard = %u)",
X		    &dqblk.dqb_curinodes, &dqblk.dqb_isoftlimit,
X		    &dqblk.dqb_ihardlimit);
X		if (cnt != 3) {
X			fprintf(stderr, "%s: %s: bad format\n", fsp, line2);
X			return (0);
X		}
X		for (qup = quplist; qup; qup = qup->next) {
X			if (strcmp(fsp, qup->fsname))
X				continue;
X			qup->dqblk.dqb_bsoftlimit = dqblk.dqb_bsoftlimit;
X			qup->dqblk.dqb_bhardlimit = dqblk.dqb_bhardlimit;
X			qup->dqblk.dqb_isoftlimit = dqblk.dqb_isoftlimit;
X			qup->dqblk.dqb_ihardlimit = dqblk.dqb_ihardlimit;
X			qup->flags |= FOUND;
X			if (dqblk.dqb_curblocks == qup->dqblk.dqb_curblocks &&
X			    dqblk.dqb_curinodes == qup->dqblk.dqb_curinodes)
X				break;
X			fprintf(stderr,
X			    "%s: cannot change current allocation\n", fsp);
X			break;
X		}
X	}
X	fclose(fd);
X	/*
X	 * Disable quotas for any filesystems that have not been found.
X	 */
X	for (qup = quplist; qup; qup = qup->next) {
X		if (qup->flags & FOUND) {
X			qup->flags &= ~FOUND;
X			continue;
X		}
X		qup->dqblk.dqb_bsoftlimit = 0;
X		qup->dqblk.dqb_bhardlimit = 0;
X		qup->dqblk.dqb_isoftlimit = 0;
X		qup->dqblk.dqb_ihardlimit = 0;
X	}
X	return (1);
X}
X
X/*
X * Free a list of quotause structures.
X */
Xfreeprivs(quplist)
X	struct quotause *quplist;
X{
X	register struct quotause *qup, *nextqup;
X
X	for (qup = quplist; qup; qup = nextqup) {
X		nextqup = qup->next;
X		free(qup);
X	}
X}
X
X/*
X * Check whether a string is completely composed of digits.
X */
Xalldigits(s)
X	register char *s;
X{
X	register c;
X
X	c = *s++;
X	do {
X		if (!isdigit(c))
X			return (0);
X	} while (c = *s++);
X	return (1);
X}
X
X/*
X * Check to see if a particular quota is to be enabled.
X */
Xhasquota(fs, qfnamep)
X	register struct fstab *fs;
X	char **qfnamep;
X{
X	register char *opt;
X	char *cp;
X	static char initname, usrname[100];
X	static char buf[BUFSIZ];
X
X	if (!initname) {
X		strcpy(usrname, qfname);
X		initname = 1;
X	}
X	strcpy(buf, fs->fs_mntops);
X	for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
X		if (cp = index(opt, '='))
X			*cp++ = '\0';
X		if (strcmp(opt, usrname) == 0)
X			break;
X		if (strcmp(opt, FSTAB_RQ) == 0)	/* XXX compatibility */
X			break;
X	}
X	if (!opt)
X		return (0);
X	if (cp) {
X		*qfnamep = cp;
X		return (1);
X	}
X	(void) sprintf(buf, "%s/%s", fs->fs_file, qfname);
X	*qfnamep = buf;
X	return (1);
X}
SHAR_EOF
chmod 644 '/usr/src/etc/edquota.c'
fi
if test -f '/usr/src/etc/quotaon.c'
then
	echo shar: "will not over-write existing file '/usr/src/etc/quotaon.c'"
else
sed 's/^X//' << \SHAR_EOF > '/usr/src/etc/quotaon.c'
X/*
X * Copyright (c) 1980, 1990, 1993
X *	The Regents of the University of California.  All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Robert Elz at The University of Melbourne.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if	!defined(lint) && defined(DOSCCS)
Xstatic char copyright[] =
X"@(#) Copyright (c) 1980, 1990, 1993\n\
X	The Regents of the University of California.  All rights reserved.\n";
X
Xstatic char sccsid[] = "@(#)quotaon.c	8.1.1 (2.11BSD) 1996/1/21";
X#endif /* not lint */
X
X/*
X * Turn quota on/off for a filesystem.
X */
X#include <sys/param.h>
X#include <sys/file.h>
X#include <sys/mount.h>
X#include <stdio.h>
X#include <fstab.h>
X#include <string.h>
X#include <stdlib.h>
X
Xchar *qfname = "quotas";
X
Xint	aflag;		/* all file systems */
Xint	vflag;		/* verbose */
X
Xmain(argc, argv)
X	int argc;
X	char **argv;
X{
X	register struct fstab *fs;
X	char ch, *qfnp, *whoami;
X	long done = 0;
X	int i, argnum, offmode = 0, errs = 0;
X
X	whoami = rindex(*argv, '/') + 1;
X	if (whoami == (char *)1)
X		whoami = *argv;
X	if (strcmp(whoami, "quotaoff") == 0)
X		offmode++;
X	else if (strcmp(whoami, "quotaon") != 0) {
X		fprintf(stderr, "Name must be quotaon or quotaoff not %s\n",
X			whoami);
X		exit(1);
X	}
X	while ((ch = getopt(argc, argv, "avug")) != EOF) {
X		switch(ch) {
X		case 'a':
X			aflag++;
X			break;
X		case 'v':
X			vflag++;
X			break;
X		default:
X			usage(whoami);
X		}
X	}
X	argc -= optind;
X	argv += optind;
X	if (argc <= 0 && !aflag)
X		usage(whoami);
X	setfsent();
X	while ((fs = getfsent()) != NULL) {
X		if (strcmp(fs->fs_type, FSTAB_RQ) == 0)  /* XXX compatibility */
X			fs->fs_type = FSTAB_RW;
X		if (strcmp(fs->fs_vfstype, "ufs") ||
X		    strcmp(fs->fs_type, FSTAB_RW))
X			continue;
X		if (aflag) {
X			if (hasquota(fs, &qfnp))
X				errs += quotaonoff(fs, offmode, qfnp);
X			continue;
X		}
X		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
X		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
X			done |= 1 << argnum;
X			if (hasquota(fs, &qfnp))
X				errs += quotaonoff(fs, offmode, qfnp);
X		}
X	}
X	endfsent();
X	for (i = 0; i < argc; i++)
X		if ((done & (1 << i)) == 0)
X			fprintf(stderr, "%s not found in fstab\n",
X				argv[i]);
X	exit(errs);
X}
X
Xusage(whoami)
X	char *whoami;
X{
X
X	fprintf(stderr, "Usage:\n\t%s [-v] -a\n", whoami);
X	fprintf(stderr, "\t%s [-v] filesys ...\n", whoami);
X	exit(1);
X}
X
Xquotaonoff(fs, offmode, qfpathname)
X	register struct fstab *fs;
X	int offmode;
X	char *qfpathname;
X{
X
X	if (strcmp(fs->fs_file, "/") && readonly(fs))
X		return (1);
X	if (offmode) {
X		if (setquota(fs->fs_spec, (char *)NULL) < 0) {
X			fprintf(stderr, "quotaoff: ");
X			perror(fs->fs_spec);
X			return (1);
X		}
X		if (vflag)
X			printf("%s: quotas turned off\n", fs->fs_file);
X		return (0);
X	}
X	if (setquota(fs->fs_spec, qfpathname) < 0) {
X		fprintf(stderr, "quotaon: using %s on", qfpathname);
X		perror(fs->fs_file);
X		return (1);
X	}
X	if (vflag)
X		printf("%s: quotas turned on\n", fs->fs_file);
X	return (0);
X}
X
X/*
X * Check to see if target appears in list of size cnt.
X */
Xoneof(target, list, cnt)
X	register char *target, *list[];
X	int cnt;
X{
X	register int i;
X
X	for (i = 0; i < cnt; i++)
X		if (strcmp(target, list[i]) == 0)
X			return (i);
X	return (-1);
X}
X
X/*
X * Check to see if a particular quota is to be enabled.
X */
Xhasquota(fs, qfnamep)
X	register struct fstab *fs;
X	char **qfnamep;
X{
X	register char *opt;
X	char *cp;
X	static char initname, usrname[100];
X	static char buf[BUFSIZ];
X
X	if (!initname) {
X		strcpy(usrname, qfname);
X		initname = 1;
X	}
X	strcpy(buf, fs->fs_mntops);
X	for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
X		if (cp = index(opt, '='))
X			*cp++ = '\0';
X		if (strcmp(opt, usrname) == 0)
X			break;
X		if (strcmp(opt, FSTAB_RQ) == 0)	/* XXX compatibility */
X			break;
X	}
X	if (!opt)
X		return (0);
X	if (cp) {
X		*qfnamep = cp;
X		return (1);
X	}
X	(void) sprintf(buf, "%s/%s", fs->fs_file, qfname);
X	*qfnamep = buf;
X	return (1);
X}
X
X/*
X * Verify file system is mounted and not readonly.
X */
Xreadonly(fs)
X	register struct fstab *fs;
X{
X	struct statfs fsbuf;
X
X	if (statfs(fs->fs_file, &fsbuf) < 0 ||
X	    strcmp(fsbuf.f_mntonname, fs->fs_file) ||
X	    strcmp(fsbuf.f_mntfromname, fs->fs_spec)) {
X		printf("%s: not mounted\n", fs->fs_file);
X		return (1);
X	}
X	if (fsbuf.f_flags & MNT_RDONLY) {
X		printf("%s: mounted read-only\n", fs->fs_file);
X		return (1);
X	}
X	return (0);
X}
SHAR_EOF
chmod 444 '/usr/src/etc/quotaon.c'
fi
if test -f '/usr/src/etc/repquota.c'
then
	echo shar: "will not over-write existing file '/usr/src/etc/repquota.c'"
else
sed 's/^X//' << \SHAR_EOF > '/usr/src/etc/repquota.c'
X/*
X * Copyright (c) 1980, 1990, 1993
X *	The Regents of the University of California.  All rights reserved.
X *
X * This code is derived from software contributed to Berkeley by
X * Robert Elz at The University of Melbourne.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if	!defined(lint) && defined(DOSCCS)
Xstatic char copyright[] =
X"@(#) Copyright (c) 1980, 1990, 1993\n\
X	The Regents of the University of California.  All rights reserved.\n";
X
Xstatic char sccsid[] = "@(#)repquota.c	8.1 (Berkeley) 6/6/93";
X#endif /* not lint */
X
X/*
X * Quota report
X */
X#include <sys/param.h>
X#include <sys/stat.h>
X#include <sys/quota.h>
X#include <fstab.h>
X#include <pwd.h>
X#include <stdio.h>
X#include <errno.h>
X#include <string.h>
X
Xchar *qfname = QUOTAFILENAME;
X
Xstruct fileusage {
X	struct	fileusage *fu_next;
X	struct	dqblk fu_dqblk;
X	u_int	fu_id;
X	char	fu_name[1];
X	/* actually bigger */
X};
X#define FUHASH 256	/* must be power of two */
Xstruct fileusage *fuhead[FUHASH];
Xstruct fileusage *lookup();
Xstruct fileusage *addid();
Xu_int highid;		/* highest addid()'ed identifier per type */
X
Xint	vflag;			/* verbose */
Xint	aflag;			/* all file systems */
X
Xmain(argc, argv)
X	int argc;
X	char **argv;
X{
X	register struct fstab *fs;
X	register struct passwd *pw;
X	int errs = 0;
X	int i, argnum;
X	long done = 0;
X	extern char *optarg;
X	extern int optind;
X	char ch, *qfnp;
X
X	while ((ch = getopt(argc, argv, "aguv")) != EOF) {
X		switch(ch) {
X		case 'a':
X			aflag++;
X			break;
X		case 'v':
X			vflag++;
X			break;
X		default:
X			usage();
X		}
X	}
X	argc -= optind;
X	argv += optind;
X	if (argc == 0 && !aflag)
X		usage();
X
X	setpwent();
X	while ((pw = getpwent()) != 0)
X		(void) addid(pw->pw_uid, pw->pw_name);
X	endpwent();
X
X	setfsent();
X	while ((fs = getfsent()) != NULL) {
X		if (strcmp(fs->fs_vfstype, "ufs"))
X			continue;
X		if (aflag) {
X			if (hasquota(fs, &qfnp))
X				errs += repquota(fs, qfnp);
X			continue;
X		}
X		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
X		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
X			done |= 1 << argnum;
X			if (hasquota(fs, &qfnp))
X				errs += repquota(fs, qfnp);
X		}
X	}
X	endfsent();
X	for (i = 0; i < argc; i++)
X		if ((done & (1 << i)) == 0)
X			fprintf(stderr, "%s not found in fstab\n", argv[i]);
X	exit(errs);
X}
X
Xusage()
X{
X	fprintf(stderr, "Usage:\n\t%s\n\t%s\n",
X		"repquota [-v] [-g] [-u] -a",
X		"repquota [-v] [-g] [-u] filesys ...");
X	exit(1);
X}
X
Xrepquota(fs, qfpathname)
X	register struct fstab *fs;
X	char *qfpathname;
X{
X	register struct fileusage *fup;
X	FILE *qf;
X	u_int id;
X	struct dqblk dqbuf;
X	struct stat statb;
X	static struct dqblk zerodqblk;
X	static int warned = 0;
X	static int multiple = 0;
X	extern int errno;
X
X	if ((qf = fopen(qfpathname, "r")) == NULL) {
X		perror(qfpathname);
X		return (1);
X	}
X	if (fstat(fileno(qf), &statb) < 0) {
X		perror(qfpathname);
X		fclose(qf);
X		return(1);
X	}
X	if (quota(Q_SYNC, 0, statb.st_dev, 0) < 0 &&
X	    errno == EOPNOTSUPP && !warned && vflag) {
X		warned++;
X		fprintf(stdout,
X		    "*** Warning: Quotas are not compiled into this kernel\n");
X	}
X	if (multiple++)
X		printf("\n");
X	if (vflag)
X		fprintf(stdout, "*** Report for quotas on %s (%s)\n",
X		    fs->fs_file, fs->fs_spec);
X	for (id = 0; ; id++) {
X		fread(&dqbuf, sizeof(struct dqblk), 1, qf);
X		if (feof(qf))
X			break;
X		if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0)
X			continue;
X		if ((fup = lookup(id)) == 0)
X			fup = addid(id, (char *)0);
X		fup->fu_dqblk = dqbuf;
X	}
X	fclose(qf);
X	printf("                        Block limits               File limits\n");
X	printf("User            used    soft    hard  warn    used  soft  hard  warn\n");
X	for (id = 0; id <= highid; id++) {
X		fup = lookup(id);
X		if (fup == 0)
X			continue;
X		if (fup->fu_dqblk.dqb_curinodes == 0 &&
X		    fup->fu_dqblk.dqb_curblocks == 0)
X			continue;
X		printf("%-10s", fup->fu_name);
X		printf("%c%c%8ld%8ld%8ld%5u",
X			fup->fu_dqblk.dqb_bsoftlimit && 
X			    fup->fu_dqblk.dqb_curblocks >= 
X			    fup->fu_dqblk.dqb_bsoftlimit ? '+' : '-',
X			fup->fu_dqblk.dqb_isoftlimit &&
X			    fup->fu_dqblk.dqb_curinodes >=
X			    fup->fu_dqblk.dqb_isoftlimit ? '+' : '-',
X			fup->fu_dqblk.dqb_curblocks / 1024,
X			fup->fu_dqblk.dqb_bsoftlimit / 1024,
X			fup->fu_dqblk.dqb_bhardlimit / 1024,
X			fup->fu_dqblk.dqb_bwarn);
X
X		printf("  %6u%6u%6u%6u\n",
X			fup->fu_dqblk.dqb_curinodes,
X			fup->fu_dqblk.dqb_isoftlimit,
X			fup->fu_dqblk.dqb_ihardlimit,
X			fup->fu_dqblk.dqb_iwarn);
X		fup->fu_dqblk = zerodqblk;
X	}
X	return (0);
X}
X
X/*
X * Check to see if target appears in list of size cnt.
X */
Xoneof(target, list, cnt)
X	register char *target, *list[];
X	int cnt;
X{
X	register int i;
X
X	for (i = 0; i < cnt; i++)
X		if (strcmp(target, list[i]) == 0)
X			return (i);
X	return (-1);
X}
X
X/*
X * Check to see if a particular quota is to be enabled.
X */
Xhasquota(fs, qfnamep)
X	register struct fstab *fs;
X	char **qfnamep;
X{
X	register char *opt;
X	char *cp;
X	static char initname, usrname[100];
X	static char buf[BUFSIZ];
X
X	if (!initname) {
X		strcpy(usrname, qfname);
X		initname = 1;
X	}
X	strcpy(buf, fs->fs_mntops);
X	for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
X		if (cp = index(opt, '='))
X			*cp++ = '\0';
X		if (strcmp(opt, usrname) == 0)
X			break;
X		if (strcmp(opt, FSTAB_RQ) == 0)	/* XXX compatibility */
X			break;
X	}
X	if (!opt)
X		return (0);
X	if (cp) {
X		*qfnamep = cp;
X		return (1);
X	}
X	(void) sprintf(buf, "%s/%s", fs->fs_file, qfname);
X	*qfnamep = buf;
X	return (1);
X}
X
X/*
X * Routines to manage the file usage table.
X *
X * Lookup an id.
X */
Xstruct fileusage *
Xlookup(id)
X	u_int id;
X{
X	register struct fileusage *fup;
X
X	for (fup = fuhead[id & (FUHASH-1)]; fup != 0; fup = fup->fu_next)
X		if (fup->fu_id == id)
X			return (fup);
X	return ((struct fileusage *)0);
X}
X
X/*
X * Add a new file usage id if it does not already exist.
X */
Xstruct fileusage *
Xaddid(id, name)
X	u_short id;
X	char *name;
X{
X	struct fileusage *fup, **fhp;
X	int len;
X	extern char *calloc();
X
X	if (fup = lookup(id))
X		return (fup);
X	if (name)
X		len = strlen(name);
X	else
X		len = 10;
X	if ((fup = (struct fileusage *)calloc(1, sizeof(*fup) + len)) == NULL) {
X		fprintf(stderr, "out of memory for fileusage structures\n");
X		exit(1);
X	}
X	fhp = &fuhead[id & (FUHASH - 1)];
X	fup->fu_next = *fhp;
X	*fhp = fup;
X	fup->fu_id = id;
X	if (id > highid)
X		highid = id;
X	if (name) {
X		bcopy(name, fup->fu_name, len + 1);
X	} else {
X		sprintf(fup->fu_name, "%u", id);
X	}
X	return (fup);
X}
SHAR_EOF
chmod 444 '/usr/src/etc/repquota.c'
fi
exit 0
#	End of shell archive