init_sysctl.c revision 1.20
1/* $NetBSD: init_sysctl.c,v 1.20 2004/01/17 03:33:24 atatat Exp $ */ 2 3/*- 4 * Copyright (c) 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Brown. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39#include <sys/cdefs.h> 40__KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.20 2004/01/17 03:33:24 atatat Exp $"); 41 42#include "opt_sysv.h" 43#include "opt_multiprocessor.h" 44#include "opt_posix.h" 45#include "pty.h" 46#include "rnd.h" 47 48#include <sys/types.h> 49#include <sys/param.h> 50#include <sys/sysctl.h> 51#include <sys/errno.h> 52#include <sys/systm.h> 53#include <sys/kernel.h> 54#include <sys/unistd.h> 55#include <sys/disklabel.h> 56#include <sys/rnd.h> 57#include <sys/vnode.h> 58#include <sys/mount.h> 59#include <sys/namei.h> 60#include <sys/msgbuf.h> 61#include <dev/cons.h> 62#include <sys/socketvar.h> 63#include <sys/file.h> 64#include <sys/tty.h> 65#include <sys/malloc.h> 66#include <sys/resource.h> 67#include <sys/resourcevar.h> 68#include <sys/exec.h> 69#include <sys/conf.h> 70#include <sys/device.h> 71 72#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 73#include <sys/ipc.h> 74#endif 75#ifdef SYSVMSG 76#include <sys/msg.h> 77#endif 78#ifdef SYSVSEM 79#include <sys/sem.h> 80#endif 81#ifdef SYSVSHM 82#include <sys/shm.h> 83#endif 84 85#include <machine/cpu.h> 86 87/* 88 * try over estimating by 5 procs/lwps 89 */ 90#define KERN_PROCSLOP (5 * sizeof(struct kinfo_proc)) 91#define KERN_LWPSLOP (5 * sizeof(struct kinfo_lwp)) 92 93/* 94 * convert pointer to 64 int for struct kinfo_proc2 95 */ 96#define PTRTOINT64(foo) ((u_int64_t)(uintptr_t)(foo)) 97 98#ifndef MULTIPROCESSOR 99#define sysctl_ncpus() (1) 100#else /* MULTIPROCESSOR */ 101#ifndef CPU_INFO_FOREACH 102#define CPU_INFO_ITERATOR int 103#define CPU_INFO_FOREACH(cii, ci) cii = 0, ci = curcpu(); ci != NULL; ci = NULL 104#endif 105static int 106sysctl_ncpus(void) 107{ 108 struct cpu_info *ci; 109 CPU_INFO_ITERATOR cii; 110 111 int ncpus = 0; 112 for (CPU_INFO_FOREACH(cii, ci)) 113 ncpus++; 114 return (ncpus); 115} 116#endif /* MULTIPROCESSOR */ 117 118static int sysctl_kern_maxvnodes(SYSCTLFN_PROTO); 119static int sysctl_kern_rtc_offset(SYSCTLFN_PROTO); 120static int sysctl_kern_maxproc(SYSCTLFN_PROTO); 121static int sysctl_kern_securelevel(SYSCTLFN_PROTO); 122static int sysctl_kern_hostid(SYSCTLFN_PROTO); 123static int sysctl_setlen(SYSCTLFN_PROTO); 124static int sysctl_kern_clockrate(SYSCTLFN_PROTO); 125static int sysctl_kern_file(SYSCTLFN_PROTO); 126static int sysctl_kern_autonice(SYSCTLFN_PROTO); 127static int sysctl_msgbuf(SYSCTLFN_PROTO); 128static int sysctl_kern_defcorename(SYSCTLFN_PROTO); 129static int sysctl_kern_cptime(SYSCTLFN_PROTO); 130#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 131static int sysctl_kern_sysvipc(SYSCTLFN_PROTO); 132#endif /* defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) */ 133#if NPTY > 0 134static int sysctl_kern_maxptys(SYSCTLFN_PROTO); 135#endif /* NPTY > 0 */ 136static int sysctl_kern_sbmax(SYSCTLFN_PROTO); 137static int sysctl_kern_urnd(SYSCTLFN_PROTO); 138static int sysctl_kern_lwp(SYSCTLFN_PROTO); 139static int sysctl_kern_forkfsleep(SYSCTLFN_PROTO); 140static int sysctl_kern_somaxkva(SYSCTLFN_PROTO); 141static int sysctl_kern_root_partition(SYSCTLFN_PROTO); 142static int sysctl_kern_drivers(SYSCTLFN_PROTO); 143static int sysctl_doeproc(SYSCTLFN_PROTO); 144static int sysctl_kern_proc_args(SYSCTLFN_PROTO); 145static int sysctl_hw_usermem(SYSCTLFN_PROTO); 146static int sysctl_hw_cnmagic(SYSCTLFN_PROTO); 147static int sysctl_hw_ncpu(SYSCTLFN_PROTO); 148 149static void fill_kproc2(struct proc *, struct kinfo_proc2 *); 150static void fill_lwp(struct lwp *l, struct kinfo_lwp *kl); 151 152/* 153 * ******************************************************************** 154 * section 1: setup routines 155 * ******************************************************************** 156 * these functions are stuffed into a link set for sysctl setup 157 * functions. they're never called or referenced from anywhere else. 158 * ******************************************************************** 159 */ 160 161/* 162 * sets up the base nodes... 163 */ 164SYSCTL_SETUP(sysctl_root_setup, "sysctl base setup") 165{ 166 167 sysctl_createv(SYSCTL_PERMANENT, 168 CTLTYPE_NODE, "kern", NULL, 169 NULL, 0, NULL, 0, 170 CTL_KERN, CTL_EOL); 171 sysctl_createv(SYSCTL_PERMANENT, 172 CTLTYPE_NODE, "vm", NULL, 173 NULL, 0, NULL, 0, 174 CTL_VM, CTL_EOL); 175 sysctl_createv(SYSCTL_PERMANENT, 176 CTLTYPE_NODE, "vfs", NULL, 177 NULL, 0, NULL, 0, 178 CTL_VFS, CTL_EOL); 179 sysctl_createv(SYSCTL_PERMANENT, 180 CTLTYPE_NODE, "net", NULL, 181 NULL, 0, NULL, 0, 182 CTL_NET, CTL_EOL); 183 sysctl_createv(SYSCTL_PERMANENT, 184 CTLTYPE_NODE, "debug", NULL, 185 NULL, 0, NULL, 0, 186 CTL_DEBUG, CTL_EOL); 187 sysctl_createv(SYSCTL_PERMANENT, 188 CTLTYPE_NODE, "hw", NULL, 189 NULL, 0, NULL, 0, 190 CTL_HW, CTL_EOL); 191 sysctl_createv(SYSCTL_PERMANENT, 192 CTLTYPE_NODE, "machdep", NULL, 193 NULL, 0, NULL, 0, 194 CTL_MACHDEP, CTL_EOL); 195 /* 196 * this node is inserted so that the sysctl nodes in libc can 197 * operate. 198 */ 199 sysctl_createv(SYSCTL_PERMANENT, 200 CTLTYPE_NODE, "user", NULL, 201 NULL, 0, NULL, 0, 202 CTL_USER, CTL_EOL); 203 sysctl_createv(SYSCTL_PERMANENT, 204 CTLTYPE_NODE, "ddb", NULL, 205 NULL, 0, NULL, 0, 206 CTL_DDB, CTL_EOL); 207 sysctl_createv(SYSCTL_PERMANENT, 208 CTLTYPE_NODE, "proc", NULL, 209 NULL, 0, NULL, 0, 210 CTL_PROC, CTL_EOL); 211 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 212 CTLTYPE_NODE, "vendor", NULL, 213 NULL, 0, NULL, 0, 214 CTL_VENDOR, CTL_EOL); 215 sysctl_createv(SYSCTL_PERMANENT, 216 CTLTYPE_NODE, "emul", NULL, 217 NULL, 0, NULL, 0, 218 CTL_EMUL, CTL_EOL); 219} 220 221/* 222 * this setup routine is a replacement for kern_sysctl() 223 */ 224SYSCTL_SETUP(sysctl_kern_setup, "sysctl kern subtree setup") 225{ 226 extern int kern_logsigexit; /* defined in kern/kern_sig.c */ 227 extern fixpt_t ccpu; /* defined in kern/kern_synch.c */ 228 extern int dumponpanic; /* defined in kern/subr_prf.c */ 229 230 sysctl_createv(SYSCTL_PERMANENT, 231 CTLTYPE_NODE, "kern", NULL, 232 NULL, 0, NULL, 0, 233 CTL_KERN, CTL_EOL); 234 235 sysctl_createv(SYSCTL_PERMANENT, 236 CTLTYPE_STRING, "ostype", NULL, 237 NULL, 0, &ostype, 0, 238 CTL_KERN, KERN_OSTYPE, CTL_EOL); 239 sysctl_createv(SYSCTL_PERMANENT, 240 CTLTYPE_STRING, "osrelease", NULL, 241 NULL, 0, &osrelease, 0, 242 CTL_KERN, KERN_OSRELEASE, CTL_EOL); 243 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 244 CTLTYPE_INT, "osrevision", NULL, 245 NULL, __NetBSD_Version__, NULL, 0, 246 CTL_KERN, KERN_OSREV, CTL_EOL); 247 sysctl_createv(SYSCTL_PERMANENT, 248 CTLTYPE_STRING, "version", NULL, 249 NULL, 0, &version, 0, 250 CTL_KERN, KERN_VERSION, CTL_EOL); 251 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 252 CTLTYPE_INT, "maxvnodes", NULL, 253 sysctl_kern_maxvnodes, 0, NULL, 0, 254 CTL_KERN, KERN_MAXVNODES, CTL_EOL); 255 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 256 CTLTYPE_INT, "maxproc", NULL, 257 sysctl_kern_maxproc, 0, NULL, 0, 258 CTL_KERN, KERN_MAXPROC, CTL_EOL); 259 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 260 CTLTYPE_INT, "maxfiles", NULL, 261 NULL, 0, &maxfiles, 0, 262 CTL_KERN, KERN_MAXFILES, CTL_EOL); 263 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 264 CTLTYPE_INT, "argmax", NULL, 265 NULL, ARG_MAX, NULL, 0, 266 CTL_KERN, KERN_ARGMAX, CTL_EOL); 267 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 268 CTLTYPE_INT, "securelevel", NULL, 269 sysctl_kern_securelevel, 0, &securelevel, 0, 270 CTL_KERN, KERN_SECURELVL, CTL_EOL); 271 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 272 CTLTYPE_STRING, "hostname", NULL, 273 sysctl_setlen, 0, &hostname, MAXHOSTNAMELEN, 274 CTL_KERN, KERN_HOSTNAME, CTL_EOL); 275 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 276 CTLTYPE_INT, "hostid", NULL, 277 sysctl_kern_hostid, 0, NULL, 0, 278 CTL_KERN, KERN_HOSTID, CTL_EOL); 279 sysctl_createv(SYSCTL_PERMANENT, 280 CTLTYPE_STRUCT, "clockrate", NULL, 281 sysctl_kern_clockrate, 0, NULL, 282 sizeof(struct clockinfo), 283 CTL_KERN, KERN_CLOCKRATE, CTL_EOL); 284 sysctl_createv(SYSCTL_PERMANENT, 285 CTLTYPE_STRUCT, "vnode", NULL, 286 sysctl_kern_vnode, 0, NULL, 0, 287 CTL_KERN, KERN_VNODE, CTL_EOL); 288 sysctl_createv(SYSCTL_PERMANENT, 289 CTLTYPE_STRUCT, "file", NULL, 290 sysctl_kern_file, 0, NULL, 0, 291 CTL_KERN, KERN_FILE, CTL_EOL); 292#ifndef GPROF 293 sysctl_createv(SYSCTL_PERMANENT, 294 CTLTYPE_NODE, "profiling", NULL, 295 sysctl_notavail, 0, NULL, 0, 296 CTL_KERN, KERN_PROF, CTL_EOL); 297#endif 298 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 299 CTLTYPE_INT, "posix1version", NULL, 300 NULL, _POSIX_VERSION, NULL, 0, 301 CTL_KERN, KERN_POSIX1, CTL_EOL); 302 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 303 CTLTYPE_INT, "ngroups", NULL, 304 NULL, NGROUPS_MAX, NULL, 0, 305 CTL_KERN, KERN_NGROUPS, CTL_EOL); 306 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 307 CTLTYPE_INT, "job_control", NULL, 308 NULL, 1, NULL, 0, 309 CTL_KERN, KERN_JOB_CONTROL, CTL_EOL); 310 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 311 CTLTYPE_INT, "saved_ids", NULL, NULL, 312#ifdef _POSIX_SAVED_IDS 313 1, 314#else /* _POSIX_SAVED_IDS */ 315 0, 316#endif /* _POSIX_SAVED_IDS */ 317 NULL, 0, CTL_KERN, KERN_SAVED_IDS, CTL_EOL); 318 sysctl_createv(SYSCTL_PERMANENT, 319 CTLTYPE_STRUCT, "boottime", NULL, 320 NULL, 0, &boottime, sizeof(boottime), 321 CTL_KERN, KERN_BOOTTIME, CTL_EOL); 322 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 323 CTLTYPE_STRING, "domainname", NULL, 324 sysctl_setlen, 0, &domainname, MAXHOSTNAMELEN, 325 CTL_KERN, KERN_DOMAINNAME, CTL_EOL); 326 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 327 CTLTYPE_INT, "maxpartitions", NULL, 328 NULL, MAXPARTITIONS, NULL, 0, 329 CTL_KERN, KERN_MAXPARTITIONS, CTL_EOL); 330 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 331 CTLTYPE_INT, "rawpartition", NULL, 332 NULL, RAW_PART, NULL, 0, 333 CTL_KERN, KERN_RAWPARTITION, CTL_EOL); 334 sysctl_createv(SYSCTL_PERMANENT, 335 CTLTYPE_STRUCT, "timex", NULL, 336 sysctl_notavail, 0, NULL, 0, 337 CTL_KERN, KERN_TIMEX, CTL_EOL); 338 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 339 CTLTYPE_INT, "autonicetime", NULL, 340 sysctl_kern_autonice, 0, &autonicetime, 0, 341 CTL_KERN, KERN_AUTONICETIME, CTL_EOL); 342 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 343 CTLTYPE_INT, "autoniceval", NULL, 344 sysctl_kern_autonice, 0, &autoniceval, 0, 345 CTL_KERN, KERN_AUTONICEVAL, CTL_EOL); 346 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 347 CTLTYPE_INT, "rtc_offset", NULL, 348 sysctl_kern_rtc_offset, 0, &rtc_offset, 0, 349 CTL_KERN, KERN_RTC_OFFSET, CTL_EOL); 350 sysctl_createv(SYSCTL_PERMANENT, 351 CTLTYPE_STRING, "root_device", NULL, 352 sysctl_root_device, 0, NULL, 0, 353 CTL_KERN, KERN_ROOT_DEVICE, CTL_EOL); 354 sysctl_createv(SYSCTL_PERMANENT, 355 CTLTYPE_INT, "msgbufsize", NULL, 356 sysctl_msgbuf, 0, &msgbufp->msg_bufs, 0, 357 CTL_KERN, KERN_MSGBUFSIZE, CTL_EOL); 358 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 359 CTLTYPE_INT, "fsync", NULL, 360 NULL, 1, NULL, 0, 361 CTL_KERN, KERN_FSYNC, CTL_EOL); 362 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 363 CTLTYPE_INT, "sysvmsg", NULL, NULL, 364#ifdef SYSVMSG 365 1, 366#else /* SYSVMSG */ 367 0, 368#endif /* SYSVMSG */ 369 NULL, 0, CTL_KERN, KERN_SYSVMSG, CTL_EOL); 370 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 371 CTLTYPE_INT, "sysvsem", NULL, NULL, 372#ifdef SYSVSEM 373 1, 374#else /* SYSVSEM */ 375 0, 376#endif /* SYSVSEM */ 377 NULL, 0, CTL_KERN, KERN_SYSVSEM, CTL_EOL); 378 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 379 CTLTYPE_INT, "sysvshm", NULL, NULL, 380#ifdef SYSVSHM 381 1, 382#else /* SYSVSHM */ 383 0, 384#endif /* SYSVSHM */ 385 NULL, 0, CTL_KERN, KERN_SYSVSHM, CTL_EOL); 386 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 387 CTLTYPE_INT, "synchronized_io", NULL, 388 NULL, 1, NULL, 0, 389 CTL_KERN, KERN_SYNCHRONIZED_IO, CTL_EOL); 390 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 391 CTLTYPE_INT, "iov_max", NULL, 392 NULL, IOV_MAX, NULL, 0, 393 CTL_KERN, KERN_IOV_MAX, CTL_EOL); 394 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 395 CTLTYPE_INT, "mapped_files", NULL, 396 NULL, 1, NULL, 0, 397 CTL_KERN, KERN_MAPPED_FILES, CTL_EOL); 398 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 399 CTLTYPE_INT, "memlock", NULL, 400 NULL, 1, NULL, 0, 401 CTL_KERN, KERN_MEMLOCK, CTL_EOL); 402 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 403 CTLTYPE_INT, "memlock_range", NULL, 404 NULL, 1, NULL, 0, 405 CTL_KERN, KERN_MEMLOCK_RANGE, CTL_EOL); 406 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 407 CTLTYPE_INT, "memory_protection", NULL, 408 NULL, 1, NULL, 0, 409 CTL_KERN, KERN_MEMORY_PROTECTION, CTL_EOL); 410 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 411 CTLTYPE_INT, "login_name_max", NULL, 412 NULL, LOGIN_NAME_MAX, NULL, 0, 413 CTL_KERN, KERN_LOGIN_NAME_MAX, CTL_EOL); 414 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 415 CTLTYPE_STRING, "defcorename", NULL, 416 sysctl_kern_defcorename, 0, defcorename, MAXPATHLEN, 417 CTL_KERN, KERN_DEFCORENAME, CTL_EOL); 418 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 419 CTLTYPE_INT, "logsigexit", NULL, 420 NULL, 0, &kern_logsigexit, 0, 421 CTL_KERN, KERN_LOGSIGEXIT, CTL_EOL); 422 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 423 CTLTYPE_INT, "fscale", NULL, 424 NULL, FSCALE, NULL, 0, 425 CTL_KERN, KERN_FSCALE, CTL_EOL); 426 sysctl_createv(SYSCTL_PERMANENT, 427 CTLTYPE_INT, "ccpu", NULL, 428 NULL, 0, &ccpu, 0, 429 CTL_KERN, KERN_CCPU, CTL_EOL); 430 sysctl_createv(SYSCTL_PERMANENT, 431 CTLTYPE_STRUCT, "cp_time", NULL, 432 sysctl_kern_cptime, 0, NULL, 0, 433 CTL_KERN, KERN_CP_TIME, CTL_EOL); 434#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 435 sysctl_createv(SYSCTL_PERMANENT, 436 CTLTYPE_STRUCT, "sysvipc_info", NULL, 437 sysctl_kern_sysvipc, 0, NULL, 0, 438 CTL_KERN, KERN_SYSVIPC_INFO, CTL_EOL); 439#endif /* SYSVMSG || SYSVSEM || SYSVSHM */ 440 sysctl_createv(SYSCTL_PERMANENT, 441 CTLTYPE_INT, "msgbuf", NULL, 442 sysctl_msgbuf, 0, NULL, 0, 443 CTL_KERN, KERN_MSGBUF, CTL_EOL); 444 sysctl_createv(SYSCTL_PERMANENT, 445 CTLTYPE_STRUCT, "consdev", NULL, 446 sysctl_consdev, 0, NULL, sizeof(dev_t), 447 CTL_KERN, KERN_CONSDEV, CTL_EOL); 448#if NPTY > 0 449 sysctl_createv(SYSCTL_PERMANENT, 450 CTLTYPE_INT, "maxptys", NULL, 451 sysctl_kern_maxptys, 0, NULL, 0, 452 CTL_KERN, KERN_MAXPTYS, CTL_EOL); 453#endif /* NPTY > 0 */ 454 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 455 CTLTYPE_INT, "maxphys", NULL, 456 NULL, MAXPHYS, NULL, 0, 457 CTL_KERN, KERN_MAXPHYS, CTL_EOL); 458 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 459 CTLTYPE_INT, "sbmax", NULL, 460 sysctl_kern_sbmax, 0, NULL, 0, 461 CTL_KERN, KERN_SBMAX, CTL_EOL); 462 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 463 CTLTYPE_INT, "monotonic_clock", NULL, 464 /* XXX _POSIX_VERSION */ 465 NULL, _POSIX_MONOTONIC_CLOCK, NULL, 0, 466 CTL_KERN, KERN_MONOTONIC_CLOCK, CTL_EOL); 467 sysctl_createv(SYSCTL_PERMANENT, 468 CTLTYPE_INT, "urandom", NULL, 469 sysctl_kern_urnd, 0, NULL, 0, 470 CTL_KERN, KERN_URND, CTL_EOL); 471 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 472 CTLTYPE_INT, "labelsector", NULL, 473 NULL, LABELSECTOR, NULL, 0, 474 CTL_KERN, KERN_LABELSECTOR, CTL_EOL); 475 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 476 CTLTYPE_INT, "labeloffset", NULL, 477 NULL, LABELOFFSET, NULL, 0, 478 CTL_KERN, KERN_LABELOFFSET, CTL_EOL); 479 sysctl_createv(SYSCTL_PERMANENT, 480 CTLTYPE_NODE, "lwp", NULL, 481 sysctl_kern_lwp, 0, NULL, 0, 482 CTL_KERN, KERN_LWP, CTL_EOL); 483 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 484 CTLTYPE_INT, "forkfsleep", NULL, 485 sysctl_kern_forkfsleep, 0, NULL, 0, 486 CTL_KERN, KERN_FORKFSLEEP, CTL_EOL); 487 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 488 CTLTYPE_INT, "posix_threads", NULL, 489 /* XXX _POSIX_VERSION */ 490 NULL, _POSIX_THREADS, NULL, 0, 491 CTL_KERN, KERN_POSIX_THREADS, CTL_EOL); 492 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 493 CTLTYPE_INT, "posix_semaphores", NULL, NULL, 494#ifdef P1003_1B_SEMAPHORE 495 200112, 496#else /* P1003_1B_SEMAPHORE */ 497 0, 498#endif /* P1003_1B_SEMAPHORE */ 499 NULL, 0, CTL_KERN, KERN_POSIX_SEMAPHORES, CTL_EOL); 500 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 501 CTLTYPE_INT, "posix_barriers", NULL, 502 /* XXX _POSIX_VERSION */ 503 NULL, _POSIX_BARRIERS, NULL, 0, 504 CTL_KERN, KERN_POSIX_BARRIERS, CTL_EOL); 505 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 506 CTLTYPE_INT, "posix_timers", NULL, 507 /* XXX _POSIX_VERSION */ 508 NULL, _POSIX_TIMERS, NULL, 0, 509 CTL_KERN, KERN_POSIX_TIMERS, CTL_EOL); 510 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 511 CTLTYPE_INT, "posix_spin_locks", NULL, 512 /* XXX _POSIX_VERSION */ 513 NULL, _POSIX_SPIN_LOCKS, NULL, 0, 514 CTL_KERN, KERN_POSIX_SPIN_LOCKS, CTL_EOL); 515 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 516 CTLTYPE_INT, "posix_reader_writer_locks", NULL, 517 /* XXX _POSIX_VERSION */ 518 NULL, _POSIX_READER_WRITER_LOCKS, NULL, 0, 519 CTL_KERN, KERN_POSIX_READER_WRITER_LOCKS, CTL_EOL); 520 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 521 CTLTYPE_INT, "dump_on_panic", NULL, 522 NULL, 0, &dumponpanic, 0, 523 CTL_KERN, KERN_DUMP_ON_PANIC, CTL_EOL); 524 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE, 525 CTLTYPE_INT, "somaxkva", NULL, 526 sysctl_kern_somaxkva, 0, NULL, 0, 527 CTL_KERN, KERN_SOMAXKVA, CTL_EOL); 528 sysctl_createv(SYSCTL_PERMANENT, 529 CTLTYPE_INT, "root_partition", NULL, 530 sysctl_kern_root_partition, 0, NULL, 0, 531 CTL_KERN, KERN_ROOT_PARTITION, CTL_EOL); 532 sysctl_createv(SYSCTL_PERMANENT, 533 CTLTYPE_STRUCT, "drivers", NULL, 534 sysctl_kern_drivers, 0, NULL, 0, 535 CTL_KERN, KERN_DRIVERS, CTL_EOL); 536} 537 538SYSCTL_SETUP(sysctl_kern_proc_setup, 539 "sysctl kern.proc/proc2/proc_args subtree setup") 540{ 541 542 sysctl_createv(SYSCTL_PERMANENT, 543 CTLTYPE_NODE, "kern", NULL, 544 NULL, 0, NULL, 0, 545 CTL_KERN, CTL_EOL); 546 547 sysctl_createv(SYSCTL_PERMANENT, 548 CTLTYPE_NODE, "proc", NULL, 549 sysctl_doeproc, 0, NULL, 0, 550 CTL_KERN, KERN_PROC, CTL_EOL); 551 sysctl_createv(SYSCTL_PERMANENT, 552 CTLTYPE_NODE, "proc2", NULL, 553 sysctl_doeproc, 0, NULL, 0, 554 CTL_KERN, KERN_PROC2, CTL_EOL); 555 sysctl_createv(SYSCTL_PERMANENT, 556 CTLTYPE_NODE, "proc_args", NULL, 557 sysctl_kern_proc_args, 0, NULL, 0, 558 CTL_KERN, KERN_PROC_ARGS, CTL_EOL); 559 560 /* 561 "nodes" under these: 562 563 KERN_PROC_ALL 564 KERN_PROC_PID pid 565 KERN_PROC_PGRP pgrp 566 KERN_PROC_SESSION sess 567 KERN_PROC_TTY tty 568 KERN_PROC_UID uid 569 KERN_PROC_RUID uid 570 KERN_PROC_GID gid 571 KERN_PROC_RGID gid 572 573 all in all, probably not worth the effort... 574 */ 575} 576 577SYSCTL_SETUP(sysctl_hw_setup, "sysctl hw subtree setup") 578{ 579 u_int u; 580 u_quad_t q; 581 582 sysctl_createv(SYSCTL_PERMANENT, 583 CTLTYPE_NODE, "hw", NULL, 584 NULL, 0, NULL, 0, 585 CTL_HW, CTL_EOL); 586 587 sysctl_createv(SYSCTL_PERMANENT, 588 CTLTYPE_STRING, "machine", NULL, 589 NULL, 0, machine, 0, 590 CTL_HW, HW_MACHINE, CTL_EOL); 591 sysctl_createv(SYSCTL_PERMANENT, 592 CTLTYPE_STRING, "model", NULL, 593 NULL, 0, cpu_model, 0, 594 CTL_HW, HW_MODEL, CTL_EOL); 595 sysctl_createv(SYSCTL_PERMANENT, 596 CTLTYPE_INT, "ncpu", NULL, 597 sysctl_hw_ncpu, 0, NULL, 0, 598 CTL_HW, HW_NCPU, CTL_EOL); 599 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 600 CTLTYPE_INT, "byteorder", NULL, 601 NULL, BYTE_ORDER, NULL, 0, 602 CTL_HW, HW_BYTEORDER, CTL_EOL); 603 u = ((u_int)physmem > (UINT_MAX / PAGE_SIZE)) ? 604 UINT_MAX : physmem * PAGE_SIZE; 605 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 606 CTLTYPE_INT, "physmem", NULL, 607 NULL, u, NULL, 0, 608 CTL_HW, HW_PHYSMEM, CTL_EOL); 609 sysctl_createv(SYSCTL_PERMANENT, 610 CTLTYPE_INT, "usermem", NULL, 611 sysctl_hw_usermem, 0, NULL, 0, 612 CTL_HW, HW_USERMEM, CTL_EOL); 613 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 614 CTLTYPE_INT, "pagesize", NULL, 615 NULL, PAGE_SIZE, NULL, 0, 616 CTL_HW, HW_PAGESIZE, CTL_EOL); 617 sysctl_createv(SYSCTL_PERMANENT, 618 CTLTYPE_STRING, "disknames", NULL, 619 sysctl_hw_disknames, 0, NULL, 0, 620 CTL_HW, HW_DISKNAMES, CTL_EOL); 621 sysctl_createv(SYSCTL_PERMANENT, 622 CTLTYPE_STRUCT, "diskstats", NULL, 623 sysctl_hw_diskstats, 0, NULL, 0, 624 CTL_HW, HW_DISKSTATS, CTL_EOL); 625 sysctl_createv(SYSCTL_PERMANENT, 626 CTLTYPE_STRING, "machine_arch", NULL, 627 NULL, 0, machine_arch, 0, 628 CTL_HW, HW_MACHINE_ARCH, CTL_EOL); 629 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 630 CTLTYPE_INT, "alignbytes", NULL, 631 NULL, ALIGNBYTES, NULL, 0, 632 CTL_HW, HW_ALIGNBYTES, CTL_EOL); 633 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_READWRITE|SYSCTL_HEX, 634 CTLTYPE_STRING, "cnmagic", NULL, 635 sysctl_hw_cnmagic, 0, NULL, CNS_LEN, 636 CTL_HW, HW_CNMAGIC, CTL_EOL); 637 q = (u_quad_t)physmem * PAGE_SIZE; 638 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_IMMEDIATE, 639 CTLTYPE_QUAD, "physmem64", NULL, 640 NULL, q, NULL, 0, 641 CTL_HW, HW_PHYSMEM64, CTL_EOL); 642 sysctl_createv(SYSCTL_PERMANENT, 643 CTLTYPE_QUAD, "usermem64", NULL, 644 sysctl_hw_usermem, 0, NULL, 0, 645 CTL_HW, HW_USERMEM64, CTL_EOL); 646} 647 648#ifdef DEBUG 649/* 650 * Debugging related system variables. 651 */ 652struct ctldebug /* debug0, */ /* debug1, */ debug2, debug3, debug4; 653struct ctldebug debug5, debug6, debug7, debug8, debug9; 654struct ctldebug debug10, debug11, debug12, debug13, debug14; 655struct ctldebug debug15, debug16, debug17, debug18, debug19; 656static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = { 657 &debug0, &debug1, &debug2, &debug3, &debug4, 658 &debug5, &debug6, &debug7, &debug8, &debug9, 659 &debug10, &debug11, &debug12, &debug13, &debug14, 660 &debug15, &debug16, &debug17, &debug18, &debug19, 661}; 662 663/* 664 * this setup routine is a replacement for debug_sysctl() 665 * 666 * note that it creates several nodes per defined debug variable 667 */ 668SYSCTL_SETUP(sysctl_debug_setup, "sysctl debug subtree setup") 669{ 670 struct ctldebug *cdp; 671 char nodename[20]; 672 int i; 673 674 /* 675 * two ways here: 676 * 677 * the "old" way (debug.name -> value) which was emulated by 678 * the sysctl(8) binary 679 * 680 * the new way, which the sysctl(8) binary was actually using 681 682 node debug 683 node debug.0 684 string debug.0.name 685 int debug.0.value 686 int debug.name 687 688 */ 689 690 sysctl_createv(SYSCTL_PERMANENT, 691 CTLTYPE_NODE, "debug", NULL, 692 NULL, 0, NULL, 0, 693 CTL_DEBUG, CTL_EOL); 694 695 for (i = 0; i < CTL_DEBUG_MAXID; i++) { 696 cdp = debugvars[i]; 697 if (cdp->debugname == NULL || cdp->debugvar == NULL) 698 continue; 699 700 snprintf(nodename, sizeof(nodename), "debug%d", i); 701 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_HIDDEN, 702 CTLTYPE_NODE, nodename, NULL, 703 NULL, 0, NULL, 0, 704 CTL_DEBUG, i, CTL_EOL); 705 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_HIDDEN, 706 CTLTYPE_STRING, "name", NULL, 707 NULL, 0, cdp->debugname, 0, 708 CTL_DEBUG, i, CTL_DEBUG_NAME, CTL_EOL); 709 sysctl_createv(SYSCTL_PERMANENT|SYSCTL_HIDDEN, 710 CTLTYPE_INT, "value", NULL, 711 NULL, 0, cdp->debugvar, 0, 712 CTL_DEBUG, i, CTL_DEBUG_VALUE, CTL_EOL); 713 sysctl_createv(SYSCTL_PERMANENT, 714 CTLTYPE_INT, cdp->debugname, NULL, 715 NULL, 0, cdp->debugvar, 0, 716 CTL_DEBUG, CTL_CREATE, CTL_EOL); 717 } 718} 719#endif /* DEBUG */ 720 721/* 722 * ******************************************************************** 723 * section 2: private node-specific helper routines. 724 * ******************************************************************** 725 */ 726 727/* 728 * sysctl helper routine for kern.maxvnodes. drain vnodes if 729 * new value is lower than desiredvnodes and then calls reinit 730 * routines that needs to adjust to the new value. 731 */ 732static int 733sysctl_kern_maxvnodes(SYSCTLFN_ARGS) 734{ 735 int error, new_vnodes, old_vnodes; 736 struct sysctlnode node; 737 738 new_vnodes = desiredvnodes; 739 node = *rnode; 740 node.sysctl_data = &new_vnodes; 741 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 742 if (error || newp == NULL) 743 return (error); 744 745 old_vnodes = desiredvnodes; 746 desiredvnodes = new_vnodes; 747 if (new_vnodes < old_vnodes) { 748 error = vfs_drainvnodes(new_vnodes, l->l_proc); 749 if (error) { 750 desiredvnodes = old_vnodes; 751 return (error); 752 } 753 } 754 vfs_reinit(); 755 nchreinit(); 756 757 return (0); 758} 759 760/* 761 * sysctl helper routine for rtc_offset - set time after changes 762 */ 763static int 764sysctl_kern_rtc_offset(SYSCTLFN_ARGS) 765{ 766 struct timeval tv, delta; 767 int s, error, new_rtc_offset; 768 struct sysctlnode node; 769 770 new_rtc_offset = rtc_offset; 771 node = *rnode; 772 node.sysctl_data = &new_rtc_offset; 773 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 774 if (error || newp == NULL) 775 return (error); 776 777 if (securelevel > 0) 778 return (EPERM); 779 if (rtc_offset == new_rtc_offset) 780 return (0); 781 782 /* if we change the offset, adjust the time */ 783 s = splclock(); 784 tv = time; 785 splx(s); 786 delta.tv_sec = 60*(new_rtc_offset - rtc_offset); 787 delta.tv_usec = 0; 788 timeradd(&tv, &delta, &tv); 789 rtc_offset = new_rtc_offset; 790 settime(&tv); 791 792 return (0); 793} 794 795/* 796 * sysctl helper routine for kern.maxvnodes. ensures that the new 797 * values are not too low or too high. 798 */ 799static int 800sysctl_kern_maxproc(SYSCTLFN_ARGS) 801{ 802 int error, nmaxproc; 803 struct sysctlnode node; 804 805 nmaxproc = maxproc; 806 node = *rnode; 807 node.sysctl_data = &nmaxproc; 808 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 809 if (error || newp == NULL) 810 return (error); 811 812 if (nmaxproc < 0 || nmaxproc >= PID_MAX) 813 return (EINVAL); 814#ifdef __HAVE_CPU_MAXPROC 815 if (nmaxproc > cpu_maxproc()) 816 return (EINVAL); 817#endif 818 maxproc = nmaxproc; 819 820 return (0); 821} 822 823/* 824 * sysctl helper routine for kern.securelevel. ensures that the value 825 * only rises unless the caller has pid 1 (assumed to be init). 826 */ 827static int 828sysctl_kern_securelevel(SYSCTLFN_ARGS) 829{ 830 int newsecurelevel, error; 831 struct sysctlnode node; 832 833 newsecurelevel = securelevel; 834 node = *rnode; 835 node.sysctl_data = &newsecurelevel; 836 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 837 if (error || newp == NULL) 838 return (error); 839 840 if (newsecurelevel < securelevel && l && l->l_proc->p_pid != 1) 841 return (EPERM); 842 securelevel = newsecurelevel; 843 844 return (error); 845} 846 847/* 848 * sysctl helper function for kern.hostid. the hostid is a long, but 849 * we export it as an int, so we need to give it a little help. 850 */ 851static int 852sysctl_kern_hostid(SYSCTLFN_ARGS) 853{ 854 int error, inthostid; 855 struct sysctlnode node; 856 857 inthostid = hostid; /* XXX assumes sizeof int >= sizeof long */ 858 node = *rnode; 859 node.sysctl_data = &inthostid; 860 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 861 if (error || newp == NULL) 862 return (error); 863 864 hostid = inthostid; 865 866 return (0); 867} 868 869/* 870 * sysctl helper function for kern.hostname and kern.domainnname. 871 * resets the relevant recorded length when the underlying name is 872 * changed. 873 */ 874static int 875sysctl_setlen(SYSCTLFN_ARGS) 876{ 877 int error; 878 879 error = sysctl_lookup(SYSCTLFN_CALL(rnode)); 880 if (error || newp == NULL) 881 return (error); 882 883 switch (rnode->sysctl_num) { 884 case KERN_HOSTNAME: 885 hostnamelen = strlen((const char*)rnode->sysctl_data); 886 break; 887 case KERN_DOMAINNAME: 888 domainnamelen = strlen((const char*)rnode->sysctl_data); 889 break; 890 } 891 892 return (0); 893} 894 895/* 896 * sysctl helper routine for kern.clockrate. assembles a struct on 897 * the fly to be returned to the caller. 898 */ 899static int 900sysctl_kern_clockrate(SYSCTLFN_ARGS) 901{ 902 struct clockinfo clkinfo; 903 struct sysctlnode node; 904 905 clkinfo.tick = tick; 906 clkinfo.tickadj = tickadj; 907 clkinfo.hz = hz; 908 clkinfo.profhz = profhz; 909 clkinfo.stathz = stathz ? stathz : hz; 910 911 node = *rnode; 912 node.sysctl_data = &clkinfo; 913 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 914} 915 916 917/* 918 * sysctl helper routine for kern.file pseudo-subtree. 919 */ 920static int 921sysctl_kern_file(SYSCTLFN_ARGS) 922{ 923 int error; 924 size_t buflen; 925 struct file *fp; 926 char *start, *where; 927 928 start = where = oldp; 929 buflen = *oldlenp; 930 if (where == NULL) { 931 /* 932 * overestimate by 10 files 933 */ 934 *oldlenp = sizeof(filehead) + (nfiles + 10) * sizeof(struct file); 935 return (0); 936 } 937 938 /* 939 * first copyout filehead 940 */ 941 if (buflen < sizeof(filehead)) { 942 *oldlenp = 0; 943 return (0); 944 } 945 error = copyout(&filehead, where, sizeof(filehead)); 946 if (error) 947 return (error); 948 buflen -= sizeof(filehead); 949 where += sizeof(filehead); 950 951 /* 952 * followed by an array of file structures 953 */ 954 LIST_FOREACH(fp, &filehead, f_list) { 955 if (buflen < sizeof(struct file)) { 956 *oldlenp = where - start; 957 return (ENOMEM); 958 } 959 error = copyout(fp, where, sizeof(struct file)); 960 if (error) 961 return (error); 962 buflen -= sizeof(struct file); 963 where += sizeof(struct file); 964 } 965 *oldlenp = where - start; 966 return (0); 967} 968 969/* 970 * sysctl helper routine for kern.autonicetime and kern.autoniceval. 971 * asserts that the assigned value is in the correct range. 972 */ 973static int 974sysctl_kern_autonice(SYSCTLFN_ARGS) 975{ 976 int error, t = 0; 977 struct sysctlnode node; 978 979 node = *rnode; 980 t = *(int*)node.sysctl_data; 981 node.sysctl_data = &t; 982 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 983 if (error || newp == NULL) 984 return (error); 985 986 switch (node.sysctl_num) { 987 case KERN_AUTONICETIME: 988 if (t >= 0) 989 autonicetime = t; 990 break; 991 case KERN_AUTONICEVAL: 992 if (t < PRIO_MIN) 993 t = PRIO_MIN; 994 else if (t > PRIO_MAX) 995 t = PRIO_MAX; 996 autoniceval = t; 997 break; 998 } 999 1000 return (0); 1001} 1002 1003/* 1004 * sysctl helper routine for kern.msgbufsize and kern.msgbuf. for the 1005 * former it merely checks the the message buffer is set up. for the 1006 * latter, it also copies out the data if necessary. 1007 */ 1008static int 1009sysctl_msgbuf(SYSCTLFN_ARGS) 1010{ 1011 char *where = oldp; 1012 size_t len, maxlen; 1013 long beg, end; 1014 int error; 1015 1016 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) { 1017 msgbufenabled = 0; 1018 return (ENXIO); 1019 } 1020 1021 switch (rnode->sysctl_num) { 1022 case KERN_MSGBUFSIZE: 1023 return (sysctl_lookup(SYSCTLFN_CALL(rnode))); 1024 case KERN_MSGBUF: 1025 break; 1026 default: 1027 return (EOPNOTSUPP); 1028 } 1029 1030 if (newp != NULL) 1031 return (EPERM); 1032 1033 if (oldp == NULL) { 1034 /* always return full buffer size */ 1035 *oldlenp = msgbufp->msg_bufs; 1036 return (0); 1037 } 1038 1039 error = 0; 1040 maxlen = MIN(msgbufp->msg_bufs, *oldlenp); 1041 1042 /* 1043 * First, copy from the write pointer to the end of 1044 * message buffer. 1045 */ 1046 beg = msgbufp->msg_bufx; 1047 end = msgbufp->msg_bufs; 1048 while (maxlen > 0) { 1049 len = MIN(end - beg, maxlen); 1050 if (len == 0) 1051 break; 1052 error = copyout(&msgbufp->msg_bufc[beg], where, len); 1053 if (error) 1054 break; 1055 where += len; 1056 maxlen -= len; 1057 1058 /* 1059 * ... then, copy from the beginning of message buffer to 1060 * the write pointer. 1061 */ 1062 beg = 0; 1063 end = msgbufp->msg_bufx; 1064 } 1065 1066 return (error); 1067} 1068 1069/* 1070 * sysctl helper routine for kern.defcorename. in the case of a new 1071 * string being assigned, check that it's not a zero-length string. 1072 * (XXX the check in -current doesn't work, but do we really care?) 1073 */ 1074static int 1075sysctl_kern_defcorename(SYSCTLFN_ARGS) 1076{ 1077 int error; 1078 char newcorename[MAXPATHLEN]; 1079 struct sysctlnode node; 1080 1081 node = *rnode; 1082 node.sysctl_data = &newcorename[0]; 1083 memcpy(node.sysctl_data, rnode->sysctl_data, MAXPATHLEN); 1084 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1085 if (error || newp == NULL) 1086 return (error); 1087 1088 /* 1089 * when sysctl_lookup() deals with a string, it's guaranteed 1090 * to come back nul terminated. so there. :) 1091 */ 1092 if (strlen(newcorename) == 0) 1093 return (EINVAL); 1094 1095 memcpy(rnode->sysctl_data, node.sysctl_data, MAXPATHLEN); 1096 1097 return (0); 1098} 1099 1100/* 1101 * sysctl helper routine for kern.cp_time node. adds up cpu time 1102 * across all cpus. 1103 */ 1104static int 1105sysctl_kern_cptime(SYSCTLFN_ARGS) 1106{ 1107 struct sysctlnode node = *rnode; 1108 1109#ifndef MULTIPROCESSOR 1110 1111 if (namelen == 1) { 1112 if (name[0] != 0) 1113 return (ENOENT); 1114 /* 1115 * you're allowed to ask for the zero'th processor 1116 */ 1117 name++; 1118 namelen--; 1119 } 1120 node.sysctl_data = curcpu()->ci_schedstate.spc_cp_time; 1121 node.sysctl_size = sizeof(curcpu()->ci_schedstate.spc_cp_time); 1122 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 1123 1124#else /* MULTIPROCESSOR */ 1125 1126 u_int64_t *cp_time = NULL; 1127 int error, n = sysctl_ncpus(), i; 1128 struct cpu_info *ci; 1129 CPU_INFO_ITERATOR cii; 1130 1131 /* 1132 * if you specifically pass a buffer that is the size of the 1133 * sum, or if you are probing for the size, you get the "sum" 1134 * of cp_time (and the size thereof) across all processors. 1135 * 1136 * alternately, you can pass an additional mib number and get 1137 * cp_time for that particular processor. 1138 */ 1139 switch (namelen) { 1140 case 0: 1141 if (*oldlenp == sizeof(u_int64_t) * CPUSTATES || oldp == NULL) { 1142 node.sysctl_size = sizeof(u_int64_t) * CPUSTATES; 1143 n = -1; /* SUM */ 1144 } 1145 else { 1146 node.sysctl_size = n * sizeof(u_int64_t) * CPUSTATES; 1147 n = -2; /* ALL */ 1148 } 1149 break; 1150 case 1: 1151 if (name[0] < 0 || name[0] >= n) 1152 return (ENOENT); /* ENOSUCHPROCESSOR */ 1153 node.sysctl_size = sizeof(u_int64_t) * CPUSTATES; 1154 n = name[0]; 1155 /* 1156 * adjust these so that sysctl_lookup() will be happy 1157 */ 1158 name++; 1159 namelen--; 1160 break; 1161 default: 1162 return (EINVAL); 1163 } 1164 1165 cp_time = malloc(node.sysctl_size, M_TEMP, M_WAITOK|M_CANFAIL); 1166 if (cp_time == NULL) 1167 return (ENOMEM); 1168 node.sysctl_data = cp_time; 1169 memset(cp_time, 0, node.sysctl_size); 1170 1171 for (CPU_INFO_FOREACH(cii, ci)) { 1172 if (n <= 0) 1173 for (i = 0; i < CPUSTATES; i++) 1174 cp_time[i] += ci->ci_schedstate.spc_cp_time[i]; 1175 /* 1176 * if a specific processor was requested and we just 1177 * did it, we're done here 1178 */ 1179 if (n == 0) 1180 break; 1181 /* 1182 * if doing "all", skip to next cp_time set for next processor 1183 */ 1184 if (n == -2) 1185 cp_time += CPUSTATES; 1186 /* 1187 * if we're doing a specific processor, we're one 1188 * processor closer 1189 */ 1190 if (n > 0) 1191 n--; 1192 } 1193 1194 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1195 free(node.sysctl_data, M_TEMP); 1196 return (error); 1197 1198#endif /* MULTIPROCESSOR */ 1199} 1200 1201#if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) 1202/* 1203 * sysctl helper routine for kern.sysvipc_info subtree. 1204 */ 1205 1206#define FILL_PERM(src, dst) do { \ 1207 (dst)._key = (src)._key; \ 1208 (dst).uid = (src).uid; \ 1209 (dst).gid = (src).gid; \ 1210 (dst).cuid = (src).cuid; \ 1211 (dst).cgid = (src).cgid; \ 1212 (dst).mode = (src).mode; \ 1213 (dst)._seq = (src)._seq; \ 1214} while (/*CONSTCOND*/ 0); 1215#define FILL_MSG(src, dst) do { \ 1216 FILL_PERM((src).msg_perm, (dst).msg_perm); \ 1217 (dst).msg_qnum = (src).msg_qnum; \ 1218 (dst).msg_qbytes = (src).msg_qbytes; \ 1219 (dst)._msg_cbytes = (src)._msg_cbytes; \ 1220 (dst).msg_lspid = (src).msg_lspid; \ 1221 (dst).msg_lrpid = (src).msg_lrpid; \ 1222 (dst).msg_stime = (src).msg_stime; \ 1223 (dst).msg_rtime = (src).msg_rtime; \ 1224 (dst).msg_ctime = (src).msg_ctime; \ 1225} while (/*CONSTCOND*/ 0) 1226#define FILL_SEM(src, dst) do { \ 1227 FILL_PERM((src).sem_perm, (dst).sem_perm); \ 1228 (dst).sem_nsems = (src).sem_nsems; \ 1229 (dst).sem_otime = (src).sem_otime; \ 1230 (dst).sem_ctime = (src).sem_ctime; \ 1231} while (/*CONSTCOND*/ 0) 1232#define FILL_SHM(src, dst) do { \ 1233 FILL_PERM((src).shm_perm, (dst).shm_perm); \ 1234 (dst).shm_segsz = (src).shm_segsz; \ 1235 (dst).shm_lpid = (src).shm_lpid; \ 1236 (dst).shm_cpid = (src).shm_cpid; \ 1237 (dst).shm_atime = (src).shm_atime; \ 1238 (dst).shm_dtime = (src).shm_dtime; \ 1239 (dst).shm_ctime = (src).shm_ctime; \ 1240 (dst).shm_nattch = (src).shm_nattch; \ 1241} while (/*CONSTCOND*/ 0) 1242 1243static int 1244sysctl_kern_sysvipc(SYSCTLFN_ARGS) 1245{ 1246 void *where = oldp; 1247 size_t *sizep = oldlenp; 1248#ifdef SYSVMSG 1249 struct msg_sysctl_info *msgsi = NULL; 1250#endif 1251#ifdef SYSVSEM 1252 struct sem_sysctl_info *semsi = NULL; 1253#endif 1254#ifdef SYSVSHM 1255 struct shm_sysctl_info *shmsi = NULL; 1256#endif 1257 size_t infosize, dssize, tsize, buflen; 1258 void *buf = NULL; 1259 char *start; 1260 int32_t nds; 1261 int i, error, ret; 1262 1263 if (namelen != 1) 1264 return (EINVAL); 1265 1266 start = where; 1267 buflen = *sizep; 1268 1269 switch (*name) { 1270 case KERN_SYSVIPC_MSG_INFO: 1271#ifdef SYSVMSG 1272 infosize = sizeof(msgsi->msginfo); 1273 nds = msginfo.msgmni; 1274 dssize = sizeof(msgsi->msgids[0]); 1275 break; 1276#else 1277 return (EINVAL); 1278#endif 1279 case KERN_SYSVIPC_SEM_INFO: 1280#ifdef SYSVSEM 1281 infosize = sizeof(semsi->seminfo); 1282 nds = seminfo.semmni; 1283 dssize = sizeof(semsi->semids[0]); 1284 break; 1285#else 1286 return (EINVAL); 1287#endif 1288 case KERN_SYSVIPC_SHM_INFO: 1289#ifdef SYSVSHM 1290 infosize = sizeof(shmsi->shminfo); 1291 nds = shminfo.shmmni; 1292 dssize = sizeof(shmsi->shmids[0]); 1293 break; 1294#else 1295 return (EINVAL); 1296#endif 1297 default: 1298 return (EINVAL); 1299 } 1300 /* 1301 * Round infosize to 64 bit boundary if requesting more than just 1302 * the info structure or getting the total data size. 1303 */ 1304 if (where == NULL || *sizep > infosize) 1305 infosize = ((infosize + 7) / 8) * 8; 1306 tsize = infosize + nds * dssize; 1307 1308 /* Return just the total size required. */ 1309 if (where == NULL) { 1310 *sizep = tsize; 1311 return (0); 1312 } 1313 1314 /* Not enough room for even the info struct. */ 1315 if (buflen < infosize) { 1316 *sizep = 0; 1317 return (ENOMEM); 1318 } 1319 buf = malloc(min(tsize, buflen), M_TEMP, M_WAITOK); 1320 memset(buf, 0, min(tsize, buflen)); 1321 1322 switch (*name) { 1323#ifdef SYSVMSG 1324 case KERN_SYSVIPC_MSG_INFO: 1325 msgsi = (struct msg_sysctl_info *)buf; 1326 msgsi->msginfo = msginfo; 1327 break; 1328#endif 1329#ifdef SYSVSEM 1330 case KERN_SYSVIPC_SEM_INFO: 1331 semsi = (struct sem_sysctl_info *)buf; 1332 semsi->seminfo = seminfo; 1333 break; 1334#endif 1335#ifdef SYSVSHM 1336 case KERN_SYSVIPC_SHM_INFO: 1337 shmsi = (struct shm_sysctl_info *)buf; 1338 shmsi->shminfo = shminfo; 1339 break; 1340#endif 1341 } 1342 buflen -= infosize; 1343 1344 ret = 0; 1345 if (buflen > 0) { 1346 /* Fill in the IPC data structures. */ 1347 for (i = 0; i < nds; i++) { 1348 if (buflen < dssize) { 1349 ret = ENOMEM; 1350 break; 1351 } 1352 switch (*name) { 1353#ifdef SYSVMSG 1354 case KERN_SYSVIPC_MSG_INFO: 1355 FILL_MSG(msqids[i], msgsi->msgids[i]); 1356 break; 1357#endif 1358#ifdef SYSVSEM 1359 case KERN_SYSVIPC_SEM_INFO: 1360 FILL_SEM(sema[i], semsi->semids[i]); 1361 break; 1362#endif 1363#ifdef SYSVSHM 1364 case KERN_SYSVIPC_SHM_INFO: 1365 FILL_SHM(shmsegs[i], shmsi->shmids[i]); 1366 break; 1367#endif 1368 } 1369 buflen -= dssize; 1370 } 1371 } 1372 *sizep -= buflen; 1373 error = copyout(buf, start, *sizep); 1374 /* If copyout succeeded, use return code set earlier. */ 1375 if (error == 0) 1376 error = ret; 1377 if (buf) 1378 free(buf, M_TEMP); 1379 return (error); 1380} 1381 1382#undef FILL_PERM 1383#undef FILL_MSG 1384#undef FILL_SEM 1385#undef FILL_SHM 1386 1387#endif /* defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM) */ 1388 1389#if NPTY > 0 1390/* 1391 * sysctl helper routine for kern.maxptys. ensures that any new value 1392 * is acceptable to the pty subsystem. 1393 */ 1394static int 1395sysctl_kern_maxptys(SYSCTLFN_ARGS) 1396{ 1397 int pty_maxptys(int, int); /* defined in kern/tty_pty.c */ 1398 int error, max; 1399 struct sysctlnode node; 1400 1401 /* get current value of maxptys */ 1402 max = pty_maxptys(0, 0); 1403 1404 node = *rnode; 1405 node.sysctl_data = &max; 1406 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1407 if (error || newp == NULL) 1408 return (error); 1409 1410 if (max != pty_maxptys(max, 1)) 1411 return (EINVAL); 1412 1413 return (0); 1414} 1415#endif /* NPTY > 0 */ 1416 1417/* 1418 * sysctl helper routine for kern.sbmax. basically just ensures that 1419 * any new value is not too small. 1420 */ 1421static int 1422sysctl_kern_sbmax(SYSCTLFN_ARGS) 1423{ 1424 int error, new_sbmax; 1425 struct sysctlnode node; 1426 1427 new_sbmax = sb_max; 1428 node = *rnode; 1429 node.sysctl_data = &new_sbmax; 1430 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1431 if (error || newp == NULL) 1432 return (error); 1433 1434 error = sb_max_set(new_sbmax); 1435 1436 return (error); 1437} 1438 1439/* 1440 * sysctl helper routine for kern.urandom node. picks a random number 1441 * for you. 1442 */ 1443static int 1444sysctl_kern_urnd(SYSCTLFN_ARGS) 1445{ 1446#if NRND > 0 1447 int v; 1448 1449 if (rnd_extract_data(&v, sizeof(v), RND_EXTRACT_ANY) == sizeof(v)) { 1450 struct sysctlnode node = *rnode; 1451 node.sysctl_data = &v; 1452 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 1453 } 1454 else 1455 return (EIO); /*XXX*/ 1456#else 1457 return (EOPNOTSUPP); 1458#endif 1459} 1460 1461/* 1462 * sysctl helper routine to do kern.lwp.* work. 1463 */ 1464static int 1465sysctl_kern_lwp(SYSCTLFN_ARGS) 1466{ 1467 struct kinfo_lwp klwp; 1468 struct proc *p; 1469 struct lwp *l2; 1470 char *where, *dp; 1471 int pid, elem_size, elem_count; 1472 int buflen, needed, error; 1473 1474 if (namelen == 1 && name[0] == CTL_QUERY) 1475 return (sysctl_query(SYSCTLFN_CALL(rnode))); 1476 1477 dp = where = oldp; 1478 buflen = where != NULL ? *oldlenp : 0; 1479 error = needed = 0; 1480 1481 if (newp != NULL || namelen != 3) 1482 return (EINVAL); 1483 pid = name[0]; 1484 elem_size = name[1]; 1485 elem_count = name[2]; 1486 1487 p = pfind(pid); 1488 if (p == NULL) 1489 return (ESRCH); 1490 LIST_FOREACH(l2, &p->p_lwps, l_sibling) { 1491 if (buflen >= elem_size && elem_count > 0) { 1492 fill_lwp(l2, &klwp); 1493 /* 1494 * Copy out elem_size, but not larger than 1495 * the size of a struct kinfo_proc2. 1496 */ 1497 error = copyout(&klwp, dp, 1498 min(sizeof(klwp), elem_size)); 1499 if (error) 1500 goto cleanup; 1501 dp += elem_size; 1502 buflen -= elem_size; 1503 elem_count--; 1504 } 1505 needed += elem_size; 1506 } 1507 1508 if (where != NULL) { 1509 *oldlenp = dp - where; 1510 if (needed > *oldlenp) 1511 return (ENOMEM); 1512 } else { 1513 needed += KERN_PROCSLOP; 1514 *oldlenp = needed; 1515 } 1516 return (0); 1517 cleanup: 1518 return (error); 1519} 1520 1521/* 1522 * sysctl helper routine for kern.forkfsleep node. ensures that the 1523 * given value is not too large or two small, and is at least one 1524 * timer tick if not zero. 1525 */ 1526static int 1527sysctl_kern_forkfsleep(SYSCTLFN_ARGS) 1528{ 1529 /* userland sees value in ms, internally is in ticks */ 1530 extern int forkfsleep; /* defined in kern/kern_fork.c */ 1531 int error, timo, lsleep; 1532 struct sysctlnode node; 1533 1534 lsleep = forkfsleep * 1000 / hz; 1535 node = *rnode; 1536 node.sysctl_data = &lsleep; 1537 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1538 if (error || newp == NULL) 1539 return (error); 1540 1541 /* refuse negative values, and overly 'long time' */ 1542 if (lsleep < 0 || lsleep > MAXSLP * 1000) 1543 return (EINVAL); 1544 1545 timo = mstohz(lsleep); 1546 1547 /* if the interval is >0 ms && <1 tick, use 1 tick */ 1548 if (lsleep != 0 && timo == 0) 1549 forkfsleep = 1; 1550 else 1551 forkfsleep = timo; 1552 1553 return (0); 1554} 1555 1556/* 1557 * sysctl helper routine for kern.somaxkva. ensures that the given 1558 * value is not too small. 1559 * (XXX should we maybe make sure it's not too large as well?) 1560 */ 1561static int 1562sysctl_kern_somaxkva(SYSCTLFN_ARGS) 1563{ 1564 int error, new_somaxkva; 1565 struct sysctlnode node; 1566 1567 new_somaxkva = somaxkva; 1568 node = *rnode; 1569 node.sysctl_data = &new_somaxkva; 1570 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 1571 if (error || newp == NULL) 1572 return (error); 1573 1574 if (new_somaxkva < (16 * 1024 * 1024)) /* sanity */ 1575 return (EINVAL); 1576 somaxkva = new_somaxkva; 1577 1578 return (error); 1579} 1580 1581/* 1582 * sysctl helper routine for kern.root_partition 1583 */ 1584static int 1585sysctl_kern_root_partition(SYSCTLFN_ARGS) 1586{ 1587 int rootpart = DISKPART(rootdev); 1588 struct sysctlnode node = *rnode; 1589 1590 node.sysctl_data = &rootpart; 1591 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 1592} 1593 1594/* 1595 * sysctl helper function for kern.drivers 1596 */ 1597static int 1598sysctl_kern_drivers(SYSCTLFN_ARGS) 1599{ 1600 int error; 1601 size_t buflen; 1602 struct kinfo_drivers kd; 1603 char *start, *where; 1604 const char *dname; 1605 int i; 1606 extern struct devsw_conv *devsw_conv; 1607 extern int max_devsw_convs; 1608 1609 if (newp != NULL || namelen != 0) 1610 return (EINVAL); 1611 1612 start = where = oldp; 1613 buflen = *oldlenp; 1614 if (where == NULL) { 1615 *oldlenp = max_devsw_convs * sizeof kd; 1616 return 0; 1617 } 1618 1619 /* 1620 * An array of kinfo_drivers structures 1621 */ 1622 error = 0; 1623 for (i = 0; i < max_devsw_convs; i++) { 1624 dname = devsw_conv[i].d_name; 1625 if (dname == NULL) 1626 continue; 1627 if (buflen < sizeof kd) { 1628 error = ENOMEM; 1629 break; 1630 } 1631 kd.d_bmajor = devsw_conv[i].d_bmajor; 1632 kd.d_cmajor = devsw_conv[i].d_cmajor; 1633 strlcpy(kd.d_name, dname, sizeof kd.d_name); 1634 error = copyout(&kd, where, sizeof kd); 1635 if (error != 0) 1636 break; 1637 buflen -= sizeof kd; 1638 where += sizeof kd; 1639 } 1640 *oldlenp = where - start; 1641 return error; 1642} 1643 1644static int 1645sysctl_doeproc(SYSCTLFN_ARGS) 1646{ 1647 struct eproc eproc; 1648 struct kinfo_proc2 kproc2; 1649 struct kinfo_proc *dp; 1650 struct proc *p; 1651 const struct proclist_desc *pd; 1652 char *where, *dp2; 1653 int type, op, arg; 1654 u_int elem_size, elem_count; 1655 size_t buflen, needed; 1656 int error; 1657 1658 if (namelen == 1 && name[0] == CTL_QUERY) 1659 return (sysctl_query(SYSCTLFN_CALL(rnode))); 1660 1661 dp = oldp; 1662 dp2 = where = oldp; 1663 buflen = where != NULL ? *oldlenp : 0; 1664 error = 0; 1665 needed = 0; 1666 type = rnode->sysctl_num; 1667 1668 if (type == KERN_PROC) { 1669 if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL)) 1670 return (EINVAL); 1671 op = name[0]; 1672 if (op != KERN_PROC_ALL) 1673 arg = name[1]; 1674 else 1675 arg = 0; /* Quell compiler warning */ 1676 elem_size = elem_count = 0; /* Ditto */ 1677 } else { 1678 if (namelen != 4) 1679 return (EINVAL); 1680 op = name[0]; 1681 arg = name[1]; 1682 elem_size = name[2]; 1683 elem_count = name[3]; 1684 } 1685 1686 proclist_lock_read(); 1687 1688 pd = proclists; 1689again: 1690 for (p = LIST_FIRST(pd->pd_list); p != NULL; p = LIST_NEXT(p, p_list)) { 1691 /* 1692 * Skip embryonic processes. 1693 */ 1694 if (p->p_stat == SIDL) 1695 continue; 1696 /* 1697 * TODO - make more efficient (see notes below). 1698 * do by session. 1699 */ 1700 switch (op) { 1701 1702 case KERN_PROC_PID: 1703 /* could do this with just a lookup */ 1704 if (p->p_pid != (pid_t)arg) 1705 continue; 1706 break; 1707 1708 case KERN_PROC_PGRP: 1709 /* could do this by traversing pgrp */ 1710 if (p->p_pgrp->pg_id != (pid_t)arg) 1711 continue; 1712 break; 1713 1714 case KERN_PROC_SESSION: 1715 if (p->p_session->s_sid != (pid_t)arg) 1716 continue; 1717 break; 1718 1719 case KERN_PROC_TTY: 1720 if (arg == (int) KERN_PROC_TTY_REVOKE) { 1721 if ((p->p_flag & P_CONTROLT) == 0 || 1722 p->p_session->s_ttyp == NULL || 1723 p->p_session->s_ttyvp != NULL) 1724 continue; 1725 } else if ((p->p_flag & P_CONTROLT) == 0 || 1726 p->p_session->s_ttyp == NULL) { 1727 if ((dev_t)arg != KERN_PROC_TTY_NODEV) 1728 continue; 1729 } else if (p->p_session->s_ttyp->t_dev != (dev_t)arg) 1730 continue; 1731 break; 1732 1733 case KERN_PROC_UID: 1734 if (p->p_ucred->cr_uid != (uid_t)arg) 1735 continue; 1736 break; 1737 1738 case KERN_PROC_RUID: 1739 if (p->p_cred->p_ruid != (uid_t)arg) 1740 continue; 1741 break; 1742 1743 case KERN_PROC_GID: 1744 if (p->p_ucred->cr_gid != (uid_t)arg) 1745 continue; 1746 break; 1747 1748 case KERN_PROC_RGID: 1749 if (p->p_cred->p_rgid != (uid_t)arg) 1750 continue; 1751 break; 1752 1753 case KERN_PROC_ALL: 1754 /* allow everything */ 1755 break; 1756 1757 default: 1758 error = EINVAL; 1759 goto cleanup; 1760 } 1761 if (type == KERN_PROC) { 1762 if (buflen >= sizeof(struct kinfo_proc)) { 1763 fill_eproc(p, &eproc); 1764 error = copyout(p, &dp->kp_proc, 1765 sizeof(struct proc)); 1766 if (error) 1767 goto cleanup; 1768 error = copyout(&eproc, &dp->kp_eproc, 1769 sizeof(eproc)); 1770 if (error) 1771 goto cleanup; 1772 dp++; 1773 buflen -= sizeof(struct kinfo_proc); 1774 } 1775 needed += sizeof(struct kinfo_proc); 1776 } else { /* KERN_PROC2 */ 1777 if (buflen >= elem_size && elem_count > 0) { 1778 fill_kproc2(p, &kproc2); 1779 /* 1780 * Copy out elem_size, but not larger than 1781 * the size of a struct kinfo_proc2. 1782 */ 1783 error = copyout(&kproc2, dp2, 1784 min(sizeof(kproc2), elem_size)); 1785 if (error) 1786 goto cleanup; 1787 dp2 += elem_size; 1788 buflen -= elem_size; 1789 elem_count--; 1790 } 1791 needed += elem_size; 1792 } 1793 } 1794 pd++; 1795 if (pd->pd_list != NULL) 1796 goto again; 1797 proclist_unlock_read(); 1798 1799 if (where != NULL) { 1800 if (type == KERN_PROC) 1801 *oldlenp = (char *)dp - where; 1802 else 1803 *oldlenp = dp2 - where; 1804 if (needed > *oldlenp) 1805 return (ENOMEM); 1806 } else { 1807 needed += KERN_LWPSLOP; 1808 *oldlenp = needed; 1809 } 1810 return (0); 1811 cleanup: 1812 proclist_unlock_read(); 1813 return (error); 1814} 1815 1816/* 1817 * sysctl helper routine for kern.proc_args pseudo-subtree. 1818 */ 1819static int 1820sysctl_kern_proc_args(SYSCTLFN_ARGS) 1821{ 1822 struct ps_strings pss; 1823 struct proc *p, *up = l->l_proc; 1824 size_t len, upper_bound, xlen, i; 1825 struct uio auio; 1826 struct iovec aiov; 1827 vaddr_t argv; 1828 pid_t pid; 1829 int nargv, type, error; 1830 char *arg; 1831 char *tmp; 1832 1833 if (namelen == 1 && name[0] == CTL_QUERY) 1834 return (sysctl_query(SYSCTLFN_CALL(rnode))); 1835 1836 if (newp != NULL || namelen != 2) 1837 return (EINVAL); 1838 pid = name[0]; 1839 type = name[1]; 1840 1841 switch (type) { 1842 case KERN_PROC_ARGV: 1843 case KERN_PROC_NARGV: 1844 case KERN_PROC_ENV: 1845 case KERN_PROC_NENV: 1846 /* ok */ 1847 break; 1848 default: 1849 return (EINVAL); 1850 } 1851 1852 /* check pid */ 1853 if ((p = pfind(pid)) == NULL) 1854 return (EINVAL); 1855 1856 /* only root or same user change look at the environment */ 1857 if (type == KERN_PROC_ENV || type == KERN_PROC_NENV) { 1858 if (up->p_ucred->cr_uid != 0) { 1859 if (up->p_cred->p_ruid != p->p_cred->p_ruid || 1860 up->p_cred->p_ruid != p->p_cred->p_svuid) 1861 return (EPERM); 1862 } 1863 } 1864 1865 if (oldp == NULL) { 1866 if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV) 1867 *oldlenp = sizeof (int); 1868 else 1869 *oldlenp = ARG_MAX; /* XXX XXX XXX */ 1870 return (0); 1871 } 1872 1873 /* 1874 * Zombies don't have a stack, so we can't read their psstrings. 1875 * System processes also don't have a user stack. 1876 */ 1877 if (P_ZOMBIE(p) || (p->p_flag & P_SYSTEM) != 0) 1878 return (EINVAL); 1879 1880 /* 1881 * Lock the process down in memory. 1882 */ 1883 /* XXXCDC: how should locking work here? */ 1884 if ((p->p_flag & P_WEXIT) || (p->p_vmspace->vm_refcnt < 1)) 1885 return (EFAULT); 1886 1887 p->p_vmspace->vm_refcnt++; /* XXX */ 1888 1889 /* 1890 * Allocate a temporary buffer to hold the arguments. 1891 */ 1892 arg = malloc(PAGE_SIZE, M_TEMP, M_WAITOK); 1893 1894 /* 1895 * Read in the ps_strings structure. 1896 */ 1897 aiov.iov_base = &pss; 1898 aiov.iov_len = sizeof(pss); 1899 auio.uio_iov = &aiov; 1900 auio.uio_iovcnt = 1; 1901 auio.uio_offset = (vaddr_t)p->p_psstr; 1902 auio.uio_resid = sizeof(pss); 1903 auio.uio_segflg = UIO_SYSSPACE; 1904 auio.uio_rw = UIO_READ; 1905 auio.uio_procp = NULL; 1906 error = uvm_io(&p->p_vmspace->vm_map, &auio); 1907 if (error) 1908 goto done; 1909 1910 if (type == KERN_PROC_ARGV || type == KERN_PROC_NARGV) 1911 memcpy(&nargv, (char *)&pss + p->p_psnargv, sizeof(nargv)); 1912 else 1913 memcpy(&nargv, (char *)&pss + p->p_psnenv, sizeof(nargv)); 1914 if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV) { 1915 error = copyout(&nargv, oldp, sizeof(nargv)); 1916 *oldlenp = sizeof(nargv); 1917 goto done; 1918 } 1919 /* 1920 * Now read the address of the argument vector. 1921 */ 1922 switch (type) { 1923 case KERN_PROC_ARGV: 1924 /* XXX compat32 stuff here */ 1925 memcpy(&tmp, (char *)&pss + p->p_psargv, sizeof(tmp)); 1926 break; 1927 case KERN_PROC_ENV: 1928 memcpy(&tmp, (char *)&pss + p->p_psenv, sizeof(tmp)); 1929 break; 1930 default: 1931 return (EINVAL); 1932 } 1933 auio.uio_offset = (off_t)(long)tmp; 1934 aiov.iov_base = &argv; 1935 aiov.iov_len = sizeof(argv); 1936 auio.uio_iov = &aiov; 1937 auio.uio_iovcnt = 1; 1938 auio.uio_resid = sizeof(argv); 1939 auio.uio_segflg = UIO_SYSSPACE; 1940 auio.uio_rw = UIO_READ; 1941 auio.uio_procp = NULL; 1942 error = uvm_io(&p->p_vmspace->vm_map, &auio); 1943 if (error) 1944 goto done; 1945 1946 /* 1947 * Now copy in the actual argument vector, one page at a time, 1948 * since we don't know how long the vector is (though, we do 1949 * know how many NUL-terminated strings are in the vector). 1950 */ 1951 len = 0; 1952 upper_bound = *oldlenp; 1953 for (; nargv != 0 && len < upper_bound; len += xlen) { 1954 aiov.iov_base = arg; 1955 aiov.iov_len = PAGE_SIZE; 1956 auio.uio_iov = &aiov; 1957 auio.uio_iovcnt = 1; 1958 auio.uio_offset = argv + len; 1959 xlen = PAGE_SIZE - ((argv + len) & PAGE_MASK); 1960 auio.uio_resid = xlen; 1961 auio.uio_segflg = UIO_SYSSPACE; 1962 auio.uio_rw = UIO_READ; 1963 auio.uio_procp = NULL; 1964 error = uvm_io(&p->p_vmspace->vm_map, &auio); 1965 if (error) 1966 goto done; 1967 1968 for (i = 0; i < xlen && nargv != 0; i++) { 1969 if (arg[i] == '\0') 1970 nargv--; /* one full string */ 1971 } 1972 1973 /* 1974 * Make sure we don't copyout past the end of the user's 1975 * buffer. 1976 */ 1977 if (len + i > upper_bound) 1978 i = upper_bound - len; 1979 1980 error = copyout(arg, (char *)oldp + len, i); 1981 if (error) 1982 break; 1983 1984 if (nargv == 0) { 1985 len += i; 1986 break; 1987 } 1988 } 1989 *oldlenp = len; 1990 1991done: 1992 uvmspace_free(p->p_vmspace); 1993 1994 free(arg, M_TEMP); 1995 return (error); 1996} 1997 1998/* 1999 * sysctl helper routine for hw.usermem and hw.usermem64. values are 2000 * calculate on the fly taking into account integer overflow and the 2001 * current wired count. 2002 */ 2003static int 2004sysctl_hw_usermem(SYSCTLFN_ARGS) 2005{ 2006 u_int ui; 2007 u_quad_t uq; 2008 struct sysctlnode node; 2009 2010 node = *rnode; 2011 switch (rnode->sysctl_num) { 2012 case HW_USERMEM: 2013 if ((ui = physmem - uvmexp.wired) > (UINT_MAX / PAGE_SIZE)) 2014 ui = UINT_MAX; 2015 else 2016 ui *= PAGE_SIZE; 2017 node.sysctl_data = &ui; 2018 break; 2019 case HW_USERMEM64: 2020 uq = (u_quad_t)(physmem - uvmexp.wired) * PAGE_SIZE; 2021 node.sysctl_data = &uq; 2022 break; 2023 default: 2024 return (EINVAL); 2025 } 2026 2027 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 2028} 2029 2030/* 2031 * sysctl helper routine for kern.cnmagic node. pulls the old value 2032 * out, encoded, and stuffs the new value in for decoding. 2033 */ 2034static int 2035sysctl_hw_cnmagic(SYSCTLFN_ARGS) 2036{ 2037 char magic[CNS_LEN]; 2038 int error; 2039 struct sysctlnode node; 2040 2041 if (oldp) 2042 cn_get_magic(magic, CNS_LEN); 2043 node = *rnode; 2044 node.sysctl_data = &magic[0]; 2045 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 2046 if (error || newp == NULL) 2047 return (error); 2048 2049 return (cn_set_magic(magic)); 2050} 2051 2052static int 2053sysctl_hw_ncpu(SYSCTLFN_ARGS) 2054{ 2055 int ncpu; 2056 struct sysctlnode node; 2057 2058 ncpu = sysctl_ncpus(); 2059 node = *rnode; 2060 node.sysctl_data = &ncpu; 2061 2062 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 2063} 2064 2065 2066/* 2067 * ******************************************************************** 2068 * section 3: public helper routines that are used for more than one 2069 * node 2070 * ******************************************************************** 2071 */ 2072 2073/* 2074 * sysctl helper routine for the kern.root_device node and some ports' 2075 * machdep.root_device nodes. 2076 */ 2077int 2078sysctl_root_device(SYSCTLFN_ARGS) 2079{ 2080 struct sysctlnode node; 2081 2082 node = *rnode; 2083 node.sysctl_data = root_device->dv_xname; 2084 node.sysctl_size = strlen(root_device->dv_xname) + 1; 2085 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 2086} 2087 2088/* 2089 * sysctl helper routine for kern.consdev, dependent on the current 2090 * state of the console. also used for machdep.console_device on some 2091 * ports. 2092 */ 2093int 2094sysctl_consdev(SYSCTLFN_ARGS) 2095{ 2096 dev_t consdev; 2097 struct sysctlnode node; 2098 2099 if (cn_tab != NULL) 2100 consdev = cn_tab->cn_dev; 2101 else 2102 consdev = NODEV; 2103 node = *rnode; 2104 node.sysctl_data = &consdev; 2105 node.sysctl_size = sizeof(consdev); 2106 return (sysctl_lookup(SYSCTLFN_CALL(&node))); 2107} 2108 2109/* 2110 * ******************************************************************** 2111 * section 4: support for some helpers 2112 * ******************************************************************** 2113 */ 2114 2115/* 2116 * Fill in a kinfo_proc2 structure for the specified process. 2117 */ 2118static void 2119fill_kproc2(struct proc *p, struct kinfo_proc2 *ki) 2120{ 2121 struct tty *tp; 2122 struct lwp *l; 2123 struct timeval ut, st; 2124 2125 memset(ki, 0, sizeof(*ki)); 2126 2127 ki->p_paddr = PTRTOINT64(p); 2128 ki->p_fd = PTRTOINT64(p->p_fd); 2129 ki->p_cwdi = PTRTOINT64(p->p_cwdi); 2130 ki->p_stats = PTRTOINT64(p->p_stats); 2131 ki->p_limit = PTRTOINT64(p->p_limit); 2132 ki->p_vmspace = PTRTOINT64(p->p_vmspace); 2133 ki->p_sigacts = PTRTOINT64(p->p_sigacts); 2134 ki->p_sess = PTRTOINT64(p->p_session); 2135 ki->p_tsess = 0; /* may be changed if controlling tty below */ 2136 ki->p_ru = PTRTOINT64(p->p_ru); 2137 2138 ki->p_eflag = 0; 2139 ki->p_exitsig = p->p_exitsig; 2140 ki->p_flag = p->p_flag; 2141 2142 ki->p_pid = p->p_pid; 2143 if (p->p_pptr) 2144 ki->p_ppid = p->p_pptr->p_pid; 2145 else 2146 ki->p_ppid = 0; 2147 ki->p_sid = p->p_session->s_sid; 2148 ki->p__pgid = p->p_pgrp->pg_id; 2149 2150 ki->p_tpgid = NO_PGID; /* may be changed if controlling tty below */ 2151 2152 ki->p_uid = p->p_ucred->cr_uid; 2153 ki->p_ruid = p->p_cred->p_ruid; 2154 ki->p_gid = p->p_ucred->cr_gid; 2155 ki->p_rgid = p->p_cred->p_rgid; 2156 ki->p_svuid = p->p_cred->p_svuid; 2157 ki->p_svgid = p->p_cred->p_svgid; 2158 2159 memcpy(ki->p_groups, p->p_cred->pc_ucred->cr_groups, 2160 min(sizeof(ki->p_groups), sizeof(p->p_cred->pc_ucred->cr_groups))); 2161 ki->p_ngroups = p->p_cred->pc_ucred->cr_ngroups; 2162 2163 ki->p_jobc = p->p_pgrp->pg_jobc; 2164 if ((p->p_flag & P_CONTROLT) && (tp = p->p_session->s_ttyp)) { 2165 ki->p_tdev = tp->t_dev; 2166 ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID; 2167 ki->p_tsess = PTRTOINT64(tp->t_session); 2168 } else { 2169 ki->p_tdev = NODEV; 2170 } 2171 2172 ki->p_estcpu = p->p_estcpu; 2173 ki->p_rtime_sec = p->p_rtime.tv_sec; 2174 ki->p_rtime_usec = p->p_rtime.tv_usec; 2175 ki->p_cpticks = p->p_cpticks; 2176 ki->p_pctcpu = p->p_pctcpu; 2177 2178 ki->p_uticks = p->p_uticks; 2179 ki->p_sticks = p->p_sticks; 2180 ki->p_iticks = p->p_iticks; 2181 2182 ki->p_tracep = PTRTOINT64(p->p_tracep); 2183 ki->p_traceflag = p->p_traceflag; 2184 2185 2186 memcpy(&ki->p_siglist, &p->p_sigctx.ps_siglist, sizeof(ki_sigset_t)); 2187 memcpy(&ki->p_sigmask, &p->p_sigctx.ps_sigmask, sizeof(ki_sigset_t)); 2188 memcpy(&ki->p_sigignore, &p->p_sigctx.ps_sigignore,sizeof(ki_sigset_t)); 2189 memcpy(&ki->p_sigcatch, &p->p_sigctx.ps_sigcatch, sizeof(ki_sigset_t)); 2190 2191 ki->p_stat = p->p_stat; /* Will likely be overridden by LWP status */ 2192 ki->p_realstat = p->p_stat; 2193 ki->p_nice = p->p_nice; 2194 2195 ki->p_xstat = p->p_xstat; 2196 ki->p_acflag = p->p_acflag; 2197 2198 strncpy(ki->p_comm, p->p_comm, 2199 min(sizeof(ki->p_comm), sizeof(p->p_comm))); 2200 2201 strncpy(ki->p_login, p->p_session->s_login, 2202 min(sizeof ki->p_login - 1, sizeof p->p_session->s_login)); 2203 2204 ki->p_nlwps = p->p_nlwps; 2205 ki->p_nrlwps = p->p_nrlwps; 2206 ki->p_realflag = p->p_flag; 2207 2208 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 2209 ki->p_vm_rssize = 0; 2210 ki->p_vm_tsize = 0; 2211 ki->p_vm_dsize = 0; 2212 ki->p_vm_ssize = 0; 2213 l = NULL; 2214 } else { 2215 struct vmspace *vm = p->p_vmspace; 2216 2217 ki->p_vm_rssize = vm_resident_count(vm); 2218 ki->p_vm_tsize = vm->vm_tsize; 2219 ki->p_vm_dsize = vm->vm_dsize; 2220 ki->p_vm_ssize = vm->vm_ssize; 2221 2222 /* Pick a "representative" LWP */ 2223 l = proc_representative_lwp(p); 2224 ki->p_forw = PTRTOINT64(l->l_forw); 2225 ki->p_back = PTRTOINT64(l->l_back); 2226 ki->p_addr = PTRTOINT64(l->l_addr); 2227 ki->p_stat = l->l_stat; 2228 ki->p_flag |= l->l_flag; 2229 ki->p_swtime = l->l_swtime; 2230 ki->p_slptime = l->l_slptime; 2231 if (l->l_stat == LSONPROC) { 2232 KDASSERT(l->l_cpu != NULL); 2233 ki->p_schedflags = l->l_cpu->ci_schedstate.spc_flags; 2234 } else 2235 ki->p_schedflags = 0; 2236 ki->p_holdcnt = l->l_holdcnt; 2237 ki->p_priority = l->l_priority; 2238 ki->p_usrpri = l->l_usrpri; 2239 if (l->l_wmesg) 2240 strncpy(ki->p_wmesg, l->l_wmesg, sizeof(ki->p_wmesg)); 2241 ki->p_wchan = PTRTOINT64(l->l_wchan); 2242 2243 } 2244 2245 if (p->p_session->s_ttyvp) 2246 ki->p_eflag |= EPROC_CTTY; 2247 if (SESS_LEADER(p)) 2248 ki->p_eflag |= EPROC_SLEADER; 2249 2250 /* XXX Is this double check necessary? */ 2251 if (P_ZOMBIE(p)) { 2252 ki->p_uvalid = 0; 2253 } else { 2254 ki->p_uvalid = 1; 2255 2256 ki->p_ustart_sec = p->p_stats->p_start.tv_sec; 2257 ki->p_ustart_usec = p->p_stats->p_start.tv_usec; 2258 2259 calcru(p, &ut, &st, 0); 2260 ki->p_uutime_sec = ut.tv_sec; 2261 ki->p_uutime_usec = ut.tv_usec; 2262 ki->p_ustime_sec = st.tv_sec; 2263 ki->p_ustime_usec = st.tv_usec; 2264 2265 ki->p_uru_maxrss = p->p_stats->p_ru.ru_maxrss; 2266 ki->p_uru_ixrss = p->p_stats->p_ru.ru_ixrss; 2267 ki->p_uru_idrss = p->p_stats->p_ru.ru_idrss; 2268 ki->p_uru_isrss = p->p_stats->p_ru.ru_isrss; 2269 ki->p_uru_minflt = p->p_stats->p_ru.ru_minflt; 2270 ki->p_uru_majflt = p->p_stats->p_ru.ru_majflt; 2271 ki->p_uru_nswap = p->p_stats->p_ru.ru_nswap; 2272 ki->p_uru_inblock = p->p_stats->p_ru.ru_inblock; 2273 ki->p_uru_oublock = p->p_stats->p_ru.ru_oublock; 2274 ki->p_uru_msgsnd = p->p_stats->p_ru.ru_msgsnd; 2275 ki->p_uru_msgrcv = p->p_stats->p_ru.ru_msgrcv; 2276 ki->p_uru_nsignals = p->p_stats->p_ru.ru_nsignals; 2277 ki->p_uru_nvcsw = p->p_stats->p_ru.ru_nvcsw; 2278 ki->p_uru_nivcsw = p->p_stats->p_ru.ru_nivcsw; 2279 2280 timeradd(&p->p_stats->p_cru.ru_utime, 2281 &p->p_stats->p_cru.ru_stime, &ut); 2282 ki->p_uctime_sec = ut.tv_sec; 2283 ki->p_uctime_usec = ut.tv_usec; 2284 } 2285#ifdef MULTIPROCESSOR 2286 if (l && l->l_cpu != NULL) 2287 ki->p_cpuid = l->l_cpu->ci_cpuid; 2288 else 2289#endif 2290 ki->p_cpuid = KI_NOCPU; 2291} 2292 2293/* 2294 * Fill in a kinfo_lwp structure for the specified lwp. 2295 */ 2296static void 2297fill_lwp(struct lwp *l, struct kinfo_lwp *kl) 2298{ 2299 2300 kl->l_forw = PTRTOINT64(l->l_forw); 2301 kl->l_back = PTRTOINT64(l->l_back); 2302 kl->l_laddr = PTRTOINT64(l); 2303 kl->l_addr = PTRTOINT64(l->l_addr); 2304 kl->l_stat = l->l_stat; 2305 kl->l_lid = l->l_lid; 2306 kl->l_flag = l->l_flag; 2307 2308 kl->l_swtime = l->l_swtime; 2309 kl->l_slptime = l->l_slptime; 2310 if (l->l_stat == LSONPROC) { 2311 KDASSERT(l->l_cpu != NULL); 2312 kl->l_schedflags = l->l_cpu->ci_schedstate.spc_flags; 2313 } else 2314 kl->l_schedflags = 0; 2315 kl->l_holdcnt = l->l_holdcnt; 2316 kl->l_priority = l->l_priority; 2317 kl->l_usrpri = l->l_usrpri; 2318 if (l->l_wmesg) 2319 strncpy(kl->l_wmesg, l->l_wmesg, sizeof(kl->l_wmesg)); 2320 kl->l_wchan = PTRTOINT64(l->l_wchan); 2321#ifdef MULTIPROCESSOR 2322 if (l->l_cpu != NULL) 2323 kl->l_cpuid = l->l_cpu->ci_cpuid; 2324 else 2325#endif 2326 kl->l_cpuid = KI_NOCPU; 2327} 2328 2329/* 2330 * Fill in an eproc structure for the specified process. 2331 */ 2332void 2333fill_eproc(struct proc *p, struct eproc *ep) 2334{ 2335 struct tty *tp; 2336 struct lwp *l; 2337 2338 ep->e_paddr = p; 2339 ep->e_sess = p->p_session; 2340 ep->e_pcred = *p->p_cred; 2341 ep->e_ucred = *p->p_ucred; 2342 if (p->p_stat == SIDL || P_ZOMBIE(p)) { 2343 ep->e_vm.vm_rssize = 0; 2344 ep->e_vm.vm_tsize = 0; 2345 ep->e_vm.vm_dsize = 0; 2346 ep->e_vm.vm_ssize = 0; 2347 /* ep->e_vm.vm_pmap = XXX; */ 2348 } else { 2349 struct vmspace *vm = p->p_vmspace; 2350 2351 ep->e_vm.vm_rssize = vm_resident_count(vm); 2352 ep->e_vm.vm_tsize = vm->vm_tsize; 2353 ep->e_vm.vm_dsize = vm->vm_dsize; 2354 ep->e_vm.vm_ssize = vm->vm_ssize; 2355 2356 /* Pick a "representative" LWP */ 2357 l = proc_representative_lwp(p); 2358 2359 if (l->l_wmesg) 2360 strncpy(ep->e_wmesg, l->l_wmesg, WMESGLEN); 2361 } 2362 if (p->p_pptr) 2363 ep->e_ppid = p->p_pptr->p_pid; 2364 else 2365 ep->e_ppid = 0; 2366 ep->e_pgid = p->p_pgrp->pg_id; 2367 ep->e_sid = ep->e_sess->s_sid; 2368 ep->e_jobc = p->p_pgrp->pg_jobc; 2369 if ((p->p_flag & P_CONTROLT) && 2370 (tp = ep->e_sess->s_ttyp)) { 2371 ep->e_tdev = tp->t_dev; 2372 ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID; 2373 ep->e_tsess = tp->t_session; 2374 } else 2375 ep->e_tdev = NODEV; 2376 2377 ep->e_xsize = ep->e_xrssize = 0; 2378 ep->e_xccount = ep->e_xswrss = 0; 2379 ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0; 2380 if (SESS_LEADER(p)) 2381 ep->e_flag |= EPROC_SLEADER; 2382 strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME); 2383} 2384