From 31eb6c75007077404b61c0f544f4bd8cedbff5bd Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Wed, 7 Jan 2004 02:16:34 +0000 Subject: Implement kvm_getproc2(), kvm_getargv2() and kvm_getenvv2() that use the KERN_PROC2 sysctl. Based on changes from NetBSD but uses our own kvm_arg_sysctl(). --- lib/libkvm/kvm_getprocs.3 | 53 ++++++- lib/libkvm/kvm_private.h | 3 +- lib/libkvm/kvm_proc.c | 371 +++++++++++++++++++++++++++++++++++++++++----- lib/libkvm/shlib_version | 2 +- 4 files changed, 383 insertions(+), 46 deletions(-) (limited to 'lib/libkvm') diff --git a/lib/libkvm/kvm_getprocs.3 b/lib/libkvm/kvm_getprocs.3 index 1420dbde55f..e2f38f21be8 100644 --- a/lib/libkvm/kvm_getprocs.3 +++ b/lib/libkvm/kvm_getprocs.3 @@ -1,5 +1,5 @@ -.\" $OpenBSD: kvm_getprocs.3,v 1.10 2003/06/02 20:18:40 millert Exp $ -.\" $NetBSD: kvm_getprocs.3,v 1.3 1996/05/20 16:58:03 mrg Exp $ +.\" $OpenBSD: kvm_getprocs.3,v 1.11 2004/01/07 02:16:33 millert Exp $ +.\" $NetBSD: kvm_getprocs.3,v 1.13 2003/08/07 16:44:37 agc Exp $ .\" .\" Copyright (c) 1992, 1993 .\" The Regents of the University of California. All rights reserved. @@ -40,7 +40,10 @@ .Sh NAME .Nm kvm_getprocs , .Nm kvm_getargv , -.Nm kvm_getenvv +.Nm kvm_getenvv , +.Nm kvm_getproc2 , +.Nm kvm_getargv2 , +.Nm kvm_getenvv2 .Nd access user process state .Sh SYNOPSIS .Fd #include @@ -51,6 +54,12 @@ .Fn kvm_getargv "kvm_t *kd" "const struct kinfo_proc *p" "int nchr" .Ft char ** .Fn kvm_getenvv "kvm_t *kd" "const struct kinfo_proc *p" "int nchr" +.Ft struct kinfo_proc2 * +.Fn kvm_getproc2 "kvm_t *kd" "int op" "int arg" "int elemsize" "int *cnt" +.Ft char ** +.Fn kvm_getargv2 "kvm_t *kd" "const struct kinfo_proc2 *p" "int nchr" +.Ft char ** +.Fn kvm_getenvv2 "kvm_t *kd" "const struct kinfo_proc2 *p" "int nchr" .Sh DESCRIPTION .Fn kvm_getprocs returns a (sub-)set of active processes in the kernel indicated by @@ -59,8 +68,7 @@ The .Fa op and .Fa arg -arguments constitute a predicate which limits the set of processes -returned. +arguments constitute a predicate which limits the set of processes returned. The value of .Fa op describes the filtering predicate as follows: @@ -147,11 +155,44 @@ function is similar to .Fn kvm_getargv but returns the vector of environment strings. This data is also alterable by the process. +.Pp +.Fn kvm_getproc2 +is similar to +.Fn kvm_getprocs +but returns an array of +.Li kinfo_proc2 +structures. +Additionally, only the first +.Fa elemsize +bytes of each array entry are returned. +If the size of the +.Li kinfo_proc2 +structure increases in size in a future release of +.Ox , +the kernel will only return the requested amount of data for +each array entry and programs that use +.Fn kvm_getproc2 +will continue to function without the need for recompilation. +.Pp +The +.Fn kvm_getargv2 +and +.Fn kvm_getenvv2 +functions are equivalents to the +.Fn kvm_getargv +and +.Fn kvm_getenvv +functions that use a +.Li kinfo_proc2 +structure to specify the process. .Sh RETURN VALUES .Fn kvm_getprocs , .Fn kvm_getargv , -and .Fn kvm_getenvv , +.Fn kvm_getproc2 , +.Fn kvm_getargv2 , +and +.Fn kvm_getenvv2 all return .Dv NULL on failure. diff --git a/lib/libkvm/kvm_private.h b/lib/libkvm/kvm_private.h index 4b5cf8d262a..b05ac34f944 100644 --- a/lib/libkvm/kvm_private.h +++ b/lib/libkvm/kvm_private.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kvm_private.h,v 1.8 2003/06/02 20:18:41 millert Exp $ */ +/* $OpenBSD: kvm_private.h,v 1.9 2004/01/07 02:16:33 millert Exp $ */ /* $NetBSD: kvm_private.h,v 1.7 1996/05/05 04:32:15 gwr Exp $ */ /*- @@ -51,6 +51,7 @@ struct __kvm { int swfd; /* swap file (e.g., /dev/drum) */ int nlfd; /* namelist file (e.g., /vmunix) */ struct kinfo_proc *procbase; + struct kinfo_proc2 *procbase2; int nbpg; /* page size */ char *swapspc; /* (dynamic) storage for swapped pages */ char *argspc, *argbuf; /* (dynamic) storage for argv strings */ diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c index c3683e49f48..1d01e730184 100644 --- a/lib/libkvm/kvm_proc.c +++ b/lib/libkvm/kvm_proc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kvm_proc.c,v 1.19 2003/11/17 20:25:18 millert Exp $ */ +/* $OpenBSD: kvm_proc.c,v 1.20 2004/01/07 02:16:33 millert Exp $ */ /* $NetBSD: kvm_proc.c,v 1.30 1999/03/24 05:50:50 mrg Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -73,7 +73,7 @@ #if 0 static char sccsid[] = "@(#)kvm_proc.c 8.3 (Berkeley) 9/23/93"; #else -static char *rcsid = "$OpenBSD: kvm_proc.c,v 1.19 2003/11/17 20:25:18 millert Exp $"; +static char *rcsid = "$OpenBSD: kvm_proc.c,v 1.20 2004/01/07 02:16:33 millert Exp $"; #endif #endif /* LIBC_SCCS and not lint */ @@ -110,25 +110,70 @@ static char *rcsid = "$OpenBSD: kvm_proc.c,v 1.19 2003/11/17 20:25:18 millert Ex #include "kvm_private.h" +/* + * Common info from kinfo_proc and kinfo_proc2 used by helper routines. + */ +struct miniproc { + struct vmspace *p_vmspace; + char p_stat; + struct proc *p_paddr; + pid_t p_pid; +}; + +/* + * Convert from struct proc and kinfo_proc{,2} to miniproc. + */ +#define PTOMINI(kp, p) \ + do { \ + (p)->p_stat = (kp)->p_stat; \ + (p)->p_pid = (kp)->p_pid; \ + (p)->p_paddr = NULL; \ + (p)->p_vmspace = (kp)->p_vmspace; \ + } while (/*CONSTCOND*/0); + +#define KPTOMINI(kp, p) \ + do { \ + (p)->p_stat = (kp)->kp_proc.p_stat; \ + (p)->p_pid = (kp)->kp_proc.p_pid; \ + (p)->p_paddr = (kp)->kp_eproc.e_paddr; \ + (p)->p_vmspace = (kp)->kp_proc.p_vmspace; \ + } while (/*CONSTCOND*/0); + +#define KP2TOMINI(kp, p) \ + do { \ + (p)->p_stat = (kp)->p_stat; \ + (p)->p_pid = (kp)->p_pid; \ + (p)->p_paddr = (void *)(long)(kp)->p_paddr; \ + (p)->p_vmspace = (void *)(long)(kp)->p_vmspace; \ + } while (/*CONSTCOND*/0); + + +#define PTRTOINT64(foo) ((u_int64_t)(const register_t)(const void *)(foo)) + #define KREAD(kd, addr, obj) \ (kvm_read(kd, addr, (void *)(obj), sizeof(*obj)) != sizeof(*obj)) ssize_t kvm_uread(kvm_t *, const struct proc *, u_long, char *, size_t); -static char **kvm_argv(kvm_t *, const struct proc *, u_long, int, int); +static char *_kvm_ureadm(kvm_t *, const struct miniproc *, u_long, u_long *); +static ssize_t kvm_ureadm(kvm_t *, const struct miniproc *, u_long, char *, size_t); + +static char **kvm_argv(kvm_t *, const struct miniproc *, u_long, int, int); + static int kvm_deadprocs(kvm_t *, int, int, u_long, u_long, int); -static char **kvm_doargv(kvm_t *, const struct kinfo_proc *, int, +static char **kvm_doargv(kvm_t *, const struct miniproc *, int, void (*)(struct ps_strings *, u_long *, int *)); +static char **kvm_doargv2(kvm_t *, pid_t, int, int); static int kvm_proclist(kvm_t *, int, int, struct proc *, struct kinfo_proc *, int); -static int proc_verify(kvm_t *, u_long, const struct proc *); +static int proc_verify(kvm_t *, const struct miniproc *); static void ps_str_a(struct ps_strings *, u_long *, int *); static void ps_str_e(struct ps_strings *, u_long *, int *); -char * -_kvm_uread(kd, p, va, cnt) +static char * +_kvm_ureadm(kd, p, va, cnt) kvm_t *kd; - const struct proc *p; + const struct miniproc *p; u_long va; u_long *cnt; { @@ -210,6 +255,19 @@ _kvm_uread(kd, p, va, cnt) return (&kd->swapspc[offset]); } +char * +_kvm_uread(kd, p, va, cnt) + kvm_t *kd; + const struct proc *p; + u_long va; + u_long *cnt; +{ + struct miniproc mp; + + PTOMINI(p, &mp); + return (_kvm_ureadm(kd, &mp, va, cnt)); +} + /* * Read proc's from memory file into buffer bp, which has space to hold * at most maxcnt procs. @@ -375,6 +433,203 @@ kvm_deadprocs(kd, what, arg, a_allproc, a_zombproc, maxcnt) return (acnt + zcnt); } +struct kinfo_proc2 * +kvm_getproc2(kd, op, arg, esize, cnt) + kvm_t *kd; + int op, arg; + size_t esize; + int *cnt; +{ + size_t size; + int mib[6], st, nprocs; + struct user user; + + if (esize < 0) + return NULL; + + if (kd->procbase2 != NULL) { + free(kd->procbase2); + /* + * Clear this pointer in case this call fails. Otherwise, + * kvm_close() will free it again. + */ + kd->procbase2 = 0; + } + + if (ISALIVE(kd)) { + size = 0; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC2; + mib[2] = op; + mib[3] = arg; + mib[4] = esize; + mib[5] = 0; + st = sysctl(mib, 6, NULL, &size, NULL, 0); + if (st == -1) { + _kvm_syserr(kd, kd->program, "kvm_getproc2"); + return NULL; + } + + mib[5] = size / esize; + kd->procbase2 = (struct kinfo_proc2 *)_kvm_malloc(kd, size); + if (kd->procbase2 == 0) + return NULL; + st = sysctl(mib, 6, kd->procbase2, &size, NULL, 0); + if (st == -1) { + _kvm_syserr(kd, kd->program, "kvm_getproc2"); + return NULL; + } + nprocs = size / esize; + } else { + char *kp2c; + struct kinfo_proc *kp; + struct kinfo_proc2 kp2, *kp2p; + int i; + + kp = kvm_getprocs(kd, op, arg, &nprocs); + if (kp == NULL) + return NULL; + + kd->procbase2 = _kvm_malloc(kd, nprocs * esize); + kp2c = (char *)kd->procbase2; + kp2p = &kp2; + for (i = 0; i < nprocs; i++, kp++) { + memset(kp2p, 0, sizeof(kp2)); + kp2p->p_forw = PTRTOINT64(kp->kp_proc.p_forw); + kp2p->p_back = PTRTOINT64(kp->kp_proc.p_back); + kp2p->p_paddr = PTRTOINT64(kp->kp_eproc.e_paddr); + + kp2p->p_addr = PTRTOINT64(kp->kp_proc.p_addr); + kp2p->p_fd = PTRTOINT64(kp->kp_proc.p_fd); + kp2p->p_stats = PTRTOINT64(kp->kp_proc.p_stats); + kp2p->p_limit = PTRTOINT64(kp->kp_proc.p_limit); + kp2p->p_vmspace = PTRTOINT64(kp->kp_proc.p_vmspace); + kp2p->p_sigacts = PTRTOINT64(kp->kp_proc.p_sigacts); + kp2p->p_sess = PTRTOINT64(kp->kp_eproc.e_sess); + kp2p->p_tsess = 0; + kp2p->p_ru = PTRTOINT64(kp->kp_proc.p_ru); + + kp2p->p_eflag = 0; + kp2p->p_exitsig = kp->kp_proc.p_exitsig; + kp2p->p_flag = kp->kp_proc.p_flag; + + kp2p->p_pid = kp->kp_proc.p_pid; + + kp2p->p_ppid = kp->kp_eproc.e_ppid; +#if 0 + kp2p->p_sid = kp->kp_eproc.e_sid; +#else + kp2p->p_sid = -1; /* XXX */ +#endif + kp2p->p__pgid = kp->kp_eproc.e_pgid; + + kp2p->p_tpgid = -1; + + kp2p->p_uid = kp->kp_eproc.e_ucred.cr_uid; + kp2p->p_ruid = kp->kp_eproc.e_pcred.p_ruid; + kp2p->p_gid = kp->kp_eproc.e_ucred.cr_gid; + kp2p->p_rgid = kp->kp_eproc.e_pcred.p_rgid; + + memcpy(kp2p->p_groups, kp->kp_eproc.e_ucred.cr_groups, + MIN(sizeof(kp2p->p_groups), sizeof(kp->kp_eproc.e_ucred.cr_groups))); + kp2p->p_ngroups = kp->kp_eproc.e_ucred.cr_ngroups; + + kp2p->p_jobc = kp->kp_eproc.e_jobc; + kp2p->p_tdev = kp->kp_eproc.e_tdev; + kp2p->p_tpgid = kp->kp_eproc.e_tpgid; + kp2p->p_tsess = PTRTOINT64(kp->kp_eproc.e_tsess); + + kp2p->p_estcpu = kp->kp_proc.p_estcpu; + kp2p->p_rtime_sec = kp->kp_proc.p_estcpu; + kp2p->p_rtime_usec = kp->kp_proc.p_estcpu; + kp2p->p_cpticks = kp->kp_proc.p_cpticks; + kp2p->p_pctcpu = kp->kp_proc.p_pctcpu; + kp2p->p_swtime = kp->kp_proc.p_swtime; + kp2p->p_slptime = kp->kp_proc.p_slptime; + kp2p->p_schedflags = kp->kp_proc.p_schedflags; + + kp2p->p_uticks = kp->kp_proc.p_uticks; + kp2p->p_sticks = kp->kp_proc.p_sticks; + kp2p->p_iticks = kp->kp_proc.p_iticks; + + kp2p->p_tracep = PTRTOINT64(kp->kp_proc.p_tracep); + kp2p->p_traceflag = kp->kp_proc.p_traceflag; + + kp2p->p_holdcnt = kp->kp_proc.p_holdcnt; + + kp2p->p_siglist = kp->kp_proc.p_siglist; + kp2p->p_sigmask = kp->kp_proc.p_sigmask; + kp2p->p_sigignore = kp->kp_proc.p_sigignore; + kp2p->p_sigcatch = kp->kp_proc.p_sigcatch; + + kp2p->p_stat = kp->kp_proc.p_stat; + kp2p->p_priority = kp->kp_proc.p_priority; + kp2p->p_usrpri = kp->kp_proc.p_usrpri; + kp2p->p_nice = kp->kp_proc.p_nice; + + kp2p->p_xstat = kp->kp_proc.p_xstat; + kp2p->p_acflag = kp->kp_proc.p_acflag; + + strncpy(kp2p->p_comm, kp->kp_proc.p_comm, + MIN(sizeof(kp2p->p_comm), sizeof(kp->kp_proc.p_comm))); + + strncpy(kp2p->p_wmesg, kp->kp_eproc.e_wmesg, sizeof(kp2p->p_wmesg)); + kp2p->p_wchan = PTRTOINT64(kp->kp_proc.p_wchan); + + strncpy(kp2p->p_login, kp->kp_eproc.e_login, sizeof(kp2p->p_login)); + + kp2p->p_vm_rssize = kp->kp_eproc.e_xrssize; + kp2p->p_vm_tsize = kp->kp_eproc.e_vm.vm_tsize; + kp2p->p_vm_dsize = kp->kp_eproc.e_vm.vm_dsize; + kp2p->p_vm_ssize = kp->kp_eproc.e_vm.vm_ssize; + + kp2p->p_eflag = kp->kp_eproc.e_flag; + + if (P_ZOMBIE(&kp->kp_proc) || kp->kp_proc.p_addr == NULL || + KREAD(kd, (u_long)kp->kp_proc.p_addr, &user)) { + kp2p->p_uvalid = 0; + } else { + kp2p->p_uvalid = 1; + + kp2p->p_ustart_sec = user.u_stats.p_start.tv_sec; + kp2p->p_ustart_usec = user.u_stats.p_start.tv_usec; + + kp2p->p_uutime_sec = user.u_stats.p_ru.ru_utime.tv_sec; + kp2p->p_uutime_usec = user.u_stats.p_ru.ru_utime.tv_usec; + kp2p->p_ustime_sec = user.u_stats.p_ru.ru_stime.tv_sec; + kp2p->p_ustime_usec = user.u_stats.p_ru.ru_stime.tv_usec; + + kp2p->p_uru_maxrss = user.u_stats.p_ru.ru_maxrss; + kp2p->p_uru_ixrss = user.u_stats.p_ru.ru_ixrss; + kp2p->p_uru_idrss = user.u_stats.p_ru.ru_idrss; + kp2p->p_uru_isrss = user.u_stats.p_ru.ru_isrss; + kp2p->p_uru_minflt = user.u_stats.p_ru.ru_minflt; + kp2p->p_uru_majflt = user.u_stats.p_ru.ru_majflt; + kp2p->p_uru_nswap = user.u_stats.p_ru.ru_nswap; + kp2p->p_uru_inblock = user.u_stats.p_ru.ru_inblock; + kp2p->p_uru_oublock = user.u_stats.p_ru.ru_oublock; + kp2p->p_uru_msgsnd = user.u_stats.p_ru.ru_msgsnd; + kp2p->p_uru_msgrcv = user.u_stats.p_ru.ru_msgrcv; + kp2p->p_uru_nsignals = user.u_stats.p_ru.ru_nsignals; + kp2p->p_uru_nvcsw = user.u_stats.p_ru.ru_nvcsw; + kp2p->p_uru_nivcsw = user.u_stats.p_ru.ru_nivcsw; + + kp2p->p_uctime_sec = user.u_stats.p_cru.ru_utime.tv_sec + + user.u_stats.p_cru.ru_stime.tv_sec; + kp2p->p_uctime_usec = user.u_stats.p_cru.ru_utime.tv_usec + + user.u_stats.p_cru.ru_stime.tv_usec; + } + + memcpy(kp2c, &kp2, esize); + kp2c += esize; + } + + free(kd->procbase); + } + *cnt = nprocs; + return (kd->procbase2); +} + struct kinfo_proc * kvm_getprocs(kd, op, arg, cnt) kvm_t *kd; @@ -477,10 +732,6 @@ _kvm_realloc(kd, p, n) return (np); } -#ifndef MAX -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#endif - /* * Read in an argument vector from the user address space of process p. * addr if the user-space base address of narg null-terminated contiguous @@ -490,7 +741,7 @@ _kvm_realloc(kd, p, n) static char ** kvm_argv(kd, p, addr, narg, maxcnt) kvm_t *kd; - const struct proc *p; + const struct miniproc *p; u_long addr; int narg; int maxcnt; @@ -535,7 +786,7 @@ kvm_argv(kd, p, addr, narg, maxcnt) return (0); } cc = sizeof(char *) * narg; - if (kvm_uread(kd, p, addr, (char *)kd->argv, cc) != cc) + if (kvm_ureadm(kd, p, addr, (char *)kd->argv, cc) != cc) return (0); ap = np = kd->argspc; argv = kd->argv; @@ -546,7 +797,7 @@ kvm_argv(kd, p, addr, narg, maxcnt) while (argv < kd->argv + narg && *argv != 0) { addr = (u_long)*argv & ~(kd->nbpg - 1); if (addr != oaddr) { - if (kvm_uread(kd, p, addr, kd->argbuf, kd->nbpg) != + if (kvm_ureadm(kd, p, addr, kd->argbuf, kd->nbpg) != kd->nbpg) return (0); oaddr = addr; @@ -630,10 +881,9 @@ ps_str_e(p, addr, n) * being wrong are very low. */ static int -proc_verify(kd, kernp, p) +proc_verify(kd, p) kvm_t *kd; - u_long kernp; - const struct proc *p; + const struct miniproc *p; { struct proc kernproc; @@ -641,7 +891,7 @@ proc_verify(kd, kernp, p) * Just read in the whole proc. It's not that big relative * to the cost of the read system call. */ - if (kvm_read(kd, kernp, &kernproc, sizeof(kernproc)) != + if (kvm_read(kd, (u_long)p->p_paddr, &kernproc, sizeof(kernproc)) != sizeof(kernproc)) return (0); return (p->p_pid == kernproc.p_pid && @@ -649,13 +899,12 @@ proc_verify(kd, kernp, p) } static char ** -kvm_doargv(kd, kp, nchr, info) +kvm_doargv(kd, p, nchr, info) kvm_t *kd; - const struct kinfo_proc *kp; + const struct miniproc *p; int nchr; void (*info)(struct ps_strings *, u_long *, int *); { - const struct proc *p = &kp->kp_proc; char **ap; u_long addr; int cnt; @@ -678,7 +927,7 @@ kvm_doargv(kd, kp, nchr, info) * Pointers are stored at the top of the user stack. */ if (p->p_stat == SZOMB || - kvm_uread(kd, p, (u_long)ps, (char *)&arginfo, + kvm_ureadm(kd, p, (u_long)ps, (char *)&arginfo, sizeof(arginfo)) != sizeof(arginfo)) return (0); @@ -689,14 +938,13 @@ kvm_doargv(kd, kp, nchr, info) /* * For live kernels, make sure this process didn't go away. */ - if (ap != 0 && ISALIVE(kd) && - !proc_verify(kd, (u_long)kp->kp_eproc.e_paddr, p)) + if (ap != 0 && ISALIVE(kd) && !proc_verify(kd, p)) ap = 0; return (ap); } static char ** -kvm_arg_sysctl(kvm_t *kd, const struct kinfo_proc *kp, int nchr, int env) +kvm_arg_sysctl(kvm_t *kd, pid_t pid, int nchr, int env) { int mib[4]; size_t len, orglen; @@ -712,7 +960,7 @@ kvm_arg_sysctl(kvm_t *kd, const struct kinfo_proc *kp, int nchr, int env) again: mib[0] = CTL_KERN; mib[1] = KERN_PROC_ARGS; - mib[2] = (int)kp->kp_proc.p_pid; + mib[2] = (int)pid; mib[3] = env ? KERN_PROC_ENV : KERN_PROC_ARGV; len = orglen; @@ -750,9 +998,12 @@ kvm_getargv(kd, kp, nchr) const struct kinfo_proc *kp; int nchr; { + struct miniproc p; + if (ISALIVE(kd)) - return (kvm_arg_sysctl(kd, kp, nchr, 0)); - return (kvm_doargv(kd, kp, nchr, ps_str_a)); + return (kvm_arg_sysctl(kd, kp->kp_proc.p_pid, nchr, 0)); + KPTOMINI(kp, &p); + return (kvm_doargv(kd, &p, nchr, ps_str_a)); } char ** @@ -761,18 +1012,49 @@ kvm_getenvv(kd, kp, nchr) const struct kinfo_proc *kp; int nchr; { + struct miniproc p; + + if (ISALIVE(kd)) + return (kvm_arg_sysctl(kd, kp->kp_proc.p_pid, nchr, 1)); + KPTOMINI(kp, &p); + return (kvm_doargv(kd, &p, nchr, ps_str_e)); +} + +char ** +kvm_getargv2(kd, kp, nchr) + kvm_t *kd; + const struct kinfo_proc2 *kp; + int nchr; +{ + struct miniproc p; + if (ISALIVE(kd)) - return (kvm_arg_sysctl(kd, kp, nchr, 1)); - return (kvm_doargv(kd, kp, nchr, ps_str_e)); + return (kvm_arg_sysctl(kd, kp->p_pid, nchr, 0)); + KP2TOMINI(kp, &p); + return (kvm_doargv(kd, &p, nchr, ps_str_a)); +} + +char ** +kvm_getenvv2(kd, kp, nchr) + kvm_t *kd; + const struct kinfo_proc2 *kp; + int nchr; +{ + struct miniproc p; + + if (ISALIVE(kd)) + return (kvm_arg_sysctl(kd, kp->p_pid, nchr, 1)); + KP2TOMINI(kp, &p); + return (kvm_doargv(kd, &p, nchr, ps_str_e)); } /* * Read from user space. The user context is given by p. */ -ssize_t -kvm_uread(kd, p, uva, buf, len) +static ssize_t +kvm_ureadm(kd, p, uva, buf, len) kvm_t *kd; - const struct proc *p; + const struct miniproc *p; u_long uva; char *buf; size_t len; @@ -781,21 +1063,34 @@ kvm_uread(kd, p, uva, buf, len) cp = buf; while (len > 0) { - int cc; + size_t cc; char *dp; u_long cnt; - dp = _kvm_uread(kd, p, uva, &cnt); + dp = _kvm_ureadm(kd, p, uva, &cnt); if (dp == 0) { _kvm_err(kd, 0, "invalid address (%lx)", uva); return (0); } - cc = MIN(cnt, len); + cc = (size_t)MIN(cnt, len); bcopy(dp, cp, cc); - cp += cc; uva += cc; len -= cc; } return (ssize_t)(cp - buf); } + +ssize_t +kvm_uread(kd, p, uva, buf, len) + kvm_t *kd; + const struct proc *p; + u_long uva; + char *buf; + size_t len; +{ + struct miniproc mp; + + PTOMINI(p, &mp); + return (kvm_ureadm(kd, &mp, uva, buf, len)); +} diff --git a/lib/libkvm/shlib_version b/lib/libkvm/shlib_version index 5b844bbf422..b39addfcc64 100644 --- a/lib/libkvm/shlib_version +++ b/lib/libkvm/shlib_version @@ -1,2 +1,2 @@ major=7 -minor=0 +minor=1 -- cgit v1.2.3