linprocfs.c revision 76827
159412Smsmith/*
265577Sdes * Copyright (c) 2000 Dag-Erling Co�dan Sm�rgrav
365577Sdes * Copyright (c) 1999 Pierre Beyssac
459412Smsmith * Copyright (c) 1993 Jan-Simon Pendry
559412Smsmith * Copyright (c) 1993
659412Smsmith *	The Regents of the University of California.  All rights reserved.
759412Smsmith *
859412Smsmith * This code is derived from software contributed to Berkeley by
959412Smsmith * Jan-Simon Pendry.
1059412Smsmith *
1159412Smsmith * Redistribution and use in source and binary forms, with or without
1259412Smsmith * modification, are permitted provided that the following conditions
1359412Smsmith * are met:
1459412Smsmith * 1. Redistributions of source code must retain the above copyright
1559412Smsmith *    notice, this list of conditions and the following disclaimer.
1659412Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1759412Smsmith *    notice, this list of conditions and the following disclaimer in the
1859412Smsmith *    documentation and/or other materials provided with the distribution.
1959412Smsmith * 3. All advertising materials mentioning features or use of this software
2059412Smsmith *    must display the following acknowledgement:
2159412Smsmith *	This product includes software developed by the University of
2259412Smsmith *	California, Berkeley and its contributors.
2359412Smsmith * 4. Neither the name of the University nor the names of its contributors
2459412Smsmith *    may be used to endorse or promote products derived from this software
2559412Smsmith *    without specific prior written permission.
2659412Smsmith *
2759412Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2859412Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2959412Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3059412Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3159412Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3259412Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3359412Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3459412Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3559412Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3659412Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3759412Smsmith * SUCH DAMAGE.
3859412Smsmith *
3959412Smsmith *	@(#)procfs_status.c	8.4 (Berkeley) 6/15/94
4059412Smsmith *
4159412Smsmith * $FreeBSD: head/sys/compat/linprocfs/linprocfs.c 76827 2001-05-19 01:28:09Z alfred $
4259412Smsmith */
4359412Smsmith
4459412Smsmith#include <sys/param.h>
4576166Smarkm#include <sys/systm.h>
4676166Smarkm#include <sys/blist.h>
4774135Sjlemon#include <sys/conf.h>
4865633Sdes#include <sys/dkstat.h>
4976166Smarkm#include <sys/jail.h>
5065633Sdes#include <sys/kernel.h>
5176166Smarkm#include <sys/lock.h>
5274135Sjlemon#include <sys/malloc.h>
5376827Salfred#include <sys/mutex.h>
5465633Sdes#include <sys/proc.h>
5565633Sdes#include <sys/resourcevar.h>
5669995Sdes#include <sys/sbuf.h>
5765633Sdes#include <sys/tty.h>
5859412Smsmith#include <sys/vnode.h>
5959412Smsmith
6059412Smsmith#include <vm/vm.h>
6159412Smsmith#include <vm/pmap.h>
6267588Sdes#include <vm/vm_map.h>
6359412Smsmith#include <vm/vm_param.h>
6460860Sdes#include <vm/vm_object.h>
6569995Sdes#include <vm/vm_zone.h>
6659412Smsmith#include <vm/swap_pager.h>
6769799Sdes
6869799Sdes#include <sys/exec.h>
6969799Sdes#include <sys/user.h>
7059412Smsmith#include <sys/vmmeter.h>
7159412Smsmith
7267589Sdes#include <machine/clock.h>
7367589Sdes#include <machine/cputypes.h>
7459412Smsmith#include <machine/md_var.h>
7559412Smsmith
7674135Sjlemon#include <sys/socket.h>
7774135Sjlemon#include <net/if.h>
7874135Sjlemon
7969995Sdes#include <compat/linux/linux_mib.h>
8069933Sdes#include <compat/linprocfs/linprocfs.h>
8159412Smsmith
8274135Sjlemonextern struct 	cdevsw *cdevsw[];
8374135Sjlemon
8467588Sdes/*
8567588Sdes * Various conversion macros
8667588Sdes */
8776405Sdes#define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz))	/* ticks to jiffies */
8867588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz))		/* ticks to seconds */
8967588Sdes#define B2K(x) ((x) >> 10)				/* bytes to kbytes */
9069799Sdes#define B2P(x) ((x) >> PAGE_SHIFT)			/* bytes to pages */
9167588Sdes#define P2B(x) ((x) << PAGE_SHIFT)			/* pages to bytes */
9267588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10))		/* pages to kbytes */
9374135Sjlemon
9474135Sjlemon#define COMMON_START						\
9574135Sjlemon	struct sbuf sb;						\
9674135Sjlemon	char *ps;						\
9774135Sjlemon	int error, xlen
9874135Sjlemon
9974135Sjlemon#define COMMON_END						\
10074135Sjlemon	sbuf_finish(&sb);					\
10174135Sjlemon	ps = sbuf_data(&sb) + uio->uio_offset;			\
10274135Sjlemon	xlen = sbuf_len(&sb) -  uio->uio_offset;		\
10374135Sjlemon	xlen = imin(xlen, uio->uio_resid);			\
10474135Sjlemon	error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));	\
10574135Sjlemon	sbuf_delete(&sb);					\
10674135Sjlemon	return (error)
10769799Sdes
10859412Smsmithint
10959412Smsmithlinprocfs_domeminfo(curp, p, pfs, uio)
11059412Smsmith	struct proc *curp;
11159412Smsmith	struct proc *p;
11259412Smsmith	struct pfsnode *pfs;
11359412Smsmith	struct uio *uio;
11459412Smsmith{
11574135Sjlemon	COMMON_START;
11659412Smsmith	unsigned long memtotal;		/* total memory in bytes */
11759412Smsmith	unsigned long memused;		/* used memory in bytes */
11859412Smsmith	unsigned long memfree;		/* free memory in bytes */
11959412Smsmith	unsigned long memshared;	/* shared memory ??? */
12059412Smsmith	unsigned long buffers, cached;	/* buffer / cache memory ??? */
12159412Smsmith	unsigned long swaptotal;	/* total swap space in bytes */
12259412Smsmith	unsigned long swapused;		/* used swap space in bytes */
12359412Smsmith	unsigned long swapfree;		/* free swap space in bytes */
12460860Sdes	vm_object_t object;
12559412Smsmith
12659412Smsmith	if (uio->uio_rw != UIO_READ)
12759412Smsmith		return (EOPNOTSUPP);
12859412Smsmith
12959412Smsmith	memtotal = physmem * PAGE_SIZE;
13059412Smsmith	/*
13159412Smsmith	 * The correct thing here would be:
13259412Smsmith	 *
13359412Smsmith	memfree = cnt.v_free_count * PAGE_SIZE;
13459412Smsmith	memused = memtotal - memfree;
13559412Smsmith	 *
13659412Smsmith	 * but it might mislead linux binaries into thinking there
13759412Smsmith	 * is very little memory left, so we cheat and tell them that
13859412Smsmith	 * all memory that isn't wired down is free.
13959412Smsmith	 */
14059412Smsmith	memused = cnt.v_wire_count * PAGE_SIZE;
14159412Smsmith	memfree = memtotal - memused;
14264560Sbde	if (swapblist == NULL) {
14364560Sbde		swaptotal = 0;
14464560Sbde		swapfree = 0;
14564560Sbde	} else {
14664560Sbde		swaptotal = swapblist->bl_blocks * 1024; /* XXX why 1024? */
14764560Sbde		swapfree = swapblist->bl_root->u.bmu_avail * PAGE_SIZE;
14864560Sbde	}
14959412Smsmith	swapused = swaptotal - swapfree;
15060860Sdes	memshared = 0;
15171471Sjhb	TAILQ_FOREACH(object, &vm_object_list, object_list)
15260860Sdes		if (object->shadow_count > 1)
15360860Sdes			memshared += object->resident_page_count;
15460860Sdes	memshared *= PAGE_SIZE;
15559412Smsmith	/*
15659412Smsmith	 * We'd love to be able to write:
15759412Smsmith	 *
15859412Smsmith	buffers = bufspace;
15959412Smsmith	 *
16059412Smsmith	 * but bufspace is internal to vfs_bio.c and we don't feel
16159412Smsmith	 * like unstaticizing it just for linprocfs's sake.
16259412Smsmith	 */
16359412Smsmith	buffers = 0;
16459412Smsmith	cached = cnt.v_cache_count * PAGE_SIZE;
16559412Smsmith
16669995Sdes	sbuf_new(&sb, NULL, 512, 0);
16769995Sdes	sbuf_printf(&sb,
16869799Sdes	    "        total:    used:    free:  shared: buffers:  cached:\n"
16969799Sdes	    "Mem:  %lu %lu %lu %lu %lu %lu\n"
17069799Sdes	    "Swap: %lu %lu %lu\n"
17169799Sdes	    "MemTotal: %9lu kB\n"
17269799Sdes	    "MemFree:  %9lu kB\n"
17369799Sdes	    "MemShared:%9lu kB\n"
17469799Sdes	    "Buffers:  %9lu kB\n"
17569799Sdes	    "Cached:   %9lu kB\n"
17669799Sdes	    "SwapTotal:%9lu kB\n"
17769799Sdes	    "SwapFree: %9lu kB\n",
17869799Sdes	    memtotal, memused, memfree, memshared, buffers, cached,
17969799Sdes	    swaptotal, swapused, swapfree,
18069799Sdes	    B2K(memtotal), B2K(memfree),
18169799Sdes	    B2K(memshared), B2K(buffers), B2K(cached),
18269799Sdes	    B2K(swaptotal), B2K(swapfree));
18359412Smsmith
18474135Sjlemon	COMMON_END;
18559412Smsmith}
18659412Smsmith
18759412Smsmithint
18859412Smsmithlinprocfs_docpuinfo(curp, p, pfs, uio)
18959412Smsmith	struct proc *curp;
19059412Smsmith	struct proc *p;
19159412Smsmith	struct pfsnode *pfs;
19259412Smsmith	struct uio *uio;
19359412Smsmith{
19474135Sjlemon	COMMON_START;
19569799Sdes	int class, i, fqmhz, fqkhz;
19659412Smsmith
19769799Sdes	/*
19869799Sdes         * We default the flags to include all non-conflicting flags,
19969799Sdes         * and the Intel versions of conflicting flags.
20069799Sdes	 */
20167589Sdes        static char *flags[] = {
20267589Sdes		"fpu",      "vme",     "de",       "pse",      "tsc",
20367589Sdes		"msr",      "pae",     "mce",      "cx8",      "apic",
20467589Sdes		"sep",      "sep",     "mtrr",     "pge",      "mca",
20567589Sdes		"cmov",     "pat",     "pse36",    "pn",       "b19",
20667589Sdes		"b20",      "b21",     "mmxext",   "mmx",      "fxsr",
20767589Sdes		"xmm",      "b26",     "b27",      "b28",      "b29",
20867589Sdes		"3dnowext", "3dnow"
20967589Sdes	};
21067589Sdes
21159412Smsmith	if (uio->uio_rw != UIO_READ)
21259412Smsmith		return (EOPNOTSUPP);
21359412Smsmith
21459412Smsmith	switch (cpu_class) {
21559412Smsmith	case CPUCLASS_286:
21667589Sdes		class = 2;
21759412Smsmith		break;
21859412Smsmith	case CPUCLASS_386:
21967589Sdes		class = 3;
22059412Smsmith		break;
22159412Smsmith	case CPUCLASS_486:
22267589Sdes		class = 4;
22359412Smsmith		break;
22459412Smsmith	case CPUCLASS_586:
22567589Sdes		class = 5;
22659412Smsmith		break;
22759412Smsmith	case CPUCLASS_686:
22867589Sdes		class = 6;
22959412Smsmith		break;
23059412Smsmith	default:
23167589Sdes                class = 0;
23259412Smsmith		break;
23359412Smsmith	}
23459412Smsmith
23569995Sdes	sbuf_new(&sb, NULL, 512, 0);
23669995Sdes	sbuf_printf(&sb,
23769799Sdes            "processor\t: %d\n"
23869799Sdes	    "vendor_id\t: %.20s\n"
23969799Sdes	    "cpu family\t: %d\n"
24069799Sdes	    "model\t\t: %d\n"
24169799Sdes	    "stepping\t: %d\n",
24269799Sdes	    0, cpu_vendor, class, cpu, cpu_id & 0xf);
24359412Smsmith
24469995Sdes        sbuf_cat(&sb,
24569799Sdes            "flags\t\t:");
24667589Sdes
24767589Sdes        if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) {
24867589Sdes		flags[16] = "fcmov";
24967589Sdes        } else if (!strcmp(cpu_vendor, "CyrixInstead")) {
25067589Sdes		flags[24] = "cxmmx";
25167589Sdes        }
25267589Sdes
25367589Sdes        for (i = 0; i < 32; i++)
25467589Sdes		if (cpu_feature & (1 << i))
25569995Sdes			sbuf_printf(&sb, " %s", flags[i]);
25669995Sdes	sbuf_cat(&sb, "\n");
25767589Sdes        if (class >= 5) {
25869799Sdes		fqmhz = (tsc_freq + 4999) / 1000000;
25969799Sdes		fqkhz = ((tsc_freq + 4999) / 10000) % 100;
26069995Sdes		sbuf_printf(&sb,
26169799Sdes		    "cpu MHz\t\t: %d.%02d\n"
26269799Sdes		    "bogomips\t: %d.%02d\n",
26369799Sdes		    fqmhz, fqkhz, fqmhz, fqkhz);
26467589Sdes        }
26569995Sdes
26674135Sjlemon	COMMON_END;
26759412Smsmith}
26865633Sdes
26965633Sdesint
27065633Sdeslinprocfs_dostat(curp, p, pfs, uio)
27165633Sdes	struct proc *curp;
27265633Sdes	struct proc *p;
27365633Sdes	struct pfsnode *pfs;
27465633Sdes	struct uio *uio;
27565633Sdes{
27674135Sjlemon	COMMON_START;
27765633Sdes
27869995Sdes	sbuf_new(&sb, NULL, 512, 0);
27969995Sdes	sbuf_printf(&sb,
28069799Sdes	    "cpu %ld %ld %ld %ld\n"
28169799Sdes	    "disk 0 0 0 0\n"
28269799Sdes	    "page %u %u\n"
28369799Sdes	    "swap %u %u\n"
28469799Sdes	    "intr %u\n"
28569799Sdes	    "ctxt %u\n"
28669799Sdes	    "btime %ld\n",
28769799Sdes	    T2J(cp_time[CP_USER]),
28869799Sdes	    T2J(cp_time[CP_NICE]),
28969799Sdes	    T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
29069799Sdes	    T2J(cp_time[CP_IDLE]),
29169799Sdes	    cnt.v_vnodepgsin,
29269799Sdes	    cnt.v_vnodepgsout,
29369799Sdes	    cnt.v_swappgsin,
29469799Sdes	    cnt.v_swappgsout,
29569799Sdes	    cnt.v_intr,
29669799Sdes	    cnt.v_swtch,
29769799Sdes	    boottime.tv_sec);
29869995Sdes
29974135Sjlemon	COMMON_END;
30065633Sdes}
30165633Sdes
30265633Sdesint
30365633Sdeslinprocfs_douptime(curp, p, pfs, uio)
30465633Sdes	struct proc *curp;
30565633Sdes	struct proc *p;
30665633Sdes	struct pfsnode *pfs;
30765633Sdes	struct uio *uio;
30865633Sdes{
30974135Sjlemon	COMMON_START;
31065633Sdes	struct timeval tv;
31165633Sdes
31265633Sdes	getmicrouptime(&tv);
31369995Sdes	sbuf_new(&sb, NULL, 64, 0);
31469995Sdes	sbuf_printf(&sb, "%ld.%02ld %ld.%02ld\n",
31569799Sdes	    tv.tv_sec, tv.tv_usec / 10000,
31669799Sdes	    T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100);
31774135Sjlemon
31874135Sjlemon	COMMON_END;
31965633Sdes}
32065633Sdes
32165633Sdesint
32265633Sdeslinprocfs_doversion(curp, p, pfs, uio)
32365633Sdes	struct proc *curp;
32465633Sdes	struct proc *p;
32565633Sdes	struct pfsnode *pfs;
32665633Sdes	struct uio *uio;
32765633Sdes{
32874135Sjlemon	COMMON_START;
32965633Sdes
33069995Sdes	sbuf_new(&sb, NULL, 128, 0);
33169995Sdes	sbuf_printf(&sb,
33269995Sdes	    "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")"
33369995Sdes	    " #4 Sun Dec 18 04:30:00 CET 1977\n",
33469995Sdes	    linux_get_osname(curp),
33569995Sdes	    linux_get_osrelease(curp));
33674135Sjlemon
33774135Sjlemon	COMMON_END;
33865633Sdes}
33965633Sdes
34067588Sdesint
34167588Sdeslinprocfs_doprocstat(curp, p, pfs, uio)
34267588Sdes    	struct proc *curp;
34367588Sdes	struct proc *p;
34467588Sdes	struct pfsnode *pfs;
34567588Sdes	struct uio *uio;
34667588Sdes{
34774135Sjlemon	COMMON_START;
34869995Sdes	struct kinfo_proc kp;
34967588Sdes
35069995Sdes	fill_kinfo_proc(p, &kp);
35169995Sdes	sbuf_new(&sb, NULL, 1024, 0);
35269995Sdes	sbuf_printf(&sb, "%d", p->p_pid);
35369995Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(&sb, " " fmt, arg)
35467588Sdes	PS_ADD("comm",		"(%s)",	p->p_comm);
35567588Sdes	PS_ADD("statr",		"%c",	'0'); /* XXX */
35673923Sjhb	PROC_LOCK(p);
35773923Sjhb	PS_ADD("ppid",		"%d",	p->p_pptr ? p->p_pptr->p_pid : 0);
35873923Sjhb	PROC_UNLOCK(p);
35967588Sdes	PS_ADD("pgrp",		"%d",	p->p_pgid);
36067588Sdes	PS_ADD("session",	"%d",	p->p_session->s_sid);
36167588Sdes	PS_ADD("tty",		"%d",	0); /* XXX */
36267588Sdes	PS_ADD("tpgid",		"%d",	0); /* XXX */
36367588Sdes	PS_ADD("flags",		"%u",	0); /* XXX */
36467588Sdes	PS_ADD("minflt",	"%u",	0); /* XXX */
36567588Sdes	PS_ADD("cminflt",	"%u",	0); /* XXX */
36667588Sdes	PS_ADD("majflt",	"%u",	0); /* XXX */
36767588Sdes	PS_ADD("cminflt",	"%u",	0); /* XXX */
36867588Sdes	PS_ADD("utime",		"%d",	0); /* XXX */
36967588Sdes	PS_ADD("stime",		"%d",	0); /* XXX */
37067588Sdes	PS_ADD("cutime",	"%d",	0); /* XXX */
37167588Sdes	PS_ADD("cstime",	"%d",	0); /* XXX */
37267588Sdes	PS_ADD("counter",	"%d",	0); /* XXX */
37367588Sdes	PS_ADD("priority",	"%d",	0); /* XXX */
37467588Sdes	PS_ADD("timeout",	"%u",	0); /* XXX */
37567588Sdes	PS_ADD("itrealvalue",	"%u",	0); /* XXX */
37667588Sdes	PS_ADD("starttime",	"%d",	0); /* XXX */
37769995Sdes	PS_ADD("vsize",		"%u",	kp.ki_size);
37869995Sdes	PS_ADD("rss",		"%u",	P2K(kp.ki_rssize));
37967588Sdes	PS_ADD("rlim",		"%u",	0); /* XXX */
38069995Sdes	PS_ADD("startcode",	"%u",	(unsigned)0);
38167588Sdes	PS_ADD("endcode",	"%u",	0); /* XXX */
38267588Sdes	PS_ADD("startstack",	"%u",	0); /* XXX */
38369799Sdes	PS_ADD("esp",		"%u",	0); /* XXX */
38469799Sdes	PS_ADD("eip",		"%u",	0); /* XXX */
38567588Sdes	PS_ADD("signal",	"%d",	0); /* XXX */
38667588Sdes	PS_ADD("blocked",	"%d",	0); /* XXX */
38767588Sdes	PS_ADD("sigignore",	"%d",	0); /* XXX */
38867588Sdes	PS_ADD("sigcatch",	"%d",	0); /* XXX */
38967588Sdes	PS_ADD("wchan",		"%u",	0); /* XXX */
39069799Sdes	PS_ADD("nswap",		"%lu",	(long unsigned)0); /* XXX */
39169799Sdes	PS_ADD("cnswap",	"%lu",	(long unsigned)0); /* XXX */
39269799Sdes	PS_ADD("exitsignal",	"%d",	0); /* XXX */
39369799Sdes	PS_ADD("processor",	"%d",	0); /* XXX */
39467588Sdes#undef PS_ADD
39569995Sdes	sbuf_putc(&sb, '\n');
39667588Sdes
39774135Sjlemon	COMMON_END;
39867588Sdes}
39967588Sdes
40067588Sdes/*
40167588Sdes * Map process state to descriptive letter. Note that this does not
40267588Sdes * quite correspond to what Linux outputs, but it's close enough.
40367588Sdes */
40467588Sdesstatic char *state_str[] = {
40567588Sdes	"? (unknown)",
40667588Sdes	"I (idle)",
40767588Sdes	"R (running)",
40867588Sdes	"S (sleeping)",
40967588Sdes	"T (stopped)",
41067588Sdes	"Z (zombie)",
41167588Sdes	"W (waiting)",
41267588Sdes	"M (mutex)"
41367588Sdes};
41467588Sdes
41567588Sdesint
41667588Sdeslinprocfs_doprocstatus(curp, p, pfs, uio)
41767588Sdes    	struct proc *curp;
41867588Sdes	struct proc *p;
41967588Sdes	struct pfsnode *pfs;
42067588Sdes	struct uio *uio;
42167588Sdes{
42274135Sjlemon	COMMON_START;
42369995Sdes	struct kinfo_proc kp;
42467588Sdes	char *state;
42569799Sdes	segsz_t lsize;
42674135Sjlemon	int i;
42767588Sdes
42869995Sdes	sbuf_new(&sb, NULL, 1024, 0);
42969995Sdes
43072200Sbmilekic	mtx_lock_spin(&sched_lock);
43167588Sdes	if (p->p_stat > sizeof state_str / sizeof *state_str)
43267588Sdes		state = state_str[0];
43367588Sdes	else
43467588Sdes		state = state_str[(int)p->p_stat];
43572200Sbmilekic	mtx_unlock_spin(&sched_lock);
43667588Sdes
43769995Sdes	fill_kinfo_proc(p, &kp);
43869995Sdes	sbuf_printf(&sb, "Name:\t%s\n",		p->p_comm); /* XXX escape */
43969995Sdes	sbuf_printf(&sb, "State:\t%s\n",	state);
44067588Sdes
44167588Sdes	/*
44267588Sdes	 * Credentials
44367588Sdes	 */
44469995Sdes	sbuf_printf(&sb, "Pid:\t%d\n",		p->p_pid);
44571471Sjhb	PROC_LOCK(p);
44673923Sjhb	sbuf_printf(&sb, "PPid:\t%d\n",		p->p_pptr ?
44773923Sjhb						p->p_pptr->p_pid : 0);
44869995Sdes	sbuf_printf(&sb, "Uid:\t%d %d %d %d\n", p->p_cred->p_ruid,
44969995Sdes			                        p->p_ucred->cr_uid,
45069995Sdes			                        p->p_cred->p_svuid,
45169995Sdes			                        /* FreeBSD doesn't have fsuid */
45269995Sdes				                p->p_ucred->cr_uid);
45369995Sdes	sbuf_printf(&sb, "Gid:\t%d %d %d %d\n", p->p_cred->p_rgid,
45469995Sdes			                        p->p_ucred->cr_gid,
45569995Sdes			                        p->p_cred->p_svgid,
45669995Sdes			                        /* FreeBSD doesn't have fsgid */
45769995Sdes				                p->p_ucred->cr_gid);
45869995Sdes	sbuf_cat(&sb, "Groups:\t");
45967588Sdes	for (i = 0; i < p->p_ucred->cr_ngroups; i++)
46069995Sdes		sbuf_printf(&sb, "%d ", p->p_ucred->cr_groups[i]);
46171471Sjhb	PROC_UNLOCK(p);
46269995Sdes	sbuf_putc(&sb, '\n');
46367588Sdes
46467588Sdes	/*
46567588Sdes	 * Memory
46669799Sdes	 *
46769799Sdes	 * While our approximation of VmLib may not be accurate (I
46869799Sdes	 * don't know of a simple way to verify it, and I'm not sure
46969799Sdes	 * it has much meaning anyway), I believe it's good enough.
47069799Sdes	 *
47169799Sdes	 * The same code that could (I think) accurately compute VmLib
47269799Sdes	 * could also compute VmLck, but I don't really care enough to
47369799Sdes	 * implement it. Submissions are welcome.
47467588Sdes	 */
47569995Sdes	sbuf_printf(&sb, "VmSize:\t%8u kB\n",	B2K(kp.ki_size));
47669995Sdes	sbuf_printf(&sb, "VmLck:\t%8u kB\n",	P2K(0)); /* XXX */
47769995Sdes	sbuf_printf(&sb, "VmRss:\t%8u kB\n",	P2K(kp.ki_rssize));
47869995Sdes	sbuf_printf(&sb, "VmData:\t%8u kB\n",	P2K(kp.ki_dsize));
47969995Sdes	sbuf_printf(&sb, "VmStk:\t%8u kB\n",	P2K(kp.ki_ssize));
48069995Sdes	sbuf_printf(&sb, "VmExe:\t%8u kB\n",	P2K(kp.ki_tsize));
48169995Sdes	lsize = B2P(kp.ki_size) - kp.ki_dsize -
48269995Sdes	    kp.ki_ssize - kp.ki_tsize - 1;
48369995Sdes	sbuf_printf(&sb, "VmLib:\t%8u kB\n",	P2K(lsize));
48467588Sdes
48567588Sdes	/*
48667588Sdes	 * Signal masks
48767588Sdes	 *
48867588Sdes	 * We support up to 128 signals, while Linux supports 32,
48967588Sdes	 * but we only define 32 (the same 32 as Linux, to boot), so
49067588Sdes	 * just show the lower 32 bits of each mask. XXX hack.
49167588Sdes	 *
49267588Sdes	 * NB: on certain platforms (Sparc at least) Linux actually
49367588Sdes	 * supports 64 signals, but this code is a long way from
49467588Sdes	 * running on anything but i386, so ignore that for now.
49567588Sdes	 */
49671471Sjhb	PROC_LOCK(p);
49769995Sdes	sbuf_printf(&sb, "SigPnd:\t%08x\n",	p->p_siglist.__bits[0]);
49869799Sdes	/*
49969799Sdes	 * I can't seem to find out where the signal mask is in
50069799Sdes	 * relation to struct proc, so SigBlk is left unimplemented.
50169799Sdes	 */
50269995Sdes	sbuf_printf(&sb, "SigBlk:\t%08x\n",	0); /* XXX */
50369995Sdes	sbuf_printf(&sb, "SigIgn:\t%08x\n",	p->p_sigignore.__bits[0]);
50469995Sdes	sbuf_printf(&sb, "SigCgt:\t%08x\n",	p->p_sigcatch.__bits[0]);
50571471Sjhb	PROC_UNLOCK(p);
50667588Sdes
50767588Sdes	/*
50867588Sdes	 * Linux also prints the capability masks, but we don't have
50967588Sdes	 * capabilities yet, and when we do get them they're likely to
51067588Sdes	 * be meaningless to Linux programs, so we lie. XXX
51167588Sdes	 */
51269995Sdes	sbuf_printf(&sb, "CapInh:\t%016x\n",	0);
51369995Sdes	sbuf_printf(&sb, "CapPrm:\t%016x\n",	0);
51469995Sdes	sbuf_printf(&sb, "CapEff:\t%016x\n",	0);
51569995Sdes
51674135Sjlemon	COMMON_END;
51767588Sdes}
51874135Sjlemon
51974135Sjlemonint
52074135Sjlemonlinprocfs_doselflink(curp, p, pfs, uio)
52174135Sjlemon	struct proc *curp;
52274135Sjlemon	struct proc *p;
52374135Sjlemon	struct pfsnode *pfs;
52474135Sjlemon	struct uio *uio;
52574135Sjlemon{
52674135Sjlemon	char buf[16];		/* should be enough */
52774135Sjlemon	int len;
52874135Sjlemon
52974135Sjlemon		/* XXX shouldn't this be uio->uio_procp->p_pid? */
53074135Sjlemon	len = snprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid);
53174135Sjlemon
53274135Sjlemon	return (uiomove(buf, len, uio));
53374135Sjlemon}
53474135Sjlemon
53574135Sjlemonint
53674135Sjlemonlinprocfs_doexelink(curp, p, pfs, uio)
53774135Sjlemon	struct proc *curp;
53874135Sjlemon	struct proc *p;
53974135Sjlemon	struct pfsnode *pfs;
54074135Sjlemon	struct uio *uio;
54174135Sjlemon{
54274135Sjlemon	int error = 0;
54374135Sjlemon	char *fullpath = "unknown";
54474135Sjlemon	char *freepath = NULL;
54574135Sjlemon
54674135Sjlemon	p = PFIND(pfs->pfs_pid);
54774135Sjlemon	if (p == NULL || p->p_cred == NULL || p->p_ucred == NULL) {
54874135Sjlemon		if (p != NULL)
54974135Sjlemon			PROC_UNLOCK(p);
55074135Sjlemon		printf("doexelink: pid %d disappeared\n", pfs->pfs_pid);
55174135Sjlemon	} else {
55274135Sjlemon		PROC_UNLOCK(p);
55374135Sjlemon		/* fullpath/freepath are unchanged if textvp_fullpath fails */
55474135Sjlemon		error = textvp_fullpath(p, &fullpath, &freepath);
55574135Sjlemon	}
55674135Sjlemon	error = uiomove(fullpath, strlen(fullpath), uio);
55774135Sjlemon	if (freepath)
55874135Sjlemon		free(freepath, M_TEMP);
55974135Sjlemon	return (error);
56074135Sjlemon}
56174135Sjlemon
56274135Sjlemonint
56374135Sjlemonlinprocfs_donetdev(curp, p, pfs, uio)
56474135Sjlemon	struct proc *curp;
56574135Sjlemon	struct proc *p;
56674135Sjlemon	struct pfsnode *pfs;
56774135Sjlemon	struct uio *uio;
56874135Sjlemon{
56974135Sjlemon	COMMON_START;
57074135Sjlemon	struct ifnet *ifp;
57174135Sjlemon	int eth_index = 0;
57274135Sjlemon
57374135Sjlemon	sbuf_new(&sb, NULL, 1024, 0);
57474135Sjlemon	sbuf_printf(&sb,
57574135Sjlemon	    "Inter-|   Receive                                       "
57674135Sjlemon	    "         |  Transmit\n"
57774135Sjlemon	    " face |bytes    packets errs drop fifo frame compressed "
57874135Sjlemon	    "multicast|bytes    packets errs drop fifo colls carrier "
57974135Sjlemon	    "compressed\n");
58074135Sjlemon
58174135Sjlemon	TAILQ_FOREACH(ifp, &ifnet, if_link) {
58274135Sjlemon		if (strcmp(ifp->if_name, "lo") == 0) {
58374135Sjlemon			sbuf_printf(&sb, "%6.6s:", ifp->if_name);
58474135Sjlemon		} else {
58574135Sjlemon			sbuf_printf(&sb, "%5.5s%d:", "eth", eth_index);
58674135Sjlemon			eth_index++;
58774135Sjlemon		}
58874135Sjlemon		sbuf_printf(&sb,
58974135Sjlemon		    "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu "
59074135Sjlemon		    "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
59174135Sjlemon		    0, 0, 0, 0, 0, 0, 0, 0,
59274135Sjlemon		    0, 0, 0, 0, 0, 0, 0, 0);
59374135Sjlemon	}
59474135Sjlemon
59574135Sjlemon	COMMON_END;
59674135Sjlemon}
59774135Sjlemon
59874135Sjlemonint
59974135Sjlemonlinprocfs_dodevices(curp, p, pfs, uio)
60074135Sjlemon	struct proc *curp;
60174135Sjlemon	struct proc *p;
60274135Sjlemon	struct pfsnode *pfs;
60374135Sjlemon	struct uio *uio;
60474135Sjlemon{
60574135Sjlemon	COMMON_START;
60674135Sjlemon	int i;
60774135Sjlemon
60874135Sjlemon	sbuf_new(&sb, NULL, 1024, 0);
60974135Sjlemon	sbuf_printf(&sb, "Character devices:\n");
61074135Sjlemon
61174135Sjlemon	for (i = 0; i < NUMCDEVSW; i++) {
61274135Sjlemon		if (cdevsw[i] != NULL)
61374135Sjlemon			sbuf_printf(&sb, "%3d %s\n", i, cdevsw[i]->d_name);
61474135Sjlemon	}
61574135Sjlemon
61674135Sjlemon	sbuf_printf(&sb, "\nBlock devices:\n");
61774135Sjlemon
61874135Sjlemon	COMMON_END;
61974135Sjlemon}
62074135Sjlemon
62174135Sjlemonint
62274135Sjlemonlinprocfs_docmdline(curp, p, pfs, uio)
62374135Sjlemon	struct proc *curp;
62474135Sjlemon	struct proc *p;
62574135Sjlemon	struct pfsnode *pfs;
62674135Sjlemon	struct uio *uio;
62774135Sjlemon{
62874135Sjlemon	COMMON_START;
62974135Sjlemon
63074135Sjlemon	sbuf_new(&sb, NULL, 128, 0);
63174135Sjlemon	sbuf_printf(&sb, "BOOT_IMAGE=%s", kernelname);
63274135Sjlemon	sbuf_printf(&sb, " ro root=302\n");
63374135Sjlemon
63474135Sjlemon	COMMON_END;
63574135Sjlemon}
636