There are currently five CGI scripts, written in TCL, in use. They fall into two categories - those that look up an entry in a database, and those that append an Add User message to a system's account creation file.
Database Lookup Scripts
The example given below is the script used to search for a student ID number and return information about the student.
The script is passed the student's ID number, plus the names of the systems on which accounts are to be created, and performs the following steps:
Checks to see that the request came from an authorised IP address. The code (with the IP address list removed) is as follows:
lappend validips
set ipok 0
foreach ip $validips {
if {[regexp $ip $env(REMOTE_ADDR)] == 1} {
set ipok 1
break
}
}
if {$ipok == 0} {
puts "Content-type: text/HTML\n"
puts ""
puts "You are not authorised to run this script."
puts ""
return
}
Checks to see that the student data file is available. Whenever the student database is being updated, a lock file is created and the script tests for the presence of that file. If it exists, then the student database is unavailable. The path to the lock file has been removed from the listing.
if {[file exists /student.lock.file] == 1} {
puts "Content-type: text/HTML\n"
puts ""
puts ""
puts "Student Account Login Details"
puts ""
puts ""
puts ""
puts "The student database is currently being updated. Please try again in a little while."
puts ""
return
}
Declares the binary search procedure. The procedure uses a recursion algorithm to find the matching student ID entry in the ID index. If found, the byte offset into the database is returned. If not, an empty string is returned.
proc bsrch {lo hi match} {
global if
set mid [expr (($hi + $lo) / 2)]
set mpoint [expr $mid * 16]
seek $if $mpoint
gets $if record
set reclist [split $record :]
set foundid [lindex $reclist 0]
if {$foundid == $match} {return [lindex $reclist 1]}
if {$lo >= $hi} {return ""}
if {$foundid < $match} {
set mid [expr $mid + 1]
return [bsrch $mid $hi $match]
} else {
set mid [expr $mid - 1]
return [bsrch $lo $mid $match]
}
}
The database file and its index are then opened. The number of entries in the index is calculated.
set loginfile
set indexfile
set lf [open $loginfile r]
set hi [expr [file size $indexfile] / 16]
set if [open $indexfile r]
Input from the HTML form is read and parsed. The student ID is searched for in the index and, if found, the matching record is read from the database. All of the selected system names (hosts) are read and built into a string.
set hostcount 0
set message [split [read stdin $env(CONTENT_LENGTH)] &]
foreach pair $message {
set name [lindex [split $pair =] 0]
set val [lindex [split $pair =] 1]
regsub -all {\+} $val { } val
# kludge to unescape chars
regsub -all {\%0A} $val \n\t val
regsub -all {\%2C} $val {,} val
regsub -all {\%27} $val {'} val
switch -exact $name {
# Read the student ID number
studentid {
set val [format "%07s" $val]
# Search the index
set offset [bsrch 0 $hi $val]
# If not found, set a flag and setup the reply string
# If found, read the matching record from the database
if {$offset == ""} {
set notfound 1
set loginline [format "Student ID %s not found" $val]
} else {
set notfound 0
seek $lf $offset
gets $lf loginline
set loginlist [split $loginline :]
}
}
# Read a host (system) name, incrementing the number of them
hosts {
lappend hostlist $val
incr hostcount
if {$val == "Chardonnay"} {
lappend hostlist Riesling
incr hostcount
}
}
}
}
Return either a form to confirm account creation or report one of two types of errors;
the student ID number was not found, or no systems (servers) were selected. Note that the returned form passes both the offset into the student database of the student's record and the nominated systems as arguments to the CGI script it calls. This enables the called script to quickly locate the student details.
if {$notfound} {
puts $loginline
} else {
if {$hostcount > 0} {
puts [format ""
} else {
puts " NO SERVERS SPECIFIED!"
puts ""
}
}
Finally return the HTML tail information.
puts ""
puts ""
Script to Append an "Add User" Message
The example given below is the script used to append student Add User messages to the account creation files for each of the specified systems. The script is passed the offset of the student's record in the database, plus the list of specified systems. The following steps are performed:
Return HTML header information.
puts "Content-type: text/HTML\n"
puts ""
Check to see that the request came from an authorised IP address. The code (with the IP address list removed) is as follows:
lappend validips
set ipok 0
foreach ip $validips {
if {[regexp $ip $env(REMOTE_ADDR)] == 1} {
set ipok 1
break
}
}
If the request is from an authorised IP address, open the student database, get the list of systems (servers), and read the student record from the database. Note that if the modem pool (Modems) is not in the systems list, it is added.
if {$ipok == 1} {
# Open data file
set loginfile
set lf [open $loginfile r]
# Get the list of servers & read student record
set arglist [split $argv ?]
set hostlist [split [lindex $arglist 1] :]
if {[lsearch -exact $hostlist Modems] < 0} {
lappend hostlist Modems
}
seek $lf [lindex $arglist 0]
set loginlist [split [gets $lf] :]
Determine whether the student is undergraduate or postgraduate. DEET codes are used to determine this.
# Set postgraduate codes
lappend courselist 01 02 03 04 05 06 07 09 12
if {[lsearch -exact $courselist [lindex $loginlist 6]] >= 0} {
set coursetype P
} else {
set coursetype U
}
Now append an Add User message to each system's account file. The account file names are composed of the prefix "SERVER." and the name of the system (server) as a suffix. Note the different message format sent to the modem pool. A message is returned listing each system for which the message has been added.