Cover V05, I04
Article
Listing 1
Listing 2
Listing 3
Listing 4
Listing 5
Table 1
Table 2
Table 3

apr96.tar


Listing 4: CGI shell script for database searching

#!/bin/sh

# If # of matches in the datafile exceeds 10, the
# script will add a self calling link at the end so
# that the user can click to see the next 10 matches
# (that way load is vastly reduced on the server and
# won't overload the user's client with thousands of
# lines of text at once if the user entered a common
# search string)

# Note that all variables defined in here are
# Temporary. They are removed from the server's memory
# upon completion of the script. If the script is
# called twice by two users browsing the page, the
# second copy's variables will NOT interfere with the
# first copy's (a new instance or process of the
# script commences)

echo Content-type: text/html
echo
# NOTE: need the blank line after the content type
# above. Leave it blank before adding any headers.

# parse the QUERY_STRING passed to us from the form in
# the client's browser

# sed /s/"'"/%27/ replaces all ' characters with %27
# (escape) characters while /s/;/%27 does it for ;
eval `echo $QUERY_STRING | sed 's/'"'"'/%27/g' | \
sed 's/;/%27/g' | \
awk 'BEGIN { RS="&"; FS="=" }
$1 ~ /^[a-zA-Z][a-zA-Z0-9_]*$/
{ printf "QS_%s=%c%s%c\n", $1, 39, toupper($2), 39 }' `

# delete the carriage return that the form adds to the
# end of the last item in the query string
# (QS_LASTNAME in this case)
QS_LASTNAME=`echo $QS_LASTNAME | sed /%13/d`

if [ "$QS_INITIAL" = "" -a "$QS_LASTNAME" = "" ]; then

echo You must enter a search string into a least one
echo of the form inputs. Please try again.
# exit means quit the script
exit

fi

# init match var to 0, in case don't find any
# matches at all
matchvar=0

# assumes datafile has "!" separated fields, and +
# used inside the name field to seperate the first
# name from the last name (no # at the beginning of
# each line, lines terminated by a carriage return (no
# control M's please)). Alternatively can seperate
# each line by a space character instead of carriage
# return. Eg: #J!BROWNS!jbrown!James+Browns

# if QS_COUNT not null (ie: this script called itself
# via the HREF link at the end), then set countentry
# to QS_COUNT
if [ "$QS_COUNT" != "" ]; then
countentry=`echo $QS_COUNT`
else
# else if QS_COUNT is null, then set # of entries gone
# through = to 0
countentry=0
fi

# read each line of the datafile in sequence
for a in `cat datafile`
do

# replace all !'s with spaces (needed the !'s in the
# first place so that when cat datafile above it will
# read the data in one line at a time)
a=`echo $a | sed 's/!/ /g' `

# first goto the correct entry based on QS_COUNT
# passed from the EMALFIND.SH script (ie: if this script
# being called again and has the QS_COUNT variable)

# only do the below if the QS_COUNT var is not null
# (ie: will NOT be null if this script called itself
# via the HREF link at the end below) and if QS_COUNT
# is not 0
if [ "$QS_COUNT" != "" -a "$QS_COUNT" != "0" ]; then

# decrement QS_COUNT
QS_COUNT=`expr $QS_COUNT - 1`
# and go on to the next entry in the datafile via
# the continue command
continue

fi

# increment the countentry var to keep track of the
# number of entries gone through in datafile (that way
# can skip to correct entry in a different script if
# the # of matches exceeds 10... see near end of code)
countentry=`expr $countentry + 1`

# if QS_LASTNAME string is not NULL (ie: something has
# been entered in that field) then check the current
# catalog entry for a match in the lastname field
if [ "$QS_LASTNAME" != "" ]; then

# prepare a temp variable to hold a non wildcard
# version of QS_PART - ie: delete any * character's
# that the user entered - by replacing the *'s with
# nulls - nothing between the slashes (//)
qstemp=`echo $QS_LASTNAME | sed 's/*//g' `

# extract LASTNAME from "$a" by using awk '{print $2}'
tempvar1=`echo $a | awk '{print $2}' | \
grep "$qstemp"`

if [ "$tempvar1" = "" ];
then
# if tempvar doesn't match this catalog entry in the
# datafile, then time to read the next line in
# datafile (ie: continue, skipping the rest and going
# back to the start above)
continue
fi

# since not null, check if the first char in the
# user's entry is a * (meaning we have a wildcard
# entry such as *40H) - note: Uses original
# QS_LASTNAME - the one that has the wildcard's (* characters)
# still intact and not deleted (unlike the qstemp version)

tempvar=`echo $QS_LASTNAME | awk '{
printf "%c%s%c", 39, substr($0, 0, 1), 39 }' `

if [ "$tempvar" = "'*'" ]; then

# since first char = *, require the match to have
# nothing after it. so, if the input field is *40,
# then Ha40 will give a match but Ha40H will not. so
# goto end of $tempvar1 match read from file, and see
# if it matches the input query string (using
# qstemp = * deleted version of input query string)

# $ at end of qstemp means search for the expression
# at the end of tempvar1
tempvar=`echo $tempvar1 | grep "$qstemp"'$' `

# if the qstemp expression is NOT at the end, then no
# match. So continue.
if [ "$tempvar" = "" ]; then
continue
fi
fi

# since first char not *, check if last char is *
tempvar=`echo $QS_LASTNAME | awk '{
printf "%c%s%c", 39, substr($0, length, 1), 39 }' `

if [ "$tempvar" = "'*'" ]; then

# since last char = *, require the match to have
# nothing before it. so, if the input field is 40*,
# then 40Ha will give a match but H40Ha will not. so
# goto start of $tempvar1 match read from file, and
# see if it matches the input query string (using
# qstemp = * deleted version of input query string)

# ^ at start of qstemp means search for the expression
# at start of tempvar1
tempvar=`echo $tempvar1 | grep '^'"$qstemp" `

# if the qstemp expression is NOT at the end, then no
# match. So continue.
if [ "$tempvar" = "" ]; then
continue
fi
fi
fi

# if QS_INITIAL field is not NULL, then check the
# current catalog entry for a match in the initial
# field
if [ "QS_INITIAL" != "" ]; then

# check if the first field in the datafile matches the
# initial field
tempvar=`echo $a | awk '{print $1}' | \
grep "$QS_INITIAL"`

# if tempvar not null, means have a match
if [ "$tempvar" = "" ]; then
continue
fi

fi

# if got here, found a match, so display the output to
# the page and increment matchvar by 1, indicating
# that did indeed find a match so don't display the no
# matches found at the end
matchvar=`expr $matchvar + 1`

echo "<BR>NAME: "
# print the name (convert + to a space) - 4th field
echo $a | awk '{print $4}' | sed 's/+/ /g'

echo "    EMAIL ADDRESS: "
# print the email address - 3rd field
tempvar=`echo $a | awk '{print $3}' `

# and print the full email address
echo "$tempvar"@ualberta.ca

# check the total # of matches now and make sure less
# than 10. If > 10, time to stop counting/searching.
if [ "$matchvar" -ge 10 ]; then

# display a link that the user can click on to get the
# rest of the info
echo "<LI>"
tempvar=`echo '<A HREF="http://www.ualberta.ca\
/cgi-bin/emalfind.sh?' `

# and send over the new query_string with the new
# count included at the beginning, separating each var
# by &
echo $tempvar"COUNT="$countentry"&INITIAL="
echo $QS_INITIAL"&LASTNAME="$QS_LASTNAME

# so new query string looks like:
# COUNT=20&INITIAL=&LASTNAME=blow

# and close off the HREF link
echo '">'

echo "Click here to see the next 10 matches.</A>"
# and exit the script now
exit

fi

done

# display finished message

echo <BR>

if [ "$QS_COUNT" = "" ]; then

if [ "$matchvar" = 0 ]; then
echo 'I am sorry, that person is not listed in our'
echo ' database. Check your spelling and try again.'
else
echo 'Search successful.'
fi

else
# else if $QS_COUNT entry is not null, means already
# found 10 matches so should say here that no more
# matches are available if none were displayed this
# time through

if [ "$matchvar" = 0 ]; then
echo 'No more matches available.'

else
echo 'Search successful.'

fi

fi