linprocfs.c revision 76839
1/* 2 * Copyright (c) 2000 Dag-Erling Co�dan Sm�rgrav 3 * Copyright (c) 1999 Pierre Beyssac 4 * Copyright (c) 1993 Jan-Simon Pendry 5 * Copyright (c) 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Jan-Simon Pendry. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94 40 * 41 * $FreeBSD: head/sys/compat/linprocfs/linprocfs.c 76839 2001-05-19 05:54:26Z jlemon $ 42 */ 43 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/blist.h> 47#include <sys/conf.h> 48#include <sys/dkstat.h> 49#include <sys/jail.h> 50#include <sys/kernel.h> 51#include <sys/lock.h> 52#include <sys/malloc.h> 53#include <sys/mutex.h> 54#include <sys/proc.h> 55#include <sys/resourcevar.h> 56#include <sys/sbuf.h> 57#include <sys/sysctl.h> 58#include <sys/tty.h> 59#include <sys/vnode.h> 60 61#include <vm/vm.h> 62#include <vm/pmap.h> 63#include <vm/vm_map.h> 64#include <vm/vm_param.h> 65#include <vm/vm_object.h> 66#include <vm/vm_zone.h> 67#include <vm/swap_pager.h> 68 69#include <sys/exec.h> 70#include <sys/user.h> 71#include <sys/vmmeter.h> 72 73#include <machine/clock.h> 74#include <machine/cputypes.h> 75#include <machine/md_var.h> 76 77#include <sys/socket.h> 78#include <net/if.h> 79 80#include <compat/linux/linux_mib.h> 81#include <compat/linprocfs/linprocfs.h> 82 83extern struct cdevsw *cdevsw[]; 84 85/* 86 * Various conversion macros 87 */ 88#define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz)) /* ticks to jiffies */ 89#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ 90#define B2K(x) ((x) >> 10) /* bytes to kbytes */ 91#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ 92#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ 93#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ 94 95#define COMMON_START \ 96 struct sbuf sb; \ 97 char *ps; \ 98 int error, xlen 99 100#define COMMON_END \ 101 sbuf_finish(&sb); \ 102 ps = sbuf_data(&sb) + uio->uio_offset; \ 103 xlen = sbuf_len(&sb) - uio->uio_offset; \ 104 xlen = imin(xlen, uio->uio_resid); \ 105 error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); \ 106 sbuf_delete(&sb); \ 107 return (error) 108 109int 110linprocfs_domeminfo(curp, p, pfs, uio) 111 struct proc *curp; 112 struct proc *p; 113 struct pfsnode *pfs; 114 struct uio *uio; 115{ 116 COMMON_START; 117 unsigned long memtotal; /* total memory in bytes */ 118 unsigned long memused; /* used memory in bytes */ 119 unsigned long memfree; /* free memory in bytes */ 120 unsigned long memshared; /* shared memory ??? */ 121 unsigned long buffers, cached; /* buffer / cache memory ??? */ 122 u_quad_t swaptotal; /* total swap space in bytes */ 123 u_quad_t swapused; /* used swap space in bytes */ 124 u_quad_t swapfree; /* free swap space in bytes */ 125 vm_object_t object; 126 127 if (uio->uio_rw != UIO_READ) 128 return (EOPNOTSUPP); 129 130 memtotal = physmem * PAGE_SIZE; 131 /* 132 * The correct thing here would be: 133 * 134 memfree = cnt.v_free_count * PAGE_SIZE; 135 memused = memtotal - memfree; 136 * 137 * but it might mislead linux binaries into thinking there 138 * is very little memory left, so we cheat and tell them that 139 * all memory that isn't wired down is free. 140 */ 141 memused = cnt.v_wire_count * PAGE_SIZE; 142 memfree = memtotal - memused; 143 if (swapblist == NULL) { 144 swaptotal = 0; 145 swapfree = 0; 146 } else { 147 swaptotal = (u_quad_t)swapblist->bl_blocks * 1024; /* XXX why 1024? */ 148 swapfree = (u_quad_t)swapblist->bl_root->u.bmu_avail * PAGE_SIZE; 149 } 150 swapused = swaptotal - swapfree; 151 memshared = 0; 152 TAILQ_FOREACH(object, &vm_object_list, object_list) 153 if (object->shadow_count > 1) 154 memshared += object->resident_page_count; 155 memshared *= PAGE_SIZE; 156 /* 157 * We'd love to be able to write: 158 * 159 buffers = bufspace; 160 * 161 * but bufspace is internal to vfs_bio.c and we don't feel 162 * like unstaticizing it just for linprocfs's sake. 163 */ 164 buffers = 0; 165 cached = cnt.v_cache_count * PAGE_SIZE; 166 167 sbuf_new(&sb, NULL, 512, 0); 168 sbuf_printf(&sb, 169 " total: used: free: shared: buffers: cached:\n" 170 "Mem: %lu %lu %lu %lu %lu %lu\n" 171 "Swap: %llu %llu %llu\n" 172 "MemTotal: %9lu kB\n" 173 "MemFree: %9lu kB\n" 174 "MemShared:%9lu kB\n" 175 "Buffers: %9lu kB\n" 176 "Cached: %9lu kB\n" 177 "SwapTotal:%9llu kB\n" 178 "SwapFree: %9llu kB\n", 179 memtotal, memused, memfree, memshared, buffers, cached, 180 swaptotal, swapused, swapfree, 181 B2K(memtotal), B2K(memfree), 182 B2K(memshared), B2K(buffers), B2K(cached), 183 B2K(swaptotal), B2K(swapfree)); 184 185 COMMON_END; 186} 187 188int 189linprocfs_docpuinfo(curp, p, pfs, uio) 190 struct proc *curp; 191 struct proc *p; 192 struct pfsnode *pfs; 193 struct uio *uio; 194{ 195 COMMON_START; 196 int class, i, fqmhz, fqkhz; 197 198 /* 199 * We default the flags to include all non-conflicting flags, 200 * and the Intel versions of conflicting flags. 201 */ 202 static char *flags[] = { 203 "fpu", "vme", "de", "pse", "tsc", 204 "msr", "pae", "mce", "cx8", "apic", 205 "sep", "sep", "mtrr", "pge", "mca", 206 "cmov", "pat", "pse36", "pn", "b19", 207 "b20", "b21", "mmxext", "mmx", "fxsr", 208 "xmm", "b26", "b27", "b28", "b29", 209 "3dnowext", "3dnow" 210 }; 211 212 if (uio->uio_rw != UIO_READ) 213 return (EOPNOTSUPP); 214 215 switch (cpu_class) { 216 case CPUCLASS_286: 217 class = 2; 218 break; 219 case CPUCLASS_386: 220 class = 3; 221 break; 222 case CPUCLASS_486: 223 class = 4; 224 break; 225 case CPUCLASS_586: 226 class = 5; 227 break; 228 case CPUCLASS_686: 229 class = 6; 230 break; 231 default: 232 class = 0; 233 break; 234 } 235 236 sbuf_new(&sb, NULL, 512, 0); 237 sbuf_printf(&sb, 238 "processor\t: %d\n" 239 "vendor_id\t: %.20s\n" 240 "cpu family\t: %d\n" 241 "model\t\t: %d\n" 242 "stepping\t: %d\n", 243 0, cpu_vendor, class, cpu, cpu_id & 0xf); 244 245 sbuf_cat(&sb, 246 "flags\t\t:"); 247 248 if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) { 249 flags[16] = "fcmov"; 250 } else if (!strcmp(cpu_vendor, "CyrixInstead")) { 251 flags[24] = "cxmmx"; 252 } 253 254 for (i = 0; i < 32; i++) 255 if (cpu_feature & (1 << i)) 256 sbuf_printf(&sb, " %s", flags[i]); 257 sbuf_cat(&sb, "\n"); 258 if (class >= 5) { 259 fqmhz = (tsc_freq + 4999) / 1000000; 260 fqkhz = ((tsc_freq + 4999) / 10000) % 100; 261 sbuf_printf(&sb, 262 "cpu MHz\t\t: %d.%02d\n" 263 "bogomips\t: %d.%02d\n", 264 fqmhz, fqkhz, fqmhz, fqkhz); 265 } 266 267 COMMON_END; 268} 269 270int 271linprocfs_dostat(curp, p, pfs, uio) 272 struct proc *curp; 273 struct proc *p; 274 struct pfsnode *pfs; 275 struct uio *uio; 276{ 277 COMMON_START; 278 279 sbuf_new(&sb, NULL, 512, 0); 280 sbuf_printf(&sb, 281 "cpu %ld %ld %ld %ld\n" 282 "disk 0 0 0 0\n" 283 "page %u %u\n" 284 "swap %u %u\n" 285 "intr %u\n" 286 "ctxt %u\n" 287 "btime %ld\n", 288 T2J(cp_time[CP_USER]), 289 T2J(cp_time[CP_NICE]), 290 T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), 291 T2J(cp_time[CP_IDLE]), 292 cnt.v_vnodepgsin, 293 cnt.v_vnodepgsout, 294 cnt.v_swappgsin, 295 cnt.v_swappgsout, 296 cnt.v_intr, 297 cnt.v_swtch, 298 boottime.tv_sec); 299 300 COMMON_END; 301} 302 303int 304linprocfs_douptime(curp, p, pfs, uio) 305 struct proc *curp; 306 struct proc *p; 307 struct pfsnode *pfs; 308 struct uio *uio; 309{ 310 COMMON_START; 311 struct timeval tv; 312 313 getmicrouptime(&tv); 314 sbuf_new(&sb, NULL, 64, 0); 315 sbuf_printf(&sb, "%ld.%02ld %ld.%02ld\n", 316 tv.tv_sec, tv.tv_usec / 10000, 317 T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100); 318 319 COMMON_END; 320} 321 322int 323linprocfs_doversion(curp, p, pfs, uio) 324 struct proc *curp; 325 struct proc *p; 326 struct pfsnode *pfs; 327 struct uio *uio; 328{ 329 COMMON_START; 330 331 sbuf_new(&sb, NULL, 128, 0); 332 sbuf_printf(&sb, 333 "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")" 334 " #4 Sun Dec 18 04:30:00 CET 1977\n", 335 linux_get_osname(curp), 336 linux_get_osrelease(curp)); 337 338 COMMON_END; 339} 340 341int 342linprocfs_doloadavg(curp, p, pfs, uio) 343 struct proc *curp; 344 struct proc *p; 345 struct pfsnode *pfs; 346 struct uio *uio; 347{ 348 COMMON_START; 349 int lastpid, ilen; 350 351 ilen = sizeof(lastpid); 352 if (kernel_sysctlbyname(p, "kern.lastpid", 353 &lastpid, &ilen, NULL, 0, NULL) != 0) 354 lastpid = -1; /* fake it */ 355 356 sbuf_new(&sb, NULL, 128, 0); 357 sbuf_printf(&sb, 358 "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 359 (int)(averunnable.ldavg[0] / averunnable.fscale), 360 (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 361 (int)(averunnable.ldavg[1] / averunnable.fscale), 362 (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 363 (int)(averunnable.ldavg[2] / averunnable.fscale), 364 (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 365 1, /* number of running tasks */ 366 nprocs, /* number of tasks */ 367 lastpid /* the last pid */ 368 ); 369 370 COMMON_END; 371} 372 373int 374linprocfs_doprocstat(curp, p, pfs, uio) 375 struct proc *curp; 376 struct proc *p; 377 struct pfsnode *pfs; 378 struct uio *uio; 379{ 380 COMMON_START; 381 struct kinfo_proc kp; 382 383 fill_kinfo_proc(p, &kp); 384 sbuf_new(&sb, NULL, 1024, 0); 385 sbuf_printf(&sb, "%d", p->p_pid); 386#define PS_ADD(name, fmt, arg) sbuf_printf(&sb, " " fmt, arg) 387 PS_ADD("comm", "(%s)", p->p_comm); 388 PS_ADD("statr", "%c", '0'); /* XXX */ 389 PROC_LOCK(p); 390 PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); 391 PROC_UNLOCK(p); 392 PS_ADD("pgrp", "%d", p->p_pgid); 393 PS_ADD("session", "%d", p->p_session->s_sid); 394 PS_ADD("tty", "%d", 0); /* XXX */ 395 PS_ADD("tpgid", "%d", 0); /* XXX */ 396 PS_ADD("flags", "%u", 0); /* XXX */ 397 PS_ADD("minflt", "%u", 0); /* XXX */ 398 PS_ADD("cminflt", "%u", 0); /* XXX */ 399 PS_ADD("majflt", "%u", 0); /* XXX */ 400 PS_ADD("cminflt", "%u", 0); /* XXX */ 401 PS_ADD("utime", "%d", 0); /* XXX */ 402 PS_ADD("stime", "%d", 0); /* XXX */ 403 PS_ADD("cutime", "%d", 0); /* XXX */ 404 PS_ADD("cstime", "%d", 0); /* XXX */ 405 PS_ADD("counter", "%d", 0); /* XXX */ 406 PS_ADD("priority", "%d", 0); /* XXX */ 407 PS_ADD("timeout", "%u", 0); /* XXX */ 408 PS_ADD("itrealvalue", "%u", 0); /* XXX */ 409 PS_ADD("starttime", "%d", 0); /* XXX */ 410 PS_ADD("vsize", "%u", kp.ki_size); 411 PS_ADD("rss", "%u", P2K(kp.ki_rssize)); 412 PS_ADD("rlim", "%u", 0); /* XXX */ 413 PS_ADD("startcode", "%u", (unsigned)0); 414 PS_ADD("endcode", "%u", 0); /* XXX */ 415 PS_ADD("startstack", "%u", 0); /* XXX */ 416 PS_ADD("esp", "%u", 0); /* XXX */ 417 PS_ADD("eip", "%u", 0); /* XXX */ 418 PS_ADD("signal", "%d", 0); /* XXX */ 419 PS_ADD("blocked", "%d", 0); /* XXX */ 420 PS_ADD("sigignore", "%d", 0); /* XXX */ 421 PS_ADD("sigcatch", "%d", 0); /* XXX */ 422 PS_ADD("wchan", "%u", 0); /* XXX */ 423 PS_ADD("nswap", "%lu", (long unsigned)0); /* XXX */ 424 PS_ADD("cnswap", "%lu", (long unsigned)0); /* XXX */ 425 PS_ADD("exitsignal", "%d", 0); /* XXX */ 426 PS_ADD("processor", "%d", 0); /* XXX */ 427#undef PS_ADD 428 sbuf_putc(&sb, '\n'); 429 430 COMMON_END; 431} 432 433/* 434 * Map process state to descriptive letter. Note that this does not 435 * quite correspond to what Linux outputs, but it's close enough. 436 */ 437static char *state_str[] = { 438 "? (unknown)", 439 "I (idle)", 440 "R (running)", 441 "S (sleeping)", 442 "T (stopped)", 443 "Z (zombie)", 444 "W (waiting)", 445 "M (mutex)" 446}; 447 448int 449linprocfs_doprocstatus(curp, p, pfs, uio) 450 struct proc *curp; 451 struct proc *p; 452 struct pfsnode *pfs; 453 struct uio *uio; 454{ 455 COMMON_START; 456 struct kinfo_proc kp; 457 char *state; 458 segsz_t lsize; 459 int i; 460 461 sbuf_new(&sb, NULL, 1024, 0); 462 463 mtx_lock_spin(&sched_lock); 464 if (p->p_stat > sizeof state_str / sizeof *state_str) 465 state = state_str[0]; 466 else 467 state = state_str[(int)p->p_stat]; 468 mtx_unlock_spin(&sched_lock); 469 470 fill_kinfo_proc(p, &kp); 471 sbuf_printf(&sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ 472 sbuf_printf(&sb, "State:\t%s\n", state); 473 474 /* 475 * Credentials 476 */ 477 sbuf_printf(&sb, "Pid:\t%d\n", p->p_pid); 478 PROC_LOCK(p); 479 sbuf_printf(&sb, "PPid:\t%d\n", p->p_pptr ? 480 p->p_pptr->p_pid : 0); 481 sbuf_printf(&sb, "Uid:\t%d %d %d %d\n", p->p_cred->p_ruid, 482 p->p_ucred->cr_uid, 483 p->p_cred->p_svuid, 484 /* FreeBSD doesn't have fsuid */ 485 p->p_ucred->cr_uid); 486 sbuf_printf(&sb, "Gid:\t%d %d %d %d\n", p->p_cred->p_rgid, 487 p->p_ucred->cr_gid, 488 p->p_cred->p_svgid, 489 /* FreeBSD doesn't have fsgid */ 490 p->p_ucred->cr_gid); 491 sbuf_cat(&sb, "Groups:\t"); 492 for (i = 0; i < p->p_ucred->cr_ngroups; i++) 493 sbuf_printf(&sb, "%d ", p->p_ucred->cr_groups[i]); 494 PROC_UNLOCK(p); 495 sbuf_putc(&sb, '\n'); 496 497 /* 498 * Memory 499 * 500 * While our approximation of VmLib may not be accurate (I 501 * don't know of a simple way to verify it, and I'm not sure 502 * it has much meaning anyway), I believe it's good enough. 503 * 504 * The same code that could (I think) accurately compute VmLib 505 * could also compute VmLck, but I don't really care enough to 506 * implement it. Submissions are welcome. 507 */ 508 sbuf_printf(&sb, "VmSize:\t%8u kB\n", B2K(kp.ki_size)); 509 sbuf_printf(&sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ 510 sbuf_printf(&sb, "VmRss:\t%8u kB\n", P2K(kp.ki_rssize)); 511 sbuf_printf(&sb, "VmData:\t%8u kB\n", P2K(kp.ki_dsize)); 512 sbuf_printf(&sb, "VmStk:\t%8u kB\n", P2K(kp.ki_ssize)); 513 sbuf_printf(&sb, "VmExe:\t%8u kB\n", P2K(kp.ki_tsize)); 514 lsize = B2P(kp.ki_size) - kp.ki_dsize - 515 kp.ki_ssize - kp.ki_tsize - 1; 516 sbuf_printf(&sb, "VmLib:\t%8u kB\n", P2K(lsize)); 517 518 /* 519 * Signal masks 520 * 521 * We support up to 128 signals, while Linux supports 32, 522 * but we only define 32 (the same 32 as Linux, to boot), so 523 * just show the lower 32 bits of each mask. XXX hack. 524 * 525 * NB: on certain platforms (Sparc at least) Linux actually 526 * supports 64 signals, but this code is a long way from 527 * running on anything but i386, so ignore that for now. 528 */ 529 PROC_LOCK(p); 530 sbuf_printf(&sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]); 531 /* 532 * I can't seem to find out where the signal mask is in 533 * relation to struct proc, so SigBlk is left unimplemented. 534 */ 535 sbuf_printf(&sb, "SigBlk:\t%08x\n", 0); /* XXX */ 536 sbuf_printf(&sb, "SigIgn:\t%08x\n", p->p_sigignore.__bits[0]); 537 sbuf_printf(&sb, "SigCgt:\t%08x\n", p->p_sigcatch.__bits[0]); 538 PROC_UNLOCK(p); 539 540 /* 541 * Linux also prints the capability masks, but we don't have 542 * capabilities yet, and when we do get them they're likely to 543 * be meaningless to Linux programs, so we lie. XXX 544 */ 545 sbuf_printf(&sb, "CapInh:\t%016x\n", 0); 546 sbuf_printf(&sb, "CapPrm:\t%016x\n", 0); 547 sbuf_printf(&sb, "CapEff:\t%016x\n", 0); 548 549 COMMON_END; 550} 551 552int 553linprocfs_doselflink(curp, p, pfs, uio) 554 struct proc *curp; 555 struct proc *p; 556 struct pfsnode *pfs; 557 struct uio *uio; 558{ 559 char buf[16]; /* should be enough */ 560 int len; 561 562 /* XXX shouldn't this be uio->uio_procp->p_pid? */ 563 len = snprintf(buf, sizeof(buf), "%ld", (long)curproc->p_pid); 564 565 return (uiomove(buf, len, uio)); 566} 567 568int 569linprocfs_doexelink(curp, p, pfs, uio) 570 struct proc *curp; 571 struct proc *p; 572 struct pfsnode *pfs; 573 struct uio *uio; 574{ 575 int error = 0; 576 char *fullpath = "unknown"; 577 char *freepath = NULL; 578 579 p = PFIND(pfs->pfs_pid); 580 if (p == NULL || p->p_cred == NULL || p->p_ucred == NULL) { 581 if (p != NULL) 582 PROC_UNLOCK(p); 583 printf("doexelink: pid %d disappeared\n", pfs->pfs_pid); 584 } else { 585 PROC_UNLOCK(p); 586 /* fullpath/freepath are unchanged if textvp_fullpath fails */ 587 error = textvp_fullpath(p, &fullpath, &freepath); 588 } 589 error = uiomove(fullpath, strlen(fullpath), uio); 590 if (freepath) 591 free(freepath, M_TEMP); 592 return (error); 593} 594 595int 596linprocfs_donetdev(curp, p, pfs, uio) 597 struct proc *curp; 598 struct proc *p; 599 struct pfsnode *pfs; 600 struct uio *uio; 601{ 602 COMMON_START; 603 struct ifnet *ifp; 604 int eth_index = 0; 605 606 sbuf_new(&sb, NULL, 1024, 0); 607 sbuf_printf(&sb, 608 "Inter-| Receive " 609 " | Transmit\n" 610 " face |bytes packets errs drop fifo frame compressed " 611 "multicast|bytes packets errs drop fifo colls carrier " 612 "compressed\n"); 613 614 TAILQ_FOREACH(ifp, &ifnet, if_link) { 615 if (strcmp(ifp->if_name, "lo") == 0) { 616 sbuf_printf(&sb, "%6.6s:", ifp->if_name); 617 } else { 618 sbuf_printf(&sb, "%5.5s%d:", "eth", eth_index); 619 eth_index++; 620 } 621 sbuf_printf(&sb, 622 "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu " 623 "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", 624 0, 0, 0, 0, 0, 0, 0, 0, 625 0, 0, 0, 0, 0, 0, 0, 0); 626 } 627 628 COMMON_END; 629} 630 631int 632linprocfs_dodevices(curp, p, pfs, uio) 633 struct proc *curp; 634 struct proc *p; 635 struct pfsnode *pfs; 636 struct uio *uio; 637{ 638 COMMON_START; 639 int i; 640 641 sbuf_new(&sb, NULL, 1024, 0); 642 sbuf_printf(&sb, "Character devices:\n"); 643 644 for (i = 0; i < NUMCDEVSW; i++) { 645 if (cdevsw[i] != NULL) 646 sbuf_printf(&sb, "%3d %s\n", i, cdevsw[i]->d_name); 647 } 648 649 sbuf_printf(&sb, "\nBlock devices:\n"); 650 651 COMMON_END; 652} 653 654int 655linprocfs_docmdline(curp, p, pfs, uio) 656 struct proc *curp; 657 struct proc *p; 658 struct pfsnode *pfs; 659 struct uio *uio; 660{ 661 COMMON_START; 662 663 sbuf_new(&sb, NULL, 128, 0); 664 sbuf_printf(&sb, "BOOT_IMAGE=%s", kernelname); 665 sbuf_printf(&sb, " ro root=302\n"); 666 667 COMMON_END; 668} 669