linprocfs.c revision 121265
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 42116173Sobrien#include <sys/cdefs.h> 43116173Sobrien__FBSDID("$FreeBSD: head/sys/compat/linprocfs/linprocfs.c 121265 2003-10-20 04:10:20Z cognet $"); 44116173Sobrien 4559412Smsmith#include <sys/param.h> 4683926Sdes#include <sys/queue.h> 4776166Smarkm#include <sys/blist.h> 4874135Sjlemon#include <sys/conf.h> 4983926Sdes#include <sys/exec.h> 50119911Sdes#include <sys/filedesc.h> 5176166Smarkm#include <sys/jail.h> 5265633Sdes#include <sys/kernel.h> 5383926Sdes#include <sys/linker.h> 5476166Smarkm#include <sys/lock.h> 5574135Sjlemon#include <sys/malloc.h> 5678025Sdes#include <sys/mount.h> 5776827Salfred#include <sys/mutex.h> 5885289Sdes#include <sys/namei.h> 5965633Sdes#include <sys/proc.h> 6065633Sdes#include <sys/resourcevar.h> 6169995Sdes#include <sys/sbuf.h> 6283926Sdes#include <sys/socket.h> 6376839Sjlemon#include <sys/sysctl.h> 6483926Sdes#include <sys/systm.h> 6565633Sdes#include <sys/tty.h> 6683926Sdes#include <sys/user.h> 6783926Sdes#include <sys/vmmeter.h> 6859412Smsmith#include <sys/vnode.h> 6959412Smsmith 7083926Sdes#include <net/if.h> 7183926Sdes 7259412Smsmith#include <vm/vm.h> 7359412Smsmith#include <vm/pmap.h> 7467588Sdes#include <vm/vm_map.h> 7559412Smsmith#include <vm/vm_param.h> 7660860Sdes#include <vm/vm_object.h> 7759412Smsmith#include <vm/swap_pager.h> 7869799Sdes 7967589Sdes#include <machine/clock.h> 8078113Sdes 8178113Sdes#ifdef __alpha__ 8278113Sdes#include <machine/alpha_cpu.h> 8378113Sdes#include <machine/cpuconf.h> 8478113Sdes#include <machine/rpb.h> 8578113Sdesextern int ncpus; 8678113Sdes#endif /* __alpha__ */ 8778113Sdes 8878113Sdes#ifdef __i386__ 8967589Sdes#include <machine/cputypes.h> 9059412Smsmith#include <machine/md_var.h> 9178113Sdes#endif /* __i386__ */ 9259412Smsmith 9387275Srwatson#include <machine/../linux/linux.h> 9485129Sdes#include <compat/linux/linux_ioctl.h> 9569995Sdes#include <compat/linux/linux_mib.h> 9685289Sdes#include <compat/linux/linux_util.h> 9778025Sdes#include <fs/pseudofs/pseudofs.h> 9884248Sdes#include <fs/procfs/procfs.h> 9959412Smsmith 10067588Sdes/* 10167588Sdes * Various conversion macros 10267588Sdes */ 10376405Sdes#define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz)) /* ticks to jiffies */ 10467588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ 10567588Sdes#define B2K(x) ((x) >> 10) /* bytes to kbytes */ 10669799Sdes#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ 10767588Sdes#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ 10867588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ 10974135Sjlemon 11078113Sdes/* 11178113Sdes * Filler function for proc/meminfo 11278113Sdes */ 11378025Sdesstatic int 11478025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS) 11559412Smsmith{ 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 ??? */ 121113574Sjhb unsigned long long swaptotal; /* total swap space in bytes */ 122113574Sjhb unsigned long long swapused; /* used swap space in bytes */ 123113574Sjhb unsigned long long swapfree; /* free swap space in bytes */ 12460860Sdes vm_object_t object; 125117723Sphk int i, j; 12659412Smsmith 12759412Smsmith memtotal = physmem * PAGE_SIZE; 12859412Smsmith /* 12959412Smsmith * The correct thing here would be: 13059412Smsmith * 13159412Smsmith memfree = cnt.v_free_count * PAGE_SIZE; 13259412Smsmith memused = memtotal - memfree; 13359412Smsmith * 13459412Smsmith * but it might mislead linux binaries into thinking there 13559412Smsmith * is very little memory left, so we cheat and tell them that 13659412Smsmith * all memory that isn't wired down is free. 13759412Smsmith */ 13859412Smsmith memused = cnt.v_wire_count * PAGE_SIZE; 13959412Smsmith memfree = memtotal - memused; 140117723Sphk swap_pager_status(&i, &j); 141117723Sphk swaptotal = i * PAGE_SIZE; 142117723Sphk swapused = j * PAGE_SIZE; 143117723Sphk swapfree = swaptotal - swapused; 14460860Sdes memshared = 0; 14571471Sjhb TAILQ_FOREACH(object, &vm_object_list, object_list) 14660860Sdes if (object->shadow_count > 1) 14760860Sdes memshared += object->resident_page_count; 14860860Sdes memshared *= PAGE_SIZE; 14959412Smsmith /* 15059412Smsmith * We'd love to be able to write: 15159412Smsmith * 15259412Smsmith buffers = bufspace; 15359412Smsmith * 15459412Smsmith * but bufspace is internal to vfs_bio.c and we don't feel 15559412Smsmith * like unstaticizing it just for linprocfs's sake. 15659412Smsmith */ 15759412Smsmith buffers = 0; 15859412Smsmith cached = cnt.v_cache_count * PAGE_SIZE; 15959412Smsmith 16078025Sdes sbuf_printf(sb, 16178031Sdes " total: used: free: shared: buffers: cached:\n" 16269799Sdes "Mem: %lu %lu %lu %lu %lu %lu\n" 16376839Sjlemon "Swap: %llu %llu %llu\n" 16469799Sdes "MemTotal: %9lu kB\n" 16569799Sdes "MemFree: %9lu kB\n" 16669799Sdes "MemShared:%9lu kB\n" 16769799Sdes "Buffers: %9lu kB\n" 16869799Sdes "Cached: %9lu kB\n" 16976839Sjlemon "SwapTotal:%9llu kB\n" 17076839Sjlemon "SwapFree: %9llu kB\n", 17169799Sdes memtotal, memused, memfree, memshared, buffers, cached, 17269799Sdes swaptotal, swapused, swapfree, 17369799Sdes B2K(memtotal), B2K(memfree), 17469799Sdes B2K(memshared), B2K(buffers), B2K(cached), 17569799Sdes B2K(swaptotal), B2K(swapfree)); 17659412Smsmith 17778025Sdes return (0); 17859412Smsmith} 17959412Smsmith 18078113Sdes#ifdef __alpha__ 181119008Smarcelextern struct rpb *hwrpb; 18278113Sdes/* 18378113Sdes * Filler function for proc/cpuinfo (Alpha version) 18478113Sdes */ 18578025Sdesstatic int 18678025Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS) 18759412Smsmith{ 18878113Sdes u_int64_t type, major; 18978113Sdes struct pcs *pcsp; 19078113Sdes const char *model, *sysname; 19178113Sdes 19278113Sdes static const char *cpuname[] = { 19378113Sdes "EV3", "EV4", "Simulate", "LCA4", "EV5", "EV45", "EV56", 19478113Sdes "EV6", "PCA56", "PCA57", "EV67", "EV68CB", "EV68AL" 19578113Sdes }; 19678113Sdes 19778113Sdes pcsp = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id); 19878113Sdes type = pcsp->pcs_proc_type; 19978113Sdes major = (type & PCS_PROC_MAJOR) >> PCS_PROC_MAJORSHIFT; 20078113Sdes if (major < sizeof(cpuname)/sizeof(char *)) { 20178113Sdes model = cpuname[major - 1]; 20278113Sdes } else { 20378113Sdes model = "unknown"; 20478113Sdes } 205119068Sdes 20678113Sdes sysname = alpha_dsr_sysname(); 207119068Sdes 20878113Sdes sbuf_printf(sb, 20978113Sdes "cpu\t\t\t: Alpha\n" 21078113Sdes "cpu model\t\t: %s\n" 21178113Sdes "cpu variation\t\t: %ld\n" 212113574Sjhb "cpu revision\t\t: %d\n" 21378113Sdes "cpu serial number\t: %s\n" 21478113Sdes "system type\t\t: %s\n" 21578113Sdes "system variation\t: %s\n" 216113574Sjhb "system revision\t\t: %d\n" 21778113Sdes "system serial number\t: %s\n" 21878113Sdes "cycle frequency [Hz]\t: %lu\n" 219113574Sjhb "timer frequency [Hz]\t: %u\n" 22078113Sdes "page size [bytes]\t: %ld\n" 22178113Sdes "phys. address bits\t: %ld\n" 22278113Sdes "max. addr. space #\t: %ld\n" 223113574Sjhb "BogoMIPS\t\t: %u.%02u\n" 224113574Sjhb "kernel unaligned acc\t: %d (pc=%x,va=%x)\n" 225113574Sjhb "user unaligned acc\t: %d (pc=%x,va=%x)\n" 22678113Sdes "platform string\t\t: %s\n" 22778113Sdes "cpus detected\t\t: %d\n" 22878113Sdes , 22978113Sdes model, 23078113Sdes pcsp->pcs_proc_var, 23178113Sdes *(int *)hwrpb->rpb_revision, 23278113Sdes " ", 23378113Sdes " ", 23478113Sdes "0", 23578113Sdes 0, 23678113Sdes " ", 23778113Sdes hwrpb->rpb_cc_freq, 23878113Sdes hz, 23978113Sdes hwrpb->rpb_page_size, 24078113Sdes hwrpb->rpb_phys_addr_size, 24178113Sdes hwrpb->rpb_max_asn, 24278113Sdes 0, 0, 24378113Sdes 0, 0, 0, 24478113Sdes 0, 0, 0, 24578113Sdes sysname, 24678113Sdes ncpus); 24778113Sdes return (0); 24878113Sdes} 24978113Sdes#endif /* __alpha__ */ 25078113Sdes 25178113Sdes#ifdef __i386__ 25278113Sdes/* 25378113Sdes * Filler function for proc/cpuinfo (i386 version) 25478113Sdes */ 25578113Sdesstatic int 25678113Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS) 25778113Sdes{ 258118421Sdes int class, fqmhz, fqkhz, ncpu; 259118421Sdes int name[2], olen, plen; 260118421Sdes int i; 26159412Smsmith 262118421Sdes name[0] = CTL_HW; 263118421Sdes name[1] = HW_NCPU; 264118421Sdes if (kernel_sysctl(td, name, 2, &ncpu, &olen, NULL, 0, &plen) != 0) 265118421Sdes ncpu = 1; 266118421Sdes 26769799Sdes /* 26878031Sdes * We default the flags to include all non-conflicting flags, 26978031Sdes * and the Intel versions of conflicting flags. 27069799Sdes */ 27178031Sdes static char *flags[] = { 27278031Sdes "fpu", "vme", "de", "pse", "tsc", 27378031Sdes "msr", "pae", "mce", "cx8", "apic", 27478031Sdes "sep", "sep", "mtrr", "pge", "mca", 27578031Sdes "cmov", "pat", "pse36", "pn", "b19", 27678031Sdes "b20", "b21", "mmxext", "mmx", "fxsr", 27778031Sdes "xmm", "b26", "b27", "b28", "b29", 27867589Sdes "3dnowext", "3dnow" 27967589Sdes }; 28067589Sdes 28159412Smsmith switch (cpu_class) { 28259412Smsmith case CPUCLASS_286: 28367589Sdes class = 2; 28459412Smsmith break; 28559412Smsmith case CPUCLASS_386: 28667589Sdes class = 3; 28759412Smsmith break; 28859412Smsmith case CPUCLASS_486: 28967589Sdes class = 4; 29059412Smsmith break; 29159412Smsmith case CPUCLASS_586: 29267589Sdes class = 5; 29359412Smsmith break; 29459412Smsmith case CPUCLASS_686: 29567589Sdes class = 6; 29659412Smsmith break; 29759412Smsmith default: 29878031Sdes class = 0; 29959412Smsmith break; 30059412Smsmith } 30159412Smsmith 302118421Sdes for (i = 0; i < ncpu; ++i) { 303118421Sdes sbuf_printf(sb, 304118421Sdes "processor\t: %d\n" 305118421Sdes "vendor_id\t: %.20s\n" 306118421Sdes "cpu family\t: %d\n" 307118421Sdes "model\t\t: %d\n" 308118421Sdes "stepping\t: %d\n", 309118421Sdes i, cpu_vendor, class, cpu, cpu_id & 0xf); 310118421Sdes /* XXX per-cpu vendor / class / id? */ 311118421Sdes } 31259412Smsmith 31378031Sdes sbuf_cat(sb, 31478031Sdes "flags\t\t:"); 31567589Sdes 31678031Sdes if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) { 31767589Sdes flags[16] = "fcmov"; 31878031Sdes } else if (!strcmp(cpu_vendor, "CyrixInstead")) { 31967589Sdes flags[24] = "cxmmx"; 32078031Sdes } 321119068Sdes 32278031Sdes for (i = 0; i < 32; i++) 32367589Sdes if (cpu_feature & (1 << i)) 32478025Sdes sbuf_printf(sb, " %s", flags[i]); 32578025Sdes sbuf_cat(sb, "\n"); 32678031Sdes if (class >= 5) { 32769799Sdes fqmhz = (tsc_freq + 4999) / 1000000; 32869799Sdes fqkhz = ((tsc_freq + 4999) / 10000) % 100; 32978025Sdes sbuf_printf(sb, 33069799Sdes "cpu MHz\t\t: %d.%02d\n" 33169799Sdes "bogomips\t: %d.%02d\n", 33269799Sdes fqmhz, fqkhz, fqmhz, fqkhz); 33378031Sdes } 33469995Sdes 33578025Sdes return (0); 33659412Smsmith} 33778113Sdes#endif /* __i386__ */ 33865633Sdes 33978113Sdes/* 34085289Sdes * Filler function for proc/mtab 34185289Sdes * 34285289Sdes * This file doesn't exist in Linux' procfs, but is included here so 34385289Sdes * users can symlink /compat/linux/etc/mtab to /proc/mtab 34485289Sdes */ 34585289Sdesstatic int 34685289Sdeslinprocfs_domtab(PFS_FILL_ARGS) 34785289Sdes{ 34885289Sdes struct nameidata nd; 34985289Sdes struct mount *mp; 35091334Sjulian const char *lep; 35191334Sjulian char *dlep, *flep, *mntto, *mntfrom, *fstype; 35285289Sdes size_t lep_len; 35385289Sdes int error; 35485289Sdes 35585289Sdes /* resolve symlinks etc. in the emulation tree prefix */ 35685289Sdes NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td); 35785289Sdes flep = NULL; 35891334Sjulian if (namei(&nd) != 0 || vn_fullpath(td, nd.ni_vp, &dlep, &flep) == -1) 35985289Sdes lep = linux_emul_path; 36091334Sjulian else 36191334Sjulian lep = dlep; 36285289Sdes lep_len = strlen(lep); 363119068Sdes 36485289Sdes mtx_lock(&mountlist_mtx); 36585289Sdes error = 0; 36685289Sdes TAILQ_FOREACH(mp, &mountlist, mnt_list) { 36785289Sdes error = VFS_STATFS(mp, &mp->mnt_stat, td); 36885289Sdes if (error) 36985289Sdes break; 37085289Sdes 37185289Sdes /* determine device name */ 37285289Sdes mntfrom = mp->mnt_stat.f_mntfromname; 373119068Sdes 37485289Sdes /* determine mount point */ 37585289Sdes mntto = mp->mnt_stat.f_mntonname; 37685289Sdes if (strncmp(mntto, lep, lep_len) == 0 && 37785289Sdes mntto[lep_len] == '/') 37885289Sdes mntto += lep_len; 37985289Sdes 38085289Sdes /* determine fs type */ 38185289Sdes fstype = mp->mnt_stat.f_fstypename; 38285289Sdes if (strcmp(fstype, pn->pn_info->pi_name) == 0) 38385289Sdes mntfrom = fstype = "proc"; 38485289Sdes else if (strcmp(fstype, "procfs") == 0) 38585289Sdes continue; 386119068Sdes 38785289Sdes sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype, 38885289Sdes mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 38985289Sdes#define ADD_OPTION(opt, name) \ 39085289Sdes if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name); 39185289Sdes ADD_OPTION(MNT_SYNCHRONOUS, "sync"); 39285289Sdes ADD_OPTION(MNT_NOEXEC, "noexec"); 39385289Sdes ADD_OPTION(MNT_NOSUID, "nosuid"); 39485289Sdes ADD_OPTION(MNT_NODEV, "nodev"); 39585289Sdes ADD_OPTION(MNT_UNION, "union"); 39685289Sdes ADD_OPTION(MNT_ASYNC, "async"); 39785289Sdes ADD_OPTION(MNT_SUIDDIR, "suiddir"); 39885289Sdes ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow"); 39985289Sdes ADD_OPTION(MNT_NOATIME, "noatime"); 40085289Sdes#undef ADD_OPTION 40185289Sdes /* a real Linux mtab will also show NFS options */ 40285289Sdes sbuf_printf(sb, " 0 0\n"); 40385289Sdes } 40485289Sdes mtx_unlock(&mountlist_mtx); 40585289Sdes if (flep != NULL) 40685289Sdes free(flep, M_TEMP); 40785289Sdes return (error); 40885289Sdes} 40985289Sdes 41085289Sdes/* 41178113Sdes * Filler function for proc/stat 41278113Sdes */ 41378025Sdesstatic int 41478025Sdeslinprocfs_dostat(PFS_FILL_ARGS) 41565633Sdes{ 416120912Sgallatin size_t olen, plen; 417120605Sdes int name[2]; 418120339Sdes int i, ncpu; 419120339Sdes 420120339Sdes name[0] = CTL_HW; 421120339Sdes name[1] = HW_NCPU; 422120339Sdes if (kernel_sysctl(td, name, 2, &ncpu, &olen, NULL, 0, &plen) != 0) 423120340Sdes ncpu = 1; 424120339Sdes sbuf_printf(sb, "cpu %ld %ld %ld %ld\n", 425120339Sdes T2J(cp_time[CP_USER]), 426120339Sdes T2J(cp_time[CP_NICE]), 427120339Sdes T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), 428120339Sdes T2J(cp_time[CP_IDLE])); 429120340Sdes if (ncpu > 1) 430120340Sdes for (i = 0; i < ncpu; ++i) 431120340Sdes sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i, 432120340Sdes T2J(cp_time[CP_USER]) / ncpu, 433120340Sdes T2J(cp_time[CP_NICE]) / ncpu, 434120340Sdes T2J(cp_time[CP_SYS]) / ncpu, 435120340Sdes T2J(cp_time[CP_IDLE]) / ncpu); 43678025Sdes sbuf_printf(sb, 43769799Sdes "disk 0 0 0 0\n" 43869799Sdes "page %u %u\n" 43969799Sdes "swap %u %u\n" 44069799Sdes "intr %u\n" 44169799Sdes "ctxt %u\n" 44285657Sdillon "btime %lld\n", 44369799Sdes cnt.v_vnodepgsin, 44469799Sdes cnt.v_vnodepgsout, 44569799Sdes cnt.v_swappgsin, 44669799Sdes cnt.v_swappgsout, 44769799Sdes cnt.v_intr, 44869799Sdes cnt.v_swtch, 449113574Sjhb (long long)boottime.tv_sec); 45078025Sdes return (0); 45165633Sdes} 45265633Sdes 45378113Sdes/* 45478113Sdes * Filler function for proc/uptime 45578113Sdes */ 45678025Sdesstatic int 45778025Sdeslinprocfs_douptime(PFS_FILL_ARGS) 45865633Sdes{ 45965633Sdes struct timeval tv; 46065633Sdes 46165633Sdes getmicrouptime(&tv); 46285657Sdillon sbuf_printf(sb, "%lld.%02ld %ld.%02ld\n", 463113574Sjhb (long long)tv.tv_sec, tv.tv_usec / 10000, 46469799Sdes T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100); 46578025Sdes return (0); 46665633Sdes} 46765633Sdes 46878113Sdes/* 46978113Sdes * Filler function for proc/version 47078113Sdes */ 47178025Sdesstatic int 47278025Sdeslinprocfs_doversion(PFS_FILL_ARGS) 47365633Sdes{ 47487275Srwatson char osname[LINUX_MAX_UTSNAME]; 47587275Srwatson char osrelease[LINUX_MAX_UTSNAME]; 47687275Srwatson 477112206Sjhb linux_get_osname(td, osname); 478112206Sjhb linux_get_osrelease(td, osrelease); 47987275Srwatson 48078025Sdes sbuf_printf(sb, 48169995Sdes "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")" 48287275Srwatson " #4 Sun Dec 18 04:30:00 CET 1977\n", osname, osrelease); 48378025Sdes return (0); 48465633Sdes} 48565633Sdes 48678113Sdes/* 48778113Sdes * Filler function for proc/loadavg 48878113Sdes */ 48978025Sdesstatic int 49078025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS) 49176839Sjlemon{ 49278025Sdes sbuf_printf(sb, 49376839Sjlemon "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 49476839Sjlemon (int)(averunnable.ldavg[0] / averunnable.fscale), 49576839Sjlemon (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 49676839Sjlemon (int)(averunnable.ldavg[1] / averunnable.fscale), 49776839Sjlemon (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 49876839Sjlemon (int)(averunnable.ldavg[2] / averunnable.fscale), 49976839Sjlemon (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 50076839Sjlemon 1, /* number of running tasks */ 50176839Sjlemon nprocs, /* number of tasks */ 50278116Sdes lastpid /* the last pid */ 50376839Sjlemon ); 504119068Sdes 50578025Sdes return (0); 50676839Sjlemon} 50776839Sjlemon 50878113Sdes/* 50978113Sdes * Filler function for proc/pid/stat 51078113Sdes */ 51178025Sdesstatic int 51278025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS) 51367588Sdes{ 51469995Sdes struct kinfo_proc kp; 51567588Sdes 51694307Sjhb PROC_LOCK(p); 51769995Sdes fill_kinfo_proc(p, &kp); 51878025Sdes sbuf_printf(sb, "%d", p->p_pid); 51978025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg) 52067588Sdes PS_ADD("comm", "(%s)", p->p_comm); 52167588Sdes PS_ADD("statr", "%c", '0'); /* XXX */ 52273923Sjhb PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); 52367588Sdes PS_ADD("pgrp", "%d", p->p_pgid); 52467588Sdes PS_ADD("session", "%d", p->p_session->s_sid); 52591140Stanimura PROC_UNLOCK(p); 52667588Sdes PS_ADD("tty", "%d", 0); /* XXX */ 52767588Sdes PS_ADD("tpgid", "%d", 0); /* XXX */ 52867588Sdes PS_ADD("flags", "%u", 0); /* XXX */ 52967588Sdes PS_ADD("minflt", "%u", 0); /* XXX */ 53067588Sdes PS_ADD("cminflt", "%u", 0); /* XXX */ 53167588Sdes PS_ADD("majflt", "%u", 0); /* XXX */ 53267588Sdes PS_ADD("cminflt", "%u", 0); /* XXX */ 53367588Sdes PS_ADD("utime", "%d", 0); /* XXX */ 53467588Sdes PS_ADD("stime", "%d", 0); /* XXX */ 53567588Sdes PS_ADD("cutime", "%d", 0); /* XXX */ 53667588Sdes PS_ADD("cstime", "%d", 0); /* XXX */ 53767588Sdes PS_ADD("counter", "%d", 0); /* XXX */ 53867588Sdes PS_ADD("priority", "%d", 0); /* XXX */ 53967588Sdes PS_ADD("timeout", "%u", 0); /* XXX */ 54067588Sdes PS_ADD("itrealvalue", "%u", 0); /* XXX */ 54167588Sdes PS_ADD("starttime", "%d", 0); /* XXX */ 542113574Sjhb PS_ADD("vsize", "%ju", (uintmax_t)kp.ki_size); 543113574Sjhb PS_ADD("rss", "%ju", P2K((uintmax_t)kp.ki_rssize)); 54467588Sdes PS_ADD("rlim", "%u", 0); /* XXX */ 54569995Sdes PS_ADD("startcode", "%u", (unsigned)0); 54667588Sdes PS_ADD("endcode", "%u", 0); /* XXX */ 54767588Sdes PS_ADD("startstack", "%u", 0); /* XXX */ 54869799Sdes PS_ADD("esp", "%u", 0); /* XXX */ 54969799Sdes PS_ADD("eip", "%u", 0); /* XXX */ 55067588Sdes PS_ADD("signal", "%d", 0); /* XXX */ 55167588Sdes PS_ADD("blocked", "%d", 0); /* XXX */ 55267588Sdes PS_ADD("sigignore", "%d", 0); /* XXX */ 55367588Sdes PS_ADD("sigcatch", "%d", 0); /* XXX */ 55467588Sdes PS_ADD("wchan", "%u", 0); /* XXX */ 55569799Sdes PS_ADD("nswap", "%lu", (long unsigned)0); /* XXX */ 55669799Sdes PS_ADD("cnswap", "%lu", (long unsigned)0); /* XXX */ 55769799Sdes PS_ADD("exitsignal", "%d", 0); /* XXX */ 55869799Sdes PS_ADD("processor", "%d", 0); /* XXX */ 55967588Sdes#undef PS_ADD 56078025Sdes sbuf_putc(sb, '\n'); 561119068Sdes 56278025Sdes return (0); 56367588Sdes} 56467588Sdes 56567588Sdes/* 566119911Sdes * Filler function for proc/pid/statm 567119911Sdes */ 568119911Sdesstatic int 569119911Sdeslinprocfs_doprocstatm(PFS_FILL_ARGS) 570119911Sdes{ 571119911Sdes struct kinfo_proc kp; 572119911Sdes segsz_t lsize; 573120340Sdes 574119911Sdes PROC_LOCK(p); 575119911Sdes fill_kinfo_proc(p, &kp); 576119911Sdes PROC_UNLOCK(p); 577119911Sdes 578119911Sdes /* 579119911Sdes * See comments in linprocfs_doprocstatus() regarding the 580119911Sdes * computation of lsize. 581119911Sdes */ 582119911Sdes /* size resident share trs drs lrs dt */ 583119911Sdes sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size)); 584119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize); 585119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */ 586119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize); 587119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize)); 588119911Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 589119911Sdes kp.ki_ssize - kp.ki_tsize - 1; 590119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)lsize); 591119911Sdes sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */ 592119911Sdes 593119911Sdes return (0); 594119911Sdes} 595119911Sdes 596119911Sdes/* 59778113Sdes * Filler function for proc/pid/status 59878113Sdes */ 59978025Sdesstatic int 60078025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS) 60167588Sdes{ 60269995Sdes struct kinfo_proc kp; 60367588Sdes char *state; 60469799Sdes segsz_t lsize; 60599072Sjulian struct thread *td2; 606114983Sjhb struct sigacts *ps; 60774135Sjlemon int i; 60867588Sdes 609113611Sjhb PROC_LOCK(p); 61099072Sjulian td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */ 61199072Sjulian 61299072Sjulian if (P_SHOULDSTOP(p)) { 61399072Sjulian state = "T (stopped)"; 61499072Sjulian } else { 615113611Sjhb mtx_lock_spin(&sched_lock); 61699072Sjulian switch(p->p_state) { 61799072Sjulian case PRS_NEW: 61899072Sjulian state = "I (idle)"; 61999072Sjulian break; 62099072Sjulian case PRS_NORMAL: 62199072Sjulian if (p->p_flag & P_WEXIT) { 62299072Sjulian state = "X (exiting)"; 62399072Sjulian break; 62499072Sjulian } 62599072Sjulian switch(td2->td_state) { 626103216Sjulian case TDS_INHIBITED: 62799072Sjulian state = "S (sleeping)"; 62899072Sjulian break; 62999072Sjulian case TDS_RUNQ: 63099072Sjulian case TDS_RUNNING: 63199072Sjulian state = "R (running)"; 63299072Sjulian break; 63399072Sjulian default: 63499072Sjulian state = "? (unknown)"; 63599072Sjulian break; 63699072Sjulian } 63799072Sjulian break; 63899072Sjulian case PRS_ZOMBIE: 63999072Sjulian state = "Z (zombie)"; 64099072Sjulian break; 64199072Sjulian default: 64299072Sjulian state = "? (unknown)"; 64399072Sjulian break; 64499072Sjulian } 645113611Sjhb mtx_unlock_spin(&sched_lock); 64699072Sjulian } 64767588Sdes 64869995Sdes fill_kinfo_proc(p, &kp); 64978025Sdes sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ 65078031Sdes sbuf_printf(sb, "State:\t%s\n", state); 65167588Sdes 65267588Sdes /* 65367588Sdes * Credentials 65467588Sdes */ 65578025Sdes sbuf_printf(sb, "Pid:\t%d\n", p->p_pid); 65678025Sdes sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ? 65773923Sjhb p->p_pptr->p_pid : 0); 65878031Sdes sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid, 65978031Sdes p->p_ucred->cr_uid, 66078031Sdes p->p_ucred->cr_svuid, 66178031Sdes /* FreeBSD doesn't have fsuid */ 66278031Sdes p->p_ucred->cr_uid); 66378031Sdes sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid, 66478031Sdes p->p_ucred->cr_gid, 66578031Sdes p->p_ucred->cr_svgid, 66678031Sdes /* FreeBSD doesn't have fsgid */ 66778031Sdes p->p_ucred->cr_gid); 66878025Sdes sbuf_cat(sb, "Groups:\t"); 66967588Sdes for (i = 0; i < p->p_ucred->cr_ngroups; i++) 67078031Sdes sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]); 67171471Sjhb PROC_UNLOCK(p); 67278025Sdes sbuf_putc(sb, '\n'); 673119068Sdes 67467588Sdes /* 67567588Sdes * Memory 67669799Sdes * 67769799Sdes * While our approximation of VmLib may not be accurate (I 67869799Sdes * don't know of a simple way to verify it, and I'm not sure 67969799Sdes * it has much meaning anyway), I believe it's good enough. 68069799Sdes * 68169799Sdes * The same code that could (I think) accurately compute VmLib 68269799Sdes * could also compute VmLck, but I don't really care enough to 68369799Sdes * implement it. Submissions are welcome. 68467588Sdes */ 685113574Sjhb sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size)); 68678025Sdes sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ 687113574Sjhb sbuf_printf(sb, "VmRss:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize)); 688113574Sjhb sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize)); 689113574Sjhb sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize)); 690113574Sjhb sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize)); 69169995Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 69269995Sdes kp.ki_ssize - kp.ki_tsize - 1; 693113574Sjhb sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize)); 69467588Sdes 69567588Sdes /* 69667588Sdes * Signal masks 69767588Sdes * 69867588Sdes * We support up to 128 signals, while Linux supports 32, 69967588Sdes * but we only define 32 (the same 32 as Linux, to boot), so 70067588Sdes * just show the lower 32 bits of each mask. XXX hack. 70167588Sdes * 70267588Sdes * NB: on certain platforms (Sparc at least) Linux actually 70367588Sdes * supports 64 signals, but this code is a long way from 70467588Sdes * running on anything but i386, so ignore that for now. 70567588Sdes */ 70671471Sjhb PROC_LOCK(p); 707104306Sjmallett sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]); 70869799Sdes /* 70969799Sdes * I can't seem to find out where the signal mask is in 71069799Sdes * relation to struct proc, so SigBlk is left unimplemented. 71169799Sdes */ 71278025Sdes sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */ 713114983Sjhb ps = p->p_sigacts; 714114983Sjhb mtx_lock(&ps->ps_mtx); 715114983Sjhb sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]); 716114983Sjhb sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]); 717114983Sjhb mtx_unlock(&ps->ps_mtx); 71871471Sjhb PROC_UNLOCK(p); 719119068Sdes 72067588Sdes /* 72167588Sdes * Linux also prints the capability masks, but we don't have 72267588Sdes * capabilities yet, and when we do get them they're likely to 72367588Sdes * be meaningless to Linux programs, so we lie. XXX 72467588Sdes */ 72578025Sdes sbuf_printf(sb, "CapInh:\t%016x\n", 0); 72678025Sdes sbuf_printf(sb, "CapPrm:\t%016x\n", 0); 72778025Sdes sbuf_printf(sb, "CapEff:\t%016x\n", 0); 728119068Sdes 72978025Sdes return (0); 73067588Sdes} 73174135Sjlemon 732119911Sdes 73378113Sdes/* 734119911Sdes * Filler function for proc/pid/cwd 735119911Sdes */ 736119911Sdesstatic int 737119911Sdeslinprocfs_doproccwd(PFS_FILL_ARGS) 738119911Sdes{ 739119911Sdes char *fullpath = "unknown"; 740119911Sdes char *freepath = NULL; 741119911Sdes 742119911Sdes vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath); 743119911Sdes sbuf_printf(sb, "%s", fullpath); 744119911Sdes if (freepath) 745119911Sdes free(freepath, M_TEMP); 746119911Sdes return (0); 747119911Sdes} 748119911Sdes 749119911Sdes/* 750119911Sdes * Filler function for proc/pid/root 751119911Sdes */ 752119911Sdesstatic int 753119911Sdeslinprocfs_doprocroot(PFS_FILL_ARGS) 754119911Sdes{ 755119911Sdes struct vnode *rvp; 756119911Sdes char *fullpath = "unknown"; 757119911Sdes char *freepath = NULL; 758119911Sdes 759119911Sdes rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir; 760119911Sdes vn_fullpath(td, rvp, &fullpath, &freepath); 761119911Sdes sbuf_printf(sb, "%s", fullpath); 762119911Sdes if (freepath) 763119911Sdes free(freepath, M_TEMP); 764119911Sdes return (0); 765119911Sdes} 766119911Sdes 767119911Sdes/* 76878113Sdes * Filler function for proc/pid/cmdline 76978113Sdes */ 77078025Sdesstatic int 77178113Sdeslinprocfs_doproccmdline(PFS_FILL_ARGS) 77278113Sdes{ 77378113Sdes struct ps_strings pstr; 77478113Sdes int error, i; 77578113Sdes 77678113Sdes /* 77778113Sdes * If we are using the ps/cmdline caching, use that. Otherwise 77878113Sdes * revert back to the old way which only implements full cmdline 77978113Sdes * for the currept process and just p->p_comm for all other 78078113Sdes * processes. 78178113Sdes * Note that if the argv is no longer available, we deliberately 78278113Sdes * don't fall back on p->p_comm or return an error: the authentic 78378113Sdes * Linux behaviour is to return zero-length in this case. 78478113Sdes */ 78578113Sdes 78694620Sjhb PROC_LOCK(p); 78796886Sjhb if (p->p_args && (ps_argsopen || !p_cansee(td, p))) { 78894620Sjhb sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length); 78994620Sjhb PROC_UNLOCK(p); 79094620Sjhb } else if (p != td->td_proc) { 79194620Sjhb PROC_UNLOCK(p); 79294620Sjhb sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm); 79394620Sjhb } else { 79494620Sjhb PROC_UNLOCK(p); 795103767Sjake error = copyin((void *)p->p_sysent->sv_psstrings, &pstr, 796103767Sjake sizeof(pstr)); 79794620Sjhb if (error) 79894620Sjhb return (error); 79994620Sjhb for (i = 0; i < pstr.ps_nargvstr; i++) { 80094620Sjhb sbuf_copyin(sb, pstr.ps_argvstr[i], 0); 80194620Sjhb sbuf_printf(sb, "%c", '\0'); 80278113Sdes } 80378113Sdes } 80478113Sdes 80578113Sdes return (0); 80678113Sdes} 80778113Sdes 80878113Sdes/* 809116173Sobrien * Filler function for proc/pid/environ 810116173Sobrien */ 811116173Sobrienstatic int 812116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS) 813116173Sobrien{ 814116173Sobrien sbuf_printf(sb, "doprocenviron\n%c", '\0'); 815116173Sobrien 816116173Sobrien return (0); 817116173Sobrien} 818116173Sobrien 819116173Sobrien/* 820116173Sobrien * Filler function for proc/pid/maps 821116173Sobrien */ 822116173Sobrienstatic int 823116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS) 824116173Sobrien{ 825121265Scognet char mebuffer[512]; 826121246Scognet vm_map_t map = &p->p_vmspace->vm_map; 827121246Scognet vm_map_entry_t entry; 828121265Scognet vm_object_t obj, tobj, lobj; 829121265Scognet vm_ooffset_t off = 0; 830121265Scognet char *name = "", *freename = NULL; 831121265Scognet size_t len; 832121265Scognet ino_t ino; 833121265Scognet int ref_count, shadow_count, flags; 834121265Scognet int error; 835121246Scognet 836121246Scognet PROC_LOCK(p); 837121246Scognet error = p_candebug(td, p); 838121246Scognet PROC_UNLOCK(p); 839121246Scognet if (error) 840121246Scognet return (error); 841121246Scognet 842121246Scognet if (uio->uio_rw != UIO_READ) 843121246Scognet return (EOPNOTSUPP); 844121246Scognet 845121246Scognet if (uio->uio_offset != 0) 846121246Scognet return (0); 847121246Scognet 848121246Scognet error = 0; 849121246Scognet if (map != &curthread->td_proc->p_vmspace->vm_map) 850121246Scognet vm_map_lock_read(map); 851121246Scognet for (entry = map->header.next; 852121246Scognet ((uio->uio_resid > 0) && (entry != &map->header)); 853121246Scognet entry = entry->next) { 854121265Scognet name = ""; 855121265Scognet freename = NULL; 856121246Scognet if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) 857121246Scognet continue; 858121246Scognet obj = entry->object.vm_object; 859121246Scognet for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) 860121246Scognet lobj = tobj; 861121246Scognet ino = 0; 862121246Scognet if (lobj) { 863121246Scognet VM_OBJECT_LOCK(lobj); 864121246Scognet off = IDX_TO_OFF(lobj->size); 865121246Scognet if (lobj->type == OBJT_VNODE && lobj->handle) { 866121246Scognet vn_fullpath(td, (struct vnode *)lobj->handle, 867121246Scognet &name, &freename); 868121246Scognet ino = ((struct vnode *) 869121246Scognet lobj->handle)->v_cachedid; 870121246Scognet } 871121246Scognet flags = obj->flags; 872121246Scognet ref_count = obj->ref_count; 873121246Scognet shadow_count = obj->shadow_count; 874121246Scognet VM_OBJECT_UNLOCK(lobj); 875121246Scognet } else { 876121246Scognet flags = 0; 877121246Scognet ref_count = 0; 878121246Scognet shadow_count = 0; 879121246Scognet } 880121246Scognet 881121246Scognet /* 882121246Scognet * format: 883121246Scognet * start, end, access, offset, major, minor, inode, name. 884121246Scognet */ 885121246Scognet snprintf(mebuffer, sizeof mebuffer, 886121246Scognet "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n", 887121246Scognet (u_long)entry->start, (u_long)entry->end, 888121246Scognet (entry->protection & VM_PROT_READ)?"r":"-", 889121246Scognet (entry->protection & VM_PROT_WRITE)?"w":"-", 890121246Scognet (entry->protection & VM_PROT_EXECUTE)?"x":"-", 891121246Scognet "p", 892121265Scognet (u_long)off, 893121246Scognet 0, 894121246Scognet 0, 895121265Scognet (u_long)ino, 896121246Scognet *name ? " " : "", 897121246Scognet name 898121246Scognet ); 899121246Scognet if (freename) 900121246Scognet free(freename, M_TEMP); 901121246Scognet len = strlen(mebuffer); 902121246Scognet if (len > uio->uio_resid) 903121246Scognet len = uio->uio_resid; /* 904121246Scognet * XXX We should probably return 905121246Scognet * EFBIG here, as in procfs. 906121246Scognet */ 907121246Scognet error = uiomove(mebuffer, len, uio); 908121246Scognet if (error) 909121246Scognet break; 910121246Scognet } 911121246Scognet if (map != &curthread->td_proc->p_vmspace->vm_map) 912121246Scognet vm_map_unlock_read(map); 913121246Scognet 914121246Scognet return (error); 915121246Scognet} 916121246Scognet 917116173Sobrien/* 91878113Sdes * Filler function for proc/net/dev 91978113Sdes */ 92078025Sdesstatic int 92178025Sdeslinprocfs_donetdev(PFS_FILL_ARGS) 92274135Sjlemon{ 92385129Sdes char ifname[16]; /* XXX LINUX_IFNAMSIZ */ 92474135Sjlemon struct ifnet *ifp; 92574135Sjlemon 92685129Sdes sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n", 92783926Sdes "Inter-", " Receive", " Transmit", " face", 92885129Sdes "bytes packets errs drop fifo frame compressed", 92983926Sdes "bytes packets errs drop fifo frame compressed"); 93074135Sjlemon 931108172Shsu IFNET_RLOCK(); 93274135Sjlemon TAILQ_FOREACH(ifp, &ifnet, if_link) { 93385129Sdes linux_ifname(ifp, ifname, sizeof ifname); 93485129Sdes sbuf_printf(sb, "%6.6s:", ifname); 93583926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ", 93683926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 93783926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", 93883926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 93974135Sjlemon } 940108172Shsu IFNET_RUNLOCK(); 941119068Sdes 94278025Sdes return (0); 94374135Sjlemon} 94474135Sjlemon 94585538Sphk#if 0 94685538Sphkextern struct cdevsw *cdevsw[]; 94785538Sphk 94878113Sdes/* 94978113Sdes * Filler function for proc/devices 95078113Sdes */ 95178025Sdesstatic int 95278025Sdeslinprocfs_dodevices(PFS_FILL_ARGS) 95374135Sjlemon{ 95474135Sjlemon int i; 95574135Sjlemon 95678025Sdes sbuf_printf(sb, "Character devices:\n"); 95774135Sjlemon 95878025Sdes for (i = 0; i < NUMCDEVSW; i++) 95974135Sjlemon if (cdevsw[i] != NULL) 96078025Sdes sbuf_printf(sb, "%3d %s\n", i, cdevsw[i]->d_name); 96174135Sjlemon 96278025Sdes sbuf_printf(sb, "\nBlock devices:\n"); 963119068Sdes 96478025Sdes return (0); 96574135Sjlemon} 96685538Sphk#endif 96774135Sjlemon 96878113Sdes/* 96978113Sdes * Filler function for proc/cmdline 97078113Sdes */ 97178025Sdesstatic int 97278025Sdeslinprocfs_docmdline(PFS_FILL_ARGS) 97374135Sjlemon{ 97478025Sdes sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname); 97578025Sdes sbuf_printf(sb, " ro root=302\n"); 97678025Sdes return (0); 97778025Sdes} 97874135Sjlemon 97983926Sdes#if 0 98078025Sdes/* 98183926Sdes * Filler function for proc/modules 98283926Sdes */ 98383926Sdesstatic int 98483926Sdeslinprocfs_domodules(PFS_FILL_ARGS) 98583926Sdes{ 98683926Sdes struct linker_file *lf; 987119068Sdes 98883926Sdes TAILQ_FOREACH(lf, &linker_files, link) { 98983926Sdes sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename, 99083926Sdes (unsigned long)lf->size, lf->refs); 99183926Sdes } 99283926Sdes return (0); 99383926Sdes} 99483926Sdes#endif 99583926Sdes 99683926Sdes/* 99785129Sdes * Constructor 99878025Sdes */ 99985129Sdesstatic int 100085129Sdeslinprocfs_init(PFS_INIT_ARGS) 100185129Sdes{ 100285129Sdes struct pfs_node *root; 100385129Sdes struct pfs_node *dir; 100474135Sjlemon 100585129Sdes root = pi->pi_root; 100678025Sdes 1007119923Sdes /* /proc/... */ 1008119911Sdes pfs_create_file(root, "cmdline", &linprocfs_docmdline, 1009119911Sdes NULL, NULL, PFS_RD); 1010119911Sdes pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo, 1011119911Sdes NULL, NULL, PFS_RD); 101285538Sphk#if 0 1013119911Sdes pfs_create_file(root, "devices", &linprocfs_dodevices, 1014119911Sdes NULL, NULL, PFS_RD); 101585538Sphk#endif 1016119911Sdes pfs_create_file(root, "loadavg", &linprocfs_doloadavg, 1017119911Sdes NULL, NULL, PFS_RD); 1018119911Sdes pfs_create_file(root, "meminfo", &linprocfs_domeminfo, 1019119911Sdes NULL, NULL, PFS_RD); 102083926Sdes#if 0 1021119911Sdes pfs_create_file(root, "modules", &linprocfs_domodules, 1022119911Sdes NULL, NULL, PFS_RD); 102383926Sdes#endif 1024119911Sdes pfs_create_file(root, "mtab", &linprocfs_domtab, 1025119911Sdes NULL, NULL, PFS_RD); 102687543Sdes pfs_create_link(root, "self", &procfs_docurproc, 102785129Sdes NULL, NULL, 0); 1028119911Sdes pfs_create_file(root, "stat", &linprocfs_dostat, 1029119911Sdes NULL, NULL, PFS_RD); 1030119911Sdes pfs_create_file(root, "uptime", &linprocfs_douptime, 1031119911Sdes NULL, NULL, PFS_RD); 1032119911Sdes pfs_create_file(root, "version", &linprocfs_doversion, 1033119911Sdes NULL, NULL, PFS_RD); 103478025Sdes 1035119923Sdes /* /proc/net/... */ 103685129Sdes dir = pfs_create_dir(root, "net", NULL, NULL, 0); 103785129Sdes pfs_create_file(dir, "dev", &linprocfs_donetdev, 103885129Sdes NULL, NULL, PFS_RD); 103978025Sdes 1040119923Sdes /* /proc/<pid>/... */ 104185129Sdes dir = pfs_create_dir(root, "pid", NULL, NULL, PFS_PROCDEP); 104285129Sdes pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline, 104385129Sdes NULL, NULL, PFS_RD); 1044119911Sdes pfs_create_link(dir, "cwd", &linprocfs_doproccwd, 1045119911Sdes NULL, NULL, 0); 1046116173Sobrien pfs_create_file(dir, "environ", &linprocfs_doprocenviron, 1047116173Sobrien NULL, NULL, PFS_RD); 104887543Sdes pfs_create_link(dir, "exe", &procfs_doprocfile, 104987543Sdes NULL, &procfs_notsystem, 0); 1050116173Sobrien pfs_create_file(dir, "maps", &linprocfs_doprocmaps, 1051116173Sobrien NULL, NULL, PFS_RD); 105285129Sdes pfs_create_file(dir, "mem", &procfs_doprocmem, 105385129Sdes &procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW); 1054119911Sdes pfs_create_link(dir, "root", &linprocfs_doprocroot, 1055119911Sdes NULL, NULL, 0); 105685129Sdes pfs_create_file(dir, "stat", &linprocfs_doprocstat, 105785129Sdes NULL, NULL, PFS_RD); 1058119911Sdes pfs_create_file(dir, "statm", &linprocfs_doprocstatm, 1059119911Sdes NULL, NULL, PFS_RD); 106085129Sdes pfs_create_file(dir, "status", &linprocfs_doprocstatus, 106185129Sdes NULL, NULL, PFS_RD); 106285129Sdes 106385129Sdes return (0); 106485129Sdes} 106585129Sdes 106685129Sdes/* 106785129Sdes * Destructor 106885129Sdes */ 106985129Sdesstatic int 107085129Sdeslinprocfs_uninit(PFS_INIT_ARGS) 107185129Sdes{ 107285129Sdes 107385129Sdes /* nothing to do, pseudofs will GC */ 107485129Sdes return (0); 107585129Sdes} 107685129Sdes 107785129SdesPSEUDOFS(linprocfs, 1); 107878025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1); 107978025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1); 1080