Subject: Re: [SWIPL] HELP-Calling prolog from CGI scripts

From: "Michael A. Covington" <[email-masked]>
Date: Wed, 11 Jul 2001 13:26:45 -0400

Below are some files documenting how I got SWI working as a CGI engine under
Windows 2000.  Some things will be different under UNIX, of course.
----------------------------------------------------------------------------
------
How to enable SWI-Prolog CGI scripts under Windows 2000

(We will use file names ending in .swi for these.)

(0) Make sure you have installed SWI-Prolog version 4.05 or later.

    (NOTE: Skip this step for now.  I *think* all my examples work under
4.00.)

(1) Go to Settings, Control Panel, Administrative Tools, Internet Services
Manager.

(2) Double-click on the name of your machine, click on [+] as needed to open
up subtrees,
    right-click on the Scripts directory and choose Properties.

(3) The "Virtual Directory" tab should be displayed.  If not, bring it to
the front.

(4) Click "Configuration".

    This opens up a list of kinds of script files and how to execute them.
    Note for example that ".pl", late in the list, is for Perl scripts.

(5) Add an entry with:

    Executable:   "c:\Program Files\pl\bin\plcon.exe" -q -t halt -g start -f
%s -- %s

           That means: Load the file whose name is passed to you
(represented by the
                       first %s); and execute '?- start.'; and then halt
rather than
                       starting a Prolog toplevel.

                       The second %s represents the CGI query string, if
any, and
                       is accessible to the program as a command line
argument.

                       NOTE:  Because it is in the toplevel, '?- halt.' will
                       execute whether '?- start.' succeeds, fails, or
crashes.

           NOTE: You can add more command line arguments, to specify stack
size and
                       the like.  Put them before the final "-- %s".

    Extension:    .swi

    Verbs:        GET,POST

    Check "Script Engine"

    Check "Check That File Exists"

    For documentation about all of this, see:

http://www.windows.com/windows2000/en/server/iis/default.asp?url=/windows200
0/en/server/iis/htm/core/iiwarndf.htm

(6) You can now put Prolog programs in your \inetpub\scripts directory, with
names
    ending in .swi, and SWI-Prolog will load and run them, using "start" as
the
    toplevel goal.

    Note that in order to read POST input, the Prolog program must first
retrieve
    the environment variable CONTENT_LENGTH and then accept that number of
characters
    from standard input.  It cannot simply read until end of file because
present
    versions of SWI-Prolog cannot detect eof on standard input.

----------------------------------------------------------------------------
------

% This file is c:\inetpub\scripts\swicgi.pl

% It is a very simple CGI script in SWI Prolog.
% It receives input from a form
% via the POST method and (in this version)
% just echoes it back to the user.

% main procedure

start :-
  write('Content-type: text/html'),nl,
  nl,
  write('<HTML>'),nl,
  write('<TITLE>An SWI CGI Sample</TITLE>'),nl,
  write('<BODY>'),nl,
  write('The data you submitted on the CGI form was:'),nl,
  write('<PRE>'),nl,
  input_post_string(S),     % read the POST data
  output_string(S),
  write('</PRE>'),nl,
  write('</BODY>'),nl,
  write('</HTML>'),nl.

% input_post_string(-String)
%   Accepts a line of input as an Edinburgh string (list of ASCII codes).
%   Does not print the '|:' prompt before accepting input.
%   Uses CONTENT_LENGTH (from the environment) to determine how
%   many characters to read, since SWI Prolog cannot detect end of
%   file on standard input.

input_post_string(String) :-
    getenv('CONTENT_LENGTH',NS),   % NS is an atom like '21' for 21
    atom_to_term(NS,N,_),          % so convert it to number
    !,
    prompt1(''),                   % suppress the '|:' prompt
    input_n_string(N,String).      % and now read N characters

input_post_string([]).    % if there was no CONTENT_LENGTH value, there's no
content

input_n_string(0,[]) :- !.

input_n_string(N,[C|Chars]) :- get0(C), NN is N-1, input_n_string(NN,Chars).

% output_string(+String)
%   Outputs an Edinburgh string to stdout.

output_string([First|Rest]) :-
   put(First),
   output_string(Rest).

output_string([]).