#! /bin/dash # # 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 # # updated June 2012 for Linux umask 077 PATH="/usr/bin"; TERM="dumb"; export PATH TERM # force sort to use ASCII order LC_COLLATE="C"; export LC_COLLATE #MANPATH="/opt/jdk/man:/opt/man:/usr/share/man"; export MANPATH MANPATH="/opt/man:/usr/share/man"; export MANPATH LOG="/vecr/logs/LOG" IDLIST="/vecr/lib/id.list" IDN="/vecr/lib/id.N" # run with time limit # RUN="/vecr/bin/run" # other programs and scripts # SETUIDGID="/vecr/bin/chroot+setuidgid" UPDATESH="/vecr/bin/update.sh" RUNSH="/vecr/bin/run.sh" #JAVA="/opt/jdk/bin/java" JAVA="/bin/java" GDB="/usr/bin/gdb" M="/bin/octave-cli" PYTHON="/opt/bin/python3" ### # send stderr to stdout # exec 2>&1 # debug # echo "Content-type: text/plain\n" ### # 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 "$@" exit 1 } ### # functions to check subdir and file name # check_sub() { case "$sub" in a1|a2|a3|a4|a5|a6|a7|a8|a9|a10|aX|GSL|PPM|iPlot|HTML|SS) ;; *) error "Bad dir: $sub"; exit 1;; esac } # check_file() { case "$file" in p1.c|p2.c|p3.c|p4.c) ;; p1.h|p2.h|p3.h|p4.h) ;; p1.cc|p2.cc|p3.cc|p4.cc) ;; p1.hh|p2.hh|p3.hh|p4.hh) ;; 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.m|p2.m|p3.m|p4.m) ;; p1.py|p2.py|p3.py|p4.py) ;; Makefile|scan.l|parse.y) ;; p1.ss|p2.ss|p3.ss|p4.ss) ;; *) error "Bad file: $file"; exit 1;; esac } ### # extract user from REMOTE_USER; restrict to alphanumeric and force lowercase: # user=`echo "${REMOTE_USER}" | tr -dc '[:alnum:]' | tr '[:upper:]' '[:lower:]'` ### # $user can't be empty # if [ -z "$user" ]; then error "Bad user: ${REMOTE_USER} -> $user" exit 1 fi ### # check for admin users - ZZ # admin="" # case "$user" in #rperry|xjiao|dchasaki) rperry) admin=1 admin_user="$user" cookie=`echo "${HTTP_COOKIE}" | grep 'VECR_USER=' | sed -e 's/.*VECR_USER=//' -e 's/;.*//'` cookie=`echo "$cookie" | tr -dc '[:alnum:]' | tr '[:upper:]' '[:lower:]'` if [ -n "$cookie" -a "$cookie" != "$user" ]; then user="$cookie" fi ;; esac # # check for special users - ZZ # 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=$((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 # case "$COURSE" in fc|os|osp) CC="p1.c p2.c p3.c p4.c p1.h p2.h p3.h p4.h";; cpp) CC="p1.cc p2.cc p3.cc p4.cc p1.hh p2.hh p3.hh p4.hh";; *) error "Bad COURSE: $COURSE" ;; esac # top="/vecr/$COURSE/home" 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}" ### # create sub-dirs if necessary # for sub in a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 aX GSL PPM iPlot HTML SS do s="$dir/$sub" if [ ! -d "$s" ]; then mkdir -m 700 "$s" chown "${uid}:${uid}" "$s" fi done fi # if more sub-dirs added, put above sub loop outside/below this if ### # run can be invoked via GET or POST # run() { # # set some limits # # -c core dump size (in 512-byte blocks) (default: 0) # -d data segment size (in kilobytes) (default: unlimited) # -f file size (in 512-byte blocks) (default: unlimited) # -l locked memory (in kilobytes) (default: 64) # -m physical memory (in kilobytes) (default: unlimited) # -n number of open files (default: 1024) # -p number of processes (default: 1024) # -s stack size (in kilobytes) (default: 10240) # -t CPU time (in seconds) (default: unlimited) # -v virtual memory (default: unlimited) # -w file locks (default: unlimited) # ulimit -c 0 #ulimit -d 16384 # 8192 - C/Run needs more than 8192, 1/17/2020 #ulimit -d 32768 # thrd_create() needs more than 16384 3/1/2020 ulimit -d 65536 # octave needs more than 32768 3/14/2020 # 16384 cpp a6 FCC-data # 8192 for osp a4 image+audio # 4096 for fc a10 image ulimit -f 8192 ulimit -l 64 ulimit -m 65536 # 8192*8 #ulimit -m 131072 # 8192*16 #ulimit -m 262144 # 8192*32 ulimit -n 64 ulimit -p 64 ulimit -s 8192 ulimit -t 10 # ulimit -t 30 # temporary for cpp Fall 2019 #ulimit -v 262144 # 8192*32 -- java can't handle this ulimit -w 64 # # set uid/gid, and run the script # exec "$SETUIDGID" --setuidgid "$uid" "$uid" \ "$RUN" "$RUNSH" "$mode" "$top/$fname" "$sub" "$file" "$args" exit 0 } ### # handle GET # # Usage: $0 GET edit|rmcmts|plinenums|mlinenums|view|compile|cerr|clean|tester|preproc| # indent|asm|asmopt|disasm|zip|frameset|passwd|run # subdir file args # if [ "$1" = "GET" ]; then mode="$2" sub="$3" file="$4" args="$5" # disable #mode="zip" HOME="$dir/$sub" export HOME if [ -z "$mode" ]; then mode="edit" fi case "$mode" in frameset) echo "Content-type: text/html\n ${user} - ${COURSE} - ${sub}/${file} <body bgcolor=white text=black> <h2>${user} - ${COURSE} - ${sub}/${file}</h2> <p>This document was designed to be viewed using Frames. You are reading this because your browser doesn't support, or has disabled, the preferred presentation.</p> <p>You may<menu> <li>Return with Frames enabled and reload this URL. <li>Accept that the document will disappear when you select a link, and <a href=\"/prog/${COURSE}?edit+${sub}+${file}\">read it unframed</a>. </menu></body>" exit 0 ;; empty) echo "Content-type: text/html\n ${user} - ${COURSE} - ${sub}/${file} results: " exit 0 ;; edit|rmcmts|indent|plinenums|mlinenums) # # if no arguments, list subdirs # if [ -z "$sub" ]; then echo "Content-type: text/html\n" echo "${user} - ${COURSE} - projects

${user} - ${COURSE} - projects

" for s in a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 aX GSL PPM iPlot HTML SS do echo "$s,  " done echo "

zip - download all projects

documentation and source code" if [ -n "$admin" ]; then echo "

" fi #-- echo "

Set/reset local password" echo "

Logout - (UserID logout with password logout)" # # if no file argument, list files # elif [ -z "$file" ]; then check_sub echo "Content-type: text/html\n" echo "${user} - ${COURSE} - ${sub}

${user} - ${COURSE} - ${sub}

Home

Edit:" echo "

  " case "$sub" in iPlot) files="p1.c p2.c p3.c BREAK Makefile" ;; SS) files="p1.ss p2.ss p3.ss p4.ss" ;; *) files="$CC BREAK p1.sh p2.sh p3.sh p4.sh p1.txt p2.txt p3.txt p4.txt BREAK Makefile p1.java p2.java p3.java p4.java scan.l parse.y BREAK p1.m p2.m p3.m p4.m p1.py p2.py p3.py p4.py" ;; esac # for file in $files do if [ "$file" = "BREAK" ]; then echo "

  " else echo "$file,  " fi done echo "

View:

"
	  #
	  ls -AlL "${dir}/${sub}" |
	    awk 'NF == 9 { printf("%8s %3s %2s %5s %s\n", $5,$6,$7,$8,$9,$9); }' subdir="$sub" course="$COURSE"
	  #--  sed -e 's/\&/\&/g' -e 's//\>/g' |
	  #--  cut -c33-
	  echo "
" # # have subdir and file arguments # else check_sub check_file 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|clean|tester|preproc|asm|asmopt|disasm) check_sub check_file # # 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" 2>/dev/null exit 0 ;; # passwd) # exec /vecr/bin/passwd.sh GET # exit 0 # ;; run) run exit 0 ;; *) error "Bad request" exit 1 ;; esac ### # handle POST # # compile|upload|update|copy|run|crun|IO|debug|IOD|plot|splot|wav|image|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}" # disable #mode="zip" HOME="$dir/$sub" export HOME # 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: https://${HTTP_HOST}/prog/${COURSE}\n" exit fi # if [ "$mode" = "passwd" ]; then # exec /vecr/bin/passwd.sh POST # exit # fi check_sub check_file 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) # # 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" # exec "$0" GET edit "$sub" "$file" "$args" exit 0 ;; run|crun|debug|plot|splot|wav|image|input|cmd) run 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 ;; scan.l|parse.y) if [ "$mode" = "IO" ]; then prog="./parse" else prog="$GDB"; args="./parse $args" fi ;; *.java) prog="$JAVA"; b=`basename "$file" .java`; args="$b $args" ;; *.sh) prog="/bin/dash"; args="$file $args" ;; *.m) prog="$M"; args="--built-in-docstrings-file /dev/null -q --no-line-editing --persist $args $file" ;; *) error "Can not perform $mode on $file"; exit 1 ;; esac echo "Content-type: text/html\n VECR/IO ${user} - ${COURSE} - ${sub}/${file} - ${sub} - Home - Running: $prog $args
" # #
" # cd "/vecr/IO/bin" || exit 1 $JAVA IOticket "$user" "$uid" echo " Your browser does not support Java, or Java is not enabled. Sorry! " exit 0 ;; *) error "Bad request" exit 1 ;; esac fi