Cover V04, I02
Listing 1


Coordinating Password and Group Files

Larry Reznick

While reviewing some other problems with a client's system, I found that the system had some group ID entries in /etc/passwd that weren't in the /etc/group file. This set of systems didn't have NIS running on them yet, so I had to wonder how many other systems had this kind of error? For that matter, where NIS was running, were the same kinds of discrepancies present?

Listing 1 shows a script that finds out whether such a discrepancy is present on the current system. In the script's beginning, variables centralize the passwd and group files because the data may come either from the real files or from NIS's maps. Using variables to control file names that collect the data allows some other part of the script to collect the data in a uniform place no matter where the data comes from. Just prior to creating those files, the script sets a trap for the common signals to kill those files.

Next, the script runs ypwhich to find out if NIS is up. If not, ypwhich exits with an error code detectable by the shell's if test. With NIS running, the script assumes that NIS holds the password and group maps and directs them to the central files. Otherwise, it takes them from their usual locations and puts them in the central files. I used cat instead of cp for the real files solely to correspond in kind with ypcat.

The real meat of the script is the for loop. The for's grp variable is set to the sorted group IDs in the central password file. They're sorted to be sure that the list shows a gid entry only once, and it has the nice side-effect of making the output appear in group sequence.

Group IDs may be arbitrarily small or large numbers. Few-digit numbers shouldn't match many-digit numbers by accident. For example, I don't want to find gid 7 within 17 and think gid 7 is present when it isn't. To be sure the gid matches are exact, I surround each number in the $grp variable with the same colon delimiters found in the group file. That forces :7: to match only that, not :17:. The resulting formatted numbers are stored in the grpfmt variable.

The match variable receives the line egrep finds that matches this formatted group number. If there is no such line in the group file, the match variable receives an empty string. The test -n is true when match holds the group ID's line. If this test is true, the OR (||) operator doesn't execute the second part of its command line, the echo command. The test is false when match is an empty string, which means that the formatted gid wasn't in the group file. If the first part of an OR is false, the second part must execute to see if it's true. That echoes the error message identifying not only which gid is missing, but looking up which users belong to that group. Such users' files will show the gid instead of their group name in long listings (ls -l).

Once I installed it, I ran this script using a for loop to rsh to every system I suspected might have a problem. For instance, in csh I could run:

foreach sys (system{1,2,3,4,5})
echo ==== badgrp report for $sys
rsh $sys badgrp

Without a very good reason to the contrary, every user should belong to a group identified in the group file. This script caught several bad group IDs for me.

About the Author

Larry Reznick has been programming professionally since 1978. He is currently working on systems programming in UNIX, MS-DOS, and OS/2. He teaches C, C++, and UNIX language courses at American River College and at the University of California, Davis extension.