There are three ways to use this server:
#! /home/setlorg/bin/setl const max_n = 10 ** 5; -- maximum allowed n if (m := getmap()) = om then stop; end if; s := m.maxprime; if (n := val s) /= om and n > 0 then n := floor n; n min:= max_n; print('Content-type: text/html'); print(); print('<TITLE>The primes up to '+n+'</TITLE>'); #define cmput(x) print(#x,'=',x) cmput({p in {2 .. n} | forall i in {2 .. floor sqrt p} | p mod i /= 0}); if n < val s then -- big number, or contains a fraction print('<p>The SETL server extends its sincerest apologies for '+ 'imposing the artificial limit of '+n+' when you asked '+ 'so nicely for '+s+'.</p>'); end if; else print('Content-type: text/html'); print(); print('<TITLE>No can do</TITLE>'); print('Error - positive number required, but got '+pretty s+'.'); end if; #include "web.setl"
#!/bin/sh export PATH=~/bin:$PATH # Limit size of created files to 1MB ulimit -f 1024 # Limit data seg size, max memory size, and virtual memory to 10MB ulimit -d 10240 ulimit -m 10240 ulimit -v 10240 # Limit total CPU time to 10 sec. ulimit -t 10 # Limit max user processes to 10 ulimit -u 10 # Run the "server", a SETL program setl -3 3<<'.' >/tmp/setl.stdout$$ 2>/tmp/setl.stderr$$ const wget_cmd = 'wget -O - '; m := getmap(); m_source := m.setl_source ? ''; m_input := m.setl_input ? ''; m_url := m.setl_url ? ''; m_data := m.setl_data ? ''; -- Fetch source text of user program if not blank m_url then m_source := wget(m_url); end if; -- Compile it if not blank m_source then m_object := filter('setl -c 2>&1',m_source+'\n'); if m_object(1) /= '#' then printa(stderr, rehigh amp m_object); stop 1; end if; else printa(stderr, 'No source (no sweat).'); stop; end if; -- Fetch data for the program if not blank m_data then m_input := wget(m_data); end if; -- Start example server, directing to stderr any output it may spew system ('setl daytime-server.setl >&2 &'); -- Run the compiled user program t := tmpnam(); putfile(t,m_object); u := tmpnam(); m_output := filter('setl -t'+ ' --restricted'+ ' --maxmem=100M'+ ' --allow-open=localhost:1313,socket'+ ' --allow-open=setl.org:1313,socket'+ ' '+t+' 2>'+u, m_input); unlink(t); -- Report its stdout output print('<pre>'); print(amp m_output); print('</pre>'); -- Report its stderr output putc(stderr, rehigh amp getfile u); unlink(u); op blank(s); return s('^ *$') = s; end; proc wget(url); return filter("wget -q -O - '"+escape url+"'"); end; op rehigh(s); -- change ANSI highlighting to HTML [saved_magic, magic] := [magic, false]; gsub(s,'\033[1m','<b><i>'); gsub(s,'\033[0m','</i></b>'); gsub(s,'\a',''); -- get rid of BEL chars too magic := saved_magic; return s; end op; #include "web.setl" #include "amp.setl" . # Report server output echo 'Content-type: text/html' echo '' echo '<title>SETL Server output</title>' if test -s /tmp/setl.stdout$$; then echo '<h3>stdout</h3>' # stdout output is expected to contain markup cat /tmp/setl.stdout$$ fi if test -s /tmp/setl.stderr$$; then echo '<h3>stderr</h3>' # stderr output is more likely to have been inadvertent echo '<pre>' cat /tmp/setl.stderr$$ echo '</pre>' fi # Remove scratch files rm -f /tmp/setl.stdout$$ /tmp/setl.stderr$$
-- A one-shot server to return a line with the current time and date -- (to the millisecond) and then return input lines in hex. const ms = 10000; -- time limit for client to connect, else we quit sd := open ('1313', 'server-socket'); -- listen on port 1313 if sd = om then stop 1; end if; -- exit(1) if (e.g.) port in use [ready] := select([{sd}], ms); -- wait up to ms for client to connect if sd notin ready then stop 2; end if; -- exit(2) on timeout fd := accept (sd); -- accept client connection printa (fd, fdate(tod)); -- send formatted date and time to client while (line := getline fd) /= om loop -- get line from client printa (fd, hex line); -- reply with line in hex form end loop; -- exit on eof from client
-- Please #include me in SETL programs that read from forms. proc getmap; -- decode form result into a SETL map if getenv 'REQUEST_METHOD' notin {'GET','POST'} then print('This script must be referenced with a METHOD of GET or POST.'); stop 1; end if; if getenv 'CONTENT_TYPE' /= 'application/x-www-form-urlencoded' then print('This script can only be used to decode form results.'); stop 1; end if; n := val getenv 'CONTENT_LENGTH'; s := getn(stdin,n); -- raw data [m, magic] := [magic, false]; -- suppress regexps gsub(s,'+',' '); -- change plusses to blanks r := {map_pair unescape x : x in split(s,'&')}; -- decode magic := m; -- restore status of regexp use return r; -- that's it! end getmap; op escape(x); -- convert certain characters to %HH (hex) return +/[if c in '.:/#?&=,;~0123456789-_'+ 'abcdefghijklmnopqrstuvwxyz'+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' then c else '%' + hex c end : c in x]; end escape; op unescape(x); -- convert %HH hex escapes to normal chars r := ''; while #x > 0 loop if x(1) = '%' then r +:= unhex x(2..3); x(1..3) := ''; else r +:= x(1); x(1) := ''; end if; end loop; return r; end unescape; op map_pair(x); -- equiv. to split(x,'=') on just the first '=' s := break(x,'='); return [s,x(2..1 max #x)]; end map_pair;
-- Useful transformation for text to be placed inside <pre>...</pre> op amp(s); -- expand some characters to &...; gsub(s,'&','\\&'); gsub(s,'<','\\<'); gsub(s,'>','\\>'); return s; end amp;
#!/bin/sh # Handy script to apply the "amp.setl" transformation on stdin setl ' putchar (amp getfile stdin); #include "amp.setl" '
dB bacon@cs.nyu.edu