CGI Scripts


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:

  1. 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 <List of valid IP addresses goes here> 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 "<HTML>" puts "You are not authorised to run this script." puts "</HTML>" return }
  2. 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 <path goes here>/student.lock.file] == 1} { puts "Content-type: text/HTML\n" puts "<HTML>" puts "<HEAD>" puts "<TITLE>Student Account Login Details</TITLE>" puts "</HEAD>" puts "<BODY>" puts "<hr>" puts "The student database is currently being updated. Please try again in a little while.<hr>" puts "</body></html>" return }
  3. 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] } }
  4. The database file and its index are then opened. The number of entries in the index is calculated.

    set loginfile <student database path goes here> set indexfile <student ID index path goes here> set lf [open $loginfile r] set hi [expr [file size $indexfile] / 16] set if [open $indexfile r]
  5. 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 <b>%s</b> 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 } } } }
  6. Return some HTML header information.

    puts "Content-type: text/HTML\n" puts "<HTML>" puts "<HEAD>" puts "<TITLE>Student Account Login Details</TITLE>" puts "</HEAD>" puts "<BODY>" puts "<center><H3>Student Account Login Details</H3></center>"
  7. 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 "<FORM METHOD=POST action=\"http://mite.cs.cowan.edu.au/cgi-bin/<cgi name>?%d?%s\">" $offset [join $hostlist :]] } puts -nonewline [format "<pre><b>Student ID:</b> %-10s" [lindex $loginlist 0]] puts [format "<b>Name:</b> %s %s %s" [lindex $loginlist 2] [lindex $loginlist 3] [lindex $loginlist 1]] puts -nonewline [format "\n <b>Login ID:</b> %-10s<b>Password:</b> %s\n\n <b>Units:</b> %s\n\n <b>Servers:</b>" [lindex $loginlist 4] [lindex $loginlist 5] [lindex $loginlist 7]] if {$hostcount > 0} { set hostsout 0 foreach host $hostlist { if {$hostsout == 6} {puts -nonewline [format "\n "]} puts -nonewline " $host" incr hostsout } puts "</PRE>" puts "<p>The password listed above, is for initial use on all NETWORK SERVERS and the MODEM POOL. " puts "Pilot accounts will be issued with a different password in a few days. Please return " puts "to collect it." puts "Note that when you first login to any of the NETWORK SERVERS (Shiraz, Merlot, Chablis, Chardonnay, Riesling or Cabernet), you will be required to create a new password." puts "<p><center><INPUT value=\"Confirm Account Creation\" TYPE=submit></center>" puts "</FORM>" } else { puts " <i>NO SERVERS SPECIFIED!</i>" puts "</PRE>" } }
  8. Finally return the HTML tail information.

    puts "</BODY>" puts "</HTML>"

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:

  1. Return HTML header information.

    puts "Content-type: text/HTML\n" puts "<HTML>"
  2. 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 <Valid IP addresses listed here> set ipok 0 foreach ip $validips { if {[regexp $ip $env(REMOTE_ADDR)] == 1} { set ipok 1 break } }
  3. 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 <Student database path here> 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] :]
  4. 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 }
  5. 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.

    puts "<h3>Login application sent to hosts</h3><ul>" foreach host $hostlist { set outfile <Output file path here>/SERVER. append outfile $host set of [open $outfile a+] if {$host == "Modems"} { puts $of [format "AU:%s:%s %s:%s:%s" [lindex $loginlist 4] [lindex $loginlist 2] [lindex $loginlist 1] [lindex $loginlist 5] $coursetype] } else { puts $of [format "AU:%s:%s %s:%s:%s" [lindex $loginlist 4] [lindex $loginlist 2] [lindex $loginlist 1] [lindex $loginlist 5] [lindex $loginlist 7]] } close $of puts "<li>$host" } puts "</ul><a href=\"/<HTML path here>/studentapp.html\">Create next account</a>"
  6. If the request was not from an authorised IP address, return the appropriate message.

    } else { puts "You are not authorised to run this script." }
  7. Finally return the HTML tail information.

    puts "</HTML>"

Return to Implementation page...