Import Lite2's src/usr.sbin, except for timed. All changed files
except one unimportant one have already left the vendor branch.
This commit is contained in:
parent
9c60775004
commit
59fe2c14b4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/WIN_TUE_NL/; revision=27850
229
sbin/sysctl/sysctl.8
Normal file
229
sbin/sysctl/sysctl.8
Normal file
@ -0,0 +1,229 @@
|
||||
.\" Copyright (c) 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)sysctl.8 8.2 (Berkeley) 5/9/95
|
||||
.\"
|
||||
.Dd "May 9, 1995"
|
||||
.Dt SYSCTL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm sysctl
|
||||
.Nd get or set kernel state
|
||||
.Sh SYNOPSIS
|
||||
.Nm sysctl
|
||||
.Op Fl n
|
||||
.Ar name ...
|
||||
.Nm sysctl
|
||||
.Op Fl n
|
||||
.Fl w
|
||||
.Ar name=value ...
|
||||
.Nm sysctl
|
||||
.Op Fl n
|
||||
.Fl aA
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm sysctl
|
||||
utility retrieves kernel state and allows processes with
|
||||
appropriate privilege to set kernel state.
|
||||
The state to be retrieved or set is described using a
|
||||
``Management Information Base'' (``MIB'') style name,
|
||||
described as a dotted set of components.
|
||||
The
|
||||
.Fl a
|
||||
flag can be used to list all the currently available string or integer values.
|
||||
The
|
||||
.Fl A
|
||||
flag will list all the known MIB names including tables.
|
||||
Those with string or integer values will be printed as with the
|
||||
.Fl a
|
||||
flag; for the table values,
|
||||
the name of the utility to retrieve them is given.
|
||||
.Pp
|
||||
The
|
||||
.Fl n
|
||||
flag specifies that the printing of the field name should be
|
||||
suppressed and that only its value should be output.
|
||||
This flag is useful for setting shell variables.
|
||||
For example, to save the pagesize in variable psize, use:
|
||||
.Bd -literal -offset indent -compact
|
||||
set psize=`sysctl -n hw.pagesize`
|
||||
.Ed
|
||||
.Pp
|
||||
If just a MIB style name is given,
|
||||
the corresponding value is retrieved.
|
||||
If a value is to be set, the
|
||||
.Fl w
|
||||
flag must be specified and the MIB name followed
|
||||
by an equal sign and the new value to be used.
|
||||
.Pp
|
||||
The information available from
|
||||
.Nm sysctl
|
||||
consists of integers, strings, and tables.
|
||||
The tabular information can only be retrieved by special
|
||||
purpose programs such as
|
||||
.Nm ps ,
|
||||
.Nm systat ,
|
||||
and
|
||||
.Nm netstat .
|
||||
The string and integer information is summaried below.
|
||||
For a detailed description of these variable see
|
||||
.Xr sysctl 3 .
|
||||
The changeable column indicates whether a process with appropriate
|
||||
privilege can change the value.
|
||||
.Bl -column net.inet.ip.forwardingxxxxxx integerxxx
|
||||
.It Sy Name Type Changeable
|
||||
.It kern.ostype string no
|
||||
.It kern.osrelease string no
|
||||
.It kern.osrevision integer no
|
||||
.It kern.version string no
|
||||
.It kern.maxvnodes integer yes
|
||||
.It kern.maxproc integer yes
|
||||
.It kern.maxfiles integer yes
|
||||
.It kern.argmax integer no
|
||||
.It kern.securelevel integer raise only
|
||||
.It kern.hostname string yes
|
||||
.It kern.hostid integer yes
|
||||
.It kern.clockrate struct no
|
||||
.It kern.posix1version integer no
|
||||
.It kern.ngroups integer no
|
||||
.It kern.job_control integer no
|
||||
.It kern.saved_ids integer no
|
||||
.It kern.link_max integer no
|
||||
.It kern.max_canon integer no
|
||||
.It kern.max_input integer no
|
||||
.It kern.name_max integer no
|
||||
.It kern.path_max integer no
|
||||
.It kern.pipe_buf integer no
|
||||
.It kern.chown_restricted integer no
|
||||
.It kern.no_trunc integer no
|
||||
.It kern.vdisable integer no
|
||||
.It kern.boottime struct no
|
||||
.It vm.loadavg struct no
|
||||
.It machdep.console_device dev_t no
|
||||
.It net.inet.ip.forwarding integer yes
|
||||
.It net.inet.ip.redirect integer yes
|
||||
.It net.inet.ip.ttl integer yes
|
||||
.It net.inet.icmp.maskrepl integer yes
|
||||
.It net.inet.udp.checksum integer yes
|
||||
.It hw.machine string no
|
||||
.It hw.model string no
|
||||
.It hw.ncpu integer no
|
||||
.It hw.byteorder integer no
|
||||
.It hw.physmem integer no
|
||||
.It hw.usermem integer no
|
||||
.It hw.pagesize integer no
|
||||
.It user.cs_path string no
|
||||
.It user.bc_base_max integer no
|
||||
.It user.bc_dim_max integer no
|
||||
.It user.bc_scale_max integer no
|
||||
.It user.bc_string_max integer no
|
||||
.It user.coll_weights_max integer no
|
||||
.It user.expr_nest_max integer no
|
||||
.It user.line_max integer no
|
||||
.It user.re_dup_max integer no
|
||||
.It user.posix2_version integer no
|
||||
.It user.posix2_c_bind integer no
|
||||
.It user.posix2_c_dev integer no
|
||||
.It user.posix2_char_term integer no
|
||||
.It user.posix2_fort_dev integer no
|
||||
.It user.posix2_fort_run integer no
|
||||
.It user.posix2_localedef integer no
|
||||
.It user.posix2_sw_dev integer no
|
||||
.It user.posix2_upe integer no
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm sysctl
|
||||
program can get or set debugging variables
|
||||
that have been identified for its display.
|
||||
This information can be obtained by using the command:
|
||||
.Bd -literal -offset indent
|
||||
sysctl debug
|
||||
.Ed
|
||||
In addition,
|
||||
.Nm sysctl
|
||||
can extract information about the filesystems that have been compiled
|
||||
into the running system.
|
||||
This information can be obtained by using the command:
|
||||
.Bd -literal -offset indent
|
||||
sysctl vfs
|
||||
.Ed
|
||||
By default, only filesystems that are actively being used are listed.
|
||||
Use of the
|
||||
.Fl A
|
||||
flag lists all the filesystems compiled into the running kernel.
|
||||
.Sh EXAMPLES
|
||||
.Pp
|
||||
For example, to retrieve the maximum number of processes allowed
|
||||
in the system, one would use the follow request:
|
||||
.Bd -literal -offset indent -compact
|
||||
sysctl kern.maxproc
|
||||
.Ed
|
||||
.Pp
|
||||
To set the maximum number of processes allowed
|
||||
in the system to 1000, one would use the follow request:
|
||||
.Bd -literal -offset indent -compact
|
||||
sysctl -w kern.maxproc=1000
|
||||
.Ed
|
||||
.Pp
|
||||
Information about the system clock rate may be obtained with:
|
||||
.Bd -literal -offset indent -compact
|
||||
sysctl kern.clockrate
|
||||
.Ed
|
||||
.Pp
|
||||
Information about the load average history may be obtained with
|
||||
.Bd -literal -offset indent -compact
|
||||
sysctl vm.loadavg
|
||||
.Ed
|
||||
.Sh FILES
|
||||
.Bl -tag -width <netinet/icmpXvar.h> -compact
|
||||
.It Pa <sys/sysctl.h>
|
||||
definitions for top level identifiers, second level kernel and hardware
|
||||
identifiers, and user level identifiers
|
||||
.It Pa <sys/socket.h>
|
||||
definitions for second level network identifiers
|
||||
.It Pa <sys/gmon.h>
|
||||
definitions for third level profiling identifiers
|
||||
.It Pa <vm/vm_param.h>
|
||||
definitions for second level virtual memory identifiers
|
||||
.It Pa <netinet/in.h>
|
||||
definitions for third level Internet identifiers and
|
||||
fourth level IP identifiers
|
||||
.It Pa <netinet/icmp_var.h>
|
||||
definitions for fourth level ICMP identifiers
|
||||
.It Pa <netinet/udp_var.h>
|
||||
definitions for fourth level UDP identifiers
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr sysctl 3
|
||||
.Sh HISTORY
|
||||
.Nm sysctl
|
||||
first appeared in 4.4BSD.
|
644
sbin/sysctl/sysctl.c
Normal file
644
sbin/sysctl/sysctl.c
Normal file
@ -0,0 +1,644 @@
|
||||
/*
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)sysctl.c 8.5 (Berkeley) 5/9/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/gmon.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/icmp_var.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/udp_var.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct ctlname topname[] = CTL_NAMES;
|
||||
struct ctlname kernname[] = CTL_KERN_NAMES;
|
||||
struct ctlname vmname[] = CTL_VM_NAMES;
|
||||
struct ctlname netname[] = CTL_NET_NAMES;
|
||||
struct ctlname hwname[] = CTL_HW_NAMES;
|
||||
struct ctlname username[] = CTL_USER_NAMES;
|
||||
struct ctlname debugname[CTL_DEBUG_MAXID];
|
||||
struct ctlname *vfsname;
|
||||
#ifdef CTL_MACHDEP_NAMES
|
||||
struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
|
||||
#endif
|
||||
char names[BUFSIZ];
|
||||
int lastused;
|
||||
|
||||
struct list {
|
||||
struct ctlname *list;
|
||||
int size;
|
||||
};
|
||||
struct list toplist = { topname, CTL_MAXID };
|
||||
struct list secondlevel[] = {
|
||||
{ 0, 0 }, /* CTL_UNSPEC */
|
||||
{ kernname, KERN_MAXID }, /* CTL_KERN */
|
||||
{ vmname, VM_MAXID }, /* CTL_VM */
|
||||
{ 0, 0 }, /* CTL_VFS */
|
||||
{ netname, NET_MAXID }, /* CTL_NET */
|
||||
{ 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */
|
||||
{ hwname, HW_MAXID }, /* CTL_HW */
|
||||
#ifdef CTL_MACHDEP_NAMES
|
||||
{ machdepname, CPU_MAXID }, /* CTL_MACHDEP */
|
||||
#else
|
||||
{ 0, 0 }, /* CTL_MACHDEP */
|
||||
#endif
|
||||
{ username, USER_MAXID }, /* CTL_USER_NAMES */
|
||||
};
|
||||
|
||||
int Aflag, aflag, nflag, wflag;
|
||||
|
||||
/*
|
||||
* Variables requiring special processing.
|
||||
*/
|
||||
#define CLOCK 0x00000001
|
||||
#define BOOTTIME 0x00000002
|
||||
#define CONSDEV 0x00000004
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
int ch, lvl1;
|
||||
|
||||
while ((ch = getopt(argc, argv, "Aanw")) != EOF) {
|
||||
switch (ch) {
|
||||
|
||||
case 'A':
|
||||
Aflag = 1;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
aflag = 1;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
wflag = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0 && (Aflag || aflag)) {
|
||||
debuginit();
|
||||
vfsinit();
|
||||
for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
|
||||
listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
|
||||
exit(0);
|
||||
}
|
||||
if (argc == 0)
|
||||
usage();
|
||||
for (; *argv != NULL; ++argv)
|
||||
parse(*argv, 1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* List all variables known to the system.
|
||||
*/
|
||||
listall(prefix, lp)
|
||||
char *prefix;
|
||||
struct list *lp;
|
||||
{
|
||||
int lvl2;
|
||||
char *cp, name[BUFSIZ];
|
||||
|
||||
if (lp->list == 0)
|
||||
return;
|
||||
strcpy(name, prefix);
|
||||
cp = &name[strlen(name)];
|
||||
*cp++ = '.';
|
||||
for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
|
||||
if (lp->list[lvl2].ctl_name == 0)
|
||||
continue;
|
||||
strcpy(cp, lp->list[lvl2].ctl_name);
|
||||
parse(name, Aflag);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a name into a MIB entry.
|
||||
* Lookup and print out the MIB entry if it exists.
|
||||
* Set a new value if requested.
|
||||
*/
|
||||
parse(string, flags)
|
||||
char *string;
|
||||
int flags;
|
||||
{
|
||||
int indx, type, state, len;
|
||||
size_t size;
|
||||
int special = 0;
|
||||
void *newval = 0;
|
||||
int intval, newsize = 0;
|
||||
quad_t quadval;
|
||||
struct list *lp;
|
||||
struct vfsconf vfc;
|
||||
int mib[CTL_MAXNAME];
|
||||
char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ];
|
||||
|
||||
bufp = buf;
|
||||
snprintf(buf, BUFSIZ, "%s", string);
|
||||
if ((cp = strchr(string, '=')) != NULL) {
|
||||
if (!wflag) {
|
||||
fprintf(stderr, "Must specify -w to set variables\n");
|
||||
exit(2);
|
||||
}
|
||||
*strchr(buf, '=') = '\0';
|
||||
*cp++ = '\0';
|
||||
while (isspace(*cp))
|
||||
cp++;
|
||||
newval = cp;
|
||||
newsize = strlen(cp);
|
||||
}
|
||||
if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
|
||||
return;
|
||||
mib[0] = indx;
|
||||
if (indx == CTL_VFS)
|
||||
vfsinit();
|
||||
if (indx == CTL_DEBUG)
|
||||
debuginit();
|
||||
lp = &secondlevel[indx];
|
||||
if (lp->list == 0) {
|
||||
fprintf(stderr, "%s: class is not implemented\n",
|
||||
topname[indx]);
|
||||
return;
|
||||
}
|
||||
if (bufp == NULL) {
|
||||
listall(topname[indx].ctl_name, lp);
|
||||
return;
|
||||
}
|
||||
if ((indx = findname(string, "second", &bufp, lp)) == -1)
|
||||
return;
|
||||
mib[1] = indx;
|
||||
type = lp->list[indx].ctl_type;
|
||||
len = 2;
|
||||
switch (mib[0]) {
|
||||
|
||||
case CTL_KERN:
|
||||
switch (mib[1]) {
|
||||
case KERN_PROF:
|
||||
mib[2] = GPROF_STATE;
|
||||
size = sizeof state;
|
||||
if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
|
||||
if (flags == 0)
|
||||
return;
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: ", string);
|
||||
fprintf(stderr,
|
||||
"kernel is not compiled for profiling\n");
|
||||
return;
|
||||
}
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: %s\n", string,
|
||||
state == GMON_PROF_OFF ? "off" : "running");
|
||||
return;
|
||||
case KERN_VNODE:
|
||||
case KERN_FILE:
|
||||
if (flags == 0)
|
||||
return;
|
||||
fprintf(stderr,
|
||||
"Use pstat to view %s information\n", string);
|
||||
return;
|
||||
case KERN_PROC:
|
||||
if (flags == 0)
|
||||
return;
|
||||
fprintf(stderr,
|
||||
"Use ps to view %s information\n", string);
|
||||
return;
|
||||
case KERN_CLOCKRATE:
|
||||
special |= CLOCK;
|
||||
break;
|
||||
case KERN_BOOTTIME:
|
||||
special |= BOOTTIME;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CTL_HW:
|
||||
break;
|
||||
|
||||
case CTL_VM:
|
||||
if (mib[1] == VM_LOADAVG) {
|
||||
double loads[3];
|
||||
|
||||
getloadavg(loads, 3);
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: ", string);
|
||||
fprintf(stdout, "%.2f %.2f %.2f\n",
|
||||
loads[0], loads[1], loads[2]);
|
||||
return;
|
||||
}
|
||||
if (flags == 0)
|
||||
return;
|
||||
fprintf(stderr,
|
||||
"Use vmstat or systat to view %s information\n", string);
|
||||
return;
|
||||
|
||||
case CTL_NET:
|
||||
if (mib[1] == PF_INET) {
|
||||
len = sysctl_inet(string, &bufp, mib, flags, &type);
|
||||
if (len >= 0)
|
||||
break;
|
||||
return;
|
||||
}
|
||||
if (flags == 0)
|
||||
return;
|
||||
fprintf(stderr, "Use netstat to view %s information\n", string);
|
||||
return;
|
||||
|
||||
case CTL_DEBUG:
|
||||
mib[2] = CTL_DEBUG_VALUE;
|
||||
len = 3;
|
||||
break;
|
||||
|
||||
case CTL_MACHDEP:
|
||||
#ifdef CPU_CONSDEV
|
||||
if (mib[1] == CPU_CONSDEV)
|
||||
special |= CONSDEV;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case CTL_VFS:
|
||||
mib[3] = mib[1];
|
||||
mib[1] = VFS_GENERIC;
|
||||
mib[2] = VFS_CONF;
|
||||
len = 4;
|
||||
size = sizeof vfc;
|
||||
if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
|
||||
perror("vfs print");
|
||||
return;
|
||||
}
|
||||
if (flags == 0 && vfc.vfc_refcount == 0)
|
||||
return;
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s has %d mounted instance%s\n",
|
||||
string, vfc.vfc_refcount,
|
||||
vfc.vfc_refcount != 1 ? "s" : "");
|
||||
else
|
||||
fprintf(stdout, "%d\n", vfc.vfc_refcount);
|
||||
return;
|
||||
|
||||
case CTL_USER:
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Illegal top level value: %d\n", mib[0]);
|
||||
return;
|
||||
|
||||
}
|
||||
if (bufp) {
|
||||
fprintf(stderr, "name %s in %s is unknown\n", *bufp, string);
|
||||
return;
|
||||
}
|
||||
if (newsize > 0) {
|
||||
switch (type) {
|
||||
case CTLTYPE_INT:
|
||||
intval = atoi(newval);
|
||||
newval = &intval;
|
||||
newsize = sizeof intval;
|
||||
break;
|
||||
|
||||
case CTLTYPE_QUAD:
|
||||
sscanf(newval, "%qd", &quadval);
|
||||
newval = &quadval;
|
||||
newsize = sizeof quadval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
size = BUFSIZ;
|
||||
if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
|
||||
if (flags == 0)
|
||||
return;
|
||||
switch (errno) {
|
||||
case EOPNOTSUPP:
|
||||
fprintf(stderr, "%s: value is not available\n", string);
|
||||
return;
|
||||
case ENOTDIR:
|
||||
fprintf(stderr, "%s: specification is incomplete\n",
|
||||
string);
|
||||
return;
|
||||
case ENOMEM:
|
||||
fprintf(stderr, "%s: type is unknown to this program\n",
|
||||
string);
|
||||
return;
|
||||
default:
|
||||
perror(string);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (special & CLOCK) {
|
||||
struct clockinfo *clkp = (struct clockinfo *)buf;
|
||||
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: ", string);
|
||||
fprintf(stdout,
|
||||
"hz = %d, tick = %d, profhz = %d, stathz = %d\n",
|
||||
clkp->hz, clkp->tick, clkp->profhz, clkp->stathz);
|
||||
return;
|
||||
}
|
||||
if (special & BOOTTIME) {
|
||||
struct timeval *btp = (struct timeval *)buf;
|
||||
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s = %s\n", string,
|
||||
ctime(&btp->tv_sec));
|
||||
else
|
||||
fprintf(stdout, "%d\n", btp->tv_sec);
|
||||
return;
|
||||
}
|
||||
if (special & CONSDEV) {
|
||||
dev_t dev = *(dev_t *)buf;
|
||||
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s = %s\n", string,
|
||||
devname(dev, S_IFCHR));
|
||||
else
|
||||
fprintf(stdout, "0x%x\n", dev);
|
||||
return;
|
||||
}
|
||||
switch (type) {
|
||||
case CTLTYPE_INT:
|
||||
if (newsize == 0) {
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s = ", string);
|
||||
fprintf(stdout, "%d\n", *(int *)buf);
|
||||
} else {
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: %d -> ", string,
|
||||
*(int *)buf);
|
||||
fprintf(stdout, "%d\n", *(int *)newval);
|
||||
}
|
||||
return;
|
||||
|
||||
case CTLTYPE_STRING:
|
||||
if (newsize == 0) {
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s = ", string);
|
||||
fprintf(stdout, "%s\n", buf);
|
||||
} else {
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: %s -> ", string, buf);
|
||||
fprintf(stdout, "%s\n", newval);
|
||||
}
|
||||
return;
|
||||
|
||||
case CTLTYPE_QUAD:
|
||||
if (newsize == 0) {
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s = ", string);
|
||||
fprintf(stdout, "%qd\n", *(quad_t *)buf);
|
||||
} else {
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: %qd -> ", string,
|
||||
*(quad_t *)buf);
|
||||
fprintf(stdout, "%qd\n", *(quad_t *)newval);
|
||||
}
|
||||
return;
|
||||
|
||||
case CTLTYPE_STRUCT:
|
||||
fprintf(stderr, "%s: unknown structure returned\n",
|
||||
string);
|
||||
return;
|
||||
|
||||
default:
|
||||
case CTLTYPE_NODE:
|
||||
fprintf(stderr, "%s: unknown type returned\n",
|
||||
string);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the set of debugging names
|
||||
*/
|
||||
debuginit()
|
||||
{
|
||||
int mib[3], loc, i;
|
||||
size_t size;
|
||||
|
||||
if (secondlevel[CTL_DEBUG].list != 0)
|
||||
return;
|
||||
secondlevel[CTL_DEBUG].list = debugname;
|
||||
mib[0] = CTL_DEBUG;
|
||||
mib[2] = CTL_DEBUG_NAME;
|
||||
for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
|
||||
mib[1] = i;
|
||||
size = BUFSIZ - loc;
|
||||
if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
|
||||
continue;
|
||||
debugname[i].ctl_name = &names[loc];
|
||||
debugname[i].ctl_type = CTLTYPE_INT;
|
||||
loc += size;
|
||||
}
|
||||
lastused = loc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the set of filesystem names
|
||||
*/
|
||||
vfsinit()
|
||||
{
|
||||
int mib[4], maxtypenum, cnt, loc, size;
|
||||
struct vfsconf vfc;
|
||||
size_t buflen;
|
||||
|
||||
if (secondlevel[CTL_VFS].list != 0)
|
||||
return;
|
||||
mib[0] = CTL_VFS;
|
||||
mib[1] = VFS_GENERIC;
|
||||
mib[2] = VFS_MAXTYPENUM;
|
||||
buflen = 4;
|
||||
if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
|
||||
return;
|
||||
if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == 0)
|
||||
return;
|
||||
memset(vfsname, 0, maxtypenum * sizeof(*vfsname));
|
||||
mib[2] = VFS_CONF;
|
||||
buflen = sizeof vfc;
|
||||
for (loc = lastused, cnt = 0; cnt < maxtypenum; cnt++) {
|
||||
mib[3] = cnt;
|
||||
if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
|
||||
if (errno == EOPNOTSUPP)
|
||||
continue;
|
||||
perror("vfsinit");
|
||||
free(vfsname);
|
||||
return;
|
||||
}
|
||||
strcat(&names[loc], vfc.vfc_name);
|
||||
vfsname[cnt].ctl_name = &names[loc];
|
||||
vfsname[cnt].ctl_type = CTLTYPE_INT;
|
||||
size = strlen(vfc.vfc_name) + 1;
|
||||
loc += size;
|
||||
}
|
||||
lastused = loc;
|
||||
secondlevel[CTL_VFS].list = vfsname;
|
||||
secondlevel[CTL_VFS].size = maxtypenum;
|
||||
return;
|
||||
}
|
||||
|
||||
struct ctlname inetname[] = CTL_IPPROTO_NAMES;
|
||||
struct ctlname ipname[] = IPCTL_NAMES;
|
||||
struct ctlname icmpname[] = ICMPCTL_NAMES;
|
||||
struct ctlname udpname[] = UDPCTL_NAMES;
|
||||
struct list inetlist = { inetname, IPPROTO_MAXID };
|
||||
struct list inetvars[] = {
|
||||
{ ipname, IPCTL_MAXID }, /* ip */
|
||||
{ icmpname, ICMPCTL_MAXID }, /* icmp */
|
||||
{ 0, 0 }, /* igmp */
|
||||
{ 0, 0 }, /* ggmp */
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 }, /* tcp */
|
||||
{ 0, 0 },
|
||||
{ 0, 0 }, /* egp */
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 }, /* pup */
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ udpname, UDPCTL_MAXID }, /* udp */
|
||||
};
|
||||
|
||||
/*
|
||||
* handle internet requests
|
||||
*/
|
||||
sysctl_inet(string, bufpp, mib, flags, typep)
|
||||
char *string;
|
||||
char **bufpp;
|
||||
int mib[];
|
||||
int flags;
|
||||
int *typep;
|
||||
{
|
||||
struct list *lp;
|
||||
int indx;
|
||||
|
||||
if (*bufpp == NULL) {
|
||||
listall(string, &inetlist);
|
||||
return (-1);
|
||||
}
|
||||
if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
|
||||
return (-1);
|
||||
mib[2] = indx;
|
||||
if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL)
|
||||
lp = &inetvars[indx];
|
||||
else if (!flags)
|
||||
return (-1);
|
||||
else {
|
||||
fprintf(stderr, "%s: no variables defined for this protocol\n",
|
||||
string);
|
||||
return (-1);
|
||||
}
|
||||
if (*bufpp == NULL) {
|
||||
listall(string, lp);
|
||||
return (-1);
|
||||
}
|
||||
if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
|
||||
return (-1);
|
||||
mib[3] = indx;
|
||||
*typep = lp->list[indx].ctl_type;
|
||||
return (4);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan a list of names searching for a particular name.
|
||||
*/
|
||||
findname(string, level, bufp, namelist)
|
||||
char *string;
|
||||
char *level;
|
||||
char **bufp;
|
||||
struct list *namelist;
|
||||
{
|
||||
char *name;
|
||||
int i;
|
||||
|
||||
if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
|
||||
fprintf(stderr, "%s: incomplete specification\n", string);
|
||||
return (-1);
|
||||
}
|
||||
for (i = 0; i < namelist->size; i++)
|
||||
if (namelist->list[i].ctl_name != NULL &&
|
||||
strcmp(name, namelist->list[i].ctl_name) == 0)
|
||||
break;
|
||||
if (i == namelist->size) {
|
||||
fprintf(stderr, "%s level name %s in %s is invalid\n",
|
||||
level, name, string);
|
||||
return (-1);
|
||||
}
|
||||
return (i);
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
|
||||
"sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
|
||||
"sysctl [-n] -a", "sysctl [-n] -A");
|
||||
exit(1);
|
||||
}
|
1820
usr.sbin/amd/amd/afs_ops.c
Normal file
1820
usr.sbin/amd/amd/afs_ops.c
Normal file
File diff suppressed because it is too large
Load Diff
233
usr.sbin/amd/amd/amd.8
Normal file
233
usr.sbin/amd/amd/amd.8
Normal file
@ -0,0 +1,233 @@
|
||||
.\"
|
||||
.\" Copyright (c) 1989 Jan-Simon Pendry
|
||||
.\" Copyright (c) 1989 Imperial College of Science, Technology & Medicine
|
||||
.\" Copyright (c) 1989, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" Jan-Simon Pendry at Imperial College, London.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)amd.8 5.11 (Berkeley) 6/1/94
|
||||
.\"
|
||||
.\" $Id: amd.8,v 5.2.2.1 1992/02/09 15:11:39 jsp beta $
|
||||
.\"
|
||||
.Dd "June 1, 1994"
|
||||
.Dt AMD 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm amd
|
||||
.Nd automatically mount file systems
|
||||
.Sh SYNOPSIS
|
||||
.Nm amd
|
||||
.Op Fl nprv
|
||||
.Op Fl a Ar mount_point
|
||||
.Op Fl c Ar duration
|
||||
.Op Fl d Ar domain
|
||||
.Bk -words
|
||||
.Op Fl k Ar kernel-arch
|
||||
.Ek
|
||||
.Op Fl l Ar logfile
|
||||
.Op Fl t Ar interval.interval
|
||||
.Bk -words
|
||||
.Op Fl w Ar interval
|
||||
.Ek
|
||||
.Op Fl x Ar log-option
|
||||
.Op Fl y Ar YP-domain
|
||||
.Bk -words
|
||||
.Op Fl C Ar cluster-name
|
||||
.Ek
|
||||
.Op Fl D Ar option
|
||||
.Oo
|
||||
.Ar directory mapname
|
||||
.Op Fl map-options
|
||||
.Oc
|
||||
.Ar ...
|
||||
.Sh DESCRIPTION
|
||||
.Nm Amd
|
||||
is a daemon that automatically mounts filesystems
|
||||
whenever a file or directory
|
||||
within that filesystem is accessed.
|
||||
Filesystems are automatically unmounted when they
|
||||
appear to be quiescent.
|
||||
.Pp
|
||||
.Nm Amd
|
||||
operates by attaching itself as an
|
||||
.Tn NFS
|
||||
server to each of the specified
|
||||
.Ar directories .
|
||||
Lookups within the specified directories
|
||||
are handled by
|
||||
.Nm amd ,
|
||||
which uses the map defined by
|
||||
.Ar mapname
|
||||
to determine how to resolve the lookup.
|
||||
Generally, this will be a host name, some filesystem information
|
||||
and some mount options for the given filesystem.
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a Ar temporary-directory
|
||||
Specify an alternative location for the real mount points.
|
||||
The default is
|
||||
.Pa /a .
|
||||
.It Fl c Ar duration
|
||||
Specify a
|
||||
.Ar duration ,
|
||||
in seconds, that a looked up name remains
|
||||
cached when not in use. The default is 5 minutes.
|
||||
.It Fl d Ar domain
|
||||
Specify the local domain name. If this option is not
|
||||
given the domain name is determined from the hostname.
|
||||
.It Fl k Ar kernel-arch
|
||||
Specifies the kernel architecture. This is used solely
|
||||
to set the ${karch} selector.
|
||||
.It Fl l Ar logfile
|
||||
Specify a logfile in which to record mount and unmount events.
|
||||
If
|
||||
.Ar logfile
|
||||
is the string
|
||||
.Em syslog ,
|
||||
the log messages will be sent to the system log daemon by
|
||||
.Xr syslog 3 .
|
||||
.It Fl n
|
||||
Normalize hostnames.
|
||||
The name referred to by ${rhost} is normalized relative to the
|
||||
host database before being used. The effect is to translate
|
||||
aliases into ``official'' names.
|
||||
.It Fl p
|
||||
Print
|
||||
.Em PID .
|
||||
Outputs the process-id of
|
||||
.Nm amd
|
||||
to standard output where it can be saved into a file.
|
||||
.It Fl r
|
||||
Restart existing mounts.
|
||||
.Nm Amd
|
||||
will scan the mount file table to determine which filesystems
|
||||
are currently mounted. Whenever one of these would have
|
||||
been auto-mounted,
|
||||
.Nm amd
|
||||
.Em inherits
|
||||
it.
|
||||
.It Fl t Ar interval.interval
|
||||
Specify the
|
||||
.Ar interval ,
|
||||
in tenths of a second, between
|
||||
.Tn NFS/RPC/UDP
|
||||
retries.
|
||||
The default is 0.8 seconds.
|
||||
The second values alters the retransmit counter.
|
||||
Useful defaults are supplied if either or both
|
||||
values are missing.
|
||||
.It Fl v
|
||||
Version. Displays version and configuration information on standard error.
|
||||
.ne 1i
|
||||
.It Fl w Ar interval
|
||||
Specify an
|
||||
.Ar interval ,
|
||||
in seconds, between attempts to dismount
|
||||
filesystems that have exceeded their cached times.
|
||||
The default is 2 minutes.
|
||||
.It Fl y Ar domain
|
||||
Specify an alternative
|
||||
.Tn NIS
|
||||
domain from which to fetch the
|
||||
.Tn NIS
|
||||
maps.
|
||||
The default is the system domain name.
|
||||
This option is ignored if
|
||||
.Tn NIS
|
||||
support is not available.
|
||||
.It Fl x Ar options
|
||||
Specify run-time logging options. The options are a comma separated
|
||||
list chosen from: fatal, error, user, warn, info, map, stats, all.
|
||||
.It Fl D Ar option
|
||||
Select from a variety of debug options. Prefixing an
|
||||
option with the string
|
||||
.Em no
|
||||
reverses the effect of that option. Options are cumulative.
|
||||
The most useful option is
|
||||
.Ar all .
|
||||
.El
|
||||
.Pp
|
||||
Since
|
||||
.Fl D
|
||||
is only used for debugging other options are not documented here:
|
||||
the current supported set of options is listed by the
|
||||
.Fl v
|
||||
option
|
||||
and a fuller description is available in the program source.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /axx
|
||||
.It Pa /a
|
||||
directory under which filesystems are dynamically mounted
|
||||
.El
|
||||
.Sh CAVEATS
|
||||
Some care may be required when creating a mount map.
|
||||
.Pp
|
||||
Symbolic links on an
|
||||
.Tn NFS
|
||||
filesystem can be incredibly inefficient.
|
||||
In most implementations of
|
||||
.Tn NFS ,
|
||||
their interpolations are not cached by
|
||||
the kernel and each time a symbolic link is
|
||||
encountered during a
|
||||
.Em lookuppn
|
||||
translation it costs an
|
||||
.Tn RPC
|
||||
call to the
|
||||
.Tn NFS
|
||||
server.
|
||||
A large improvement in real-time
|
||||
performance could be gained by adding a cache somewhere.
|
||||
Replacing
|
||||
.Xr symlinks 2
|
||||
with a suitable incarnation of the auto-mounter
|
||||
results in a large real-time speedup, but also causes a large
|
||||
number of process context switches.
|
||||
.Pp
|
||||
A weird imagination is most useful to gain full advantage of all
|
||||
the features.
|
||||
.Sh SEE ALSO
|
||||
.Xr amq 8 ,
|
||||
.Xr hostname 1 ,
|
||||
.Xr mount 8 ,
|
||||
.Xr umount 8 ,
|
||||
.Rs
|
||||
.%T Amd \- The 4.4 BSD Automounter
|
||||
.Re
|
||||
.Sh AUTHOR
|
||||
.An Jan-Simon Pendry
|
||||
<jsp@doc.ic.ac.uk>, Department of Computing, Imperial College, London, UK.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm amd
|
||||
utility first appeared in 4.4BSD.
|
811
usr.sbin/amd/amd/nfs_ops.c
Normal file
811
usr.sbin/amd/amd/nfs_ops.c
Normal file
@ -0,0 +1,811 @@
|
||||
/*-
|
||||
* Copyright (c) 1990 Jan-Simon Pendry
|
||||
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Jan-Simon Pendry at Imperial College, London.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id: nfs_ops.c,v 5.2.2.2 1992/05/31 16:35:05 jsp Exp $
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)nfs_ops.c 8.2 (Berkeley) 5/10/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include "am.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef HAS_NFS
|
||||
|
||||
#define NFS
|
||||
#define NFSCLIENT
|
||||
#ifdef NFS_3
|
||||
typedef nfs_fh fhandle_t;
|
||||
#endif /* NFS_3 */
|
||||
#include <sys/mount.h>
|
||||
#ifdef NFS_HDR
|
||||
#include NFS_HDR
|
||||
#endif /* NFS_HDR */
|
||||
#include "mount.h"
|
||||
|
||||
/*
|
||||
* Network file system
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert from nfsstat to UN*X error code
|
||||
*/
|
||||
#define unx_error(e) ((int)(e))
|
||||
|
||||
/*
|
||||
* The NFS layer maintains a cache of file handles.
|
||||
* This is *fundamental* to the implementation and
|
||||
* also allows quick remounting when a filesystem
|
||||
* is accessed soon after timing out.
|
||||
*
|
||||
* The NFS server layer knows to flush this cache
|
||||
* when a server goes down so avoiding stale handles.
|
||||
*
|
||||
* Each cache entry keeps a hard reference to
|
||||
* the corresponding server. This ensures that
|
||||
* the server keepalive information is maintained.
|
||||
*
|
||||
* The copy of the sockaddr_in here is taken so
|
||||
* that the port can be twiddled to talk to mountd
|
||||
* instead of portmap or the NFS server as used
|
||||
* elsewhere.
|
||||
* The port# is flushed if a server goes down.
|
||||
* The IP address is never flushed - we assume
|
||||
* that the address of a mounted machine never
|
||||
* changes. If it does, then you have other
|
||||
* problems...
|
||||
*/
|
||||
typedef struct fh_cache fh_cache;
|
||||
struct fh_cache {
|
||||
qelem fh_q; /* List header */
|
||||
voidp fh_wchan; /* Wait channel */
|
||||
int fh_error; /* Valid data? */
|
||||
int fh_id; /* Unique id */
|
||||
int fh_cid; /* Callout id */
|
||||
struct fhstatus fh_handle; /* Handle on filesystem */
|
||||
struct sockaddr_in fh_sin; /* Address of mountd */
|
||||
fserver *fh_fs; /* Server holding filesystem */
|
||||
char *fh_path; /* Filesystem on host */
|
||||
};
|
||||
|
||||
/*
|
||||
* FH_TTL is the time a file handle will remain in the cache since
|
||||
* last being used. If the file handle becomes invalid, then it
|
||||
* will be flushed anyway.
|
||||
*/
|
||||
#define FH_TTL (5 * 60) /* five minutes */
|
||||
#define FH_TTL_ERROR (30) /* 30 seconds */
|
||||
|
||||
static int fh_id = 0;
|
||||
#define FHID_ALLOC() (++fh_id)
|
||||
extern qelem fh_head;
|
||||
qelem fh_head = { &fh_head, &fh_head };
|
||||
|
||||
static int call_mountd P((fh_cache*, unsigned long, fwd_fun, voidp));
|
||||
|
||||
AUTH *nfs_auth;
|
||||
|
||||
static fh_cache *find_nfs_fhandle_cache P((voidp idv, int done));
|
||||
static fh_cache *find_nfs_fhandle_cache(idv, done)
|
||||
voidp idv;
|
||||
int done;
|
||||
{
|
||||
fh_cache *fp, *fp2 = 0;
|
||||
int id = (int) idv;
|
||||
|
||||
ITER(fp, fh_cache, &fh_head) {
|
||||
if (fp->fh_id == id) {
|
||||
fp2 = fp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (fp2) {
|
||||
dlog("fh cache gives fp %#x, fs %s", fp2, fp2->fh_path);
|
||||
} else {
|
||||
dlog("fh cache search failed");
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
if (fp2 && !done) {
|
||||
fp2->fh_error = ETIMEDOUT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return fp2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when a filehandle appears
|
||||
*/
|
||||
static void got_nfs_fh P((voidp pkt, int len, struct sockaddr_in *sa,
|
||||
struct sockaddr_in *ia, voidp idv, int done));
|
||||
static void got_nfs_fh(pkt, len, sa, ia, idv, done)
|
||||
voidp pkt;
|
||||
int len;
|
||||
struct sockaddr_in *sa, *ia;
|
||||
voidp idv;
|
||||
int done;
|
||||
{
|
||||
fh_cache *fp = find_nfs_fhandle_cache(idv, done);
|
||||
if (fp) {
|
||||
fp->fh_error = pickup_rpc_reply(pkt, len, (voidp) &fp->fh_handle, xdr_fhstatus);
|
||||
if (!fp->fh_error) {
|
||||
#ifdef DEBUG
|
||||
dlog("got filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
|
||||
#endif /* DEBUG */
|
||||
/*
|
||||
* Wakeup anything sleeping on this filehandle
|
||||
*/
|
||||
if (fp->fh_wchan) {
|
||||
#ifdef DEBUG
|
||||
dlog("Calling wakeup on %#x", fp->fh_wchan);
|
||||
#endif /* DEBUG */
|
||||
wakeup(fp->fh_wchan);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flush_nfs_fhandle_cache P((fserver *fs));
|
||||
void flush_nfs_fhandle_cache(fs)
|
||||
fserver *fs;
|
||||
{
|
||||
fh_cache *fp;
|
||||
ITER(fp, fh_cache, &fh_head) {
|
||||
if (fp->fh_fs == fs || fs == 0) {
|
||||
fp->fh_sin.sin_port = (u_short) 0;
|
||||
fp->fh_error = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void discard_fh P((fh_cache *fp));
|
||||
static void discard_fh(fp)
|
||||
fh_cache *fp;
|
||||
{
|
||||
rem_que(&fp->fh_q);
|
||||
#ifdef DEBUG
|
||||
dlog("Discarding filehandle for %s:%s", fp->fh_fs->fs_host, fp->fh_path);
|
||||
#endif /* DEBUG */
|
||||
free_srvr(fp->fh_fs);
|
||||
free((voidp) fp->fh_path);
|
||||
free((voidp) fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the file handle for a node
|
||||
*/
|
||||
static int prime_nfs_fhandle_cache P((char *path, fserver *fs, struct fhstatus *fhbuf, voidp wchan));
|
||||
static int prime_nfs_fhandle_cache(path, fs, fhbuf, wchan)
|
||||
char *path;
|
||||
fserver *fs;
|
||||
struct fhstatus *fhbuf;
|
||||
voidp wchan;
|
||||
{
|
||||
fh_cache *fp, *fp_save = 0;
|
||||
int error;
|
||||
int reuse_id = FALSE;
|
||||
|
||||
#ifdef DEBUG
|
||||
dlog("Searching cache for %s:%s", fs->fs_host, path);
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* First search the cache
|
||||
*/
|
||||
ITER(fp, fh_cache, &fh_head) {
|
||||
if (fs == fp->fh_fs && strcmp(path, fp->fh_path) == 0) {
|
||||
switch (fp->fh_error) {
|
||||
case 0:
|
||||
error = fp->fh_error = unx_error(fp->fh_handle.fhs_status);
|
||||
if (error == 0) {
|
||||
if (fhbuf)
|
||||
bcopy((voidp) &fp->fh_handle, (voidp) fhbuf,
|
||||
sizeof(fp->fh_handle));
|
||||
if (fp->fh_cid)
|
||||
untimeout(fp->fh_cid);
|
||||
fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);
|
||||
} else if (error == EACCES) {
|
||||
/*
|
||||
* Now decode the file handle return code.
|
||||
*/
|
||||
plog(XLOG_INFO, "Filehandle denied for \"%s:%s\"",
|
||||
fs->fs_host, path);
|
||||
} else {
|
||||
errno = error; /* XXX */
|
||||
plog(XLOG_INFO, "Filehandle error for \"%s:%s\": %m",
|
||||
fs->fs_host, path);
|
||||
}
|
||||
|
||||
/*
|
||||
* The error was returned from the remote mount daemon.
|
||||
* Policy: this error will be cached for now...
|
||||
*/
|
||||
return error;
|
||||
|
||||
case -1:
|
||||
/*
|
||||
* Still thinking about it, but we can re-use.
|
||||
*/
|
||||
fp_save = fp;
|
||||
reuse_id = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* Return the error.
|
||||
* Policy: make sure we recompute if required again
|
||||
* in case this was caused by a network failure.
|
||||
* This can thrash mountd's though... If you find
|
||||
* your mountd going slowly then:
|
||||
* 1. Add a fork() loop to main.
|
||||
* 2. Remove the call to innetgr() and don't use
|
||||
* netgroups, especially if you don't use YP.
|
||||
*/
|
||||
error = fp->fh_error;
|
||||
fp->fh_error = -1;
|
||||
return error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Not in cache
|
||||
*/
|
||||
if (fp_save) {
|
||||
fp = fp_save;
|
||||
/*
|
||||
* Re-use existing slot
|
||||
*/
|
||||
untimeout(fp->fh_cid);
|
||||
free_srvr(fp->fh_fs);
|
||||
free(fp->fh_path);
|
||||
} else {
|
||||
fp = ALLOC(fh_cache);
|
||||
bzero((voidp) fp, sizeof(*fp));
|
||||
ins_que(&fp->fh_q, &fh_head);
|
||||
}
|
||||
if (!reuse_id)
|
||||
fp->fh_id = FHID_ALLOC();
|
||||
fp->fh_wchan = wchan;
|
||||
fp->fh_error = -1;
|
||||
fp->fh_cid = timeout(FH_TTL, discard_fh, (voidp) fp);
|
||||
|
||||
/*
|
||||
* If the address has changed then don't try to re-use the
|
||||
* port information
|
||||
*/
|
||||
if (fp->fh_sin.sin_addr.s_addr != fs->fs_ip->sin_addr.s_addr) {
|
||||
fp->fh_sin = *fs->fs_ip;
|
||||
fp->fh_sin.sin_port = 0;
|
||||
}
|
||||
fp->fh_fs = dup_srvr(fs);
|
||||
fp->fh_path = strdup(path);
|
||||
|
||||
error = call_mountd(fp, MOUNTPROC_MNT, got_nfs_fh, wchan);
|
||||
if (error) {
|
||||
/*
|
||||
* Local error - cache for a short period
|
||||
* just to prevent thrashing.
|
||||
*/
|
||||
untimeout(fp->fh_cid);
|
||||
fp->fh_cid = timeout(error < 0 ? 2 * ALLOWED_MOUNT_TIME : FH_TTL_ERROR,
|
||||
discard_fh, (voidp) fp);
|
||||
fp->fh_error = error;
|
||||
} else {
|
||||
error = fp->fh_error;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
int make_nfs_auth P((void))
|
||||
{
|
||||
#ifdef HAS_NFS_QUALIFIED_NAMES
|
||||
/*
|
||||
* From: Chris Metcalf <metcalf@masala.lcs.mit.edu>
|
||||
* Use hostd, not just hostname. Note that uids
|
||||
* and gids and the gidlist are type *int* and not the
|
||||
* system uid_t and gid_t types.
|
||||
*/
|
||||
static int group_wheel = 0;
|
||||
nfs_auth = authunix_create(hostd, 0, 0, 1, &group_wheel);
|
||||
#else
|
||||
nfs_auth = authunix_create_default();
|
||||
#endif
|
||||
if (!nfs_auth)
|
||||
return ENOBUFS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int call_mountd P((fh_cache *fp, u_long proc, fwd_fun f, voidp wchan));
|
||||
static int call_mountd(fp, proc, f, wchan)
|
||||
fh_cache *fp;
|
||||
u_long proc;
|
||||
fwd_fun f;
|
||||
voidp wchan;
|
||||
{
|
||||
struct rpc_msg mnt_msg;
|
||||
int len;
|
||||
char iobuf[8192];
|
||||
int error;
|
||||
|
||||
if (!nfs_auth) {
|
||||
error = make_nfs_auth();
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
if (fp->fh_sin.sin_port == 0) {
|
||||
u_short port;
|
||||
error = nfs_srvr_port(fp->fh_fs, &port, wchan);
|
||||
if (error)
|
||||
return error;
|
||||
fp->fh_sin.sin_port = port;
|
||||
}
|
||||
|
||||
rpc_msg_init(&mnt_msg, MOUNTPROG, MOUNTVERS, (unsigned long) 0);
|
||||
len = make_rpc_packet(iobuf, sizeof(iobuf), proc,
|
||||
&mnt_msg, (voidp) &fp->fh_path, xdr_nfspath, nfs_auth);
|
||||
|
||||
if (len > 0) {
|
||||
error = fwd_packet(MK_RPC_XID(RPC_XID_MOUNTD, fp->fh_id),
|
||||
(voidp) iobuf, len, &fp->fh_sin, &fp->fh_sin, (voidp) fp->fh_id, f);
|
||||
} else {
|
||||
error = -len;
|
||||
}
|
||||
/*
|
||||
* It may be the case that we're sending to the wrong MOUNTD port. This
|
||||
* occurs if mountd is restarted on the server after the port has been
|
||||
* looked up and stored in the filehandle cache somewhere. The correct
|
||||
* solution, if we're going to cache port numbers is to catch the ICMP
|
||||
* port unreachable reply from the server and cause the portmap request
|
||||
* to be redone. The quick solution here is to invalidate the MOUNTD
|
||||
* port.
|
||||
*/
|
||||
fp->fh_sin.sin_port = 0;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* NFS needs the local filesystem, remote filesystem
|
||||
* remote hostname.
|
||||
* Local filesystem defaults to remote and vice-versa.
|
||||
*/
|
||||
static char *nfs_match(fo)
|
||||
am_opts *fo;
|
||||
{
|
||||
char *xmtab;
|
||||
if (fo->opt_fs && !fo->opt_rfs)
|
||||
fo->opt_rfs = fo->opt_fs;
|
||||
if (!fo->opt_rfs) {
|
||||
plog(XLOG_USER, "nfs: no remote filesystem specified");
|
||||
return FALSE;
|
||||
}
|
||||
if (!fo->opt_rhost) {
|
||||
plog(XLOG_USER, "nfs: no remote host specified");
|
||||
return FALSE;
|
||||
}
|
||||
/*
|
||||
* Determine magic cookie to put in mtab
|
||||
*/
|
||||
xmtab = (char *) xmalloc(strlen(fo->opt_rhost) + strlen(fo->opt_rfs) + 2);
|
||||
sprintf(xmtab, "%s:%s", fo->opt_rhost, fo->opt_rfs);
|
||||
#ifdef DEBUG
|
||||
dlog("NFS: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"",
|
||||
fo->opt_rhost, fo->opt_rfs, fo->opt_fs);
|
||||
#endif /* DEBUG */
|
||||
|
||||
return xmtab;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise am structure for nfs
|
||||
*/
|
||||
static int nfs_init(mf)
|
||||
mntfs *mf;
|
||||
{
|
||||
if (!mf->mf_private) {
|
||||
int error;
|
||||
struct fhstatus fhs;
|
||||
|
||||
char *colon = strchr(mf->mf_info, ':');
|
||||
if (colon == 0)
|
||||
return ENOENT;
|
||||
|
||||
error = prime_nfs_fhandle_cache(colon+1, mf->mf_server, &fhs, (voidp) mf);
|
||||
if (!error) {
|
||||
mf->mf_private = (voidp) ALLOC(fhstatus);
|
||||
mf->mf_prfree = (void (*)()) free;
|
||||
bcopy((voidp) &fhs, mf->mf_private, sizeof(fhs));
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mount_nfs_fh P((struct fhstatus *fhp, char *dir, char *fs_name, char *opts, mntfs *mf));
|
||||
int mount_nfs_fh(fhp, dir, fs_name, opts, mf)
|
||||
struct fhstatus *fhp;
|
||||
char *dir;
|
||||
char *fs_name;
|
||||
char *opts;
|
||||
mntfs *mf;
|
||||
{
|
||||
struct nfs_args nfs_args;
|
||||
struct mntent mnt;
|
||||
int retry;
|
||||
char *colon;
|
||||
/*char *path;*/
|
||||
char host[MAXHOSTNAMELEN + MAXPATHLEN + 2];
|
||||
fserver *fs = mf->mf_server;
|
||||
int flags;
|
||||
char *xopts;
|
||||
int error;
|
||||
#ifdef notdef
|
||||
unsigned short port;
|
||||
#endif /* notdef */
|
||||
|
||||
MTYPE_TYPE type = MOUNT_TYPE_NFS;
|
||||
|
||||
bzero((voidp) &nfs_args, sizeof(nfs_args)); /* Paranoid */
|
||||
|
||||
/*
|
||||
* Extract host name to give to kernel
|
||||
*/
|
||||
if (!(colon = strchr(fs_name, ':')))
|
||||
return ENOENT;
|
||||
#ifndef NFS_ARGS_NEEDS_PATH
|
||||
*colon = '\0';
|
||||
#endif
|
||||
strncpy(host, fs_name, sizeof(host));
|
||||
#ifndef NFS_ARGS_NEEDS_PATH
|
||||
*colon = ':';
|
||||
#endif /* NFS_ARGS_NEEDS_PATH */
|
||||
/*path = colon + 1;*/
|
||||
|
||||
if (mf->mf_remopts && *mf->mf_remopts && !islocalnet(fs->fs_ip->sin_addr.s_addr))
|
||||
xopts = strdup(mf->mf_remopts);
|
||||
else
|
||||
xopts = strdup(opts);
|
||||
|
||||
mnt.mnt_dir = dir;
|
||||
mnt.mnt_fsname = fs_name;
|
||||
mnt.mnt_type = MTAB_TYPE_NFS;
|
||||
mnt.mnt_opts = xopts;
|
||||
mnt.mnt_freq = 0;
|
||||
mnt.mnt_passno = 0;
|
||||
|
||||
retry = hasmntval(&mnt, "retry");
|
||||
if (retry <= 0)
|
||||
retry = 1; /* XXX */
|
||||
|
||||
/*again:*/
|
||||
|
||||
/*
|
||||
* set mount args
|
||||
*/
|
||||
#ifdef NFS_ARGSVERSION
|
||||
nfs_args.version = NFS_ARGSVERSION;
|
||||
#endif
|
||||
|
||||
NFS_FH_DREF(nfs_args.fh, (NFS_FH_TYPE) fhp->fhstatus_u.fhs_fhandle);
|
||||
|
||||
#ifdef ULTRIX_HACK
|
||||
nfs_args.optstr = mnt.mnt_opts;
|
||||
#endif /* ULTRIX_HACK */
|
||||
|
||||
nfs_args.hostname = host;
|
||||
nfs_args.flags |= NFSMNT_HOSTNAME;
|
||||
#ifdef HOSTNAMESZ
|
||||
/*
|
||||
* Most kernels have a name length restriction.
|
||||
*/
|
||||
if (strlen(host) >= HOSTNAMESZ)
|
||||
strcpy(host + HOSTNAMESZ - 3, "..");
|
||||
#endif /* HOSTNAMESZ */
|
||||
|
||||
if (nfs_args.rsize = hasmntval(&mnt, "rsize"))
|
||||
nfs_args.flags |= NFSMNT_RSIZE;
|
||||
|
||||
if (nfs_args.wsize = hasmntval(&mnt, "wsize"))
|
||||
nfs_args.flags |= NFSMNT_WSIZE;
|
||||
|
||||
if (nfs_args.timeo = hasmntval(&mnt, "timeo"))
|
||||
nfs_args.flags |= NFSMNT_TIMEO;
|
||||
|
||||
if (nfs_args.retrans = hasmntval(&mnt, "retrans"))
|
||||
nfs_args.flags |= NFSMNT_RETRANS;
|
||||
|
||||
#ifdef NFSMNT_BIODS
|
||||
if (nfs_args.biods = hasmntval(&mnt, "biods"))
|
||||
nfs_args.flags |= NFSMNT_BIODS;
|
||||
|
||||
#endif /* NFSMNT_BIODS */
|
||||
|
||||
#ifdef NFSMNT_MAXGRPS
|
||||
if (nfs_args.maxgrouplist = hasmntval(&mnt, "maxgroups"))
|
||||
nfs_args.flags |= NFSMNT_MAXGRPS;
|
||||
#endif /* NFSMNT_MAXGRPS */
|
||||
|
||||
#ifdef notdef
|
||||
/*
|
||||
* This isn't supported by the ping algorithm yet.
|
||||
* In any case, it is all done in nfs_init().
|
||||
*/
|
||||
if (port = hasmntval(&mnt, "port"))
|
||||
sin.sin_port = htons(port);
|
||||
else
|
||||
sin.sin_port = htons(NFS_PORT); /* XXX should use portmapper */
|
||||
#endif /* notdef */
|
||||
|
||||
if (hasmntopt(&mnt, MNTOPT_SOFT) != NULL)
|
||||
nfs_args.flags |= NFSMNT_SOFT;
|
||||
|
||||
#ifdef NFSMNT_SPONGY
|
||||
if (hasmntopt(&mnt, "spongy") != NULL) {
|
||||
nfs_args.flags |= NFSMNT_SPONGY;
|
||||
if (nfs_args.flags & NFSMNT_SOFT) {
|
||||
plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored");
|
||||
nfs_args.flags &= ~NFSMNT_SOFT;
|
||||
}
|
||||
}
|
||||
#endif /* MNTOPT_SPONGY */
|
||||
|
||||
#ifdef MNTOPT_INTR
|
||||
if (hasmntopt(&mnt, MNTOPT_INTR) != NULL)
|
||||
nfs_args.flags |= NFSMNT_INT;
|
||||
#endif /* MNTOPT_INTR */
|
||||
|
||||
#ifdef MNTOPT_NODEVS
|
||||
if (hasmntopt(&mnt, MNTOPT_NODEVS) != NULL)
|
||||
nfs_args.flags |= NFSMNT_NODEVS;
|
||||
#endif /* MNTOPT_NODEVS */
|
||||
|
||||
#ifdef MNTOPT_COMPRESS
|
||||
if (hasmntopt(&mnt, "compress") != NULL)
|
||||
nfs_args.flags |= NFSMNT_COMPRESS;
|
||||
#endif /* MNTOPT_COMPRESS */
|
||||
|
||||
#ifdef MNTOPT_NOCONN
|
||||
if (hasmntopt(&mnt, "noconn") != NULL)
|
||||
nfs_args.flags |= NFSMNT_NOCONN;
|
||||
#endif /* MNTOPT_NOCONN */
|
||||
|
||||
#ifdef NFSMNT_PGTHRESH
|
||||
if (nfs_args.pg_thresh = hasmntval(&mnt, "pgthresh"))
|
||||
nfs_args.flags |= NFSMNT_PGTHRESH;
|
||||
#endif /* NFSMNT_PGTHRESH */
|
||||
|
||||
NFS_SA_DREF(nfs_args, fs->fs_ip);
|
||||
|
||||
flags = compute_mount_flags(&mnt);
|
||||
|
||||
#ifdef NFSMNT_NOCTO
|
||||
if (hasmntopt(&mnt, "nocto") != NULL)
|
||||
nfs_args.flags |= NFSMNT_NOCTO;
|
||||
#endif /* NFSMNT_NOCTO */
|
||||
|
||||
#ifdef HAS_TCP_NFS
|
||||
if (hasmntopt(&mnt, "tcp") != NULL)
|
||||
nfs_args.sotype = SOCK_STREAM;
|
||||
#endif /* HAS_TCP_NFS */
|
||||
|
||||
|
||||
#ifdef ULTRIX_HACK
|
||||
/*
|
||||
* Ultrix passes the flags argument as part of the
|
||||
* mount data structure, rather than using the
|
||||
* flags argument to the system call. This is
|
||||
* confusing...
|
||||
*/
|
||||
if (!(nfs_args.flags & NFSMNT_PGTHRESH)) {
|
||||
nfs_args.pg_thresh = 64; /* 64k - XXX */
|
||||
nfs_args.flags |= NFSMNT_PGTHRESH;
|
||||
}
|
||||
nfs_args.gfs_flags = flags;
|
||||
flags &= M_RDONLY;
|
||||
if (flags & M_RDONLY)
|
||||
nfs_args.flags |= NFSMNT_RONLY;
|
||||
#endif /* ULTRIX_HACK */
|
||||
|
||||
error = mount_fs(&mnt, flags, (caddr_t) &nfs_args, retry, type);
|
||||
free(xopts);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int mount_nfs(dir, fs_name, opts, mf)
|
||||
char *dir;
|
||||
char *fs_name;
|
||||
char *opts;
|
||||
mntfs *mf;
|
||||
{
|
||||
#ifdef notdef
|
||||
int error;
|
||||
struct fhstatus fhs;
|
||||
char *colon;
|
||||
|
||||
if (!(colon = strchr(fs_name, ':')))
|
||||
return ENOENT;
|
||||
|
||||
#ifdef DEBUG
|
||||
dlog("locating fhandle for %s", fs_name);
|
||||
#endif /* DEBUG */
|
||||
error = prime_nfs_fhandle_cache(colon+1, mf->mf_server, &fhs, (voidp) 0);
|
||||
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return mount_nfs_fh(&fhs, dir, fs_name, opts, mf);
|
||||
#endif
|
||||
if (!mf->mf_private) {
|
||||
plog(XLOG_ERROR, "Missing filehandle for %s", fs_name);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return mount_nfs_fh((struct fhstatus *) mf->mf_private, dir, fs_name, opts, mf);
|
||||
}
|
||||
|
||||
static int nfs_fmount(mf)
|
||||
mntfs *mf;
|
||||
{
|
||||
int error;
|
||||
|
||||
error = mount_nfs(mf->mf_mount, mf->mf_info, mf->mf_mopts, mf);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (error) {
|
||||
errno = error;
|
||||
dlog("mount_nfs: %m");
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
return error;
|
||||
}
|
||||
|
||||
static int nfs_fumount(mf)
|
||||
mntfs *mf;
|
||||
{
|
||||
int error = UMOUNT_FS(mf->mf_mount);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nfs_umounted(mp)
|
||||
am_node *mp;
|
||||
{
|
||||
#ifdef INFORM_MOUNTD
|
||||
/*
|
||||
* Don't bother to inform remote mountd
|
||||
* that we are finished. Until a full
|
||||
* track of filehandles is maintained
|
||||
* the mountd unmount callback cannot
|
||||
* be done correctly anyway...
|
||||
*/
|
||||
|
||||
mntfs *mf = mp->am_mnt;
|
||||
fserver *fs;
|
||||
char *colon, *path;
|
||||
|
||||
if (mf->mf_error || mf->mf_refc > 1)
|
||||
return;
|
||||
|
||||
fs = mf->mf_server;
|
||||
|
||||
/*
|
||||
* Call the mount daemon on the server to
|
||||
* announce that we are not using the fs any more.
|
||||
*
|
||||
* This is *wrong*. The mountd should be called
|
||||
* when the fhandle is flushed from the cache, and
|
||||
* a reference held to the cached entry while the
|
||||
* fs is mounted...
|
||||
*/
|
||||
colon = path = strchr(mf->mf_info, ':');
|
||||
if (fs && colon) {
|
||||
fh_cache f;
|
||||
#ifdef DEBUG
|
||||
dlog("calling mountd for %s", mf->mf_info);
|
||||
#endif /* DEBUG */
|
||||
*path++ = '\0';
|
||||
f.fh_path = path;
|
||||
f.fh_sin = *fs->fs_ip;
|
||||
f.fh_sin.sin_port = (u_short) 0;
|
||||
f.fh_fs = fs;
|
||||
f.fh_id = 0;
|
||||
f.fh_error = 0;
|
||||
(void) prime_nfs_fhandle_cache(colon+1, mf->mf_server, (struct fhstatus *) 0, (voidp) mf);
|
||||
(void) call_mountd(&f, MOUNTPROC_UMNT, (fwd_fun) 0, (voidp) 0);
|
||||
*colon = ':';
|
||||
}
|
||||
#endif /* INFORM_MOUNTD */
|
||||
|
||||
#ifdef KICK_KERNEL
|
||||
/* This should go into the mainline code, not in nfs_ops... */
|
||||
|
||||
/*
|
||||
* Run lstat over the underlying directory in
|
||||
* case this was a direct mount. This will
|
||||
* get the kernel back in sync with reality.
|
||||
*/
|
||||
if (mp->am_parent && mp->am_parent->am_path &&
|
||||
STREQ(mp->am_parent->am_mnt->mf_ops->fs_type, "direct")) {
|
||||
struct stat stb;
|
||||
int pid;
|
||||
if ((pid = background()) == 0) {
|
||||
if (lstat(mp->am_parent->am_path, &stb) < 0) {
|
||||
plog(XLOG_ERROR, "lstat(%s) after unmount: %m", mp->am_parent->am_path);
|
||||
#ifdef DEBUG
|
||||
} else {
|
||||
dlog("hack lstat(%s): ok", mp->am_parent->am_path);
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
_exit(0);
|
||||
}
|
||||
}
|
||||
#endif /* KICK_KERNEL */
|
||||
}
|
||||
|
||||
/*
|
||||
* Network file system
|
||||
*/
|
||||
am_ops nfs_ops = {
|
||||
"nfs",
|
||||
nfs_match,
|
||||
nfs_init,
|
||||
auto_fmount,
|
||||
nfs_fmount,
|
||||
auto_fumount,
|
||||
nfs_fumount,
|
||||
efs_lookuppn,
|
||||
efs_readdir,
|
||||
0, /* nfs_readlink */
|
||||
0, /* nfs_mounted */
|
||||
nfs_umounted,
|
||||
find_nfs_srvr,
|
||||
FS_MKMNT|FS_BACKGROUND|FS_AMQINFO
|
||||
};
|
||||
|
||||
#endif /* HAS_NFS */
|
178
usr.sbin/amd/amd/ufs_ops.c
Normal file
178
usr.sbin/amd/amd/ufs_ops.c
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 1990 Jan-Simon Pendry
|
||||
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Jan-Simon Pendry at Imperial College, London.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @(#)ufs_ops.c 8.2 (Berkeley) 5/10/95
|
||||
*
|
||||
* $Id: ufs_ops.c,v 5.2.2.1 1992/02/09 15:09:08 jsp beta $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "am.h"
|
||||
|
||||
#ifdef HAS_UFS
|
||||
|
||||
#include <sys/stat.h>
|
||||
#ifdef NFS_3
|
||||
typedef nfs_fh fhandle_t;
|
||||
#endif /* NFS_3 */
|
||||
|
||||
#include <sys/mount.h>
|
||||
|
||||
#ifdef UFS_HDR
|
||||
#include UFS_HDR
|
||||
#endif /* UFS_HDR */
|
||||
|
||||
/*
|
||||
* UN*X file system
|
||||
*/
|
||||
|
||||
/*
|
||||
* UFS needs local filesystem and device.
|
||||
*/
|
||||
static char *ufs_match P((am_opts *fo));
|
||||
static char *ufs_match(fo)
|
||||
am_opts *fo;
|
||||
{
|
||||
if (!fo->opt_dev) {
|
||||
plog(XLOG_USER, "ufs: no device specified");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
dlog("UFS: mounting device \"%s\" on \"%s\"",
|
||||
fo->opt_dev, fo->opt_fs);
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* Determine magic cookie to put in mtab
|
||||
*/
|
||||
return strdup(fo->opt_dev);
|
||||
}
|
||||
|
||||
static mount_ufs(dir, fs_name, opts)
|
||||
char *dir;
|
||||
char *fs_name;
|
||||
char *opts;
|
||||
{
|
||||
struct ufs_args ufs_args;
|
||||
struct mntent mnt;
|
||||
int flags;
|
||||
|
||||
/*
|
||||
* Figure out the name of the file system type.
|
||||
*/
|
||||
#ifdef M_NEWTYPE
|
||||
char *type = MOUNT_TYPE_UFS;
|
||||
#else
|
||||
int type = MOUNT_TYPE_UFS;
|
||||
#endif /* M_NEWTYPE */
|
||||
|
||||
bzero((voidp) &ufs_args, sizeof(ufs_args)); /* Paranoid */
|
||||
|
||||
/*
|
||||
* Fill in the mount structure
|
||||
*/
|
||||
mnt.mnt_dir = dir;
|
||||
mnt.mnt_fsname = fs_name;
|
||||
mnt.mnt_type = MTAB_TYPE_UFS;
|
||||
mnt.mnt_opts = opts;
|
||||
mnt.mnt_freq = 1;
|
||||
mnt.mnt_passno = 2;
|
||||
|
||||
flags = compute_mount_flags(&mnt);
|
||||
|
||||
#ifdef ULTRIX_HACK
|
||||
ufs_args.ufs_flags = flags;
|
||||
ufs_args.ufs_pgthresh = 64; /* 64K - XXX */
|
||||
flags &= M_RDONLY;
|
||||
#else
|
||||
ufs_args.fspec = fs_name;
|
||||
#endif /* ULTRIX_HACK */
|
||||
|
||||
/*
|
||||
* Call generic mount routine
|
||||
*/
|
||||
return mount_fs(&mnt, flags, (caddr_t) &ufs_args, 0, type);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static int ufs_fmount(mf)
|
||||
mntfs *mf;
|
||||
{
|
||||
int error;
|
||||
|
||||
error = mount_ufs(mf->mf_mount, mf->mf_info, mf->mf_mopts);
|
||||
if (error) {
|
||||
errno = error;
|
||||
plog(XLOG_ERROR, "mount_ufs: %m");
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ufs_fumount(mf)
|
||||
mntfs *mf;
|
||||
{
|
||||
return UMOUNT_FS(mf->mf_mount);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ops structure
|
||||
*/
|
||||
am_ops ufs_ops = {
|
||||
"ufs",
|
||||
ufs_match,
|
||||
0, /* ufs_init */
|
||||
auto_fmount,
|
||||
ufs_fmount,
|
||||
auto_fumount,
|
||||
ufs_fumount,
|
||||
efs_lookuppn,
|
||||
efs_readdir,
|
||||
0, /* ufs_readlink */
|
||||
0, /* ufs_mounted */
|
||||
0, /* ufs_umounted */
|
||||
find_afs_srvr,
|
||||
#ifdef FLUSH_KERNEL_NAME_CACHE
|
||||
FS_MKMNT|FS_NOTIMEOUT|FS_UBACKGROUND|FS_AMQINFO
|
||||
#else /* FLUSH_KERNEL_NAME_CACHE */
|
||||
FS_MKMNT|FS_NOTIMEOUT|FS_UBACKGROUND|FS_AMQINFO
|
||||
#endif /* FLUSH_KERNEL_NAME_CACHE */
|
||||
};
|
||||
|
||||
#endif /* HAS_UFS */
|
48
usr.sbin/amd/config/misc-bsd44l.h
Normal file
48
usr.sbin/amd/config/misc-bsd44l.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 1995 Jan-Simon Pendry
|
||||
* Copyright (c) 1995
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Jan-Simon Pendry.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @(#)misc-bsd44l.h 8.1 (Berkeley) 5/10/95
|
||||
*
|
||||
*/
|
||||
|
||||
#define M_NEWTYPE 0
|
||||
|
||||
#include <sys/ucred.h>
|
||||
#include <nfs/rpcv2.h>
|
||||
#define NFS_NPROCS 26 /* from <nfs/nfsproto.h> */
|
||||
#include <nfs/nfs.h>
|
||||
|
||||
#include <ufs/ufs/ufsmount.h>
|
118
usr.sbin/amd/config/mtab_bsd.c
Normal file
118
usr.sbin/amd/config/mtab_bsd.c
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 1990 Jan-Simon Pendry
|
||||
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Jan-Simon Pendry at Imperial College, London.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @(#)mtab_bsd.c 8.2 (Berkeley) 5/10/95
|
||||
*
|
||||
* $Id: mtab_bsd.c,v 5.2.2.1 1992/02/09 15:10:13 jsp beta $
|
||||
*
|
||||
*/
|
||||
|
||||
#include "am.h"
|
||||
|
||||
#ifdef READ_MTAB_BSD_STYLE
|
||||
|
||||
#include <sys/mount.h>
|
||||
|
||||
static struct mntent *mnt_dup(mp)
|
||||
struct statfs *mp;
|
||||
{
|
||||
struct mntent *new_mp = ALLOC(mntent);
|
||||
char *ty;
|
||||
|
||||
new_mp->mnt_fsname = strdup(mp->f_mntfromname);
|
||||
new_mp->mnt_dir = strdup(mp->f_mntonname);
|
||||
#if BSD >= 199506
|
||||
ty = mp->f_fstypename;
|
||||
#else
|
||||
switch (mp->f_type) {
|
||||
case MOUNT_UFS: ty = MTAB_TYPE_UFS; break;
|
||||
case MOUNT_NFS: ty = MTAB_TYPE_NFS; break;
|
||||
case MOUNT_MFS: ty = MTAB_TYPE_MFS; break;
|
||||
default: ty = "unknown"; break;
|
||||
}
|
||||
#endif
|
||||
new_mp->mnt_type = strdup(ty);
|
||||
new_mp->mnt_opts = strdup("unset");
|
||||
new_mp->mnt_freq = 0;
|
||||
new_mp->mnt_passno = 0;
|
||||
|
||||
return new_mp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a mount table into memory
|
||||
*/
|
||||
mntlist *read_mtab(fs)
|
||||
char *fs;
|
||||
{
|
||||
mntlist **mpp, *mhp;
|
||||
struct statfs *mntbufp, *mntp;
|
||||
|
||||
int nloc = getmntinfo(&mntbufp, MNT_NOWAIT);
|
||||
|
||||
if (nloc == 0) {
|
||||
plog(XLOG_ERROR, "Can't read mount table");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mpp = &mhp;
|
||||
for (mntp = mntbufp; mntp < mntbufp + nloc; mntp++) {
|
||||
/*
|
||||
* Allocate a new slot
|
||||
*/
|
||||
*mpp = ALLOC(mntlist);
|
||||
|
||||
/*
|
||||
* Copy the data returned by getmntent
|
||||
*/
|
||||
(*mpp)->mnt = mnt_dup(mntp);
|
||||
|
||||
/*
|
||||
* Move to next pointer
|
||||
*/
|
||||
mpp = &(*mpp)->mnext;
|
||||
}
|
||||
|
||||
/*
|
||||
* Terminate the list
|
||||
*/
|
||||
*mpp = 0;
|
||||
|
||||
return mhp;
|
||||
}
|
||||
|
||||
#endif /* READ_MTAB_BSD_STYLE */
|
228
usr.sbin/amd/config/os-bsd44.h
Normal file
228
usr.sbin/amd/config/os-bsd44.h
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (c) 1990 Jan-Simon Pendry
|
||||
* Copyright (c) 1990 Imperial College of Science, Technology & Medicine
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Jan-Simon Pendry at Imperial College, London.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* @(#)os-bsd44.h 8.2 (Berkeley) 5/10/95
|
||||
*
|
||||
* $Id: os-bsd44.h,v 5.2.2.1 1992/02/09 15:10:11 jsp beta $
|
||||
*
|
||||
* 4.4 BSD definitions for Amd (automounter)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Does the compiler grok void *
|
||||
*/
|
||||
#define VOIDP
|
||||
|
||||
/*
|
||||
* Which version of the Sun RPC library we are using
|
||||
* This is the implementation release number, not
|
||||
* the protocol revision number.
|
||||
*/
|
||||
#define RPC_4
|
||||
|
||||
#include <sys/param.h>
|
||||
#if BSD >= 199506
|
||||
#define NFS_HDR "misc-bsd44l.h"
|
||||
#define UFS_HDR "misc-bsd44l.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Which version of the NFS interface are we using.
|
||||
* This is the implementation release number, not
|
||||
* the protocol revision number.
|
||||
*/
|
||||
#define NFS_44
|
||||
#define HAS_TCP_NFS
|
||||
|
||||
/*
|
||||
* Does this OS have NDBM support?
|
||||
*/
|
||||
#define OS_HAS_NDBM
|
||||
|
||||
/*
|
||||
* 4.4 doesn't provide NIS.
|
||||
*/
|
||||
#undef HAS_NIS_MAPS
|
||||
|
||||
/*
|
||||
* OS provides strerror()
|
||||
*/
|
||||
#define HAS_STRERROR
|
||||
|
||||
/*
|
||||
* The mount table is obtained from the kernel
|
||||
*/
|
||||
#undef UPDATE_MTAB
|
||||
|
||||
/*
|
||||
* No mntent info on 4.4 BSD
|
||||
*/
|
||||
#undef MNTENT_HDR
|
||||
|
||||
/*
|
||||
* Name of filesystem types
|
||||
*/
|
||||
#define MOUNT_TYPE_NFS MOUNT_NFS
|
||||
#define MOUNT_TYPE_UFS MOUNT_UFS
|
||||
#undef MTAB_TYPE_UFS
|
||||
#define MTAB_TYPE_UFS "ufs"
|
||||
#define MTAB_TYPE_MFS "mfs"
|
||||
|
||||
/*
|
||||
* How to unmount filesystems
|
||||
*/
|
||||
#undef UNMOUNT_TRAP
|
||||
#undef NEED_UMOUNT_FS
|
||||
#define NEED_UMOUNT_BSD
|
||||
|
||||
/*
|
||||
* How to copy an address into an NFS filehandle
|
||||
*/
|
||||
#undef NFS_SA_DREF
|
||||
#if BSD >= 199506
|
||||
#define NFS_SA_DREF(dst, src) { \
|
||||
(dst).addr = (struct sockaddr *) (src); \
|
||||
(dst).addrlen = sizeof(*src); \
|
||||
(dst).sotype = SOCK_DGRAM; \
|
||||
(dst).proto = 0; \
|
||||
(dst).fhsize = FHSIZE; \
|
||||
(dst).wsize = NFS_WSIZE; \
|
||||
(dst).rsize = NFS_RSIZE; \
|
||||
(dst).readdirsize = NFS_READDIRSIZE; \
|
||||
(dst).timeo = 10; \
|
||||
(dst).retrans = NFS_RETRANS; \
|
||||
(dst).maxgrouplist = NFS_MAXGRPS; \
|
||||
(dst).readahead = NFS_DEFRAHEAD; \
|
||||
(dst).leaseterm = 0; \
|
||||
(dst).deadthresh = 0; \
|
||||
}
|
||||
#else
|
||||
#define NFS_SA_DREF(dst, src) { \
|
||||
(dst).addr = (struct sockaddr *) (src); \
|
||||
(dst).addrlen = sizeof(*src); \
|
||||
(dst).sotype = SOCK_DGRAM; \
|
||||
(dst).proto = 0; \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Byte ordering
|
||||
*/
|
||||
#ifndef BYTE_ORDER
|
||||
#include <machine/endian.h>
|
||||
#endif /* BYTE_ORDER */
|
||||
|
||||
#undef ARCH_ENDIAN
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define ARCH_ENDIAN "little"
|
||||
#else
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
#define ARCH_ENDIAN "big"
|
||||
#else
|
||||
XXX - Probably no hope of running Amd on this machine!
|
||||
#endif /* BIG */
|
||||
#endif /* LITTLE */
|
||||
|
||||
/*
|
||||
* Miscellaneous 4.4 BSD bits
|
||||
*/
|
||||
#define NEED_MNTOPT_PARSER
|
||||
#define SHORT_MOUNT_NAME
|
||||
|
||||
#define MNTMAXSTR 128
|
||||
|
||||
#define MNTTYPE_UFS "ufs" /* Un*x file system */
|
||||
#define MNTTYPE_NFS "nfs" /* network file system */
|
||||
#define MNTTYPE_MFS "mfs" /* memory file system */
|
||||
#define MNTTYPE_IGNORE "ignore" /* No type specified, ignore this entry */
|
||||
|
||||
#define M_RDONLY MNT_RDONLY
|
||||
#define M_SYNC MNT_SYNCHRONOUS
|
||||
#define M_NOEXEC MNT_NOEXEC
|
||||
#define M_NOSUID MNT_NOSUID
|
||||
#define M_NODEV MNT_NODEV
|
||||
|
||||
#define MNTOPT_SOFT "soft" /* soft mount */
|
||||
#define MNTOPT_INTR "intr" /* interrupts allowed */
|
||||
|
||||
#define NFSMNT_HOSTNAME 0 /* hostname on 4.4 is not optional */
|
||||
|
||||
struct mntent {
|
||||
char *mnt_fsname; /* name of mounted file system */
|
||||
char *mnt_dir; /* file system path prefix */
|
||||
char *mnt_type; /* MNTTYPE_* */
|
||||
char *mnt_opts; /* MNTOPT* */
|
||||
int mnt_freq; /* dump frequency, in days */
|
||||
int mnt_passno; /* pass number on parallel fsck */
|
||||
};
|
||||
|
||||
/*
|
||||
* Type of a file handle
|
||||
*/
|
||||
#undef NFS_FH_TYPE
|
||||
#if BSD >= 199506
|
||||
#define NFS_FH_TYPE void *
|
||||
#else
|
||||
#define NFS_FH_TYPE nfsv2fh_t *
|
||||
#endif
|
||||
|
||||
/*
|
||||
* How to get a mount list
|
||||
*/
|
||||
#undef READ_MTAB_FROM_FILE
|
||||
#define READ_MTAB_BSD_STYLE
|
||||
|
||||
/*
|
||||
* The data for the mount syscall needs the path in addition to the
|
||||
* host name since that is the only source of information about the
|
||||
* mounted filesystem.
|
||||
*/
|
||||
#define NFS_ARGS_NEEDS_PATH
|
||||
|
||||
/*
|
||||
* 4.4 has RE support built in
|
||||
*/
|
||||
#undef RE_HDR
|
||||
#define RE_HDR <regexp.h>
|
||||
|
||||
#if BSD >= 199506
|
||||
#undef MTYPE_TYPE
|
||||
#define MTYPE_TYPE char *
|
||||
#define MOUNT_NFS "nfs"
|
||||
#define MOUNT_UFS "ffs"
|
||||
#define MOUNT_MFS "mfs"
|
||||
#endif
|
194
usr.sbin/amd/text/INSTALL
Normal file
194
usr.sbin/amd/text/INSTALL
Normal file
@ -0,0 +1,194 @@
|
||||
Installation Notes for Amd.
|
||||
|
||||
NOTE: Please read all of this before starting.
|
||||
It is not very long and may save you time in the long term.
|
||||
|
||||
1. ``Getting started...''
|
||||
|
||||
If you don't know what an Automounter does for you then read the
|
||||
documentation in doc/amdref.texinfo. You can either use TeX to print
|
||||
it out or read it directly using the GNU info package.
|
||||
|
||||
2. ``Find out what version of UN*X you are running...''
|
||||
|
||||
To install Amd you need a port for your version of UN*X. In the
|
||||
config/ directory are several files called os-*.h. One of these
|
||||
should correspond to your version of UN*X. Run the program
|
||||
"config/os-type" to find out what system Amd thinks you have. Check
|
||||
the correspondong config/os-??? file to make sure that you and Amd are
|
||||
in agreement. If os-type returns "unknown" then either no-one has yet
|
||||
done a port, or your version of UN*X is so braindead that a port is
|
||||
not possible (e.g. System V without reliable signals). The current
|
||||
known operating systems (grouped by architecture) are:
|
||||
|
||||
acis43 (AOS) ACIS 4.3BSD on an IBM RT
|
||||
aix3 AIX 3.2
|
||||
aux Apple A/UX
|
||||
bsd44 4.4 BSD on whatever
|
||||
concentrix Concentrix on an Alliant
|
||||
dgux Data General AViiON
|
||||
fpx4 Celerity FPX 4.1/2
|
||||
hlh42 4.2 BSD on HLH Orion 1/05
|
||||
hpux HP-UX 6.* and 7.* on a HP9000/300
|
||||
irix3 SGI Iris
|
||||
irix4 SGI Iris w/Irix 4.0.x
|
||||
next NeXT
|
||||
riscix 4.3 BSD on an Acorn Archimedes
|
||||
sos3, sos4 SunOS 3.* and 4.* on a Sun-3 and Sun-4
|
||||
u2_2 Ultrix 2.2 (or 2.*?) on a VAX (broken)
|
||||
u3_0 Ultrix 3.0 (or 3.*?) on a VAX (broken)
|
||||
u4_2 Ultrix 4.2
|
||||
umax43 4.3 BSD on an Encore Multimax
|
||||
xinu43 More/BSD (4.3 BSD) on a VAX or HP9000/300
|
||||
|
||||
+ some others...
|
||||
|
||||
If you do define a new operating system type foo, you may need to create a
|
||||
file called Makefile.foo which defines the special Makefile parameters.
|
||||
|
||||
3. ``Hacking the Makefile...''
|
||||
|
||||
Amd tries very hard to determine what type of machine you are using
|
||||
and how best to compile itself. If this does not work then you will
|
||||
have to find some heuristic which can differentiate your
|
||||
configuration. You may need to edit "config/arch" and
|
||||
"config/os-type". If you do make sure your changes can cope if
|
||||
/etc/motd is missing and please send it to the address below.
|
||||
|
||||
To check whether things are working, run:
|
||||
sh config/arch
|
||||
sh config/os-type
|
||||
|
||||
You may care to tailor some site specific preferences in "Makefile.com". The
|
||||
variables most likely to be changes are at the top. Any changes should be
|
||||
added to a file called config/Makefile.local (if they are applicable to all
|
||||
operating systems at your site) or Makefile.local.foo (where foo is the OS type
|
||||
as determined in part 2).
|
||||
|
||||
Additionally, some configuration options may be altered in
|
||||
"config/Makefile.config". This means that you should not need to edit any
|
||||
distributed files apart from "config/Makefile.config". As a minimum, you
|
||||
should check:
|
||||
|
||||
* You are using the correct C compiler. Amd, as shipped, does not use GCC.
|
||||
Note that using GCC version 1.34 or later (e.g. 1.36) gives structure
|
||||
passing problems with some parts of Sun's RPC library at least on Sun-4's.
|
||||
The current workaround is to use the system CC to compile the part of the
|
||||
automounter that gets hit by this problem. [[This is not the same problem
|
||||
that is fixed by -fpcc-struct-return.]] Amd contains no "register"
|
||||
declarations, so using old PCC based code generators is probably bad news.
|
||||
|
||||
To use GNU CC, add the following to config/Makefile.local{.os-type}:
|
||||
|
||||
CC = gcc ${GCCOPTS}
|
||||
|
||||
* The installation directory (ETC) is set up correctly.
|
||||
|
||||
* If you are running tests then it may be worth switching on the DEBUG flag
|
||||
which will cause a running commentary to be printed to the log file. To
|
||||
compile in the debug code, add the following to
|
||||
config/Makefile.local{.os-type}:
|
||||
|
||||
DEBUG = -DDEBUG
|
||||
CCOPTS = -g
|
||||
|
||||
The -g option will also allow you to use gdb. Using dbx is not advisable
|
||||
since it puts a breakpoint on exit() which causes all of Amd's child
|
||||
processes to dump core. gdb does not suffer from this problem.
|
||||
|
||||
4. ``Build the executable...''
|
||||
|
||||
Now you need to compile the automounter. To do this you type:
|
||||
|
||||
make
|
||||
|
||||
in the top-level directory. You can also go into each of the program
|
||||
directories and just run make there.
|
||||
|
||||
If you are porting to a new machine you may want to do:
|
||||
|
||||
make OS=foo
|
||||
|
||||
where foo is the name of your version of UN*X as determined in part 1, until
|
||||
you have made the changes to config/os-type and/or config/arch. When the
|
||||
compilation is complete you will end up with a program called "A.arch_foo/amd".
|
||||
|
||||
Try running:
|
||||
|
||||
A.arch_foo/amd -v
|
||||
|
||||
and check the output. It should look something like:
|
||||
|
||||
Copyright (c) 1990 Jan-Simon Pendry
|
||||
Copyright (c) 1990 Imperial College of Science, Technology & Medicine
|
||||
Copyright (c) 1990 The Regents of the University of California.
|
||||
amd 5.2.1.5 of 90/09/16 13:22:46 5.3Alpha5 #0: Sun Sep 16 13:23:28 BST 1990
|
||||
Built by pendry@okeeffe.Berkeley.EDU for a tahoe running bsd44 (big-endian)
|
||||
Map support for: root, passwd, nis, file, error.
|
||||
fstypes: ufs, nfs, nfsx, host, link, program, auto, direct, toplvl, error.
|
||||
|
||||
Make sure the O/S and architecture types were correctly derived during the
|
||||
build.
|
||||
|
||||
5. ``Installation...''
|
||||
|
||||
If you are not just testing Amd, then you can install it by typing:
|
||||
|
||||
make install
|
||||
|
||||
to install "A.arch_foo/amd" in "/usr/local/etc/amd" (or as otherwise
|
||||
modified in part 3).
|
||||
|
||||
6. ``Update /etc/rpc''
|
||||
|
||||
Amq uses Sun RPC to talk to Amd using program number 300019 which has
|
||||
been registered with Sun. Add the following lines to /etc/rpc or your
|
||||
YP or Hesiod master:
|
||||
|
||||
# Automount control protocol
|
||||
amd 300019 amq
|
||||
|
||||
Amd does not require this addition - it just keeps rpcinfo happy.
|
||||
|
||||
7. ``Hanging your machine...''
|
||||
|
||||
WARNING: THIS MAY HANG YOUR MACHINE IF YOU GET IT WRONG.
|
||||
|
||||
Running Amd with a carelessly thought out mount map can cause your Amd to
|
||||
enter a deadlock inside the kernel. For example, attempting to automount a
|
||||
directory which is automounted. This will cause the automounter to issue a mount
|
||||
request causing the kernel to send an NFS request back to the same automounter,
|
||||
which is currently stuck in a system call and unable to respond - even
|
||||
kill -s KILL won't get you out of this one.
|
||||
|
||||
There is nothing you can do to fix it without rebooting your machine, so...
|
||||
|
||||
Find a diskless workstation and play with that first before trying this on
|
||||
your main 200 user service machine (unless you hate your users). Something
|
||||
like a diskless Sun-4 is best for development testing - you can compile on a
|
||||
Sun-4 server and run the binary on the diskless node. They reboot very fast
|
||||
as well between tests.
|
||||
|
||||
Now you can try running Amd. Please read the documentation in doc/Amd.tex
|
||||
for more details. The configuration file "maps/a_master" provides a sample for
|
||||
you to play with. Something like:
|
||||
|
||||
./amd -c 40 -D test,nodaemon /tmp/amnt ../maps/a_master &
|
||||
|
||||
is good for testing. Note that Amd will clean up correctly if you send it a
|
||||
SIGINT or SIGTERM. Other signals are either ignored or will blow it away,
|
||||
leaving your machine in a potentially dangerous state.
|
||||
|
||||
Remember that Amd needs to run as root in order to do mounts/unmounts
|
||||
though it does check this condition somewhere near line one of main().
|
||||
It will also need write permission in the working directory if you
|
||||
have built it with DEBUG defined and your system's mount table is
|
||||
reflected in a file. In this case watch out for NFS stepping in and
|
||||
mapping root to nobody.
|
||||
|
||||
8. ``Report what happened...''
|
||||
|
||||
If anything interesting happened, eg it didn't work, please report it to me
|
||||
-- Jan-Simon Pendry <jsp@doc.ic.ac.uk> -- as detailed in the README file.
|
||||
|
||||
$Id: INSTALL,v 5.2.2.2 1992/05/31 16:49:22 jsp Exp $
|
122
usr.sbin/arp/arp.8
Normal file
122
usr.sbin/arp/arp.8
Normal file
@ -0,0 +1,122 @@
|
||||
.\" Copyright (c) 1985, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)arp.8 8.2 (Berkeley) 4/27/95
|
||||
.\"
|
||||
.Dd April 27, 1995
|
||||
.Dt ARP 8
|
||||
.Os BSD 4.3
|
||||
.Sh NAME
|
||||
.Nm arp
|
||||
.Nd address resolution display and control
|
||||
.Sh SYNOPSIS
|
||||
.Nm arp
|
||||
.Ar hostname
|
||||
.Nm arp
|
||||
.Fl a
|
||||
.Nm arp
|
||||
.Fl d Ar hostname
|
||||
.Nm arp
|
||||
.Fl s Ar hostname ether_addr
|
||||
.Op Ar temp
|
||||
.Op Ar pub
|
||||
.Nm arp
|
||||
.Fl f Ar filename
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm arp
|
||||
program displays and modifies the Internet-to-Ethernet address translation
|
||||
tables used by the address resolution protocol
|
||||
.Pq Xr arp 4 .
|
||||
With no flags, the program displays the current
|
||||
.Tn ARP
|
||||
entry for
|
||||
.Ar hostname .
|
||||
The host may be specified by name or by number,
|
||||
using Internet dot notation.
|
||||
.Pp
|
||||
Available options:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl a
|
||||
The program displays all of the current
|
||||
.Tn ARP
|
||||
entries.
|
||||
.It Fl d
|
||||
A super-user may delete an entry for the host called
|
||||
.Ar hostname
|
||||
with the
|
||||
.Fl d
|
||||
flag.
|
||||
.It Fl s Ar hostname ether_addr
|
||||
Create an
|
||||
.Tn ARP
|
||||
entry for the host called
|
||||
.Ar hostname
|
||||
with the Ethernet address
|
||||
.Ar ether_addr .
|
||||
The Ethernet address is given as six hex bytes separated by colons.
|
||||
The entry will be permanent unless the word
|
||||
.Ar temp
|
||||
is given in the command.
|
||||
If the word
|
||||
.Ar pub
|
||||
is given, the entry will be "published"; i.e., this system will
|
||||
act as an
|
||||
.Tn ARP
|
||||
server,
|
||||
responding to requests for
|
||||
.Ar hostname
|
||||
even though the host address is not its own.
|
||||
.It Fl f
|
||||
Causes the file
|
||||
.Ar filename
|
||||
to be read and multiple entries to be set in the
|
||||
.Tn ARP
|
||||
tables. Entries
|
||||
in the file should be of the form
|
||||
.Pp
|
||||
.Bd -filled -offset indent -compact
|
||||
.Ar hostname ether_addr
|
||||
.Op Ar temp
|
||||
.Op Ar pub
|
||||
.Ed
|
||||
.Pp
|
||||
with argument meanings as given above.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr inet 3 ,
|
||||
.Xr arp 4 ,
|
||||
.Xr ifconfig 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.3 .
|
531
usr.sbin/arp/arp.c
Normal file
531
usr.sbin/arp/arp.c
Normal file
@ -0,0 +1,531 @@
|
||||
/*
|
||||
* Copyright (c) 1984, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Sun Microsystems, 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1984, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)arp.c 8.3 (Berkeley) 4/28/95";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* arp - display, set, and delete arp table entries
|
||||
*/
|
||||
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/if_ether.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <nlist.h>
|
||||
#include <paths.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int pid;
|
||||
static int nflag;
|
||||
static int s = -1;
|
||||
|
||||
int delete __P((char *, char *));
|
||||
void dump __P((u_long));
|
||||
int ether_aton __P((char *, u_char *));
|
||||
void ether_print __P((u_char *));
|
||||
int file __P((char *));
|
||||
void get __P((char *));
|
||||
void getsocket __P((void));
|
||||
int rtmsg __P((int));
|
||||
int set __P((int, char **));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int ch;
|
||||
|
||||
pid = getpid();
|
||||
while ((ch = getopt(argc, argv, "ands")) != EOF)
|
||||
switch((char)ch) {
|
||||
case 'a':
|
||||
dump(0);
|
||||
exit(0);
|
||||
case 'd':
|
||||
if (argc < 3 || argc > 4)
|
||||
usage();
|
||||
delete(argv[2], argv[3]);
|
||||
exit(0);
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
continue;
|
||||
case 's':
|
||||
if (argc < 4 || argc > 7)
|
||||
usage();
|
||||
exit(set(argc-2, &argv[2]) ? 1 : 0);
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
if (argc != 2)
|
||||
usage();
|
||||
get(argv[1]);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a file to set standard arp entries
|
||||
*/
|
||||
int
|
||||
file(name)
|
||||
char *name;
|
||||
{
|
||||
FILE *fp;
|
||||
int i, retval;
|
||||
char line[100], arg[5][50], *args[5];
|
||||
|
||||
if ((fp = fopen(name, "r")) == NULL) {
|
||||
fprintf(stderr, "arp: cannot open %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
args[0] = &arg[0][0];
|
||||
args[1] = &arg[1][0];
|
||||
args[2] = &arg[2][0];
|
||||
args[3] = &arg[3][0];
|
||||
args[4] = &arg[4][0];
|
||||
retval = 0;
|
||||
while(fgets(line, 100, fp) != NULL) {
|
||||
i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2],
|
||||
arg[3], arg[4]);
|
||||
if (i < 2) {
|
||||
fprintf(stderr, "arp: bad line: %s\n", line);
|
||||
retval = 1;
|
||||
continue;
|
||||
}
|
||||
if (set(i, args))
|
||||
retval = 1;
|
||||
}
|
||||
fclose(fp);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
void
|
||||
getsocket() {
|
||||
if (s < 0) {
|
||||
s = socket(PF_ROUTE, SOCK_RAW, 0);
|
||||
if (s < 0) {
|
||||
perror("arp: socket");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct sockaddr_in so_mask = {8, 0, 0, { 0xffffffff}};
|
||||
struct sockaddr_inarp blank_sin = {sizeof(blank_sin), AF_INET }, sin_m;
|
||||
struct sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m;
|
||||
int expire_time, flags, export_only, doing_proxy, found_entry;
|
||||
struct {
|
||||
struct rt_msghdr m_rtm;
|
||||
char m_space[512];
|
||||
} m_rtmsg;
|
||||
|
||||
/*
|
||||
* Set an individual arp entry
|
||||
*/
|
||||
int
|
||||
set(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
struct hostent *hp;
|
||||
register struct sockaddr_inarp *sin = &sin_m;
|
||||
register struct sockaddr_dl *sdl;
|
||||
register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm);
|
||||
u_char *ea;
|
||||
char *host = argv[0], *eaddr = argv[1];
|
||||
|
||||
getsocket();
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
sdl_m = blank_sdl;
|
||||
sin_m = blank_sin;
|
||||
sin->sin_addr.s_addr = inet_addr(host);
|
||||
if (sin->sin_addr.s_addr == -1) {
|
||||
if (!(hp = gethostbyname(host))) {
|
||||
fprintf(stderr, "arp: %s: ", host);
|
||||
herror((char *)NULL);
|
||||
return (1);
|
||||
}
|
||||
bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
|
||||
sizeof sin->sin_addr);
|
||||
}
|
||||
ea = (u_char *)LLADDR(&sdl_m);
|
||||
if (ether_aton(eaddr, ea) == 0)
|
||||
sdl_m.sdl_alen = 6;
|
||||
doing_proxy = flags = export_only = expire_time = 0;
|
||||
while (argc-- > 0) {
|
||||
if (strncmp(argv[0], "temp", 4) == 0) {
|
||||
struct timeval time;
|
||||
gettimeofday(&time, 0);
|
||||
expire_time = time.tv_sec + 20 * 60;
|
||||
}
|
||||
else if (strncmp(argv[0], "pub", 3) == 0) {
|
||||
flags |= RTF_ANNOUNCE;
|
||||
doing_proxy = SIN_PROXY;
|
||||
} else if (strncmp(argv[0], "trail", 5) == 0) {
|
||||
printf("%s: Sending trailers is no longer supported\n",
|
||||
host);
|
||||
}
|
||||
argv++;
|
||||
}
|
||||
tryagain:
|
||||
if (rtmsg(RTM_GET) < 0) {
|
||||
perror(host);
|
||||
return (1);
|
||||
}
|
||||
sin = (struct sockaddr_inarp *)(rtm + 1);
|
||||
sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
|
||||
if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
|
||||
if (sdl->sdl_family == AF_LINK &&
|
||||
(rtm->rtm_flags & RTF_LLINFO) &&
|
||||
!(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {
|
||||
case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
|
||||
case IFT_ISO88024: case IFT_ISO88025:
|
||||
goto overwrite;
|
||||
}
|
||||
if (doing_proxy == 0) {
|
||||
printf("set: can only proxy for %s\n", host);
|
||||
return (1);
|
||||
}
|
||||
if (sin_m.sin_other & SIN_PROXY) {
|
||||
printf("set: proxy entry exists for non 802 device\n");
|
||||
return(1);
|
||||
}
|
||||
sin_m.sin_other = SIN_PROXY;
|
||||
export_only = 1;
|
||||
goto tryagain;
|
||||
}
|
||||
overwrite:
|
||||
if (sdl->sdl_family != AF_LINK) {
|
||||
printf("cannot intuit interface index and type for %s\n", host);
|
||||
return (1);
|
||||
}
|
||||
sdl_m.sdl_type = sdl->sdl_type;
|
||||
sdl_m.sdl_index = sdl->sdl_index;
|
||||
return (rtmsg(RTM_ADD));
|
||||
}
|
||||
|
||||
/*
|
||||
* Display an individual arp entry
|
||||
*/
|
||||
void
|
||||
get(host)
|
||||
char *host;
|
||||
{
|
||||
struct hostent *hp;
|
||||
struct sockaddr_inarp *sin = &sin_m;
|
||||
|
||||
sin_m = blank_sin;
|
||||
sin->sin_addr.s_addr = inet_addr(host);
|
||||
if (sin->sin_addr.s_addr == -1) {
|
||||
if (!(hp = gethostbyname(host))) {
|
||||
fprintf(stderr, "arp: %s: ", host);
|
||||
herror((char *)NULL);
|
||||
exit(1);
|
||||
}
|
||||
bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
|
||||
sizeof sin->sin_addr);
|
||||
}
|
||||
dump(sin->sin_addr.s_addr);
|
||||
if (found_entry == 0) {
|
||||
printf("%s (%s) -- no entry\n",
|
||||
host, inet_ntoa(sin->sin_addr));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete an arp entry
|
||||
*/
|
||||
int
|
||||
delete(host, info)
|
||||
char *host;
|
||||
char *info;
|
||||
{
|
||||
struct hostent *hp;
|
||||
register struct sockaddr_inarp *sin = &sin_m;
|
||||
register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
|
||||
struct sockaddr_dl *sdl;
|
||||
|
||||
if (info && strncmp(info, "pro", 3) )
|
||||
export_only = 1;
|
||||
getsocket();
|
||||
sin_m = blank_sin;
|
||||
sin->sin_addr.s_addr = inet_addr(host);
|
||||
if (sin->sin_addr.s_addr == -1) {
|
||||
if (!(hp = gethostbyname(host))) {
|
||||
fprintf(stderr, "arp: %s: ", host);
|
||||
herror((char *)NULL);
|
||||
return (1);
|
||||
}
|
||||
bcopy((char *)hp->h_addr, (char *)&sin->sin_addr,
|
||||
sizeof sin->sin_addr);
|
||||
}
|
||||
tryagain:
|
||||
if (rtmsg(RTM_GET) < 0) {
|
||||
perror(host);
|
||||
return (1);
|
||||
}
|
||||
sin = (struct sockaddr_inarp *)(rtm + 1);
|
||||
sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin);
|
||||
if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) {
|
||||
if (sdl->sdl_family == AF_LINK &&
|
||||
(rtm->rtm_flags & RTF_LLINFO) &&
|
||||
!(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) {
|
||||
case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023:
|
||||
case IFT_ISO88024: case IFT_ISO88025:
|
||||
goto delete;
|
||||
}
|
||||
}
|
||||
if (sin_m.sin_other & SIN_PROXY) {
|
||||
fprintf(stderr, "delete: can't locate %s\n",host);
|
||||
return (1);
|
||||
} else {
|
||||
sin_m.sin_other = SIN_PROXY;
|
||||
goto tryagain;
|
||||
}
|
||||
delete:
|
||||
if (sdl->sdl_family != AF_LINK) {
|
||||
printf("cannot locate %s\n", host);
|
||||
return (1);
|
||||
}
|
||||
if (rtmsg(RTM_DELETE))
|
||||
return (1);
|
||||
printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr));
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the entire arp table
|
||||
*/
|
||||
void
|
||||
dump(addr)
|
||||
u_long addr;
|
||||
{
|
||||
int mib[6];
|
||||
size_t needed;
|
||||
char *host, *lim, *buf, *next;
|
||||
struct rt_msghdr *rtm;
|
||||
struct sockaddr_inarp *sin;
|
||||
struct sockaddr_dl *sdl;
|
||||
extern int h_errno;
|
||||
struct hostent *hp;
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = PF_ROUTE;
|
||||
mib[2] = 0;
|
||||
mib[3] = AF_INET;
|
||||
mib[4] = NET_RT_FLAGS;
|
||||
mib[5] = RTF_LLINFO;
|
||||
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
|
||||
err(1, "route-sysctl-estimate");
|
||||
if ((buf = malloc(needed)) == NULL)
|
||||
err(1, "malloc");
|
||||
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
|
||||
err(1, "actual retrieval of routing table");
|
||||
lim = buf + needed;
|
||||
for (next = buf; next < lim; next += rtm->rtm_msglen) {
|
||||
rtm = (struct rt_msghdr *)next;
|
||||
sin = (struct sockaddr_inarp *)(rtm + 1);
|
||||
sdl = (struct sockaddr_dl *)(sin + 1);
|
||||
if (addr) {
|
||||
if (addr != sin->sin_addr.s_addr)
|
||||
continue;
|
||||
found_entry = 1;
|
||||
}
|
||||
if (nflag == 0)
|
||||
hp = gethostbyaddr((caddr_t)&(sin->sin_addr),
|
||||
sizeof sin->sin_addr, AF_INET);
|
||||
else
|
||||
hp = 0;
|
||||
if (hp)
|
||||
host = hp->h_name;
|
||||
else {
|
||||
host = "?";
|
||||
if (h_errno == TRY_AGAIN)
|
||||
nflag = 1;
|
||||
}
|
||||
printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr));
|
||||
if (sdl->sdl_alen)
|
||||
ether_print((u_char *)LLADDR(sdl));
|
||||
else
|
||||
printf("(incomplete)");
|
||||
if (rtm->rtm_rmx.rmx_expire == 0)
|
||||
printf(" permanent");
|
||||
if (sin->sin_other & SIN_PROXY)
|
||||
printf(" published (proxy only)");
|
||||
if (rtm->rtm_addrs & RTA_NETMASK) {
|
||||
sin = (struct sockaddr_inarp *)
|
||||
(sdl->sdl_len + (char *)sdl);
|
||||
if (sin->sin_addr.s_addr == 0xffffffff)
|
||||
printf(" published");
|
||||
if (sin->sin_len != 8)
|
||||
printf("(wierd)");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ether_print(cp)
|
||||
u_char *cp;
|
||||
{
|
||||
printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
|
||||
}
|
||||
|
||||
int
|
||||
ether_aton(a, n)
|
||||
char *a;
|
||||
u_char *n;
|
||||
{
|
||||
int i, o[6];
|
||||
|
||||
i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2],
|
||||
&o[3], &o[4], &o[5]);
|
||||
if (i != 6) {
|
||||
fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a);
|
||||
return (1);
|
||||
}
|
||||
for (i=0; i<6; i++)
|
||||
n[i] = o[i];
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
printf("usage: arp hostname\n");
|
||||
printf(" arp -a [kernel] [kernel_memory]\n");
|
||||
printf(" arp -d hostname\n");
|
||||
printf(" arp -s hostname ether_addr [temp] [pub]\n");
|
||||
printf(" arp -f filename\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
rtmsg(cmd)
|
||||
int cmd;
|
||||
{
|
||||
static int seq;
|
||||
int rlen;
|
||||
register struct rt_msghdr *rtm = &m_rtmsg.m_rtm;
|
||||
register char *cp = m_rtmsg.m_space;
|
||||
register int l;
|
||||
|
||||
errno = 0;
|
||||
if (cmd == RTM_DELETE)
|
||||
goto doit;
|
||||
bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
|
||||
rtm->rtm_flags = flags;
|
||||
rtm->rtm_version = RTM_VERSION;
|
||||
|
||||
switch (cmd) {
|
||||
default:
|
||||
fprintf(stderr, "arp: internal wrong cmd\n");
|
||||
exit(1);
|
||||
case RTM_ADD:
|
||||
rtm->rtm_addrs |= RTA_GATEWAY;
|
||||
rtm->rtm_rmx.rmx_expire = expire_time;
|
||||
rtm->rtm_inits = RTV_EXPIRE;
|
||||
rtm->rtm_flags |= (RTF_HOST | RTF_STATIC);
|
||||
sin_m.sin_other = 0;
|
||||
if (doing_proxy) {
|
||||
if (export_only)
|
||||
sin_m.sin_other = SIN_PROXY;
|
||||
else {
|
||||
rtm->rtm_addrs |= RTA_NETMASK;
|
||||
rtm->rtm_flags &= ~RTF_HOST;
|
||||
}
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case RTM_GET:
|
||||
rtm->rtm_addrs |= RTA_DST;
|
||||
}
|
||||
#define NEXTADDR(w, s) \
|
||||
if (rtm->rtm_addrs & (w)) { \
|
||||
bcopy((char *)&s, cp, sizeof(s)); cp += sizeof(s);}
|
||||
|
||||
NEXTADDR(RTA_DST, sin_m);
|
||||
NEXTADDR(RTA_GATEWAY, sdl_m);
|
||||
NEXTADDR(RTA_NETMASK, so_mask);
|
||||
|
||||
rtm->rtm_msglen = cp - (char *)&m_rtmsg;
|
||||
doit:
|
||||
l = rtm->rtm_msglen;
|
||||
rtm->rtm_seq = ++seq;
|
||||
rtm->rtm_type = cmd;
|
||||
if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
|
||||
if (errno != ESRCH || cmd != RTM_DELETE) {
|
||||
perror("writing to routing socket");
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
do {
|
||||
l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
|
||||
} while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid));
|
||||
if (l < 0)
|
||||
(void) fprintf(stderr, "arp: read from routing socket: %s\n",
|
||||
strerror(errno));
|
||||
return (0);
|
||||
}
|
124
usr.sbin/arp/arp4.4
Normal file
124
usr.sbin/arp/arp4.4
Normal file
@ -0,0 +1,124 @@
|
||||
.\" Copyright (c) 1985, 1986, 1988, 1994
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)arp4.4 6.5 (Berkeley) 4/18/94
|
||||
.\"
|
||||
.Dd April 18, 1994
|
||||
.Dt ARP 4
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm arp
|
||||
.Nd Address Resolution Protocol
|
||||
.Sh SYNOPSIS
|
||||
.Em "pseudo-device ether"
|
||||
.Sh DESCRIPTION
|
||||
The Address Resolution Protocol (ARP) is a protocol used to dynamically
|
||||
map between Internet host addresses and 10Mb/s Ethernet addresses.
|
||||
It is used by all the 10Mb/s Ethernet interface drivers.
|
||||
It is not specific to Internet protocols or to 10Mb/s Ethernet,
|
||||
but this implementation currently supports only that combination.
|
||||
.Pp
|
||||
ARP caches Internet-Ethernet address mappings.
|
||||
When an interface requests a mapping for an address not in the cache,
|
||||
ARP queues the message which requires the mapping and broadcasts
|
||||
a message on the associated network requesting the address mapping.
|
||||
If a response is provided, the new mapping is cached and any pending
|
||||
message is transmitted.
|
||||
ARP will queue at most one packet while waiting for a response to a
|
||||
mapping request;
|
||||
only the most recently ``transmitted'' packet is kept.
|
||||
If the target host does not respond after several requests,
|
||||
the host is considered to be down for a short period (normally 20 seconds),
|
||||
allowing an error to be returned to transmission attempts during this
|
||||
interval.
|
||||
The error is
|
||||
.Li EHOSTDOWN
|
||||
for a non-responding destination host, and
|
||||
.Li EHOSTUNREACH
|
||||
for a non-responding router.
|
||||
.Pp
|
||||
The ARP cache is stored in the system routing table as
|
||||
dynamically-created host routes.
|
||||
The route to a directly-attached Ethernet network is installed as a
|
||||
.Dq cloning
|
||||
route (one with the
|
||||
.Li RTF_CLONING
|
||||
flag set),
|
||||
causing routes to individual hosts on that network to be created on
|
||||
demand.
|
||||
These routes time out periodically (normally 20 minutes after validated;
|
||||
entries are not validated when not in use).
|
||||
An entry for a host which is not responding is a
|
||||
.Dq reject
|
||||
route (one with the
|
||||
.Li RTF_REJECT
|
||||
flag set).
|
||||
.Pp
|
||||
ARP entries may be added, deleted or changed with the
|
||||
.Xr arp 8
|
||||
utility.
|
||||
Manually-added entries may be temporary or permanent,
|
||||
and may be
|
||||
.Dq published ,
|
||||
in which case the system will respond to ARP requests for that host
|
||||
as if it were the target of the request.
|
||||
.Pp
|
||||
In the past,
|
||||
ARP was used to negotiate the use of a trailer encapsulation.
|
||||
This is no longer supported.
|
||||
.Pp
|
||||
ARP watches passively for hosts impersonating the local host (i.e. a host
|
||||
which responds to an ARP mapping request for the local host's address).
|
||||
.Sh DIAGNOSTICS
|
||||
.Em "duplicate IP address %x!! sent from ethernet address: %x:%x:%x:%x:%x:%x."
|
||||
ARP has discovered another host on the local network which responds to
|
||||
mapping requests for its own Internet address with a different Ethernet
|
||||
address, generally indicating that two hosts are attempting to use the
|
||||
same Internet address.
|
||||
.Sh SEE ALSO
|
||||
.Xr inet 4 ,
|
||||
.Xr route 4 ,
|
||||
.Xr arp 8 ,
|
||||
.Xr ifconfig 8 ,
|
||||
.Xr route 8
|
||||
.sp
|
||||
.Rs
|
||||
.%A Plummer, D.
|
||||
.%B "An Ethernet Address Resolution Protocol"
|
||||
.%T RFC826
|
||||
.Re
|
||||
.Rs
|
||||
.%A Leffler, S.J.
|
||||
.%A Karels, M.J.
|
||||
.%B "Trailer Encapsulations
|
||||
.%T RFC893
|
||||
.Re
|
||||
|
662
usr.sbin/bad144/bad144.c
Normal file
662
usr.sbin/bad144/bad144.c
Normal file
@ -0,0 +1,662 @@
|
||||
/*
|
||||
* Copyright (c) 1980, 1986, 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1980, 1986, 1988, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif not lint
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)bad144.c 8.2 (Berkeley) 4/27/95";
|
||||
#endif not lint
|
||||
|
||||
/*
|
||||
* bad144
|
||||
*
|
||||
* This program prints and/or initializes a bad block record for a pack,
|
||||
* in the format used by the DEC standard 144.
|
||||
* It can also add bad sector(s) to the record, moving the sector
|
||||
* replacements as necessary.
|
||||
*
|
||||
* It is preferable to write the bad information with a standard formatter,
|
||||
* but this program will do.
|
||||
*
|
||||
* RP06 sectors are marked as bad by inverting the format bit in the
|
||||
* header; on other drives the valid-sector bit is cleared.
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/dkbad.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <ufs/ffs/fs.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <paths.h>
|
||||
|
||||
#define RETRIES 10 /* number of retries on reading old sectors */
|
||||
#define RAWPART "c" /* disk partition containing badsector tables */
|
||||
|
||||
int fflag, add, copy, verbose, nflag;
|
||||
int compare();
|
||||
int dups;
|
||||
int badfile = -1; /* copy of badsector table to use, -1 if any */
|
||||
#define MAXSECSIZE 1024
|
||||
struct dkbad curbad, oldbad;
|
||||
#define DKBAD_MAGIC 0
|
||||
|
||||
char label[BBSIZE];
|
||||
daddr_t size, getold(), badsn();
|
||||
struct disklabel *dp;
|
||||
char name[BUFSIZ];
|
||||
char *malloc();
|
||||
off_t lseek();
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register struct bt_bad *bt;
|
||||
daddr_t sn, bn[126];
|
||||
int i, f, nbad, new, bad, errs;
|
||||
|
||||
argc--, argv++;
|
||||
while (argc > 0 && **argv == '-') {
|
||||
(*argv)++;
|
||||
while (**argv) {
|
||||
switch (**argv) {
|
||||
#if vax
|
||||
case 'f':
|
||||
fflag++;
|
||||
break;
|
||||
#endif
|
||||
case 'a':
|
||||
add++;
|
||||
break;
|
||||
case 'c':
|
||||
copy++;
|
||||
break;
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
case 'n':
|
||||
nflag++;
|
||||
verbose++;
|
||||
break;
|
||||
default:
|
||||
if (**argv >= '0' && **argv <= '4') {
|
||||
badfile = **argv - '0';
|
||||
break;
|
||||
}
|
||||
goto usage;
|
||||
}
|
||||
(*argv)++;
|
||||
}
|
||||
argc--, argv++;
|
||||
}
|
||||
if (argc < 1) {
|
||||
usage:
|
||||
fprintf(stderr,
|
||||
"usage: bad144 [ -f ] disk [ snum [ bn ... ] ]\n");
|
||||
fprintf(stderr,
|
||||
"to read or overwrite bad-sector table, e.g.: bad144 hp0\n");
|
||||
fprintf(stderr,
|
||||
"or bad144 -a [ -f ] [ -c ] disk bn ...\n");
|
||||
fprintf(stderr, "where options are:\n");
|
||||
fprintf(stderr, "\t-a add new bad sectors to the table\n");
|
||||
fprintf(stderr, "\t-f reformat listed sectors as bad\n");
|
||||
fprintf(stderr, "\t-c copy original sector to replacement\n");
|
||||
exit(1);
|
||||
}
|
||||
if (argv[0][0] != '/')
|
||||
(void)sprintf(name, "%s/r%s%s", _PATH_DEV, argv[0], RAWPART);
|
||||
else
|
||||
strcpy(name, argv[0]);
|
||||
f = open(name, argc == 1? O_RDONLY : O_RDWR);
|
||||
if (f < 0)
|
||||
Perror(name);
|
||||
if (read(f, label, sizeof(label)) < 0)
|
||||
Perror("read");
|
||||
for (dp = (struct disklabel *)(label + LABELOFFSET);
|
||||
dp < (struct disklabel *)
|
||||
(label + sizeof(label) - sizeof(struct disklabel));
|
||||
dp = (struct disklabel *)((char *)dp + 64))
|
||||
if (dp->d_magic == DISKMAGIC && dp->d_magic2 == DISKMAGIC)
|
||||
break;
|
||||
if (dp->d_magic != DISKMAGIC || dp->d_magic2 != DISKMAGIC) {
|
||||
fprintf(stderr, "Bad pack magic number (pack is unlabeled)\n");
|
||||
exit(1);
|
||||
}
|
||||
if (dp->d_secsize > MAXSECSIZE || dp->d_secsize <= 0) {
|
||||
fprintf(stderr, "Disk sector size too large/small (%d)\n",
|
||||
dp->d_secsize);
|
||||
exit(7);
|
||||
}
|
||||
size = dp->d_nsectors * dp->d_ntracks * dp->d_ncylinders;
|
||||
argc--;
|
||||
argv++;
|
||||
if (argc == 0) {
|
||||
sn = getold(f, &oldbad);
|
||||
printf("bad block information at sector %d in %s:\n",
|
||||
sn, name);
|
||||
printf("cartridge serial number: %d(10)\n", oldbad.bt_csn);
|
||||
switch (oldbad.bt_flag) {
|
||||
|
||||
case (u_short)-1:
|
||||
printf("alignment cartridge\n");
|
||||
break;
|
||||
|
||||
case DKBAD_MAGIC:
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("bt_flag=%x(16)?\n", oldbad.bt_flag);
|
||||
break;
|
||||
}
|
||||
bt = oldbad.bt_bad;
|
||||
for (i = 0; i < 126; i++) {
|
||||
bad = (bt->bt_cyl<<16) + bt->bt_trksec;
|
||||
if (bad < 0)
|
||||
break;
|
||||
printf("sn=%d, cn=%d, tn=%d, sn=%d\n", badsn(bt),
|
||||
bt->bt_cyl, bt->bt_trksec>>8, bt->bt_trksec&0xff);
|
||||
bt++;
|
||||
}
|
||||
(void) checkold(&oldbad);
|
||||
exit(0);
|
||||
}
|
||||
if (add) {
|
||||
/*
|
||||
* Read in the old badsector table.
|
||||
* Verify that it makes sense, and the bad sectors
|
||||
* are in order. Copy the old table to the new one.
|
||||
*/
|
||||
(void) getold(f, &oldbad);
|
||||
i = checkold(&oldbad);
|
||||
if (verbose)
|
||||
printf("Had %d bad sectors, adding %d\n", i, argc);
|
||||
if (i + argc > 126) {
|
||||
printf("bad144: not enough room for %d more sectors\n",
|
||||
argc);
|
||||
printf("limited to 126 by information format\n");
|
||||
exit(1);
|
||||
}
|
||||
curbad = oldbad;
|
||||
} else {
|
||||
curbad.bt_csn = atoi(*argv++);
|
||||
argc--;
|
||||
curbad.bt_mbz = 0;
|
||||
curbad.bt_flag = DKBAD_MAGIC;
|
||||
if (argc > 126) {
|
||||
printf("bad144: too many bad sectors specified\n");
|
||||
printf("limited to 126 by information format\n");
|
||||
exit(1);
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
errs = 0;
|
||||
new = argc;
|
||||
while (argc > 0) {
|
||||
daddr_t sn = atoi(*argv++);
|
||||
argc--;
|
||||
if (sn < 0 || sn >= size) {
|
||||
printf("%d: out of range [0,%d) for disk %s\n",
|
||||
sn, size, dp->d_typename);
|
||||
errs++;
|
||||
continue;
|
||||
}
|
||||
bn[i] = sn;
|
||||
curbad.bt_bad[i].bt_cyl = sn / (dp->d_nsectors*dp->d_ntracks);
|
||||
sn %= (dp->d_nsectors*dp->d_ntracks);
|
||||
curbad.bt_bad[i].bt_trksec =
|
||||
((sn/dp->d_nsectors) << 8) + (sn%dp->d_nsectors);
|
||||
i++;
|
||||
}
|
||||
if (errs)
|
||||
exit(1);
|
||||
nbad = i;
|
||||
while (i < 126) {
|
||||
curbad.bt_bad[i].bt_trksec = -1;
|
||||
curbad.bt_bad[i].bt_cyl = -1;
|
||||
i++;
|
||||
}
|
||||
if (add) {
|
||||
/*
|
||||
* Sort the new bad sectors into the list.
|
||||
* Then shuffle the replacement sectors so that
|
||||
* the previous bad sectors get the same replacement data.
|
||||
*/
|
||||
qsort((char *)curbad.bt_bad, nbad, sizeof (struct bt_bad),
|
||||
compare);
|
||||
if (dups) {
|
||||
fprintf(stderr,
|
||||
"bad144: bad sectors have been duplicated; can't add existing sectors\n");
|
||||
exit(3);
|
||||
}
|
||||
shift(f, nbad, nbad-new);
|
||||
}
|
||||
if (badfile == -1)
|
||||
i = 0;
|
||||
else
|
||||
i = badfile * 2;
|
||||
for (; i < 10 && i < dp->d_nsectors; i += 2) {
|
||||
if (lseek(f, dp->d_secsize * (size - dp->d_nsectors + i),
|
||||
L_SET) < 0)
|
||||
Perror("lseek");
|
||||
if (verbose)
|
||||
printf("write badsect file at %d\n",
|
||||
size - dp->d_nsectors + i);
|
||||
if (nflag == 0 && write(f, (caddr_t)&curbad, sizeof(curbad)) !=
|
||||
sizeof(curbad)) {
|
||||
char msg[80];
|
||||
(void)sprintf(msg, "bad144: write bad sector file %d",
|
||||
i/2);
|
||||
perror(msg);
|
||||
}
|
||||
if (badfile != -1)
|
||||
break;
|
||||
}
|
||||
#ifdef vax
|
||||
if (nflag == 0 && fflag)
|
||||
for (i = nbad - new; i < nbad; i++)
|
||||
format(f, bn[i]);
|
||||
#endif
|
||||
#ifdef DIOCSBAD
|
||||
if (nflag == 0 && ioctl(f, DIOCSBAD, (caddr_t)&curbad) < 0)
|
||||
fprintf(stderr,
|
||||
"Can't sync bad-sector file; reboot for changes to take effect\n");
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
|
||||
daddr_t
|
||||
getold(f, bad)
|
||||
struct dkbad *bad;
|
||||
{
|
||||
register int i;
|
||||
daddr_t sn;
|
||||
char msg[80];
|
||||
|
||||
if (badfile == -1)
|
||||
i = 0;
|
||||
else
|
||||
i = badfile * 2;
|
||||
for (; i < 10 && i < dp->d_nsectors; i += 2) {
|
||||
sn = size - dp->d_nsectors + i;
|
||||
if (lseek(f, sn * dp->d_secsize, L_SET) < 0)
|
||||
Perror("lseek");
|
||||
if (read(f, (char *) bad, dp->d_secsize) == dp->d_secsize) {
|
||||
if (i > 0)
|
||||
printf("Using bad-sector file %d\n", i/2);
|
||||
return(sn);
|
||||
}
|
||||
(void)sprintf(msg, "bad144: read bad sector file at sn %d", sn);
|
||||
perror(msg);
|
||||
if (badfile != -1)
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "bad144: %s: can't read bad block info\n", name);
|
||||
exit(1);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
checkold()
|
||||
{
|
||||
register int i;
|
||||
register struct bt_bad *bt;
|
||||
daddr_t sn, lsn;
|
||||
int errors = 0, warned = 0;
|
||||
|
||||
if (oldbad.bt_flag != DKBAD_MAGIC) {
|
||||
fprintf(stderr, "bad144: %s: bad flag in bad-sector table\n",
|
||||
name);
|
||||
errors++;
|
||||
}
|
||||
if (oldbad.bt_mbz != 0) {
|
||||
fprintf(stderr, "bad144: %s: bad magic number\n", name);
|
||||
errors++;
|
||||
}
|
||||
bt = oldbad.bt_bad;
|
||||
for (i = 0; i < 126; i++, bt++) {
|
||||
if (bt->bt_cyl == 0xffff && bt->bt_trksec == 0xffff)
|
||||
break;
|
||||
if ((bt->bt_cyl >= dp->d_ncylinders) ||
|
||||
((bt->bt_trksec >> 8) >= dp->d_ntracks) ||
|
||||
((bt->bt_trksec & 0xff) >= dp->d_nsectors)) {
|
||||
fprintf(stderr,
|
||||
"bad144: cyl/trk/sect out of range in existing entry: ");
|
||||
fprintf(stderr, "sn=%d, cn=%d, tn=%d, sn=%d\n",
|
||||
badsn(bt), bt->bt_cyl, bt->bt_trksec>>8,
|
||||
bt->bt_trksec & 0xff);
|
||||
errors++;
|
||||
}
|
||||
sn = (bt->bt_cyl * dp->d_ntracks +
|
||||
(bt->bt_trksec >> 8)) *
|
||||
dp->d_nsectors + (bt->bt_trksec & 0xff);
|
||||
if (i > 0 && sn < lsn && !warned) {
|
||||
fprintf(stderr,
|
||||
"bad144: bad sector file is out of order\n");
|
||||
errors++;
|
||||
warned++;
|
||||
}
|
||||
if (i > 0 && sn == lsn) {
|
||||
fprintf(stderr,
|
||||
"bad144: bad sector file contains duplicates (sn %d)\n",
|
||||
sn);
|
||||
errors++;
|
||||
}
|
||||
lsn = sn;
|
||||
}
|
||||
if (errors)
|
||||
exit(1);
|
||||
return (i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Move the bad sector replacements
|
||||
* to make room for the new bad sectors.
|
||||
* new is the new number of bad sectors, old is the previous count.
|
||||
*/
|
||||
shift(f, new, old)
|
||||
{
|
||||
daddr_t repl;
|
||||
|
||||
/*
|
||||
* First replacement is last sector of second-to-last track.
|
||||
*/
|
||||
repl = size - dp->d_nsectors - 1;
|
||||
new--; old--;
|
||||
while (new >= 0 && new != old) {
|
||||
if (old < 0 ||
|
||||
compare(&curbad.bt_bad[new], &oldbad.bt_bad[old]) > 0) {
|
||||
/*
|
||||
* Insert new replacement here-- copy original
|
||||
* sector if requested and possible,
|
||||
* otherwise write a zero block.
|
||||
*/
|
||||
if (!copy ||
|
||||
!blkcopy(f, badsn(&curbad.bt_bad[new]), repl - new))
|
||||
blkzero(f, repl - new);
|
||||
} else {
|
||||
if (blkcopy(f, repl - old, repl - new) == 0)
|
||||
fprintf(stderr,
|
||||
"Can't copy replacement sector %d to %d\n",
|
||||
repl-old, repl-new);
|
||||
old--;
|
||||
}
|
||||
new--;
|
||||
}
|
||||
}
|
||||
|
||||
char *buf;
|
||||
|
||||
/*
|
||||
* Copy disk sector s1 to s2.
|
||||
*/
|
||||
blkcopy(f, s1, s2)
|
||||
daddr_t s1, s2;
|
||||
{
|
||||
register tries, n;
|
||||
|
||||
if (buf == (char *)NULL) {
|
||||
buf = malloc((unsigned)dp->d_secsize);
|
||||
if (buf == (char *)NULL) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(20);
|
||||
}
|
||||
}
|
||||
for (tries = 0; tries < RETRIES; tries++) {
|
||||
if (lseek(f, dp->d_secsize * s1, L_SET) < 0)
|
||||
Perror("lseek");
|
||||
if ((n = read(f, buf, dp->d_secsize)) == dp->d_secsize)
|
||||
break;
|
||||
}
|
||||
if (n != dp->d_secsize) {
|
||||
fprintf(stderr, "bad144: can't read sector, %d: ", s1);
|
||||
if (n < 0)
|
||||
perror((char *)0);
|
||||
return(0);
|
||||
}
|
||||
if (lseek(f, dp->d_secsize * s2, L_SET) < 0)
|
||||
Perror("lseek");
|
||||
if (verbose)
|
||||
printf("copying %d to %d\n", s1, s2);
|
||||
if (nflag == 0 && write(f, buf, dp->d_secsize) != dp->d_secsize) {
|
||||
fprintf(stderr,
|
||||
"bad144: can't write replacement sector, %d: ", s2);
|
||||
perror((char *)0);
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
char *zbuf;
|
||||
|
||||
blkzero(f, sn)
|
||||
daddr_t sn;
|
||||
{
|
||||
|
||||
if (zbuf == (char *)NULL) {
|
||||
zbuf = malloc((unsigned)dp->d_secsize);
|
||||
if (zbuf == (char *)NULL) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(20);
|
||||
}
|
||||
}
|
||||
if (lseek(f, dp->d_secsize * sn, L_SET) < 0)
|
||||
Perror("lseek");
|
||||
if (verbose)
|
||||
printf("zeroing %d\n", sn);
|
||||
if (nflag == 0 && write(f, zbuf, dp->d_secsize) != dp->d_secsize) {
|
||||
fprintf(stderr,
|
||||
"bad144: can't write replacement sector, %d: ", sn);
|
||||
perror((char *)0);
|
||||
}
|
||||
}
|
||||
|
||||
compare(b1, b2)
|
||||
register struct bt_bad *b1, *b2;
|
||||
{
|
||||
if (b1->bt_cyl > b2->bt_cyl)
|
||||
return(1);
|
||||
if (b1->bt_cyl < b2->bt_cyl)
|
||||
return(-1);
|
||||
if (b1->bt_trksec == b2->bt_trksec)
|
||||
dups++;
|
||||
return (b1->bt_trksec - b2->bt_trksec);
|
||||
}
|
||||
|
||||
daddr_t
|
||||
badsn(bt)
|
||||
register struct bt_bad *bt;
|
||||
{
|
||||
return ((bt->bt_cyl*dp->d_ntracks + (bt->bt_trksec>>8)) * dp->d_nsectors
|
||||
+ (bt->bt_trksec&0xff));
|
||||
}
|
||||
|
||||
#ifdef vax
|
||||
|
||||
struct rp06hdr {
|
||||
short h_cyl;
|
||||
short h_trksec;
|
||||
short h_key1;
|
||||
short h_key2;
|
||||
char h_data[512];
|
||||
#define RP06_FMT 010000 /* 1 == 16 bit, 0 == 18 bit */
|
||||
};
|
||||
|
||||
/*
|
||||
* Most massbus and unibus drives
|
||||
* have headers of this form
|
||||
*/
|
||||
struct hpuphdr {
|
||||
u_short hpup_cyl;
|
||||
u_char hpup_sect;
|
||||
u_char hpup_track;
|
||||
char hpup_data[512];
|
||||
#define HPUP_OKSECT 0xc000 /* this normally means sector is good */
|
||||
#define HPUP_16BIT 0x1000 /* 1 == 16 bit format */
|
||||
};
|
||||
int rp06format(), hpupformat();
|
||||
|
||||
struct formats {
|
||||
char *f_name; /* disk name */
|
||||
int f_bufsize; /* size of sector + header */
|
||||
int f_bic; /* value to bic in hpup_cyl */
|
||||
int (*f_routine)(); /* routine for special handling */
|
||||
} formats[] = {
|
||||
{ "rp06", sizeof (struct rp06hdr), RP06_FMT, rp06format },
|
||||
{ "eagle", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
|
||||
{ "capricorn", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
|
||||
{ "rm03", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
|
||||
{ "rm05", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
|
||||
{ "9300", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
|
||||
{ "9766", sizeof (struct hpuphdr), HPUP_OKSECT, hpupformat },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
/*ARGSUSED*/
|
||||
hpupformat(fp, dp, blk, buf, count)
|
||||
struct formats *fp;
|
||||
struct disklabel *dp;
|
||||
daddr_t blk;
|
||||
char *buf;
|
||||
int count;
|
||||
{
|
||||
struct hpuphdr *hdr = (struct hpuphdr *)buf;
|
||||
int sect;
|
||||
|
||||
if (count < sizeof(struct hpuphdr)) {
|
||||
hdr->hpup_cyl = (HPUP_OKSECT | HPUP_16BIT) |
|
||||
(blk / (dp->d_nsectors * dp->d_ntracks));
|
||||
sect = blk % (dp->d_nsectors * dp->d_ntracks);
|
||||
hdr->hpup_track = (u_char)(sect / dp->d_nsectors);
|
||||
hdr->hpup_sect = (u_char)(sect % dp->d_nsectors);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
rp06format(fp, dp, blk, buf, count)
|
||||
struct formats *fp;
|
||||
struct disklabel *dp;
|
||||
daddr_t blk;
|
||||
char *buf;
|
||||
int count;
|
||||
{
|
||||
|
||||
if (count < sizeof(struct rp06hdr)) {
|
||||
fprintf(stderr, "Can't read header on blk %d, can't reformat\n",
|
||||
blk);
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
format(fd, blk)
|
||||
int fd;
|
||||
daddr_t blk;
|
||||
{
|
||||
register struct formats *fp;
|
||||
static char *buf;
|
||||
static char bufsize;
|
||||
struct format_op fop;
|
||||
int n;
|
||||
|
||||
for (fp = formats; fp->f_name; fp++)
|
||||
if (strcmp(dp->d_typename, fp->f_name) == 0)
|
||||
break;
|
||||
if (fp->f_name == 0) {
|
||||
fprintf(stderr, "bad144: don't know how to format %s disks\n",
|
||||
dp->d_typename);
|
||||
exit(2);
|
||||
}
|
||||
if (buf && bufsize < fp->f_bufsize) {
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
if (buf == NULL)
|
||||
buf = malloc((unsigned)fp->f_bufsize);
|
||||
if (buf == NULL) {
|
||||
fprintf(stderr, "bad144: can't allocate sector buffer\n");
|
||||
exit(3);
|
||||
}
|
||||
bufsize = fp->f_bufsize;
|
||||
/*
|
||||
* Here we do the actual formatting. All we really
|
||||
* do is rewrite the sector header and flag the bad sector
|
||||
* according to the format table description. If a special
|
||||
* purpose format routine is specified, we allow it to
|
||||
* process the sector as well.
|
||||
*/
|
||||
if (verbose)
|
||||
printf("format blk %d\n", blk);
|
||||
bzero((char *)&fop, sizeof(fop));
|
||||
fop.df_buf = buf;
|
||||
fop.df_count = fp->f_bufsize;
|
||||
fop.df_startblk = blk;
|
||||
bzero(buf, fp->f_bufsize);
|
||||
if (ioctl(fd, DIOCRFORMAT, &fop) < 0)
|
||||
perror("bad144: read format");
|
||||
if (fp->f_routine &&
|
||||
(*fp->f_routine)(fp, dp, blk, buf, fop.df_count) != 0)
|
||||
return;
|
||||
if (fp->f_bic) {
|
||||
struct hpuphdr *xp = (struct hpuphdr *)buf;
|
||||
|
||||
xp->hpup_cyl &= ~fp->f_bic;
|
||||
}
|
||||
if (nflag)
|
||||
return;
|
||||
bzero((char *)&fop, sizeof(fop));
|
||||
fop.df_buf = buf;
|
||||
fop.df_count = fp->f_bufsize;
|
||||
fop.df_startblk = blk;
|
||||
if (ioctl(fd, DIOCWFORMAT, &fop) < 0)
|
||||
Perror("write format");
|
||||
if (fop.df_count != fp->f_bufsize) {
|
||||
char msg[80];
|
||||
(void)sprintf(msg, "bad144: write format %d", blk);
|
||||
perror(msg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Perror(op)
|
||||
char *op;
|
||||
{
|
||||
|
||||
fprintf(stderr, "bad144: "); perror(op);
|
||||
exit(4);
|
||||
}
|
12
usr.sbin/config.new/Makefile
Normal file
12
usr.sbin/config.new/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
# @(#)Makefile 8.3 (Berkeley) 5/29/94
|
||||
|
||||
PROG= config
|
||||
SRCS= files.c gram.y hash.c main.c mkheaders.c mkioconf.c mkmakefile.c \
|
||||
mkswap.c pack.c scan.l sem.c util.c
|
||||
CFLAGS+=-I${.CURDIR} -I.
|
||||
CLEANFILES=gram.c scan.c y.tab.h
|
||||
MAN8= config.0
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
||||
.depend: gram.c scan.c
|
167
usr.sbin/config.new/config.8
Normal file
167
usr.sbin/config.new/config.8
Normal file
@ -0,0 +1,167 @@
|
||||
.\" Copyright (c) 1980, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)config.8 8.2 (Berkeley) 4/19/94
|
||||
.\"
|
||||
.Dd April 19, 1994
|
||||
.Dt CONFIG.NEW 8
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm config.new
|
||||
.Nd build kernel compilation directories
|
||||
.Sh SYNOPSIS
|
||||
.Nm config
|
||||
.Op Fl p
|
||||
.Ar system-name
|
||||
.Sh DESCRIPTION
|
||||
.Pp
|
||||
This is the new version of the
|
||||
.Nm config
|
||||
program.
|
||||
It understands the more modern autoconfiguration scheme
|
||||
used on the SPARC and i386 platforms.
|
||||
The old version of config is still used with the
|
||||
HP300, DECstation, and derivative platforms.
|
||||
Only the version of
|
||||
.Nm config
|
||||
applicable to the architecture that you are running
|
||||
will be installed on your machine.
|
||||
.Pp
|
||||
.Nm Config
|
||||
builds a set of configuration files from the file
|
||||
.Ar system-name ,
|
||||
which describes
|
||||
the system to configure.
|
||||
.Pp
|
||||
.Nm Config
|
||||
should run from the
|
||||
.Pa conf
|
||||
subdirectory of the top-level machine-specific directory
|
||||
of the system source (usually
|
||||
.Pa /sys/MACHINE/conf ,
|
||||
where
|
||||
.Pa MACHINE
|
||||
is one of
|
||||
.Pa vax ,
|
||||
.Pa tahoe ,
|
||||
.Pa hp300 ,
|
||||
and so forth).
|
||||
.Nm Config
|
||||
assumes the directory
|
||||
.Pa ../../compile
|
||||
exists; it places all output files in a subdirectory there,
|
||||
creating the subdirectory if necessary.
|
||||
The subdirectory name is taken from the
|
||||
.Ar system-name ;
|
||||
thus, configuring with
|
||||
.Dq Li config PICKLE
|
||||
will use the directory
|
||||
.Pa ../../compile/PICKLE .
|
||||
.Pp
|
||||
If the
|
||||
.Fl p
|
||||
option is supplied,
|
||||
.Pa .PROF
|
||||
is appended to the compilation directory name, and
|
||||
.Nm config
|
||||
acts as if the lines
|
||||
.Dq Li makeoptions PROF="-pg"
|
||||
and
|
||||
.Dq Li options GPROF
|
||||
appeared in the configuration file.
|
||||
This will build a system that includes profiling code; see
|
||||
.Xr kgmon 8
|
||||
and
|
||||
.Xr gprof 1 .
|
||||
The
|
||||
.Fl p
|
||||
flag is expected to be used for
|
||||
.Dq one-shot
|
||||
profiles of existing systems;
|
||||
for regular profiling,
|
||||
it is probably wiser to make a separate configuration
|
||||
containing the
|
||||
.Li makeoptions
|
||||
line.
|
||||
.Pp
|
||||
The old undocumented
|
||||
.Fl g
|
||||
flag is no longer supported.
|
||||
Instead, use
|
||||
.Dq Li makeoptions DEBUG="-g"
|
||||
and (typically)
|
||||
.Dq Li options KGDB .
|
||||
.Pp
|
||||
The output of
|
||||
.Nm config
|
||||
consists of a number of files, principally
|
||||
.Pa ioconf.c ,
|
||||
a description of I/O devices that may be attached to the system; and a
|
||||
.Pa Makefile ,
|
||||
used by
|
||||
.Xr make 1
|
||||
in building the kernel.
|
||||
.Pp
|
||||
After running
|
||||
.Nm config ,
|
||||
it is wise to run
|
||||
.Dq Li make depend
|
||||
in the directory where the new makefile
|
||||
was created.
|
||||
.Nm Config
|
||||
prints a reminder of this when it completes.
|
||||
.Pp
|
||||
If
|
||||
.Nm config
|
||||
stops due to errors, the problems reported should be corrected and
|
||||
.Nm config
|
||||
should be run again.
|
||||
.Nm Config
|
||||
attempts to avoid changing the compilation directory
|
||||
if there are configuration errors,
|
||||
but this code is not well-tested,
|
||||
and some problems (such as running out of disk space)
|
||||
are unrecoverable.
|
||||
.Sh SEE ALSO
|
||||
The SYNOPSIS portion of each device in section 4.
|
||||
.Rs
|
||||
.%T "Building 4.4 BSD Systems with Config"
|
||||
.\" .%T "Device Support in 4.4BSD"
|
||||
.Re
|
||||
.sp
|
||||
.Xr config 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.1 .
|
||||
It was completely revised in
|
||||
.Bx 4.4 .
|
476
usr.sbin/diskpart/diskpart.c
Normal file
476
usr.sbin/diskpart/diskpart.c
Normal file
@ -0,0 +1,476 @@
|
||||
/*
|
||||
* Copyright (c) 1983, 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1983, 1988, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)diskpart.c 8.3 (Berkeley) 11/30/94";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Program to calculate standard disk partition sizes.
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#define DKTYPENAMES
|
||||
#include <sys/disklabel.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define for_now /* show all of `c' partition for disklabel */
|
||||
#define NPARTITIONS 8
|
||||
#define PART(x) (x - 'a')
|
||||
|
||||
/*
|
||||
* Default partition sizes, where they exist.
|
||||
*/
|
||||
#define NDEFAULTS 4
|
||||
int defpart[NDEFAULTS][NPARTITIONS] = {
|
||||
{ 15884, 66880, 0, 15884, 307200, 0, 0, 291346 }, /* ~ 356+ Mbytes */
|
||||
{ 15884, 33440, 0, 15884, 55936, 0, 0, 291346 }, /* ~ 206-355 Mbytes */
|
||||
{ 15884, 33440, 0, 15884, 55936, 0, 0, 0 }, /* ~ 61-205 Mbytes */
|
||||
{ 15884, 10032, 0, 15884, 0, 0, 0, 0 }, /* ~ 20-60 Mbytes */
|
||||
};
|
||||
|
||||
/*
|
||||
* Each array defines a layout for a disk;
|
||||
* that is, the collection of partitions totally
|
||||
* covers the physical space on a disk.
|
||||
*/
|
||||
#define NLAYOUTS 3
|
||||
char layouts[NLAYOUTS][NPARTITIONS] = {
|
||||
{ 'a', 'b', 'h', 'g' },
|
||||
{ 'a', 'b', 'h', 'd', 'e', 'f' },
|
||||
{ 'c' },
|
||||
};
|
||||
|
||||
/*
|
||||
* Default disk block and disk block fragment
|
||||
* sizes for each file system. Those file systems
|
||||
* with zero block and frag sizes are special cases
|
||||
* (e.g. swap areas or for access to the entire device).
|
||||
*/
|
||||
struct partition defparam[NPARTITIONS] = {
|
||||
{ 0, 0, 1024, FS_UNUSED, 8, 0 }, /* a */
|
||||
{ 0, 0, 1024, FS_SWAP, 8, 0 }, /* b */
|
||||
{ 0, 0, 1024, FS_UNUSED, 8, 0 }, /* c */
|
||||
{ 0, 0, 512, FS_UNUSED, 8, 0 }, /* d */
|
||||
{ 0, 0, 1024, FS_UNUSED, 8, 0 }, /* e */
|
||||
{ 0, 0, 1024, FS_UNUSED, 8, 0 }, /* f */
|
||||
{ 0, 0, 1024, FS_UNUSED, 8, 0 }, /* g */
|
||||
{ 0, 0, 1024, FS_UNUSED, 8, 0 } /* h */
|
||||
};
|
||||
|
||||
/*
|
||||
* Each disk has some space reserved for a bad sector
|
||||
* forwarding table. DEC standard 144 uses the first
|
||||
* 5 even numbered sectors in the last track of the
|
||||
* last cylinder for replicated storage of the bad sector
|
||||
* table; another 126 sectors past this is needed as a
|
||||
* pool of replacement sectors.
|
||||
*/
|
||||
int badsecttable = 126; /* # sectors */
|
||||
|
||||
int pflag; /* print device driver partition tables */
|
||||
int dflag; /* print disktab entry */
|
||||
|
||||
struct disklabel *promptfordisk();
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
struct disklabel *dp;
|
||||
register int curcyl, spc, def, part, layout, j;
|
||||
int threshhold, numcyls[NPARTITIONS], startcyl[NPARTITIONS];
|
||||
int totsize = 0;
|
||||
char *lp, *tyname;
|
||||
|
||||
argc--, argv++;
|
||||
if (argc < 1) {
|
||||
fprintf(stderr,
|
||||
"usage: disktab [ -p ] [ -d ] [ -s size ] disk-type\n");
|
||||
exit(1);
|
||||
}
|
||||
if (argc > 0 && strcmp(*argv, "-p") == 0) {
|
||||
pflag++;
|
||||
argc--, argv++;
|
||||
}
|
||||
if (argc > 0 && strcmp(*argv, "-d") == 0) {
|
||||
dflag++;
|
||||
argc--, argv++;
|
||||
}
|
||||
if (argc > 1 && strcmp(*argv, "-s") == 0) {
|
||||
totsize = atoi(argv[1]);
|
||||
argc += 2, argv += 2;
|
||||
}
|
||||
dp = getdiskbyname(*argv);
|
||||
if (dp == NULL) {
|
||||
if (isatty(0))
|
||||
dp = promptfordisk(*argv);
|
||||
if (dp == NULL) {
|
||||
fprintf(stderr, "%s: unknown disk type\n", *argv);
|
||||
exit(2);
|
||||
}
|
||||
} else {
|
||||
if (dp->d_flags & D_REMOVABLE)
|
||||
tyname = "removable";
|
||||
else if (dp->d_flags & D_RAMDISK)
|
||||
tyname = "simulated";
|
||||
else
|
||||
tyname = "winchester";
|
||||
}
|
||||
spc = dp->d_secpercyl;
|
||||
/*
|
||||
* Bad sector table contains one track for the replicated
|
||||
* copies of the table and enough full tracks preceding
|
||||
* the last track to hold the pool of free blocks to which
|
||||
* bad sectors are mapped.
|
||||
* If disk size was specified explicitly, use specified size.
|
||||
*/
|
||||
if (dp->d_type == DTYPE_SMD && dp->d_flags & D_BADSECT &&
|
||||
totsize == 0) {
|
||||
badsecttable = dp->d_nsectors +
|
||||
roundup(badsecttable, dp->d_nsectors);
|
||||
threshhold = howmany(spc, badsecttable);
|
||||
} else {
|
||||
badsecttable = 0;
|
||||
threshhold = 0;
|
||||
}
|
||||
/*
|
||||
* If disk size was specified, recompute number of cylinders
|
||||
* that may be used, and set badsecttable to any remaining
|
||||
* fraction of the last cylinder.
|
||||
*/
|
||||
if (totsize != 0) {
|
||||
dp->d_ncylinders = howmany(totsize, spc);
|
||||
badsecttable = spc * dp->d_ncylinders - totsize;
|
||||
}
|
||||
|
||||
/*
|
||||
* Figure out if disk is large enough for
|
||||
* expanded swap area and 'd', 'e', and 'f'
|
||||
* partitions. Otherwise, use smaller defaults
|
||||
* based on RK07.
|
||||
*/
|
||||
for (def = 0; def < NDEFAULTS; def++) {
|
||||
curcyl = 0;
|
||||
for (part = PART('a'); part < NPARTITIONS; part++)
|
||||
curcyl += howmany(defpart[def][part], spc);
|
||||
if (curcyl < dp->d_ncylinders - threshhold)
|
||||
break;
|
||||
}
|
||||
if (def >= NDEFAULTS) {
|
||||
fprintf(stderr, "%s: disk too small, calculate by hand\n",
|
||||
*argv);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate number of cylinders allocated to each disk
|
||||
* partition. We may waste a bit of space here, but it's
|
||||
* in the interest of (very backward) compatibility
|
||||
* (for mixed disk systems).
|
||||
*/
|
||||
for (curcyl = 0, part = PART('a'); part < NPARTITIONS; part++) {
|
||||
numcyls[part] = 0;
|
||||
if (defpart[def][part] != 0) {
|
||||
numcyls[part] = howmany(defpart[def][part], spc);
|
||||
curcyl += numcyls[part];
|
||||
}
|
||||
}
|
||||
numcyls[PART('f')] = dp->d_ncylinders - curcyl;
|
||||
numcyls[PART('g')] =
|
||||
numcyls[PART('d')] + numcyls[PART('e')] + numcyls[PART('f')];
|
||||
numcyls[PART('c')] = dp->d_ncylinders;
|
||||
defpart[def][PART('f')] = numcyls[PART('f')] * spc - badsecttable;
|
||||
defpart[def][PART('g')] = numcyls[PART('g')] * spc - badsecttable;
|
||||
defpart[def][PART('c')] = numcyls[PART('c')] * spc;
|
||||
#ifndef for_now
|
||||
if (totsize || !pflag)
|
||||
#else
|
||||
if (totsize)
|
||||
#endif
|
||||
defpart[def][PART('c')] -= badsecttable;
|
||||
|
||||
/*
|
||||
* Calculate starting cylinder number for each partition.
|
||||
* Note the 'h' partition is physically located before the
|
||||
* 'g' or 'd' partition. This is reflected in the layout
|
||||
* arrays defined above.
|
||||
*/
|
||||
for (layout = 0; layout < NLAYOUTS; layout++) {
|
||||
curcyl = 0;
|
||||
for (lp = layouts[layout]; *lp != 0; lp++) {
|
||||
startcyl[PART(*lp)] = curcyl;
|
||||
curcyl += numcyls[PART(*lp)];
|
||||
}
|
||||
}
|
||||
|
||||
if (pflag) {
|
||||
printf("}, %s_sizes[%d] = {\n", dp->d_typename, NPARTITIONS);
|
||||
for (part = PART('a'); part < NPARTITIONS; part++) {
|
||||
if (numcyls[part] == 0) {
|
||||
printf("\t0,\t0,\n");
|
||||
continue;
|
||||
}
|
||||
if (dp->d_type != DTYPE_MSCP) {
|
||||
printf("\t%d,\t%d,\t\t/* %c=cyl %d thru %d */\n",
|
||||
defpart[def][part], startcyl[part],
|
||||
'A' + part, startcyl[part],
|
||||
startcyl[part] + numcyls[part] - 1);
|
||||
continue;
|
||||
}
|
||||
printf("\t%d,\t%d,\t\t/* %c=sectors %d thru %d */\n",
|
||||
defpart[def][part], spc * startcyl[part],
|
||||
'A' + part, spc * startcyl[part],
|
||||
spc * startcyl[part] + defpart[def][part] - 1);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
if (dflag) {
|
||||
int nparts;
|
||||
|
||||
/*
|
||||
* In case the disk is in the ``in-between'' range
|
||||
* where the 'g' partition is smaller than the 'h'
|
||||
* partition, reverse the frag sizes so the /usr partition
|
||||
* is always set up with a frag size larger than the
|
||||
* user's partition.
|
||||
*/
|
||||
if (defpart[def][PART('g')] < defpart[def][PART('h')]) {
|
||||
int temp;
|
||||
|
||||
temp = defparam[PART('h')].p_fsize;
|
||||
defparam[PART('h')].p_fsize =
|
||||
defparam[PART('g')].p_fsize;
|
||||
defparam[PART('g')].p_fsize = temp;
|
||||
}
|
||||
printf("%s:\\\n", dp->d_typename);
|
||||
printf("\t:ty=%s:ns#%d:nt#%d:nc#%d:", tyname,
|
||||
dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders);
|
||||
if (dp->d_secpercyl != dp->d_nsectors * dp->d_ntracks)
|
||||
printf("sc#%d:", dp->d_secpercyl);
|
||||
if (dp->d_type == DTYPE_SMD && dp->d_flags & D_BADSECT)
|
||||
printf("sf:");
|
||||
printf("\\\n\t:dt=%s:", dktypenames[dp->d_type]);
|
||||
for (part = NDDATA - 1; part >= 0; part--)
|
||||
if (dp->d_drivedata[part])
|
||||
break;
|
||||
for (j = 0; j <= part; j++)
|
||||
printf("d%d#%d:", j, dp->d_drivedata[j]);
|
||||
printf("\\\n");
|
||||
for (nparts = 0, part = PART('a'); part < NPARTITIONS; part++)
|
||||
if (defpart[def][part] != 0)
|
||||
nparts++;
|
||||
for (part = PART('a'); part < NPARTITIONS; part++) {
|
||||
if (defpart[def][part] == 0)
|
||||
continue;
|
||||
printf("\t:p%c#%d:", 'a' + part, defpart[def][part]);
|
||||
printf("o%c#%d:b%c#%d:f%c#%d:",
|
||||
'a' + part, spc * startcyl[part],
|
||||
'a' + part,
|
||||
defparam[part].p_frag * defparam[part].p_fsize,
|
||||
'a' + part, defparam[part].p_fsize);
|
||||
if (defparam[part].p_fstype == FS_SWAP)
|
||||
printf("t%c=swap:", 'a' + part);
|
||||
nparts--;
|
||||
printf("%s\n", nparts > 0 ? "\\" : "");
|
||||
}
|
||||
#ifdef for_now
|
||||
defpart[def][PART('c')] -= badsecttable;
|
||||
part = PART('c');
|
||||
printf("#\t:p%c#%d:", 'a' + part, defpart[def][part]);
|
||||
printf("o%c#%d:b%c#%d:f%c#%d:\n",
|
||||
'a' + part, spc * startcyl[part],
|
||||
'a' + part,
|
||||
defparam[part].p_frag * defparam[part].p_fsize,
|
||||
'a' + part, defparam[part].p_fsize);
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
printf("%s: #sectors/track=%d, #tracks/cylinder=%d #cylinders=%d\n",
|
||||
dp->d_typename, dp->d_nsectors, dp->d_ntracks,
|
||||
dp->d_ncylinders);
|
||||
printf("\n Partition\t Size\t Offset\t Range\n");
|
||||
for (part = PART('a'); part < NPARTITIONS; part++) {
|
||||
printf("\t%c\t", 'a' + part);
|
||||
if (numcyls[part] == 0) {
|
||||
printf(" unused\n");
|
||||
continue;
|
||||
}
|
||||
printf("%7d\t%7d\t%4d - %d%s\n",
|
||||
defpart[def][part], startcyl[part] * spc,
|
||||
startcyl[part], startcyl[part] + numcyls[part] - 1,
|
||||
defpart[def][part] % spc ? "*" : "");
|
||||
}
|
||||
}
|
||||
|
||||
struct disklabel disk;
|
||||
|
||||
struct field {
|
||||
char *f_name;
|
||||
char *f_defaults;
|
||||
u_int32_t *f_location;
|
||||
} fields[] = {
|
||||
{ "sector size", "512", &disk.d_secsize },
|
||||
{ "#sectors/track", 0, &disk.d_nsectors },
|
||||
{ "#tracks/cylinder", 0, &disk.d_ntracks },
|
||||
{ "#cylinders", 0, &disk.d_ncylinders },
|
||||
{ 0, 0, 0 },
|
||||
};
|
||||
|
||||
struct disklabel *
|
||||
promptfordisk(name)
|
||||
char *name;
|
||||
{
|
||||
register struct disklabel *dp = &disk;
|
||||
register struct field *fp;
|
||||
register i;
|
||||
char buf[BUFSIZ], **tp, *cp, *gets();
|
||||
|
||||
strncpy(dp->d_typename, name, sizeof(dp->d_typename));
|
||||
fprintf(stderr,
|
||||
"%s: unknown disk type, want to supply parameters (y/n)? ",
|
||||
name);
|
||||
(void) gets(buf);
|
||||
if (*buf != 'y')
|
||||
return ((struct disklabel *)0);
|
||||
for (;;) {
|
||||
fprintf(stderr, "Disk/controller type (%s)? ", dktypenames[1]);
|
||||
(void) gets(buf);
|
||||
if (buf[0] == 0) {
|
||||
dp->d_type = 1;
|
||||
break;
|
||||
}
|
||||
if ((i = gettype(buf, dktypenames)) >= 0) {
|
||||
dp->d_type = i;
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "%s: unrecognized controller type\n", buf);
|
||||
fprintf(stderr, "use one of:\n", buf);
|
||||
for (tp = dktypenames; *tp; tp++)
|
||||
if (index(*tp, ' ') == 0)
|
||||
fprintf(stderr, "\t%s\n", *tp);
|
||||
}
|
||||
gettype:
|
||||
dp->d_flags = 0;
|
||||
fprintf(stderr, "type (winchester|removable|simulated)? ");
|
||||
(void) gets(buf);
|
||||
if (strcmp(buf, "removable") == 0)
|
||||
dp->d_flags = D_REMOVABLE;
|
||||
else if (strcmp(buf, "simulated") == 0)
|
||||
dp->d_flags = D_RAMDISK;
|
||||
else if (strcmp(buf, "winchester")) {
|
||||
fprintf(stderr, "%s: bad disk type\n", buf);
|
||||
goto gettype;
|
||||
}
|
||||
strncpy(dp->d_typename, buf, sizeof(dp->d_typename));
|
||||
fprintf(stderr, "(type <cr> to get default value, if only one)\n");
|
||||
if (dp->d_type == DTYPE_SMD)
|
||||
fprintf(stderr, "Do %ss support bad144 bad block forwarding (yes)? ",
|
||||
dp->d_typename);
|
||||
(void) gets(buf);
|
||||
if (*buf != 'n')
|
||||
dp->d_flags |= D_BADSECT;
|
||||
for (fp = fields; fp->f_name != NULL; fp++) {
|
||||
again:
|
||||
fprintf(stderr, "%s ", fp->f_name);
|
||||
if (fp->f_defaults != NULL)
|
||||
fprintf(stderr, "(%s)", fp->f_defaults);
|
||||
fprintf(stderr, "? ");
|
||||
cp = gets(buf);
|
||||
if (*cp == '\0') {
|
||||
if (fp->f_defaults == NULL) {
|
||||
fprintf(stderr, "no default value\n");
|
||||
goto again;
|
||||
}
|
||||
cp = fp->f_defaults;
|
||||
}
|
||||
*fp->f_location = atol(cp);
|
||||
if (*fp->f_location == 0) {
|
||||
fprintf(stderr, "%s: bad value\n", cp);
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "sectors/cylinder (%d)? ",
|
||||
dp->d_nsectors * dp->d_ntracks);
|
||||
(void) gets(buf);
|
||||
if (buf[0] == 0)
|
||||
dp->d_secpercyl = dp->d_nsectors * dp->d_ntracks;
|
||||
else
|
||||
dp->d_secpercyl = atol(buf);
|
||||
fprintf(stderr, "Drive-type-specific parameters, <cr> to terminate:\n");
|
||||
for (i = 0; i < NDDATA; i++) {
|
||||
fprintf(stderr, "d%d? ", i);
|
||||
(void) gets(buf);
|
||||
if (buf[0] == 0)
|
||||
break;
|
||||
dp->d_drivedata[i] = atol(buf);
|
||||
}
|
||||
return (dp);
|
||||
}
|
||||
|
||||
gettype(t, names)
|
||||
char *t;
|
||||
char **names;
|
||||
{
|
||||
register char **nm;
|
||||
|
||||
for (nm = names; *nm; nm++)
|
||||
if (ustrcmp(t, *nm) == 0)
|
||||
return (nm - names);
|
||||
if (isdigit(*t))
|
||||
return (atoi(t));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
ustrcmp(s1, s2)
|
||||
register char *s1, *s2;
|
||||
{
|
||||
#define lower(c) (islower(c) ? (c) : tolower(c))
|
||||
|
||||
for (; *s1; s1++, s2++) {
|
||||
if (*s1 == *s2)
|
||||
continue;
|
||||
if (isalpha(*s1) && isalpha(*s2) &&
|
||||
lower(*s1) == lower(*s2))
|
||||
continue;
|
||||
return (*s2 - *s1);
|
||||
}
|
||||
return (0);
|
||||
}
|
160
usr.sbin/edquota/edquota.8
Normal file
160
usr.sbin/edquota/edquota.8
Normal file
@ -0,0 +1,160 @@
|
||||
.\" Copyright (c) 1983, 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" Robert Elz at The University of Melbourne.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)edquota.8 8.2 (Berkeley) 4/27/95
|
||||
.\"
|
||||
.Dd "April 27, 1995"
|
||||
.Dt EDQUOTA 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm edquota
|
||||
.Nd edit user quotas
|
||||
.Sh SYNOPSIS
|
||||
.Nm edquota
|
||||
.Op Fl u
|
||||
.Op Fl p Ar proto-username
|
||||
.Ar username ...
|
||||
.Nm edquota
|
||||
.Fl g
|
||||
.Op Fl p Ar proto-groupname
|
||||
.Ar groupname ...
|
||||
.Nm edquota
|
||||
.Fl t
|
||||
.Op Fl u
|
||||
.Nm edquota
|
||||
.Fl t
|
||||
.Fl g
|
||||
.Sh DESCRIPTION
|
||||
.Nm Edquota
|
||||
is a quota editor.
|
||||
By default, or if the
|
||||
.Fl u
|
||||
flag is specified,
|
||||
one or more users may be specified on the command line.
|
||||
For each user a temporary file is created
|
||||
with an ASCII representation of the current
|
||||
disk quotas for that user.
|
||||
The list of filesystems with user quotas is determined from
|
||||
.Pa /etc/fstab .
|
||||
An editor is invoked on the ASCII file.
|
||||
The editor invoked is
|
||||
.Xr vi 1
|
||||
unless the environment variable
|
||||
.Ev EDITOR
|
||||
specifies otherwise.
|
||||
.Pp
|
||||
The quotas may then be modified, new quotas added, etc.
|
||||
Setting a quota to zero indicates that no quota should be imposed.
|
||||
Setting a hard limit to one indicates that no allocations should
|
||||
be permitted.
|
||||
Setting a soft limit to one with a hard limit of zero
|
||||
indicates that allocations should be permitted on
|
||||
only a temporary basis (see
|
||||
.Fl t
|
||||
below).
|
||||
The current usage information in the file is for informational purposes;
|
||||
only the hard and soft limits can be changed.
|
||||
.Pp
|
||||
On leaving the editor,
|
||||
.Nm edquota
|
||||
reads the temporary file and modifies the binary
|
||||
quota files to reflect the changes made.
|
||||
.Pp
|
||||
If the
|
||||
.Fl p
|
||||
flag is specified,
|
||||
.Nm edquota
|
||||
will duplicate the quotas of the prototypical user
|
||||
specified for each user specified.
|
||||
This is the normal mechanism used to
|
||||
initialize quotas for groups of users.
|
||||
.Pp
|
||||
If the
|
||||
.Fl g
|
||||
flag is specified,
|
||||
.Nm edquota
|
||||
is invoked to edit the quotas of
|
||||
one or more groups specified on the command line.
|
||||
The
|
||||
.Fl p
|
||||
flag can be specified in conjunction with
|
||||
the
|
||||
.Fl g
|
||||
flag to specify a prototypical group
|
||||
to be duplicated among the listed set of groups.
|
||||
.Pp
|
||||
Users are permitted to exceed their soft limits
|
||||
for a grace period that may be specified per filesystem.
|
||||
Once the grace period has expired,
|
||||
the soft limit is enforced as a hard limit.
|
||||
The default grace period for a filesystem is specified in
|
||||
.Pa /usr/include/ufs/ufs/quota.h .
|
||||
The
|
||||
.Fl t
|
||||
flag can be used to change the grace period.
|
||||
By default, or when invoked with the
|
||||
.Fl u
|
||||
flag, the grace period is set for all the filesystems with user
|
||||
quotas specified in
|
||||
.Pa /etc/fstab .
|
||||
When invoked with the
|
||||
.Fl g
|
||||
flag the grace period is
|
||||
set for all the filesystems with group quotas specified in
|
||||
.Pa /etc/fstab .
|
||||
The grace period may be specified in days, hours, minutes, or seconds.
|
||||
Setting a grace period to zero indicates that the default
|
||||
grace period should be imposed.
|
||||
Setting a grace period to one second indicates that no
|
||||
grace period should be granted.
|
||||
.Pp
|
||||
Only the super-user may edit quotas.
|
||||
.Sh FILES
|
||||
.Bl -tag -width 24n -compact
|
||||
.It Pa quota.user
|
||||
at the filesystem root with user quotas
|
||||
.It Pa quota.group
|
||||
at the filesystem root with group quotas
|
||||
.It Pa /etc/fstab
|
||||
to find filesystem names and locations
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr quota 1 ,
|
||||
.Xr quotactl 2 ,
|
||||
.Xr fstab 5 ,
|
||||
.Xr quotacheck 8 ,
|
||||
.Xr quotaon 8 ,
|
||||
.Xr repquota 8
|
||||
.Sh DIAGNOSTICS
|
||||
Various messages about inaccessible files; self-explanatory.
|
724
usr.sbin/edquota/edquota.c
Normal file
724
usr.sbin/edquota/edquota.c
Normal file
@ -0,0 +1,724 @@
|
||||
/*
|
||||
* Copyright (c) 1980, 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Robert Elz at The University of Melbourne.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1980, 1990, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)edquota.c 8.3 (Berkeley) 4/27/95";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Disk quota editor.
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/queue.h>
|
||||
#include <ufs/ufs/quota.h>
|
||||
#include <errno.h>
|
||||
#include <fstab.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "pathnames.h"
|
||||
|
||||
char *qfname = QUOTAFILENAME;
|
||||
char *qfextension[] = INITQFNAMES;
|
||||
char *quotagroup = QUOTAGROUP;
|
||||
char tmpfil[] = _PATH_TMP;
|
||||
|
||||
struct quotause {
|
||||
struct quotause *next;
|
||||
long flags;
|
||||
struct dqblk dqblk;
|
||||
char fsname[MAXPATHLEN + 1];
|
||||
char qfname[1]; /* actually longer */
|
||||
} *getprivs();
|
||||
#define FOUND 0x01
|
||||
|
||||
main(argc, argv)
|
||||
register char **argv;
|
||||
int argc;
|
||||
{
|
||||
register struct quotause *qup, *protoprivs, *curprivs;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
register long id, protoid;
|
||||
register int quotatype, tmpfd;
|
||||
char *protoname, ch;
|
||||
int tflag = 0, pflag = 0;
|
||||
|
||||
if (argc < 2)
|
||||
usage();
|
||||
if (getuid()) {
|
||||
fprintf(stderr, "edquota: permission denied\n");
|
||||
exit(1);
|
||||
}
|
||||
quotatype = USRQUOTA;
|
||||
while ((ch = getopt(argc, argv, "ugtp:")) != EOF) {
|
||||
switch(ch) {
|
||||
case 'p':
|
||||
protoname = optarg;
|
||||
pflag++;
|
||||
break;
|
||||
case 'g':
|
||||
quotatype = GRPQUOTA;
|
||||
break;
|
||||
case 'u':
|
||||
quotatype = USRQUOTA;
|
||||
break;
|
||||
case 't':
|
||||
tflag++;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (pflag) {
|
||||
if ((protoid = getentry(protoname, quotatype)) == -1)
|
||||
exit(1);
|
||||
protoprivs = getprivs(protoid, quotatype);
|
||||
for (qup = protoprivs; qup; qup = qup->next) {
|
||||
qup->dqblk.dqb_btime = 0;
|
||||
qup->dqblk.dqb_itime = 0;
|
||||
}
|
||||
while (argc-- > 0) {
|
||||
if ((id = getentry(*argv++, quotatype)) < 0)
|
||||
continue;
|
||||
putprivs(id, quotatype, protoprivs);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
tmpfd = mkstemp(tmpfil);
|
||||
fchown(tmpfd, getuid(), getgid());
|
||||
if (tflag) {
|
||||
protoprivs = getprivs(0, quotatype);
|
||||
if (writetimes(protoprivs, tmpfd, quotatype) == 0)
|
||||
exit(1);
|
||||
if (editit(tmpfil) && readtimes(protoprivs, tmpfd))
|
||||
putprivs(0, quotatype, protoprivs);
|
||||
freeprivs(protoprivs);
|
||||
exit(0);
|
||||
}
|
||||
for ( ; argc > 0; argc--, argv++) {
|
||||
if ((id = getentry(*argv, quotatype)) == -1)
|
||||
continue;
|
||||
curprivs = getprivs(id, quotatype);
|
||||
if (writeprivs(curprivs, tmpfd, *argv, quotatype) == 0)
|
||||
continue;
|
||||
if (editit(tmpfil) && readprivs(curprivs, tmpfd))
|
||||
putprivs(id, quotatype, curprivs);
|
||||
freeprivs(curprivs);
|
||||
}
|
||||
close(tmpfd);
|
||||
unlink(tmpfil);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "%s%s%s%s",
|
||||
"Usage: edquota [-u] [-p username] username ...\n",
|
||||
"\tedquota -g [-p groupname] groupname ...\n",
|
||||
"\tedquota [-u] -t\n", "\tedquota -g -t\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine converts a name for a particular quota type to
|
||||
* an identifier. This routine must agree with the kernel routine
|
||||
* getinoquota as to the interpretation of quota types.
|
||||
*/
|
||||
getentry(name, quotatype)
|
||||
char *name;
|
||||
int quotatype;
|
||||
{
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
|
||||
if (alldigits(name))
|
||||
return (atoi(name));
|
||||
switch(quotatype) {
|
||||
case USRQUOTA:
|
||||
if (pw = getpwnam(name))
|
||||
return (pw->pw_uid);
|
||||
fprintf(stderr, "%s: no such user\n", name);
|
||||
break;
|
||||
case GRPQUOTA:
|
||||
if (gr = getgrnam(name))
|
||||
return (gr->gr_gid);
|
||||
fprintf(stderr, "%s: no such group\n", name);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%d: unknown quota type\n", quotatype);
|
||||
break;
|
||||
}
|
||||
sleep(1);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Collect the requested quota information.
|
||||
*/
|
||||
struct quotause *
|
||||
getprivs(id, quotatype)
|
||||
register long id;
|
||||
int quotatype;
|
||||
{
|
||||
register struct fstab *fs;
|
||||
register struct quotause *qup, *quptail;
|
||||
struct quotause *quphead;
|
||||
int qcmd, qupsize, fd;
|
||||
char *qfpathname;
|
||||
static int warned = 0;
|
||||
extern int errno;
|
||||
|
||||
setfsent();
|
||||
quphead = (struct quotause *)0;
|
||||
qcmd = QCMD(Q_GETQUOTA, quotatype);
|
||||
while (fs = getfsent()) {
|
||||
if (strcmp(fs->fs_vfstype, "ufs"))
|
||||
continue;
|
||||
if (!hasquota(fs, quotatype, &qfpathname))
|
||||
continue;
|
||||
qupsize = sizeof(*qup) + strlen(qfpathname);
|
||||
if ((qup = (struct quotause *)malloc(qupsize)) == NULL) {
|
||||
fprintf(stderr, "edquota: out of memory\n");
|
||||
exit(2);
|
||||
}
|
||||
if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) {
|
||||
if (errno == EOPNOTSUPP && !warned) {
|
||||
warned++;
|
||||
fprintf(stderr, "Warning: %s\n",
|
||||
"Quotas are not compiled into this kernel");
|
||||
sleep(3);
|
||||
}
|
||||
if ((fd = open(qfpathname, O_RDONLY)) < 0) {
|
||||
fd = open(qfpathname, O_RDWR|O_CREAT, 0640);
|
||||
if (fd < 0 && errno != ENOENT) {
|
||||
perror(qfpathname);
|
||||
free(qup);
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "Creating quota file %s\n",
|
||||
qfpathname);
|
||||
sleep(3);
|
||||
(void) fchown(fd, getuid(),
|
||||
getentry(quotagroup, GRPQUOTA));
|
||||
(void) fchmod(fd, 0640);
|
||||
}
|
||||
lseek(fd, (off_t)(id * sizeof(struct dqblk)), L_SET);
|
||||
switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) {
|
||||
case 0: /* EOF */
|
||||
/*
|
||||
* Convert implicit 0 quota (EOF)
|
||||
* into an explicit one (zero'ed dqblk)
|
||||
*/
|
||||
bzero((caddr_t)&qup->dqblk,
|
||||
sizeof(struct dqblk));
|
||||
break;
|
||||
|
||||
case sizeof(struct dqblk): /* OK */
|
||||
break;
|
||||
|
||||
default: /* ERROR */
|
||||
fprintf(stderr, "edquota: read error in ");
|
||||
perror(qfpathname);
|
||||
close(fd);
|
||||
free(qup);
|
||||
continue;
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
strcpy(qup->qfname, qfpathname);
|
||||
strcpy(qup->fsname, fs->fs_file);
|
||||
if (quphead == NULL)
|
||||
quphead = qup;
|
||||
else
|
||||
quptail->next = qup;
|
||||
quptail = qup;
|
||||
qup->next = 0;
|
||||
}
|
||||
endfsent();
|
||||
return (quphead);
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the requested quota information.
|
||||
*/
|
||||
putprivs(id, quotatype, quplist)
|
||||
long id;
|
||||
int quotatype;
|
||||
struct quotause *quplist;
|
||||
{
|
||||
register struct quotause *qup;
|
||||
int qcmd, fd;
|
||||
|
||||
qcmd = QCMD(Q_SETQUOTA, quotatype);
|
||||
for (qup = quplist; qup; qup = qup->next) {
|
||||
if (quotactl(qup->fsname, qcmd, id, &qup->dqblk) == 0)
|
||||
continue;
|
||||
if ((fd = open(qup->qfname, O_WRONLY)) < 0) {
|
||||
perror(qup->qfname);
|
||||
} else {
|
||||
lseek(fd,
|
||||
(off_t)(id * (long)sizeof (struct dqblk)), L_SET);
|
||||
if (write(fd, &qup->dqblk, sizeof (struct dqblk)) !=
|
||||
sizeof (struct dqblk)) {
|
||||
fprintf(stderr, "edquota: ");
|
||||
perror(qup->qfname);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Take a list of priviledges and get it edited.
|
||||
*/
|
||||
editit(tmpfile)
|
||||
char *tmpfile;
|
||||
{
|
||||
long omask;
|
||||
int pid, stat;
|
||||
extern char *getenv();
|
||||
|
||||
omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
|
||||
top:
|
||||
if ((pid = fork()) < 0) {
|
||||
extern errno;
|
||||
|
||||
if (errno == EPROCLIM) {
|
||||
fprintf(stderr, "You have too many processes\n");
|
||||
return(0);
|
||||
}
|
||||
if (errno == EAGAIN) {
|
||||
sleep(1);
|
||||
goto top;
|
||||
}
|
||||
perror("fork");
|
||||
return (0);
|
||||
}
|
||||
if (pid == 0) {
|
||||
register char *ed;
|
||||
|
||||
sigsetmask(omask);
|
||||
setgid(getgid());
|
||||
setuid(getuid());
|
||||
if ((ed = getenv("EDITOR")) == (char *)0)
|
||||
ed = _PATH_VI;
|
||||
execlp(ed, ed, tmpfile, 0);
|
||||
perror(ed);
|
||||
exit(1);
|
||||
}
|
||||
waitpid(pid, &stat, 0);
|
||||
sigsetmask(omask);
|
||||
if (!WIFEXITED(stat) || WEXITSTATUS(stat) != 0)
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a quotause list to an ASCII file.
|
||||
*/
|
||||
writeprivs(quplist, outfd, name, quotatype)
|
||||
struct quotause *quplist;
|
||||
int outfd;
|
||||
char *name;
|
||||
int quotatype;
|
||||
{
|
||||
register struct quotause *qup;
|
||||
FILE *fd;
|
||||
|
||||
ftruncate(outfd, 0);
|
||||
lseek(outfd, 0, L_SET);
|
||||
if ((fd = fdopen(dup(outfd), "w")) == NULL) {
|
||||
fprintf(stderr, "edquota: ");
|
||||
perror(tmpfil);
|
||||
exit(1);
|
||||
}
|
||||
fprintf(fd, "Quotas for %s %s:\n", qfextension[quotatype], name);
|
||||
for (qup = quplist; qup; qup = qup->next) {
|
||||
fprintf(fd, "%s: %s %d, limits (soft = %d, hard = %d)\n",
|
||||
qup->fsname, "blocks in use:",
|
||||
dbtob(qup->dqblk.dqb_curblocks) / 1024,
|
||||
dbtob(qup->dqblk.dqb_bsoftlimit) / 1024,
|
||||
dbtob(qup->dqblk.dqb_bhardlimit) / 1024);
|
||||
fprintf(fd, "%s %d, limits (soft = %d, hard = %d)\n",
|
||||
"\tinodes in use:", qup->dqblk.dqb_curinodes,
|
||||
qup->dqblk.dqb_isoftlimit, qup->dqblk.dqb_ihardlimit);
|
||||
}
|
||||
fclose(fd);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Merge changes to an ASCII file into a quotause list.
|
||||
*/
|
||||
readprivs(quplist, infd)
|
||||
struct quotause *quplist;
|
||||
int infd;
|
||||
{
|
||||
register struct quotause *qup;
|
||||
FILE *fd;
|
||||
int cnt;
|
||||
register char *cp;
|
||||
struct dqblk dqblk;
|
||||
char *fsp, line1[BUFSIZ], line2[BUFSIZ];
|
||||
|
||||
lseek(infd, 0, L_SET);
|
||||
fd = fdopen(dup(infd), "r");
|
||||
if (fd == NULL) {
|
||||
fprintf(stderr, "Can't re-read temp file!!\n");
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* Discard title line, then read pairs of lines to process.
|
||||
*/
|
||||
(void) fgets(line1, sizeof (line1), fd);
|
||||
while (fgets(line1, sizeof (line1), fd) != NULL &&
|
||||
fgets(line2, sizeof (line2), fd) != NULL) {
|
||||
if ((fsp = strtok(line1, " \t:")) == NULL) {
|
||||
fprintf(stderr, "%s: bad format\n", line1);
|
||||
return (0);
|
||||
}
|
||||
if ((cp = strtok((char *)0, "\n")) == NULL) {
|
||||
fprintf(stderr, "%s: %s: bad format\n", fsp,
|
||||
&fsp[strlen(fsp) + 1]);
|
||||
return (0);
|
||||
}
|
||||
cnt = sscanf(cp,
|
||||
" blocks in use: %d, limits (soft = %d, hard = %d)",
|
||||
&dqblk.dqb_curblocks, &dqblk.dqb_bsoftlimit,
|
||||
&dqblk.dqb_bhardlimit);
|
||||
if (cnt != 3) {
|
||||
fprintf(stderr, "%s:%s: bad format\n", fsp, cp);
|
||||
return (0);
|
||||
}
|
||||
dqblk.dqb_curblocks = btodb(dqblk.dqb_curblocks * 1024);
|
||||
dqblk.dqb_bsoftlimit = btodb(dqblk.dqb_bsoftlimit * 1024);
|
||||
dqblk.dqb_bhardlimit = btodb(dqblk.dqb_bhardlimit * 1024);
|
||||
if ((cp = strtok(line2, "\n")) == NULL) {
|
||||
fprintf(stderr, "%s: %s: bad format\n", fsp, line2);
|
||||
return (0);
|
||||
}
|
||||
cnt = sscanf(cp,
|
||||
"\tinodes in use: %d, limits (soft = %d, hard = %d)",
|
||||
&dqblk.dqb_curinodes, &dqblk.dqb_isoftlimit,
|
||||
&dqblk.dqb_ihardlimit);
|
||||
if (cnt != 3) {
|
||||
fprintf(stderr, "%s: %s: bad format\n", fsp, line2);
|
||||
return (0);
|
||||
}
|
||||
for (qup = quplist; qup; qup = qup->next) {
|
||||
if (strcmp(fsp, qup->fsname))
|
||||
continue;
|
||||
/*
|
||||
* Cause time limit to be reset when the quota
|
||||
* is next used if previously had no soft limit
|
||||
* or were under it, but now have a soft limit
|
||||
* and are over it.
|
||||
*/
|
||||
if (dqblk.dqb_bsoftlimit &&
|
||||
qup->dqblk.dqb_curblocks >= dqblk.dqb_bsoftlimit &&
|
||||
(qup->dqblk.dqb_bsoftlimit == 0 ||
|
||||
qup->dqblk.dqb_curblocks <
|
||||
qup->dqblk.dqb_bsoftlimit))
|
||||
qup->dqblk.dqb_btime = 0;
|
||||
if (dqblk.dqb_isoftlimit &&
|
||||
qup->dqblk.dqb_curinodes >= dqblk.dqb_isoftlimit &&
|
||||
(qup->dqblk.dqb_isoftlimit == 0 ||
|
||||
qup->dqblk.dqb_curinodes <
|
||||
qup->dqblk.dqb_isoftlimit))
|
||||
qup->dqblk.dqb_itime = 0;
|
||||
qup->dqblk.dqb_bsoftlimit = dqblk.dqb_bsoftlimit;
|
||||
qup->dqblk.dqb_bhardlimit = dqblk.dqb_bhardlimit;
|
||||
qup->dqblk.dqb_isoftlimit = dqblk.dqb_isoftlimit;
|
||||
qup->dqblk.dqb_ihardlimit = dqblk.dqb_ihardlimit;
|
||||
qup->flags |= FOUND;
|
||||
if (dqblk.dqb_curblocks == qup->dqblk.dqb_curblocks &&
|
||||
dqblk.dqb_curinodes == qup->dqblk.dqb_curinodes)
|
||||
break;
|
||||
fprintf(stderr,
|
||||
"%s: cannot change current allocation\n", fsp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fd);
|
||||
/*
|
||||
* Disable quotas for any filesystems that have not been found.
|
||||
*/
|
||||
for (qup = quplist; qup; qup = qup->next) {
|
||||
if (qup->flags & FOUND) {
|
||||
qup->flags &= ~FOUND;
|
||||
continue;
|
||||
}
|
||||
qup->dqblk.dqb_bsoftlimit = 0;
|
||||
qup->dqblk.dqb_bhardlimit = 0;
|
||||
qup->dqblk.dqb_isoftlimit = 0;
|
||||
qup->dqblk.dqb_ihardlimit = 0;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a quotause list to an ASCII file of grace times.
|
||||
*/
|
||||
writetimes(quplist, outfd, quotatype)
|
||||
struct quotause *quplist;
|
||||
int outfd;
|
||||
int quotatype;
|
||||
{
|
||||
register struct quotause *qup;
|
||||
char *cvtstoa();
|
||||
FILE *fd;
|
||||
|
||||
ftruncate(outfd, 0);
|
||||
lseek(outfd, 0, L_SET);
|
||||
if ((fd = fdopen(dup(outfd), "w")) == NULL) {
|
||||
fprintf(stderr, "edquota: ");
|
||||
perror(tmpfil);
|
||||
exit(1);
|
||||
}
|
||||
fprintf(fd, "Time units may be: days, hours, minutes, or seconds\n");
|
||||
fprintf(fd, "Grace period before enforcing soft limits for %ss:\n",
|
||||
qfextension[quotatype]);
|
||||
for (qup = quplist; qup; qup = qup->next) {
|
||||
fprintf(fd, "%s: block grace period: %s, ",
|
||||
qup->fsname, cvtstoa(qup->dqblk.dqb_btime));
|
||||
fprintf(fd, "file grace period: %s\n",
|
||||
cvtstoa(qup->dqblk.dqb_itime));
|
||||
}
|
||||
fclose(fd);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Merge changes of grace times in an ASCII file into a quotause list.
|
||||
*/
|
||||
readtimes(quplist, infd)
|
||||
struct quotause *quplist;
|
||||
int infd;
|
||||
{
|
||||
register struct quotause *qup;
|
||||
FILE *fd;
|
||||
int cnt;
|
||||
register char *cp;
|
||||
time_t itime, btime, iseconds, bseconds;
|
||||
char *fsp, bunits[10], iunits[10], line1[BUFSIZ];
|
||||
|
||||
lseek(infd, 0, L_SET);
|
||||
fd = fdopen(dup(infd), "r");
|
||||
if (fd == NULL) {
|
||||
fprintf(stderr, "Can't re-read temp file!!\n");
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* Discard two title lines, then read lines to process.
|
||||
*/
|
||||
(void) fgets(line1, sizeof (line1), fd);
|
||||
(void) fgets(line1, sizeof (line1), fd);
|
||||
while (fgets(line1, sizeof (line1), fd) != NULL) {
|
||||
if ((fsp = strtok(line1, " \t:")) == NULL) {
|
||||
fprintf(stderr, "%s: bad format\n", line1);
|
||||
return (0);
|
||||
}
|
||||
if ((cp = strtok((char *)0, "\n")) == NULL) {
|
||||
fprintf(stderr, "%s: %s: bad format\n", fsp,
|
||||
&fsp[strlen(fsp) + 1]);
|
||||
return (0);
|
||||
}
|
||||
cnt = sscanf(cp,
|
||||
" block grace period: %d %s file grace period: %d %s",
|
||||
&btime, bunits, &itime, iunits);
|
||||
if (cnt != 4) {
|
||||
fprintf(stderr, "%s:%s: bad format\n", fsp, cp);
|
||||
return (0);
|
||||
}
|
||||
if (cvtatos(btime, bunits, &bseconds) == 0)
|
||||
return (0);
|
||||
if (cvtatos(itime, iunits, &iseconds) == 0)
|
||||
return (0);
|
||||
for (qup = quplist; qup; qup = qup->next) {
|
||||
if (strcmp(fsp, qup->fsname))
|
||||
continue;
|
||||
qup->dqblk.dqb_btime = bseconds;
|
||||
qup->dqblk.dqb_itime = iseconds;
|
||||
qup->flags |= FOUND;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(fd);
|
||||
/*
|
||||
* reset default grace periods for any filesystems
|
||||
* that have not been found.
|
||||
*/
|
||||
for (qup = quplist; qup; qup = qup->next) {
|
||||
if (qup->flags & FOUND) {
|
||||
qup->flags &= ~FOUND;
|
||||
continue;
|
||||
}
|
||||
qup->dqblk.dqb_btime = 0;
|
||||
qup->dqblk.dqb_itime = 0;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert seconds to ASCII times.
|
||||
*/
|
||||
char *
|
||||
cvtstoa(time)
|
||||
time_t time;
|
||||
{
|
||||
static char buf[20];
|
||||
|
||||
if (time % (24 * 60 * 60) == 0) {
|
||||
time /= 24 * 60 * 60;
|
||||
sprintf(buf, "%d day%s", time, time == 1 ? "" : "s");
|
||||
} else if (time % (60 * 60) == 0) {
|
||||
time /= 60 * 60;
|
||||
sprintf(buf, "%d hour%s", time, time == 1 ? "" : "s");
|
||||
} else if (time % 60 == 0) {
|
||||
time /= 60;
|
||||
sprintf(buf, "%d minute%s", time, time == 1 ? "" : "s");
|
||||
} else
|
||||
sprintf(buf, "%d second%s", time, time == 1 ? "" : "s");
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert ASCII input times to seconds.
|
||||
*/
|
||||
cvtatos(time, units, seconds)
|
||||
time_t time;
|
||||
char *units;
|
||||
time_t *seconds;
|
||||
{
|
||||
|
||||
if (bcmp(units, "second", 6) == 0)
|
||||
*seconds = time;
|
||||
else if (bcmp(units, "minute", 6) == 0)
|
||||
*seconds = time * 60;
|
||||
else if (bcmp(units, "hour", 4) == 0)
|
||||
*seconds = time * 60 * 60;
|
||||
else if (bcmp(units, "day", 3) == 0)
|
||||
*seconds = time * 24 * 60 * 60;
|
||||
else {
|
||||
printf("%s: bad units, specify %s\n", units,
|
||||
"days, hours, minutes, or seconds");
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free a list of quotause structures.
|
||||
*/
|
||||
freeprivs(quplist)
|
||||
struct quotause *quplist;
|
||||
{
|
||||
register struct quotause *qup, *nextqup;
|
||||
|
||||
for (qup = quplist; qup; qup = nextqup) {
|
||||
nextqup = qup->next;
|
||||
free(qup);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether a string is completely composed of digits.
|
||||
*/
|
||||
alldigits(s)
|
||||
register char *s;
|
||||
{
|
||||
register c;
|
||||
|
||||
c = *s++;
|
||||
do {
|
||||
if (!isdigit(c))
|
||||
return (0);
|
||||
} while (c = *s++);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if a particular quota is to be enabled.
|
||||
*/
|
||||
hasquota(fs, type, qfnamep)
|
||||
register struct fstab *fs;
|
||||
int type;
|
||||
char **qfnamep;
|
||||
{
|
||||
register char *opt;
|
||||
char *cp, *index(), *strtok();
|
||||
static char initname, usrname[100], grpname[100];
|
||||
static char buf[BUFSIZ];
|
||||
|
||||
if (!initname) {
|
||||
sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
|
||||
sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname);
|
||||
initname = 1;
|
||||
}
|
||||
strcpy(buf, fs->fs_mntops);
|
||||
for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
|
||||
if (cp = index(opt, '='))
|
||||
*cp++ = '\0';
|
||||
if (type == USRQUOTA && strcmp(opt, usrname) == 0)
|
||||
break;
|
||||
if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
|
||||
break;
|
||||
}
|
||||
if (!opt)
|
||||
return (0);
|
||||
if (cp) {
|
||||
*qfnamep = cp;
|
||||
return (1);
|
||||
}
|
||||
(void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
|
||||
*qfnamep = buf;
|
||||
return (1);
|
||||
}
|
376
usr.sbin/inetd/inetd.8
Normal file
376
usr.sbin/inetd/inetd.8
Normal file
@ -0,0 +1,376 @@
|
||||
.\" Copyright (c) 1985, 1991, 1993, 1994
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)inetd.8 8.4 (Berkeley) 6/1/94
|
||||
.\"
|
||||
.Dd June 1, 1994
|
||||
.Dt INETD 8
|
||||
.Os BSD 4.4
|
||||
.Sh NAME
|
||||
.Nm inetd
|
||||
.Nd internet
|
||||
.Dq super-server
|
||||
.Sh SYNOPSIS
|
||||
.Nm inetd
|
||||
.Op Fl d
|
||||
.Op Fl R Ar rate
|
||||
.Op Ar configuration file
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm inetd
|
||||
program
|
||||
should be run at boot time by
|
||||
.Pa /etc/rc
|
||||
(see
|
||||
.Xr rc 8 ) .
|
||||
It then listens for connections on certain
|
||||
internet sockets. When a connection is found on one
|
||||
of its sockets, it decides what service the socket
|
||||
corresponds to, and invokes a program to service the request.
|
||||
The server program is invoked with the service socket
|
||||
as its standard input, output and error descriptors.
|
||||
After the program is
|
||||
finished,
|
||||
.Nm inetd
|
||||
continues to listen on the socket (except in some cases which
|
||||
will be described below). Essentially,
|
||||
.Nm inetd
|
||||
allows running one daemon to invoke several others,
|
||||
reducing load on the system.
|
||||
.Pp
|
||||
The options available for
|
||||
.Nm inetd:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl d
|
||||
Turns on debugging.
|
||||
.It Fl R Ar rate
|
||||
Specifies the maximum number of times a service can be invoked
|
||||
in one minute; the default is 1000.
|
||||
.El
|
||||
.Pp
|
||||
Upon execution,
|
||||
.Nm inetd
|
||||
reads its configuration information from a configuration
|
||||
file which, by default, is
|
||||
.Pa /etc/inetd.conf .
|
||||
There must be an entry for each field of the configuration
|
||||
file, with entries for each field separated by a tab or
|
||||
a space. Comments are denoted by a ``#'' at the beginning
|
||||
of a line. There must be an entry for each field. The
|
||||
fields of the configuration file are as follows:
|
||||
.Pp
|
||||
.Bd -unfilled -offset indent -compact
|
||||
service name
|
||||
socket type
|
||||
protocol
|
||||
wait/nowait
|
||||
user
|
||||
server program
|
||||
server program arguments
|
||||
.Ed
|
||||
.Pp
|
||||
There are two types of services that
|
||||
.Nm inetd
|
||||
can start: standard and TCPMUX.
|
||||
A standard service has a well-known port assigned to it;
|
||||
it may be a service that implements an official Internet standard or is a
|
||||
BSD-specific service.
|
||||
As described in
|
||||
.Tn RFC 1078 ,
|
||||
TCPMUX services are nonstandard services that do not have a
|
||||
well-known port assigned to them.
|
||||
They are invoked from
|
||||
.Nm inetd
|
||||
when a program connects to the
|
||||
.Dq tcpmux
|
||||
well-known port and specifies
|
||||
the service name.
|
||||
This feature is useful for adding locally-developed servers.
|
||||
.Pp
|
||||
The
|
||||
.Em service-name
|
||||
entry is the name of a valid service in
|
||||
the file
|
||||
.Pa /etc/services .
|
||||
For
|
||||
.Dq internal
|
||||
services (discussed below), the service
|
||||
name
|
||||
.Em must
|
||||
be the official name of the service (that is, the first entry in
|
||||
.Pa /etc/services ) .
|
||||
For TCPMUX services, the value of the
|
||||
.Em service-name
|
||||
field consists of the string
|
||||
.Dq tcpmux
|
||||
followed by a slash and the
|
||||
locally-chosen service name.
|
||||
The service names listed in
|
||||
.Pa /etc/services
|
||||
and the name
|
||||
.Dq help
|
||||
are reserved.
|
||||
Try to choose unique names for your TCPMUX services by prefixing them with
|
||||
your organization's name and suffixing them with a version number.
|
||||
.Pp
|
||||
The
|
||||
.Em socket-type
|
||||
should be one of
|
||||
.Dq stream ,
|
||||
.Dq dgram ,
|
||||
.Dq raw ,
|
||||
.Dq rdm ,
|
||||
or
|
||||
.Dq seqpacket ,
|
||||
depending on whether the socket is a stream, datagram, raw,
|
||||
reliably delivered message, or sequenced packet socket.
|
||||
TCPMUX services must use
|
||||
.Dq stream .
|
||||
.Pp
|
||||
The
|
||||
.Em protocol
|
||||
must be a valid protocol as given in
|
||||
.Pa /etc/protocols .
|
||||
Examples might be
|
||||
.Dq tcp
|
||||
or
|
||||
.Dq udp .
|
||||
TCPMUX services must use
|
||||
.Dq tcp .
|
||||
.Pp
|
||||
The
|
||||
.Em wait/nowait
|
||||
entry specifies whether the server that is invoked by inetd will take over
|
||||
the socket associated with the service access point, and thus whether
|
||||
.Nm inetd
|
||||
should wait for the server to exit before listening for new service
|
||||
requests.
|
||||
Datagram servers must use
|
||||
.Dq wait ,
|
||||
as they are always invoked with the original datagram socket bound
|
||||
to the specified service address.
|
||||
These servers must read at least one datagram from the socket
|
||||
before exiting.
|
||||
If a datagram server connects
|
||||
to its peer, freeing the socket so
|
||||
.Nm inetd
|
||||
can received further messages on the socket, it is said to be
|
||||
a
|
||||
.Dq multi-threaded
|
||||
server;
|
||||
it should read one datagram from the socket and create a new socket
|
||||
connected to the peer.
|
||||
It should fork, and the parent should then exit
|
||||
to allow
|
||||
.Nm inetd
|
||||
to check for new service requests to spawn new servers.
|
||||
Datagram servers which process all incoming datagrams
|
||||
on a socket and eventually time out are said to be
|
||||
.Dq single-threaded .
|
||||
.Xr Comsat 8 ,
|
||||
.Pq Xr biff 1
|
||||
and
|
||||
.Xr talkd 8
|
||||
are both examples of the latter type of
|
||||
datagram server.
|
||||
.Xr Tftpd 8
|
||||
is an example of a multi-threaded datagram server.
|
||||
.Pp
|
||||
Servers using stream sockets generally are multi-threaded and
|
||||
use the
|
||||
.Dq nowait
|
||||
entry.
|
||||
Connection requests for these services are accepted by
|
||||
.Nm inetd ,
|
||||
and the server is given only the newly-accepted socket connected
|
||||
to a client of the service.
|
||||
Most stream-based services operate in this manner.
|
||||
Stream-based servers that use
|
||||
.Dq wait
|
||||
are started with the listening service socket, and must accept
|
||||
at least one connection request before exiting.
|
||||
Such a server would normally accept and process incoming connection
|
||||
requests until a timeout.
|
||||
TCPMUX services must use
|
||||
.Dq nowait .
|
||||
.Pp
|
||||
The
|
||||
.Em user
|
||||
entry should contain the user name of the user as whom the server
|
||||
should run. This allows for servers to be given less permission
|
||||
than root.
|
||||
.Pp
|
||||
The
|
||||
.Em server-program
|
||||
entry should contain the pathname of the program which is to be
|
||||
executed by
|
||||
.Nm inetd
|
||||
when a request is found on its socket. If
|
||||
.Nm inetd
|
||||
provides this service internally, this entry should
|
||||
be
|
||||
.Dq internal .
|
||||
.Pp
|
||||
The
|
||||
.Em server program arguments
|
||||
should be just as arguments
|
||||
normally are, starting with argv[0], which is the name of
|
||||
the program. If the service is provided internally, the
|
||||
word
|
||||
.Dq internal
|
||||
should take the place of this entry.
|
||||
.Pp
|
||||
The
|
||||
.Nm inetd
|
||||
program
|
||||
provides several
|
||||
.Dq trivial
|
||||
services internally by use of
|
||||
routines within itself. These services are
|
||||
.Dq echo ,
|
||||
.Dq discard ,
|
||||
.Dq chargen
|
||||
(character generator),
|
||||
.Dq daytime
|
||||
(human readable time), and
|
||||
.Dq time
|
||||
(machine readable time,
|
||||
in the form of the number of seconds since midnight, January
|
||||
1, 1900). All of these services are tcp based. For
|
||||
details of these services, consult the appropriate
|
||||
.Tn RFC
|
||||
from the Network Information Center.
|
||||
.Pp
|
||||
The
|
||||
.Nm inetd
|
||||
program
|
||||
rereads its configuration file when it receives a hangup signal,
|
||||
.Dv SIGHUP .
|
||||
Services may be added, deleted or modified when the configuration file
|
||||
is reread.
|
||||
.Sh TCPMUX
|
||||
.Pp
|
||||
.Tn RFC 1078
|
||||
describes the TCPMUX protocol:
|
||||
``A TCP client connects to a foreign host on TCP port 1. It sends the
|
||||
service name followed by a carriage-return line-feed <CRLF>. The
|
||||
service name is never case sensitive. The server replies with a
|
||||
single character indicating positive (+) or negative (\-)
|
||||
acknowledgment, immediately followed by an optional message of
|
||||
explanation, terminated with a <CRLF>. If the reply was positive,
|
||||
the selected protocol begins; otherwise the connection is closed.''
|
||||
The program is passed the TCP connection as file descriptors 0 and 1.
|
||||
.Pp
|
||||
If the TCPMUX service name begins with a ``+'',
|
||||
.Nm inetd
|
||||
returns the positive reply for the program.
|
||||
This allows you to invoke programs that use stdin/stdout
|
||||
without putting any special server code in them.
|
||||
.Pp
|
||||
The special service name
|
||||
.Dq help
|
||||
causes
|
||||
.Nm inetd
|
||||
to list TCPMUX services in
|
||||
.Pa inetd.conf .
|
||||
.ne 1i
|
||||
.Sh "EXAMPLES"
|
||||
.Pp
|
||||
Here are several example service entries for the various types of services:
|
||||
.Bd -literal
|
||||
ftp stream tcp nowait root /usr/libexec/ftpd ftpd -l
|
||||
ntalk dgram udp wait root /usr/libexec/ntalkd ntalkd
|
||||
tcpmux/+date stream tcp nowait guest /bin/date date
|
||||
tcpmux/phonebook stream tcp nowait guest /usr/local/bin/phonebook phonebook
|
||||
.Ed
|
||||
.Sh "ERROR MESSAGES"
|
||||
The
|
||||
.Nm inetd
|
||||
server
|
||||
logs error messages using
|
||||
.Xr syslog 3 .
|
||||
Important error messages and their explanations are:
|
||||
.Bd -literal
|
||||
\fIservice\fP/\fIprotocol\fP server failing (looping), service terminated.
|
||||
.Ed
|
||||
The number of requests for the specified service in the past minute
|
||||
exceeded the limit. The limit exists to prevent a broken program
|
||||
or a malicious user from swamping the system.
|
||||
This message may occur for several reasons:
|
||||
1) there are lots of hosts requesting the service within a short time period,
|
||||
2) a 'broken' client program is requesting the service too frequently,
|
||||
3) a malicious user is running a program to invoke the service in
|
||||
a 'denial of service' attack, or
|
||||
4) the invoked service program has an error that causes clients
|
||||
to retry quickly.
|
||||
Use the
|
||||
.Op Fl R
|
||||
option,
|
||||
as described above, to change the rate limit.
|
||||
Once the limit is reached, the service will be
|
||||
reenabled automatically in 10 minutes.
|
||||
.sp
|
||||
.Bd -literal
|
||||
\fIservice\fP/\fIprotocol\fP: No such user '\fIuser\fP', service ignored
|
||||
\fIservice\fP/\fIprotocol\fP: getpwnam: \fIuser\fP: No such user
|
||||
.Ed
|
||||
No entry for
|
||||
.Em user
|
||||
exists in the
|
||||
.Pa passwd
|
||||
file. The first message
|
||||
occurs when
|
||||
.Nm inetd
|
||||
(re)reads the configuration file. The second message occurs when the
|
||||
service is invoked.
|
||||
.sp
|
||||
.Bd -literal
|
||||
\fIservice\fP: can't set uid \fInumber\fP
|
||||
\fIservice\fP: can't set gid \fInumber\fP
|
||||
.Ed
|
||||
The user or group ID for the entry's
|
||||
.Em user
|
||||
is invalid.
|
||||
.Sh SEE ALSO
|
||||
.Xr comsat 8 ,
|
||||
.Xr fingerd 8 ,
|
||||
.Xr ftpd 8 ,
|
||||
.Xr rexecd 8 ,
|
||||
.Xr rlogind 8 ,
|
||||
.Xr rshd 8 ,
|
||||
.Xr telnetd 8 ,
|
||||
.Xr tftpd 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.3 .
|
||||
TCPMUX is based on code and documentation by Mark Lottor.
|
391
usr.sbin/iostat/iostat.c
Normal file
391
usr.sbin/iostat/iostat.c
Normal file
@ -0,0 +1,391 @@
|
||||
/*-
|
||||
* Copyright (c) 1986, 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1986, 1991, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)iostat.c 8.3 (Berkeley) 4/28/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/dkstat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <kvm.h>
|
||||
#include <limits.h>
|
||||
#include <nlist.h>
|
||||
#include <paths.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct nlist namelist[] = {
|
||||
#define X_DK_TIME 0
|
||||
{ "_dk_time" },
|
||||
#define X_DK_XFER 1
|
||||
{ "_dk_xfer" },
|
||||
#define X_DK_WDS 2
|
||||
{ "_dk_wds" },
|
||||
#define X_TK_NIN 3
|
||||
{ "_tk_nin" },
|
||||
#define X_TK_NOUT 4
|
||||
{ "_tk_nout" },
|
||||
#define X_DK_SEEK 5
|
||||
{ "_dk_seek" },
|
||||
#define X_CP_TIME 6
|
||||
{ "_cp_time" },
|
||||
#define X_DK_WPMS 7
|
||||
{ "_dk_wpms" },
|
||||
#define X_HZ 8
|
||||
{ "_hz" },
|
||||
#define X_STATHZ 9
|
||||
{ "_stathz" },
|
||||
#define X_DK_NDRIVE 10
|
||||
{ "_dk_ndrive" },
|
||||
#define X_END 10
|
||||
#if defined(hp300) || defined(luna68k)
|
||||
#define X_HPDINIT (X_END+1)
|
||||
{ "_hp_dinit" },
|
||||
#endif
|
||||
#ifdef mips
|
||||
#define X_SCSI_DINIT (X_END+1)
|
||||
{ "_scsi_dinit" },
|
||||
#endif
|
||||
#ifdef tahoe
|
||||
#define X_VBDINIT (X_END+1)
|
||||
{ "_vbdinit" },
|
||||
#endif
|
||||
#ifdef vax
|
||||
{ "_mbdinit" },
|
||||
#define X_MBDINIT (X_END+1)
|
||||
{ "_ubdinit" },
|
||||
#define X_UBDINIT (X_END+2)
|
||||
#endif
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
struct _disk {
|
||||
long cp_time[CPUSTATES];
|
||||
long *dk_time;
|
||||
long *dk_wds;
|
||||
long *dk_seek;
|
||||
long *dk_xfer;
|
||||
long tk_nin;
|
||||
long tk_nout;
|
||||
} cur, last;
|
||||
|
||||
kvm_t *kd;
|
||||
double etime;
|
||||
long *dk_wpms;
|
||||
int dk_ndrive, *dr_select, hz, kmemfd, ndrives;
|
||||
char **dr_name;
|
||||
|
||||
#define nlread(x, v) \
|
||||
kvm_read(kd, namelist[x].n_value, &(v), sizeof(v))
|
||||
|
||||
#include "names.c" /* XXX */
|
||||
|
||||
void cpustats __P((void));
|
||||
void dkstats __P((void));
|
||||
void phdr __P((int));
|
||||
void usage __P((void));
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register int i;
|
||||
long tmp;
|
||||
int ch, hdrcnt, reps, interval, stathz, ndrives;
|
||||
char **cp, *memf, *nlistf, buf[30];
|
||||
char errbuf[_POSIX2_LINE_MAX];
|
||||
|
||||
interval = reps = 0;
|
||||
nlistf = memf = NULL;
|
||||
while ((ch = getopt(argc, argv, "c:M:N:w:")) != EOF)
|
||||
switch(ch) {
|
||||
case 'c':
|
||||
if ((reps = atoi(optarg)) <= 0)
|
||||
errx(1, "repetition count <= 0.");
|
||||
break;
|
||||
case 'M':
|
||||
memf = optarg;
|
||||
break;
|
||||
case 'N':
|
||||
nlistf = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
if ((interval = atoi(optarg)) <= 0)
|
||||
errx(1, "interval <= 0.");
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/*
|
||||
* Discard setgid privileges if not the running kernel so that bad
|
||||
* guys can't print interesting stuff from kernel memory.
|
||||
*/
|
||||
if (nlistf != NULL || memf != NULL)
|
||||
setgid(getgid());
|
||||
|
||||
kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
|
||||
if (kd == 0)
|
||||
errx(1, "kvm_openfiles: %s", errbuf);
|
||||
if (kvm_nlist(kd, namelist) == -1)
|
||||
errx(1, "kvm_nlist: %s", kvm_geterr(kd));
|
||||
if (namelist[X_DK_NDRIVE].n_type == 0)
|
||||
errx(1, "dk_ndrive not found in namelist");
|
||||
(void)nlread(X_DK_NDRIVE, dk_ndrive);
|
||||
if (dk_ndrive <= 0)
|
||||
errx(1, "invalid dk_ndrive %d\n", dk_ndrive);
|
||||
|
||||
cur.dk_time = calloc(dk_ndrive, sizeof(long));
|
||||
cur.dk_wds = calloc(dk_ndrive, sizeof(long));
|
||||
cur.dk_seek = calloc(dk_ndrive, sizeof(long));
|
||||
cur.dk_xfer = calloc(dk_ndrive, sizeof(long));
|
||||
last.dk_time = calloc(dk_ndrive, sizeof(long));
|
||||
last.dk_wds = calloc(dk_ndrive, sizeof(long));
|
||||
last.dk_seek = calloc(dk_ndrive, sizeof(long));
|
||||
last.dk_xfer = calloc(dk_ndrive, sizeof(long));
|
||||
dr_select = calloc(dk_ndrive, sizeof(int));
|
||||
dr_name = calloc(dk_ndrive, sizeof(char *));
|
||||
dk_wpms = calloc(dk_ndrive, sizeof(long));
|
||||
|
||||
for (i = 0; i < dk_ndrive; i++) {
|
||||
(void)sprintf(buf, "dk%d", i);
|
||||
dr_name[i] = strdup(buf);
|
||||
}
|
||||
if (!read_names())
|
||||
exit(1);
|
||||
(void)nlread(X_HZ, hz);
|
||||
(void)nlread(X_STATHZ, stathz);
|
||||
if (stathz)
|
||||
hz = stathz;
|
||||
(void)kvm_read(kd, namelist[X_DK_WPMS].n_value, dk_wpms,
|
||||
dk_ndrive * sizeof(dk_wpms));
|
||||
|
||||
/*
|
||||
* Choose drives to be displayed. Priority goes to (in order) drives
|
||||
* supplied as arguments and default drives. If everything isn't
|
||||
* filled in and there are drives not taken care of, display the first
|
||||
* few that fit.
|
||||
*
|
||||
* The backward compatibility #ifdefs permit the syntax:
|
||||
* iostat [ drives ] [ interval [ count ] ]
|
||||
*/
|
||||
#define BACKWARD_COMPATIBILITY
|
||||
for (ndrives = 0; *argv; ++argv) {
|
||||
#ifdef BACKWARD_COMPATIBILITY
|
||||
if (isdigit(**argv))
|
||||
break;
|
||||
#endif
|
||||
for (i = 0; i < dk_ndrive; i++) {
|
||||
if (strcmp(dr_name[i], *argv))
|
||||
continue;
|
||||
dr_select[i] = 1;
|
||||
++ndrives;
|
||||
}
|
||||
}
|
||||
#ifdef BACKWARD_COMPATIBILITY
|
||||
if (*argv) {
|
||||
interval = atoi(*argv);
|
||||
if (*++argv)
|
||||
reps = atoi(*argv);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (interval) {
|
||||
if (!reps)
|
||||
reps = -1;
|
||||
} else
|
||||
if (reps)
|
||||
interval = 1;
|
||||
|
||||
for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
|
||||
if (dr_select[i] || dk_wpms[i] == 0)
|
||||
continue;
|
||||
for (cp = defdrives; *cp; cp++)
|
||||
if (strcmp(dr_name[i], *cp) == 0) {
|
||||
dr_select[i] = 1;
|
||||
++ndrives;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < dk_ndrive && ndrives < 4; i++) {
|
||||
if (dr_select[i])
|
||||
continue;
|
||||
dr_select[i] = 1;
|
||||
++ndrives;
|
||||
}
|
||||
|
||||
(void)signal(SIGCONT, phdr);
|
||||
|
||||
for (hdrcnt = 1;;) {
|
||||
if (!--hdrcnt) {
|
||||
phdr(0);
|
||||
hdrcnt = 20;
|
||||
}
|
||||
(void)kvm_read(kd, namelist[X_DK_TIME].n_value,
|
||||
cur.dk_time, dk_ndrive * sizeof(long));
|
||||
(void)kvm_read(kd, namelist[X_DK_XFER].n_value,
|
||||
cur.dk_xfer, dk_ndrive * sizeof(long));
|
||||
(void)kvm_read(kd, namelist[X_DK_WDS].n_value,
|
||||
cur.dk_wds, dk_ndrive * sizeof(long));
|
||||
(void)kvm_read(kd, namelist[X_DK_SEEK].n_value,
|
||||
cur.dk_seek, dk_ndrive * sizeof(long));
|
||||
(void)kvm_read(kd, namelist[X_TK_NIN].n_value,
|
||||
&cur.tk_nin, sizeof(cur.tk_nin));
|
||||
(void)kvm_read(kd, namelist[X_TK_NOUT].n_value,
|
||||
&cur.tk_nout, sizeof(cur.tk_nout));
|
||||
(void)kvm_read(kd, namelist[X_CP_TIME].n_value,
|
||||
cur.cp_time, sizeof(cur.cp_time));
|
||||
for (i = 0; i < dk_ndrive; i++) {
|
||||
if (!dr_select[i])
|
||||
continue;
|
||||
#define X(fld) tmp = cur.fld[i]; cur.fld[i] -= last.fld[i]; last.fld[i] = tmp
|
||||
X(dk_xfer);
|
||||
X(dk_seek);
|
||||
X(dk_wds);
|
||||
X(dk_time);
|
||||
}
|
||||
tmp = cur.tk_nin;
|
||||
cur.tk_nin -= last.tk_nin;
|
||||
last.tk_nin = tmp;
|
||||
tmp = cur.tk_nout;
|
||||
cur.tk_nout -= last.tk_nout;
|
||||
last.tk_nout = tmp;
|
||||
etime = 0;
|
||||
for (i = 0; i < CPUSTATES; i++) {
|
||||
X(cp_time);
|
||||
etime += cur.cp_time[i];
|
||||
}
|
||||
if (etime == 0.0)
|
||||
etime = 1.0;
|
||||
etime /= (float)hz;
|
||||
(void)printf("%4.0f%5.0f",
|
||||
cur.tk_nin / etime, cur.tk_nout / etime);
|
||||
dkstats();
|
||||
cpustats();
|
||||
(void)printf("\n");
|
||||
(void)fflush(stdout);
|
||||
|
||||
if (reps >= 0 && --reps <= 0)
|
||||
break;
|
||||
(void)sleep(interval);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* ARGUSED */
|
||||
void
|
||||
phdr(signo)
|
||||
int signo;
|
||||
{
|
||||
register int i;
|
||||
|
||||
(void)printf(" tty");
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (dr_select[i])
|
||||
(void)printf(" %3.3s ", dr_name[i]);
|
||||
(void)printf(" cpu\n tin tout");
|
||||
for (i = 0; i < dk_ndrive; i++)
|
||||
if (dr_select[i])
|
||||
(void)printf(" sps tps msps ");
|
||||
(void)printf(" us ni sy in id\n");
|
||||
}
|
||||
|
||||
void
|
||||
dkstats()
|
||||
{
|
||||
register int dn;
|
||||
double atime, itime, msps, words, xtime;
|
||||
|
||||
for (dn = 0; dn < dk_ndrive; ++dn) {
|
||||
if (!dr_select[dn])
|
||||
continue;
|
||||
words = cur.dk_wds[dn] * 32; /* words xfer'd */
|
||||
(void)printf("%4.0f", /* sectors */
|
||||
words / (DEV_BSIZE / 2) / etime);
|
||||
|
||||
(void)printf("%4.0f", cur.dk_xfer[dn] / etime);
|
||||
|
||||
if (dk_wpms[dn] && cur.dk_xfer[dn]) {
|
||||
atime = cur.dk_time[dn]; /* ticks disk busy */
|
||||
atime /= (float)hz; /* ticks to seconds */
|
||||
xtime = words / dk_wpms[dn]; /* transfer time */
|
||||
itime = atime - xtime; /* time not xfer'ing */
|
||||
if (itime < 0)
|
||||
msps = 0;
|
||||
else
|
||||
msps = itime * 1000 / cur.dk_xfer[dn];
|
||||
} else
|
||||
msps = 0;
|
||||
(void)printf("%5.1f ", msps);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cpustats()
|
||||
{
|
||||
register int state;
|
||||
double time;
|
||||
|
||||
time = 0;
|
||||
for (state = 0; state < CPUSTATES; ++state)
|
||||
time += cur.cp_time[state];
|
||||
for (state = 0; state < CPUSTATES; ++state)
|
||||
(void)printf("%3.0f",
|
||||
100. * cur.cp_time[state] / (time ? time : 1));
|
||||
}
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: iostat [-c count] [-M core] [-N system] [-w wait] [drives]\n");
|
||||
exit(1);
|
||||
}
|
9
usr.sbin/mtree/Makefile
Normal file
9
usr.sbin/mtree/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# @(#)Makefile 8.2 (Berkeley) 4/27/95
|
||||
|
||||
PROG= mtree
|
||||
MAN8= mtree.0
|
||||
#CFLAGS+=-DDEBUG
|
||||
SRCS= compare.c crc.c create.c misc.c mtree.c spec.c verify.c
|
||||
.PATH: ${.CURDIR}/../../usr.bin/cksum
|
||||
|
||||
.include <bsd.prog.mk>
|
280
usr.sbin/mtree/spec.c
Normal file
280
usr.sbin/mtree/spec.c
Normal file
@ -0,0 +1,280 @@
|
||||
/*-
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)spec.c 8.2 (Berkeley) 4/28/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fts.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "mtree.h"
|
||||
#include "extern.h"
|
||||
|
||||
int lineno; /* Current spec line number. */
|
||||
|
||||
static void set __P((char *, NODE *));
|
||||
static void unset __P((char *, NODE *));
|
||||
|
||||
NODE *
|
||||
spec()
|
||||
{
|
||||
register NODE *centry, *last;
|
||||
register char *p;
|
||||
NODE ginfo, *root;
|
||||
int c_cur, c_next;
|
||||
char buf[2048];
|
||||
|
||||
root = NULL;
|
||||
bzero(&ginfo, sizeof(ginfo));
|
||||
c_cur = c_next = 0;
|
||||
for (lineno = 1; fgets(buf, sizeof(buf), stdin);
|
||||
++lineno, c_cur = c_next, c_next = 0) {
|
||||
/* Skip empty lines. */
|
||||
if (buf[0] == '\n')
|
||||
continue;
|
||||
|
||||
/* Find end of line. */
|
||||
if ((p = index(buf, '\n')) == NULL)
|
||||
err("line %d too long", lineno);
|
||||
|
||||
/* See if next line is continuation line. */
|
||||
if (p[-1] == '\\') {
|
||||
--p;
|
||||
c_next = 1;
|
||||
}
|
||||
|
||||
/* Null-terminate the line. */
|
||||
*p = '\0';
|
||||
|
||||
/* Skip leading whitespace. */
|
||||
for (p = buf; *p && isspace(*p); ++p);
|
||||
|
||||
/* If nothing but whitespace or comment char, continue. */
|
||||
if (!*p || *p == '#')
|
||||
continue;
|
||||
|
||||
#ifdef DEBUG
|
||||
(void)fprintf(stderr, "line %d: {%s}\n", lineno, p);
|
||||
#endif
|
||||
if (c_cur) {
|
||||
set(p, centry);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Grab file name, "$", "set", or "unset". */
|
||||
if ((p = strtok(p, "\n\t ")) == NULL)
|
||||
err("missing field");
|
||||
|
||||
if (p[0] == '/')
|
||||
switch(p[1]) {
|
||||
case 's':
|
||||
if (strcmp(p + 1, "set"))
|
||||
break;
|
||||
set(NULL, &ginfo);
|
||||
continue;
|
||||
case 'u':
|
||||
if (strcmp(p + 1, "unset"))
|
||||
break;
|
||||
unset(NULL, &ginfo);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (index(p, '/'))
|
||||
err("slash character in file name");
|
||||
|
||||
if (!strcmp(p, "..")) {
|
||||
/* Don't go up, if haven't gone down. */
|
||||
if (!root)
|
||||
goto noparent;
|
||||
if (last->type != F_DIR || last->flags & F_DONE) {
|
||||
if (last == root)
|
||||
goto noparent;
|
||||
last = last->parent;
|
||||
}
|
||||
last->flags |= F_DONE;
|
||||
continue;
|
||||
|
||||
noparent: err("no parent node");
|
||||
}
|
||||
|
||||
if ((centry = calloc(1, sizeof(NODE) + strlen(p))) == NULL)
|
||||
err("%s", strerror(errno));
|
||||
*centry = ginfo;
|
||||
(void)strcpy(centry->name, p);
|
||||
#define MAGIC "?*["
|
||||
if (strpbrk(p, MAGIC))
|
||||
centry->flags |= F_MAGIC;
|
||||
set(NULL, centry);
|
||||
|
||||
if (!root) {
|
||||
last = root = centry;
|
||||
root->parent = root;
|
||||
} else if (last->type == F_DIR && !(last->flags & F_DONE)) {
|
||||
centry->parent = last;
|
||||
last = last->child = centry;
|
||||
} else {
|
||||
centry->parent = last->parent;
|
||||
centry->prev = last;
|
||||
last = last->next = centry;
|
||||
}
|
||||
}
|
||||
return (root);
|
||||
}
|
||||
|
||||
static void
|
||||
set(t, ip)
|
||||
char *t;
|
||||
register NODE *ip;
|
||||
{
|
||||
register int type;
|
||||
register char *kw, *val;
|
||||
struct group *gr;
|
||||
struct passwd *pw;
|
||||
mode_t *m;
|
||||
int value;
|
||||
char *ep;
|
||||
|
||||
for (; kw = strtok(t, "= \t\n"); t = NULL) {
|
||||
ip->flags |= type = parsekey(kw, &value);
|
||||
if (value && (val = strtok(NULL, " \t\n")) == NULL)
|
||||
err("missing value");
|
||||
switch(type) {
|
||||
case F_CKSUM:
|
||||
ip->cksum = strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
err("invalid checksum %s", val);
|
||||
break;
|
||||
case F_GID:
|
||||
ip->st_gid = strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
err("invalid gid %s", val);
|
||||
break;
|
||||
case F_GNAME:
|
||||
if ((gr = getgrnam(val)) == NULL)
|
||||
err("unknown group %s", val);
|
||||
ip->st_gid = gr->gr_gid;
|
||||
break;
|
||||
case F_IGN:
|
||||
/* just set flag bit */
|
||||
break;
|
||||
case F_MODE:
|
||||
if ((m = setmode(val)) == NULL)
|
||||
err("invalid file mode %s", val);
|
||||
ip->st_mode = getmode(m, 0);
|
||||
break;
|
||||
case F_NLINK:
|
||||
ip->st_nlink = strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
err("invalid link count %s", val);
|
||||
break;
|
||||
case F_SIZE:
|
||||
ip->st_size = strtouq(val, &ep, 10);
|
||||
if (*ep)
|
||||
err("invalid size %s", val);
|
||||
break;
|
||||
case F_SLINK:
|
||||
if ((ip->slink = strdup(val)) == NULL)
|
||||
err("%s", strerror(errno));
|
||||
break;
|
||||
case F_TIME:
|
||||
ip->st_mtimespec.ts_sec = strtoul(val, &ep, 10);
|
||||
if (*ep != '.')
|
||||
err("invalid time %s", val);
|
||||
val = ep + 1;
|
||||
ip->st_mtimespec.ts_nsec = strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
err("invalid time %s", val);
|
||||
break;
|
||||
case F_TYPE:
|
||||
switch(*val) {
|
||||
case 'b':
|
||||
if (!strcmp(val, "block"))
|
||||
ip->type = F_BLOCK;
|
||||
break;
|
||||
case 'c':
|
||||
if (!strcmp(val, "char"))
|
||||
ip->type = F_CHAR;
|
||||
break;
|
||||
case 'd':
|
||||
if (!strcmp(val, "dir"))
|
||||
ip->type = F_DIR;
|
||||
break;
|
||||
case 'f':
|
||||
if (!strcmp(val, "file"))
|
||||
ip->type = F_FILE;
|
||||
if (!strcmp(val, "fifo"))
|
||||
ip->type = F_FIFO;
|
||||
break;
|
||||
case 'l':
|
||||
if (!strcmp(val, "link"))
|
||||
ip->type = F_LINK;
|
||||
break;
|
||||
case 's':
|
||||
if (!strcmp(val, "socket"))
|
||||
ip->type = F_SOCK;
|
||||
break;
|
||||
default:
|
||||
err("unknown file type %s", val);
|
||||
}
|
||||
break;
|
||||
case F_UID:
|
||||
ip->st_uid = strtoul(val, &ep, 10);
|
||||
if (*ep)
|
||||
err("invalid uid %s", val);
|
||||
break;
|
||||
case F_UNAME:
|
||||
if ((pw = getpwnam(val)) == NULL)
|
||||
err("unknown user %s", val);
|
||||
ip->st_uid = pw->pw_uid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unset(t, ip)
|
||||
char *t;
|
||||
register NODE *ip;
|
||||
{
|
||||
register char *p;
|
||||
|
||||
while (p = strtok(t, "\n\t "))
|
||||
ip->flags &= ~parsekey(p, NULL);
|
||||
}
|
8
usr.sbin/portmap/Makefile
Normal file
8
usr.sbin/portmap/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= portmap
|
||||
DPADD= ${LIBRPC}
|
||||
LDADD= -lrpc
|
||||
MAN8= portmap.0
|
||||
|
||||
.include <bsd.prog.mk>
|
110
usr.sbin/portmap/portmap.8
Normal file
110
usr.sbin/portmap/portmap.8
Normal file
@ -0,0 +1,110 @@
|
||||
.\" Copyright (c) 1987 Sun Microsystems
|
||||
.\" Copyright (c) 1990, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)portmap.8 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd June 6, 1993
|
||||
.Dt PORTMAP 8
|
||||
.Os BSD 4.3
|
||||
.Sh NAME
|
||||
.Nm portmap
|
||||
.Nd
|
||||
.Tn DARPA
|
||||
port to
|
||||
.Tn RPC
|
||||
program number mapper
|
||||
.Sh SYNOPSIS
|
||||
.Nm portmap
|
||||
.Op Fl d
|
||||
.Sh DESCRIPTION
|
||||
.Nm Portmap
|
||||
is a server that converts
|
||||
.Tn RPC
|
||||
program numbers into
|
||||
.Tn DARPA
|
||||
protocol port numbers.
|
||||
It must be running in order to make
|
||||
.Tn RPC
|
||||
calls.
|
||||
.Pp
|
||||
When an
|
||||
.Tn RPC
|
||||
server is started, it will tell
|
||||
.Nm portmap
|
||||
what port number it is listening to, and what
|
||||
.Tn RPC
|
||||
program numbers it is prepared to serve.
|
||||
When a client wishes to make an
|
||||
.Tn RPC
|
||||
call to a given program number,
|
||||
it will first contact
|
||||
.Nm portmap
|
||||
on the server machine to determine
|
||||
the port number where
|
||||
.Tn RPC
|
||||
packets should be sent.
|
||||
.Pp
|
||||
.Nm Portmap
|
||||
must be started before any
|
||||
.Tn RPC
|
||||
servers are invoked.
|
||||
.Pp
|
||||
Normally
|
||||
.Nm portmap
|
||||
forks and dissociates itself from the terminal
|
||||
like any other daemon.
|
||||
.Nm Portmap
|
||||
then logs errors using
|
||||
.Xr syslog 3 .
|
||||
.Pp
|
||||
Option available:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl d
|
||||
(debug) prevents
|
||||
.Nm portmap
|
||||
from running as a daemon,
|
||||
and causes errors and debugging information
|
||||
to be printed to the standard error output.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr inetd.conf 5 ,
|
||||
.Xr rpcinfo 8 ,
|
||||
.Xr inetd 8
|
||||
.Sh BUGS
|
||||
If
|
||||
.Nm portmap
|
||||
crashes, all servers must be restarted.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.3
|
541
usr.sbin/portmap/portmap.c
Normal file
541
usr.sbin/portmap/portmap.c
Normal file
@ -0,0 +1,541 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1990, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)portmap.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
@(#)portmap.c 2.3 88/08/11 4.0 RPCSRC
|
||||
static char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro";
|
||||
*/
|
||||
|
||||
/*
|
||||
* portmap.c, Implements the program,version to port number mapping for
|
||||
* rpc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/pmap_prot.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/signal.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
void reg_service();
|
||||
void reap();
|
||||
static void callit();
|
||||
struct pmaplist *pmaplist;
|
||||
int debugging = 0;
|
||||
extern int errno;
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
SVCXPRT *xprt;
|
||||
int sock, c;
|
||||
struct sockaddr_in addr;
|
||||
int len = sizeof(struct sockaddr_in);
|
||||
register struct pmaplist *pml;
|
||||
|
||||
while ((c = getopt(argc, argv, "d")) != EOF) {
|
||||
switch (c) {
|
||||
|
||||
case 'd':
|
||||
debugging = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
(void) fprintf(stderr, "usage: %s [-d]\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!debugging && daemon(0, 0)) {
|
||||
(void) fprintf(stderr, "portmap: fork: %s", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
openlog("portmap", debugging ? LOG_PID | LOG_PERROR : LOG_PID,
|
||||
LOG_DAEMON);
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
||||
syslog(LOG_ERR, "cannot create udp socket: %m");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
addr.sin_addr.s_addr = 0;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(PMAPPORT);
|
||||
if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
|
||||
syslog(LOG_ERR, "cannot bind udp: %m");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
|
||||
syslog(LOG_ERR, "couldn't do udp_create");
|
||||
exit(1);
|
||||
}
|
||||
/* make an entry for ourself */
|
||||
pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
|
||||
pml->pml_next = 0;
|
||||
pml->pml_map.pm_prog = PMAPPROG;
|
||||
pml->pml_map.pm_vers = PMAPVERS;
|
||||
pml->pml_map.pm_prot = IPPROTO_UDP;
|
||||
pml->pml_map.pm_port = PMAPPORT;
|
||||
pmaplist = pml;
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
|
||||
syslog(LOG_ERR, "cannot create tcp socket: %m");
|
||||
exit(1);
|
||||
}
|
||||
if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
|
||||
syslog(LOG_ERR, "cannot bind udp: %m");
|
||||
exit(1);
|
||||
}
|
||||
if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
|
||||
== (SVCXPRT *)NULL) {
|
||||
syslog(LOG_ERR, "couldn't do tcp_create");
|
||||
exit(1);
|
||||
}
|
||||
/* make an entry for ourself */
|
||||
pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
|
||||
pml->pml_map.pm_prog = PMAPPROG;
|
||||
pml->pml_map.pm_vers = PMAPVERS;
|
||||
pml->pml_map.pm_prot = IPPROTO_TCP;
|
||||
pml->pml_map.pm_port = PMAPPORT;
|
||||
pml->pml_next = pmaplist;
|
||||
pmaplist = pml;
|
||||
|
||||
(void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
|
||||
|
||||
(void)signal(SIGCHLD, reap);
|
||||
svc_run();
|
||||
syslog(LOG_ERR, "run_svc returned unexpectedly");
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifndef lint
|
||||
/* need to override perror calls in rpc library */
|
||||
void
|
||||
perror(what)
|
||||
const char *what;
|
||||
{
|
||||
|
||||
syslog(LOG_ERR, "%s: %m", what);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct pmaplist *
|
||||
find_service(prog, vers, prot)
|
||||
u_long prog, vers, prot;
|
||||
{
|
||||
register struct pmaplist *hit = NULL;
|
||||
register struct pmaplist *pml;
|
||||
|
||||
for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
|
||||
if ((pml->pml_map.pm_prog != prog) ||
|
||||
(pml->pml_map.pm_prot != prot))
|
||||
continue;
|
||||
hit = pml;
|
||||
if (pml->pml_map.pm_vers == vers)
|
||||
break;
|
||||
}
|
||||
return (hit);
|
||||
}
|
||||
|
||||
/*
|
||||
* 1 OK, 0 not
|
||||
*/
|
||||
void
|
||||
reg_service(rqstp, xprt)
|
||||
struct svc_req *rqstp;
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
struct pmap reg;
|
||||
struct pmaplist *pml, *prevpml, *fnd;
|
||||
int ans, port;
|
||||
caddr_t t;
|
||||
|
||||
if (debugging)
|
||||
(void) fprintf(stderr, "server: about do a switch\n");
|
||||
switch (rqstp->rq_proc) {
|
||||
|
||||
case PMAPPROC_NULL:
|
||||
/*
|
||||
* Null proc call
|
||||
*/
|
||||
if (!svc_sendreply(xprt, xdr_void, (caddr_t)0) && debugging) {
|
||||
abort();
|
||||
}
|
||||
break;
|
||||
|
||||
case PMAPPROC_SET:
|
||||
/*
|
||||
* Set a program,version to port mapping
|
||||
*/
|
||||
if (!svc_getargs(xprt, xdr_pmap, ®))
|
||||
svcerr_decode(xprt);
|
||||
else {
|
||||
/*
|
||||
* check to see if already used
|
||||
* find_service returns a hit even if
|
||||
* the versions don't match, so check for it
|
||||
*/
|
||||
fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
|
||||
if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
|
||||
if (fnd->pml_map.pm_port == reg.pm_port) {
|
||||
ans = 1;
|
||||
goto done;
|
||||
}
|
||||
else {
|
||||
ans = 0;
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* add to END of list
|
||||
*/
|
||||
pml = (struct pmaplist *)
|
||||
malloc((u_int)sizeof(struct pmaplist));
|
||||
pml->pml_map = reg;
|
||||
pml->pml_next = 0;
|
||||
if (pmaplist == 0) {
|
||||
pmaplist = pml;
|
||||
} else {
|
||||
for (fnd= pmaplist; fnd->pml_next != 0;
|
||||
fnd = fnd->pml_next);
|
||||
fnd->pml_next = pml;
|
||||
}
|
||||
ans = 1;
|
||||
}
|
||||
done:
|
||||
if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
|
||||
debugging) {
|
||||
(void) fprintf(stderr, "svc_sendreply\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PMAPPROC_UNSET:
|
||||
/*
|
||||
* Remove a program,version to port mapping.
|
||||
*/
|
||||
if (!svc_getargs(xprt, xdr_pmap, ®))
|
||||
svcerr_decode(xprt);
|
||||
else {
|
||||
ans = 0;
|
||||
for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
|
||||
if ((pml->pml_map.pm_prog != reg.pm_prog) ||
|
||||
(pml->pml_map.pm_vers != reg.pm_vers)) {
|
||||
/* both pml & prevpml move forwards */
|
||||
prevpml = pml;
|
||||
pml = pml->pml_next;
|
||||
continue;
|
||||
}
|
||||
/* found it; pml moves forward, prevpml stays */
|
||||
ans = 1;
|
||||
t = (caddr_t)pml;
|
||||
pml = pml->pml_next;
|
||||
if (prevpml == NULL)
|
||||
pmaplist = pml;
|
||||
else
|
||||
prevpml->pml_next = pml;
|
||||
free(t);
|
||||
}
|
||||
if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
|
||||
debugging) {
|
||||
(void) fprintf(stderr, "svc_sendreply\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PMAPPROC_GETPORT:
|
||||
/*
|
||||
* Lookup the mapping for a program,version and return its port
|
||||
*/
|
||||
if (!svc_getargs(xprt, xdr_pmap, ®))
|
||||
svcerr_decode(xprt);
|
||||
else {
|
||||
fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
|
||||
if (fnd)
|
||||
port = fnd->pml_map.pm_port;
|
||||
else
|
||||
port = 0;
|
||||
if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) &&
|
||||
debugging) {
|
||||
(void) fprintf(stderr, "svc_sendreply\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PMAPPROC_DUMP:
|
||||
/*
|
||||
* Return the current set of mapped program,version
|
||||
*/
|
||||
if (!svc_getargs(xprt, xdr_void, NULL))
|
||||
svcerr_decode(xprt);
|
||||
else {
|
||||
if ((!svc_sendreply(xprt, xdr_pmaplist,
|
||||
(caddr_t)&pmaplist)) && debugging) {
|
||||
(void) fprintf(stderr, "svc_sendreply\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PMAPPROC_CALLIT:
|
||||
/*
|
||||
* Calls a procedure on the local machine. If the requested
|
||||
* procedure is not registered this procedure does not return
|
||||
* error information!!
|
||||
* This procedure is only supported on rpc/udp and calls via
|
||||
* rpc/udp. It passes null authentication parameters.
|
||||
*/
|
||||
callit(rqstp, xprt);
|
||||
break;
|
||||
|
||||
default:
|
||||
svcerr_noproc(xprt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Stuff for the rmtcall service
|
||||
*/
|
||||
#define ARGSIZE 9000
|
||||
|
||||
struct encap_parms {
|
||||
u_long arglen;
|
||||
char *args;
|
||||
};
|
||||
|
||||
static bool_t
|
||||
xdr_encap_parms(xdrs, epp)
|
||||
XDR *xdrs;
|
||||
struct encap_parms *epp;
|
||||
{
|
||||
|
||||
return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE));
|
||||
}
|
||||
|
||||
struct rmtcallargs {
|
||||
u_long rmt_prog;
|
||||
u_long rmt_vers;
|
||||
u_long rmt_port;
|
||||
u_long rmt_proc;
|
||||
struct encap_parms rmt_args;
|
||||
};
|
||||
|
||||
static bool_t
|
||||
xdr_rmtcall_args(xdrs, cap)
|
||||
register XDR *xdrs;
|
||||
register struct rmtcallargs *cap;
|
||||
{
|
||||
|
||||
/* does not get a port number */
|
||||
if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
|
||||
xdr_u_long(xdrs, &(cap->rmt_vers)) &&
|
||||
xdr_u_long(xdrs, &(cap->rmt_proc))) {
|
||||
return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdr_rmtcall_result(xdrs, cap)
|
||||
register XDR *xdrs;
|
||||
register struct rmtcallargs *cap;
|
||||
{
|
||||
if (xdr_u_long(xdrs, &(cap->rmt_port)))
|
||||
return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* only worries about the struct encap_parms part of struct rmtcallargs.
|
||||
* The arglen must already be set!!
|
||||
*/
|
||||
static bool_t
|
||||
xdr_opaque_parms(xdrs, cap)
|
||||
XDR *xdrs;
|
||||
struct rmtcallargs *cap;
|
||||
{
|
||||
|
||||
return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine finds and sets the length of incoming opaque paraters
|
||||
* and then calls xdr_opaque_parms.
|
||||
*/
|
||||
static bool_t
|
||||
xdr_len_opaque_parms(xdrs, cap)
|
||||
register XDR *xdrs;
|
||||
struct rmtcallargs *cap;
|
||||
{
|
||||
register u_int beginpos, lowpos, highpos, currpos, pos;
|
||||
|
||||
beginpos = lowpos = pos = xdr_getpos(xdrs);
|
||||
highpos = lowpos + ARGSIZE;
|
||||
while ((int)(highpos - lowpos) >= 0) {
|
||||
currpos = (lowpos + highpos) / 2;
|
||||
if (xdr_setpos(xdrs, currpos)) {
|
||||
pos = currpos;
|
||||
lowpos = currpos + 1;
|
||||
} else {
|
||||
highpos = currpos - 1;
|
||||
}
|
||||
}
|
||||
xdr_setpos(xdrs, beginpos);
|
||||
cap->rmt_args.arglen = pos - beginpos;
|
||||
return (xdr_opaque_parms(xdrs, cap));
|
||||
}
|
||||
|
||||
/*
|
||||
* Call a remote procedure service
|
||||
* This procedure is very quiet when things go wrong.
|
||||
* The proc is written to support broadcast rpc. In the broadcast case,
|
||||
* a machine should shut-up instead of complain, less the requestor be
|
||||
* overrun with complaints at the expense of not hearing a valid reply ...
|
||||
*
|
||||
* This now forks so that the program & process that it calls can call
|
||||
* back to the portmapper.
|
||||
*/
|
||||
static void
|
||||
callit(rqstp, xprt)
|
||||
struct svc_req *rqstp;
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
struct rmtcallargs a;
|
||||
struct pmaplist *pml;
|
||||
u_short port;
|
||||
struct sockaddr_in me;
|
||||
int pid, so = -1;
|
||||
CLIENT *client;
|
||||
struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
|
||||
struct timeval timeout;
|
||||
char buf[ARGSIZE];
|
||||
|
||||
timeout.tv_sec = 5;
|
||||
timeout.tv_usec = 0;
|
||||
a.rmt_args.args = buf;
|
||||
if (!svc_getargs(xprt, xdr_rmtcall_args, &a))
|
||||
return;
|
||||
if ((pml = find_service(a.rmt_prog, a.rmt_vers,
|
||||
(u_long)IPPROTO_UDP)) == NULL)
|
||||
return;
|
||||
/*
|
||||
* fork a child to do the work. Parent immediately returns.
|
||||
* Child exits upon completion.
|
||||
*/
|
||||
if ((pid = fork()) != 0) {
|
||||
if (pid < 0)
|
||||
syslog(LOG_ERR, "CALLIT (prog %lu): fork: %m",
|
||||
a.rmt_prog);
|
||||
return;
|
||||
}
|
||||
port = pml->pml_map.pm_port;
|
||||
get_myaddress(&me);
|
||||
me.sin_port = htons(port);
|
||||
client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &so);
|
||||
if (client != (CLIENT *)NULL) {
|
||||
if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
|
||||
client->cl_auth = authunix_create(au->aup_machname,
|
||||
au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids);
|
||||
}
|
||||
a.rmt_port = (u_long)port;
|
||||
if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a,
|
||||
xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) {
|
||||
svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a);
|
||||
}
|
||||
AUTH_DESTROY(client->cl_auth);
|
||||
clnt_destroy(client);
|
||||
}
|
||||
(void)close(so);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
reap()
|
||||
{
|
||||
while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0);
|
||||
}
|
128
usr.sbin/pwd_mkdb/pwd_mkdb.8
Normal file
128
usr.sbin/pwd_mkdb/pwd_mkdb.8
Normal file
@ -0,0 +1,128 @@
|
||||
.\" Copyright (c) 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)pwd_mkdb.8 8.2 (Berkeley) 4/27/95
|
||||
.\"
|
||||
.Dd April 27, 1995
|
||||
.Dt PWD_MKDB 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm pwd_mkdb
|
||||
.Nd "generate the password databases"
|
||||
.Sh SYNOPSIS
|
||||
.Nm pwd_mkdb
|
||||
.Op Fl p
|
||||
.Ar file
|
||||
.Sh DESCRIPTION
|
||||
.Nm Pwd_mkdb
|
||||
creates
|
||||
.Xr db 3
|
||||
style secure and insecure databases for the specified file.
|
||||
These databases are then installed into
|
||||
.Dq Pa /etc/spwd.db
|
||||
and
|
||||
.Dq Pa /etc/pwd.db
|
||||
respectively.
|
||||
The file is installed into
|
||||
.Dq Pa /etc/master.passwd .
|
||||
The file must be in the correct format (see
|
||||
.Xr passwd 5 ) .
|
||||
It is important to note that the format used in this system is
|
||||
different from the historic Version 7 style format.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width flag
|
||||
.It Fl p
|
||||
Create a Version 7 style password file and install it into
|
||||
.Dq Pa /etc/passwd .
|
||||
.El
|
||||
.Pp
|
||||
The two databases differ in that the secure version contains the user's
|
||||
encrypted password and the insecure version has an asterisk (``*'')
|
||||
.Pp
|
||||
The databases are used by the C library password routines (see
|
||||
.Xr getpwent 3 ) .
|
||||
.Pp
|
||||
.Nm Pwd_mkdb
|
||||
exits zero on success, non-zero on failure.
|
||||
.Sh FILES
|
||||
.Bl -tag -width Pa -compact
|
||||
.It Pa /etc/master.passwd
|
||||
The current password file.
|
||||
.It Pa /etc/passwd
|
||||
A Version 7 format password file.
|
||||
.It Pa /etc/pwd.db
|
||||
The insecure password database file.
|
||||
.It Pa /etc/pwd.db.tmp
|
||||
A temporary file.
|
||||
.It Pa /etc/spwd.db
|
||||
The secure password database file.
|
||||
.It Pa /etc/spwd.db.tmp
|
||||
A temporary file.
|
||||
.El
|
||||
.Sh BUGS
|
||||
Because of the necessity for atomic update of the password files,
|
||||
.Nm pwd_mkdb
|
||||
uses
|
||||
.Xr rename 2
|
||||
to install them.
|
||||
This, however, requires that the file specified on the command line live
|
||||
on the same file system as the
|
||||
.Dq Pa /etc
|
||||
directory.
|
||||
.Pp
|
||||
There are the obvious races with multiple people running
|
||||
.Nm pwd_mkdb
|
||||
on different password files at the same time.
|
||||
The front-ends to
|
||||
.Nm pwd_mkdb ,
|
||||
.Xr chpass 1 ,
|
||||
.Xr passwd 1
|
||||
and
|
||||
.Xr vipw 8 ,
|
||||
handle the locking necessary to avoid this problem.
|
||||
.Sh COMPATIBILITY
|
||||
Previous versions of the system had a program similar to
|
||||
.Nm pwd_mkdb ,
|
||||
.Xr mkpasswd 8 ,
|
||||
which built
|
||||
.Xr dbm 3
|
||||
style databases for the password file but depended on the calling programs
|
||||
to install them.
|
||||
The program was renamed in order that previous users of the program
|
||||
not be surprised by the changes in functionality.
|
||||
.Sh SEE ALSO
|
||||
.Xr chpass 1 ,
|
||||
.Xr passwd 1 ,
|
||||
.Xr db 3 ,
|
||||
.Xr getpwent 3 ,
|
||||
.Xr passwd 5 ,
|
||||
.Xr vipw 8
|
84
usr.sbin/quot/quot.8
Normal file
84
usr.sbin/quot/quot.8
Normal file
@ -0,0 +1,84 @@
|
||||
.\" Copyright (c) 1980, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)quot.8 8.1 (Berkeley) 6/6/93
|
||||
.\"
|
||||
.Dd June 6, 1993
|
||||
.Dt QUOT 8
|
||||
.Os BSD 4
|
||||
.Sh NAME
|
||||
.Nm quot
|
||||
.Nd display total block usage per user for a file system
|
||||
.Sh SYNOPSIS
|
||||
.Nm quot
|
||||
.Op Fl ncf
|
||||
.Op Ar filesystem Ar ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm quot
|
||||
command
|
||||
displays the total count of blocks owned by a user for the filesystem
|
||||
.Ar filesystem .
|
||||
If the filesystem option
|
||||
.Ar filesystem
|
||||
is not specified,
|
||||
the file systems listed in
|
||||
.Pa /etc/fstab
|
||||
are used.
|
||||
The following options are available:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl c
|
||||
Display information on file size and block usage. The file sizes
|
||||
are listed in the first column, the second column contains a count
|
||||
of how many files of that size were found and the third column
|
||||
lists the cumulative block usage for the displayed size and all smaller
|
||||
files.
|
||||
.It Fl f
|
||||
For each user,
|
||||
the number of files (inodes) owned is displayed in addition
|
||||
to the block usage.
|
||||
.It Fl n
|
||||
A list sorted by block usage is displayed.
|
||||
This is the result of
|
||||
.Nm quot
|
||||
executing the following command:
|
||||
.Bd -literal -offset indent
|
||||
ncheck filesystem \&| sort +0n \&| quot \-n filesystem
|
||||
.Ed
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr ls 1 ,
|
||||
.Xr du 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.At 32v .
|
380
usr.sbin/repquota/repquota.c
Normal file
380
usr.sbin/repquota/repquota.c
Normal file
@ -0,0 +1,380 @@
|
||||
/*
|
||||
* Copyright (c) 1980, 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Robert Elz at The University of Melbourne.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1980, 1990, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)repquota.c 8.2 (Berkeley) 11/22/94";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* Quota report
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/queue.h>
|
||||
#include <ufs/ufs/quota.h>
|
||||
#include <fstab.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
char *qfname = QUOTAFILENAME;
|
||||
char *qfextension[] = INITQFNAMES;
|
||||
|
||||
struct fileusage {
|
||||
struct fileusage *fu_next;
|
||||
struct dqblk fu_dqblk;
|
||||
u_long fu_id;
|
||||
char fu_name[1];
|
||||
/* actually bigger */
|
||||
};
|
||||
#define FUHASH 1024 /* must be power of two */
|
||||
struct fileusage *fuhead[MAXQUOTAS][FUHASH];
|
||||
struct fileusage *lookup();
|
||||
struct fileusage *addid();
|
||||
u_long highid[MAXQUOTAS]; /* highest addid()'ed identifier per type */
|
||||
|
||||
int vflag; /* verbose */
|
||||
int aflag; /* all file systems */
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
register struct fstab *fs;
|
||||
register struct passwd *pw;
|
||||
register struct group *gr;
|
||||
int gflag = 0, uflag = 0, errs = 0;
|
||||
long i, argnum, done = 0;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
char ch, *qfnp;
|
||||
|
||||
while ((ch = getopt(argc, argv, "aguv")) != EOF) {
|
||||
switch(ch) {
|
||||
case 'a':
|
||||
aflag++;
|
||||
break;
|
||||
case 'g':
|
||||
gflag++;
|
||||
break;
|
||||
case 'u':
|
||||
uflag++;
|
||||
break;
|
||||
case 'v':
|
||||
vflag++;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc == 0 && !aflag)
|
||||
usage();
|
||||
if (!gflag && !uflag) {
|
||||
if (aflag)
|
||||
gflag++;
|
||||
uflag++;
|
||||
}
|
||||
if (gflag) {
|
||||
setgrent();
|
||||
while ((gr = getgrent()) != 0)
|
||||
(void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name);
|
||||
endgrent();
|
||||
}
|
||||
if (uflag) {
|
||||
setpwent();
|
||||
while ((pw = getpwent()) != 0)
|
||||
(void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name);
|
||||
endpwent();
|
||||
}
|
||||
setfsent();
|
||||
while ((fs = getfsent()) != NULL) {
|
||||
if (strcmp(fs->fs_vfstype, "ufs"))
|
||||
continue;
|
||||
if (aflag) {
|
||||
if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
|
||||
errs += repquota(fs, GRPQUOTA, qfnp);
|
||||
if (uflag && hasquota(fs, USRQUOTA, &qfnp))
|
||||
errs += repquota(fs, USRQUOTA, qfnp);
|
||||
continue;
|
||||
}
|
||||
if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
|
||||
(argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
|
||||
done |= 1 << argnum;
|
||||
if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
|
||||
errs += repquota(fs, GRPQUOTA, qfnp);
|
||||
if (uflag && hasquota(fs, USRQUOTA, &qfnp))
|
||||
errs += repquota(fs, USRQUOTA, qfnp);
|
||||
}
|
||||
}
|
||||
endfsent();
|
||||
for (i = 0; i < argc; i++)
|
||||
if ((done & (1 << i)) == 0)
|
||||
fprintf(stderr, "%s not found in fstab\n", argv[i]);
|
||||
exit(errs);
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "Usage:\n\t%s\n\t%s\n",
|
||||
"repquota [-v] [-g] [-u] -a",
|
||||
"repquota [-v] [-g] [-u] filesys ...");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
repquota(fs, type, qfpathname)
|
||||
register struct fstab *fs;
|
||||
int type;
|
||||
char *qfpathname;
|
||||
{
|
||||
register struct fileusage *fup;
|
||||
FILE *qf;
|
||||
u_long id;
|
||||
struct dqblk dqbuf;
|
||||
char *timeprt();
|
||||
static struct dqblk zerodqblk;
|
||||
static int warned = 0;
|
||||
static int multiple = 0;
|
||||
extern int errno;
|
||||
|
||||
if (quotactl(fs->fs_file, QCMD(Q_SYNC, type), 0, 0) < 0 &&
|
||||
errno == EOPNOTSUPP && !warned && vflag) {
|
||||
warned++;
|
||||
fprintf(stdout,
|
||||
"*** Warning: Quotas are not compiled into this kernel\n");
|
||||
}
|
||||
if (multiple++)
|
||||
printf("\n");
|
||||
if (vflag)
|
||||
fprintf(stdout, "*** Report for %s quotas on %s (%s)\n",
|
||||
qfextension[type], fs->fs_file, fs->fs_spec);
|
||||
if ((qf = fopen(qfpathname, "r")) == NULL) {
|
||||
perror(qfpathname);
|
||||
return (1);
|
||||
}
|
||||
for (id = 0; ; id++) {
|
||||
fread(&dqbuf, sizeof(struct dqblk), 1, qf);
|
||||
if (feof(qf))
|
||||
break;
|
||||
if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0)
|
||||
continue;
|
||||
if ((fup = lookup(id, type)) == 0)
|
||||
fup = addid(id, type, (char *)0);
|
||||
fup->fu_dqblk = dqbuf;
|
||||
}
|
||||
fclose(qf);
|
||||
printf(" Block limits File limits\n");
|
||||
printf("User used soft hard grace used soft hard grace\n");
|
||||
for (id = 0; id <= highid[type]; id++) {
|
||||
fup = lookup(id, type);
|
||||
if (fup == 0)
|
||||
continue;
|
||||
if (fup->fu_dqblk.dqb_curinodes == 0 &&
|
||||
fup->fu_dqblk.dqb_curblocks == 0)
|
||||
continue;
|
||||
printf("%-10s", fup->fu_name);
|
||||
printf("%c%c%8d%8d%8d%7s",
|
||||
fup->fu_dqblk.dqb_bsoftlimit &&
|
||||
fup->fu_dqblk.dqb_curblocks >=
|
||||
fup->fu_dqblk.dqb_bsoftlimit ? '+' : '-',
|
||||
fup->fu_dqblk.dqb_isoftlimit &&
|
||||
fup->fu_dqblk.dqb_curinodes >=
|
||||
fup->fu_dqblk.dqb_isoftlimit ? '+' : '-',
|
||||
dbtob(fup->fu_dqblk.dqb_curblocks) / 1024,
|
||||
dbtob(fup->fu_dqblk.dqb_bsoftlimit) / 1024,
|
||||
dbtob(fup->fu_dqblk.dqb_bhardlimit) / 1024,
|
||||
fup->fu_dqblk.dqb_bsoftlimit &&
|
||||
fup->fu_dqblk.dqb_curblocks >=
|
||||
fup->fu_dqblk.dqb_bsoftlimit ?
|
||||
timeprt(fup->fu_dqblk.dqb_btime) : "");
|
||||
printf(" %6d%6d%6d%7s\n",
|
||||
fup->fu_dqblk.dqb_curinodes,
|
||||
fup->fu_dqblk.dqb_isoftlimit,
|
||||
fup->fu_dqblk.dqb_ihardlimit,
|
||||
fup->fu_dqblk.dqb_isoftlimit &&
|
||||
fup->fu_dqblk.dqb_curinodes >=
|
||||
fup->fu_dqblk.dqb_isoftlimit ?
|
||||
timeprt(fup->fu_dqblk.dqb_itime) : "");
|
||||
fup->fu_dqblk = zerodqblk;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if target appears in list of size cnt.
|
||||
*/
|
||||
oneof(target, list, cnt)
|
||||
register char *target, *list[];
|
||||
int cnt;
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < cnt; i++)
|
||||
if (strcmp(target, list[i]) == 0)
|
||||
return (i);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if a particular quota is to be enabled.
|
||||
*/
|
||||
hasquota(fs, type, qfnamep)
|
||||
register struct fstab *fs;
|
||||
int type;
|
||||
char **qfnamep;
|
||||
{
|
||||
register char *opt;
|
||||
char *cp, *index(), *strtok();
|
||||
static char initname, usrname[100], grpname[100];
|
||||
static char buf[BUFSIZ];
|
||||
|
||||
if (!initname) {
|
||||
sprintf(usrname, "%s%s", qfextension[USRQUOTA], qfname);
|
||||
sprintf(grpname, "%s%s", qfextension[GRPQUOTA], qfname);
|
||||
initname = 1;
|
||||
}
|
||||
strcpy(buf, fs->fs_mntops);
|
||||
for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) {
|
||||
if (cp = index(opt, '='))
|
||||
*cp++ = '\0';
|
||||
if (type == USRQUOTA && strcmp(opt, usrname) == 0)
|
||||
break;
|
||||
if (type == GRPQUOTA && strcmp(opt, grpname) == 0)
|
||||
break;
|
||||
}
|
||||
if (!opt)
|
||||
return (0);
|
||||
if (cp) {
|
||||
*qfnamep = cp;
|
||||
return (1);
|
||||
}
|
||||
(void) sprintf(buf, "%s/%s.%s", fs->fs_file, qfname, qfextension[type]);
|
||||
*qfnamep = buf;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Routines to manage the file usage table.
|
||||
*
|
||||
* Lookup an id of a specific type.
|
||||
*/
|
||||
struct fileusage *
|
||||
lookup(id, type)
|
||||
u_long id;
|
||||
int type;
|
||||
{
|
||||
register struct fileusage *fup;
|
||||
|
||||
for (fup = fuhead[type][id & (FUHASH-1)]; fup != 0; fup = fup->fu_next)
|
||||
if (fup->fu_id == id)
|
||||
return (fup);
|
||||
return ((struct fileusage *)0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new file usage id if it does not already exist.
|
||||
*/
|
||||
struct fileusage *
|
||||
addid(id, type, name)
|
||||
u_long id;
|
||||
int type;
|
||||
char *name;
|
||||
{
|
||||
struct fileusage *fup, **fhp;
|
||||
int len;
|
||||
extern char *calloc();
|
||||
|
||||
if (fup = lookup(id, type))
|
||||
return (fup);
|
||||
if (name)
|
||||
len = strlen(name);
|
||||
else
|
||||
len = 10;
|
||||
if ((fup = (struct fileusage *)calloc(1, sizeof(*fup) + len)) == NULL) {
|
||||
fprintf(stderr, "out of memory for fileusage structures\n");
|
||||
exit(1);
|
||||
}
|
||||
fhp = &fuhead[type][id & (FUHASH - 1)];
|
||||
fup->fu_next = *fhp;
|
||||
*fhp = fup;
|
||||
fup->fu_id = id;
|
||||
if (id > highid[type])
|
||||
highid[type] = id;
|
||||
if (name) {
|
||||
bcopy(name, fup->fu_name, len + 1);
|
||||
} else {
|
||||
sprintf(fup->fu_name, "%u", id);
|
||||
}
|
||||
return (fup);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the grace period and return a printable string for it.
|
||||
*/
|
||||
char *
|
||||
timeprt(seconds)
|
||||
time_t seconds;
|
||||
{
|
||||
time_t hours, minutes;
|
||||
static char buf[20];
|
||||
static time_t now;
|
||||
|
||||
if (now == 0)
|
||||
time(&now);
|
||||
if (now > seconds)
|
||||
return ("none");
|
||||
seconds -= now;
|
||||
minutes = (seconds + 30) / 60;
|
||||
hours = (minutes + 30) / 60;
|
||||
if (hours >= 36) {
|
||||
sprintf(buf, "%ddays", (hours + 12) / 24);
|
||||
return (buf);
|
||||
}
|
||||
if (minutes >= 60) {
|
||||
sprintf(buf, "%2d:%d", minutes / 60, minutes % 60);
|
||||
return (buf);
|
||||
}
|
||||
sprintf(buf, "%2d", minutes);
|
||||
return (buf);
|
||||
}
|
218
usr.sbin/rmt/rmt.8
Normal file
218
usr.sbin/rmt/rmt.8
Normal file
@ -0,0 +1,218 @@
|
||||
.\" Copyright (c) 1983, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)rmt.8 8.3 (Berkeley) 6/1/94
|
||||
.\"
|
||||
.Dd June 1, 1994
|
||||
.Dt RMT 8
|
||||
.Os BSD 4.2
|
||||
.Sh NAME
|
||||
.Nm rmt
|
||||
.Nd remote magtape protocol module
|
||||
.Sh SYNOPSIS
|
||||
.Nm rmt
|
||||
.Sh DESCRIPTION
|
||||
.Nm Rmt
|
||||
is a program used by the remote dump and restore programs
|
||||
in manipulating a magnetic tape drive through an interprocess
|
||||
communication connection.
|
||||
.Nm Rmt
|
||||
is normally started up with an
|
||||
.Xr rexec 3
|
||||
or
|
||||
.Xr rcmd 3
|
||||
call.
|
||||
.Pp
|
||||
The
|
||||
.Nm rmt
|
||||
program accepts requests specific to the manipulation of
|
||||
magnetic tapes, performs the commands, then responds with
|
||||
a status indication. All responses are in
|
||||
.Tn ASCII
|
||||
and in
|
||||
one of two forms.
|
||||
Successful commands have responses of:
|
||||
.Bd -filled -offset indent
|
||||
.Sm off
|
||||
.Sy A Ar number No \en
|
||||
.Sm on
|
||||
.Ed
|
||||
.Pp
|
||||
.Ar Number
|
||||
is an
|
||||
.Tn ASCII
|
||||
representation of a decimal number.
|
||||
Unsuccessful commands are responded to with:
|
||||
.Bd -filled -offset indent
|
||||
.Sm off
|
||||
.Xo Sy E Ar error-number
|
||||
.No \en Ar error-message
|
||||
.No \en
|
||||
.Xc
|
||||
.Sm on
|
||||
.Ed
|
||||
.Pp
|
||||
.Ar Error-number
|
||||
is one of the possible error
|
||||
numbers described in
|
||||
.Xr intro 2
|
||||
and
|
||||
.Ar error-message
|
||||
is the corresponding error string as printed
|
||||
from a call to
|
||||
.Xr perror 3 .
|
||||
The protocol is comprised of the
|
||||
following commands, which are sent as indicated - no spaces are supplied
|
||||
between the command and its arguments, or between its arguments, and
|
||||
.Ql \en
|
||||
indicates that a newline should be supplied:
|
||||
.Bl -tag -width Ds
|
||||
.Sm off
|
||||
.It Xo Sy \&O Ar device
|
||||
.No \en Ar mode No \en
|
||||
.Xc
|
||||
Open the specified
|
||||
.Ar device
|
||||
using the indicated
|
||||
.Ar mode .
|
||||
.Ar Device
|
||||
is a full pathname and
|
||||
.Ar mode
|
||||
is an
|
||||
.Tn ASCII
|
||||
representation of a decimal
|
||||
number suitable for passing to
|
||||
.Xr open 2 .
|
||||
If a device had already been opened, it is
|
||||
closed before a new open is performed.
|
||||
.It Xo Sy C Ar device No \en
|
||||
.Xc
|
||||
Close the currently open device. The
|
||||
.Ar device
|
||||
specified is ignored.
|
||||
.It Xo Sy L
|
||||
.Ar whence No \en
|
||||
.Ar offset No \en
|
||||
.Xc
|
||||
.Sm on
|
||||
Perform an
|
||||
.Xr lseek 2
|
||||
operation using the specified parameters.
|
||||
The response value is that returned from the
|
||||
.Xr lseek
|
||||
call.
|
||||
.Sm off
|
||||
.It Sy W Ar count No \en
|
||||
.Sm on
|
||||
Write data onto the open device.
|
||||
.Nm Rmt
|
||||
reads
|
||||
.Ar count
|
||||
bytes from the connection, aborting if
|
||||
a premature end-of-file is encountered.
|
||||
The response value is that returned from
|
||||
the
|
||||
.Xr write 2
|
||||
call.
|
||||
.Sm off
|
||||
.It Sy R Ar count No \en
|
||||
.Sm on
|
||||
Read
|
||||
.Ar count
|
||||
bytes of data from the open device.
|
||||
If
|
||||
.Ar count
|
||||
exceeds the size of the data buffer (10 kilobytes), it is
|
||||
truncated to the data buffer size.
|
||||
.Nm rmt
|
||||
then performs the requested
|
||||
.Xr read 2
|
||||
and responds with
|
||||
.Sm off
|
||||
.Sy A Ar count-read No \en
|
||||
.Sm on
|
||||
if the read was
|
||||
successful; otherwise an error in the
|
||||
standard format is returned. If the read
|
||||
was successful, the data read is then sent.
|
||||
.Sm off
|
||||
.It Xo Sy I Ar operation
|
||||
.No \en Ar count No \en
|
||||
.Xc
|
||||
.Sm on
|
||||
Perform a
|
||||
.Dv MTIOCOP
|
||||
.Xr ioctl 2
|
||||
command using the specified parameters.
|
||||
The parameters are interpreted as the
|
||||
.Tn ASCII
|
||||
representations of the decimal values
|
||||
to place in the
|
||||
.Ar mt_op
|
||||
and
|
||||
.Ar mt_count
|
||||
fields of the structure used in the
|
||||
.Xr ioctl
|
||||
call. The return value is the
|
||||
.Ar count
|
||||
parameter when the operation is successful.
|
||||
.ne 1i
|
||||
.It Sy S
|
||||
Return the status of the open device, as
|
||||
obtained with a
|
||||
.Dv MTIOCGET
|
||||
.Xr ioctl
|
||||
call. If the operation was successful,
|
||||
an ``ack'' is sent with the size of the
|
||||
status buffer, then the status buffer is
|
||||
sent (in binary).
|
||||
.El
|
||||
.Sm on
|
||||
.Pp
|
||||
Any other command causes
|
||||
.Nm rmt
|
||||
to exit.
|
||||
.Sh DIAGNOSTICS
|
||||
All responses are of the form described above.
|
||||
.Sh SEE ALSO
|
||||
.Xr rcmd 3 ,
|
||||
.Xr rexec 3 ,
|
||||
.Xr mtio 4 ,
|
||||
.Xr rdump 8 ,
|
||||
.Xr rrestore 8
|
||||
.Sh BUGS
|
||||
People should be discouraged from using this for a remote
|
||||
file access protocol.
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.2 .
|
4
usr.sbin/sendmail/README
Normal file
4
usr.sbin/sendmail/README
Normal file
@ -0,0 +1,4 @@
|
||||
The beta version of sendmail 2.7.0 was removed at the developers request.
|
||||
|
||||
You can FTP the latest version from ftp.cs.berkeley.edu:/ucb/sendmail
|
||||
|
11
usr.sbin/sliplogin/slip.hosts
Normal file
11
usr.sbin/sliplogin/slip.hosts
Normal file
@ -0,0 +1,11 @@
|
||||
# @(#)slip.hosts 8.1 (Berkeley) 6/6/93
|
||||
#
|
||||
# login local-addr remote-addr mask opt1 opt2
|
||||
# (normal,compress,noicmp)
|
||||
#
|
||||
Schez vangogh chez 0xffffff00 compress
|
||||
Sjun vangogh 128.32.130.36 0xffffff00 normal
|
||||
Sleconte vangogh leconte 0xffffff00 compress
|
||||
Sleeb vangogh leeb 0xffffff00 compress
|
||||
Smjk vangogh pissaro-sl 0xffffff00 compress
|
||||
Soxford vangogh oxford 0xffffff00 compress
|
12
usr.sbin/sliplogin/slip.login
Normal file
12
usr.sbin/sliplogin/slip.login
Normal file
@ -0,0 +1,12 @@
|
||||
#!/bin/sh -
|
||||
#
|
||||
# @(#)slip.login 8.1 (Berkeley) 6/6/93
|
||||
|
||||
#
|
||||
# generic login file for a slip line. sliplogin invokes this with
|
||||
# the parameters:
|
||||
# 1 2 3 4 5 6 7-n
|
||||
# slipunit ttyspeed loginname local-addr remote-addr mask opt-args
|
||||
#
|
||||
/sbin/ifconfig sl$1 inet $4 $5 netmask $6
|
||||
exit
|
229
usr.sbin/sysctl/sysctl.8
Normal file
229
usr.sbin/sysctl/sysctl.8
Normal file
@ -0,0 +1,229 @@
|
||||
.\" Copyright (c) 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)sysctl.8 8.2 (Berkeley) 5/9/95
|
||||
.\"
|
||||
.Dd "May 9, 1995"
|
||||
.Dt SYSCTL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm sysctl
|
||||
.Nd get or set kernel state
|
||||
.Sh SYNOPSIS
|
||||
.Nm sysctl
|
||||
.Op Fl n
|
||||
.Ar name ...
|
||||
.Nm sysctl
|
||||
.Op Fl n
|
||||
.Fl w
|
||||
.Ar name=value ...
|
||||
.Nm sysctl
|
||||
.Op Fl n
|
||||
.Fl aA
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm sysctl
|
||||
utility retrieves kernel state and allows processes with
|
||||
appropriate privilege to set kernel state.
|
||||
The state to be retrieved or set is described using a
|
||||
``Management Information Base'' (``MIB'') style name,
|
||||
described as a dotted set of components.
|
||||
The
|
||||
.Fl a
|
||||
flag can be used to list all the currently available string or integer values.
|
||||
The
|
||||
.Fl A
|
||||
flag will list all the known MIB names including tables.
|
||||
Those with string or integer values will be printed as with the
|
||||
.Fl a
|
||||
flag; for the table values,
|
||||
the name of the utility to retrieve them is given.
|
||||
.Pp
|
||||
The
|
||||
.Fl n
|
||||
flag specifies that the printing of the field name should be
|
||||
suppressed and that only its value should be output.
|
||||
This flag is useful for setting shell variables.
|
||||
For example, to save the pagesize in variable psize, use:
|
||||
.Bd -literal -offset indent -compact
|
||||
set psize=`sysctl -n hw.pagesize`
|
||||
.Ed
|
||||
.Pp
|
||||
If just a MIB style name is given,
|
||||
the corresponding value is retrieved.
|
||||
If a value is to be set, the
|
||||
.Fl w
|
||||
flag must be specified and the MIB name followed
|
||||
by an equal sign and the new value to be used.
|
||||
.Pp
|
||||
The information available from
|
||||
.Nm sysctl
|
||||
consists of integers, strings, and tables.
|
||||
The tabular information can only be retrieved by special
|
||||
purpose programs such as
|
||||
.Nm ps ,
|
||||
.Nm systat ,
|
||||
and
|
||||
.Nm netstat .
|
||||
The string and integer information is summaried below.
|
||||
For a detailed description of these variable see
|
||||
.Xr sysctl 3 .
|
||||
The changeable column indicates whether a process with appropriate
|
||||
privilege can change the value.
|
||||
.Bl -column net.inet.ip.forwardingxxxxxx integerxxx
|
||||
.It Sy Name Type Changeable
|
||||
.It kern.ostype string no
|
||||
.It kern.osrelease string no
|
||||
.It kern.osrevision integer no
|
||||
.It kern.version string no
|
||||
.It kern.maxvnodes integer yes
|
||||
.It kern.maxproc integer yes
|
||||
.It kern.maxfiles integer yes
|
||||
.It kern.argmax integer no
|
||||
.It kern.securelevel integer raise only
|
||||
.It kern.hostname string yes
|
||||
.It kern.hostid integer yes
|
||||
.It kern.clockrate struct no
|
||||
.It kern.posix1version integer no
|
||||
.It kern.ngroups integer no
|
||||
.It kern.job_control integer no
|
||||
.It kern.saved_ids integer no
|
||||
.It kern.link_max integer no
|
||||
.It kern.max_canon integer no
|
||||
.It kern.max_input integer no
|
||||
.It kern.name_max integer no
|
||||
.It kern.path_max integer no
|
||||
.It kern.pipe_buf integer no
|
||||
.It kern.chown_restricted integer no
|
||||
.It kern.no_trunc integer no
|
||||
.It kern.vdisable integer no
|
||||
.It kern.boottime struct no
|
||||
.It vm.loadavg struct no
|
||||
.It machdep.console_device dev_t no
|
||||
.It net.inet.ip.forwarding integer yes
|
||||
.It net.inet.ip.redirect integer yes
|
||||
.It net.inet.ip.ttl integer yes
|
||||
.It net.inet.icmp.maskrepl integer yes
|
||||
.It net.inet.udp.checksum integer yes
|
||||
.It hw.machine string no
|
||||
.It hw.model string no
|
||||
.It hw.ncpu integer no
|
||||
.It hw.byteorder integer no
|
||||
.It hw.physmem integer no
|
||||
.It hw.usermem integer no
|
||||
.It hw.pagesize integer no
|
||||
.It user.cs_path string no
|
||||
.It user.bc_base_max integer no
|
||||
.It user.bc_dim_max integer no
|
||||
.It user.bc_scale_max integer no
|
||||
.It user.bc_string_max integer no
|
||||
.It user.coll_weights_max integer no
|
||||
.It user.expr_nest_max integer no
|
||||
.It user.line_max integer no
|
||||
.It user.re_dup_max integer no
|
||||
.It user.posix2_version integer no
|
||||
.It user.posix2_c_bind integer no
|
||||
.It user.posix2_c_dev integer no
|
||||
.It user.posix2_char_term integer no
|
||||
.It user.posix2_fort_dev integer no
|
||||
.It user.posix2_fort_run integer no
|
||||
.It user.posix2_localedef integer no
|
||||
.It user.posix2_sw_dev integer no
|
||||
.It user.posix2_upe integer no
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Nm sysctl
|
||||
program can get or set debugging variables
|
||||
that have been identified for its display.
|
||||
This information can be obtained by using the command:
|
||||
.Bd -literal -offset indent
|
||||
sysctl debug
|
||||
.Ed
|
||||
In addition,
|
||||
.Nm sysctl
|
||||
can extract information about the filesystems that have been compiled
|
||||
into the running system.
|
||||
This information can be obtained by using the command:
|
||||
.Bd -literal -offset indent
|
||||
sysctl vfs
|
||||
.Ed
|
||||
By default, only filesystems that are actively being used are listed.
|
||||
Use of the
|
||||
.Fl A
|
||||
flag lists all the filesystems compiled into the running kernel.
|
||||
.Sh EXAMPLES
|
||||
.Pp
|
||||
For example, to retrieve the maximum number of processes allowed
|
||||
in the system, one would use the follow request:
|
||||
.Bd -literal -offset indent -compact
|
||||
sysctl kern.maxproc
|
||||
.Ed
|
||||
.Pp
|
||||
To set the maximum number of processes allowed
|
||||
in the system to 1000, one would use the follow request:
|
||||
.Bd -literal -offset indent -compact
|
||||
sysctl -w kern.maxproc=1000
|
||||
.Ed
|
||||
.Pp
|
||||
Information about the system clock rate may be obtained with:
|
||||
.Bd -literal -offset indent -compact
|
||||
sysctl kern.clockrate
|
||||
.Ed
|
||||
.Pp
|
||||
Information about the load average history may be obtained with
|
||||
.Bd -literal -offset indent -compact
|
||||
sysctl vm.loadavg
|
||||
.Ed
|
||||
.Sh FILES
|
||||
.Bl -tag -width <netinet/icmpXvar.h> -compact
|
||||
.It Pa <sys/sysctl.h>
|
||||
definitions for top level identifiers, second level kernel and hardware
|
||||
identifiers, and user level identifiers
|
||||
.It Pa <sys/socket.h>
|
||||
definitions for second level network identifiers
|
||||
.It Pa <sys/gmon.h>
|
||||
definitions for third level profiling identifiers
|
||||
.It Pa <vm/vm_param.h>
|
||||
definitions for second level virtual memory identifiers
|
||||
.It Pa <netinet/in.h>
|
||||
definitions for third level Internet identifiers and
|
||||
fourth level IP identifiers
|
||||
.It Pa <netinet/icmp_var.h>
|
||||
definitions for fourth level ICMP identifiers
|
||||
.It Pa <netinet/udp_var.h>
|
||||
definitions for fourth level UDP identifiers
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr sysctl 3
|
||||
.Sh HISTORY
|
||||
.Nm sysctl
|
||||
first appeared in 4.4BSD.
|
644
usr.sbin/sysctl/sysctl.c
Normal file
644
usr.sbin/sysctl/sysctl.c
Normal file
@ -0,0 +1,644 @@
|
||||
/*
|
||||
* Copyright (c) 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)sysctl.c 8.5 (Berkeley) 5/9/95";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/gmon.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/ip_icmp.h>
|
||||
#include <netinet/icmp_var.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/udp_var.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct ctlname topname[] = CTL_NAMES;
|
||||
struct ctlname kernname[] = CTL_KERN_NAMES;
|
||||
struct ctlname vmname[] = CTL_VM_NAMES;
|
||||
struct ctlname netname[] = CTL_NET_NAMES;
|
||||
struct ctlname hwname[] = CTL_HW_NAMES;
|
||||
struct ctlname username[] = CTL_USER_NAMES;
|
||||
struct ctlname debugname[CTL_DEBUG_MAXID];
|
||||
struct ctlname *vfsname;
|
||||
#ifdef CTL_MACHDEP_NAMES
|
||||
struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
|
||||
#endif
|
||||
char names[BUFSIZ];
|
||||
int lastused;
|
||||
|
||||
struct list {
|
||||
struct ctlname *list;
|
||||
int size;
|
||||
};
|
||||
struct list toplist = { topname, CTL_MAXID };
|
||||
struct list secondlevel[] = {
|
||||
{ 0, 0 }, /* CTL_UNSPEC */
|
||||
{ kernname, KERN_MAXID }, /* CTL_KERN */
|
||||
{ vmname, VM_MAXID }, /* CTL_VM */
|
||||
{ 0, 0 }, /* CTL_VFS */
|
||||
{ netname, NET_MAXID }, /* CTL_NET */
|
||||
{ 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */
|
||||
{ hwname, HW_MAXID }, /* CTL_HW */
|
||||
#ifdef CTL_MACHDEP_NAMES
|
||||
{ machdepname, CPU_MAXID }, /* CTL_MACHDEP */
|
||||
#else
|
||||
{ 0, 0 }, /* CTL_MACHDEP */
|
||||
#endif
|
||||
{ username, USER_MAXID }, /* CTL_USER_NAMES */
|
||||
};
|
||||
|
||||
int Aflag, aflag, nflag, wflag;
|
||||
|
||||
/*
|
||||
* Variables requiring special processing.
|
||||
*/
|
||||
#define CLOCK 0x00000001
|
||||
#define BOOTTIME 0x00000002
|
||||
#define CONSDEV 0x00000004
|
||||
|
||||
int
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
int ch, lvl1;
|
||||
|
||||
while ((ch = getopt(argc, argv, "Aanw")) != EOF) {
|
||||
switch (ch) {
|
||||
|
||||
case 'A':
|
||||
Aflag = 1;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
aflag = 1;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
wflag = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0 && (Aflag || aflag)) {
|
||||
debuginit();
|
||||
vfsinit();
|
||||
for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
|
||||
listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
|
||||
exit(0);
|
||||
}
|
||||
if (argc == 0)
|
||||
usage();
|
||||
for (; *argv != NULL; ++argv)
|
||||
parse(*argv, 1);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* List all variables known to the system.
|
||||
*/
|
||||
listall(prefix, lp)
|
||||
char *prefix;
|
||||
struct list *lp;
|
||||
{
|
||||
int lvl2;
|
||||
char *cp, name[BUFSIZ];
|
||||
|
||||
if (lp->list == 0)
|
||||
return;
|
||||
strcpy(name, prefix);
|
||||
cp = &name[strlen(name)];
|
||||
*cp++ = '.';
|
||||
for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
|
||||
if (lp->list[lvl2].ctl_name == 0)
|
||||
continue;
|
||||
strcpy(cp, lp->list[lvl2].ctl_name);
|
||||
parse(name, Aflag);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a name into a MIB entry.
|
||||
* Lookup and print out the MIB entry if it exists.
|
||||
* Set a new value if requested.
|
||||
*/
|
||||
parse(string, flags)
|
||||
char *string;
|
||||
int flags;
|
||||
{
|
||||
int indx, type, state, len;
|
||||
size_t size;
|
||||
int special = 0;
|
||||
void *newval = 0;
|
||||
int intval, newsize = 0;
|
||||
quad_t quadval;
|
||||
struct list *lp;
|
||||
struct vfsconf vfc;
|
||||
int mib[CTL_MAXNAME];
|
||||
char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ];
|
||||
|
||||
bufp = buf;
|
||||
snprintf(buf, BUFSIZ, "%s", string);
|
||||
if ((cp = strchr(string, '=')) != NULL) {
|
||||
if (!wflag) {
|
||||
fprintf(stderr, "Must specify -w to set variables\n");
|
||||
exit(2);
|
||||
}
|
||||
*strchr(buf, '=') = '\0';
|
||||
*cp++ = '\0';
|
||||
while (isspace(*cp))
|
||||
cp++;
|
||||
newval = cp;
|
||||
newsize = strlen(cp);
|
||||
}
|
||||
if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
|
||||
return;
|
||||
mib[0] = indx;
|
||||
if (indx == CTL_VFS)
|
||||
vfsinit();
|
||||
if (indx == CTL_DEBUG)
|
||||
debuginit();
|
||||
lp = &secondlevel[indx];
|
||||
if (lp->list == 0) {
|
||||
fprintf(stderr, "%s: class is not implemented\n",
|
||||
topname[indx]);
|
||||
return;
|
||||
}
|
||||
if (bufp == NULL) {
|
||||
listall(topname[indx].ctl_name, lp);
|
||||
return;
|
||||
}
|
||||
if ((indx = findname(string, "second", &bufp, lp)) == -1)
|
||||
return;
|
||||
mib[1] = indx;
|
||||
type = lp->list[indx].ctl_type;
|
||||
len = 2;
|
||||
switch (mib[0]) {
|
||||
|
||||
case CTL_KERN:
|
||||
switch (mib[1]) {
|
||||
case KERN_PROF:
|
||||
mib[2] = GPROF_STATE;
|
||||
size = sizeof state;
|
||||
if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
|
||||
if (flags == 0)
|
||||
return;
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: ", string);
|
||||
fprintf(stderr,
|
||||
"kernel is not compiled for profiling\n");
|
||||
return;
|
||||
}
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: %s\n", string,
|
||||
state == GMON_PROF_OFF ? "off" : "running");
|
||||
return;
|
||||
case KERN_VNODE:
|
||||
case KERN_FILE:
|
||||
if (flags == 0)
|
||||
return;
|
||||
fprintf(stderr,
|
||||
"Use pstat to view %s information\n", string);
|
||||
return;
|
||||
case KERN_PROC:
|
||||
if (flags == 0)
|
||||
return;
|
||||
fprintf(stderr,
|
||||
"Use ps to view %s information\n", string);
|
||||
return;
|
||||
case KERN_CLOCKRATE:
|
||||
special |= CLOCK;
|
||||
break;
|
||||
case KERN_BOOTTIME:
|
||||
special |= BOOTTIME;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case CTL_HW:
|
||||
break;
|
||||
|
||||
case CTL_VM:
|
||||
if (mib[1] == VM_LOADAVG) {
|
||||
double loads[3];
|
||||
|
||||
getloadavg(loads, 3);
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: ", string);
|
||||
fprintf(stdout, "%.2f %.2f %.2f\n",
|
||||
loads[0], loads[1], loads[2]);
|
||||
return;
|
||||
}
|
||||
if (flags == 0)
|
||||
return;
|
||||
fprintf(stderr,
|
||||
"Use vmstat or systat to view %s information\n", string);
|
||||
return;
|
||||
|
||||
case CTL_NET:
|
||||
if (mib[1] == PF_INET) {
|
||||
len = sysctl_inet(string, &bufp, mib, flags, &type);
|
||||
if (len >= 0)
|
||||
break;
|
||||
return;
|
||||
}
|
||||
if (flags == 0)
|
||||
return;
|
||||
fprintf(stderr, "Use netstat to view %s information\n", string);
|
||||
return;
|
||||
|
||||
case CTL_DEBUG:
|
||||
mib[2] = CTL_DEBUG_VALUE;
|
||||
len = 3;
|
||||
break;
|
||||
|
||||
case CTL_MACHDEP:
|
||||
#ifdef CPU_CONSDEV
|
||||
if (mib[1] == CPU_CONSDEV)
|
||||
special |= CONSDEV;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case CTL_VFS:
|
||||
mib[3] = mib[1];
|
||||
mib[1] = VFS_GENERIC;
|
||||
mib[2] = VFS_CONF;
|
||||
len = 4;
|
||||
size = sizeof vfc;
|
||||
if (sysctl(mib, 4, &vfc, &size, (void *)0, (size_t)0) < 0) {
|
||||
perror("vfs print");
|
||||
return;
|
||||
}
|
||||
if (flags == 0 && vfc.vfc_refcount == 0)
|
||||
return;
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s has %d mounted instance%s\n",
|
||||
string, vfc.vfc_refcount,
|
||||
vfc.vfc_refcount != 1 ? "s" : "");
|
||||
else
|
||||
fprintf(stdout, "%d\n", vfc.vfc_refcount);
|
||||
return;
|
||||
|
||||
case CTL_USER:
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Illegal top level value: %d\n", mib[0]);
|
||||
return;
|
||||
|
||||
}
|
||||
if (bufp) {
|
||||
fprintf(stderr, "name %s in %s is unknown\n", *bufp, string);
|
||||
return;
|
||||
}
|
||||
if (newsize > 0) {
|
||||
switch (type) {
|
||||
case CTLTYPE_INT:
|
||||
intval = atoi(newval);
|
||||
newval = &intval;
|
||||
newsize = sizeof intval;
|
||||
break;
|
||||
|
||||
case CTLTYPE_QUAD:
|
||||
sscanf(newval, "%qd", &quadval);
|
||||
newval = &quadval;
|
||||
newsize = sizeof quadval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
size = BUFSIZ;
|
||||
if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
|
||||
if (flags == 0)
|
||||
return;
|
||||
switch (errno) {
|
||||
case EOPNOTSUPP:
|
||||
fprintf(stderr, "%s: value is not available\n", string);
|
||||
return;
|
||||
case ENOTDIR:
|
||||
fprintf(stderr, "%s: specification is incomplete\n",
|
||||
string);
|
||||
return;
|
||||
case ENOMEM:
|
||||
fprintf(stderr, "%s: type is unknown to this program\n",
|
||||
string);
|
||||
return;
|
||||
default:
|
||||
perror(string);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (special & CLOCK) {
|
||||
struct clockinfo *clkp = (struct clockinfo *)buf;
|
||||
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: ", string);
|
||||
fprintf(stdout,
|
||||
"hz = %d, tick = %d, profhz = %d, stathz = %d\n",
|
||||
clkp->hz, clkp->tick, clkp->profhz, clkp->stathz);
|
||||
return;
|
||||
}
|
||||
if (special & BOOTTIME) {
|
||||
struct timeval *btp = (struct timeval *)buf;
|
||||
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s = %s\n", string,
|
||||
ctime(&btp->tv_sec));
|
||||
else
|
||||
fprintf(stdout, "%d\n", btp->tv_sec);
|
||||
return;
|
||||
}
|
||||
if (special & CONSDEV) {
|
||||
dev_t dev = *(dev_t *)buf;
|
||||
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s = %s\n", string,
|
||||
devname(dev, S_IFCHR));
|
||||
else
|
||||
fprintf(stdout, "0x%x\n", dev);
|
||||
return;
|
||||
}
|
||||
switch (type) {
|
||||
case CTLTYPE_INT:
|
||||
if (newsize == 0) {
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s = ", string);
|
||||
fprintf(stdout, "%d\n", *(int *)buf);
|
||||
} else {
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: %d -> ", string,
|
||||
*(int *)buf);
|
||||
fprintf(stdout, "%d\n", *(int *)newval);
|
||||
}
|
||||
return;
|
||||
|
||||
case CTLTYPE_STRING:
|
||||
if (newsize == 0) {
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s = ", string);
|
||||
fprintf(stdout, "%s\n", buf);
|
||||
} else {
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: %s -> ", string, buf);
|
||||
fprintf(stdout, "%s\n", newval);
|
||||
}
|
||||
return;
|
||||
|
||||
case CTLTYPE_QUAD:
|
||||
if (newsize == 0) {
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s = ", string);
|
||||
fprintf(stdout, "%qd\n", *(quad_t *)buf);
|
||||
} else {
|
||||
if (!nflag)
|
||||
fprintf(stdout, "%s: %qd -> ", string,
|
||||
*(quad_t *)buf);
|
||||
fprintf(stdout, "%qd\n", *(quad_t *)newval);
|
||||
}
|
||||
return;
|
||||
|
||||
case CTLTYPE_STRUCT:
|
||||
fprintf(stderr, "%s: unknown structure returned\n",
|
||||
string);
|
||||
return;
|
||||
|
||||
default:
|
||||
case CTLTYPE_NODE:
|
||||
fprintf(stderr, "%s: unknown type returned\n",
|
||||
string);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the set of debugging names
|
||||
*/
|
||||
debuginit()
|
||||
{
|
||||
int mib[3], loc, i;
|
||||
size_t size;
|
||||
|
||||
if (secondlevel[CTL_DEBUG].list != 0)
|
||||
return;
|
||||
secondlevel[CTL_DEBUG].list = debugname;
|
||||
mib[0] = CTL_DEBUG;
|
||||
mib[2] = CTL_DEBUG_NAME;
|
||||
for (loc = lastused, i = 0; i < CTL_DEBUG_MAXID; i++) {
|
||||
mib[1] = i;
|
||||
size = BUFSIZ - loc;
|
||||
if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
|
||||
continue;
|
||||
debugname[i].ctl_name = &names[loc];
|
||||
debugname[i].ctl_type = CTLTYPE_INT;
|
||||
loc += size;
|
||||
}
|
||||
lastused = loc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the set of filesystem names
|
||||
*/
|
||||
vfsinit()
|
||||
{
|
||||
int mib[4], maxtypenum, cnt, loc, size;
|
||||
struct vfsconf vfc;
|
||||
size_t buflen;
|
||||
|
||||
if (secondlevel[CTL_VFS].list != 0)
|
||||
return;
|
||||
mib[0] = CTL_VFS;
|
||||
mib[1] = VFS_GENERIC;
|
||||
mib[2] = VFS_MAXTYPENUM;
|
||||
buflen = 4;
|
||||
if (sysctl(mib, 3, &maxtypenum, &buflen, (void *)0, (size_t)0) < 0)
|
||||
return;
|
||||
if ((vfsname = malloc(maxtypenum * sizeof(*vfsname))) == 0)
|
||||
return;
|
||||
memset(vfsname, 0, maxtypenum * sizeof(*vfsname));
|
||||
mib[2] = VFS_CONF;
|
||||
buflen = sizeof vfc;
|
||||
for (loc = lastused, cnt = 0; cnt < maxtypenum; cnt++) {
|
||||
mib[3] = cnt;
|
||||
if (sysctl(mib, 4, &vfc, &buflen, (void *)0, (size_t)0) < 0) {
|
||||
if (errno == EOPNOTSUPP)
|
||||
continue;
|
||||
perror("vfsinit");
|
||||
free(vfsname);
|
||||
return;
|
||||
}
|
||||
strcat(&names[loc], vfc.vfc_name);
|
||||
vfsname[cnt].ctl_name = &names[loc];
|
||||
vfsname[cnt].ctl_type = CTLTYPE_INT;
|
||||
size = strlen(vfc.vfc_name) + 1;
|
||||
loc += size;
|
||||
}
|
||||
lastused = loc;
|
||||
secondlevel[CTL_VFS].list = vfsname;
|
||||
secondlevel[CTL_VFS].size = maxtypenum;
|
||||
return;
|
||||
}
|
||||
|
||||
struct ctlname inetname[] = CTL_IPPROTO_NAMES;
|
||||
struct ctlname ipname[] = IPCTL_NAMES;
|
||||
struct ctlname icmpname[] = ICMPCTL_NAMES;
|
||||
struct ctlname udpname[] = UDPCTL_NAMES;
|
||||
struct list inetlist = { inetname, IPPROTO_MAXID };
|
||||
struct list inetvars[] = {
|
||||
{ ipname, IPCTL_MAXID }, /* ip */
|
||||
{ icmpname, ICMPCTL_MAXID }, /* icmp */
|
||||
{ 0, 0 }, /* igmp */
|
||||
{ 0, 0 }, /* ggmp */
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 }, /* tcp */
|
||||
{ 0, 0 },
|
||||
{ 0, 0 }, /* egp */
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 }, /* pup */
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ 0, 0 },
|
||||
{ udpname, UDPCTL_MAXID }, /* udp */
|
||||
};
|
||||
|
||||
/*
|
||||
* handle internet requests
|
||||
*/
|
||||
sysctl_inet(string, bufpp, mib, flags, typep)
|
||||
char *string;
|
||||
char **bufpp;
|
||||
int mib[];
|
||||
int flags;
|
||||
int *typep;
|
||||
{
|
||||
struct list *lp;
|
||||
int indx;
|
||||
|
||||
if (*bufpp == NULL) {
|
||||
listall(string, &inetlist);
|
||||
return (-1);
|
||||
}
|
||||
if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
|
||||
return (-1);
|
||||
mib[2] = indx;
|
||||
if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL)
|
||||
lp = &inetvars[indx];
|
||||
else if (!flags)
|
||||
return (-1);
|
||||
else {
|
||||
fprintf(stderr, "%s: no variables defined for this protocol\n",
|
||||
string);
|
||||
return (-1);
|
||||
}
|
||||
if (*bufpp == NULL) {
|
||||
listall(string, lp);
|
||||
return (-1);
|
||||
}
|
||||
if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
|
||||
return (-1);
|
||||
mib[3] = indx;
|
||||
*typep = lp->list[indx].ctl_type;
|
||||
return (4);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan a list of names searching for a particular name.
|
||||
*/
|
||||
findname(string, level, bufp, namelist)
|
||||
char *string;
|
||||
char *level;
|
||||
char **bufp;
|
||||
struct list *namelist;
|
||||
{
|
||||
char *name;
|
||||
int i;
|
||||
|
||||
if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
|
||||
fprintf(stderr, "%s: incomplete specification\n", string);
|
||||
return (-1);
|
||||
}
|
||||
for (i = 0; i < namelist->size; i++)
|
||||
if (namelist->list[i].ctl_name != NULL &&
|
||||
strcmp(name, namelist->list[i].ctl_name) == 0)
|
||||
break;
|
||||
if (i == namelist->size) {
|
||||
fprintf(stderr, "%s level name %s in %s is invalid\n",
|
||||
level, name, string);
|
||||
return (-1);
|
||||
}
|
||||
return (i);
|
||||
}
|
||||
|
||||
usage()
|
||||
{
|
||||
|
||||
(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
|
||||
"sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
|
||||
"sysctl [-n] -a", "sysctl [-n] -A");
|
||||
exit(1);
|
||||
}
|
337
usr.sbin/traceroute/traceroute.8
Normal file
337
usr.sbin/traceroute/traceroute.8
Normal file
@ -0,0 +1,337 @@
|
||||
.\" Copyright (c) 1990, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to Berkeley by
|
||||
.\" Van Jacobson.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)traceroute.8 8.2 (Berkeley) 6/1/94
|
||||
.\"
|
||||
.Dd June 1, 1994
|
||||
.Dt TRACEROUTE 8
|
||||
.Os BSD 4.3
|
||||
.Sh NAME
|
||||
.Nm traceroute
|
||||
.Nd print the route packets take to network host
|
||||
.Sh SYNOPSIS
|
||||
.Nm traceroute
|
||||
.Op Fl m Ar max_ttl
|
||||
.Op Fl n
|
||||
.Op Fl p Ar port
|
||||
.Op Fl q Ar nqueries
|
||||
.Op Fl r
|
||||
.Bk -words
|
||||
.Op Fl s Ar src_addr
|
||||
.Ek
|
||||
.Op Fl t Ar tos
|
||||
.Op Fl w Ar waittime
|
||||
.Ar host
|
||||
.Op Ar packetsize
|
||||
.Sh DESCRIPTION
|
||||
The Internet is a large and complex aggregation of
|
||||
network hardware, connected together by gateways.
|
||||
Tracking the route one's packets follow (or finding the miscreant
|
||||
gateway that's discarding your packets) can be difficult.
|
||||
.Nm Traceroute
|
||||
utilizes the IP protocol `time to live' field and attempts to elicit an
|
||||
.Tn ICMP
|
||||
.Dv TIME_EXCEEDED
|
||||
response from each gateway along the path to some
|
||||
host.
|
||||
.Pp
|
||||
The only mandatory parameter is the destination host name or IP number.
|
||||
The default probe datagram length is 38 bytes, but this may be increased
|
||||
by specifying a packet size (in bytes) after the destination host
|
||||
name.
|
||||
.Pp
|
||||
Other options are:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl m Ar max_ttl
|
||||
Set the max time-to-live (max number of hops) used in outgoing probe
|
||||
packets. The default is 30 hops (the same default used for
|
||||
.Tn TCP
|
||||
connections).
|
||||
.It Fl n
|
||||
Print hop addresses numerically rather than symbolically and numerically
|
||||
(saves a nameserver address-to-name lookup for each gateway found on the
|
||||
path).
|
||||
.It Fl p Ar port
|
||||
Set the base
|
||||
.Tn UDP
|
||||
.Ar port
|
||||
number used in probes (default is 33434).
|
||||
.Nm Traceroute
|
||||
hopes that nothing is listening on
|
||||
.Tn UDP
|
||||
ports
|
||||
.Em base
|
||||
to
|
||||
.Em base+nhops-1
|
||||
at the destination host (so an
|
||||
.Tn ICMP
|
||||
.Dv PORT_UNREACHABLE
|
||||
message will
|
||||
be returned to terminate the route tracing). If something is
|
||||
listening on a port in the default range, this option can be used
|
||||
to pick an unused port range.
|
||||
.It Fl q Ar nqueries
|
||||
Set the number of probes per ``ttl'' to
|
||||
.Ar nqueries
|
||||
(default is three probes).
|
||||
.It Fl r
|
||||
Bypass the normal routing tables and send directly to a host on an attached
|
||||
network.
|
||||
If the host is not on a directly-attached network,
|
||||
an error is returned.
|
||||
This option can be used to ping a local host through an interface
|
||||
that has no route through it (e.g., after the interface was dropped by
|
||||
.Xr routed 8 ) .
|
||||
.It Fl s Ar src_addr
|
||||
Use the following IP address
|
||||
(which must be given as an IP number, not
|
||||
a hostname) as the source address in outgoing probe packets. On
|
||||
hosts with more than one IP address, this option can be used to
|
||||
force the source address to be something other than the IP address
|
||||
of the interface the probe packet is sent on. If the IP address
|
||||
is not one of this machine's interface addresses, an error is
|
||||
returned and nothing is sent.
|
||||
.ne 1i
|
||||
.It Fl t Ar tos
|
||||
Set the
|
||||
.Em type-of-service
|
||||
in probe packets to the following value (default zero). The value must be
|
||||
a decimal integer in the range 0 to 255. This option can be used to
|
||||
see if different types-of-service result in different paths. (If you
|
||||
are not running a
|
||||
.Bx 4.3 tahoe
|
||||
or later system, this may be academic since the normal network
|
||||
services like telnet and ftp don't let you control the
|
||||
.Dv TOS ) .
|
||||
Not all values of
|
||||
.Dv TOS
|
||||
are legal or
|
||||
meaningful \- see the IP spec for definitions. Useful values are
|
||||
probably
|
||||
.Ql \-t 16
|
||||
(low delay) and
|
||||
.Ql \-t 8
|
||||
(high throughput).
|
||||
.It Fl v
|
||||
Verbose output. Received
|
||||
.Tn ICMP
|
||||
packets other than
|
||||
.Dv TIME_EXCEEDED
|
||||
and
|
||||
.Dv UNREACHABLE Ns s
|
||||
are listed.
|
||||
.It Fl w
|
||||
Set the time (in seconds) to wait for a response to a probe (default 3
|
||||
sec.).
|
||||
.El
|
||||
.Pp
|
||||
This program attempts to trace the route an IP packet would follow to some
|
||||
internet host by launching
|
||||
.Tn UDP
|
||||
probe
|
||||
packets with a small ttl (time to live) then listening for an
|
||||
.Tn ICMP
|
||||
"time exceeded" reply from a gateway. We start our probes
|
||||
with a ttl of one and increase by one until we get an
|
||||
.Tn ICMP
|
||||
"port unreachable"
|
||||
(which means we got to "host") or hit a max (which
|
||||
defaults to 30 hops & can be changed with the
|
||||
.Fl m
|
||||
flag). Three
|
||||
probes (changed with
|
||||
.Fl q
|
||||
flag) are sent at each ttl setting and a
|
||||
line is printed showing the ttl, address of the gateway and
|
||||
round trip time of each probe. If the probe answers come from
|
||||
different gateways, the address of each responding system will
|
||||
be printed. If there is no response within a 3 sec. timeout
|
||||
interval (changed with the
|
||||
.Fl w
|
||||
flag), a "*" is printed for that
|
||||
probe.
|
||||
.Pp
|
||||
We don't want the destination
|
||||
host to process the
|
||||
.Tn UDP
|
||||
probe packets so the destination port is set to an
|
||||
unlikely value (if some clod on the destination is using that
|
||||
value, it can be changed with the
|
||||
.Fl p
|
||||
flag).
|
||||
.Pp
|
||||
A sample use and output might be:
|
||||
.Bd -literal
|
||||
[yak 71]% traceroute nis.nsf.net.
|
||||
traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet
|
||||
1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms
|
||||
2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
|
||||
3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms
|
||||
4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms
|
||||
5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms
|
||||
6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms
|
||||
7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms
|
||||
8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms
|
||||
9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms
|
||||
10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms
|
||||
11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms
|
||||
|
||||
.Ed
|
||||
Note that lines 2 & 3 are the same. This is due to a buggy
|
||||
kernel on the 2nd hop system \- lbl-csam.arpa \- that forwards
|
||||
packets with a zero ttl (a bug in the distributed version
|
||||
of 4.3
|
||||
.Tn BSD ) .
|
||||
Note that you have to guess what path
|
||||
the packets are taking cross-country since the
|
||||
.Tn NSFNet
|
||||
(129.140)
|
||||
doesn't supply address-to-name translations for its
|
||||
.Tn NSS Ns es .
|
||||
.Pp
|
||||
A more interesting example is:
|
||||
.Bd -literal
|
||||
[yak 72]% traceroute allspice.lcs.mit.edu.
|
||||
traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max
|
||||
1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
|
||||
2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms
|
||||
3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms
|
||||
4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms
|
||||
5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms
|
||||
6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms
|
||||
7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms
|
||||
8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms
|
||||
9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms
|
||||
10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms
|
||||
11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms
|
||||
12 * * *
|
||||
13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms
|
||||
14 * * *
|
||||
15 * * *
|
||||
16 * * *
|
||||
17 * * *
|
||||
18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms
|
||||
|
||||
.Ed
|
||||
Note that the gateways 12, 14, 15, 16 & 17 hops away
|
||||
either don't send
|
||||
.Tn ICMP
|
||||
"time exceeded" messages or send them
|
||||
with a ttl too small to reach us. 14 \- 17 are running the
|
||||
.Tn MIT
|
||||
C Gateway code that doesn't send "time exceeded"s. God
|
||||
only knows what's going on with 12.
|
||||
.Pp
|
||||
The silent gateway 12 in the above may be the result of a bug in
|
||||
the 4.[23]
|
||||
.Tn BSD
|
||||
network code (and its derivatives): 4.x (x <= 3)
|
||||
sends an unreachable message using whatever ttl remains in the
|
||||
original datagram. Since, for gateways, the remaining ttl is
|
||||
zero, the
|
||||
.Tn ICMP
|
||||
"time exceeded" is guaranteed to not make it back
|
||||
to us. The behavior of this bug is slightly more interesting
|
||||
when it appears on the destination system:
|
||||
.Bd -literal
|
||||
1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms
|
||||
2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms
|
||||
3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms
|
||||
4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms
|
||||
5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms
|
||||
6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms
|
||||
7 * * *
|
||||
8 * * *
|
||||
9 * * *
|
||||
10 * * *
|
||||
11 * * *
|
||||
12 * * *
|
||||
13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms !
|
||||
|
||||
.Ed
|
||||
Notice that there are 12 "gateways" (13 is the final
|
||||
destination) and exactly the last half of them are "missing".
|
||||
What's really happening is that rip (a Sun-3 running Sun OS3.5)
|
||||
is using the ttl from our arriving datagram as the ttl in its
|
||||
.Tn ICMP
|
||||
reply. So, the reply will time out on the return path
|
||||
(with no notice sent to anyone since
|
||||
.Tn ICMP's
|
||||
aren't sent for
|
||||
.Tn ICMP's )
|
||||
until we probe with a ttl that's at least twice the path
|
||||
length. I.e., rip is really only 7 hops away. A reply that
|
||||
returns with a ttl of 1 is a clue this problem exists.
|
||||
.Nm Traceroute
|
||||
prints a "!" after the time if the ttl is <= 1.
|
||||
Since vendors ship a lot of obsolete
|
||||
.Pf ( Tn DEC Ns \'s
|
||||
Ultrix, Sun 3.x) or
|
||||
non-standard
|
||||
.Pq Tn HPUX
|
||||
software, expect to see this problem
|
||||
frequently and/or take care picking the target host of your
|
||||
probes.
|
||||
Other possible annotations after the time are
|
||||
.Sy !H ,
|
||||
.Sy !N ,
|
||||
.Sy !P
|
||||
(got a host, network or protocol unreachable, respectively),
|
||||
.Sy !S
|
||||
or
|
||||
.Sy !F
|
||||
(source route failed or fragmentation needed \- neither of these should
|
||||
ever occur and the associated gateway is busted if you see one). If
|
||||
almost all the probes result in some kind of unreachable,
|
||||
.Nm traceroute
|
||||
will give up and exit.
|
||||
.Pp
|
||||
This program is intended for use in network testing, measurement
|
||||
and management.
|
||||
It should be used primarily for manual fault isolation.
|
||||
Because of the load it could impose on the network, it is unwise to use
|
||||
.Nm traceroute
|
||||
during normal operations or from automated scripts.
|
||||
.Sh AUTHOR
|
||||
Implemented by Van Jacobson from a suggestion by Steve Deering. Debugged
|
||||
by a cast of thousands with particularly cogent suggestions or fixes from
|
||||
C. Philip Wood, Tim Seaver and Ken Adelman.
|
||||
.Sh SEE ALSO
|
||||
.Xr netstat 1 ,
|
||||
.Xr ping 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
command
|
||||
.Bt
|
6
usr.sbin/update/Makefile
Normal file
6
usr.sbin/update/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
# @(#)Makefile 8.1 (Berkeley) 6/6/93
|
||||
|
||||
PROG= update
|
||||
MAN8= update.0
|
||||
|
||||
.include <bsd.prog.mk>
|
74
usr.sbin/update/update.8
Normal file
74
usr.sbin/update/update.8
Normal file
@ -0,0 +1,74 @@
|
||||
.\" Copyright (c) 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)update.8 8.3 (Berkeley) 4/19/94
|
||||
.\"
|
||||
.Dd April 19, 1994
|
||||
.Dt UPDATE 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm update
|
||||
.Nd flush internal filesystem caches to disk frequently
|
||||
.Sh SYNOPSIS
|
||||
.Nm update
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm update
|
||||
command helps protect the integrity of disk volumes
|
||||
by flushing
|
||||
volatile cached filesystem data
|
||||
to disk at thirty second intervals.
|
||||
.Nm Update
|
||||
uses the
|
||||
.Xr sync 2
|
||||
function call to do the task.
|
||||
.Pp
|
||||
.Nm Update
|
||||
is commonly invoked at startup time by
|
||||
.Xr rc 8
|
||||
when the system goes multi-user.
|
||||
.Sh SEE ALSO
|
||||
.Xr sync 2 ,
|
||||
.Xr fsck 8 ,
|
||||
.Xr init 8 ,
|
||||
.Xr rc 8 ,
|
||||
.Xr sync 8
|
||||
.Sh BUGS
|
||||
It is possible on some systems that a
|
||||
.Xr sync
|
||||
occurring simultaneously with a crash may cause
|
||||
file system damage. See
|
||||
.Xr fsck 8 .
|
||||
.Sh HISTORY
|
||||
An
|
||||
.Nm update
|
||||
command appeared in
|
||||
.At v6 .
|
75
usr.sbin/update/update.c
Normal file
75
usr.sbin/update/update.c
Normal file
@ -0,0 +1,75 @@
|
||||
/*-
|
||||
* Copyright (c) 1987, 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1987, 1990, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)update.c 8.1 (Berkeley) 6/6/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
main()
|
||||
{
|
||||
struct itimerval value;
|
||||
void mysync();
|
||||
|
||||
daemon(0, 0);
|
||||
|
||||
(void)signal(SIGALRM, mysync);
|
||||
|
||||
value.it_interval.tv_sec = 30;
|
||||
value.it_interval.tv_usec = 0;
|
||||
value.it_value = value.it_interval;
|
||||
if (setitimer(ITIMER_REAL, &value, NULL)) {
|
||||
perror("update: setitimer");
|
||||
exit(1);
|
||||
}
|
||||
for (;;)
|
||||
sigpause(sigblock(0L));
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void
|
||||
mysync()
|
||||
{
|
||||
(void)sync();
|
||||
}
|
220
usr.sbin/vipw/pw_util.c
Normal file
220
usr.sbin/vipw/pw_util.c
Normal file
@ -0,0 +1,220 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)pw_util.c 8.4 (Berkeley) 4/28/95";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
* This file is used by all the "password" programs; vipw(8), chpass(1),
|
||||
* and passwd(1).
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pw_util.h"
|
||||
|
||||
extern char *tempname;
|
||||
static pid_t editpid = -1;
|
||||
static int lockfd;
|
||||
|
||||
void
|
||||
pw_cont(sig)
|
||||
int sig;
|
||||
{
|
||||
|
||||
if (editpid != -1)
|
||||
kill(editpid, sig);
|
||||
}
|
||||
|
||||
void
|
||||
pw_init()
|
||||
{
|
||||
struct rlimit rlim;
|
||||
|
||||
/* Unlimited resource limits. */
|
||||
rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
|
||||
(void)setrlimit(RLIMIT_CPU, &rlim);
|
||||
(void)setrlimit(RLIMIT_FSIZE, &rlim);
|
||||
(void)setrlimit(RLIMIT_STACK, &rlim);
|
||||
(void)setrlimit(RLIMIT_DATA, &rlim);
|
||||
(void)setrlimit(RLIMIT_RSS, &rlim);
|
||||
|
||||
/* Don't drop core (not really necessary, but GP's). */
|
||||
rlim.rlim_cur = rlim.rlim_max = 0;
|
||||
(void)setrlimit(RLIMIT_CORE, &rlim);
|
||||
|
||||
/* Turn off signals. */
|
||||
(void)signal(SIGALRM, SIG_IGN);
|
||||
(void)signal(SIGHUP, SIG_IGN);
|
||||
(void)signal(SIGINT, SIG_IGN);
|
||||
(void)signal(SIGPIPE, SIG_IGN);
|
||||
(void)signal(SIGQUIT, SIG_IGN);
|
||||
(void)signal(SIGTERM, SIG_IGN);
|
||||
(void)signal(SIGCONT, pw_cont);
|
||||
|
||||
/* Create with exact permissions. */
|
||||
(void)umask(0);
|
||||
}
|
||||
|
||||
int
|
||||
pw_lock()
|
||||
{
|
||||
/*
|
||||
* If the master password file doesn't exist, the system is hosed.
|
||||
* Might as well try to build one. Set the close-on-exec bit so
|
||||
* that users can't get at the encrypted passwords while editing.
|
||||
* Open should allow flock'ing the file; see 4.4BSD. XXX
|
||||
*/
|
||||
lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
|
||||
if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1)
|
||||
err(1, "%s", _PATH_MASTERPASSWD);
|
||||
if (flock(lockfd, LOCK_EX|LOCK_NB))
|
||||
errx(1, "the password db file is busy");
|
||||
return (lockfd);
|
||||
}
|
||||
|
||||
int
|
||||
pw_tmp()
|
||||
{
|
||||
static char path[MAXPATHLEN] = _PATH_MASTERPASSWD;
|
||||
int fd;
|
||||
char *p;
|
||||
|
||||
if (p = strrchr(path, '/'))
|
||||
++p;
|
||||
else
|
||||
p = path;
|
||||
strcpy(p, "pw.XXXXXX");
|
||||
if ((fd = mkstemp(path)) == -1)
|
||||
err(1, "%s", path);
|
||||
tempname = path;
|
||||
return (fd);
|
||||
}
|
||||
|
||||
int
|
||||
pw_mkdb()
|
||||
{
|
||||
int pstat;
|
||||
pid_t pid;
|
||||
|
||||
warnx("rebuilding the database...");
|
||||
(void)fflush(stderr);
|
||||
if (!(pid = vfork())) {
|
||||
execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
|
||||
pw_error(_PATH_PWD_MKDB, 1, 1);
|
||||
}
|
||||
pid = waitpid(pid, &pstat, 0);
|
||||
if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
|
||||
return (0);
|
||||
warnx("done");
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
pw_edit(notsetuid)
|
||||
int notsetuid;
|
||||
{
|
||||
int pstat;
|
||||
char *p, *editor;
|
||||
|
||||
if (!(editor = getenv("EDITOR")))
|
||||
editor = _PATH_VI;
|
||||
if (p = strrchr(editor, '/'))
|
||||
++p;
|
||||
else
|
||||
p = editor;
|
||||
|
||||
if (!(editpid = vfork())) {
|
||||
if (notsetuid) {
|
||||
(void)setgid(getgid());
|
||||
(void)setuid(getuid());
|
||||
}
|
||||
execlp(editor, p, tempname, NULL);
|
||||
_exit(1);
|
||||
}
|
||||
for (;;) {
|
||||
editpid = waitpid(editpid, (int *)&pstat, WUNTRACED);
|
||||
if (editpid == -1)
|
||||
pw_error(editor, 1, 1);
|
||||
else if (WIFSTOPPED(pstat))
|
||||
raise(WSTOPSIG(pstat));
|
||||
else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0)
|
||||
break;
|
||||
else
|
||||
pw_error(editor, 1, 1);
|
||||
}
|
||||
editpid = -1;
|
||||
}
|
||||
|
||||
void
|
||||
pw_prompt()
|
||||
{
|
||||
int c;
|
||||
|
||||
(void)printf("re-edit the password file? [y]: ");
|
||||
(void)fflush(stdout);
|
||||
c = getchar();
|
||||
if (c != EOF && c != '\n')
|
||||
while (getchar() != '\n');
|
||||
if (c == 'n')
|
||||
pw_error(NULL, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
pw_error(name, err, eval)
|
||||
char *name;
|
||||
int err, eval;
|
||||
{
|
||||
if (err)
|
||||
warn(name);
|
||||
|
||||
warnx("%s: unchanged", _PATH_MASTERPASSWD);
|
||||
(void)unlink(tempname);
|
||||
exit(eval);
|
||||
}
|
Loading…
Reference in New Issue
Block a user