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:
Bruce Evans 1997-08-02 19:36:03 +00:00
parent 9c60775004
commit 59fe2c14b4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/WIN_TUE_NL/; revision=27850
40 changed files with 11618 additions and 0 deletions

229
sbin/sysctl/sysctl.8 Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

233
usr.sbin/amd/amd/amd.8 Normal file
View 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
View 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
View 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 */

View 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>

View 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 */

View 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
View 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
View 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
View 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
View 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
View 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);
}

View 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

View 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 .

View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}

View 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
View 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
View 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, &reg))
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, &reg))
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, &reg))
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);
}

View 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
View 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 .

View 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
View 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
View 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

View 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

View 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
View 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
View 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);
}

View 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
View 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
View 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
View 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
View 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);
}