Get other process' argv in OS X using C
Asked Answered
G

2

5

I want to get other process' argv like ps.

I'm using Mac OS X 10.4.11 running on Intel or PowerPC.

First, I read code of ps and man kvm, then I wrote some C code.

#include <kvm.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#include <paths.h>

int
main(void) {
    char errbuf[1024];
    kvm_t *kd = kvm_openfiles(_PATH_DEVNULL, NULL, _PATH_DEVNULL, O_RDONLY, errbuf);
    int num_procs;
    if (!kd) { fprintf(stderr, "kvm_openfiles failed : %s\n", errbuf); return 0; }
    struct kinfo_proc *proc_table = kvm_getprocs(kd, KERN_PROC_ALL, 0, &num_procs);

    for (int i = 0; i < num_procs; i++) {
        struct kinfo_proc *pproc = &proc_table[i];
        char **proc_argv = kvm_getargv(kd, pproc, 0);
        printf("%p\n", proc_argv);
    }

    kvm_close(kd);
    return 0;
}

When ran on PowerPC, kvm_getargv() always returned NULL. When ran on Intel, kvm_openfiles() failed with error /dev/mem: No such file or directory.

Of cource, I know about permission.

Second, I tried sysctl.

#include <sys/sysctl.h>
#include <stdio.h>
#include <stdlib.h>
#define pid_of(pproc) pproc->kp_proc.p_pid

int
main(void) {

   int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0 };
   int buffer_size;
   sysctl(mib, 4, NULL, &buffer_size, NULL, 0);

   struct kinfo_proc *result = malloc(buffer_size);
   sysctl(mib, 4, result, &buffer_size, NULL, 0);

   int num_procs = buffer_size / sizeof(struct kinfo_proc);
   for (int i = 0; i < num_procs; i++) {
       struct kinfo_proc *pproc = result + i;
       int mib[3] = { CTL_KERN, KERN_PROCARGS, pid_of(pproc) }; // KERN_PROC_ARGS is not defined
       char *proc_argv;
       int argv_len;
       sysctl(mib, 3, NULL, &argv_len, NULL, 0);
       proc_argv = malloc(sizeof(char) * argv_len);
       sysctl(mib, 3, proc_argv, &argv_len, NULL, 0);
       fwrite(proc_argv, sizeof(char), argv_len, stdout);
       printf("\n");
       free(proc_argv);
   }

   return 0;
}

By fwrite, I got argv[0] but argv[1..] are not (environment variables are printed out.)

There is no more way to do it?

Gazo answered 16/10, 2008 at 21:34 Comment(3)
What are you trying to do ? You can attach to the process as a debugger but that's the only valid reason to subvert security.Harrold
I want to treat working processes as data. I see, security is important. but then, why ps can access argv? I also can parse output of ps, but I want whole argv.Gazo
KERN_PROCARGS includes the environment variables in it's output, you need to use KERN_PROCARGS2 which only includes argv.Nettle
G
7

In 10.6, KERN_PROCARGS2 is available: https://gist.github.com/770696

This way is used from ps, procfs on MacFUSE, etc.

Gazo answered 8/1, 2011 at 8:58 Comment(1)
really good example of using sysctl. I just want to mention that there's a comment in that file that says "There is no way to deterministically know where the command arguments end and the environment strings start", but it returns the argc so you know to stop processing after you read argc strings.Nettle
G
4

I've actually been needing the same thing for a Python library I'm writing, and in my searching I came across another Python lib (PSI) that implements this in C code. It's part of the python module code for listing processes and includes listing the arguments for each process as well. You could take a look at the source code for that for a working example:

darwin_process.c - scroll down to set_exe() for the relevant code

Note: the site is really slow so you'll have to be a bit patient while it loads.

Gynaeco answered 17/10, 2008 at 0:27 Comment(3)
Thanks, Jay. I tried again with browsing and copying your code, I got argv!Gazo
That link is broken; the file no longer exists. I spent a while browsing around the project's source, and what it boils down to is that they're using 'sysctl'. The current location of that code is in src/arch/darwin_process.c. Hope that helps anyone else who comes across this question.Bach
The relevant link with code seems to return 502 – Bad Gateway error, @jay. If possible, please fix it, since answers to many later questions point at this post. Thanks.Thud

© 2022 - 2024 — McMap. All rights reserved.