Retire linprocfs_doargv(). Instead use new functions, proc_getargv()

and proc_getenvv(), which were implemented using linprocfs_doargv() as
a reference.

Suggested by:	kib
Reviewed by:	kib
Approved by:	des (linprocfs maintainer)
MFC after:	2 weeks
This commit is contained in:
Mikolaj Golub 2011-11-22 20:45:11 +00:00
parent 66c6108d5d
commit 7a837e17ba

View File

@ -919,150 +919,6 @@ linprocfs_doprocroot(PFS_FILL_ARGS)
return (0);
}
#define MAX_ARGV_STR 512 /* Max number of argv-like strings */
#define UIO_CHUNK_SZ 256 /* Max chunk size (bytes) for uiomove */
static int
linprocfs_doargv(struct thread *td, struct proc *p, struct sbuf *sb,
void (*resolver)(const struct ps_strings, u_long *, int *))
{
struct iovec iov;
struct uio tmp_uio;
struct ps_strings pss;
int ret, i, n_elements, elm_len;
u_long addr, pbegin;
char **env_vector, *envp;
char env_string[UIO_CHUNK_SZ];
#ifdef COMPAT_FREEBSD32
struct freebsd32_ps_strings pss32;
uint32_t *env_vector32;
#endif
#define UIO_HELPER(uio, iov, base, len, cnt, offset, sz, flg, rw, td) \
do { \
iov.iov_base = (caddr_t)(base); \
iov.iov_len = (len); \
uio.uio_iov = &(iov); \
uio.uio_iovcnt = (cnt); \
uio.uio_offset = (off_t)(offset); \
uio.uio_resid = (sz); \
uio.uio_segflg = (flg); \
uio.uio_rw = (rw); \
uio.uio_td = (td); \
} while (0)
env_vector = malloc(sizeof(char *) * MAX_ARGV_STR, M_TEMP, M_WAITOK);
#ifdef COMPAT_FREEBSD32
env_vector32 = NULL;
if (SV_PROC_FLAG(p, SV_ILP32) != 0) {
env_vector32 = malloc(sizeof(*env_vector32) * MAX_ARGV_STR,
M_TEMP, M_WAITOK);
elm_len = sizeof(int32_t);
envp = (char *)env_vector32;
UIO_HELPER(tmp_uio, iov, &pss32, sizeof(pss32), 1,
(off_t)(p->p_sysent->sv_psstrings),
sizeof(pss32), UIO_SYSSPACE, UIO_READ, td);
ret = proc_rwmem(p, &tmp_uio);
if (ret != 0)
goto done;
pss.ps_argvstr = PTRIN(pss32.ps_argvstr);
pss.ps_nargvstr = pss32.ps_nargvstr;
pss.ps_envstr = PTRIN(pss32.ps_envstr);
pss.ps_nenvstr = pss32.ps_nenvstr;
} else {
#endif
elm_len = sizeof(char *);
envp = (char *)env_vector;
UIO_HELPER(tmp_uio, iov, &pss, sizeof(pss), 1,
(off_t)(p->p_sysent->sv_psstrings),
sizeof(pss), UIO_SYSSPACE, UIO_READ, td);
ret = proc_rwmem(p, &tmp_uio);
if (ret != 0)
goto done;
#ifdef COMPAT_FREEBSD32
}
#endif
/* Get the array address and the number of elements */
resolver(pss, &addr, &n_elements);
/* Consistent with lib/libkvm/kvm_proc.c */
if (n_elements > MAX_ARGV_STR) {
ret = E2BIG;
goto done;
}
UIO_HELPER(tmp_uio, iov, envp, n_elements * elm_len, 1,
(vm_offset_t)(addr), iov.iov_len, UIO_SYSSPACE, UIO_READ, td);
ret = proc_rwmem(p, &tmp_uio);
if (ret != 0)
goto done;
#ifdef COMPAT_FREEBSD32
if (env_vector32 != NULL) {
for (i = 0; i < n_elements; i++)
env_vector[i] = PTRIN(env_vector32[i]);
}
#endif
/* Now we can iterate through the list of strings */
for (i = 0; i < n_elements; i++) {
pbegin = (vm_offset_t)env_vector[i];
for (;;) {
UIO_HELPER(tmp_uio, iov, env_string, sizeof(env_string),
1, pbegin, iov.iov_len, UIO_SYSSPACE, UIO_READ, td);
ret = proc_rwmem(p, &tmp_uio);
if (ret != 0)
goto done;
if (!strvalid(env_string, UIO_CHUNK_SZ)) {
/*
* We didn't find the end of the string.
* Add the string to the buffer and move
* the pointer. But do not allow strings
* of unlimited length.
*/
sbuf_bcat(sb, env_string, UIO_CHUNK_SZ);
if (sbuf_len(sb) >= ARG_MAX) {
ret = E2BIG;
goto done;
}
pbegin += UIO_CHUNK_SZ;
} else {
sbuf_cat(sb, env_string);
break;
}
}
sbuf_bcat(sb, "", 1);
}
#undef UIO_HELPER
done:
free(env_vector, M_TEMP);
#ifdef COMPAT_FREEBSD32
free(env_vector32, M_TEMP);
#endif
return (ret);
}
static void
ps_string_argv(const struct ps_strings ps, u_long *addr, int *n)
{
*addr = (u_long) ps.ps_argvstr;
*n = ps.ps_nargvstr;
}
static void
ps_string_env(const struct ps_strings ps, u_long *addr, int *n)
{
*addr = (u_long) ps.ps_envstr;
*n = ps.ps_nenvstr;
}
/*
* Filler function for proc/pid/cmdline
*/
@ -1090,9 +946,15 @@ linprocfs_doproccmdline(PFS_FILL_ARGS)
PROC_UNLOCK(p);
return (0);
}
if ((p->p_flag & P_SYSTEM) != 0) {
PROC_UNLOCK(p);
return (0);
}
PROC_UNLOCK(p);
ret = linprocfs_doargv(td, p, sb, ps_string_argv);
ret = proc_getargv(td, p, sb, ARG_MAX);
return (ret);
}
@ -1118,9 +980,15 @@ linprocfs_doprocenviron(PFS_FILL_ARGS)
PROC_UNLOCK(p);
return (0);
}
if ((p->p_flag & P_SYSTEM) != 0) {
PROC_UNLOCK(p);
return (0);
}
PROC_UNLOCK(p);
ret = linprocfs_doargv(td, p, sb, ps_string_env);
ret = proc_getenvv(td, p, sb, ARG_MAX);
return (ret);
}