#! /bin/sh # # view/edit/compile/run project files # # R. Perry, Jan. 2003 # # This runs as root in the chroot environment of the web server # # ZZ marks local customization sections # umask 077 PATH="/usr/bin"; export PATH # force sort to use ASCII order LC_COLLATE="C"; export LC_COLLATE MANPATH="/opt/man:/usr/man"; export MANPATH LOG="/vecr/logs/LOG" IDLIST="/vecr/local-lib/id.list" FCLIST="/vecr/local-lib/fc.list" IDN="/vecr/local-lib/id.N" # run with time limit # RUN="/vecr/local-bin/run" # other programs and scripts # SETUIDGID="/vecr/local-bin/chroot+setuidgid" UPDATESH="/vecr/local-bin/update.sh" RUNSH="/vecr/local-bin/run.sh" JAVA="/opt/bin/java" GDB="/opt/bin/gdb" ### # send stderr to stdout # exec 2>&1 ### # log the connection # echo "`date` \"${REMOTE_USER}\" ${REMOTE_ADDR} ${SERVER_PORT} ${COURSE} $*" >> "${LOG}" ### # function to display error and exit # error() { echo "Content-type: text/plain\n" echo "$@" # if [ "t3" = "$sub" ]; then # echo "\nTest #3 has been collected." # fi exit 1 } ### # functions to check subdir and file name # check_sub() { case "$sub" in a1|a2|a3|a4|a5|a6|a7|a8|a9|a10|iPlot|HTML|SS) READONLY="";; *) error "Bad dir: $sub"; exit 1;; esac } # check_file() { case "$file" in p1.c|p2.c|p3.c|p4.c) ;; p1.java|p2.java|p3.java|p4.java) ;; p1.sh|p2.sh|p3.sh|p4.sh) ;; p1.txt|p2.txt|p3.txt|p4.txt) ;; p1.ss|p2.ss|p3.ss|p4.ss) ;; Makefile) ;; p1.h|p2.h|p3.h|p4.h) ;; *) error "Bad file: $file"; exit 1;; esac } ### # extract user from REMOTE_USER # user=`echo "${REMOTE_USER}" | sed -e 's/,.*//' -e 's/.*=//' -e 's;/;;g' -e 's/\.//g' -e 's/ //g' -e 's/ //g' | tr '[:upper:]' '[:lower:]'` ### # $user can't be empty # if [ -z "$user" ]; then error "Bad user: ${REMOTE_USER} -> $user" exit 1 fi ### # check for admin user - ZZ # #-- RP & TA #admin="" #case "$user" in # rperry|fmercede|mreda01) # admin=1 # admin_user="$user" # cookie=`echo "${HTTP_COOKIE}" | grep 'VECR_USER=' | sed -e 's/.*VECR_USER=//' -e 's/;.*//'` # if [ -n "$cookie" -a "$cookie" != "$user" ]; then # case "$user" in # fmercede|mreda01) # x=`grep "^${cookie}\$" "$FCLIST"` # if [ -n "$x" ]; then # user="$cookie" # fi # ;; # rperry) user="$cookie" # ;; # esac # fi # ;; #esac #-- admin="" case "$user" in rperry) admin=1 admin_user="$user" cookie=`echo "${HTTP_COOKIE}" | grep 'VECR_USER=' | sed -e 's/.*VECR_USER=//' -e 's/;.*//'` if [ -n "$cookie" -a "$cookie" != "$user" ]; then user="$cookie" fi ;; esac #-- # # check for special users # case "$user" in frodo) umask 022 ;; esac # export user ### # set uid, create if necessary # # possible race condition here... # uid=`grep "^${user} " "$IDLIST" | awk '{ print $2 }' | head -1` if [ -z "$uid" ]; then last=`cat "$IDN"` uid=`expr "$last" + 1` echo "$uid" > "$IDN" echo "$user $uid" >> "$IDLIST" fi # if [ "$uid" -lt 3000 ]; then error "Bad uid: $uid - please contact Rick Perry about this!" exit 1 fi ### # set dir, create if necessary # # fname is $user, COURSE env is set by the wrapper # # ZZ - current courses # #SVS submit="/vecr/$COURSE/submit" # case "$COURSE" in osp|ccs|fc) top="/vecr/$COURSE/home" ;; *) error "Bad COURSE: $COURSE" ;; esac # fname="$user" dir="$top/$fname" if [ ! -d "$dir" ]; then mkdir -m 750 "$dir" chgrp "${uid}" "$dir" echo "`date` \"${REMOTE_USER}\" ${REMOTE_ADDR} ${SERVER_PORT} ${COURSE} mkdir $fname $uid" >> "${LOG}" fi ### # create sub-dirs if necessary # for sub in a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 iPlot HTML SS do s="$dir/$sub" if [ ! -d "$s" ]; then check_sub if [ -z "$READONLY" ]; then mkdir -m 700 "$s" chown "${uid}:${uid}" "$s" fi fi done ### # handle GET # # Usage: $0 GET edit|plinenums|mlinenums|view|compile|cerr|tester|preproc|asm|asmopt|zip|frameset|passwd #SVS |submit|submit_view|submit_get # subdir file # if [ "$1" = "GET" ]; then mode="$2" sub="$3" file="$4" args="$5" HOME="$dir/$sub" export HOME # ZZ # # if [ -n "$sub" -a -z "$admin" -a "$COURSE" != "N" ]; then # #- if [ -n "$sub" -a -z "$admin" ]; then #- mode="zip" #- fi if [ -z "$mode" ]; then mode="edit" fi case "$mode" in frameset) echo "Content-type: text/html\n
" for s in a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 iPlot HTML SS do echo "$s, " done echo "
zip - download all projects
documentation and source code" if [ -n "$admin" ]; then echo "
" fi echo "Logout - (UserID logout with empty password)" # # if no file argument, list files # elif [ -z "$file" ]; then check_sub echo "Content-type: text/html\n" echo "
Edit:" #SVS - submit #SVS - view submissions # ZZ # echo "
Note: this environment will be shut down after May 9, # then will be available again, read-only, later next week.
" if [ -z "$READONLY" ]; then echo "
" case "$sub" in iPlot) files="p1.c p2.c p3.c" ;; SS) files="p1.ss p2.ss p3.ss p4.ss" ;; *) files="p1.c p2.c p3.c p4.c p1.java p2.java p3.java p4.java BREAK p1.sh p2.sh p3.sh p4.sh p1.txt p2.txt p3.txt p4.txt BREAK Makefile p1.h p2.h p3.h p4.h" ;; esac # for file in $files do if [ "$file" = "BREAK" ]; then echo "
" else echo "$file, " fi done fi echo "
View:
"
#
ls -AlL "${dir}/${sub}" |
awk 'NF == 9 { printf("%8s %3s %2s %5s %s\n", \
$5,$6,$7,$8,$9,$9); }' sub="$sub" course="$COURSE"
#-- sed -e 's/\&/\&/g' -e 's/\</g' -e 's/>/\>/g' |
#-- cut -c33-
echo ""
#
# have subdir and file arguments
#
else
check_sub
check_file
if [ -n "$READONLY" ]; then
error "Readonly dir: $sub"; exit 1
fi
cd "${dir}/${sub}"
P="`pwd`"
if [ "$P" != "${dir}/${sub}" ]; then
error "Bad dir: $P != ${dir}/${sub}"; exit 1
fi
#
exec "$SETUIDGID" --setuidgid "$uid" "$uid" \
"$UPDATESH" "$mode" "$user" "$sub" "$file" "$args"
exit 0
fi
;;
view)
#
# must have subdir and file arguments
#
if [ -z "$file" ]; then
error "missing subdir and file arguments"
exit 1;
fi
#
check_sub
#
# set uid/gid, and run the script
#
exec "$SETUIDGID" --setuidgid "$uid" "$uid" \
"$RUN" "$RUNSH" "$mode" "$top/$fname" "$sub" "$file"
exit 0
;;
compile|cerr|tester|preproc|asm|asmopt)
check_sub
check_file
if [ -n "$READONLY" ]; then
error "Readonly dir: $sub"; exit 1
fi
#
# set uid/gid, and run the script
#
exec "$SETUIDGID" --setuidgid "$uid" "$uid" \
"$RUN" "$RUNSH" "$mode" "$top/$fname" "$sub" "$file"
exit 0
;;
zip)
cd "$top" || exit 1
#echo "Content-type: application/zip\n"
echo "Content-type: application/octet-stream
Content-Disposition: attachment; filename=\"$user.zip\"\n"
exec "$SETUIDGID" --setuidgid "$uid" "$uid" \
/usr/bin/zip -rq - "$user"
exit 0
;;
#SVS submit|submit_view|submit_get)
#SVS check_sub
#SVS cd "$top" || exit 1
#SVS d="$submit/$user"
#SVS if [ ! -d "$d" ]; then
#SVS mkdir "$d"
#SVS fi
#SVS #
#SVS case "$mode" in
#SVS submit)
#SVS d="$d/$sub-`date '+%Y-%m-%d-%H:%M:%S'`.tar.gz"
#SVS echo "Content-type: text/plain\n\nSubmitting ${COURSE} $sub\n\nCreating $d...\n"
#SVS tar cvf - "$user/$sub" | gzip > "$d"
#SVS echo "\nDone."
#SVS exit 0
#SVS ;;
#SVS submit_view)
#SVS echo "Content-type: text/html\n
#SVS "
#SVS ls "$d" | grep "^${sub}-" | while read f
#SVS do
#SVS echo "\n$f"
#SVS gzip -d < "$d/$f" | tar tvf - 2>/dev/null | cut -c21-
#SVS done
#SVS echo "\nEnd."
#SVS exit 0
#SVS ;;
#SVS submit_get)
#SVS #
#SVS # careful here, $file is unsafe
#SVS #
#SVS (ls "$d"; echo "NOT_FOUND") | while read f
#SVS do
#SVS if [ "$f" = "NOT_FOUND" ]; then
#SVS error "File $file not found."
#SVS exit 1
#SVS elif [ "$f" = "$file" ]; then
#SVS echo "Content-type: application/octet-stream
#SVSContent-Disposition: attachment; filename=\"${user}-${COURSE}-${f}\"\n"
#SVS cat "$d/$f"
#SVS exit 0
#SVS fi
#SVS done
#SVS exit 0
#SVS ;;
#SVS esac
#SVS ;;
passwd)
exec /vecr/local-bin/passwd.sh GET
exit 0
;;
*)
error "Bad request"
exit 1
;;
esac
###
# handle POST
#
# compile|upload|update| #UCR update_compile|update_compile_run
# |copy|run|crun|IO|debug|IOD|plot|splot|audio|setuser|passwd
# subdir file args
#
else
read mode sub file args
echo "`date` \"${user}\" ${REMOTE_ADDR} ${SERVER_PORT} ${COURSE} POST $mode $sub $file $args" >> "${LOG}"
HOME="$dir/$sub"
export HOME
# ZZ
#
# if [ -z "$admin" -a "$COURSE" != "N" ]; then
#
#- if [ -z "$admin" ]; then
#- exec "$0" GET zip
#- exit 0
#- fi
# setuser and passwd special cases
#
if [ -n "$admin" -a "$mode" = "setuser" ]; then
echo "Content-type: text/html
Set-Cookie: VECR_USER=$args; path=/
Status: 302 Moved Temporarily
Location: http://${HTTP_HOST}/prog/${COURSE}\n"
exit
fi
if [ "$mode" = "passwd" ]; then
exec /vecr/local-bin/passwd.sh POST
exit
fi
check_sub
check_file
if [ -n "$READONLY" ]; then
error "Readonly dir: $sub"; exit 1
fi
case "$mode" in
compile)
#
# set uid/gid, and run the script
#
exec "$SETUIDGID" --setuidgid "$uid" "$uid" \
"$RUN" "$RUNSH" "$mode" "$top/$fname" "$sub" "$file"
exit 0
;;
upload|update|copy) #UCR |update_compile|update_compile_run
#
# update file, then redisplay
#
cd "${dir}/${sub}"
P="`pwd`"
if [ "$P" != "${dir}/${sub}" ]; then
error "Bad dir: $P != ${dir}/${sub}"; exit 1
fi
#
"$SETUIDGID" --setuidgid "$uid" "$uid" \
"$UPDATESH" "$mode" "$user" "$sub" "$file" "$args"
#
#UCR case "$mode" in
#UCR update_compile)
#UCR exec "$0" GET compile "$sub" "$file" "$args"
#UCR ;;
#UCR update_compile_run)
#UCR echo "crun $sub $file $args" | exec "$0" POST
#UCR ;;
#UCR *)
#UCR exec "$0" GET edit "$sub" "$file" "$args"
#UCR ;;
#UCR esac
#
exec "$0" GET edit "$sub" "$file" "$args"
exit 0
;;
run|crun|debug|plot|splot|audio|cmd)
#
# flush stdin ??? why ??? -- removed 11/12/2006
#
# cat >/dev/null
#
# set some limits
#
# -c maximum core file size (in 512-byte blocks)
# -d maximum size of data segment or heap (in kbytes)
# -f maximum file size (in 512-byte blocks)
# -n maximum file descriptor plus 1
# -s maximum size of stack segment (in kbytes)
# -t maximum CPU time (in seconds)
# -v maximum size of virtual memory (in kbytes)
#
ulimit -c 0
ulimit -d 8192
ulimit -f 1024
ulimit -n 64
ulimit -s 8192
ulimit -t 10
# ulimit -v 65536 # jdk1.3 has a problem with this limit
#
# set uid/gid, and run the script
#
exec "$SETUIDGID" --setuidgid "$uid" "$uid" \
"$RUN" "$RUNSH" "$mode" "$top/$fname" "$sub" "$file" "$args"
exit 0
;;
IO|IOD)
#
# generate IO applet HTML
#
case "$file" in # add debug here to run gdb ZZ
*.c)
if [ "$mode" = "IO" ]; then
prog=./`basename "$file" .c`
else
prog="$GDB"; b=./`basename "$file" .c`; args="$b $args"
fi
;;
*.java) prog="$JAVA"; b=`basename "$file" .java`; args="$b $args"
;;
*.sh) prog="/opt/bin/ksh"; args="$file $args"
;;
esac
echo "Content-type: text/html\n