--- //depot/vendor/freebsd/src/bin/ps/ps.c 2004/11/19 16:36:55 +++ //depot/user/pjd/ps-e/bin/ps/ps.c 2004/11/30 23:05:02 @@ -129,7 +129,6 @@ } l; }; -static int check_procfs(void); static int addelem_gid(struct listinfo *, const char *); static int addelem_pid(struct listinfo *, const char *); static int addelem_tty(struct listinfo *, const char *); @@ -403,14 +402,21 @@ argc -= optind; argv += optind; - /* - * If the user specified ps -e then they want a copy of the process - * environment kvm_getenvv(3) attempts to open /proc//mem. - * Check to make sure that procfs is mounted on /proc, otherwise - * print a warning informing the user that output will be incomplete. - */ - if (needenv == 1 && check_procfs() == 0) - warnx("Process environment requires procfs(5)"); + if (needenv) { + unsigned long buflen; + size_t bufsz; + + bufsz = sizeof(buflen); + if (sysctlbyname("kern.ps_env_cache_limit", &buflen, &bufsz, + NULL, 0) == -1) { + warnx("Userland and kernel out of sync (error=%d)", + errno); + } else if (buflen == 0) { + warnx("Process environment requires sysctl " + "kern.ps_env_cache_limit > 0"); + } + } + /* * If there arguments after processing all the options, attempt * to treat them as a list of process ids. @@ -1027,7 +1033,7 @@ ki->ki_args = NULL; } if (needenv) { - if (UREADOK(ki)) + if (UREADOK(ki) || (ki->ki_p->ki_envs != NULL)) ki->ki_env = strdup(fmt(kvm_getenvv, ki, (char *)NULL, 0)); else @@ -1176,18 +1182,6 @@ return (newopts); } -static int -check_procfs(void) -{ - struct statfs mnt; - - if (statfs("/proc", &mnt) < 0) - return (0); - if (strcmp(mnt.f_fstypename, "procfs") != 0) - return (0); - return (1); -} - static void usage(void) { --- //depot/vendor/freebsd/src/lib/libkvm/kvm.h 2003/10/13 05:36:17 +++ //depot/user/pjd/ps-e/lib/libkvm/kvm.h 2004/11/16 22:45:52 @@ -88,7 +88,7 @@ (const char *, const char *, const char *, int, char *); ssize_t kvm_read(kvm_t *, unsigned long, void *, size_t); ssize_t kvm_uread - (kvm_t *, struct kinfo_proc *, unsigned long, char *, size_t); + (kvm_t *, const struct kinfo_proc *, unsigned long, char *, size_t); ssize_t kvm_write(kvm_t *, unsigned long, const void *, size_t); __END_DECLS --- //depot/vendor/freebsd/src/lib/libkvm/kvm_proc.c 2004/11/20 02:37:11 +++ //depot/user/pjd/ps-e/lib/libkvm/kvm_proc.c 2004/11/30 22:28:40 @@ -204,6 +204,7 @@ kp->ki_addr = 0; /* XXX uarea */ /* kp->ki_kstack = proc.p_thread.td_kstack; XXXKSE */ kp->ki_args = proc.p_args; + kp->ki_envs = proc.p_envs; kp->ki_tracep = proc.p_tracevp; kp->ki_textvp = proc.p_textvp; kp->ki_fd = proc.p_fd; @@ -615,7 +616,7 @@ static char ** kvm_argv(kd, kp, addr, narg, maxcnt) kvm_t *kd; - struct kinfo_proc *kp; + const struct kinfo_proc *kp; u_long addr; int narg; int maxcnt; @@ -815,7 +816,7 @@ */ static int proc_verify(curkp) - struct kinfo_proc *curkp; + const struct kinfo_proc *curkp; { struct kinfo_proc newkp; int mib[4]; @@ -835,7 +836,7 @@ static char ** kvm_doargv(kd, kp, nchr, info) kvm_t *kd; - struct kinfo_proc *kp; + const struct kinfo_proc *kp; int nchr; void (*info)(struct ps_strings *, u_long *, int *); { @@ -874,21 +875,22 @@ } /* - * Get the command args. This code is now machine independent. + * Get the command args or envs. This code is now machine independent. */ -char ** -kvm_getargv(kd, kp, nchr) +static char ** +kvm_getargvenvv(kd, kp, nchr, args) kvm_t *kd; const struct kinfo_proc *kp; int nchr; + int args; /* 1 for args, 0 for envs */ { - int oid[4]; - int i; + static unsigned long argslen = 0, envslen = 0; + static char *buf = NULL, **bufp = NULL; + static int argc = 32; + unsigned long buflen; size_t bufsz; - static unsigned long buflen; - static char *buf, *p; - static char **bufp; - static int argc; + char *p; + int i, oid[4]; if (!ISALIVE(kd)) { _kvm_err(kd, kd->program, @@ -896,24 +898,36 @@ return (0); } - if (!buflen) { - bufsz = sizeof(buflen); - i = sysctlbyname("kern.ps_arg_cache_limit", - &buflen, &bufsz, NULL, 0); - if (i == -1) { + bufsz = sizeof(buflen); + if (args) { + if (argslen == 0) { + i = sysctlbyname("kern.ps_arg_cache_limit", &argslen, + &bufsz, NULL, 0); + } + buflen = argslen; + } else { + if (envslen == 0) { + i = sysctlbyname("kern.ps_env_cache_limit", &envslen, + &bufsz, NULL, 0); + } + buflen = envslen; + } + if (buf == NULL) { + buf = malloc(buflen); + if (buf == NULL) buflen = 0; - } else { - buf = malloc(buflen); - if (buf == NULL) + else { + bufp = malloc(sizeof(char *) * argc); + if (bufp == NULL) { + free(buf); buflen = 0; - argc = 32; - bufp = malloc(sizeof(char *) * argc); + } } } if (buf != NULL) { oid[0] = CTL_KERN; oid[1] = KERN_PROC; - oid[2] = KERN_PROC_ARGS; + oid[2] = args ? KERN_PROC_ARGS : KERN_PROC_ENVS; oid[3] = kp->ki_pid; bufsz = buflen; i = sysctl(oid, 4, buf, &bufsz, 0, 0); @@ -929,13 +943,23 @@ sizeof(char *) * argc); } } while (p < buf + bufsz); - bufp[i++] = 0; + bufp[i++] = NULL; return (bufp); } } if (kp->ki_flag & P_SYSTEM) return (NULL); - return (kvm_doargv(kd, kp, nchr, ps_str_a)); + return (kvm_doargv(kd, kp, nchr, args ? ps_str_a : ps_str_e)); +} + +char ** +kvm_getargv(kd, kp, nchr) + kvm_t *kd; + const struct kinfo_proc *kp; + int nchr; +{ + + return (kvm_getargvenvv(kd, kp, nchr, 1)); } char ** @@ -944,7 +968,8 @@ const struct kinfo_proc *kp; int nchr; { - return (kvm_doargv(kd, kp, nchr, ps_str_e)); + + return (kvm_getargvenvv(kd, kp, nchr, 0)); } /* @@ -953,7 +978,7 @@ ssize_t kvm_uread(kd, kp, uva, buf, len) kvm_t *kd; - struct kinfo_proc *kp; + const struct kinfo_proc *kp; u_long uva; char *buf; size_t len; --- //depot/vendor/freebsd/src/sys/compat/linprocfs/linprocfs.c 2004/12/01 21:35:45 +++ //depot/user/pjd/ps-e/sys/compat/linprocfs/linprocfs.c 2004/12/06 09:09:13 @@ -821,8 +821,15 @@ static int linprocfs_doprocenviron(PFS_FILL_ARGS) { - sbuf_printf(sb, "doprocenviron\n%c", '\0'); + PROC_LOCK(p); + if (p->p_envs != NULL && p_candebug(td, p) == 0) { + sbuf_bcpy(sb, p->p_envs->ar_envs, p->p_envs->ar_length); + PROC_UNLOCK(p); + } else { + PROC_UNLOCK(p); + sbuf_printf(sb, "doprocenviron\n%c", '\0'); + } return (0); } --- //depot/vendor/freebsd/src/sys/compat/svr4/svr4_misc.c 2004/11/27 06:55:50 +++ //depot/user/pjd/ps-e/sys/compat/svr4/svr4_misc.c 2004/11/30 16:51:58 @@ -1301,9 +1301,10 @@ q->p_ucred = NULL; /* - * Remove unused arguments + * Remove unused arguments and environment variables */ pargs_drop(q->p_args); + pargs_drop(q->p_envs); PROC_UNLOCK(q); /* --- //depot/vendor/freebsd/src/sys/kern/kern_exec.c 2004/11/27 06:55:50 +++ //depot/user/pjd/ps-e/sys/kern/kern_exec.c 2004/12/06 09:11:52 @@ -97,6 +97,10 @@ SYSCTL_ULONG(_kern, OID_AUTO, ps_arg_cache_limit, CTLFLAG_RW, &ps_arg_cache_limit, 0, ""); +u_long ps_env_cache_limit = PAGE_SIZE / 4; +SYSCTL_ULONG(_kern, OID_AUTO, ps_env_cache_limit, CTLFLAG_RW, + &ps_env_cache_limit, 0, ""); + static int sysctl_kern_ps_strings(SYSCTL_HANDLER_ARGS) { @@ -263,11 +267,12 @@ struct ucred *newcred = NULL, *oldcred; struct uidinfo *euip; register_t *stack_base; - int error, len, i; + int error, len, i, argslen, envslen; struct image_params image_params, *imgp; struct vattr attr; int (*img_first)(struct image_params *); struct pargs *oldargs = NULL, *newargs = NULL; + struct pargs *oldenvs = NULL, *newenvs = NULL; struct sigacts *oldsigacts, *newsigacts; #ifdef KTRACE struct vnode *tracevp = NULL; @@ -481,9 +486,12 @@ */ newcred = crget(); euip = uifind(attr.va_uid); - i = imgp->endargs - imgp->stringbase; - if (ps_arg_cache_limit >= i + sizeof(struct pargs)) - newargs = pargs_alloc(i); + argslen = imgp->endargs - imgp->startargs; + if (ps_arg_cache_limit >= argslen + sizeof(struct pargs)) + newargs = pargs_alloc(argslen); + envslen = imgp->endenvs - imgp->startenvs; + if (ps_env_cache_limit >= envslen + sizeof(struct pargs)) + newenvs = pargs_alloc(envslen); /* close files on exec */ fdcloseexec(td); @@ -669,11 +677,22 @@ p->p_args = NULL; /* Cache arguments if they fit inside our allowance */ - if (ps_arg_cache_limit >= i + sizeof(struct pargs)) { - bcopy(imgp->stringbase, newargs->ar_args, i); + if (ps_arg_cache_limit >= argslen + sizeof(struct pargs)) { + bcopy(imgp->startargs, newargs->ar_args, argslen); p->p_args = newargs; newargs = NULL; } + + /* Free any previous environment cache */ + oldenvs = p->p_envs; + p->p_envs = NULL; + + /* Cache environment variables if they fit inside our allowance */ + if (ps_env_cache_limit >= envslen + sizeof(struct pargs)) { + bcopy(imgp->startenvs, newenvs->ar_envs, envslen); + p->p_envs = newenvs; + newenvs = NULL; + } PROC_UNLOCK(p); /* Set values passed into the program in registers. */ @@ -710,6 +729,10 @@ pargs_drop(oldargs); if (newargs != NULL) pargs_drop(newargs); + if (oldenvs != NULL) + pargs_drop(oldenvs); + if (newenvs != NULL) + pargs_drop(newenvs); if (oldsigacts != NULL) sigacts_free(oldsigacts); @@ -997,6 +1020,8 @@ } } + imgp->endenvs = imgp->stringp; + return (0); } --- //depot/vendor/freebsd/src/sys/kern/kern_fork.c 2004/11/27 06:55:50 +++ //depot/user/pjd/ps-e/sys/kern/kern_fork.c 2004/11/30 16:51:58 @@ -503,6 +503,7 @@ td2->td_ucred = crhold(p2->p_ucred); /* XXXKSE */ pargs_hold(p2->p_args); + pargs_hold(p2->p_envs); if (flags & RFSIGSHARE) { p2->p_sigacts = sigacts_hold(p1->p_sigacts); --- //depot/vendor/freebsd/src/sys/kern/kern_proc.c 2004/11/27 06:50:42 +++ //depot/user/pjd/ps-e/sys/kern/kern_proc.c 2004/12/06 09:02:31 @@ -623,6 +623,7 @@ PROC_LOCK_ASSERT(p, MA_OWNED); kp->ki_addr =/* p->p_addr; */0; /* XXXKSE */ kp->ki_args = p->p_args; + kp->ki_envs = p->p_envs; kp->ki_textvp = p->p_textvp; #ifdef KTRACE kp->ki_tracep = p->p_tracevp; @@ -1137,17 +1138,25 @@ if (!p) return (ESRCH); - if ((error = p_cansee(curthread, p)) != 0) { + if ((error = p_cansee(req->td, p)) != 0) { + PROC_UNLOCK(p); + return (error); + } + if (oidp->oid_number == KERN_PROC_ENVS && + (error = p_candebug(req->td, p)) != 0) { PROC_UNLOCK(p); return (error); } - if (req->newptr && curproc != p) { + if (req->newptr && req->td->td_proc != p) { PROC_UNLOCK(p); return (EPERM); } - pa = p->p_args; + if (oidp->oid_number == KERN_PROC_ARGS) + pa = p->p_args; + else /* if (oidp->oid_number == KERN_PROC_ENVS) */ + pa = p->p_envs; pargs_hold(pa); PROC_UNLOCK(p); if (req->oldptr != NULL && pa != NULL) @@ -1156,8 +1165,13 @@ if (error != 0 || req->newptr == NULL) return (error); - if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit) - return (ENOMEM); + if (oidp->oid_number == KERN_PROC_ARGS) { + if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit) + return (ENOMEM); + } else /* if (oidp->oid_number == KERN_PROC_ENVS) */ { + if (req->newlen + sizeof(struct pargs) > ps_env_cache_limit) + return (ENOMEM); + } newpa = pargs_alloc(req->newlen); error = SYSCTL_IN(req, newpa->ar_args, req->newlen); if (error != 0) { @@ -1165,8 +1179,13 @@ return (error); } PROC_LOCK(p); - pa = p->p_args; - p->p_args = newpa; + if (oidp->oid_number == KERN_PROC_ARGS) { + pa = p->p_args; + p->p_args = newpa; + } else /* if (oidp->oid_number == KERN_PROC_ENVS) */ { + pa = p->p_envs; + p->p_envs = newpa; + } PROC_UNLOCK(p); pargs_drop(pa); return (0); @@ -1233,6 +1252,9 @@ SYSCTL_NODE(_kern_proc, KERN_PROC_ARGS, args, CTLFLAG_RW | CTLFLAG_ANYBODY, sysctl_kern_proc_args, "Process argument list"); +SYSCTL_NODE(_kern_proc, KERN_PROC_ENVS, envs, CTLFLAG_RW | CTLFLAG_ANYBODY, + sysctl_kern_proc_args, "Process environment variable list"); + SYSCTL_NODE(_kern_proc, KERN_PROC_SV_NAME, sv_name, CTLFLAG_RD, sysctl_kern_proc_sv_name, "Process syscall vector name (ABI type)"); --- //depot/vendor/freebsd/src/sys/sys/imgact.h 2004/04/24 06:45:20 +++ //depot/user/pjd/ps-e/sys/sys/imgact.h 2004/11/15 00:03:06 @@ -44,8 +44,11 @@ struct vattr *attr; /* attributes of file */ const char *image_header; /* head of file to exec */ char *stringbase; /* base address of tmp string storage */ +#define startargs stringbase char *stringp; /* current 'end' pointer of tmp strings */ char *endargs; /* end of argv vector */ +#define startenvs endargs + char *endenvs; /* end of envv vector */ int stringspace; /* space left in tmp string storage area */ int argc, envc; /* count of argument and environment strings */ char *argv0; /* Replacement for argv[0] when interpreting */ --- //depot/vendor/freebsd/src/sys/sys/proc.h 2004/11/20 02:35:39 +++ //depot/user/pjd/ps-e/sys/sys/proc.h 2004/11/21 11:24:47 @@ -104,6 +104,7 @@ u_int ar_ref; /* Reference count. */ u_int ar_length; /* Length. */ u_char ar_args[1]; /* Arguments. */ +#define ar_envs ar_args }; /*- @@ -584,6 +585,7 @@ struct pgrp *p_pgrp; /* (c + e) Pointer to process group. */ struct sysentvec *p_sysent; /* (b) Syscall dispatch info. */ struct pargs *p_args; /* (c) Process arguments. */ + struct pargs *p_envs; /* (c) Process environment variables. */ rlim_t p_cpulimit; /* (j) Current CPU limit in seconds. */ signed char p_nice; /* (c + j) Process "nice" value. */ /* End area that is copied on creation. */ @@ -814,6 +816,7 @@ extern int nprocs, maxproc; /* Current and max number of procs. */ extern int maxprocperuid; /* Max procs per uid. */ extern u_long ps_arg_cache_limit; +extern u_long ps_env_cache_limit; extern int sched_quantum; /* Scheduling quantum in ticks. */ LIST_HEAD(proclist, proc); --- //depot/vendor/freebsd/src/sys/sys/sysctl.h 2004/10/11 22:05:44 +++ //depot/user/pjd/ps-e/sys/sys/sysctl.h 2004/11/15 00:03:06 @@ -428,6 +428,7 @@ #define KERN_PROC_SV_NAME 9 /* get syscall vector name */ #define KERN_PROC_RGID 10 /* by real group id */ #define KERN_PROC_GID 11 /* by effective group id */ +#define KERN_PROC_ENVS 12 /* get/set environment variables */ #define KERN_PROC_INC_THREAD 0x10 /* * modifier for pid, pgrp, tty, * uid, ruid, gid, rgid and proc --- //depot/vendor/freebsd/src/sys/sys/user.h 2004/11/27 06:50:42 +++ //depot/user/pjd/ps-e/sys/sys/user.h 2004/11/30 16:51:58 @@ -74,7 +74,7 @@ * end of kinfo_proc. It may need to be overridden on a platform-specific * basis as new fields are added. */ -#define KI_NSPARE 16 +#define KI_NSPARE 15 #ifdef __alpha__ #define KINFO_PROC_SIZE 912 @@ -84,7 +84,7 @@ #endif #ifdef __arm__ #undef KI_NSPARE /* Fewer spare longs on this arch */ -#define KI_NSPARE 15 +#define KI_NSPARE 14 #define KINFO_PROC_SIZE 648 #endif #ifdef __ia64__ @@ -92,7 +92,7 @@ #endif #ifdef __i386__ #undef KI_NSPARE /* Fewer spare longs on this arch */ -#define KI_NSPARE 15 +#define KI_NSPARE 14 #define KINFO_PROC_SIZE 648 #endif #ifdef __powerpc__ @@ -187,6 +187,7 @@ lwpid_t ki_tid; /* XXXKSE thread id */ int ki_numthreads; /* XXXKSE number of threads in total */ void *ki_udata; /* User convenience pointer */ + struct pargs *ki_envs; /* address of environment variables */ long ki_spare[KI_NSPARE]; /* spare room for later growth */ }; void fill_kinfo_proc(struct proc *, struct kinfo_proc *);