Category: Unix Admin
Author/Contact Info hal halsys@mindspring.com
Description: On the Unix server we have groups of classes that need accounts just for a semester. Instructors request so many seats for such a class. This is a script I wrote to make it easy. I have a script that does the same for regular users.
#!/usr/bin/perl -w

   use strict;
   use diagnostics;
   use Term::Cap;
   use Term::ReadKey;
   use Term::ReadLine;


#-------Exits------------------------------
#This little bit is important as the Term::* stuf
#   _will_ hose your connection if you do not exit
#   properly.
$SIG{INT} = sub { done("Ouch!") };

#-----Variables-----------------------------
my $key;
my $count = 0;
my $count2 = 0;
my $timeout = 1;
my $entry;
my $stuf;
my $dataDescr;
my $SAVE = "";
my $section = 'u';
my $numOsections = 1;
my $item = "";

#---Get data on classes from the cstgroups file. The file is formated
#        CLASS:GROUP_NUMBER:HOME_DIR:UID_START
#    CLASS = class name in the catalog
#    GROUP_NUMBER = group number for the class
#    HOME_DIR = over directory where to place the user's directory
#    UID_START = UID fed to adduser, adduser then takes the next avali
+ble
#  ":" is the separator
#
open GROUPDATA, "</usr8/user/cstgroups";
my %AGItems;
while(defined($item = <GROUPDATA>))
{
    my @tosplit = split(':', $item);    
    my $class = $tosplit[0];
    $AGItems{$class} = [ @tosplit ]; 
}
close GROUPDATA;

my @CSTclasses;
$item = "";
my @Values = values %AGItems;
while( $item = pop @Values)
{
    push @CSTclasses, @$item->[0];
}

my $t = new Term::ReadLine::Gnu 'Data Entry';

#----------Start menu-------------------------------------------------
+------- 
   
my $data = ""; 
system("clear");
print "Select class with arrow keys\n" 
    . "\t\tor\'q\' to quit\n\n";
      
my @CST = @CSTclasses;
$item = "";
while($stuf = pop @CST)
{  
    $item = $item . " $stuf "; 
    if ( $count == 3 )
    {
        print "$item\n";
        $item = "";
        $count = 0;
    }
    else
    {
        $count++;
    }
}
print "$item\n\n\n";
    
#--Create the history list for arrow keys
@CST = @CSTclasses; 
$t->clear_history; #dump the history so we can use it.
while ( defined($data = pop @CST))
{     #seperate each item to an entry on the history list
   $t->addhistory($data);
}
$t->addhistory("q"); 
my $Class = $t->readline("Which Course > ", "cst1030"); 
chomp $Class;

if ($Class eq 'q') { done("See ya");} 

my $numOfStudents = $t->readline("How many seats in each class > ", "2
+5");
chomp $numOfStudents;

$section = $t->readline("How Many sections in for this class? ", "1");
chomp $section;
if ($section != '1')
{
    #--With eight char usernames we need an easy ID
    #        The system policy has been "c" for CST, the four number
       #        ID from the catalog and "u" for user(?). Mulit section
+s
       #        were just created by adding users, but then you get 10
+8 class
       #        members and which set of users goes with which instruc
+tor? 
       #        So I broke it so that we use a letter other than "u" f
+or sections
       #
   $numOsections = $t->readline("Please give a single digit number for
+ "
               . "this section ", "1");
    { #--perl switch
        if ($numOsections == 1) { $section = 'a'; last;}
        if ($numOsections == 2) { $section = 'b'; last;}
        if ($numOsections == 3) { $section = 'c'; last;}
        if ($numOsections == 4) { $section = 'd'; last;}
        if ($numOsections == 5) { $section = 'e'; last;}
        if ($numOsections == 6) { $section = 'f'; last;}
        if ($numOsections == 7) { $section = 'g'; last;}
        if ($numOsections == 8) { $section = 'h'; last;}
        if ($numOsections == 9) { $section = 'i'; last;}
    }
}
else #or not
{
   $section = 'u';
}
      
$key = $t->readline("Create $numOfStudents accounts for $Class ", "Yes
+");
if (!($key  eq "Yes")) { done("No Accounts Made");} 
      
$Class = lc $Class;
my $uid_base= $AGItems{$Class}[3];
my $gid = $AGItems{$Class}[1];
my $name = $Class;
$name =~ s/cst/c/;
       
my $passwdfile = "$Class" . "-passwd";
open WRITEIT, "> $passwdfile" || die "\ncan't open write file\n";
print WRITEIT "username+password\n";
      
my $HOME = $AGItems{$Class}[2];
if(!(-e $HOME))
{
    system("mkdir $HOME");
}
            
foreach my $number (1..$numOfStudents) 
{
    my $username= $name . $section . '0' x (2 - length($number)) . $nu
+mber;
    my $Password = Pass();
    chomp $Password;
    #--This file works great for making labels through your favorite W
+P
    print WRITEIT "$username+$Password\n";

# Make the account.
#    You might wonder at using the system command. I like the feedback
+ as
#    as the accounts are made, and I like to use the 'system' way.

    system("./adduser $username $Password $gid 17 \"Account for $Class
+\" " 
                . "$HOME/$username");

# Make the directory
    system("mkdir $HOME/$username");

# Copy skelton files into place

    print "setting up home for student $username\n";

    system("cp /usr/local/skeleton/students/cshrc $HOME/$username/.csh
+rc");
    system("cp /usr/local/skeleton/students/login $HOME/$username/.log
+in");
    system("cp /usr/local/skeleton/students/logout $HOME/$username/.lo
+gout");
    system("cp /usr/local/skeleton/newaccount $HOME/$username/.newacco
+unt");

    print "setting files to owner $username\n";
    system("chown $username $HOME/$username");
    system("chown $username $HOME/$username/.[cln]*");
    system("chgrp $gid $HOME/$username");
    system("chgrp $gid $HOME/$username/.[cln]*");

#---send mail so /var/mail/$user is made,
#
    print "sending first mail\n"; 
    system("mail $username < /usr8/user/welcome.user");
    sleep 10; #sometimes sendmail is slow...
    print "setting mail for $username\n";
    system("chown $username /var/mail/$username");
    system("chgrp mail /var/mail/$username");

}
close WRITEIT;

#-------------------------------------------------
sub Pass
#Got this from a discusion I had on permonks
# http://perlmonks.org/index.pl?node_id=9924&lastnode_id=864& 
{ my @password_chars = ( 0 .. 9, 'A' .. 'Z', 'a' .. 'z' );
        return 
        $password_chars[rand(@password_chars)] .
        $password_chars[rand(@password_chars)] .
        $password_chars[rand(@password_chars)] .
        $password_chars[rand(@password_chars)] .
        $password_chars[rand(@password_chars)] .
        $password_chars[rand(@password_chars)] .
        $password_chars[rand(@password_chars)] .
        $password_chars[rand(@password_chars)];
}
#-------------------------------------------------
#I found this somewhere. It's a nice way to 
#  deal with Term::* habit of hoseing your session
sub done
{
  print "@_\n\n";
  exit; 
}