1998-08-03 18:38:20 +04:00
|
|
|
/* $NetBSD: kern_sysctl.c,v 1.40 1998/08/03 14:38:21 kleink Exp $ */
|
1994-06-29 10:29:24 +04:00
|
|
|
|
1994-05-07 02:42:07 +04:00
|
|
|
/*-
|
|
|
|
* Copyright (c) 1982, 1986, 1989, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* This code is derived from software contributed to Berkeley by
|
|
|
|
* Mike Karels at Berkeley Software Design, Inc.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the University of
|
|
|
|
* California, Berkeley and its contributors.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
1998-03-01 05:20:01 +03:00
|
|
|
* @(#)kern_sysctl.c 8.9 (Berkeley) 5/20/95
|
1994-05-07 02:42:07 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* sysctl system call.
|
|
|
|
*/
|
|
|
|
|
1998-07-05 02:18:13 +04:00
|
|
|
#include "opt_ddb.h"
|
1998-01-22 04:18:30 +03:00
|
|
|
#include "opt_insecure.h"
|
1998-06-29 01:34:58 +04:00
|
|
|
#include "opt_shortcorename.h"
|
1998-02-10 17:08:44 +03:00
|
|
|
#include "opt_uvm.h"
|
1998-01-22 04:18:30 +03:00
|
|
|
|
1994-05-07 02:42:07 +04:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/file.h>
|
|
|
|
#include <sys/vnode.h>
|
|
|
|
#include <sys/unistd.h>
|
|
|
|
#include <sys/buf.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/tty.h>
|
1995-01-25 09:08:06 +03:00
|
|
|
#include <sys/disklabel.h>
|
1997-01-31 05:33:59 +03:00
|
|
|
#include <sys/device.h>
|
1994-05-07 02:42:07 +04:00
|
|
|
#include <vm/vm.h>
|
|
|
|
#include <sys/sysctl.h>
|
1997-09-19 17:52:37 +04:00
|
|
|
#include <sys/msgbuf.h>
|
1994-05-07 02:42:07 +04:00
|
|
|
|
1998-02-05 10:59:28 +03:00
|
|
|
#if defined(UVM)
|
|
|
|
#include <uvm/uvm_extern.h>
|
|
|
|
#endif
|
|
|
|
|
1994-10-20 07:22:35 +03:00
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/syscallargs.h>
|
|
|
|
|
1998-02-05 10:59:28 +03:00
|
|
|
#if defined(UVM)
|
|
|
|
#include <uvm/uvm_extern.h>
|
|
|
|
#endif
|
|
|
|
|
1998-07-05 02:18:13 +04:00
|
|
|
#if defined(DDB)
|
|
|
|
#include <ddb/ddbvar.h>
|
|
|
|
#endif
|
|
|
|
|
1994-05-07 02:42:07 +04:00
|
|
|
/*
|
|
|
|
* Locking and stats
|
|
|
|
*/
|
|
|
|
static struct sysctl_lock {
|
|
|
|
int sl_lock;
|
|
|
|
int sl_want;
|
|
|
|
int sl_locked;
|
|
|
|
} memlock;
|
|
|
|
|
|
|
|
int
|
1995-10-07 09:25:19 +03:00
|
|
|
sys___sysctl(p, v, retval)
|
1994-05-07 02:42:07 +04:00
|
|
|
struct proc *p;
|
1995-09-20 01:40:36 +04:00
|
|
|
void *v;
|
|
|
|
register_t *retval;
|
|
|
|
{
|
1995-10-07 09:25:19 +03:00
|
|
|
register struct sys___sysctl_args /* {
|
1994-10-20 07:22:35 +03:00
|
|
|
syscallarg(int *) name;
|
|
|
|
syscallarg(u_int) namelen;
|
|
|
|
syscallarg(void *) old;
|
|
|
|
syscallarg(size_t *) oldlenp;
|
|
|
|
syscallarg(void *) new;
|
|
|
|
syscallarg(size_t) newlen;
|
1995-09-20 01:40:36 +04:00
|
|
|
} */ *uap = v;
|
1994-05-07 02:42:07 +04:00
|
|
|
int error, dolock = 1;
|
1996-02-04 05:15:01 +03:00
|
|
|
size_t savelen = 0, oldlen = 0;
|
1994-05-07 02:42:07 +04:00
|
|
|
sysctlfn *fn;
|
|
|
|
int name[CTL_MAXNAME];
|
|
|
|
|
1994-10-20 07:22:35 +03:00
|
|
|
if (SCARG(uap, new) != NULL &&
|
|
|
|
(error = suser(p->p_ucred, &p->p_acflag)))
|
1994-05-07 02:42:07 +04:00
|
|
|
return (error);
|
|
|
|
/*
|
|
|
|
* all top-level sysctl names are non-terminal
|
|
|
|
*/
|
1994-10-20 07:22:35 +03:00
|
|
|
if (SCARG(uap, namelen) > CTL_MAXNAME || SCARG(uap, namelen) < 2)
|
1994-05-07 02:42:07 +04:00
|
|
|
return (EINVAL);
|
1996-02-04 05:15:01 +03:00
|
|
|
error = copyin(SCARG(uap, name), &name,
|
|
|
|
SCARG(uap, namelen) * sizeof(int));
|
|
|
|
if (error)
|
1994-05-07 02:42:07 +04:00
|
|
|
return (error);
|
|
|
|
|
|
|
|
switch (name[0]) {
|
|
|
|
case CTL_KERN:
|
|
|
|
fn = kern_sysctl;
|
|
|
|
if (name[2] != KERN_VNODE) /* XXX */
|
|
|
|
dolock = 0;
|
|
|
|
break;
|
|
|
|
case CTL_HW:
|
|
|
|
fn = hw_sysctl;
|
|
|
|
break;
|
|
|
|
case CTL_VM:
|
1998-02-05 10:59:28 +03:00
|
|
|
#if defined(UVM)
|
|
|
|
fn = uvm_sysctl;
|
|
|
|
#else
|
1994-05-07 02:42:07 +04:00
|
|
|
fn = vm_sysctl;
|
1998-02-05 10:59:28 +03:00
|
|
|
#endif
|
1994-05-07 02:42:07 +04:00
|
|
|
break;
|
|
|
|
case CTL_NET:
|
|
|
|
fn = net_sysctl;
|
|
|
|
break;
|
1998-03-01 05:20:01 +03:00
|
|
|
case CTL_VFS:
|
|
|
|
fn = vfs_sysctl;
|
1994-05-07 02:42:07 +04:00
|
|
|
break;
|
|
|
|
case CTL_MACHDEP:
|
|
|
|
fn = cpu_sysctl;
|
|
|
|
break;
|
|
|
|
#ifdef DEBUG
|
|
|
|
case CTL_DEBUG:
|
|
|
|
fn = debug_sysctl;
|
|
|
|
break;
|
1997-01-09 08:37:41 +03:00
|
|
|
#endif
|
|
|
|
#ifdef DDB
|
|
|
|
case CTL_DDB:
|
|
|
|
fn = ddb_sysctl;
|
|
|
|
break;
|
1994-05-07 02:42:07 +04:00
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
|
1994-10-20 07:22:35 +03:00
|
|
|
if (SCARG(uap, oldlenp) &&
|
|
|
|
(error = copyin(SCARG(uap, oldlenp), &oldlen, sizeof(oldlen))))
|
1994-05-07 02:42:07 +04:00
|
|
|
return (error);
|
1994-10-20 07:22:35 +03:00
|
|
|
if (SCARG(uap, old) != NULL) {
|
1998-02-05 10:59:28 +03:00
|
|
|
#if defined(UVM)
|
|
|
|
if (!uvm_useracc(SCARG(uap, old), oldlen, B_WRITE))
|
|
|
|
#else
|
1994-10-20 07:22:35 +03:00
|
|
|
if (!useracc(SCARG(uap, old), oldlen, B_WRITE))
|
1998-02-05 10:59:28 +03:00
|
|
|
#endif
|
1994-05-07 02:42:07 +04:00
|
|
|
return (EFAULT);
|
|
|
|
while (memlock.sl_lock) {
|
|
|
|
memlock.sl_want = 1;
|
|
|
|
sleep((caddr_t)&memlock, PRIBIO+1);
|
|
|
|
memlock.sl_locked++;
|
|
|
|
}
|
|
|
|
memlock.sl_lock = 1;
|
|
|
|
if (dolock)
|
1998-02-05 10:59:28 +03:00
|
|
|
#if defined(UVM)
|
1998-04-30 10:28:57 +04:00
|
|
|
uvm_vslock(p, SCARG(uap, old), oldlen);
|
1998-02-05 10:59:28 +03:00
|
|
|
#else
|
1998-04-30 10:28:57 +04:00
|
|
|
vslock(p, SCARG(uap, old), oldlen);
|
1998-02-05 10:59:28 +03:00
|
|
|
#endif
|
1994-05-07 02:42:07 +04:00
|
|
|
savelen = oldlen;
|
|
|
|
}
|
1994-10-20 07:22:35 +03:00
|
|
|
error = (*fn)(name + 1, SCARG(uap, namelen) - 1, SCARG(uap, old),
|
|
|
|
&oldlen, SCARG(uap, new), SCARG(uap, newlen), p);
|
|
|
|
if (SCARG(uap, old) != NULL) {
|
1994-05-07 02:42:07 +04:00
|
|
|
if (dolock)
|
1998-02-05 10:59:28 +03:00
|
|
|
#if defined(UVM)
|
1998-04-30 10:28:57 +04:00
|
|
|
uvm_vsunlock(p, SCARG(uap, old), savelen);
|
1998-02-05 10:59:28 +03:00
|
|
|
#else
|
1998-04-30 10:28:57 +04:00
|
|
|
vsunlock(p, SCARG(uap, old), savelen);
|
1998-02-05 10:59:28 +03:00
|
|
|
#endif
|
1994-05-07 02:42:07 +04:00
|
|
|
memlock.sl_lock = 0;
|
|
|
|
if (memlock.sl_want) {
|
|
|
|
memlock.sl_want = 0;
|
|
|
|
wakeup((caddr_t)&memlock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (error)
|
|
|
|
return (error);
|
1994-10-20 07:22:35 +03:00
|
|
|
if (SCARG(uap, oldlenp))
|
|
|
|
error = copyout(&oldlen, SCARG(uap, oldlenp), sizeof(oldlen));
|
1996-04-13 03:21:37 +04:00
|
|
|
return (error);
|
1994-05-07 02:42:07 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Attributes stored in the kernel.
|
|
|
|
*/
|
|
|
|
char hostname[MAXHOSTNAMELEN];
|
|
|
|
int hostnamelen;
|
|
|
|
char domainname[MAXHOSTNAMELEN];
|
|
|
|
int domainnamelen;
|
|
|
|
long hostid;
|
1995-03-26 04:01:08 +04:00
|
|
|
#ifdef INSECURE
|
|
|
|
int securelevel = -1;
|
|
|
|
#else
|
1996-05-20 21:49:05 +04:00
|
|
|
int securelevel = 0;
|
1995-03-26 04:01:08 +04:00
|
|
|
#endif
|
1998-06-29 01:34:58 +04:00
|
|
|
#ifdef SHORTCORENAME
|
|
|
|
int shortcorename = 1;
|
|
|
|
#else
|
|
|
|
int shortcorename = 0;
|
|
|
|
#endif
|
1994-05-07 02:42:07 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* kernel related system variables.
|
|
|
|
*/
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
1994-05-07 02:42:07 +04:00
|
|
|
kern_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
|
|
|
|
int *name;
|
|
|
|
u_int namelen;
|
|
|
|
void *oldp;
|
|
|
|
size_t *oldlenp;
|
|
|
|
void *newp;
|
|
|
|
size_t newlen;
|
|
|
|
struct proc *p;
|
|
|
|
{
|
|
|
|
int error, level, inthostid;
|
1996-07-18 01:54:04 +04:00
|
|
|
int old_autonicetime;
|
1997-01-30 13:29:24 +03:00
|
|
|
int old_vnodes;
|
1998-06-29 01:34:58 +04:00
|
|
|
int old_shortcorename;
|
1994-05-07 02:42:07 +04:00
|
|
|
extern char ostype[], osrelease[], version[];
|
|
|
|
|
|
|
|
/* all sysctl names at this level are terminal */
|
|
|
|
if (namelen != 1 && !(name[0] == KERN_PROC || name[0] == KERN_PROF))
|
|
|
|
return (ENOTDIR); /* overloaded */
|
|
|
|
|
|
|
|
switch (name[0]) {
|
|
|
|
case KERN_OSTYPE:
|
|
|
|
return (sysctl_rdstring(oldp, oldlenp, newp, ostype));
|
|
|
|
case KERN_OSRELEASE:
|
|
|
|
return (sysctl_rdstring(oldp, oldlenp, newp, osrelease));
|
|
|
|
case KERN_OSREV:
|
1997-03-21 09:50:48 +03:00
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, NetBSD));
|
1994-05-07 02:42:07 +04:00
|
|
|
case KERN_VERSION:
|
|
|
|
return (sysctl_rdstring(oldp, oldlenp, newp, version));
|
|
|
|
case KERN_MAXVNODES:
|
1997-01-30 13:29:24 +03:00
|
|
|
old_vnodes = desiredvnodes;
|
1997-10-21 22:51:06 +04:00
|
|
|
error = sysctl_int(oldp, oldlenp, newp, newlen, &desiredvnodes);
|
|
|
|
if (old_vnodes > desiredvnodes) {
|
|
|
|
desiredvnodes = old_vnodes;
|
1997-01-30 13:29:24 +03:00
|
|
|
return (EINVAL);
|
1997-10-21 22:51:06 +04:00
|
|
|
}
|
1997-01-30 13:29:24 +03:00
|
|
|
return (error);
|
1994-05-07 02:42:07 +04:00
|
|
|
case KERN_MAXPROC:
|
|
|
|
return (sysctl_int(oldp, oldlenp, newp, newlen, &maxproc));
|
|
|
|
case KERN_MAXFILES:
|
|
|
|
return (sysctl_int(oldp, oldlenp, newp, newlen, &maxfiles));
|
|
|
|
case KERN_ARGMAX:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, ARG_MAX));
|
|
|
|
case KERN_SECURELVL:
|
|
|
|
level = securelevel;
|
|
|
|
if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
|
|
|
|
newp == NULL)
|
|
|
|
return (error);
|
|
|
|
if (level < securelevel && p->p_pid != 1)
|
|
|
|
return (EPERM);
|
|
|
|
securelevel = level;
|
|
|
|
return (0);
|
|
|
|
case KERN_HOSTNAME:
|
|
|
|
error = sysctl_string(oldp, oldlenp, newp, newlen,
|
|
|
|
hostname, sizeof(hostname));
|
|
|
|
if (newp && !error)
|
|
|
|
hostnamelen = newlen;
|
|
|
|
return (error);
|
|
|
|
case KERN_DOMAINNAME:
|
|
|
|
error = sysctl_string(oldp, oldlenp, newp, newlen,
|
|
|
|
domainname, sizeof(domainname));
|
|
|
|
if (newp && !error)
|
|
|
|
domainnamelen = newlen;
|
|
|
|
return (error);
|
|
|
|
case KERN_HOSTID:
|
|
|
|
inthostid = hostid; /* XXX assumes sizeof long <= sizeof int */
|
|
|
|
error = sysctl_int(oldp, oldlenp, newp, newlen, &inthostid);
|
|
|
|
hostid = inthostid;
|
|
|
|
return (error);
|
|
|
|
case KERN_CLOCKRATE:
|
|
|
|
return (sysctl_clockrate(oldp, oldlenp));
|
|
|
|
case KERN_BOOTTIME:
|
|
|
|
return (sysctl_rdstruct(oldp, oldlenp, newp, &boottime,
|
|
|
|
sizeof(struct timeval)));
|
|
|
|
case KERN_VNODE:
|
1998-03-01 05:20:01 +03:00
|
|
|
return (sysctl_vnode(oldp, oldlenp, p));
|
1994-05-07 02:42:07 +04:00
|
|
|
case KERN_PROC:
|
|
|
|
return (sysctl_doproc(name + 1, namelen - 1, oldp, oldlenp));
|
|
|
|
case KERN_FILE:
|
|
|
|
return (sysctl_file(oldp, oldlenp));
|
|
|
|
#ifdef GPROF
|
|
|
|
case KERN_PROF:
|
|
|
|
return (sysctl_doprof(name + 1, namelen - 1, oldp, oldlenp,
|
|
|
|
newp, newlen));
|
|
|
|
#endif
|
|
|
|
case KERN_POSIX1:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, _POSIX_VERSION));
|
|
|
|
case KERN_NGROUPS:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, NGROUPS_MAX));
|
|
|
|
case KERN_JOB_CONTROL:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 1));
|
|
|
|
case KERN_SAVED_IDS:
|
|
|
|
#ifdef _POSIX_SAVED_IDS
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 1));
|
|
|
|
#else
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 0));
|
|
|
|
#endif
|
1995-01-25 09:08:06 +03:00
|
|
|
case KERN_MAXPARTITIONS:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, MAXPARTITIONS));
|
1995-08-04 22:36:08 +04:00
|
|
|
case KERN_RAWPARTITION:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, RAW_PART));
|
1996-11-14 07:47:45 +03:00
|
|
|
#ifdef NTP
|
Add NTP kernel precision timekeeping from Dave Mill's xntp distribution
and the "kernel.tar.Z" distribution on louie.udel.edu, which is older than
xntp 3.4y or 3.5a, but contains newer kernel source fragments.
This commit adds support for a new kernel configuration option, NTP.
If NTP is selected, then the system clock should be run at "HZ", which
must be defined at compile time to be one value from:
60, 64, 100, 128, 256, 512, 1024.
Powers of 2 are ideal; 60 and 100 are supported but are marginally less
accurate.
If NTP is not configured, there should be no change in behavior relative
to pre-NTP kernels.
These changes have been tested extensively with xntpd 3.4y on a decstation;
almost identical kernel mods work on an i386. No pulse-per-second (PPS)
line discipline support is included, due to unavailability of hardware
to test it.
With this in-kernel PLL support for NetBSD, both xntp 3.4y and xntp
3.5a user-level code need minor changes. xntp's prototype for
syscall() is correct for FreeBSD, but not for NetBSD.
1996-02-27 07:20:30 +03:00
|
|
|
case KERN_NTPTIME:
|
|
|
|
return (sysctl_ntptime(oldp, oldlenp));
|
1996-11-14 07:47:45 +03:00
|
|
|
#endif
|
1996-07-18 01:54:04 +04:00
|
|
|
case KERN_AUTONICETIME:
|
|
|
|
old_autonicetime = autonicetime;
|
|
|
|
error = sysctl_int(oldp, oldlenp, newp, newlen, &autonicetime);
|
|
|
|
if (autonicetime < 0)
|
|
|
|
autonicetime = old_autonicetime;
|
|
|
|
return (error);
|
|
|
|
case KERN_AUTONICEVAL:
|
|
|
|
error = sysctl_int(oldp, oldlenp, newp, newlen, &autoniceval);
|
|
|
|
if (autoniceval < PRIO_MIN)
|
|
|
|
autoniceval = PRIO_MIN;
|
|
|
|
if (autoniceval > PRIO_MAX)
|
|
|
|
autoniceval = PRIO_MAX;
|
|
|
|
return (error);
|
1997-01-15 04:28:28 +03:00
|
|
|
case KERN_RTC_OFFSET:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, rtc_offset));
|
1997-01-31 05:33:59 +03:00
|
|
|
case KERN_ROOT_DEVICE:
|
|
|
|
return (sysctl_rdstring(oldp, oldlenp, newp,
|
|
|
|
root_device->dv_xname));
|
1997-09-19 17:52:37 +04:00
|
|
|
case KERN_MSGBUFSIZE:
|
|
|
|
/*
|
|
|
|
* deal with cases where the message buffer has
|
|
|
|
* become corrupted.
|
|
|
|
*/
|
|
|
|
if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) {
|
|
|
|
msgbufenabled = 0;
|
|
|
|
return (ENXIO);
|
|
|
|
}
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, msgbufp->msg_bufs));
|
1998-05-24 23:52:01 +04:00
|
|
|
case KERN_FSYNC:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 1));
|
|
|
|
case KERN_SYSVMSG:
|
|
|
|
#ifdef SYSVMSG
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 1));
|
|
|
|
#else
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 0));
|
|
|
|
#endif
|
|
|
|
case KERN_SYSVSEM:
|
|
|
|
#ifdef SYSVSEM
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 1));
|
|
|
|
#else
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 0));
|
|
|
|
#endif
|
|
|
|
case KERN_SYSVSHM:
|
|
|
|
#ifdef SYSVSHM
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 1));
|
|
|
|
#else
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 0));
|
|
|
|
#endif
|
1998-06-29 01:34:58 +04:00
|
|
|
case KERN_SHORTCORENAME:
|
|
|
|
/* Only allow values of zero or one. */
|
|
|
|
old_shortcorename = shortcorename;
|
|
|
|
error = sysctl_int(oldp, oldlenp, newp, newlen,
|
|
|
|
&shortcorename);
|
|
|
|
if (shortcorename != 0 && shortcorename != 1) {
|
|
|
|
shortcorename = old_shortcorename;
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
return (error);
|
1998-08-03 18:38:20 +04:00
|
|
|
case KERN_SYNCHRONIZED_IO:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 1));
|
|
|
|
case KERN_IOV_MAX:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, IOV_MAX));
|
1994-05-07 02:42:07 +04:00
|
|
|
default:
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* hardware related system variables.
|
|
|
|
*/
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
1994-05-07 02:42:07 +04:00
|
|
|
hw_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
|
|
|
|
int *name;
|
|
|
|
u_int namelen;
|
|
|
|
void *oldp;
|
|
|
|
size_t *oldlenp;
|
|
|
|
void *newp;
|
|
|
|
size_t newlen;
|
|
|
|
struct proc *p;
|
|
|
|
{
|
1997-06-07 03:14:36 +04:00
|
|
|
extern char machine[], machine_arch[], cpu_model[];
|
1994-05-07 02:42:07 +04:00
|
|
|
|
|
|
|
/* all sysctl names at this level are terminal */
|
|
|
|
if (namelen != 1)
|
|
|
|
return (ENOTDIR); /* overloaded */
|
|
|
|
|
|
|
|
switch (name[0]) {
|
|
|
|
case HW_MACHINE:
|
|
|
|
return (sysctl_rdstring(oldp, oldlenp, newp, machine));
|
1997-06-07 03:14:36 +04:00
|
|
|
case HW_MACHINE_ARCH:
|
|
|
|
return (sysctl_rdstring(oldp, oldlenp, newp, machine_arch));
|
1994-05-07 02:42:07 +04:00
|
|
|
case HW_MODEL:
|
|
|
|
return (sysctl_rdstring(oldp, oldlenp, newp, cpu_model));
|
|
|
|
case HW_NCPU:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, 1)); /* XXX */
|
|
|
|
case HW_BYTEORDER:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, BYTE_ORDER));
|
|
|
|
case HW_PHYSMEM:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, ctob(physmem)));
|
|
|
|
case HW_USERMEM:
|
1998-02-05 10:59:28 +03:00
|
|
|
#if defined(UVM)
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp,
|
|
|
|
ctob(physmem - uvmexp.wired)));
|
|
|
|
#else
|
1994-05-07 02:42:07 +04:00
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp,
|
|
|
|
ctob(physmem - cnt.v_wire_count)));
|
1998-02-05 10:59:28 +03:00
|
|
|
#endif
|
1994-05-07 02:42:07 +04:00
|
|
|
case HW_PAGESIZE:
|
|
|
|
return (sysctl_rdint(oldp, oldlenp, newp, PAGE_SIZE));
|
|
|
|
default:
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
/*
|
|
|
|
* Debugging related system variables.
|
|
|
|
*/
|
|
|
|
struct ctldebug debug0, debug1, debug2, debug3, debug4;
|
|
|
|
struct ctldebug debug5, debug6, debug7, debug8, debug9;
|
|
|
|
struct ctldebug debug10, debug11, debug12, debug13, debug14;
|
|
|
|
struct ctldebug debug15, debug16, debug17, debug18, debug19;
|
|
|
|
static struct ctldebug *debugvars[CTL_DEBUG_MAXID] = {
|
|
|
|
&debug0, &debug1, &debug2, &debug3, &debug4,
|
|
|
|
&debug5, &debug6, &debug7, &debug8, &debug9,
|
|
|
|
&debug10, &debug11, &debug12, &debug13, &debug14,
|
|
|
|
&debug15, &debug16, &debug17, &debug18, &debug19,
|
|
|
|
};
|
|
|
|
int
|
|
|
|
debug_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p)
|
|
|
|
int *name;
|
|
|
|
u_int namelen;
|
|
|
|
void *oldp;
|
|
|
|
size_t *oldlenp;
|
|
|
|
void *newp;
|
|
|
|
size_t newlen;
|
|
|
|
struct proc *p;
|
|
|
|
{
|
|
|
|
struct ctldebug *cdp;
|
|
|
|
|
|
|
|
/* all sysctl names at this level are name and field */
|
|
|
|
if (namelen != 2)
|
|
|
|
return (ENOTDIR); /* overloaded */
|
|
|
|
cdp = debugvars[name[0]];
|
1998-03-01 05:20:01 +03:00
|
|
|
if (name[0] >= CTL_DEBUG_MAXID || cdp->debugname == 0)
|
1994-05-07 02:42:07 +04:00
|
|
|
return (EOPNOTSUPP);
|
|
|
|
switch (name[1]) {
|
|
|
|
case CTL_DEBUG_NAME:
|
|
|
|
return (sysctl_rdstring(oldp, oldlenp, newp, cdp->debugname));
|
|
|
|
case CTL_DEBUG_VALUE:
|
|
|
|
return (sysctl_int(oldp, oldlenp, newp, newlen, cdp->debugvar));
|
|
|
|
default:
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|
|
|
|
/* NOTREACHED */
|
|
|
|
}
|
|
|
|
#endif /* DEBUG */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Validate parameters and get old / set new parameters
|
|
|
|
* for an integer-valued sysctl function.
|
|
|
|
*/
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
1994-05-07 02:42:07 +04:00
|
|
|
sysctl_int(oldp, oldlenp, newp, newlen, valp)
|
|
|
|
void *oldp;
|
|
|
|
size_t *oldlenp;
|
|
|
|
void *newp;
|
|
|
|
size_t newlen;
|
|
|
|
int *valp;
|
|
|
|
{
|
|
|
|
int error = 0;
|
|
|
|
|
|
|
|
if (oldp && *oldlenp < sizeof(int))
|
|
|
|
return (ENOMEM);
|
|
|
|
if (newp && newlen != sizeof(int))
|
|
|
|
return (EINVAL);
|
|
|
|
*oldlenp = sizeof(int);
|
|
|
|
if (oldp)
|
|
|
|
error = copyout(valp, oldp, sizeof(int));
|
|
|
|
if (error == 0 && newp)
|
|
|
|
error = copyin(newp, valp, sizeof(int));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* As above, but read-only.
|
|
|
|
*/
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
1994-05-07 02:42:07 +04:00
|
|
|
sysctl_rdint(oldp, oldlenp, newp, val)
|
|
|
|
void *oldp;
|
|
|
|
size_t *oldlenp;
|
|
|
|
void *newp;
|
|
|
|
int val;
|
|
|
|
{
|
|
|
|
int error = 0;
|
|
|
|
|
|
|
|
if (oldp && *oldlenp < sizeof(int))
|
|
|
|
return (ENOMEM);
|
|
|
|
if (newp)
|
|
|
|
return (EPERM);
|
|
|
|
*oldlenp = sizeof(int);
|
|
|
|
if (oldp)
|
|
|
|
error = copyout((caddr_t)&val, oldp, sizeof(int));
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Validate parameters and get old / set new parameters
|
|
|
|
* for a string-valued sysctl function.
|
|
|
|
*/
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
1994-05-07 02:42:07 +04:00
|
|
|
sysctl_string(oldp, oldlenp, newp, newlen, str, maxlen)
|
|
|
|
void *oldp;
|
|
|
|
size_t *oldlenp;
|
|
|
|
void *newp;
|
|
|
|
size_t newlen;
|
|
|
|
char *str;
|
|
|
|
int maxlen;
|
|
|
|
{
|
|
|
|
int len, error = 0;
|
|
|
|
|
|
|
|
len = strlen(str) + 1;
|
|
|
|
if (oldp && *oldlenp < len)
|
|
|
|
return (ENOMEM);
|
|
|
|
if (newp && newlen >= maxlen)
|
|
|
|
return (EINVAL);
|
|
|
|
if (oldp) {
|
|
|
|
*oldlenp = len;
|
|
|
|
error = copyout(str, oldp, len);
|
|
|
|
}
|
|
|
|
if (error == 0 && newp) {
|
|
|
|
error = copyin(newp, str, newlen);
|
|
|
|
str[newlen] = 0;
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* As above, but read-only.
|
|
|
|
*/
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
1994-05-07 02:42:07 +04:00
|
|
|
sysctl_rdstring(oldp, oldlenp, newp, str)
|
|
|
|
void *oldp;
|
|
|
|
size_t *oldlenp;
|
|
|
|
void *newp;
|
|
|
|
char *str;
|
|
|
|
{
|
|
|
|
int len, error = 0;
|
|
|
|
|
|
|
|
len = strlen(str) + 1;
|
|
|
|
if (oldp && *oldlenp < len)
|
|
|
|
return (ENOMEM);
|
|
|
|
if (newp)
|
|
|
|
return (EPERM);
|
|
|
|
*oldlenp = len;
|
|
|
|
if (oldp)
|
|
|
|
error = copyout(str, oldp, len);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Validate parameters and get old / set new parameters
|
|
|
|
* for a structure oriented sysctl function.
|
|
|
|
*/
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
1994-05-07 02:42:07 +04:00
|
|
|
sysctl_struct(oldp, oldlenp, newp, newlen, sp, len)
|
|
|
|
void *oldp;
|
|
|
|
size_t *oldlenp;
|
|
|
|
void *newp;
|
|
|
|
size_t newlen;
|
|
|
|
void *sp;
|
|
|
|
int len;
|
|
|
|
{
|
|
|
|
int error = 0;
|
|
|
|
|
|
|
|
if (oldp && *oldlenp < len)
|
|
|
|
return (ENOMEM);
|
|
|
|
if (newp && newlen > len)
|
|
|
|
return (EINVAL);
|
|
|
|
if (oldp) {
|
|
|
|
*oldlenp = len;
|
|
|
|
error = copyout(sp, oldp, len);
|
|
|
|
}
|
|
|
|
if (error == 0 && newp)
|
|
|
|
error = copyin(newp, sp, len);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Validate parameters and get old parameters
|
|
|
|
* for a structure oriented sysctl function.
|
|
|
|
*/
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
1994-05-07 02:42:07 +04:00
|
|
|
sysctl_rdstruct(oldp, oldlenp, newp, sp, len)
|
|
|
|
void *oldp;
|
|
|
|
size_t *oldlenp;
|
|
|
|
void *newp, *sp;
|
|
|
|
int len;
|
|
|
|
{
|
|
|
|
int error = 0;
|
|
|
|
|
|
|
|
if (oldp && *oldlenp < len)
|
|
|
|
return (ENOMEM);
|
|
|
|
if (newp)
|
|
|
|
return (EPERM);
|
|
|
|
*oldlenp = len;
|
|
|
|
if (oldp)
|
|
|
|
error = copyout(sp, oldp, len);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get file structures.
|
|
|
|
*/
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
1994-05-07 02:42:07 +04:00
|
|
|
sysctl_file(where, sizep)
|
|
|
|
char *where;
|
|
|
|
size_t *sizep;
|
|
|
|
{
|
|
|
|
int buflen, error;
|
|
|
|
struct file *fp;
|
|
|
|
char *start = where;
|
|
|
|
|
|
|
|
buflen = *sizep;
|
|
|
|
if (where == NULL) {
|
|
|
|
/*
|
|
|
|
* overestimate by 10 files
|
|
|
|
*/
|
|
|
|
*sizep = sizeof(filehead) + (nfiles + 10) * sizeof(struct file);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* first copyout filehead
|
|
|
|
*/
|
|
|
|
if (buflen < sizeof(filehead)) {
|
|
|
|
*sizep = 0;
|
|
|
|
return (0);
|
|
|
|
}
|
1996-02-04 05:15:01 +03:00
|
|
|
error = copyout((caddr_t)&filehead, where, sizeof(filehead));
|
|
|
|
if (error)
|
1994-05-07 02:42:07 +04:00
|
|
|
return (error);
|
|
|
|
buflen -= sizeof(filehead);
|
|
|
|
where += sizeof(filehead);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* followed by an array of file structures
|
|
|
|
*/
|
1994-08-30 07:04:28 +04:00
|
|
|
for (fp = filehead.lh_first; fp != 0; fp = fp->f_list.le_next) {
|
1994-05-07 02:42:07 +04:00
|
|
|
if (buflen < sizeof(struct file)) {
|
|
|
|
*sizep = where - start;
|
|
|
|
return (ENOMEM);
|
|
|
|
}
|
1998-08-01 02:50:48 +04:00
|
|
|
error = copyout((caddr_t)fp, where, sizeof(struct file));
|
1996-02-04 05:15:01 +03:00
|
|
|
if (error)
|
1994-05-07 02:42:07 +04:00
|
|
|
return (error);
|
|
|
|
buflen -= sizeof(struct file);
|
|
|
|
where += sizeof(struct file);
|
|
|
|
}
|
|
|
|
*sizep = where - start;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* try over estimating by 5 procs
|
|
|
|
*/
|
1998-08-01 02:50:48 +04:00
|
|
|
#define KERN_PROCSLOP (5 * sizeof(struct kinfo_proc))
|
1994-05-07 02:42:07 +04:00
|
|
|
|
1996-02-04 05:15:01 +03:00
|
|
|
int
|
1994-05-07 02:42:07 +04:00
|
|
|
sysctl_doproc(name, namelen, where, sizep)
|
|
|
|
int *name;
|
|
|
|
u_int namelen;
|
|
|
|
char *where;
|
|
|
|
size_t *sizep;
|
|
|
|
{
|
|
|
|
register struct proc *p;
|
|
|
|
register struct kinfo_proc *dp = (struct kinfo_proc *)where;
|
|
|
|
register int needed = 0;
|
|
|
|
int buflen = where != NULL ? *sizep : 0;
|
|
|
|
int doingzomb;
|
|
|
|
struct eproc eproc;
|
|
|
|
int error = 0;
|
|
|
|
|
|
|
|
if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
|
|
|
|
return (EINVAL);
|
1994-08-30 07:04:28 +04:00
|
|
|
p = allproc.lh_first;
|
1994-05-07 02:42:07 +04:00
|
|
|
doingzomb = 0;
|
|
|
|
again:
|
1994-08-30 07:04:28 +04:00
|
|
|
for (; p != 0; p = p->p_list.le_next) {
|
1994-05-07 02:42:07 +04:00
|
|
|
/*
|
|
|
|
* Skip embryonic processes.
|
|
|
|
*/
|
|
|
|
if (p->p_stat == SIDL)
|
|
|
|
continue;
|
|
|
|
/*
|
|
|
|
* TODO - make more efficient (see notes below).
|
|
|
|
* do by session.
|
|
|
|
*/
|
|
|
|
switch (name[0]) {
|
|
|
|
|
|
|
|
case KERN_PROC_PID:
|
|
|
|
/* could do this with just a lookup */
|
|
|
|
if (p->p_pid != (pid_t)name[1])
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KERN_PROC_PGRP:
|
|
|
|
/* could do this by traversing pgrp */
|
|
|
|
if (p->p_pgrp->pg_id != (pid_t)name[1])
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KERN_PROC_TTY:
|
|
|
|
if ((p->p_flag & P_CONTROLT) == 0 ||
|
|
|
|
p->p_session->s_ttyp == NULL ||
|
|
|
|
p->p_session->s_ttyp->t_dev != (dev_t)name[1])
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KERN_PROC_UID:
|
|
|
|
if (p->p_ucred->cr_uid != (uid_t)name[1])
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KERN_PROC_RUID:
|
|
|
|
if (p->p_cred->p_ruid != (uid_t)name[1])
|
|
|
|
continue;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (buflen >= sizeof(struct kinfo_proc)) {
|
|
|
|
fill_eproc(p, &eproc);
|
1996-02-04 05:15:01 +03:00
|
|
|
error = copyout((caddr_t)p, &dp->kp_proc,
|
|
|
|
sizeof(struct proc));
|
|
|
|
if (error)
|
1994-05-07 02:42:07 +04:00
|
|
|
return (error);
|
1996-02-04 05:15:01 +03:00
|
|
|
error = copyout((caddr_t)&eproc, &dp->kp_eproc,
|
|
|
|
sizeof(eproc));
|
|
|
|
if (error)
|
1994-05-07 02:42:07 +04:00
|
|
|
return (error);
|
|
|
|
dp++;
|
|
|
|
buflen -= sizeof(struct kinfo_proc);
|
|
|
|
}
|
|
|
|
needed += sizeof(struct kinfo_proc);
|
|
|
|
}
|
|
|
|
if (doingzomb == 0) {
|
1994-08-30 07:04:28 +04:00
|
|
|
p = zombproc.lh_first;
|
1994-05-07 02:42:07 +04:00
|
|
|
doingzomb++;
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
if (where != NULL) {
|
|
|
|
*sizep = (caddr_t)dp - where;
|
|
|
|
if (needed > *sizep)
|
|
|
|
return (ENOMEM);
|
|
|
|
} else {
|
|
|
|
needed += KERN_PROCSLOP;
|
|
|
|
*sizep = needed;
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Fill in an eproc structure for the specified process.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
fill_eproc(p, ep)
|
|
|
|
register struct proc *p;
|
|
|
|
register struct eproc *ep;
|
|
|
|
{
|
|
|
|
register struct tty *tp;
|
|
|
|
|
|
|
|
ep->e_paddr = p;
|
|
|
|
ep->e_sess = p->p_pgrp->pg_session;
|
|
|
|
ep->e_pcred = *p->p_cred;
|
|
|
|
ep->e_ucred = *p->p_ucred;
|
|
|
|
if (p->p_stat == SIDL || p->p_stat == SZOMB) {
|
|
|
|
ep->e_vm.vm_rssize = 0;
|
|
|
|
ep->e_vm.vm_tsize = 0;
|
|
|
|
ep->e_vm.vm_dsize = 0;
|
|
|
|
ep->e_vm.vm_ssize = 0;
|
|
|
|
/* ep->e_vm.vm_pmap = XXX; */
|
|
|
|
} else {
|
|
|
|
register struct vmspace *vm = p->p_vmspace;
|
|
|
|
|
1997-05-17 01:39:50 +04:00
|
|
|
ep->e_vm.vm_rssize = vm_resident_count(vm);
|
1994-05-07 02:42:07 +04:00
|
|
|
ep->e_vm.vm_tsize = vm->vm_tsize;
|
|
|
|
ep->e_vm.vm_dsize = vm->vm_dsize;
|
|
|
|
ep->e_vm.vm_ssize = vm->vm_ssize;
|
|
|
|
}
|
|
|
|
if (p->p_pptr)
|
|
|
|
ep->e_ppid = p->p_pptr->p_pid;
|
|
|
|
else
|
|
|
|
ep->e_ppid = 0;
|
|
|
|
ep->e_pgid = p->p_pgrp->pg_id;
|
1998-02-14 03:37:26 +03:00
|
|
|
ep->e_sid = ep->e_sess->s_sid;
|
1994-05-07 02:42:07 +04:00
|
|
|
ep->e_jobc = p->p_pgrp->pg_jobc;
|
|
|
|
if ((p->p_flag & P_CONTROLT) &&
|
|
|
|
(tp = ep->e_sess->s_ttyp)) {
|
|
|
|
ep->e_tdev = tp->t_dev;
|
|
|
|
ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
|
|
|
|
ep->e_tsess = tp->t_session;
|
|
|
|
} else
|
|
|
|
ep->e_tdev = NODEV;
|
|
|
|
if (p->p_wmesg)
|
|
|
|
strncpy(ep->e_wmesg, p->p_wmesg, WMESGLEN);
|
|
|
|
ep->e_xsize = ep->e_xrssize = 0;
|
|
|
|
ep->e_xccount = ep->e_xswrss = 0;
|
1997-03-19 07:55:07 +03:00
|
|
|
ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
|
|
|
|
if (SESS_LEADER(p))
|
|
|
|
ep->e_flag |= EPROC_SLEADER;
|
|
|
|
strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME);
|
1994-05-07 02:42:07 +04:00
|
|
|
}
|
|
|
|
|