View source with raw comments or as raw
    1/*  Part of SWI-Prolog
    2
    3    Author:        Jan Wielemaker & Steve Prior
    4    E-mail:        J.Wielemaker@vu.nl
    5    WWW:           http://www.swi-prolog.org
    6    Copyright (c)  2004-2020, University of Amsterdam
    7                              VU University Amsterdam
    8                              CWI, Amsterdam
    9    All rights reserved.
   10
   11    Redistribution and use in source and binary forms, with or without
   12    modification, are permitted provided that the following conditions
   13    are met:
   14
   15    1. Redistributions of source code must retain the above copyright
   16       notice, this list of conditions and the following disclaimer.
   17
   18    2. Redistributions in binary form must reproduce the above copyright
   19       notice, this list of conditions and the following disclaimer in
   20       the documentation and/or other materials provided with the
   21       distribution.
   22
   23    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   24    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   25    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   26    FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   27    COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   28    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   29    BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   30    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   31    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   33    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   34    POSSIBILITY OF SUCH DAMAGE.
   35*/
   36
   37:- module(prolog_server,
   38          [ prolog_server/2             % +Port, +Options
   39          ]).   40
   41:- autoload(library(lists),[member/2]).   42:- autoload(library(socket),
   43	    [ tcp_socket/1,
   44	      tcp_setopt/2,
   45	      tcp_bind/2,
   46	      tcp_listen/2,
   47	      tcp_accept/3,
   48	      tcp_open_socket/3,
   49	      tcp_host_to_address/2
   50	    ]).
 prolog_server(?Port, +Options)
Create a TCP/IP based server on the given Port, so you can telnet into Prolog and run an interactive session. This library is intended to provide access for debugging and management of embedded servers.

Currently defined options are:

allow(IP)
Allow access from IP, a term of the format ip(A,B,C,D). Multiple of such terms can exist and access is granted if the peer IP address unifies to one of them. If no allow option is provided access is only granted from ip(127,0,0,1) (localhost).

For example:

?- prolog_server(4000, []).

% telnet localhost 4000
Welcome to the SWI-Prolog server on thread 3

1 ?-
bug
- As the connection does not involve a terminal, command history and completion are not provided. Neither are interrupts (Control-C). To terminate the Prolog shell one must enter the command "end_of_file."
   86prolog_server(Port, Options) :-
   87    tcp_socket(ServerSocket),
   88    tcp_setopt(ServerSocket, reuseaddr),
   89    tcp_bind(ServerSocket, Port),
   90    tcp_listen(ServerSocket, 5),
   91    thread_create(server_loop(ServerSocket, Options), _,
   92                  [ alias(prolog_server)
   93                  ]).
   94
   95server_loop(ServerSocket, Options) :-
   96    tcp_accept(ServerSocket, Slave, Peer),
   97    tcp_open_socket(Slave, InStream, OutStream),
   98    set_stream(InStream, close_on_abort(false)),
   99    set_stream(OutStream, close_on_abort(false)),
  100    tcp_host_to_address(Host, Peer),
  101    (   Postfix = []
  102    ;   between(2, 1000, Num),
  103        Postfix = [-, Num]
  104    ),
  105    atomic_list_concat(['client@', Host | Postfix], Alias),
  106    catch(thread_create(
  107              service_client(InStream, OutStream, Peer, Options),
  108              _,
  109              [ alias(Alias)
  110              ]),
  111          error(permission_error(create, thread, Alias), _),
  112          fail),
  113    !,
  114    server_loop(ServerSocket, Options).
  115
  116service_client(InStream, OutStream, Peer, Options) :-
  117    allow(Peer, Options),
  118    !,
  119    thread_self(Id),
  120    set_prolog_IO(InStream, OutStream, OutStream),
  121    set_stream(InStream, tty(true)),
  122    set_prolog_flag(tty_control, false),
  123    current_prolog_flag(encoding, Enc),
  124    set_stream(user_input, encoding(Enc)),
  125    set_stream(user_output, encoding(Enc)),
  126    set_stream(user_error, encoding(Enc)),
  127    set_stream(user_input, newline(detect)),
  128    set_stream(user_output, newline(dos)),
  129    set_stream(user_error, newline(dos)),
  130    format(user_error,
  131           'Welcome to the SWI-Prolog server on thread ~w~n~n',
  132           [Id]),
  133    call_cleanup(prolog,
  134                 ( close(InStream),
  135                   close(OutStream),
  136                   thread_detach(Id))).
  137service_client(InStream, OutStream, _, _):-
  138    thread_self(Id),
  139    format(OutStream, 'Go away!!~n', []),
  140    close(InStream),
  141    close(OutStream),
  142    thread_detach(Id).
  143
  144
  145allow(Peer, Options) :-
  146    (   member(allow(Allow), Options)
  147    *-> Peer = Allow,
  148        !
  149    ;   Peer = ip(127,0,0,1)
  150    )