diff --git a/process_darwin.h b/process_darwin.h index c7742ef..87bd1b0 100644 --- a/process_darwin.h +++ b/process_darwin.h @@ -5,7 +5,10 @@ #include #include -#include +#include +#include +#include +#include // This is declared in process_darwin.go extern void go_darwin_append_proc(pid_t, pid_t, char *); @@ -17,50 +20,41 @@ extern void go_darwin_append_proc(pid_t, pid_t, char *); // be possible to do this all in Go, I didn't want to go spelunking through // header files to get all the structures properly. It is much easier to just // call it in C and be done with it. + static inline int darwinProcesses() { - int err = 0; - int i = 0; - static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 }; - size_t length = 0; - struct kinfo_proc *result = NULL; - size_t resultCount = 0; - // Get the length first - err = sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, - NULL, &length, NULL, 0); - if (err != 0) { - goto ERREXIT; - } + uid_t euid = geteuid(); - // Allocate the appropriate sized buffer to read the process list - result = malloc(length); + int pid_buf_size = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0); + int pid_count = pid_buf_size / sizeof(pid_t); - // Call sysctl again with our buffer to fill it with the process list - err = sysctl((int*)name, (sizeof(name) / sizeof(*name)) - 1, - result, &length, - NULL, 0); - if (err != 0) { - goto ERREXIT; - } + pid_t* pids = malloc(pid_buf_size); + bzero(pids, pid_buf_size); - resultCount = length / sizeof(struct kinfo_proc); - for (i = 0; i < resultCount; i++) { - struct kinfo_proc *single = &result[i]; - go_darwin_append_proc( - single->kp_proc.p_pid, - single->kp_eproc.e_ppid, - single->kp_proc.p_comm); - } + proc_listpids(PROC_ALL_PIDS, 0, pids, pid_buf_size); + char path_buffer[PROC_PIDPATHINFO_MAXSIZE]; -ERREXIT: - if (result != NULL) { - free(result); + int ppid = 0; + + for (int i=0; i < pid_count; i++) { + if (pids[i] == 0) break; + + if (euid == 0) { + // You need root permission to get proc_bsdinfo from some processes. + // When you call following function with normal user permission you will + // receive 'operation not permitted' error and it will be terminated. + struct proc_bsdinfo bsdinfo; + proc_pidinfo(pids[i], PROC_PIDTBSDINFO, 0, &bsdinfo, sizeof(struct proc_bsdinfo)); + ppid = bsdinfo.pbi_ppid; } - if (err != 0) { - return errno; + bzero(path_buffer, PROC_PIDPATHINFO_MAXSIZE); + if (proc_pidpath(pids[i], path_buffer, sizeof(path_buffer)) > 0) { + go_darwin_append_proc(pids[i], ppid, path_buffer); } - return 0; -} + } + free(pids); + return 0; +} #endif