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

前端 未结 5 1977
隐瞒了意图╮
隐瞒了意图╮ 2020-12-09 14:01

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 i

相关标签:
5条回答
  • 2020-12-09 14:24

    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.

    0 讨论(0)
  • 2020-12-09 14:35

    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 e.g. 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

    0 讨论(0)
  • 2020-12-09 14:38

    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.

    0 讨论(0)
  • 2020-12-09 14:43

    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.

    0 讨论(0)
  • 2020-12-09 14:45

    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.

    0 讨论(0)
提交回复
热议问题