[comp.lang.perl] Perl script to check Sun YP-style netgroups files

stripes@eng.umd.edu (Joshua Osborne) (01/14/91)

I wrote this perl script to check a Sun YP-style netgroups files (we don't use
YP, we use Hesiod (and the 3-head'ed hell-hound) but we made it look and feel
as much like YP (modulo lots of security holes and misc bugs) as possable.

This may be usefull to others, but what I am really hoping for is comments on
what I did "wrong" (so I can learn the Perl Way), and even what I did Right (so
others can leran by example :-), plus the ego boost can't hurt).

You will need to change the place it looks for the netgroups file, and the
domains it thinks are valid.  If anything else need to be changed please let me
know, thanks.

Oh, I almost forgot here is some sample output:
Sucking down users, Sucked 2119 users, checking for errors...

27 users appearing in netgroups more then once
clamb 2     emad 2      arora 2     burgoyne 2  sneetch 2   ziegast 2
bhandrkr 2  cogan 2     osterman 2  cta 2       jbw 2       darth 2
news 2      rajan 2     suzan 2     fpe 2       jxia 2      ytw 2
langston 2  motif 2     mojalvo 2   aahz 2      wells 2     fabrice 2
lbruck 2    lta 2       rsk 2       pugsley 2

35 users in passwd file, but not in netgroups
sverma    muro      amy       garai     baddy     jajodia   minis     kamath
naqvi     nazzal    mkamath   phuc      boulet    anitha    torok     proth
nagi      fmowrer   johri     wlbc      lincp     pritch    lance     mayd
bohse     george    cws       pk        uu-sphin  uu-musta  uu-kiwi   uu-edf
Upadthai  uu-mimsy  screen    stafroot

No users in netgroups, but not in passwd file

(as you can see we arn't 100% up and running yet, also I report dup entrys
even 'tho they arn't allways an error, for example at least 20 of our 27 dup
entrys are correct...)

#!/usr/local/bin/perl

# Check netgrups base file on egypt...       JMO 8Jan91
# New output format JMO 14Jan91

open(NG, "</local/etc/named/hesiod/makepw/netgroup.user") 
	|| die "Can't open netgroups file";

# This step can take some time w/ 2119 users!  (and more to come when the
# semester starts...)
$| = 1;  print "Sucking down users, ";  $| = 0;

while(<NG>) {
	next if !m/\(/;
	if (!m/^\(/) {
		#Can't get this to work...   s/[\w\b]*\(/\(/;
		$idx = index($_, "(");
		$_ = substr($_, $idx, length($_) - $idx);
	}
	@lusers = split(m/\(-,/, $_);
	foreach (@lusers) {
		next if m/^$/;
		if (m/\\$/) {
			m/\) +\\$/ || die "Bad end entry: $_";
			chop; chop;
			while(m/[ \n\t]$/) {
				chop;
			}
		} else {
			m/\)[ \n\t]+$/ || die "Bad entry: $_";
			while(m/[ \n\t]$/) {
				chop;
			}
		}
		chop;

		($luser, $domain) = split(m/,/, $_);
		die "Bad domain: $domain for $luser" unless $domain =~ m/^eng.umd.edu$/;
		push(users, $luser);
	}
}

print "Sucked $#users users, checking for errors...\n\n";

foreach $luser (@users) {
	if ($cnt{$luser}) {
		$cnt{$luser}++;
	} else {
		$cnt{$luser} = 1;
	}
}
foreach $luser (keys(%cnt)) {
	if ($cnt{$luser} <= 0) {
		die "$luser == $cnt{$luser}";
	} elsif ($cnt{$luser} > 1) {
		push(@dup_users, $luser . " " . $cnt{$luser});
	}
}

&report("users appearing in netgroups more then once", *dup_users);
@dup_users = ();

# Checking vs. password file

setpwent;

$luser = "not empty";
while ($luser) {
	($luser, $pisswd, $uid, $gid, $quota, $comment, $gcos, $dir,
		$shell) = getpwent;
#	print "$luser, $pisswd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell";
	last if (!$luser);
	$pusers{$luser} = $uid;
	if (!defined($cnt{$luser})) {
		push(@missing, $luser);
	}
}

&report("users in passwd file, but not in netgroups", *missing);
@missing = ();

# Checking passwd vs. netgroups

foreach $luser (@users) {
	push(@missing, $luser) unless defined($pusers{$luser});
}
&report("users in netgroups, but not in passwd file", *missing);
@missing = ();


## End line, program...
exit(0);


# report($title, *list)
# Print $#list $title \n, then format the list in N cols.
sub report {
#Strangly 'nuf $#dup_users can be < 0!
	local($title, *list) = @_;
	local($listlen) = $#list;
	local($width) = 0;
	local($itm, $cols, $fmtstr);

	if ($#list <= 0) {
		print("No ", $title, "\n\n");
		return;
	}

	printf("%d %s\n", $#list, $title);

	foreach $itm (@list) {
		$width = length($itm) if length($itm) > $width;
	}
	$fmtstr = "%-" . $width . "s  ";
	$width += 2;	# Trailing spaces
	# Assume 80col CRT
	$cols = int(80 / $width);

	#Strange, $#list can go <0!
	while ($#list >= 0) {
		for $i (1..$cols) {
			printf($fmtstr, pop(@list));
		}
		print "\n";
	}
	print "\n";

	# Restore list...
	$#list = $listlen;
}

-- 
           stripes@eng.umd.edu          "Security for Unix is like
      Josh_Osborne@Real_World,The          Multitasking for MS-DOS"
      "The dyslexic porgramer"                  - Kevin Lockwood
"Don't over-comment"     - p151 The Elements of Programming Style 2nd Edition
                                   Kernighan and Plauger