psutil_proc_oneshot_info(PyObject *self, PyObject *args) {
    long pid;
    long rss;
    long vms;
    long memtext;
    long memdata;
    long memstack;
    int oncpu;
    kinfo_proc kp;
    long pagesize = sysconf(_SC_PAGESIZE);
    char str[1000];
    PyObject *py_name;
    PyObject *py_retlist;

    if (! PyArg_ParseTuple(args, "l", &pid))
        return NULL;
    if (psutil_kinfo_proc(pid, &kp) == -1)
        return NULL;

    // Process
#ifdef PSUTIL_FREEBSD
    sprintf(str, "%s", kp.ki_comm);
#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD)
    sprintf(str, "%s", kp.p_comm);
#endif
    py_name = PyUnicode_DecodeFSDefault(str);
    if (! py_name) {
        // Likely a decoding error. We don't want to fail the whole
        // operation. The python module may retry with proc_name().
        PyErr_Clear();
        py_name = Py_None;
    }
    // Py_INCREF(py_name);

    // Calculate memory.
#ifdef PSUTIL_FREEBSD
    rss = (long)kp.ki_rssize * pagesize;
    vms = (long)kp.ki_size;
    memtext = (long)kp.ki_tsize * pagesize;
    memdata = (long)kp.ki_dsize * pagesize;
    memstack = (long)kp.ki_ssize * pagesize;
#else
    rss = (long)kp.p_vm_rssize * pagesize;
    #ifdef PSUTIL_OPENBSD
        // VMS, this is how ps determines it on OpenBSD:
        // https://github.com/openbsd/src/blob/
        //     588f7f8c69786211f2d16865c552afb91b1c7cba/bin/ps/print.c#L505
        vms = (long)(kp.p_vm_dsize + kp.p_vm_ssize + kp.p_vm_tsize) * pagesize;
    #elif PSUTIL_NETBSD
        // VMS, this is how top determines it on NetBSD:
        // https://github.com/IIJ-NetBSD/netbsd-src/blob/master/external/
        //     bsd/top/dist/machine/m_netbsd.c
        vms = (long)kp.p_vm_msize * pagesize;
    #endif
        memtext = (long)kp.p_vm_tsize * pagesize;
        memdata = (long)kp.p_vm_dsize * pagesize;
        memstack = (long)kp.p_vm_ssize * pagesize;
#endif

#ifdef PSUTIL_FREEBSD
    // what CPU we're on; top was used as an example:
    // https://svnweb.freebsd.org/base/head/usr.bin/top/machine.c?
    //     view=markup&pathrev=273835
    // XXX - note: for "intr" PID this is -1.
    if (kp.ki_stat == SRUN && kp.ki_oncpu != NOCPU)
        oncpu = kp.ki_oncpu;
    else
        oncpu = kp.ki_lastcpu;
#else
    // On Net/OpenBSD we have kp.p_cpuid but it appears it's always
    // set to KI_NOCPU. Even if it's not, ki_lastcpu does not exist
    // so there's no way to determine where "sleeping" processes
    // were. Not supported.
    oncpu = -1;
#endif

    // Return a single big tuple with all process info.
    py_retlist = Py_BuildValue(
        "(lillllllidllllddddlllllbO)",
#ifdef PSUTIL_FREEBSD
        //
        (long)kp.ki_ppid,                // (long) ppid
        (int)kp.ki_stat,                 // (int) status
        // UIDs
        (long)kp.ki_ruid,                // (long) real uid
        (long)kp.ki_uid,                 // (long) effective uid
        (long)kp.ki_svuid,               // (long) saved uid
        // GIDs
        (long)kp.ki_rgid,                // (long) real gid
        (long)kp.ki_groups[0],           // (long) effective gid
        (long)kp.ki_svuid,               // (long) saved gid
        //
        kp.ki_tdev,                      // (int) tty nr
        PSUTIL_TV2DOUBLE(kp.ki_start),   // (double) create time
        // ctx switches
        kp.ki_rusage.ru_nvcsw,           // (long) ctx switches (voluntary)
        kp.ki_rusage.ru_nivcsw,          // (long) ctx switches (unvoluntary)
        // IO count
        kp.ki_rusage.ru_inblock,         // (long) read io count
        kp.ki_rusage.ru_oublock,         // (long) write io count
        // CPU times: convert from micro seconds to seconds.
        PSUTIL_TV2DOUBLE(kp.ki_rusage.ru_utime),     // (double) user time
        PSUTIL_TV2DOUBLE(kp.ki_rusage.ru_stime),     // (double) sys time
        PSUTIL_TV2DOUBLE(kp.ki_rusage_ch.ru_utime),  // (double) children utime
        PSUTIL_TV2DOUBLE(kp.ki_rusage_ch.ru_stime),  // (double) children stime
        // memory
        rss,                              // (long) rss
        vms,                              // (long) vms
        memtext,                          // (long) mem text
        memdata,                          // (long) mem data
        memstack,                         // (long) mem stack
        // others
        oncpu,                            // (int) the CPU we are on
#elif defined(PSUTIL_OPENBSD) || defined(PSUTIL_NETBSD)
        //
        (long)kp.p_ppid,                 // (long) ppid
        (int)kp.p_stat,                  // (int) status
        // UIDs
        (long)kp.p_ruid,                 // (long) real uid
        (long)kp.p_uid,                  // (long) effective uid
        (long)kp.p_svuid,                // (long) saved uid
        // GIDs
        (long)kp.p_rgid,                 // (long) real gid
        (long)kp.p_groups[0],            // (long) effective gid
        (long)kp.p_svuid,                // (long) saved gid
        //
        kp.p_tdev,                       // (int) tty nr
        PSUTIL_KPT2DOUBLE(kp.p_ustart),  // (double) create time
        // ctx switches
        kp.p_uru_nvcsw,                  // (long) ctx switches (voluntary)
        kp.p_uru_nivcsw,                 // (long) ctx switches (unvoluntary)
        // IO count
        kp.p_uru_inblock,                // (long) read io count
        kp.p_uru_oublock,                // (long) write io count
        // CPU times: convert from micro seconds to seconds.
        PSUTIL_KPT2DOUBLE(kp.p_uutime),  // (double) user time
        PSUTIL_KPT2DOUBLE(kp.p_ustime),  // (double) sys time
        // OpenBSD and NetBSD provide children user + system times summed
        // together (no distinction).
        kp.p_uctime_sec + kp.p_uctime_usec / 1000000.0,  // (double) ch utime
        kp.p_uctime_sec + kp.p_uctime_usec / 1000000.0,  // (double) ch stime
        // memory
        rss,                              // (long) rss
        vms,                              // (long) vms
        memtext,                          // (long) mem text
        memdata,                          // (long) mem data
        memstack,                         // (long) mem stack
        // others
        oncpu,                            // (int) the CPU we are on
#endif
        py_name                           // (pystr) name
    );

    Py_DECREF(py_name);
    return py_retlist;
}