Add chkgrp, a small utility for checking for syntax errors in group

files.

PR:		bin/1387
Suggested-by:	Giles Lean <giles@nemeton.com
This commit is contained in:
Dag-Erling Smørgrav 1998-05-24 15:09:23 +00:00
parent 2c8d830407
commit 83bc6a1106
3 changed files with 220 additions and 0 deletions

7
usr.sbin/chkgrp/Makefile Normal file
View File

@ -0,0 +1,7 @@
# $Id$
PROG= chkgrp
SRCS= chkgrp.c
MAN8= chkgrp.8
.include <bsd.prog.mk>

70
usr.sbin/chkgrp/chkgrp.8 Normal file
View File

@ -0,0 +1,70 @@
.\" Copyright (c) 1998 Dag-Erling Coïdan Smørgrav
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer
.\" in this position and unchanged.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. The name of the author may not be used to endorse or promote products
.\" derived from this software withough specific prior written permission
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $Id$
.\"
.Dd May 5, 1998
.Dt CHKGRP 8
.Os
.Sh NAME
.Nm chkgrp
.Nd check the syntax of the group file
.Sh SYNOPSIS
.Nm chkgrp
.Op Ar groupfile
.Sh DESCRIPTION
.Nm Chkgrp
scans the given file or, failing that, the system-wide group file for
errors. Specifically, it checks that every non-blank, non-comment
entry is composed of four colon-separated fields, that none of them
contains whitespace, and that the third field (the group ID) is
numeric.
.Sh SEE ALSO
.Xr getgrent 3 ,
.Xr group 5
.Sh DIAGNOSTICS
For each error found,
.Nm chkgrp
will print an error message containins the name of the file being
scanned and the line number on which the error was found. Otherwise no
output is produced.
.Pp
.Nm Chkgrp
returns EX_DATAERR if errors were found in the group file, and EX_OK
otherwise.
.Sh HISTORY
The
.Nm
command appeared in
.Tn FreeBSD
3.0
.Sh AUTHORS
.Nm Chkgrp
and this manual page were written by
.An Dag-Erling Coïdan Smørgav Aq des@FreeBSD.ORG .
.Sh BUGS
Should check fields more thoroughly for allowed / disallowed
characters, and the range of the group ID.

143
usr.sbin/chkgrp/chkgrp.c Normal file
View File

@ -0,0 +1,143 @@
/*-
* Copyright (c) 1998 Dag-Erling Coïdan Smørgrav
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software withough specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*/
static const char CVSID[] = "$Id$";
#include <err.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
extern char *__progname;
void
usage(void)
{
fprintf(stderr, "usage: %s [groupfile]\n", __progname);
exit(EX_USAGE);
}
int
main(int argc, char *argv[])
{
unsigned int len;
int n = 0, i, k, e = 0;
char *gfn, *line, *f[4], *p;
FILE *gf;
/* check arguments */
switch (argc) {
case 1:
gfn = "/etc/group";
break;
case 2:
gfn = argv[1];
break;
default:
gfn = NULL; /* silence compiler */
usage();
}
/* open group file */
if ((gf = fopen(gfn, "r")) == NULL)
err(EX_IOERR, gfn); /* XXX - is IO_ERR the correct exit code? */
/* check line by line */
while (++n) {
if ((line = fgetln(gf, &len)) == NULL)
break;
while (len && isspace(line[len-1]))
len--;
/* ignore blank lines and comments */
for (p = line; p < (line + len); p++)
if (!isspace(*p)) break;
if (!len || (*p == '#')) {
#if 0
/* entry is correct, so print it */
printf("%*.*s\n", len, len, line);
#endif
continue;
}
/*
* A correct group entry has four colon-separated fields, the third
* of which must be entirely numeric and the fourth of which may
* be empty.
*/
for (i = k = 0; k < 4; k++) {
for (f[k] = line+i; (i < len) && (line[i] != ':'); i++)
/* nothing */ ;
if ((k < 3) && (line[i] != ':'))
break;
line[i++] = 0;
}
if (k < 4) {
warnx("%s: line %d: missing field(s)", gfn, n);
e++;
continue;
}
/* check if fourth field ended with a colon */
if (i < len) {
warnx("%s: line %d: too many fields", gfn, n);
e++;
continue;
}
/* check that none of the fields contain whitespace */
for (k = 0; k < 4; k++)
if (strcspn(f[k], " \t") != strlen(f[k]))
warnx("%s: line %d: field %d contains whitespace",
gfn, n, k+1);
/* check that the GID is numeric */
if (strspn(f[2], "0123456789") != strlen(f[2])) {
warnx("%s: line %d: GID is not numeric", gfn, n);
e++;
continue;
}
#if 0
/* entry is correct, so print it */
printf("%s:%s:%s:%s\n", f[0], f[1], f[2], f[3]);
#endif
}
/* check what broke the loop */
if (ferror(gf))
err(EX_IOERR, "%s: line %d", gfn, n);
/* done */
fclose(gf);
exit(e ? EX_DATAERR : EX_OK);
}