FreeBSD/sys/kern/kern_proc.c
/*
 * This sysctl allows a process to retrieve the path of the executable for
 * itself or another process.
 */
This sysctl allows a process to retrieve the path of the executable for
itself or another process.
This sysctl allows a process to retrieve the path of the executable for itself or another process .
static int
sysctl_kern_proc_pathname(SYSCTL_HANDLER_ARGS)
{
	pid_t *pidp = (pid_t *)arg1;
	unsigned int arglen = arg2;
	struct proc *p;
	struct vnode *vp;
	char *retbuf, *freebuf;
	int error;
	if (arglen != 1)
		return (EINVAL);
	if (*pidp == -1) {	
		p = req->td->td_proc;
	} else {
		error = pget(*pidp, PGET_CANSEE, &p);
		if (error != 0)
			return (error);
	}
	vp = p->p_textvp;
	if (vp == NULL) {
		if (*pidp != -1)
			PROC_UNLOCK(p);
		return (0);
	}
	vref(vp);
	if (*pidp != -1)
		PROC_UNLOCK(p);
	error = vn_fullpath(req->td, vp, &retbuf, &freebuf);
	vrele(vp);
	if (error)
		return (error);
	error = SYSCTL_OUT(req, retbuf, strlen(retbuf) + 1);
	free(freebuf, M_TEMP);
	return (error);
}
static int sysctl_kern_proc_pathname ( SYSCTL_HANDLER_ARGS ) { pid_t * pidp = ( pid_t * ) arg1 ; unsigned int arglen = arg2 ; struct proc * p ; struct vnode * vp ; char * retbuf , * freebuf ; int error ; if ( arglen != 1 ) return ( EINVAL ) ; if ( * pidp == -1 ) { p = req -> td -> td_proc ; } else { error = pget ( * pidp , PGET_CANSEE , & p ) ; if ( error != 0 ) return ( error ) ; } vp = p -> p_textvp ; if ( vp == NULL ) { if ( * pidp != -1 ) PROC_UNLOCK ( p ) ; return ( 0 ) ; } vref ( vp ) ; if ( * pidp != -1 ) PROC_UNLOCK ( p ) ; error = vn_fullpath ( req -> td , vp , & retbuf , & freebuf ) ; vrele ( vp ) ; if ( error ) return ( error ) ; error = SYSCTL_OUT ( req , retbuf , strlen ( retbuf ) + 1 ) ; free ( freebuf , M_TEMP ) ; return ( error ) ; }
This sysctl allows a process to retrieve the path of the executable for
 itself or another process.
This sysctl allows a process to retrieve the path of the executable for itself or another process .
/* -1 means this process */