简体   繁体   中英

How to programatically get uid from pid in osx using c++?

Given a pid, I want to find the owner of the process (as uid). Is there a way to get this in osx (or any unix) using C++?

Google didn't help. 'ps' is able to do it; so I assume there should be a way to get it programatically.

Solution from Indhu helped me on my way, so I would like to post my own.

UID from PID with pure C:

#include <sys/sysctl.h>

uid_t uidFromPid(pid_t pid)
{
    uid_t uid = -1;

    struct kinfo_proc process;
    size_t procBufferSize = sizeof(process);

    // Compose search path for sysctl. Here you can specify PID directly.
    const u_int pathLenth = 4;
    int path[pathLenth] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};

    int sysctlResult = sysctl(path, pathLenth, &process, &procBufferSize, NULL, 0);

    // If sysctl did not fail and process with PID available - take UID.
    if ((sysctlResult == 0) && (procBufferSize != 0))
    {
        uid = process.kp_eproc.e_ucred.cr_uid;
    }

    return uid;
}

No excess allocation, no loops.

The source for the ps command, reveals that there is a function called get_proc_stats defined in proc/readproc.h that (among other things) returns the real user name(UID) & Effective user name(EUID) for a given pid.

You need to do install libproc-dev to get this function. and then you can do:

#include <proc/readproc.h>
void printppid(pid_t pid) 
{
    proc_t process_info;
    get_proc_stats(pid, &process_info);
    printf("Real user of the process[%d] is [%s]\n", pid, process_info.ruser);
}

compile it with gcc the-file.c -lproc .

Once you have the real user name you can use getpwnam() and getgrnam() functions to get the uid.

You could look at how ps does it . It looks like it uses the kvm_getprocs function.

However, it's much more portable (you said "any unix", but eg the Linux and Solaris way is to look in the /proc filesystem - and other unixes may have different APIs) to just parse the output of ps ( ps -o user= -p (pid) for example, to eliminate any extraneous output) than to do any system-specific process stuff

There's not a portable way to do this. On Mac OS, you've got to use poorly documented sysctl interfaces: see this previous stackoverflow question . (As other commenters pointed out, on Linux you can use proc. On FreeBSD, you should be able to use kvm_getfiles , although this is not available on Mac OS.)

Your best bet is to use the source for Apple's ps as a jumping-off point for grabbing process data and then you'll be able to use getpwuid(3) once you have the uid.

Finally found a way to programatically do this without parsing the output of 'ps'

uint getUidUsingSysctl(uint pid)
{
    struct kinfo_proc *sProcesses = NULL, *sNewProcesses;
    int    aiNames[4];
    size_t iNamesLength;
    int    i, iRetCode, iNumProcs;
    size_t iSize;

    iSize = 0;
    aiNames[0] = CTL_KERN;
    aiNames[1] = KERN_PROC;
    aiNames[2] = KERN_PROC_ALL;
    aiNames[3] = 0;
    iNamesLength = 3;

    iRetCode = sysctl(aiNames, iNamesLength, NULL, &iSize, NULL, 0);

    /* allocate memory and populate info in the  processes structure */
    do
    {
        iSize += iSize / 10;
        sNewProcesses = (kinfo_proc *)realloc(sProcesses, iSize);

        if (sNewProcesses == 0)
        {
            if (sProcesses)
                free(sProcesses);
            /* could not realloc memory, just return */
            return -1;
        }
        sProcesses = sNewProcesses;
        iRetCode = sysctl(aiNames, iNamesLength, sProcesses, &iSize, NULL, 0);
    } while (iRetCode == -1 && errno == ENOMEM);

    iNumProcs = iSize / sizeof(struct kinfo_proc);

    for (i = 0; i < iNumProcs; i++)
    {
        if (sProcesses[i].kp_proc.p_pid == pid) 
        {
            return sProcesses[i].kp_eproc.e_ucred.cr_uid;
        }

    }

    /* clean up and return to the caller */
    free(sProcesses);

    return -1;
}

Note: There might be a better way to get 'kinfo_proc' instead of iterating through all process.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM