Jocelyn asks:
> I'd be interesting in knowing of any work that's been done in
> connecting Poplog programs to World-Wide Web servers; I'm thinking of
> the Web as one method for delivering my teaching applications. At the
> moment, the methods for interaction, and the style in which results can
> be displayed, are rather limited, but things should improve as Java (or
> its competitors) become more widely available.
I'm posting this to pop-forum because I think it is of quite general
interest as far as I can tell.
Our work involves a WWW server "park". We run a small LAN (about
10 machines) outside the corporate firewall which acts as host
for a variety of local businesses. The interesting aspect for
Poploggers is that many of the scripts are implementing in
Pop11.
To do this efficiently, I created a compact Pop11 executable -
without X or VED - which I call poplite. [To create one of your
own simply link with -noved and nox.] I then "strip" the
resulting executable to create a 1Mb base. This, although not
truly lightweight, is good enough for our purposes.
On top of this, we use a small saved image created by the script
which I enclose below. The saved image is used to write Pop11
scripts. So, if you wanted to implement the same functionality
as post-query, you would write a file that looks like this ...
#/bin/csh -f
source /usr/local/lib/poplog/preamble
exec $popsys/poplite +script $0 $*
pr( 'Content-type: text/html\r\n\r\n' ); ;;; MIME header + termination.
npr( 'The following name/value pairs were submitted :-<P>' );
npr( '<UL>' );
lvars i;
for i in cgi_names do
nprintf( '<LI>%p = %p', [% i.dup.cgi_args %] );
endfor;
Note that preamble is a trivial C-shell script for setting the
minimum of shell variable for Poplog to run. For more details,
read "http://www.avonibp.co.uk/office/scripts/pop/pop.html".
People who are interested in working with me to make Poplog properly
integrated with the Internet and especially the WWW should drop me
a line. I'm very keen on making Poplog a good alternative to Perl
for WWW hacking, for example, and making the PLUG Source Code Archive
available dynamically.
Steve Knight
#!/bin/csh -f
# Use this script to create the scripting saved image.
../poplite << 'EOT'
uses plug_archive
compile_mode :pop11 +strict;
section;
define global syntax $ ;
sysPUSHQ( readitem() sys_>< nullstring );
sysCALL -> pop_expr_inst;
"systranslate" -> pop_expr_item;
enddefine;
define global incharline( r ); lvars procedure r;
lconstant terminator = identfn(% termin %);
procedure();
lvars count = 0;
repeat
lvars c = r();
if c == `\n` do
consstring(count);
quitloop
elseif c == termin do
if count == 0 then
termin
else
;;; Poplog guarantees that all end-of-files are
;;; preceded by end-of-lines. However, I do not wish
;;; to rely on this undocumented fact & have put this
;;; line in as protection.
consstring( count );
terminator -> r;
endif;
quitloop
else
c;
count fi_+ 1 -> count;
endif;
endrepeat;
endprocedure
enddefine;
global vars cgi_names = [];
global vars cgi_args =
newproperty( [], 8, false, "perm" );
define lconstant cgi_escape( a, b ); lvars a, b;
lconstant hx = '0123456789ABCDEF';
lvars x = strmember( a, hx );
lvars y = strmember( b, hx );
unless x and y do
npr( 'Invalid escape sequence sent by server' );
nprintf( 'Found %%%c%c', [% a, b %] );
fast_sysexit();
endunless;
( x - 1 ) << 4 + ( y - 1 )
enddefine;
define lconstant cgi_oops();
pr( 'Content-type: text/html\n\n' );
enddefine;
define lconstant bad_request();
cgi_oops();
npr( 'Sorry, we failed to receive your request correctly. ' );
npr( 'If you try again you may be lucky. ' );
fast_sysexit();
enddefine;
define lconstant readN( nbytes ); lvars nbytes;
consstring(#|
fast_repeat fi_check( nbytes, 0, false ) times
lvars ch = charin();
if ch == termin then
bad_request()
else
ch
endif
endrepeat
|#);
enddefine;
define lconstant cgi_parse( rptr ); lvars procedure rptr;
{%
lvars state = "key";
lvars K = 0;
repeat
lvars ch = rptr();
quitif( ch == termin );
if ch == `%` then
;;; This is an escape sequence.
lvars a = rptr();
if a == termin then bad_request() endif;
lvars b = rptr();
if b == termin then bad_request() endif;
cgi_escape( a, b );
K fi_+ 1 -> K;
elseif ch == `+` then
K fi_+ 1 -> K;
` `
elseif ch == `=` then
consword( K );
0 -> K;
"value" -> state;
elseif ch == `&` then
consstring( K );
0 -> K;
"key" -> state;
else
K fi_+ 1 -> K;
ch
endif;
endrepeat;
if state == "value" then
consstring( K );
elseif state == "key" and K > 0 then
lvars s = consstring( K );
nprintf( 'Key (%p) without value', [ ^s ] );
fast_sysexit();
endif;
%}
enddefine;
define lconstant cgi_tabulate( v ); lvars v;
unless length( v ) mod 2 == 0 do
npr( 'Incorrect format for arguments' );
fast_sysexit();
endunless;
[%
lvars i;
fast_for i from 1 by 2 to length( v ) do
lvars name = v( i );
v(i+1) -> cgi_args( name );
name;
endfor;
%] -> cgi_names;
enddefine;
define lconstant cgi_prepare();
lvars m = $REQUEST_METHOD;
if m = 'POST' then
unless $CONTENT_TYPE = 'application/x-www-form-urlencoded' then
cgi_oops();
npr( 'This script can only be used to decode form results.' );
fast_sysexit(1);
endunless;
lvars nbytes = strnumber( $CONTENT_LENGTH or nullstring );
unless nbytes.isinteger do
cgi_oops();
npr( 'This server is incorrectly configured.' );
npr( 'The $CONTENT_LENGTH environment variable is not set' );
fast_sysexit();
endunless;
readN( nbytes )
elseif m = 'GET' then
$QUERY_STRING or nullstring
else
cgi_oops();
npr( 'This script should be referenced with a METHOD of POST or GET.\n' );
pr( 'If you don\'t understand this, see this ' );
pr( '<A HREF="http://www.ncsa.uiuc.edu/SDG/Software/Mosaic/Docs/fill-out-forms/overview.html">forms overview</A>.\n' );
fast_sysexit();
endif.stringin.cgi_parse.cgi_tabulate
enddefine;
define lconstant cgi_compile( file ); lvars file;
lvars chars = discin( file );
lvars line;
for line from_repeater incharline( chars ) do
quitif( isstartstring( 'exec', line ) );
endfor;
chain( chars, pop11_compile );
enddefine;
define global cgi_startup();
;;; Set some global variables.
fast_sysexit -> interrupt;
false -> poplinewidth;
false -> popmemlim;
cgi_prepare();
cgi_compile( poparglist.dest -> poparglist );
fast_sysexit();
enddefine;
;;; Garbage collect as required.
sysgarbage();
sysgarbage();
if syssave( 'script.psv' ) then
cgi_startup();
fast_sysexit();
endif;
endsection;
'EOT'
|