#/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 ++;
}