3

I am using Lua with the luaposix library to get the the output of some commands, and sometimes send some too. I am using this code, or variants of this to do my work, but I sometimes get stuck at posix.wait(cpid) or sometimes the command doesn't seem to finish.

-- returns true on connected, else false
function wifi.wpa_supplicant_status()
    -- iw dev wlan0-1 link
    local r,w = posix.pipe()
    local cpid = posix.fork()
    if cpid == 0 then --child writes to pipe
        --close unused read end
        local devnull = posix.open("/dev/null", posix.O_RDWR)
        posix.close(r)
        posix.dup2(devnull, 0)
        posix.dup2(w, 1)
        posix.dup2(devnull, 2)
        local dir = wifi.wpa_supplicant_dir()
        local iface = posix.basename(dir)
        iface = string.gsub(iface, "wpa_supplicant%-",'')
        posix.exec('/usr/sbin/iw', {'dev', iface, 'link'})
        posix._exit(-1)
    elseif cpid > 0 then
        --parent reads from pipe, close write end
        posix.close(w)
        local buf = ''
        while true do
            local tmp = posix.read(r, 100)
            if tmp ~= nil and #tmp > 0 then
                buf = buf .. tmp
            else
                break
            end
        end
        -- TODO, check exit value, to see if entry exists or not
        while posix.wait(cpid) ~= cpid do print("waiting in wpa_supplicant_status") end
        print("status is "..buf)
        if string.find(buf, "Connected to", 1, true) then
            return true
        else
            return false
        end
    end
end

This is what I understand what I have to do(to just get output):

  1. create a single pipe

  2. fork

    • if child,

      1. close read end of pipe

      2. dup2(write_end, stdout)

      3. exec() to desired process

    • if parent

      1. close write end of pipe

      2. do blocking reads to read end of pipe, till you get a 0 byte read, which means the child process has terminated, closing the pipe

Am I missing something?

tavish
  • 61
  • 6

1 Answers1

2

You should have a look at the answers in this question How do you construct a read-write pipe with lua?

to get an idea of the difficulties to implement this. One thing that strikes me is that nobody seems to be able to get it to work with only one child process.

However, In the example you give, it seems you only want to get the output of the command, so I would suggest simply doing this:

function os.capture(cmd)
    local f = assert(io.popen(cmd, 'r'))
    local s = assert(f:read('*a'))
    f:close()
    return s
end

function wifi.wpa_supplicant_status()
    local dir = wifi.wpa_supplicant_dir()
    local iface = posix.basename(dir):gsub("wpa_supplicant%-",'')
    local cmd = ('/usr/sbin/iw dev %s link'):format(iface)
    local buf = os.capture(cmd)
    return buf:find("Connected to", 1, true) ~= nil
end

This is not even tested, but you should get the idea.

Community
  • 1
  • 1
Gilles Gregoire
  • 1,696
  • 1
  • 12
  • 14