It was pointed out that as long as we're breaking anything that's using
KERN_PROC, struct kinfo_proc, or kvm_get(procs|argv|envv), there really
isn't any reason to not change those APIs to the new forms. I.e.,
kvm_getprocs() gains another arguments (elemsize) and the struct
kinfo_proc that it returns changes to what is currently known as struct
kinfo_proc2. A #define for kinfo_proc2 and a few wrapper functions later
and nothing using the existing *2 functions or structures is broken but
we're prepped for getting rid of the ugly names instead of enshrining
them.
Tree builds cleanly with this. This doesn't switch all the in-tree
KERN_PROC2 and kvm_getproc2() callers over KERN_PROC and kvm_getprocs(),
in part to make sure the wrappers work cleanly and in part to keep this
diff down to the core required bits. Once this is in, those callers can
be switched at will (and kvm_proc.c can be simplified further, etc).
oks?
Philip Guenther
Index: sys/sys/sysctl.h
===================================================================
RCS file: /cvs/src/sys/sys/sysctl.h,v
retrieving revision 1.106
diff -u -p -r1.106 sysctl.h
--- sys/sys/sysctl.h 19 Aug 2010 18:14:13 -0000 1.106
+++ sys/sys/sysctl.h 29 Oct 2010 07:49:06 -0000
@@ -42,9 +42,7 @@
* These are for the eproc structure defined below.
*/
#ifndef _KERNEL
-#include <sys/time.h>
-#include <sys/ucred.h>
-#include <sys/proc.h>
+#include <sys/proc.h> /* for SRUN, SIDL, etc */
#include <sys/resource.h>
#endif
@@ -126,9 +124,7 @@ struct ctlname {
#define KERN_HOSTID 11 /* int: host identifier */
#define KERN_CLOCKRATE 12 /* struct: struct clockinfo */
#define KERN_VNODE 13 /* struct: vnode structures */
-#if defined(_KERNEL) || defined(_LIBKVM)
-#define KERN_PROC 14 /* struct: process entries */
-#endif
+/*define gap: was KERN_PROC 14 */
#define KERN_FILE 15 /* struct: file entries */
#define KERN_PROF 16 /* node: kernel profiling info
*/
#define KERN_POSIX1 17 /* int: POSIX.1 version */
@@ -180,7 +176,8 @@ struct ctlname {
#define KERN_INTRCNT 63 /* node: interrupt counters */
#define KERN_WATCHDOG 64 /* node: watchdog */
#define KERN_EMUL 65 /* node: emuls */
-#define KERN_PROC2 66 /* struct: process entries */
+#define KERN_PROC 66 /* struct: process entries */
+#define KERN_PROC2 KERN_PROC /* backwards compat
name */
#define KERN_MAXCLUSTERS 67 /* number of mclusters */
#define KERN_EVCOUNT 68 /* node: event counters */
#define KERN_TIMECOUNTER 69 /* node: timecounter */
@@ -207,7 +204,7 @@ struct ctlname {
{ "hostid", CTLTYPE_INT }, \
{ "clockrate", CTLTYPE_STRUCT }, \
{ "vnode", CTLTYPE_STRUCT }, \
- { "proc", CTLTYPE_STRUCT }, \
+ { "gap", 0 }, \
{ "file", CTLTYPE_STRUCT }, \
{ "profiling", CTLTYPE_NODE }, \
{ "posix1version", CTLTYPE_INT }, \
@@ -259,7 +256,7 @@ struct ctlname {
{ "intrcnt", CTLTYPE_NODE }, \
{ "watchdog", CTLTYPE_NODE }, \
{ "emul", CTLTYPE_NODE }, \
- { "proc2", CTLTYPE_STRUCT }, \
+ { "proc", CTLTYPE_STRUCT }, \
{ "maxclusters", CTLTYPE_INT }, \
{ "evcount", CTLTYPE_NODE }, \
{ "timecounter", CTLTYPE_NODE }, \
@@ -308,43 +305,7 @@ struct ctlname {
#define KERN_PROC_NENV 4
/*
- * KERN_PROC subtype ops return arrays of augmented proc structures:
- */
-struct kinfo_proc {
- struct proc kp_proc; /* proc structure */
- struct eproc {
- struct proc *e_paddr; /* address of proc */
- struct session *e_sess; /* session pointer */
- struct pcred e_pcred; /* process credentials */
- struct ucred e_ucred; /* current credentials */
- struct vmspace e_vm; /* address space */
- struct pstats e_pstats; /* process stats */
- int e_pstats_valid; /* pstats valid? */
- pid_t e_ppid; /* parent process id */
- pid_t e_pgid; /* process group id */
- short e_jobc; /* job control counter */
- dev_t e_tdev; /* controlling tty dev */
- pid_t e_tpgid; /* tty process group id */
- struct session *e_tsess; /* tty session pointer */
-#define WMESGLEN 7
- char e_wmesg[WMESGLEN+1]; /* wchan message */
- segsz_t e_xsize; /* text size */
- short e_xrssize; /* text rss */
- short e_xccount; /* text references */
- short e_xswrss;
- long e_flag;
-#define EPROC_CTTY 0x01 /* controlling tty vnode active */
-#define EPROC_SLEADER 0x02 /* session leader */
- char e_login[MAXLOGNAME]; /* setlogin() name */
-#define EMULNAMELEN 7
- char e_emul[EMULNAMELEN+1]; /* syscall emulation name */
- rlim_t e_maxrss;
- struct plimit *e_limit;
- } kp_eproc;
-};
-
-/*
- * KERN_PROC2 subtype ops return arrays of relatively fixed size
+ * KERN_PROC subtype ops return arrays of relatively fixed size
* structures of process info. Use 8 byte alignment, and new
* elements should only be added to the end of this structure so
* binary compatibility can be preserved.
@@ -357,7 +318,10 @@ struct kinfo_proc {
#define KI_NOCPU (~(u_int64_t)0)
-struct kinfo_proc2 {
+struct kinfo_proc {
+#ifndef kinfo_proc2
+#define kinfo_proc2 kinfo_proc
+#endif
u_int64_t p_forw; /* PTR: linked run/sleep queue. */
u_int64_t p_back;
u_int64_t p_paddr; /* PTR: address of proc */
@@ -372,7 +336,9 @@ struct kinfo_proc2 {
u_int64_t p_tsess; /* PTR: tty session pointer */
u_int64_t p_ru; /* PTR: Exit information. XXX */
- int32_t p_eflag; /* LONG: extra kinfo_proc2 flags */
+ int32_t p_eflag; /* LONG: extra kinfo_proc flags */
+#define EPROC_CTTY 0x01 /* controlling tty vnode active */
+#define EPROC_SLEADER 0x02 /* session leader */
int32_t p_exitsig; /* INT: signal to sent to parent on
exit */
int32_t p_flag; /* INT: P_* flags. */
@@ -476,11 +442,11 @@ struct kinfo_proc2 {
#if defined(_KERNEL) || defined(_LIBKVM)
/*
- * Macros for filling in the bulk of a kinfo_proc2 structure, used
- * in the kernel to implement the KERN_PROC2 sysctl and in userland
+ * Macros for filling in the bulk of a kinfo_proc structure, used
+ * in the kernel to implement the KERN_PROC sysctl and in userland
* in libkvm to implement reading from kernel crashes. The macro
* arguments are all pointers; by name they are:
- * kp - target kinfo_proc2 structure
+ * kp - target kinfo_proc structure
* copy_str - a function or macro invoked as copy_str(dst,src,maxlen)
* that has strlcpy or memcpy semantics; the destination is
* pre-filled with zeros
@@ -501,7 +467,7 @@ struct kinfo_proc2 {
#define PTRTOINT64(_x) ((u_int64_t)(u_long)(_x))
-#define FILL_KPROC2(kp, copy_str, p, pr, pc, uc, pg, paddr, praddr, sess, vm,
lim, ps) \
+#define FILL_KPROC(kp, copy_str, p, pr, pc, uc, pg, paddr, praddr, sess, vm,
lim, ps) \
do { \
memset((kp), 0, sizeof(*(kp))); \
\
@@ -956,12 +922,10 @@ int sysctl_doprof(int *, u_int, void *,
#endif
int sysctl_dopool(int *, u_int, char *, size_t *);
-void fill_eproc(struct proc *, struct eproc *);
-
void fill_file2(struct kinfo_file2 *, struct file *, struct filedesc *,
int, struct vnode *, struct proc *, struct proc *);
-void fill_kproc2(struct proc *, struct kinfo_proc2 *);
+void fill_kproc(struct proc *, struct kinfo_proc *);
int kern_sysctl(int *, u_int, void *, size_t *, void *, size_t,
struct proc *);
Index: sys/kern/kern_sysctl.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sysctl.c,v
retrieving revision 1.193
diff -u -p -r1.193 kern_sysctl.c
--- sys/kern/kern_sysctl.c 23 Sep 2010 13:24:22 -0000 1.193
+++ sys/kern/kern_sysctl.c 29 Oct 2010 07:49:07 -0000
@@ -274,7 +274,6 @@ kern_sysctl(int *name, u_int namelen, vo
if (namelen != 1) {
switch (name[0]) {
case KERN_PROC:
- case KERN_PROC2:
case KERN_PROF:
case KERN_MALLOCSTATS:
case KERN_TTY:
@@ -361,8 +360,7 @@ kern_sysctl(int *name, u_int namelen, vo
return (sysctl_vnode(oldp, oldlenp, p));
#ifndef SMALL_KERNEL
case KERN_PROC:
- case KERN_PROC2:
- return (sysctl_doproc(name, namelen, oldp, oldlenp));
+ return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
case KERN_PROC_ARGS:
return (sysctl_proc_args(name + 1, namelen - 1, oldp, oldlenp,
p));
@@ -1317,42 +1315,33 @@ sysctl_file2(int *name, u_int namelen, c
/*
* try over estimating by 5 procs
*/
-#define KERN_PROCSLOP (5 * sizeof (struct kinfo_proc))
+#define KERN_PROCSLOP 5
int
sysctl_doproc(int *name, u_int namelen, char *where, size_t *sizep)
{
- struct kinfo_proc2 *kproc2 = NULL;
- struct eproc *eproc = NULL;
+ struct kinfo_proc *kproc = NULL;
struct proc *p;
struct process *pr;
char *dp;
int arg, buflen, doingzomb, elem_size, elem_count;
- int error, needed, type, op;
+ int error, needed, op;
dp = where;
buflen = where != NULL ? *sizep : 0;
needed = error = 0;
- type = name[0];
- if (type == KERN_PROC) {
- if (namelen != 3 && !(namelen == 2 &&
- (name[1] == KERN_PROC_ALL || name[1] == KERN_PROC_KTHREAD)))
- return (EINVAL);
- op = name[1];
- arg = op == KERN_PROC_ALL ? 0 : name[2];
- elem_size = elem_count = 0;
- eproc = malloc(sizeof(struct eproc), M_TEMP, M_WAITOK);
- } else /* if (type == KERN_PROC2) */ {
- if (namelen != 5 || name[3] < 0 || name[4] < 0 ||
- name[3] > sizeof(*kproc2))
- return (EINVAL);
- op = name[1];
- arg = name[2];
- elem_size = name[3];
- elem_count = name[4];
- kproc2 = malloc(sizeof(struct kinfo_proc2), M_TEMP, M_WAITOK);
- }
+ if (namelen != 4 || name[2] < 0 || name[3] < 0 ||
+ name[2] > sizeof(*kproc))
+ return (EINVAL);
+ op = name[0];
+ arg = name[1];
+ elem_size = name[2];
+ elem_count = name[3];
+
+ if (where != NULL)
+ kproc = malloc(sizeof(*kproc), M_TEMP, M_WAITOK);
+
p = LIST_FIRST(&allproc);
doingzomb = 0;
again:
@@ -1412,47 +1401,26 @@ again:
if (p->p_flag & P_SYSTEM)
continue;
break;
+
case KERN_PROC_KTHREAD:
/* no filtering */
break;
+
default:
error = EINVAL;
goto err;
}
- if (type == KERN_PROC) {
- if (buflen >= sizeof(struct kinfo_proc)) {
- fill_eproc(p, eproc);
- error = copyout((caddr_t)p,
- &((struct kinfo_proc *)dp)->kp_proc,
- sizeof(struct proc));
- if (error)
- goto err;
- error = copyout((caddr_t)eproc,
- &((struct kinfo_proc *)dp)->kp_eproc,
- sizeof(*eproc));
- if (error)
- goto err;
- dp += sizeof(struct kinfo_proc);
- buflen -= sizeof(struct kinfo_proc);
- }
- needed += sizeof(struct kinfo_proc);
- } else /* if (type == KERN_PROC2) */ {
- if (buflen >= elem_size && elem_count > 0) {
- fill_kproc2(p, kproc2);
- /*
- * Copy out elem_size, but not larger than
- * the size of a struct kinfo_proc2.
- */
- error = copyout(kproc2, dp,
- min(sizeof(*kproc2), elem_size));
- if (error)
- goto err;
- dp += elem_size;
- buflen -= elem_size;
- elem_count--;
- }
- needed += elem_size;
+
+ if (buflen >= elem_size && elem_count > 0) {
+ fill_kproc(p, kproc);
+ error = copyout(kproc, dp, elem_size);
+ if (error)
+ goto err;
+ dp += elem_size;
+ buflen -= elem_size;
+ elem_count--;
}
+ needed += elem_size;
}
if (doingzomb == 0) {
p = LIST_FIRST(&zombproc);
@@ -1466,86 +1434,27 @@ again:
goto err;
}
} else {
- needed += KERN_PROCSLOP;
+ needed += KERN_PROCSLOP * elem_size;
*sizep = needed;
}
err:
- if (eproc)
- free(eproc, M_TEMP);
- if (kproc2)
- free(kproc2, M_TEMP);
+ if (kproc)
+ free(kproc, M_TEMP);
return (error);
}
/*
- * Fill in an eproc structure for the specified process.
- */
-void
-fill_eproc(struct proc *p, struct eproc *ep)
-{
- struct tty *tp;
-
- ep->e_paddr = p;
- ep->e_sess = p->p_p->ps_pgrp->pg_session;
- ep->e_pcred = *p->p_cred;
- ep->e_ucred = *p->p_ucred;
- if (p->p_stat == SIDL || P_ZOMBIE(p)) {
- ep->e_vm.vm_rssize = 0;
- ep->e_vm.vm_tsize = 0;
- ep->e_vm.vm_dsize = 0;
- ep->e_vm.vm_ssize = 0;
- bzero(&ep->e_pstats, sizeof(ep->e_pstats));
- ep->e_pstats_valid = 0;
- } else {
- struct vmspace *vm = p->p_vmspace;
-
- ep->e_vm.vm_rssize = vm_resident_count(vm);
- ep->e_vm.vm_tsize = vm->vm_tsize;
- ep->e_vm.vm_dsize = vm->vm_dused;
- ep->e_vm.vm_ssize = vm->vm_ssize;
- ep->e_pstats = *p->p_stats;
- ep->e_pstats_valid = 1;
- }
- if (p->p_p->ps_pptr)
- ep->e_ppid = p->p_p->ps_pptr->ps_pid;
- else
- ep->e_ppid = 0;
- ep->e_pgid = p->p_p->ps_pgrp->pg_id;
- ep->e_jobc = p->p_p->ps_pgrp->pg_jobc;
- if ((p->p_p->ps_flags & PS_CONTROLT) &&
- (tp = ep->e_sess->s_ttyp)) {
- ep->e_tdev = tp->t_dev;
- ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
- ep->e_tsess = tp->t_session;
- } else
- ep->e_tdev = NODEV;
- ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
- if (SESS_LEADER(p->p_p))
- ep->e_flag |= EPROC_SLEADER;
- strncpy(ep->e_wmesg, p->p_wmesg ? p->p_wmesg : "", WMESGLEN);
- ep->e_wmesg[WMESGLEN] = '\0';
- ep->e_xsize = ep->e_xrssize = 0;
- ep->e_xccount = ep->e_xswrss = 0;
- strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME-1);
- ep->e_login[MAXLOGNAME-1] = '\0';
- strncpy(ep->e_emul, p->p_emul->e_name, EMULNAMELEN);
- ep->e_emul[EMULNAMELEN] = '\0';
- ep->e_maxrss = p->p_rlimit ? p->p_rlimit[RLIMIT_RSS].rlim_cur : 0;
- ep->e_limit = p->p_p->ps_limit;
-}
-
-/*
- * Fill in a kproc2 structure for the specified process.
+ * Fill in a kproc structure for the specified process.
*/
void
-fill_kproc2(struct proc *p, struct kinfo_proc2 *ki)
+fill_kproc(struct proc *p, struct kinfo_proc *ki)
{
struct process *pr = p->p_p;
struct session *s = pr->ps_session;
struct tty *tp;
struct timeval ut, st;
- FILL_KPROC2(ki, strlcpy, p, pr, p->p_cred, p->p_ucred, pr->ps_pgrp,
+ FILL_KPROC(ki, strlcpy, p, pr, p->p_cred, p->p_ucred, pr->ps_pgrp,
p, pr, s, p->p_vmspace, pr->ps_limit, p->p_stats);
/* stuff that's too painful to generalize into the macros */
Index: include/kvm.h
===================================================================
RCS file: /cvs/src/include/kvm.h,v
retrieving revision 1.14
diff -u -p -r1.14 kvm.h
--- include/kvm.h 7 Jun 2009 03:09:34 -0000 1.14
+++ include/kvm.h 29 Oct 2010 07:49:07 -0000
@@ -54,24 +54,19 @@ __BEGIN_DECLS
typedef struct __kvm kvm_t;
struct kinfo_proc;
-struct kinfo_proc2;
int kvm_close(kvm_t *);
int kvm_dump_inval(kvm_t *);
int kvm_dump_mkheader(kvm_t *, off_t);
int kvm_dump_wrtheader(kvm_t *, FILE *, int);
char **kvm_getargv(kvm_t *, const struct kinfo_proc *, int);
-char **kvm_getargv2(kvm_t *, const struct kinfo_proc2 *, int);
char **kvm_getenvv(kvm_t *, const struct kinfo_proc *, int);
-char **kvm_getenvv2(kvm_t *, const struct kinfo_proc2 *, int);
char *kvm_geterr(kvm_t *);
int kvm_getloadavg(kvm_t *, double [], int);
char *kvm_getfiles(kvm_t *, int, int, int *);
struct kinfo_file2 *
kvm_getfile2(kvm_t *, int, int, size_t, int *);
struct kinfo_proc *
- kvm_getprocs(kvm_t *, int, int, int *);
-struct kinfo_proc2 *
- kvm_getproc2(kvm_t *, int, int, size_t, int *);
+ kvm_getprocs(kvm_t *, int, int, size_t, int *);
int kvm_nlist(kvm_t *, struct nlist *);
kvm_t *kvm_open(const char *, const char *, const char *, int, const char *);
kvm_t *kvm_openfiles(const char *, const char *, const char *,
@@ -80,6 +75,17 @@ ssize_t kvm_read(kvm_t *, unsigned lon
__attribute__((__bounded__(__buffer__,3,4)));
ssize_t kvm_write(kvm_t *, unsigned long, const void *, size_t)
__attribute__((__bounded__(__buffer__,3,4)));
+
+/*
+ * Old names that will disappear in a few revisions
+ */
+#ifndef kinfo_proc2
+#define kinfo_proc2 kinfo_proc
+#endif
+char **kvm_getargv2(kvm_t *, const struct kinfo_proc2 *, int);
+char **kvm_getenvv2(kvm_t *, const struct kinfo_proc2 *, int);
+struct kinfo_proc2 *
+ kvm_getproc2(kvm_t *, int, int, size_t, int *);
__END_DECLS
Index: sbin/sysctl/sysctl.c
===================================================================
RCS file: /cvs/src/sbin/sysctl/sysctl.c,v
retrieving revision 1.173
diff -u -p -r1.173 sysctl.c
--- sbin/sysctl/sysctl.c 19 Aug 2010 18:14:14 -0000 1.173
+++ sbin/sysctl/sysctl.c 29 Oct 2010 07:49:08 -0000
@@ -392,7 +392,6 @@ parse(char *string, int flags)
warnx("use pstat to view %s information", string);
return;
case KERN_PROC:
- case KERN_PROC2:
if (flags == 0)
return;
warnx("use ps to view %s information", string);
Index: sys/compat/common/kern_info_43.c
===================================================================
RCS file: /cvs/src/sys/compat/common/kern_info_43.c,v
retrieving revision 1.15
diff -u -p -r1.15 kern_info_43.c
--- sys/compat/common/kern_info_43.c 15 Aug 2003 20:32:15 -0000 1.15
+++ sys/compat/common/kern_info_43.c 29 Oct 2010 07:49:08 -0000
@@ -225,14 +225,6 @@ compat_43_sys_getkerninfo(p, v, retval)
kern_sysctl(name, 1, SCARG(uap, where), &size, NULL, 0, p);
break;
- case KINFO_PROC:
- name[0] = KERN_PROC;
- name[1] = SCARG(uap, op) & 0xff;
- name[2] = SCARG(uap, arg);
- error =
- kern_sysctl(name, 3, SCARG(uap, where), &size, NULL, 0, p);
- break;
-
case KINFO_FILE:
name[0] = KERN_FILE;
error =
Index: lib/libkvm/kvm.c
===================================================================
RCS file: /cvs/src/lib/libkvm/kvm.c,v
retrieving revision 1.48
diff -u -p -r1.48 kvm.c
--- lib/libkvm/kvm.c 27 Oct 2009 23:59:28 -0000 1.48
+++ lib/libkvm/kvm.c 29 Oct 2010 07:49:09 -0000
@@ -178,7 +178,6 @@ _kvm_open(kvm_t *kd, const char *uf, con
kd->alive = 0;
kd->filebase = 0;
kd->procbase = 0;
- kd->procbase2 = 0;
kd->nbpg = getpagesize();
kd->swapspc = 0;
kd->argspc = 0;
@@ -638,8 +637,6 @@ kvm_close(kvm_t *kd)
free((void *)kd->filebase);
if (kd->procbase != 0)
free((void *)kd->procbase);
- if (kd->procbase2 != 0)
- free(kd->procbase2);
if (kd->swapspc != 0)
free((void *)kd->swapspc);
if (kd->argspc != 0)
Index: lib/libkvm/kvm_getprocs.3
===================================================================
RCS file: /cvs/src/lib/libkvm/kvm_getprocs.3,v
retrieving revision 1.13
diff -u -p -r1.13 kvm_getprocs.3
--- lib/libkvm/kvm_getprocs.3 31 May 2007 19:19:35 -0000 1.13
+++ lib/libkvm/kvm_getprocs.3 29 Oct 2010 07:49:09 -0000
@@ -50,17 +50,17 @@
.Fd #include <sys/sysctl.h>
.Fd #include <kvm.h>
.Ft struct kinfo_proc *
-.Fn kvm_getprocs "kvm_t *kd" "int op" "int arg" "int *cnt"
+.Fn kvm_getprocs "kvm_t *kd" "int op" "int arg" "size_t elemsize" "int *cnt"
.Ft char **
.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 *
+.Ft struct kinfo_proc *
.Fn kvm_getproc2 "kvm_t *kd" "int op" "int arg" "size_t elemsize" "int *cnt"
.Ft char **
-.Fn kvm_getargv2 "kvm_t *kd" "const struct kinfo_proc2 *p" "int nchr"
+.Fn kvm_getargv2 "kvm_t *kd" "const struct kinfo_proc *p" "int nchr"
.Ft char **
-.Fn kvm_getenvv2 "kvm_t *kd" "const struct kinfo_proc2 *p" "int nchr"
+.Fn kvm_getenvv2 "kvm_t *kd" "const struct kinfo_proc *p" "int nchr"
.Sh DESCRIPTION
.Fn kvm_getprocs
returns a (sub-)set of active processes in the kernel indicated by
@@ -100,6 +100,17 @@ processes with real user ID
.Fa arg
.El
.Pp
+Only the first
+.Fa elemsize
+bytes of each array entry are returned.
+If the size of the
+.Vt kinfo_proc
+structure increases in size in a future release of
+.Ox ,
+the library will only return the requested amount of data for
+each array entry and programs that use
+.Fn kvm_getprocs
+will continue to function without the need for recompilation.
The number of processes found is returned in the reference parameter
.Fa cnt .
The processes are returned as a contiguous array of
@@ -162,35 +173,16 @@ function is similar to
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
-.Vt kinfo_proc2
-structures.
-Additionally, only the first
-.Fa elemsize
-bytes of each array entry are returned.
-If the size of the
-.Vt 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
+.Fn kvm_getproc2 ,
+.Fn kvm_getargv2 ,
and
.Fn kvm_getenvv2
-functions are equivalents to the
-.Fn kvm_getargv
+functions are obsolete equivalents for
+.Fn kvm_getprocs ,
+.Fn kvm_getargv ,
and
.Fn kvm_getenvv
-functions that use a
-.Vt kinfo_proc2
-structure to specify the process.
+and have identical signatures and behavior.
.Sh RETURN VALUES
.Fn kvm_getprocs ,
.Fn kvm_getargv ,
Index: lib/libkvm/kvm_private.h
===================================================================
RCS file: /cvs/src/lib/libkvm/kvm_private.h,v
retrieving revision 1.16
diff -u -p -r1.16 kvm_private.h
--- lib/libkvm/kvm_private.h 12 Jan 2010 08:15:51 -0000 1.16
+++ lib/libkvm/kvm_private.h 29 Oct 2010 07:49:09 -0000
@@ -50,7 +50,6 @@ 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;
struct kinfo_file *filebase;
int nbpg; /* page size */
char *swapspc; /* (dynamic) storage for swapped pages */
@@ -93,7 +92,6 @@ struct __kvm {
*/
void _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...);
int _kvm_dump_mkheader(kvm_t *kd_live, kvm_t *kd_dump);
-void _kvm_freeprocs(kvm_t *kd);
void _kvm_freevtop(kvm_t *);
int _kvm_initvtop(kvm_t *);
int _kvm_kvatop(kvm_t *, u_long, paddr_t *);
Index: lib/libkvm/kvm_proc.c
===================================================================
RCS file: /cvs/src/lib/libkvm/kvm_proc.c,v
retrieving revision 1.41
diff -u -p -r1.41 kvm_proc.c
--- lib/libkvm/kvm_proc.c 26 Jul 2010 01:56:27 -0000 1.41
+++ lib/libkvm/kvm_proc.c 29 Oct 2010 07:49:09 -0000
@@ -69,7 +69,6 @@
* most other applications are interested only in open/close/read/nlist).
*/
-#define __need_process
#include <sys/param.h>
#include <sys/user.h>
#include <sys/proc.h>
@@ -97,7 +96,7 @@
#include "kvm_private.h"
/*
- * Common info from kinfo_proc and kinfo_proc2 used by helper routines.
+ * Common info from kinfo_proc used by helper routines.
*/
struct miniproc {
struct vmspace *p_vmspace;
@@ -107,26 +106,10 @@ struct miniproc {
};
/*
- * Convert from struct proc and kinfo_proc{,2} to miniproc.
+ * Convert from struct kinfo_proc 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; \
@@ -134,18 +117,13 @@ struct miniproc {
} while (/*CONSTCOND*/0);
-ssize_t kvm_uread(kvm_t *, const struct proc *, u_long, char *,
size_t);
-
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 miniproc *, int,
void (*)(struct ps_strings *, u_long *, int *));
-static int kvm_proclist(kvm_t *, int, int, struct proc *,
- struct kinfo_proc *, int);
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 *);
@@ -231,261 +209,6 @@ _kvm_ureadm(kvm_t *kd, const struct mini
return (&kd->swapspc[offset]);
}
-char *
-_kvm_uread(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.
- */
-static int
-kvm_proclist(kvm_t *kd, int what, int arg, struct proc *p,
- struct kinfo_proc *bp, int maxcnt)
-{
- struct session sess;
- struct eproc eproc;
- struct proc proc;
- struct process process;
- struct pgrp pgrp;
- struct tty tty;
- int cnt = 0;
-
- for (; cnt < maxcnt && p != NULL; p = LIST_NEXT(&proc, p_list)) {
- if (KREAD(kd, (u_long)p, &proc)) {
- _kvm_err(kd, kd->program, "can't read proc at %x", p);
- return (-1);
- }
- if (KREAD(kd, (u_long)proc.p_p, &process)) {
- _kvm_err(kd, kd->program, "can't read process at %x",
proc.p_p);
- return (-1);
- }
- if (KREAD(kd, (u_long)process.ps_cred, &eproc.e_pcred) == 0)
- KREAD(kd, (u_long)eproc.e_pcred.pc_ucred,
- &eproc.e_ucred);
-
- switch (what) {
- case KERN_PROC_PID:
- if (proc.p_pid != (pid_t)arg)
- continue;
- break;
-
- case KERN_PROC_UID:
- if (eproc.e_ucred.cr_uid != (uid_t)arg)
- continue;
- break;
-
- case KERN_PROC_RUID:
- if (eproc.e_pcred.p_ruid != (uid_t)arg)
- continue;
- break;
-
- case KERN_PROC_ALL:
- if (proc.p_flag & P_SYSTEM)
- continue;
- break;
- }
- /*
- * We're going to add another proc to the set. If this
- * will overflow the buffer, assume the reason is because
- * nprocs (or the proc list) is corrupt and declare an error.
- */
- if (cnt >= maxcnt) {
- _kvm_err(kd, kd->program, "nprocs corrupt");
- return (-1);
- }
- /*
- * gather eproc
- */
- eproc.e_paddr = p;
- if (KREAD(kd, (u_long)process.ps_pgrp, &pgrp)) {
- _kvm_err(kd, kd->program, "can't read pgrp at %x",
- process.ps_pgrp);
- return (-1);
- }
- eproc.e_sess = pgrp.pg_session;
- eproc.e_pgid = pgrp.pg_id;
- eproc.e_jobc = pgrp.pg_jobc;
- if (KREAD(kd, (u_long)pgrp.pg_session, &sess)) {
- _kvm_err(kd, kd->program, "can't read session at %x",
- pgrp.pg_session);
- return (-1);
- }
- if ((process.ps_flags & PS_CONTROLT) && sess.s_ttyp != NULL) {
- if (KREAD(kd, (u_long)sess.s_ttyp, &tty)) {
- _kvm_err(kd, kd->program,
- "can't read tty at %x", sess.s_ttyp);
- return (-1);
- }
- eproc.e_tdev = tty.t_dev;
- eproc.e_tsess = tty.t_session;
- if (tty.t_pgrp != NULL) {
- if (KREAD(kd, (u_long)tty.t_pgrp, &pgrp)) {
- _kvm_err(kd, kd->program,
- "can't read tpgrp at &x",
- tty.t_pgrp);
- return (-1);
- }
- eproc.e_tpgid = pgrp.pg_id;
- } else
- eproc.e_tpgid = -1;
- } else
- eproc.e_tdev = NODEV;
- eproc.e_flag = sess.s_ttyvp ? EPROC_CTTY : 0;
- if (sess.s_leader == proc.p_p)
- eproc.e_flag |= EPROC_SLEADER;
- if (proc.p_wmesg)
- (void)kvm_read(kd, (u_long)proc.p_wmesg,
- eproc.e_wmesg, WMESGLEN);
-
- (void)kvm_read(kd, (u_long)proc.p_vmspace,
- &eproc.e_vm, sizeof(eproc.e_vm));
-
- eproc.e_xsize = eproc.e_xrssize = 0;
- eproc.e_xccount = eproc.e_xswrss = 0;
-
- switch (what) {
- case KERN_PROC_PGRP:
- if (eproc.e_pgid != (pid_t)arg)
- continue;
- break;
-
- case KERN_PROC_TTY:
- if ((process.ps_flags & PS_CONTROLT) == 0 ||
- eproc.e_tdev != (dev_t)arg)
- continue;
- break;
- }
- proc.p_flag |= process.ps_flags;
- bcopy(&proc, &bp->kp_proc, sizeof(proc));
- bcopy(&eproc, &bp->kp_eproc, sizeof(eproc));
- ++bp;
- ++cnt;
- }
- return (cnt);
-}
-
-/*
- * Build proc info array by reading in proc list from a crash dump.
- * Return number of procs read. maxcnt is the max we will read.
- */
-static int
-kvm_deadprocs(kvm_t *kd, int what, int arg, u_long a_allproc,
- u_long a_zombproc, int maxcnt)
-{
- struct kinfo_proc *bp = kd->procbase;
- struct proc *p;
- int acnt, zcnt;
-
- if (KREAD(kd, a_allproc, &p)) {
- _kvm_err(kd, kd->program, "cannot read allproc");
- return (-1);
- }
- acnt = kvm_proclist(kd, what, arg, p, bp, maxcnt);
- if (acnt < 0)
- return (acnt);
-
- if (KREAD(kd, a_zombproc, &p)) {
- _kvm_err(kd, kd->program, "cannot read zombproc");
- return (-1);
- }
- zcnt = kvm_proclist(kd, what, arg, p, bp + acnt, maxcnt - acnt);
- if (zcnt < 0)
- zcnt = 0;
-
- return (acnt + zcnt);
-}
-
-struct kinfo_proc *
-kvm_getprocs(kvm_t *kd, int op, int arg, int *cnt)
-{
- int mib[4], st, nprocs;
- size_t size;
-
- if (kd->procbase != 0) {
- free((void *)kd->procbase);
- /*
- * Clear this pointer in case this call fails. Otherwise,
- * kvm_close() will free it again.
- */
- kd->procbase = 0;
- }
- if (ISALIVE(kd)) {
- size = 0;
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = op;
- mib[3] = arg;
- st = sysctl(mib, 4, NULL, &size, NULL, 0);
- if (st == -1) {
- _kvm_syserr(kd, kd->program, "kvm_getprocs");
- return (0);
- }
- kd->procbase = _kvm_malloc(kd, size);
- if (kd->procbase == 0)
- return (0);
- st = sysctl(mib, 4, kd->procbase, &size, NULL, 0);
- if (st == -1) {
- _kvm_syserr(kd, kd->program, "kvm_getprocs");
- return (0);
- }
- if (size % sizeof(struct kinfo_proc) != 0) {
- _kvm_err(kd, kd->program,
- "proc size mismatch (%d total, %d chunks)",
- size, sizeof(struct kinfo_proc));
- return (0);
- }
- nprocs = size / sizeof(struct kinfo_proc);
- } else {
- struct nlist nl[4], *p;
-
- memset(nl, 0, sizeof(nl));
- nl[0].n_name = "_nprocs";
- nl[1].n_name = "_allproc";
- nl[2].n_name = "_zombproc";
- nl[3].n_name = NULL;
-
- if (kvm_nlist(kd, nl) != 0) {
- for (p = nl; p->n_type != 0; ++p)
- ;
- _kvm_err(kd, kd->program,
- "%s: no such symbol", p->n_name);
- return (0);
- }
- if (KREAD(kd, nl[0].n_value, &nprocs)) {
- _kvm_err(kd, kd->program, "can't read nprocs");
- return (0);
- }
- size = nprocs * sizeof(struct kinfo_proc);
- kd->procbase = _kvm_malloc(kd, size);
- if (kd->procbase == 0)
- return (0);
-
- nprocs = kvm_deadprocs(kd, op, arg, nl[1].n_value,
- nl[2].n_value, nprocs);
-#ifdef notdef
- size = nprocs * sizeof(struct kinfo_proc);
- (void)realloc(kd->procbase, size);
-#endif
- }
- *cnt = nprocs;
- return (kd->procbase);
-}
-
-void
-_kvm_freeprocs(kvm_t *kd)
-{
- if (kd->procbase) {
- free(kd->procbase);
- kd->procbase = 0;
- }
-}
-
void *
_kvm_realloc(kvm_t *kd, void *p, size_t n)
{
@@ -511,7 +234,7 @@ kvm_argv(kvm_t *kd, const struct minipro
int len, cc;
/*
- * Check that there aren't an unreasonable number of agruments,
+ * Check that there aren't an unreasonable number of arguments,
* and that the address is in user space.
*/
if (narg > ARG_MAX || addr < VM_MIN_ADDRESS || addr >=
VM_MAXUSER_ADDRESS)
@@ -745,42 +468,32 @@ kvm_getargv(kvm_t *kd, const struct kinf
struct miniproc p;
if (ISALIVE(kd))
- return (kvm_arg_sysctl(kd, kp->kp_proc.p_pid, nchr, 0));
+ return (kvm_arg_sysctl(kd, kp->p_pid, nchr, 0));
KPTOMINI(kp, &p);
return (kvm_doargv(kd, &p, nchr, ps_str_a));
}
char **
-kvm_getenvv(kvm_t *kd, const struct kinfo_proc *kp, int nchr)
+kvm_getargv2(kvm_t *kd, 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));
+ return (kvm_getargv(kd, kp, nchr));
}
char **
-kvm_getargv2(kvm_t *kd, const struct kinfo_proc2 *kp, int nchr)
+kvm_getenvv(kvm_t *kd, const struct kinfo_proc *kp, int nchr)
{
struct miniproc p;
if (ISALIVE(kd))
- return (kvm_arg_sysctl(kd, kp->p_pid, nchr, 0));
- KP2TOMINI(kp, &p);
- return (kvm_doargv(kd, &p, nchr, ps_str_a));
+ return (kvm_arg_sysctl(kd, kp->p_pid, nchr, 1));
+ KPTOMINI(kp, &p);
+ return (kvm_doargv(kd, &p, nchr, ps_str_e));
}
char **
-kvm_getenvv2(kvm_t *kd, const struct kinfo_proc2 *kp, int nchr)
+kvm_getenvv2(kvm_t *kd, const struct kinfo_proc *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));
+ return (kvm_getenvv2(kd, kp, nchr));
}
/*
@@ -809,14 +522,4 @@ kvm_ureadm(kvm_t *kd, const struct minip
len -= cc;
}
return (ssize_t)(cp - buf);
-}
-
-ssize_t
-kvm_uread(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));
}
Index: lib/libkvm/kvm_proc2.c
===================================================================
RCS file: /cvs/src/lib/libkvm/kvm_proc2.c,v
retrieving revision 1.3
diff -u -p -r1.3 kvm_proc2.c
--- lib/libkvm/kvm_proc2.c 26 Jul 2010 01:56:27 -0000 1.3
+++ lib/libkvm/kvm_proc2.c 29 Oct 2010 07:49:09 -0000
@@ -105,7 +105,7 @@ static int
kvm_proclist(kvm_t *kd, int op, int arg, struct proc *p,
char *bp, int maxcnt, size_t esize)
{
- struct kinfo_proc2 kp;
+ struct kinfo_proc kp;
struct session sess;
struct pcred pcred;
struct ucred ucred;
@@ -265,7 +265,7 @@ kvm_proclist(kvm_t *kd, int op, int arg,
ps = NULL;
#define do_copy_str(_d, _s, _l) kvm_read(kd, (u_long)(_s), (_d), (_l)-1)
- FILL_KPROC2(&kp, do_copy_str, &proc, &process, &pcred, &ucred,
+ FILL_KPROC(&kp, do_copy_str, &proc, &process, &pcred, &ucred,
&pgrp, p, proc.p_p, &sess, vmp, limp, ps);
#undef do_copy_str
@@ -295,8 +295,8 @@ kvm_proclist(kvm_t *kd, int op, int arg,
return (cnt);
}
-struct kinfo_proc2 *
-kvm_getproc2(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
+struct kinfo_proc *
+kvm_getprocs(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
{
int mib[6], st, nprocs;
size_t size;
@@ -304,36 +304,36 @@ kvm_getproc2(kvm_t *kd, int op, int arg,
if ((ssize_t)esize < 0)
return (NULL);
- if (kd->procbase2 != NULL) {
- free(kd->procbase2);
+ if (kd->procbase != NULL) {
+ free(kd->procbase);
/*
* Clear this pointer in case this call fails. Otherwise,
* kvm_close() will free it again.
*/
- kd->procbase2 = 0;
+ kd->procbase = 0;
}
if (ISALIVE(kd)) {
size = 0;
mib[0] = CTL_KERN;
- mib[1] = KERN_PROC2;
+ mib[1] = KERN_PROC;
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");
+ _kvm_syserr(kd, kd->program, "kvm_getprocs");
return (NULL);
}
mib[5] = size / esize;
- kd->procbase2 = _kvm_malloc(kd, size);
- if (kd->procbase2 == 0)
+ kd->procbase = _kvm_malloc(kd, size);
+ if (kd->procbase == 0)
return (NULL);
- st = sysctl(mib, 6, kd->procbase2, &size, NULL, 0);
+ st = sysctl(mib, 6, kd->procbase, &size, NULL, 0);
if (st == -1) {
- _kvm_syserr(kd, kd->program, "kvm_getproc2");
+ _kvm_syserr(kd, kd->program, "kvm_getprocs");
return (NULL);
}
nprocs = size / esize;
@@ -343,9 +343,9 @@ kvm_getproc2(kvm_t *kd, int op, int arg,
struct proc *p;
char *bp;
- if (esize > sizeof(struct kinfo_proc2)) {
+ if (esize > sizeof(struct kinfo_proc)) {
_kvm_syserr(kd, kd->program,
- "kvm_getproc2: unknown fields requested: libkvm out
of date?");
+ "kvm_getprocs: unknown fields requested: libkvm out
of date?");
return (NULL);
}
@@ -367,10 +367,10 @@ kvm_getproc2(kvm_t *kd, int op, int arg,
return (NULL);
}
- kd->procbase2 = _kvm_malloc(kd, maxprocs * esize);
- if (kd->procbase2 == 0)
+ kd->procbase = _kvm_malloc(kd, maxprocs * esize);
+ if (kd->procbase == 0)
return (NULL);
- bp = (char *)kd->procbase2;
+ bp = (char *)kd->procbase;
/* allproc */
if (KREAD(kd, nl[1].n_value, &p)) {
@@ -392,6 +392,12 @@ kvm_getproc2(kvm_t *kd, int op, int arg,
nprocs += i;
}
*cnt = nprocs;
- return (kd->procbase2);
+ return (kd->procbase);
+}
+
+struct kinfo_proc *
+kvm_getproc2(kvm_t *kd, int op, int arg, size_t esize, int *cnt)
+{
+ return (kvm_getprocs(kd, op, arg, esize, cnt));
}
Index: lib/libkvm/shlib_version
===================================================================
RCS file: /cvs/src/lib/libkvm/shlib_version,v
retrieving revision 1.9
diff -u -p -r1.9 shlib_version
--- lib/libkvm/shlib_version 7 Jun 2009 03:09:34 -0000 1.9
+++ lib/libkvm/shlib_version 29 Oct 2010 07:49:09 -0000
@@ -1,2 +1,2 @@
-major=9
-minor=1
+major=10
+minor=0
Index: lib/libc/gen/sysctl.3
===================================================================
RCS file: /cvs/src/lib/libc/gen/sysctl.3,v
retrieving revision 1.200
diff -u -p -r1.200 sysctl.3
--- lib/libc/gen/sysctl.3 11 Oct 2010 08:26:40 -0000 1.200
+++ lib/libc/gen/sysctl.3 29 Oct 2010 08:25:24 -0000
@@ -448,7 +448,6 @@ information.
.It Dv KERN_OSVERSION No " string no"
.It Dv KERN_POSIX1 No " integer no"
.It Dv KERN_PROC No " struct kinfo_proc no"
-.It Dv KERN_PROC2 No " struct kinfo_proc2 no"
.It Dv KERN_PROC_ARGS No " node not applicable"
.It Dv KERN_PROF No " node not applicable"
.It Dv KERN_RAWPARTITION No " integer no"
@@ -707,10 +706,6 @@ The version of ISO/IEC 9945 (POSIX 1003.
attempts to comply.
.It Dv KERN_PROC
Return the entire process table, or a subset of it.
-This name is deprecated, as the layout of the returned structures
-is not a stable ABI; use
-.Dv KERN_PROC2
-instead.
An array of
.Li struct kinfo_proc
structures is returned,
@@ -727,14 +722,9 @@ The third and fourth level names are as
.It Dv KERN_PROC_TTY No " A tty device"
.It Dv KERN_PROC_UID No " A user ID"
.El
-.It Dv KERN_PROC2
-Like
-.Dv KERN_PROC
-but an array of
-.Li struct kinfo_proc2
-structures is returned.
+.Pp
The fifth level name is the size of the
-.Li struct kinfo_proc2
+.Li struct kinfo_proc
and the sixth level name is the number of structures to return.
.It Dv KERN_PROC_ARGS
Returns the arguments or environment of a process.