0

I'm trying to convert some piece of code to Swift that will list all running processes. But since it requires calling some C specific APIs I'm a bit struggling. Can someone tell me here what am I doing here incorrectly? print statement at the end is outputting incorrect values. I assume it should be process name. Also line info = malloc(length) gives me the creeps. How should I properly allocate it?

var maxArgumentsSize: Int = 0
if maxArgumentsSize == 0 {
    var size: size_t = MemoryLayout<Int>.size
    var mib: [Int32] = [CTL_KERN, KERN_ARGMAX]
    let a = sysctl(&mib, 2, &maxArgumentsSize, &size, nil, 0)
    if a == -1 {
        maxArgumentsSize = 4096;
    }
}

var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_ALL]
var info: UnsafeMutableRawPointer? = nil
var length: size_t = 0
var count: Int = 0

if sysctl(&mib, 3, nil, &length, nil, 0) < 0 {
    exit(EXIT_FAILURE)
}

info = malloc(length)

if sysctl(&mib, 3, info, &length, nil, 0) < 0 {
    free(info)
    exit(EXIT_FAILURE)
}

count = length / MemoryLayout<kinfo_proc>.size
for index in 0...count {
    let info = info?.assumingMemoryBound(to: kinfo_proc.self)
    let pid: pid_t = info![index].kp_proc.p_pid
    let buffer = UnsafeMutablePointer<CChar>.allocate(capacity: maxArgumentsSize)
    var mib: [Int32] = [CTL_KERN, KERN_PROCARGS2, pid]
    if sysctl(&mib, 3, buffer, &maxArgumentsSize, nil, 0) == 0 {
        let str = String(cString: buffer, encoding: .utf8)
        print(str)
    }
    free(buffer);
}
Thunder
  • 611
  • 1
  • 8
  • 25
  • Don't post a bunch of code and ask "what am I doing wrong?" Let us know, in detail, what isn't working. Are you getting compiler errors. If so, on what line(s)? Is it crashing? If so, on what line, and with what exact error message? – Duncan C Jan 18 '23 at 15:16
  • 1
    Possibly helpful: https://stackoverflow.com/a/72445381/1187415 – Martin R Jan 18 '23 at 15:23
  • @DuncanC sorry, modified the question. – Thunder Jan 18 '23 at 16:22
  • @MartinR thanks I'll look into that, modified the question as well to be more clear. – Thunder Jan 18 '23 at 17:06

1 Answers1

1

Basically I've changed my initial code to this and calling @MartinR solution (https://stackoverflow.com/a/72445381/1187415) at the end. Of course it's not complete and pasted from my code directly but it's working.

// Get all processess information:
var name: [CInt] = [CTL_KERN, KERN_PROC, KERN_PROC_ALL]
var length: size_t = 0
if sysctl(&name, CUnsignedInt(name.count), nil, &length, nil, 0) < 0 {
    return
}
var infoPtr = UnsafeMutableRawPointer.allocate(
    byteCount: length,
    alignment: MemoryLayout<kinfo_proc>.alignment
)
if sysctl(&name, CUnsignedInt(name.count), infoPtr, &length, nil, 0) < 0 {
    infoPtr.deallocate()
    return
}
let count = length / MemoryLayout<kinfo_proc>.size
for index in 0...count {
    let info = infoPtr.assumingMemoryBound(to: kinfo_proc.self)
    let pid: pid_t = info[index].kp_proc.p_pid
    let arguments = self.processArguments(pid: pid)
}
infoPtr.deallocate()
Thunder
  • 611
  • 1
  • 8
  • 25
  • 2
    See https://stackoverflow.com/a/62801035/1187415 for a slightly simpler implementation of the “get all process information” part. – Martin R Jan 18 '23 at 19:33