[racket] Sandbox, in a module, with a *shared* environment but *separate* I/O
Tony,
You probably want to look at make-eval-factory and
make-base-eval-factory. They are in scribble/eval rather than
racket/sandbox, I think mostly as a quirk of history.
Carl Eastlund
On Thu, Oct 27, 2011 at 7:32 PM, Tony Garnock-Jones <tonyg at ccs.neu.edu> wrote:
> I've managed to kludge together a solution that seems to do what I want.
> It seems that it's a shared *namespace* instance I want, with a fresh
> evaluator for each connection, and the only (?) control over namespaces
> for sandboxes is via sandbox-namespace-specs. It isn't the most elegant,
> but here's the code:
>
> ;;---
> #lang racket/base
>
> (require racket/tcp)
> (require racket/sandbox)
>
> (define e (make-base-namespace))
>
> (define (shell in out)
> (printf "Accepted\n")
> (fprintf out "Hello.\n")
> (parameterize ((current-input-port in)
> (current-output-port out)
> (current-error-port out)
> (sandbox-input in)
> (sandbox-output out)
> (sandbox-error-output out)
> (current-namespace e)
> (sandbox-namespace-specs (list (lambda () e))))
> (parameterize ((current-eval (make-evaluator '(begin))))
> (read-eval-print-loop))
> (fprintf out "\nGoodbye!\n")
> (close-input-port in)
> (close-output-port out)))
>
> (define s (tcp-listen 2322 4 #t))
> (printf "Accepting...\n")
> (let loop ()
> (define-values (i o) (tcp-accept s))
> (thread (lambda ()
> (shell i o)))
> (loop))
> ;;---
>
> Any suggestions people have for improving that are very welcome.
>
> Regards,
> Tony
>
> On 2011-10-27 3:45 PM, Tony Garnock-Jones wrote:
>> Hi all,
>>
>> The example TCP-listening sandboxed REPLs given nearish the top of
>> http://docs.racket-lang.org/reference/Sandboxed_Evaluation.html differ
>> slightly: the one that only works from the toplevel shares a namespace
>> and evaluator between all the connections, but the one that works from a
>> module uses a fresh namespace and evaluator for each connection.
>>
>> How can I set things up so that
>>
>> - a single "global environment" is shared between all connections, but
>> - each connection gets its own input and output ports, connected
>> to the socket?
>>
>> I'd like to be able to connect in one terminal, say "(define x 123)",
>> then connect in another terminal and have "x" result in "123". I'd also
>> like "(display 'hello)" to print to the issuing terminal rather than
>> going only to one or the other.
>>
>> Does this sound like a familiar problem? Have others solved this before?
>> I feel like I'm missing something about the distinction between
>> namespaces and evaluators...
>>
>> Regards,
>> Tony