defmodule NervesBackdoor.Daemon do
use GenServer
@spawn_opts [:stderr_to_stdout, :binary, :stream, {:line, 255}]
# {:ok, pid} = NervesBackdoor.Daemon.start_link "/bin/daemon"
# :ok = GenServer.stop pid
def start_link(path) do
GenServer.start_link(__MODULE__, path)
end
@impl true
def init(path) do
port = run(path)
{:ok, {path, port}}
end
@impl true
def terminate(reason, _state = {path, port}) do
IO.inspect({path, :terminate, reason})
true = Port.close(port)
end
@impl true
def handle_info({_port, {:data, data}}, state = {path, _}) do
IO.inspect({path, :data, data})
{:noreply, state}
end
@impl true
def handle_info({:DOWN, _ref, :port, _port, reason}, _state = {path, _}) do
IO.inspect({path, :down, reason})
port = run(path)
{:noreply, {path, port}}
end
defp run(path) do
env = {:env, env(path)}
opts = [env | @spawn_opts]
IO.inspect({path, :run, env})
port = Port.open({:spawn_executable, path}, opts)
_ref = Port.monitor(port)
port
end
defp env(path) do
case File.read(path <> ".env") do
{:ok, data} ->
data
|> String.split("\n")
|> Enum.filter(&filter/1)
|> Enum.map(&tuple/1)
_ ->
[]
end
end
defp filter(line) do
String.contains?(line, "=")
end
defp tuple(line) do
trimmed = String.trim(line)
[n, v] = String.split(trimmed, "=", parts: 2)
{String.to_charlist(n), String.to_charlist(v)}
end
end