Date: Wed, 1 Jul 2015 08:06:16 +0000 (UTC) From: Dag-Erling Smørgrav <des@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r284995 - stable/9/usr.sbin/chkgrp Message-ID: <201507010806.t6186GNH063022@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: des Date: Wed Jul 1 08:06:15 2015 New Revision: 284995 URL: https://svnweb.freebsd.org/changeset/base/284995 Log: MFH (r228976): UTFize MFH (r243076): check range of gid MFH (r243083): fix possible overflow in error counter MFH (r275765): clean up, reindent, add special case for + lines Modified: stable/9/usr.sbin/chkgrp/chkgrp.8 stable/9/usr.sbin/chkgrp/chkgrp.c Directory Properties: stable/9/usr.sbin/chkgrp/ (props changed) Modified: stable/9/usr.sbin/chkgrp/chkgrp.8 ============================================================================== --- stable/9/usr.sbin/chkgrp/chkgrp.8 Wed Jul 1 07:31:39 2015 (r284994) +++ stable/9/usr.sbin/chkgrp/chkgrp.8 Wed Jul 1 08:06:15 2015 (r284995) @@ -1,4 +1,4 @@ -.\" Copyright (c) 1998 Dag-Erling Coïdan Smørgrav +.\" Copyright (c) 1998 Dag-Erling Coïdan Smørgrav .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without Modified: stable/9/usr.sbin/chkgrp/chkgrp.c ============================================================================== --- stable/9/usr.sbin/chkgrp/chkgrp.c Wed Jul 1 07:31:39 2015 (r284994) +++ stable/9/usr.sbin/chkgrp/chkgrp.c Wed Jul 1 08:06:15 2015 (r284995) @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998 Dag-Erling Coïdan Smørgrav + * Copyright (c) 1998 Dag-Erling Coïdan Smørgrav * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,150 +30,163 @@ __FBSDID("$FreeBSD$"); #include <err.h> +#include <errno.h> #include <ctype.h> +#include <limits.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sysexits.h> -static char empty[] = { 0 }; - static void __dead2 usage(void) { - fprintf(stderr, "usage: chkgrp [groupfile]\n"); - exit(EX_USAGE); + + fprintf(stderr, "usage: chkgrp [-q] [groupfile]\n"); + exit(EX_USAGE); } int main(int argc, char *argv[]) { - unsigned int i; - size_t len; - int quiet; - int ch; - int n = 0, k, e = 0; - char *line, *f[4], *p; - const char *cp, *gfn; - FILE *gf; - - quiet = 0; - while ((ch = getopt(argc, argv, "q")) != -1) { - switch (ch) { + FILE *gf; + unsigned long gid; + unsigned int i; + size_t len; + int opt, quiet; + int n = 0, k, e = 0; + const char *cp, *f[4], *gfn, *p; + char *line; + + quiet = 0; + while ((opt = getopt(argc, argv, "q")) != -1) { + switch (opt) { case 'q': quiet = 1; break; - case '?': default: printf("hello\n"); usage(); - } - } - - if (optind == argc) - gfn = "/etc/group"; - else if (optind == argc - 1) - gfn = argv[optind]; - else - usage(); - - /* open group file */ - if ((gf = fopen(gfn, "r")) == NULL) - err(EX_NOINPUT, "%s", gfn); - - /* check line by line */ - while (++n) { - if ((line = fgetln(gf, &len)) == NULL) - break; - if (len > 0 && line[len - 1] != '\n') { - warnx("%s: line %d: no newline character", gfn, n); - e++; - } - 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); - for ( ; k < 4; k++) - f[k] = empty; - e++; - } - - for (cp = f[0] ; *cp ; cp++) { - if (!isalnum(*cp) && *cp != '.' && *cp != '_' && *cp != '-' && - (cp > f[0] || *cp != '+')) { - warnx("%s: line %d: '%c' invalid character", gfn, n, *cp); - e++; - } - } - - for (cp = f[3] ; *cp ; cp++) { - if (!isalnum(*cp) && *cp != '.' && *cp != '_' && *cp != '-' && - *cp != ',') { - warnx("%s: line %d: '%c' invalid character", gfn, n, *cp); - e++; - } + } } - /* check if fourth field ended with a colon */ - if (i < len) { - warnx("%s: line %d: too many fields", gfn, n); - e++; - } - - /* 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); - e++; - } - } + argc -= optind; + argv += optind; - /* 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++; - } + if (argc == 0) + gfn = "/etc/group"; + else if (argc == 1) + gfn = argv[0]; + else + usage(); + + /* open group file */ + if ((gf = fopen(gfn, "r")) == NULL) + err(EX_NOINPUT, "%s", gfn); + + /* check line by line */ + while (++n) { + if ((line = fgetln(gf, &len)) == NULL) + break; + if (len > 0 && line[len - 1] != '\n') { + warnx("%s: line %d: no newline character", gfn, n); + e = 1; + } + 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 == '#') + continue; + + /* + * Hack: special case for + line + */ + if (strncmp(line, "+:::", len) == 0) + 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); + while (k < 4) + f[k++] = ""; + e = 1; + } + + for (cp = f[0] ; *cp ; cp++) { + if (!isalnum(*cp) && *cp != '.' && *cp != '_' && + *cp != '-' && (cp > f[0] || *cp != '+')) { + warnx("%s: line %d: '%c' invalid character", + gfn, n, *cp); + e = 1; + } + } + + for (cp = f[3] ; *cp ; cp++) { + if (!isalnum(*cp) && *cp != '.' && *cp != '_' && + *cp != '-' && *cp != ',') { + warnx("%s: line %d: '%c' invalid character", + gfn, n, *cp); + e = 1; + } + } + + /* check if fourth field ended with a colon */ + if (i < len) { + warnx("%s: line %d: too many fields", gfn, n); + e = 1; + } -#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); - if (e == 0 && quiet == 0) - printf("%s is fine\n", gfn); - exit(e ? EX_DATAERR : EX_OK); + /* 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); + e = 1; + } + } + + /* check that the GID is numeric */ + if (strspn(f[2], "0123456789") != strlen(f[2])) { + warnx("%s: line %d: group id is not numeric", gfn, n); + e = 1; + } + + /* check the range of the group id */ + errno = 0; + gid = strtoul(f[2], NULL, 10); + if (errno != 0) { + warnx("%s: line %d: strtoul failed", gfn, n); + } else if (gid > GID_MAX) { + warnx("%s: line %d: group id is too large (%ju > %ju)", + gfn, n, (uintmax_t)gid, (uintmax_t)GID_MAX); + e = 1; + } + } + + /* check what broke the loop */ + if (ferror(gf)) + err(EX_IOERR, "%s: line %d", gfn, n); + + /* done */ + fclose(gf); + if (e == 0 && quiet == 0) + printf("%s is fine\n", gfn); + exit(e ? EX_DATAERR : EX_OK); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507010806.t6186GNH063022>