[erlang-questions] open_port confusing (concerning qmail-inject) UPDATE

Kevin <>
Thu Apr 30 04:48:50 CEST 2009



Kevin q2h46uw02-at-sneakemail.com |erlang| wrote:
> Hello, qmail-inject is just a command line program that takes a message 
> from stdin and dumps it into the mail queue
>
> example to deliver a very short message to :
>
> prompt> echo "subject:it worked" | qmail-inject 
>
>
> If successful it exits with a code of 0, all other numbers are errors.
>
>
> I'm writing an erlang function that will eventually, **line-by-line**, 
> feed a message to qmail-inject.
>
> Here is my attempt:
>
> start() ->
>
>     From = "",
>     To = "",
>     Command = "/var/qmail/bin/qmail-inject -a -f " ++ From ++ " " ++ To,
>     Port = open_port({spawn, Command}, [stream, exit_status]),
>
>     Port ! {self(), {command, "Subject:It worked!\n"}},
>     Port ! {self(), {command, "From:\n"}},
>     Port ! {self(), {command, "To:\n"}},
>     Port ! {self(), close},
>
>     receive
>         {Port, {exit_status, 0}} -> %% exited without a result
>             {ok, worked};
>         {Port, {exit_status, R}} -> %% dig program missing?
>             {error, inject_error, R};
>         Unknown -> Unknown
>     end.
>
>
> I was confused by the docs for port_command and port_close so I just 
> stuck with the standard erlang message passing.
>
> It works fine, but because I'm a little obsessive and I tried hiding the 
> qmail-inject program by renaming it and breaking the whole thing.
>
> By playing around I figured out the behavior of a broken command:
>
> 14> open_port({spawn, "/asdf"}, [stream, exit_status]).             
> #Port<0.444>
> 15> flush().                                          
> Shell got {#Port<0.444>,{exit_status,126}}
>
> Ok, so I now see I can received the message of a broken command.
>
> And here is a successful command:
>
> 16> open_port({spawn, "/usr/local/bin/date"}, [stream, exit_status]).
> #Port<0.445>
> 17> flush().                                                        
> Shell got {#Port<0.445>,{data,"Wed Apr 29 18:56:27 EDT 2009\n"}}
> Shell got {#Port<0.445>,{exit_status,0}}
> ok
>
>
> But with a command like qmail-inject, there is nothing to flush until 
> the message is finished, and I'm assuming it will
> be sent when send it a close signal.  And with all this flushing, is 
> there a chance of a race condition?
>
> 17> open_port({spawn, "/usr/local/bin/date"}, [stream, exit_status]).
> #Port<0.1830>
> 18> flush().
> ok
> 19>
>
> So how do I tell if the port successfully opened to a waiting 
> qmail-inject without blocking on a message that will only
> come until after I fed it the message and closed the port?  And then be 
> certain that the qmail-inject program returned
> a success code of 0?  And avoid race conditions?
>
> I would take my grandma 5 minutes to figure out how to open a pipe to a 
> command line program in a scripting language like perl or ruby, but here 
> I don't even know if I'm going in the right direction.
>
> Thanks for any help,
> Kevin
>
>
>
>
>
> _______________________________________________
> erlang-questions mailing list
> 
> http://www.erlang.org/mailman/listinfo/erlang-questions
>
>   

I'm beginning to thing there is no solution to this other than writing a 
wrapper for qmail-inject.  The main problem
is that, according to my research, there is no way to tell qmail-inject 
that it has reached the "end of file" without
port_close(Port), which, when called, will prevent any exit codes from 
being sent, so I'll never know if qmail-inject
succeeded.

-ks










More information about the erlang-questions mailing list