Version 3 of apache server with tcl cgi scripts running on safe user

Updated 2008-03-26 17:02:41 by theover

by TV

I'm making a mathematical sound rendering web application which is already in a working prototype phase, see here

 http://www.theover.org/cgi-bin/maxwav.tcl?(sin(2*%pi*110*x)*exp(-2*x)+(1/2)*sin(2*2*%pi*110*x)*exp(-4*x))/(1+(1/2)) 

(If you want to try: the above url annot be clicked but mist be pasted in the url space of the probser, or a few parentises will be missing)

The result of the scripts in my example is a prettyprinted formula:

http://82.171.148.176/Wiki/formula.gif

http://82.171.148.176/Wiki/gnuplot.gif

And a mpeg compressed soundfile (example [L1 ]).

There are three tcl scripts involved, which communicate, and the setup allows for application management (for instance parallel use control) and distributed execution of parts (neither currently the case in this setup) and mostly was setup by me to be more safe on a general internet server. This is mainly done so that a user account which has hardly any permissions at all can handle the complicated web request followup calls to maxima, a C/Fortran compiler, latex and gnuplot, and which executes the program resulting from compliling the fortran rendered formula from the math package maxima.

What follows are essential parts of the three scripts, but NOT the whole original scripts on the server being actually in use:

the cgi-bin tcl script outline:

 #!/bin/sh
 # \
 exec tclsh "$0" "$@"
 #
   puts stdout "Content-type: text/html\n"

 proc notallowed {a} {
   puts stdout "This cgi script doesn't allow the use of the character/word\n"
   puts stdout "<pre>\n   $a\n</pre>\n"
   puts stdout "in the arguments on the url line, sorry"
   puts stdout "</body>"
   puts stdout "</html>"
   flush stdout
   exit
 }

   puts stdout "<HTML>"
   puts stdout "<head>"
   puts stdout "</head>"
   puts stdout "<body>"
   if [string match -nocase {*\[*} $env(QUERY_STRING)] { notallowed \[ }
   if [string match -nocase {*\]*} $env(QUERY_STRING)] { notallowed \] }
   if [string match -nocase {*\{*} $env(QUERY_STRING)] { notallowed \{ }
   if [string match -nocase {*\]*} $env(QUERY_STRING)] { notallowed \] }
   if [string match -nocase {*\{*} $env(QUERY_STRING)] { notallowed \{ }
   if [string match -nocase {*\}*} $env(QUERY_STRING)] { notallowed \} }
   if [string match -nocase {*system*} $env(QUERY_STRING)] { notallowed system }
   if [string match -nocase {*write*} $env(QUERY_STRING)] { notallowed writefile }
   if [string match -nocase {*open*} $env(QUERY_STRING)] { notallowed open }

   set s [socket localhost 1234]

   #debug/progress info
   puts stdout "starting math application, progress follows hereafter<P>"

   # wait for the results of the other scipts being started above, 
   # stop the cgi when 'end' is received:
   fileevent $s readable {
      set t [gets $s]
      if [string equal $t "end"] { set done 3 ; close $s } {
         puts stdout $t
      }
      flush stdout
      if [eof $s] { set done 2 }
   }

   # some cgi argument character translation, this should be easy in tcl in 
   # a safe and fast way, but I could not find an example
   set tt [exec echo $env(QUERY_STRING) | sed "s/%20/ /g" | sed "s/%25/%/g" ]

   # communicate the cgi arguments with the special user script
   puts $s $tt
   flush $s

   # stop the whole thing after little under half a minute
   after 27000 set done 1
   vwait done

   puts "<P> First version Page, testing !"

   puts "<P><a href=\"http://www.theover.org\">Home Page</a>\n"
   puts stdout "</body>"
   puts stdout "</HTML>"
   flush stdout
   exit

The matapp deamon on the limited rights user is started like indicated on the page A Webcam setup with tcl scripts and is extended with inter-script communication:

set ss socket -server servvid 1234

 proc servvid {s i p} {
   global argv 
   # puts $s "connection from $i"
   puts $s "(mathapp.tcl running)<br>"
   flush  $s
   # break it up after 22 seconds
   after 22000 " puts $s end ; close $s "
   # mind the small letters to redirect errors and stdouts from the actual script:
   eval "after 23000 catch exec kill  [exec tclsh /home/smalluser/math.tcl <@ $s >&

@ $s &]"

 }

vwait forever

I used to pass file pointers (domain socket descriptors) as a good server practice between processes, anyone know how to do this with tcl (see 'advanced tcp/ip programming', addison wesley ' 85 or so)

The actual script which does the work:

 #!/bin/sh
 # \
 exec tclsh "$0" "$@"
 #
 #   puts stdout "Content-type: text/html\n"

 proc domaxima { {m} } {
    puts bla....
 }

   puts "<a href=\"http://www.theover.org/Max\">Theo Verelst Mathematical Sounds
 Page</a> from [clock format [clock seconds]]:\n" 
   puts stdout "<pre>"

   puts "<br>evaluating maxima expression.."
   flush stdout
   puts -nonewline "[set in [gets stdin]]<br>--><br>"
   puts  "[set r [domaxima $in]]"
   puts  "generating Fortran expression from it.."
   flush stdout
   # etc...
   puts stdout end
   # Makes the cgi-bin script stop the server process thinking there's a connection
   exit

Of course this is not the whole actual application script mentioned above, just an examplatory part. The actual webapp can be found here: http://www.theover.org/Max

Uhm, I recall a lecture about rivet: can't that do stuff like this easier/neater ?!


enter categories here