#/usr/bin/perl
my $count = 10019; #START COUNT HERE
my $min_id = 10000; #CHANGE ALL UIDS LESS THAN THIS
my $old_id = 1; #INITIALIZE FLAG
#####change_passwd###################################################
# This sub-program opens the etc/passwd file and copies it to
# passwd.tmp in this directory untill it finds the first
# student (2 to 4 letters followed by 4 digits). When
# encountered the user id is changed to the initial id number.
# This new id is given by the variable $id in which is
# incremented. The passwd.tmp is then used to overwrite the
# /etc/passwd file.
#
# INPUT: the start id number and the number that all
# ids < will be changed(parameters)
# OUTPUT: updated passwd file as well as passwd.bkp
# DEPENDENCIES: none
# DATE: March 26, 2001
# AUTHOR: William Martin
#####################################################################
sub change_passwd {
my ($id, $min_uid) = @_;
my $file_name = "/etc/passwd"; #Password file
my $temp_file = "passwd.tmp"; #temp file
my $flag = 0; #did we find someone?
#OPEN FILES
open(FILE, $file_name) or die "Error opening $file_name: $!\n";
open(NEW_FILE, ">$temp_file") or
die "Error opening $temp_file: $!\n";
#COPY FILE AND CHANGE THE NEXT INSTANCE OF STUDENT WITH ID < $id
while (<FILE>){
@line = split (/:/,$_);
if (($line[2] < $min_uid) &&
(m/^[a-z]{2,4}[0-9]{4}/) &&
($flag == 0)){ #HAS IT BEEN CHANGED ALREADY AND
#DOES IT MATCH THE STUDENT PATTERN AND
#HAS ONE STUDENT BEEN CHANGED ALREADY?
$flag = 1;
$home_dir = $line[5];# need this to change file ownerships
$student = $line[0];
$old_id = $line[2];
print NEW_FILE "$student:$line[1]:$id:$id:$line[4]:$line[5]:$line[6]";
print"Found $line[4] and changed user id $line[2] to $id\n";
next;
};
print NEW_FILE;
}
#COPY NEW FILE BACK INTO passwd, DESTROY passwd.bkp, AND CLOSE FILE
close(FILE); close(NEW_FILE);
open(FILE, ">$file_name") or die "Error opening $file_name: $!\n";
open(NEW_FILE, $temp_file) or
die "Error opening $temp_file: $!\n\n";
while (NEW_FILE) {
print FILE;
}
close(FILE); close(NEW_FILE);
system("rm passwd.tmp");
#RETURN INFO
if ($flag == 1){
return($home_dir, $student, $old_id);
}else{
return (" ", " ", 0);
}
}
#####################################################################
#####change_group####################################################
# This sub-program opens the etc/group file and appends the user
# $student and gives it a group id of $id (which is what we
# changed the user id to in the passwd file.
#
# INPUT: none
# OUTPUT: new file called group.new in the calling dir.
# DEPENDENCIES: none
# DATE: March 26, 2001
# AUTHOR: William Martin
#####################################################################
sub change_group {
my ($id, $student) = @_;
my $file_name = "/etc/group"; #Group file
#OPEN FILE
open(FILE, ">>$file_name") or die "Error opening $file_name: $!\n";
#APPEND NEW GROUP
print FILE "$student:\:$id:\n";
print"Added $student to group file with group id: $id\n\n";
#CLOSE FILE
close(FILE);
}
#####################################################################
####file_stat#########################################################
# This sub-program returns a group id from a 13 element list given
# by the lstat function. lstat returns the stats of files and not
# files pointed to by symbolic links.
#
# INPUT: file name in this directory
# OUTPUT: group id of this file
# DEPENDENCIES: be sure that you are currently in the directory
# that this file is in.
# DATE: April 2, 2001
# AUTHOR: William Martin
#####################################################################
sub file_stat {
my($file) = @_;
my($dev, $ino, $mode, $nlink,
$uid, $gid, $rdev, $size,
$atime, $mtime, $ctime, $blksize,
$blocks) = lstat($file);
return ($uid, $gid);
}
#####################################################################
#####dir_scan########################################################
# This sub-program opens the users directory ($dir) and changes all
# the files that belong to the group specified by $id_to_change. It
# then changes all the files to belong to the group specified by $id.
# This sub-program recurses throu the tree from the users home
# directory obtained from the passwrd file.
#
# INPUT: users home directory, group id to change,
# new group id, old uid
# OUTPUT: All filles in the users home directory are changed
# to belong to the new group id if they were prevously
# owned by the $id_to_change group.
# DEPENDENCIES: sub file_stat
# DATE: March 26, 2001
# AUTHOR: William Martin
#####################################################################
sub dir_scan{
my ($dir, $id_to_change, $id, $oid) = @_;
use Cwd;
chdir($dir) or die "Cant change to $dir:$!\n";
opendir(DIR, ".") or die "Can't open $dir:$!\n";
my @names = readdir(DIR) or die "Can't read $dir:$!\n";
closedir(DIR);
foreach my $name (@names){
next if ($name eq "..");
($usr_id, $grp_id) = &file_stat($name);
if ($usr_id == $oid){
chown($id, $grp_id, $name);
}
if ($name eq "."){
if ($grp_id == $id_to_change){
system ("chgrp", "-h", "$id", "$name");
}
next;
}
if (-d $name && !-l $name && $grp_id == $id_to_change){
if ($grp_id == $id_to_change){
system ("chgrp", "-h", "$id", "$name");
}
my $bookmark = &cwd; #we must mark our spot before recursing
&dir_scan($name, $id_to_change, $id);
chdir($bookmark) or die "Cant change to $bookmark:$!\n";
next;
}
if ($grp_id == $id_to_change){
system ("chgrp -h $id \'$name\'");
}
}
}
#####################################################################
#MAIN################################################################
#BACKUP FILES
system ("cp /etc/passwd /etc/passwd.bkp");
print "\n Backed up passwd file to passwd.bkp\n";
system ("cp /etc/group /etc/group.bkp");
print " Backed up group file to passwd.bkp\n\n";
while(1){
#CHANGE PASSWORD FILE
($home_directory, $stdnt, $old_id) =
&change_passwd($count, $min_id);
if ($old_id == 0){ #Will be zero if no more students!
print" There are no more students!\n";
last;
};
#CHANGE GROUP FILE
&change_group($count, $stdnt);
#CHANGE USERS FILES IN HOME DIRECTORY
&dir_scan($home_directory, 100, $count, $old_id);
print "Would you like to continue? ";
$answer = ; chomp $answer;
last if($answer ne "y" && $answer ne "Y");
print"\n\n";
$count ++;
}