#!/usr/bin/env perl # repl — evaluate Lisp forms against the running Passepartout daemon # Usage: repl # or: echo '' | repl # # Connects to the daemon on 127.0.0.1:9105, sends a repl-eval request # via the framed TCP protocol, reads and prints the response. use strict; use warnings; use IO::Socket::INET; my $HOST = $ENV{PASSEPARTOUT_HOST} || "127.0.0.1"; my $PORT = $ENV{PASSEPARTOUT_PORT} || "9105"; my $TIMEOUT = $ENV{PASSEPARTOUT_REPL_TIMEOUT} || 10; my $expr = join(" ", @ARGV); if (!$expr) { $expr = do { local $/; }; } chomp($expr); # Quote the expression for embedding in a Lisp string $expr =~ s/\\/\\\\/g; # backslash → doubled $expr =~ s/"/\\"/g; # " → \" if (!$expr) { die "Usage: repl \n or: echo '(+ 1 2)' | repl\n"; } my $sock = IO::Socket::INET->new( PeerHost => $HOST, PeerPort => $PORT, Proto => "tcp", Timeout => $TIMEOUT ) or die "Cannot connect to $HOST:$PORT: $!\n"; sub read_frame { my ($sock) = @_; my $hex; $sock->read($hex, 6) or return undef; my $len = hex($hex); my $content; $sock->read($content, $len); return $content; } sub write_frame { my ($sock, $content) = @_; my $len = sprintf("%06X", length($content)); $sock->send($len . $content); } # Read handshake (discard) my $handshake = read_frame($sock); # Build framed message my $msg = '(:TYPE :EVENT :PAYLOAD (:SENSOR :repl-eval :CODE "' . $expr . '"))'; write_frame($sock, $msg); # Read response my $response = read_frame($sock); if (defined $response) { if ($response eq "") { print STDERR "Daemon returned empty response\n"; exit 1; } if ($response =~ /:VALUE "([^"]*)"/s) { print "$1\n"; } elsif ($response =~ /:message "([^"]*)"/s) { print STDERR "$1\n"; exit 1; } else { print "Response: $response\n"; } } else { print STDERR "No response from daemon (is it running on $HOST:$PORT?)\n"; exit 1; } $sock->close();