Talking to Executables in Erlang.

Joe Williams - - December 19, 2008

Lately I have been working on a TCP server that works similar to D. J. Bernstein’s ucspi-tcp. Basically, it is a TCP server that sits in front of a executable of some sort and plays a middleman between the TCP client and the actual code that is performing functions on the data sent to the TCP server. More on ucspi-tcp in later post(s). The first portion of my TCP server code can be found here and blog post here. The portion of code for today is for sending and receiving messages to/from the executable in Erlang. This is done using an Erlang port, the Erlang docs have a good interoperability tutorial that should help anyone start out.

erl_portc.erl

-module(erl_portc).
-export([start/1, call_port/1, init/1, port_loop/1]).

start(Cmd) ->
% spawn a process connected to the executable
spawn(?MODULE, init, [Cmd]).

init(Cmd) ->
% register it and set things up
register(port, self()),
process_flag(trap_exit, true),
Port = open_port({spawn, Cmd}, []),
port_loop(Port).

call_port(Msg) ->
% send messages to the executable
port ! {call, self(), Msg},
receive
{port, Result} ->
Result
end.

port_loop(Port) ->
% recieve results from the executable
receive
{call, Caller, Msg} ->
Port ! {self(), {command, Msg}},
receive
{Port, {data, Data}} ->
Caller ! {port, Data};
stop ->
Port ! {self(), close},
receive
{Port, closed} ->
exit(normal)
end;
{’EXIT’, Port, Reason} ->
exit(port_terminated)
end,
port_loop(Port)
end.

Here is an example of its usage using DJB’s qmail-smtpd executable.

[joe@box01 ~]$ erl
Erlang (BEAM) emulator version 5.6.3 [source] [smp:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.6.3 (abort with ^G)
1> erl_portc:start(’/var/qmail/bin/qmail-smtpd’).
<0.32.0>
2> erl_portc:call_port(””).
“220 mail.someaddress.com ESMTP\r\n”
3> erl_portc:call_port(”HELO mail.someaddress.com\r\n”).
“250 mail.someaddress.com\r\n”
4> erl_portc:call_port(”MAIL FROM: joe@someaddress.com\r\n”).
“250 ok\r\n”
5> erl_portc:call_port(”RCPT TO: joe@someaddress.com\r\n”).
CHKUSER accepted rcpt: from remote rcpt : found existing recipient
“250 ok\r\n”
6> erl_portc:call_port(”DATA\r\n”).
“354 go ahead\r\n”
7> erl_portc:call_port(”Subject: TEST123\r\n.\r\n”).
“250 ok 1229721933 qp 10176\r\n”
8> erl_portc:call_port(”QUIT\r\n”).
“221 mail.someaddress.com\r\n”

Shortly after running the above directives I received an email in my inbox with the subject “TEST123″. So it seems to be interfacing with the executable properly.

As with most of the code on this blog, this example can be checked out from subversion and viewed in WebSVN. Enjoy!



Categories: Blogs  Joe Williams  

Comments

No comments so far, you could be the first.

Add comment

Name:

Email:

URL:

Smileys

Remember my personal information

Notify me of follow-up comments?