#!/bin/perl # # GRED - GRoup EDitor # # By: Theo Van Dinter, 95/11/12 # # This program was written using parts of WPI's C version of the gred program. # Unfortunately, the C program wouldn't compile on my system due to missing # routines and such (and various minor errors...), so I rewrote it in Perl... # It's designed so that users can create groups for themselves, and # administrate them. This is useful for project groups that need to work # together, etc... # require "neslib.pl"; $absolute_low=101; # Don't let Root do stupid things to groups w/ # GID's lower than this. $group_low=10000; # Lowest GID that users can deal with $group_high=11000; # Highest GID that users can deal with $group_file="/etc/group"; # The file with the groups in it (/etc/group) $group_back="/etc/group~"; # Backup file $group_lock="/etc/gtmp"; # Lock File for this program $my_name=getlogin||(getpwuid($<))[0]||die "Can't locate who you are!"; if ( !(-e $group_lock) ) # If the Lock file doesn't exist (a good thing) { open(F,"<$group_file"); # Open and read the group file foreach() { s/^\s+//; s/\s+$//; ($name,$data)=split(/:/,$_,2); $data=~/^.*:(\d+):/; $gid=$1; $groups{$name}=$data; # Store it all in a hash array } close(F); } else { die "Can't open group file, it's locked!"; } for($i=$group_low;$i<=$group_high;$i++) # Make the holes array { $crap{$i}=1; } foreach(sort values(%groups)) { s/^.*:(\d+):.+/$1/; delete($crap{$_}); } foreach(sort keys(%crap)) { push(@holes,$_); } undef(%crap); if ( !open(F,">$group_lock") ) # Create the lock file { die "Can't create the lock file.\n"; } print F "\n"; close(F); $removal_message=< "; ($com)=&getline; # Get a commandline print "\n"; $ccom=""; $ccom2=""; $com=~y/A-Z/a-z/; $com=~/^(.)(.*)/; $ccom=$1; $ccom2=$2; $ccom2=~s/^\s+//; $ccom2=~s/\s+$//; if ( $ccom eq "?" || $ccom eq "h" ) # Help Me! (Menu) { print "$help"; } elsif ( $ccom eq "i" ) # Group Information { if ( $selgroup eq "" ) { print "You haven't selected a group yet!\n"; } else { print "Group Name: $selgroup\n"; @test=split(/:/,$groups{$selgroup}); for($i=0;$i<=$#test;$i++) { print "Password : $test[$i]\n" if ($i==0 && $test[$i] ne ""); print "GID : $test[$i]\n" if ( $i==1 ); if ( $i==2 ) { print "Members :"; @test2=split(/,/,$test[$i]); foreach(@test2) { ($n,$p,$u,$g,$q,$c,$g,$d,$s)=getpwnam($_); ($a)=split(/,/,$g); if ( $_ ne $test2[0] ) { print "\t "; } if ( $_ ne $test2[0] ) { print " $a ($_)"; } else { print " ",&preverse,"$a ($_)",&poff; } print "\n"; } } } } } elsif ( $ccom eq "l" ) # List Groups { &print_groups; } elsif ( $ccom eq "a" ) # Add a User { if ( $selgroup eq "" ) { print "No group selected.\n"; } else { ($pass,$gid,$members)=split(/:/,$groups{$selgroup}); if ( !($members=~/^$my_name/i) ) { print "You aren't the owner of $selgroup!\n"; } else { if ( $ccom2 eq "" ) { print "User to add: "; ($user)=&getline; print "\n"; } else { $user=$ccom2; } $user=~y/A-Z/a-z/; if ( !getpwnam($user) ) # User not in the passwd file! { print "$user doesn't exist!\n"; } elsif ( &member($user,$groups{$selgroup}) ) { print "$user is already a member of this group.\n"; } else { $groups{$selgroup}.=",$user"; print "$user added to group.\n"; $change=1; } } } } elsif ( $ccom eq "d" ) # Remove a User { if ( $selgroup eq "" ) { print "No group selected.\n"; } else { ($pass,$gid,$members)=split(/:/,$groups{$selgroup}); if ( !($members=~/^$my_name/i) ) { print "You aren't the owner of $selgroup!\n"; } else { if ( $ccom2 eq "" ) { print "User to remove: "; ($user)=&getline; print "\n"; } else { $user=$ccom2; } $user=~y/A-Z/a-z/; $l=&member($user,$members); if ( !$l ) # If the user isn't a member ... { print "$user doesn't have access to this group!\n"; } elsif ( $user eq $my_name ) # Trying to remove yourself { print "You can't remove yourself with this command.\n"; } else { $groups{$selgroup}=~s/,$user//; $change=1; print "$used removed from group.\n"; } } } } elsif ( $ccom eq "g" ) # Give another User control of the group { if ( $selgroup eq "" ) { print "No group selected.\n"; } else { ($pass,$gid,$members)=split(/:/,$groups{$selgroup}); if ( &member($my_name,$members)!=1 ) { print "You aren't the owner of $selgroup!\n"; } elsif ( $gid < $absolute_low ) { print "GID Access is restricted below $absolute_low.\n"; } else { if ( $ccom2 eq "" ) { print "User for control: "; ($user)=&getline; print "\n"; } else { $user=$ccom2; } $user=~y/A-Z/a-z/; if ( !&member($user,$members) ) # User isn't a group member { print "$user doesn't have access to this group!\n"; } elsif ( $user eq $my_name ) # User is in control. { print "You already have control of this group.\n"; } else # Change owner of group. { @test=split(/,/,$members); $test[0]=$user; for($i=1;$i<=$#test;$i++) { if ( $test[$i] eq $user ) { $test[$i]=$my_name; } } $members=join(',',@test); $groups{$selgroup}="$pass:$gid:$members"; print "Control of group given to $user.\n"; $change=1; } } } } elsif ( $ccom eq "/" ) # Select a Group { if ( $ccom2 eq "" ) { print "Which Group: "; ($user)=&getline; print "\n"; } else { $user=$ccom2; } if ( !defined($groups{$user}) ) { print "Group $user doesn't exist"; if ( $user=~/^\W/ ) { print ", and the group name must start with an alphabetical char"; } elsif ( $user=~/[^0-9a-zA-Z_]/ ) { print ", and the group can only have alphanumeric characters"; } elsif ( length($user)>20 ) { print ", and the group must be 20 characters or less"; } elsif ( $#holes == -1 ) { print ", and there aren't any available GID's"; } else { print ", create (Y/n)? "; $test=&getline; $test=~y/NY/ny/; $test=~s/^(\w).*$/$1/; if ( $test eq "n" ) { print "\n",&pblink,"Aborted",&poff; } else { print "\nCreating Group $user"; $holes[0]=":$holes[0]:$my_name"; $groups{$user}=$holes[0]; shift(@holes); $selgroup=$user; } } print ".\n"; } else { ($pass,$gid,$members)=split(/:/,$groups{$user}); if ( !&member($my_name,$members) ) { print "You aren't a member of that group!\n"; } elsif ( $gid>$group_high || $gid<$group_low ) { print "The specified group is outside of the possible range.\n"; } else { print "Group $user selected.\n"; $selgroup=$user; } } } elsif ( $ccom eq "r" ) # Remove a Group { if ( $selgroup eq "" ) { print "You haven't selected a group yet!\n"; } else { ($pass,$gid,$members)=split(/:/,$groups{$selgroup}); if ( &member($my_name,$members)!=1 ) { print "You aren't the owner of that group!\n"; } elsif ( $gid < $absolute_low ) { print "GID Access is restricted below $absolute_low.\n"; } else { print "Group $selgroup has been removed.\n"; delete($groups{$selgroup}); $selgroup=""; push(@holes,$gid); @holes=sort @holes; $change=1; if ( !$rmgrp ) { print $removal_message; } $rmgrp=1; } } } elsif ( $ccom eq "q" ) # Quit { $quit=1; } elsif ( $ccom eq "x" ) # Abort { $abort=1; } else { print "Type h for help.\n"; } } if ( $abort ) { print "\t",&pblink,"Aborted!",&poff,"\n\n"; } else { if ( $change ) # Only output file if it's been changed. { system "/bin/mv","-f",$group_file,$group_back; open(F,">$group_file"); foreach(sort theo1 keys(%groups)) { print F "$_:$groups{$_}\n"; } print "New Group File Written.\n\n"; close(F); system "/bin/chmod","u=rw,go=r",$group_file; } else { print "Group file hasn't changed, no saving is neccesary.\n\n"; } } unlink($group_lock); exit; sub print_groups # Loop to print out group involvment { local($l,$l2,$te); $l2=0; foreach(sort theo1 keys(%groups)) { $groups{$_}=~/:(\d+):/; $te=$1; next if ( $te>$group_high || $te<$group_low ); $l=&member($my_name,$groups{$_}); if ( $l ) { $l2++; if ( $l==1 ) { print "You own group $_\n"; } else { print "You are a member of group $_\n"; } } } print "You aren't a member of any groups.\n" if ( !$l2 ); } sub theo1 # Sort by GID. { local($t1,$t2); $groups{$a}=~/:(.+):/; $t1=$1; $groups{$b}=~/:(.+):/; $t2=$1; $t1 <=> $t2; } sub member # Return position of user $us in the group. { # 1 is the first position, 0 if not in the local($us,$line)=@_; # group. local(@te); if ( $line=~/:/ ) { local(@te2)=split(/:/,$line,3); $line=$te2[$#te2]; } @te=split(/,/,$line); local($l)=-1; local($i); for($i=0;$i<=$#te;$i++) { if ( $te[$i] eq $us ) { $l=$i; } } return(++$l); }