1 /*
2  * Copyright (c) 1993, 1995 Jan-Simon Pendry
3  * Copyright (c) 1993, 1995
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Jan-Simon Pendry.
8  *
9  * %sccs.include.redist.c%
10  *
11  *	@(#)procfs_vnops.c	8.17 (Berkeley) 05/14/95
12  *
13  * From:
14  *	$Id: procfs_vnops.c,v 3.2 1993/12/15 09:40:17 jsp Exp $
15  */
16 
17 /*
18  * procfs vnode interface
19  */
20 
21 #include <sys/param.h>
22 #include <sys/systm.h>
23 #include <sys/time.h>
24 #include <sys/kernel.h>
25 #include <sys/file.h>
26 #include <sys/proc.h>
27 #include <sys/vnode.h>
28 #include <sys/namei.h>
29 #include <sys/malloc.h>
30 #include <sys/dirent.h>
31 #include <sys/resourcevar.h>
32 #include <vm/vm.h>	/* for PAGE_SIZE */
33 #include <machine/reg.h>
34 #include <miscfs/procfs/procfs.h>
35 
36 /*
37  * Vnode Operations.
38  *
39  */
40 
41 /*
42  * This is a list of the valid names in the
43  * process-specific sub-directories.  It is
44  * used in procfs_lookup and procfs_readdir
45  */
46 struct proc_target {
47 	u_char	pt_type;
48 	u_char	pt_namlen;
49 	char	*pt_name;
50 	pfstype	pt_pfstype;
51 	int	(*pt_valid) __P((struct proc *p));
52 } proc_targets[] = {
53 #define N(s) sizeof(s)-1, s
54 	/*	  name		type		validp */
55 	{ DT_DIR, N("."),	Pproc,		NULL },
56 	{ DT_DIR, N(".."),	Proot,		NULL },
57 	{ DT_REG, N("file"),	Pfile,		procfs_validfile },
58 	{ DT_REG, N("mem"),	Pmem,		NULL },
59 	{ DT_REG, N("regs"),	Pregs,		procfs_validregs },
60 	{ DT_REG, N("fpregs"),	Pfpregs,	procfs_validfpregs },
61 	{ DT_REG, N("ctl"),	Pctl,		NULL },
62 	{ DT_REG, N("status"),	Pstatus,	NULL },
63 	{ DT_REG, N("note"),	Pnote,		NULL },
64 	{ DT_REG, N("notepg"),	Pnotepg,	NULL },
65 #undef N
66 };
67 static int nproc_targets = sizeof(proc_targets) / sizeof(proc_targets[0]);
68 
69 static pid_t atopid __P((const char *, u_int));
70 
71 /*
72  * set things up for doing i/o on
73  * the pfsnode (vp).  (vp) is locked
74  * on entry, and should be left locked
75  * on exit.
76  *
77  * for procfs we don't need to do anything
78  * in particular for i/o.  all that is done
79  * is to support exclusive open on process
80  * memory images.
81  */
82 procfs_open(ap)
83 	struct vop_open_args /* {
84 		struct vnode *a_vp;
85 		int  a_mode;
86 		struct ucred *a_cred;
87 		struct proc *a_p;
88 	} */ *ap;
89 {
90 	struct pfsnode *pfs = VTOPFS(ap->a_vp);
91 
92 	switch (pfs->pfs_type) {
93 	case Pmem:
94 		if (PFIND(pfs->pfs_pid) == 0)
95 			return (ENOENT);	/* was ESRCH, jsp */
96 
97 		if ((pfs->pfs_flags & FWRITE) && (ap->a_mode & O_EXCL) ||
98 		    (pfs->pfs_flags & O_EXCL) && (ap->a_mode & FWRITE))
99 			return (EBUSY);
100 
101 		if (ap->a_mode & FWRITE)
102 			pfs->pfs_flags = ap->a_mode & (FWRITE|O_EXCL);
103 
104 		return (0);
105 
106 	default:
107 		break;
108 	}
109 
110 	return (0);
111 }
112 
113 /*
114  * close the pfsnode (vp) after doing i/o.
115  * (vp) is not locked on entry or exit.
116  *
117  * nothing to do for procfs other than undo
118  * any exclusive open flag (see _open above).
119  */
120 procfs_close(ap)
121 	struct vop_close_args /* {
122 		struct vnode *a_vp;
123 		int  a_fflag;
124 		struct ucred *a_cred;
125 		struct proc *a_p;
126 	} */ *ap;
127 {
128 	struct pfsnode *pfs = VTOPFS(ap->a_vp);
129 
130 	switch (pfs->pfs_type) {
131 	case Pmem:
132 		if ((ap->a_fflag & FWRITE) && (pfs->pfs_flags & O_EXCL))
133 			pfs->pfs_flags &= ~(FWRITE|O_EXCL);
134 		break;
135 	}
136 
137 	return (0);
138 }
139 
140 /*
141  * do an ioctl operation on pfsnode (vp).
142  * (vp) is not locked on entry or exit.
143  */
144 procfs_ioctl(ap)
145 	struct vop_ioctl_args /* {
146 		struct vnode *a_vp;
147 		int a_command;
148 		caddr_t a_data;
149 		int a_fflag;
150 		struct ucred *a_cred;
151 		struct proc *a_p;
152 	} */ *ap;
153 {
154 
155 	return (ENOTTY);
156 }
157 
158 /*
159  * do block mapping for pfsnode (vp).
160  * since we don't use the buffer cache
161  * for procfs this function should never
162  * be called.  in any case, it's not clear
163  * what part of the kernel ever makes use
164  * of this function.  for sanity, this is the
165  * usual no-op bmap, although returning
166  * (EIO) would be a reasonable alternative.
167  */
168 procfs_bmap(ap)
169 	struct vop_bmap_args /* {
170 		struct vnode *a_vp;
171 		daddr_t  a_bn;
172 		struct vnode **a_vpp;
173 		daddr_t *a_bnp;
174 		int *a_runp;
175 	} */ *ap;
176 {
177 
178 	if (ap->a_vpp != NULL)
179 		*ap->a_vpp = ap->a_vp;
180 	if (ap->a_bnp != NULL)
181 		*ap->a_bnp = ap->a_bn;
182 	if (ap->a_runp != NULL)
183 		*ap->a_runp = 0;
184 	return (0);
185 }
186 
187 /*
188  * _inactive is called when the pfsnode
189  * is vrele'd and the reference count goes
190  * to zero.  (vp) will be on the vnode free
191  * list, so to get it back vget() must be
192  * used.
193  *
194  * for procfs, check if the process is still
195  * alive and if it isn't then just throw away
196  * the vnode by calling vgone().  this may
197  * be overkill and a waste of time since the
198  * chances are that the process will still be
199  * there and PFIND is not free.
200  *
201  * (vp) is not locked on entry or exit.
202  */
203 procfs_inactive(ap)
204 	struct vop_inactive_args /* {
205 		struct vnode *a_vp;
206 	} */ *ap;
207 {
208 	struct pfsnode *pfs = VTOPFS(ap->a_vp);
209 
210 	if (PFIND(pfs->pfs_pid) == 0)
211 		vgone(ap->a_vp);
212 
213 	return (0);
214 }
215 
216 /*
217  * _reclaim is called when getnewvnode()
218  * wants to make use of an entry on the vnode
219  * free list.  at this time the filesystem needs
220  * to free any private data and remove the node
221  * from any private lists.
222  */
223 procfs_reclaim(ap)
224 	struct vop_reclaim_args /* {
225 		struct vnode *a_vp;
226 	} */ *ap;
227 {
228 
229 	return (procfs_freevp(ap->a_vp));
230 }
231 
232 /*
233  * Return POSIX pathconf information applicable to special devices.
234  */
235 procfs_pathconf(ap)
236 	struct vop_pathconf_args /* {
237 		struct vnode *a_vp;
238 		int a_name;
239 		int *a_retval;
240 	} */ *ap;
241 {
242 
243 	switch (ap->a_name) {
244 	case _PC_LINK_MAX:
245 		*ap->a_retval = LINK_MAX;
246 		return (0);
247 	case _PC_MAX_CANON:
248 		*ap->a_retval = MAX_CANON;
249 		return (0);
250 	case _PC_MAX_INPUT:
251 		*ap->a_retval = MAX_INPUT;
252 		return (0);
253 	case _PC_PIPE_BUF:
254 		*ap->a_retval = PIPE_BUF;
255 		return (0);
256 	case _PC_CHOWN_RESTRICTED:
257 		*ap->a_retval = 1;
258 		return (0);
259 	case _PC_VDISABLE:
260 		*ap->a_retval = _POSIX_VDISABLE;
261 		return (0);
262 	default:
263 		return (EINVAL);
264 	}
265 	/* NOTREACHED */
266 }
267 
268 /*
269  * _print is used for debugging.
270  * just print a readable description
271  * of (vp).
272  */
273 procfs_print(ap)
274 	struct vop_print_args /* {
275 		struct vnode *a_vp;
276 	} */ *ap;
277 {
278 	struct pfsnode *pfs = VTOPFS(ap->a_vp);
279 
280 	printf("tag VT_PROCFS, type %s, pid %d, mode %x, flags %x\n",
281 	    pfs->pfs_type, pfs->pfs_pid, pfs->pfs_mode, pfs->pfs_flags);
282 }
283 
284 /*
285  * _abortop is called when operations such as
286  * rename and create fail.  this entry is responsible
287  * for undoing any side-effects caused by the lookup.
288  * this will always include freeing the pathname buffer.
289  */
290 procfs_abortop(ap)
291 	struct vop_abortop_args /* {
292 		struct vnode *a_dvp;
293 		struct componentname *a_cnp;
294 	} */ *ap;
295 {
296 
297 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
298 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
299 	return (0);
300 }
301 
302 /*
303  * generic entry point for unsupported operations
304  */
305 procfs_badop()
306 {
307 
308 	return (EIO);
309 }
310 
311 /*
312  * Invent attributes for pfsnode (vp) and store
313  * them in (vap).
314  * Directories lengths are returned as zero since
315  * any real length would require the genuine size
316  * to be computed, and nothing cares anyway.
317  *
318  * this is relatively minimal for procfs.
319  */
320 procfs_getattr(ap)
321 	struct vop_getattr_args /* {
322 		struct vnode *a_vp;
323 		struct vattr *a_vap;
324 		struct ucred *a_cred;
325 		struct proc *a_p;
326 	} */ *ap;
327 {
328 	struct pfsnode *pfs = VTOPFS(ap->a_vp);
329 	struct vattr *vap = ap->a_vap;
330 	struct proc *procp;
331 	struct timeval tv;
332 	int error;
333 
334 	/* first check the process still exists */
335 	switch (pfs->pfs_type) {
336 	case Proot:
337 	case Pcurproc:
338 		procp = 0;
339 		break;
340 
341 	default:
342 		procp = PFIND(pfs->pfs_pid);
343 		if (procp == 0)
344 			return (ENOENT);
345 	}
346 
347 	error = 0;
348 
349 	/* start by zeroing out the attributes */
350 	VATTR_NULL(vap);
351 
352 	/* next do all the common fields */
353 	vap->va_type = ap->a_vp->v_type;
354 	vap->va_mode = pfs->pfs_mode;
355 	vap->va_fileid = pfs->pfs_fileno;
356 	vap->va_flags = 0;
357 	vap->va_blocksize = PAGE_SIZE;
358 	vap->va_bytes = vap->va_size = 0;
359 
360 	/*
361 	 * Make all times be current TOD.
362 	 * It would be possible to get the process start
363 	 * time from the p_stat structure, but there's
364 	 * no "file creation" time stamp anyway, and the
365 	 * p_stat structure is not addressible if u. gets
366 	 * swapped out for that process.
367 	 */
368 	microtime(&tv);
369 	TIMEVAL_TO_TIMESPEC(&tv, &vap->va_ctime);
370 	vap->va_atime = vap->va_mtime = vap->va_ctime;
371 
372 	/*
373 	 * If the process has exercised some setuid or setgid
374 	 * privilege, then rip away read/write permission so
375 	 * that only root can gain access.
376 	 */
377 	switch (pfs->pfs_type) {
378 	case Pmem:
379 	case Pregs:
380 	case Pfpregs:
381 		if (procp->p_flag & P_SUGID)
382 			vap->va_mode &= ~((VREAD|VWRITE)|
383 					  ((VREAD|VWRITE)>>3)|
384 					  ((VREAD|VWRITE)>>6));
385 	case Pctl:
386 	case Pstatus:
387 	case Pnote:
388 	case Pnotepg:
389 		vap->va_nlink = 1;
390 		vap->va_uid = procp->p_ucred->cr_uid;
391 		vap->va_gid = procp->p_ucred->cr_gid;
392 		break;
393 	}
394 
395 	/*
396 	 * now do the object specific fields
397 	 *
398 	 * The size could be set from struct reg, but it's hardly
399 	 * worth the trouble, and it puts some (potentially) machine
400 	 * dependent data into this machine-independent code.  If it
401 	 * becomes important then this function should break out into
402 	 * a per-file stat function in the corresponding .c file.
403 	 */
404 
405 	switch (pfs->pfs_type) {
406 	case Proot:
407 		/*
408 		 * Set nlink to 1 to tell fts(3) we don't actually know.
409 		 */
410 		vap->va_nlink = 1;
411 		vap->va_uid = 0;
412 		vap->va_gid = 0;
413 		vap->va_size = vap->va_bytes = DEV_BSIZE;
414 		break;
415 
416 	case Pcurproc: {
417 		char buf[16];		/* should be enough */
418 		vap->va_nlink = 1;
419 		vap->va_uid = 0;
420 		vap->va_gid = 0;
421 		vap->va_size = vap->va_bytes =
422 		    sprintf(buf, "%ld", (long)curproc->p_pid);
423 		break;
424 	}
425 
426 	case Pproc:
427 		vap->va_nlink = 2;
428 		vap->va_uid = procp->p_ucred->cr_uid;
429 		vap->va_gid = procp->p_ucred->cr_gid;
430 		vap->va_size = vap->va_bytes = DEV_BSIZE;
431 		break;
432 
433 	case Pfile:
434 		error = EOPNOTSUPP;
435 		break;
436 
437 	case Pmem:
438 		vap->va_bytes = vap->va_size =
439 			ctob(procp->p_vmspace->vm_tsize +
440 				    procp->p_vmspace->vm_dsize +
441 				    procp->p_vmspace->vm_ssize);
442 		break;
443 
444 	case Pregs:
445 		vap->va_bytes = vap->va_size = sizeof(struct reg);
446 		break;
447 
448 	case Pfpregs:
449 		vap->va_bytes = vap->va_size = sizeof(struct fpreg);
450 		break;
451 
452 	case Pctl:
453 	case Pstatus:
454 	case Pnote:
455 	case Pnotepg:
456 		break;
457 
458 	default:
459 		panic("procfs_getattr");
460 	}
461 
462 	return (error);
463 }
464 
465 procfs_setattr(ap)
466 	struct vop_setattr_args /* {
467 		struct vnode *a_vp;
468 		struct vattr *a_vap;
469 		struct ucred *a_cred;
470 		struct proc *a_p;
471 	} */ *ap;
472 {
473 	/*
474 	 * just fake out attribute setting
475 	 * it's not good to generate an error
476 	 * return, otherwise things like creat()
477 	 * will fail when they try to set the
478 	 * file length to 0.  worse, this means
479 	 * that echo $note > /proc/$pid/note will fail.
480 	 */
481 
482 	return (0);
483 }
484 
485 /*
486  * implement access checking.
487  *
488  * something very similar to this code is duplicated
489  * throughout the 4bsd kernel and should be moved
490  * into kern/vfs_subr.c sometime.
491  *
492  * actually, the check for super-user is slightly
493  * broken since it will allow read access to write-only
494  * objects.  this doesn't cause any particular trouble
495  * but does mean that the i/o entry points need to check
496  * that the operation really does make sense.
497  */
498 procfs_access(ap)
499 	struct vop_access_args /* {
500 		struct vnode *a_vp;
501 		int a_mode;
502 		struct ucred *a_cred;
503 		struct proc *a_p;
504 	} */ *ap;
505 {
506 	struct vattr *vap;
507 	struct vattr vattr;
508 	int error;
509 
510 	/*
511 	 * If you're the super-user,
512 	 * you always get access.
513 	 */
514 	if (ap->a_cred->cr_uid == 0)
515 		return (0);
516 
517 	vap = &vattr;
518 	if (error = VOP_GETATTR(ap->a_vp, vap, ap->a_cred, ap->a_p))
519 		return (error);
520 
521 	/*
522 	 * Access check is based on only one of owner, group, public.
523 	 * If not owner, then check group. If not a member of the
524 	 * group, then check public access.
525 	 */
526 	if (ap->a_cred->cr_uid != vap->va_uid) {
527 		gid_t *gp;
528 		int i;
529 
530 		ap->a_mode >>= 3;
531 		gp = ap->a_cred->cr_groups;
532 		for (i = 0; i < ap->a_cred->cr_ngroups; i++, gp++)
533 			if (vap->va_gid == *gp)
534 				goto found;
535 		ap->a_mode >>= 3;
536 found:
537 		;
538 	}
539 
540 	if ((vap->va_mode & ap->a_mode) == ap->a_mode)
541 		return (0);
542 
543 	return (EACCES);
544 }
545 
546 /*
547  * lookup.  this is incredibly complicated in the
548  * general case, however for most pseudo-filesystems
549  * very little needs to be done.
550  *
551  * unless you want to get a migraine, just make sure your
552  * filesystem doesn't do any locking of its own.  otherwise
553  * read and inwardly digest ufs_lookup().
554  */
555 procfs_lookup(ap)
556 	struct vop_lookup_args /* {
557 		struct vnode * a_dvp;
558 		struct vnode ** a_vpp;
559 		struct componentname * a_cnp;
560 	} */ *ap;
561 {
562 	struct componentname *cnp = ap->a_cnp;
563 	struct vnode **vpp = ap->a_vpp;
564 	struct vnode *dvp = ap->a_dvp;
565 	char *pname = cnp->cn_nameptr;
566 	struct proc *curp = cnp->cn_proc;
567 	int error = 0;
568 	struct proc_target *pt;
569 	struct vnode *fvp;
570 	pid_t pid;
571 	struct pfsnode *pfs;
572 	struct proc *p;
573 	int i;
574 
575 	*vpp = NULL;
576 
577 	if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
578 		return (EROFS);
579 
580 	if (cnp->cn_namelen == 1 && *pname == '.') {
581 		*vpp = dvp;
582 		VREF(dvp);
583 		/* vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, curp); */
584 		return (0);
585 	}
586 
587 	pfs = VTOPFS(dvp);
588 	switch (pfs->pfs_type) {
589 	case Proot:
590 		if (cnp->cn_flags & ISDOTDOT)
591 			return (EIO);
592 
593 		if (CNEQ(cnp, "curproc", 7))
594 			return (procfs_allocvp(dvp->v_mount, vpp, 0, Pcurproc));
595 
596 		pid = atopid(pname, cnp->cn_namelen);
597 		if (pid == NO_PID)
598 			break;
599 
600 		p = PFIND(pid);
601 		if (p == 0)
602 			break;
603 
604 		return (procfs_allocvp(dvp->v_mount, vpp, pid, Pproc));
605 
606 	case Pproc:
607 		if (cnp->cn_flags & ISDOTDOT)
608 			return (procfs_root(dvp->v_mount, vpp));
609 
610 		p = PFIND(pfs->pfs_pid);
611 		if (p == 0)
612 			break;
613 
614 		for (pt = proc_targets, i = 0; i < nproc_targets; pt++, i++) {
615 			if (cnp->cn_namelen == pt->pt_namlen &&
616 			    bcmp(pt->pt_name, pname, cnp->cn_namelen) == 0 &&
617 			    (pt->pt_valid == NULL || (*pt->pt_valid)(p)))
618 				goto found;
619 		}
620 		break;
621 
622 	found:
623 		if (pt->pt_pfstype == Pfile) {
624 			fvp = procfs_findtextvp(p);
625 			/* We already checked that it exists. */
626 			VREF(fvp);
627 			vn_lock(fvp, LK_EXCLUSIVE | LK_RETRY, curp);
628 			*vpp = fvp;
629 			return (0);
630 		}
631 
632 		return (procfs_allocvp(dvp->v_mount, vpp, pfs->pfs_pid,
633 		    pt->pt_pfstype));
634 
635 	default:
636 		return (ENOTDIR);
637 	}
638 
639 	return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS);
640 }
641 
642 int
643 procfs_validfile(p)
644 	struct proc *p;
645 {
646 
647 	return (procfs_findtextvp(p) != NULLVP);
648 }
649 
650 /*
651  * readdir returns directory entries from pfsnode (vp).
652  *
653  * the strategy here with procfs is to generate a single
654  * directory entry at a time (struct pfsdent) and then
655  * copy that out to userland using uiomove.  a more efficent
656  * though more complex implementation, would try to minimize
657  * the number of calls to uiomove().  for procfs, this is
658  * hardly worth the added code complexity.
659  *
660  * this should just be done through read()
661  */
662 procfs_readdir(ap)
663 	struct vop_readdir_args /* {
664 		struct vnode *a_vp;
665 		struct uio *a_uio;
666 		struct ucred *a_cred;
667 		int *a_eofflag;
668 		u_long *a_cookies;
669 		int a_ncookies;
670 	} */ *ap;
671 {
672 	struct uio *uio = ap->a_uio;
673 	struct pfsdent d;
674 	struct pfsdent *dp = &d;
675 	struct pfsnode *pfs;
676 	int error;
677 	int count;
678 	int i;
679 
680 	/*
681 	 * We don't allow exporting procfs mounts, and currently local
682 	 * requests do not need cookies.
683 	 */
684 	if (ap->a_ncookies)
685 		panic("procfs_readdir: not hungry");
686 
687 	pfs = VTOPFS(ap->a_vp);
688 
689 	if (uio->uio_resid < UIO_MX)
690 		return (EINVAL);
691 	if (uio->uio_offset & (UIO_MX-1))
692 		return (EINVAL);
693 	if (uio->uio_offset < 0)
694 		return (EINVAL);
695 
696 	error = 0;
697 	count = 0;
698 	i = uio->uio_offset / UIO_MX;
699 
700 	switch (pfs->pfs_type) {
701 	/*
702 	 * this is for the process-specific sub-directories.
703 	 * all that is needed to is copy out all the entries
704 	 * from the procent[] table (top of this file).
705 	 */
706 	case Pproc: {
707 		struct proc *p;
708 		struct proc_target *pt;
709 
710 		p = PFIND(pfs->pfs_pid);
711 		if (p == NULL)
712 			break;
713 
714 		for (pt = &proc_targets[i];
715 		     uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) {
716 			if (pt->pt_valid && (*pt->pt_valid)(p) == 0)
717 				continue;
718 
719 			dp->d_reclen = UIO_MX;
720 			dp->d_fileno = PROCFS_FILENO(pfs->pfs_pid, pt->pt_pfstype);
721 			dp->d_namlen = pt->pt_namlen;
722 			bcopy(pt->pt_name, dp->d_name, pt->pt_namlen + 1);
723 			dp->d_type = pt->pt_type;
724 
725 			if (error = uiomove((caddr_t)dp, UIO_MX, uio))
726 				break;
727 		}
728 
729 	    	break;
730 	    }
731 
732 	/*
733 	 * this is for the root of the procfs filesystem
734 	 * what is needed is a special entry for "curproc"
735 	 * followed by an entry for each process on allproc
736 #ifdef PROCFS_ZOMBIE
737 	 * and zombproc.
738 #endif
739 	 */
740 
741 	case Proot: {
742 #ifdef PROCFS_ZOMBIE
743 		int doingzomb = 0;
744 #endif
745 		int pcnt = 0;
746 		volatile struct proc *p = allproc.lh_first;
747 
748 	again:
749 		for (; p && uio->uio_resid >= UIO_MX; i++, pcnt++) {
750 			bzero((char *) dp, UIO_MX);
751 			dp->d_reclen = UIO_MX;
752 
753 			switch (i) {
754 			case 0:		/* `.' */
755 			case 1:		/* `..' */
756 				dp->d_fileno = PROCFS_FILENO(0, Proot);
757 				dp->d_namlen = i + 1;
758 				bcopy("..", dp->d_name, dp->d_namlen);
759 				dp->d_name[i + 1] = '\0';
760 				dp->d_type = DT_DIR;
761 				break;
762 
763 			case 2:
764 				dp->d_fileno = PROCFS_FILENO(0, Pcurproc);
765 				dp->d_namlen = 7;
766 				bcopy("curproc", dp->d_name, 8);
767 				dp->d_type = DT_LNK;
768 				break;
769 
770 			default:
771 				while (pcnt < i) {
772 					pcnt++;
773 					p = p->p_list.le_next;
774 					if (!p)
775 						goto done;
776 				}
777 				dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc);
778 				dp->d_namlen = sprintf(dp->d_name, "%ld",
779 				    (long)p->p_pid);
780 				dp->d_type = DT_REG;
781 				p = p->p_list.le_next;
782 				break;
783 			}
784 
785 			if (error = uiomove((caddr_t)dp, UIO_MX, uio))
786 				break;
787 		}
788 	done:
789 
790 #ifdef PROCFS_ZOMBIE
791 		if (p == 0 && doingzomb == 0) {
792 			doingzomb = 1;
793 			p = zombproc.lh_first;
794 			goto again;
795 		}
796 #endif
797 
798 		break;
799 
800 	    }
801 
802 	default:
803 		error = ENOTDIR;
804 		break;
805 	}
806 
807 	uio->uio_offset = i * UIO_MX;
808 
809 	return (error);
810 }
811 
812 /*
813  * readlink reads the link of `curproc'
814  */
815 procfs_readlink(ap)
816 	struct vop_readlink_args *ap;
817 {
818 	struct uio *uio = ap->a_uio;
819 	char buf[16];		/* should be enough */
820 	int len;
821 
822 	if (VTOPFS(ap->a_vp)->pfs_fileno != PROCFS_FILENO(0, Pcurproc))
823 		return (EINVAL);
824 
825 	len = sprintf(buf, "%ld", (long)curproc->p_pid);
826 
827 	return (uiomove((caddr_t)buf, len, ap->a_uio));
828 }
829 
830 /*
831  * convert decimal ascii to pid_t
832  */
833 static pid_t
834 atopid(b, len)
835 	const char *b;
836 	u_int len;
837 {
838 	pid_t p = 0;
839 
840 	while (len--) {
841 		char c = *b++;
842 		if (c < '0' || c > '9')
843 			return (NO_PID);
844 		p = 10 * p + (c - '0');
845 		if (p > PID_MAX)
846 			return (NO_PID);
847 	}
848 
849 	return (p);
850 }
851 
852 /*
853  * procfs vnode operations.
854  */
855 int (**procfs_vnodeop_p)();
856 struct vnodeopv_entry_desc procfs_vnodeop_entries[] = {
857 	{ &vop_default_desc, vn_default_error },
858 	{ &vop_lookup_desc, procfs_lookup },		/* lookup */
859 	{ &vop_create_desc, procfs_create },		/* create */
860 	{ &vop_mknod_desc, procfs_mknod },		/* mknod */
861 	{ &vop_open_desc, procfs_open },		/* open */
862 	{ &vop_close_desc, procfs_close },		/* close */
863 	{ &vop_access_desc, procfs_access },		/* access */
864 	{ &vop_getattr_desc, procfs_getattr },		/* getattr */
865 	{ &vop_setattr_desc, procfs_setattr },		/* setattr */
866 	{ &vop_read_desc, procfs_read },		/* read */
867 	{ &vop_write_desc, procfs_write },		/* write */
868 	{ &vop_ioctl_desc, procfs_ioctl },		/* ioctl */
869 	{ &vop_select_desc, procfs_select },		/* select */
870 	{ &vop_mmap_desc, procfs_mmap },		/* mmap */
871 	{ &vop_revoke_desc, procfs_revoke },		/* revoke */
872 	{ &vop_fsync_desc, procfs_fsync },		/* fsync */
873 	{ &vop_seek_desc, procfs_seek },		/* seek */
874 	{ &vop_remove_desc, procfs_remove },		/* remove */
875 	{ &vop_link_desc, procfs_link },		/* link */
876 	{ &vop_rename_desc, procfs_rename },		/* rename */
877 	{ &vop_mkdir_desc, procfs_mkdir },		/* mkdir */
878 	{ &vop_rmdir_desc, procfs_rmdir },		/* rmdir */
879 	{ &vop_symlink_desc, procfs_symlink },		/* symlink */
880 	{ &vop_readdir_desc, procfs_readdir },		/* readdir */
881 	{ &vop_readlink_desc, procfs_readlink },	/* readlink */
882 	{ &vop_abortop_desc, procfs_abortop },		/* abortop */
883 	{ &vop_inactive_desc, procfs_inactive },	/* inactive */
884 	{ &vop_reclaim_desc, procfs_reclaim },		/* reclaim */
885 	{ &vop_lock_desc, procfs_lock },		/* lock */
886 	{ &vop_unlock_desc, procfs_unlock },		/* unlock */
887 	{ &vop_bmap_desc, procfs_bmap },		/* bmap */
888 	{ &vop_strategy_desc, procfs_strategy },	/* strategy */
889 	{ &vop_print_desc, procfs_print },		/* print */
890 	{ &vop_islocked_desc, procfs_islocked },	/* islocked */
891 	{ &vop_pathconf_desc, procfs_pathconf },	/* pathconf */
892 	{ &vop_advlock_desc, procfs_advlock },		/* advlock */
893 	{ &vop_blkatoff_desc, procfs_blkatoff },	/* blkatoff */
894 	{ &vop_valloc_desc, procfs_valloc },		/* valloc */
895 	{ &vop_vfree_desc, procfs_vfree },		/* vfree */
896 	{ &vop_truncate_desc, procfs_truncate },	/* truncate */
897 	{ &vop_update_desc, procfs_update },		/* update */
898 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
899 };
900 struct vnodeopv_desc procfs_vnodeop_opv_desc =
901 	{ &procfs_vnodeop_p, procfs_vnodeop_entries };
902