With the help of SO, I wrote an app that displays all open TCP/UDP connections in Swift. In the next step, I would like to get the process that opened the connection (pretty much as lsof does).
Since lsof is open source, I could write the following code to get all the open files for a process:
Bridging-Header:
#include <mach/mach_types.h>
#include <mach/vm_param.h>
#include <mach/host_info.h>
#include <mach/task_info.h>
#include <mach/thread_info.h>
#include <mach/vm_region.h>
#include <libproc.h>
#include <sys/proc_info.h>
#include <sys/kdebug.h>
#include <sys/msgbuf.h>
(I don't think every include is needed, but at least it compiles for now).
for app in NSWorkspace.shared().runningApplications
{
let pid = app.processIdentifier
var tai = proc_taskallinfo()
let size = MemoryLayout<proc_bsdinfo>.size
var result = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &tai, Int32(size))
let fileCount: Int32 = Int32(tai.pbsd.pbi_nfiles)
if result <= 0
{
if errno == ENOMEM
{
Swift.print("Out of memory.")
}
Swift.print(errno)
continue
}
var fid = proc_fdinfo()
let fdInfoSize = MemoryLayout<proc_fdinfo>.size
result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, &fid, Int32(fdInfoSize) * fileCount)
if result <= 0
{
Swift.print("Error. No Files?")
}
else
{
Swift.print("Files found.")
}
}
The code was ported from C to Swift 3. The original C code looks like this:
int nb;
struct proc_taskallinfo tai;
...
nb = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &tai, sizeof(tai));
When I run my code, I get the errno 12 (Out of memory). Why?
P.S. I know that the second proc_pidinfo will also fail because a pointer to an array of proc_fdinfo is returned and not a pointer to a single struct, but one step at a time. It's all about the errno 12.
There are two errors. First, it should be
let size = MemoryLayout<proc_taskallinfo>.size
Second, the proc_pidinfo(pid, PROC_PIDLISTFDS, ...)
expects a buffer
with room for fileCount
structures of type proc_fdinfo
, not just
a single one:
var fid = Array(repeating: proc_fdinfo(), count: Int(fileCount))
let fdInfoSize = MemoryLayout<proc_fdinfo>.stride
result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, &fid, Int32(fdInfoSize) * fileCount)