apache server with tcl cgi scripts running on safe user

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 cannot be clicked but must be pasted in the url space of the browser, or a few parentises will be missing)

The result of the scripts in my example is a pretty-printed formula:

Image TV Wiki formula.gif

Image TV 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 compiling 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

See also Bwise blocks using exec maxima , Making mathematical waves , a tcl script for function value listing based on a fortran expression , constructing mathematical formulas with Bwise blocks

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


TV Aug 20 '08 I've updated the above with a much faster graphing method, namely integrated with the compiled fortran/C program, which writes a .ppm image file with a self made fast graph, which is then converted to a .gif in the server proces.

Notice if you try the above link to try it out (which should work even in a few seconds when the server isn't too busy!) to include 2 extra ))s because the automatic link isn't correct with the formula.

In the same area: small formula rendering tests to test where the limit is going from an easy to use (lots less debugging usually, too) tcl language for formula rendering or signal processing tests to C (or something else) for instance in BWise possibly with a small frame to make mathematical function compilation easier.

I've also added for the music lovers amoung us a Jack sound and {Alsa] midi based sound rendering program which can be automatically made from the same fortran as above was produced from a Maxima , so that after rendering a page on the server like above, the same formula can be used to render sound in realtime, and even polyphonic!

Use this C program (it's only a first prototype) [L2 ] and use this line to compile:

   gcc -o synth  synth.c /dev/shm/sub.o -lasound -ljack

Where I presumed that the above tcl application scripts produced the fortran code in a memory disk. The jack version I used is 103 on Redhat FC8/64. I´m working on a Tcl/Tk interface a la www.theover.org/Soundtest (from the Linux sound page) or possibly Bwise, a serial port tcl script and a Xilinx demo board, and am describing some of this on http://www.theover.org/Diary/ldiary51.html , about halfway. Of course Bwise is another target.