*BSD News Article 58335


Return to BSD News archive

Newsgroups: comp.bugs.2bsd
Path: euryale.cc.adfa.oz.au!newshost.anu.edu.au!harbinger.cc.monash.edu.au!news.mel.connect.com.au!munnari.OZ.AU!spool.mu.edu!howland.reston.ans.net!newsfeed.internetmci.com!in1.uu.net!news.new-york.net!wlbr!sms
From: sms@wlv.iipo.gtegsc.com (Steven M. Schultz)
Subject: TU81 bug,statfs(2)+fstatfs(2)+getfsstat(2) missing, More (#283 1 of 4)
Sender: news@wlbr.iipo.gtegsc.com (Steven M. Schultz)
Organization: GTE Government Systems, Thousand Oaks CA USA
Message-ID: <DKAHAz.9IK@wlbr.iipo.gtegsc.com>
X-Nntp-Posting-Host: wlv.iipo.gtegsc.com
Date: Thu, 28 Dec 1995 09:06:35 GMT
Lines: 3330

Subject: TU81 bug,statfs(2)+fstatfs(2)+getfsstat(2) missing, More (#283 1 of 4)
Index:	sys/pdpuba,pdp,sys 2.11BSD

Description:
	The TU81 (and TU81+) drives are not handled correctly by the TMSCP
	driver.  Multiple files can not be created on a single tape.

	The TMSCP driver does not properly check for end of media errors
	which can flood the kernel logging buffer with messages if an
	application persists in ignoring the initial error.

	The TMSCP driver does not correctly check for or handle the caching 
	capability of TU81+ drives.

	The 'mt(1)' program did not implement the commands necessary to
	turn caching on and off.

	The system calls 'statfs(2)', 'fstatfs(2)', 'getfsstat(2)' are
	missing from the system.

	The routine 'getmntinfo(3)' is missing from the C library.

	The version of 'ping(8)' present in the system is not a newer
	4.4BSD-Lite version.

	A couple "standard" include files (stddef.h, stdlib.h) useful in
	porting software are not present in the system.

	The check by the kernel to avoid swapping to a partition unless that
	partition was of type FS_SWAP was wrong.  

	When mounting a filesystem the kernel did not check that the
	partition type was valid.

	The 'fs_ilock' member of the superblock was on an ODD byte boundary.

Repeat-By:
	The TMSCP bugs can easily be seen writing a file to the non-rewinding
	device and then immediately trying to write a second file.  An
	immediate error will always result until the tape drive is rewound.

	That 'fs_ilock' being incorrectly aligned has not caused a crash
	(or rather no crash has been attributed to the wrong alignment)
	is amazing.  Evidently the locking has not been necessary YET.

	The remainder of the items in 'Description:' are 'repeated' by 
	"observation".

Fix:
	This is part 1 of 4.  The four parts are:
	
		#283   -  Contains the description, installation instructions,
			  shell script of files to be renamed/removed, and
			  the shar archive of new files to be added to the
			  system.

		#284 -	  The first of 3 patch files.  These files are
			  updated:

			/usr/include/syscall.h
			/usr/lib/tmac/tmac.an.new
			/usr/src/bin/mt.c
			/usr/src/etc/Makefile
			/usr/src/etc/mount.c
			/usr/src/lib/libc/gen/Makefile
			/usr/src/lib/libc/pdp/sys/Makefile
			/usr/src/man/man1/mt.1
			/usr/src/man/man2/Makefile
			/usr/src/man/man3/Makefile
			/usr/src/man/man4/mtio.4
			/usr/src/man/man4/tmscp.4
			/usr/src/man/man8/Makefile
			/usr/src/sys/conf/GENERIC
			/usr/src/sys/conf/Make.nsunix
			/usr/src/sys/conf/Make.pdpuba
			/usr/src/sys/conf/Make.sunix
			/usr/src/sys/conf/Make.sys
			/usr/src/sys/conf/Make.unix

		#285  -  The second part of the patches.  These files are
			 updated:

			/usr/src/sys/h/errno.h
			/usr/src/sys/h/fs.h
			/usr/src/sys/h/inode.h
			/usr/src/sys/h/mount.h
			/usr/src/sys/h/mtio.h
			/usr/src/sys/h/param.h
			/usr/src/sys/pdp/conf.c
			/usr/src/sys/pdp/machdep2.c
			/usr/src/sys/pdp/tmscp.h
			/usr/src/sys/sys/init_main.c
			/usr/src/sys/sys/init_sysent.c
			/usr/src/sys/sys/syscalls.c
			/usr/src/sys/sys/ufs_mount.c
			/usr/src/sys/sys/ufs_syscalls.c

		#286  -  The third and last part of the patches.  This is
			 also the largest patch file even though only 3 files
			 are being updated:

			/usr/src/sys/pdpuba/tmscp.c
			/usr/src/sys/pdpuba/tmscpreg.h
			/VERSION

	And now for the narrative of how what started out to be a "simple"
	(ha!) update of the TMSCP driver turned into a 4 part monster of
	a patch kit.

	Note:  the TU81 changes _should_ work, they've not been tested 
	extensively.  The TMSCP driver does work at least as well as before
	(and in the case of EOT detection the driver is much better).  It is
	anticipated there will be a small update later to the TMSCP driver.

	While waiting for test time on a system with a real TU81+ I stumbled
	across some listings from 1 year ago containing notes on porting
	the filesystem statistics syscalls (statfs, getfsstat) and resumed
	work on it.
	
	Since ufs_syscalls.c was already large (becoming unwieldy to find 
	a suitable place in the overlay structure for it) a new file 
	'ufs_syscalls2.c' was created.  Adding new modules to the kernel
	means that the Make.* files in /sys/conf have to be updated and
	in the case of the GENERIC config file the overlay structure has to
	be corrected (this is because the GENERIC kernel is always supposed
	to config+build without any changes).

	Odd wakeup channels are reserved for the networking code 
	the kernel should NEVER sleep on an odd wakeup - if 'fs_ilock' were
	ever used for sleeping then when the wakeup() was done the system
	would launch itself into hyperspace (and crash shortly there after).
	The fields in the superblock which were reordered are always
	initialized when a filesystem is mounted.

	Some time back the 4.4BSD-Lite version of 'ping' was ported (mainly to
	see how hard it would be - turned out to be quite easy).  The 'flood'
	capability is present although a 2.11 system will not place nearly 
	the load on a network that a faster system would.  DO NOT flood ping
	_to_ a 2.11 system unless you want to kill the 2.11 system - the
	mbuf pool becomes exhausted and the system becomes 'unresponsive'
	(to say the least).

	The TMSCP driver was the initial reason for this whole kit, and the
	update to the TMSCP driver is the largest single part (accounting for
	about 1/3 of the total size).  Initially the hope was to reduce the
	size of the driver.  Alas this was not how it turned out.  While
	the D-space requirements were reduced slightly (hurrah!) the code
	size increased dramatically.  This is due to several factors:  1) The
	addition of much more return status checking, 2) some additional
	debug code (which can be removed by commenting out the 'TMSDEBUG'
	statement at the top of tmscp.c), 3) reorganization - each function
	(read, write, reposition, etc) now has its own "start" and "end"
	routines.  This added a fair amount of code but makes it possible
	to perform function specific processing without complicated 'switch'
	statements and sharing common 'case' paths.

	The 4.4BSD-Lite version of 'df' was ported (mainly by ripping out
	NFS related code - if anyone every implements NFS for 2.11BSD then
	I'll volunteer to re-port 'df' and friends).  The new version of 'df'
	uses the new system calls to retrieve filesystem information and is
	at least twice as fast as before (because it does not have to open
	the raw device, read the superblock, and then close the device).

	In sys/init_main.c the check for the swap area being of type
	'FS_SWAP' was wrong.  The swap device is a "BLOCK" (IFBLK) device
	and not a "CHARACTER" (IFCHR) device - thus, the reference
	"cdevsw[major(swapdev)]" was referring to the wrong device.  For
	MSCP disks the kernel was actually calling the LP driver's 'ioctl'
	routine!  What was needed was a routine to translate between
	'block' and 'character' major device numbers.  There already existed
	a table in pdp/conf.c which contained the 'character' to 'block'
	mapping - it was a simple matter to use the same table to provide
	the reverse translation.

	The 'mount' structure now has an extension structure associated
	with it - this extension is external to the kernel and is mapped
	in as needed.  In this extension structure are kept the full pathnames
	of the device being mounted (/dev/ra0g, etc) and the mount path
	(/userfiles/home, etc).  At present only these two items are kept
	in the extension structure but in the future if the mount structure
	grows the additional members can be kept external to the kernel.

	In sys/ufs_mount.c code was added to check for a 'mount' being
	done on the root filesystem.  Previously this would have resulted
	in a 'EBUSY' error (/etc/mount skipped mounting "/")  because the
	kernel already has mounted '/' upon boot.  The changes to ufs_mount.c
	check for '/' being mounted a second time and only update the
	f_mntfromname field in the external mount structure extension.

	When the system boots to single user state the kernel does not know
	the name of the root device (/dev/ra0a) - all the kernel knows is
	the major and minor device numbers (5 and 0 respectively for ra0a).
	The kernel places 'root' in the 'f_mntfromname' field - when /etc/rc
	does the "mount -a" then /etc/mount will mount "/" from the root device
	and the kernel will update ONLY the 'f_mntfromname' field and return.

	Basically it's a poor man's method of implementing MNT_UPDATE for
	the specific case of the root filesystem.

	Finally, the 'mount' program was modified to not skip over the 
	root filesystem when doing the "mount -a" (from /etc/rc).  This
	change combined with the modifications in ufs_mount.c causes 
	"/" to be entered into the /etc/mtab file.  Now when you type 
	"mount" you will see something like:

		ra0a on /
		ra0c on /user
		ra0e on /usr
		ra0f on /xxx

	instead of

		ra0c on /user
		ra0e on /usr
		ra0f on /xxx

	AND now the moment you've all been waiting for - how to install
	the update kit!

	1) Make sure you have all 4 parts (#283, 284, 285 and 286).  The
	   instructions are only given in this part (#283).

	   Remove the mail headers from each of the four parts by cutting
	   where indicated and save the 4 parts to tmp files.  I will refer 
	   to the saved files as /tmp/283, /tmp/284, /tmp/285 and /tmp/286.
	   If you use different names then substitute as appropriate below.

	2) The first part is a shar file containing two files, a shell script
	   and a shar file (the last 3 parts are simple patch files).  Unpack 
	   by:

		cd /tmp
		sh 283

	3) Run the shell script:

		./move.283

	   this renames (rather than removing) df.c, ping.c and ping.8.  If
	   you do not want the old versions of these files then INSTEAD of
	   running the script above you can simply:

		rm /usr/src/bin/df.c
		rm /usr/src/etc/ping.c
		rm /usr/src/man/man8/ping.8

	4) Install the new files on the system:

		sh shar.283

	5) Apply the remaining patches:

		patch -p0 < 284
		patch -p0 < 285
		patch -p0 < 286

	6) Recompile the C library.  While possible to recompile and
	   install only the new modules it is probably a better idea to
	   spend the extra hour to simply recompile libc.a from scratch.

		cd /usr/src/lib/libc
		make clean
		make
		make install
		make clean

	7) Next create the new man pages:

		cd /usr/src/man/man1
		/usr/man/manroff mt.1 > mt.0
		install -m 444 mt.0 /usr/man/cat1

		cd /usr/src/man/man2
		/usr/man/manroff statfs.2 > statfs.0
		/usr/man/manroff getfsstat.2 > getfsstat.0
		install -m 444 statfs.0 getfsstat.0 /usr/man/cat2
		ln /usr/man/cat2/statfs.0 /usr/man/cat2/fstatfs.0

		cd /usr/src/man/man3
		/usr/man/manroff getmntinfo.3 > getmntinfo.0
		install -m 444 getmntinfo.0 /usr/man/cat3

	Optionally (it can be done anytime) rebuilt the 'whatis' database:

		/usr/lib/makewhatis

	8) We then rebuild the updated 'mount' program:

		cd /usr/src/etc
		make mount
		install -m 755 -s mount /etc

	9) Then reconfigure and rebuild the kernel.

	   NOTE:  The growth of the TMSCP driver and the addition of
		  new system calls will almost certainly require the
		  overlay structure to be modified.

	   The kernel Makefiles (Make.sys, etc) have changed.  You will either
	   have to copy the new conf/Make.* files into each kernel build
	   directory OR delete your existing build directories and run
	   'config'.  The GENERIC kernel will be used as an example below:

		cd /sys
		rm -r GENERIC
		cd conf
		./config GENERIC
		cd ../GENERIC
		make

	    then if no errors were encountered (and there should be none)
	    move the new generic kernel to /genunix:

		mv unix /genunix

	    To update a kernel other than GENERIC, for example PICKLE:

		cd /sys
		rm -r PICKLE
		cd conf
		./config PICKLE
		cd ../PICKLE
		make
	   
	   If errors about "too big for 0431" are seen then edit the 'Makefile'
	   to adjust the overlay layout and type "make".

		make install

	10)  After the new kernel is installed you should reboot the system

		fastboot

	    or, if  you'd prefer to have the system perform the filesystem
	    checks:

		reboot

	11) Now that the new kernel (which understands the new system calls)
	    is running it is time to compile and install the new 'df'
	    program:

		cd /usr/src/bin
		make df
		install -m 2755 -g operator -s df /bin/df

	    Try running 'df' now and see how much faster it is than before.

	12)  Two last programs to install and then you're all done:

		cd /usr/src/etc/ping
		make
		make install
		make clean

		cd /usr/src/bin
		make mt
		install -m 755 -s mt /bin/mt

	You're done.

	Enjoy!

	As always the 2.11BSD updates are available via anonymous FTP to
	the system "FTP.IIPO.GTEGSC.COM" in the directory /pub/2.11BSD.

------------------------------cut here----------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	/tmp/move.283
#	/tmp/shar.283
# This archive created: Wed Dec 27 15:01:07 1995
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f '/tmp/move.283'
then
	echo shar: "will not over-write existing file '/tmp/move.283'"
else
sed 's/^Y//' << \SHAR_EOF > '/tmp/move.283'
Ymv /usr/src/bin/df.c /usr/src/bin/df.c.old
Ymv /usr/src/etc/ping.c /usr/src/etc/ping.c.old
Ymv /usr/src/man/man8/ping.8 /usr/src/man/man8/ping.8.old
SHAR_EOF
chmod 751 '/tmp/move.283'
fi
if test -f '/tmp/shar.283'
then
	echo shar: "will not over-write existing file '/tmp/shar.283'"
else
sed 's/^Y//' << \SHAR_EOF > '/tmp/shar.283'
Y#! /bin/sh
Y# This is a shell archive, meaning:
Y# 1. Remove everything above the #! /bin/sh line.
Y# 2. Save the resulting text in a file.
Y# 3. Execute the file with /bin/sh (not csh) to create:
Y#	/usr/include/stdlib.h
Y#	/usr/src/bin/df.c
Y#	/usr/src/etc/ping
Y#	/usr/src/lib/libc/gen/getmntinfo.c
Y#	/usr/src/man/man2/getfsstat.2
Y#	/usr/src/man/man2/statfs.2
Y#	/usr/src/man/man3/getmntinfo.3
Y#	/usr/src/sys/h/stddef.h
Y#	/usr/src/sys/pdp/mscp_common.h
Y#	/usr/src/sys/pdpuba/tmscpdump.c
Y#	/usr/src/sys/sys/ufs_syscalls2.c
Y# This archive created: Wed Dec 27 11:10:34 1995
Yexport PATH; PATH=/bin:/usr/bin:$PATH
Yif test -f '/usr/include/stdlib.h'
Ythen
Y	echo shar: "will not over-write existing file '/usr/include/stdlib.h'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/include/stdlib.h'
YX/*-
YX * Copyright (c) 1990, 1993
YX *	The Regents of the University of California.  All rights reserved.
YX *
YX * Redistribution and use in source and binary forms, with or without
YX * modification, are permitted provided that the following conditions
YX * are met:
YX * 1. Redistributions of source code must retain the above copyright
YX *    notice, this list of conditions and the following disclaimer.
YX * 2. Redistributions in binary form must reproduce the above copyright
YX *    notice, this list of conditions and the following disclaimer in the
YX *    documentation and/or other materials provided with the distribution.
YX * 3. All advertising materials mentioning features or use of this software
YX *    must display the following acknowledgement:
YX *	This product includes software developed by the University of
YX *	California, Berkeley and its contributors.
YX * 4. Neither the name of the University nor the names of its contributors
YX *    may be used to endorse or promote products derived from this software
YX *    without specific prior written permission.
YX *
YX * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX * SUCH DAMAGE.
YX *
YX *	@(#)stdlib.h	8.3.1 (2.11BSD) 12995/12/26
YX *
YX * Adapted from the 4.4-Lite CD.  The odds of a ANSI C compiler for 2.11BSD
YX * being slipped under the door are not distinguishable from 0 - so the 
YX * prototypes and ANSI ifdefs have been removed from this file. 
YX *
YX * Some functions (strtoul for example) do not exist yet but are retained in
YX * this file because additions to libc.a are anticipated shortly.
YX */
YX
YX#ifndef _STDLIB_H_
YX#define _STDLIB_H_
YX
YX/* #include <machine/ansi.h> */
YX
YX#ifdef	notyet
YXtypedef struct {
YX	int quot;		/* quotient */
YX	int rem;		/* remainder */
YX} div_t;
YX
YXtypedef struct {
YX	long quot;		/* quotient */
YX	long rem;		/* remainder */
YX} ldiv_t;
YX#endif
YX
YX#ifndef NULL
YX#define	NULL	0
YX#endif
YX
YX#define	EXIT_FAILURE	1
YX#define	EXIT_SUCCESS	0
YX
YX#define	RAND_MAX	0x7fff
YX
YXvoid	abort();
YXint	abs();
YXint	atexit();
YXdouble	atof();
YXint	atoi();
YXlong	atol();
YXvoid	*calloc();
YXvoid	exit();
YXvoid	free();
YXchar	*getenv();
YXvoid	*malloc();
YXvoid	qsort();
YXint	rand();
YXvoid	*realloc();
YXvoid	srand();
YXdouble	strtod();
YXlong	strtol();
YXunsigned long strtoul();
YXint	system();
YX
YXint	putenv();
YXint	setenv();
YX
YXvoid	*alloca();
YX
YXint	daemon();
YXchar	*devname();
YXint	getloadavg();
YX
YXextern char *optarg;			/* getopt(3) external variables */
YXextern int opterr, optind, optopt;
YXint	getopt();
YX
YX#ifdef	notyet
YXextern char *suboptarg;			/* getsubopt(3) external variable */
YXint	getsubopt();
YX#endif
YX
YXlong	random();
YXchar	*setstate();
YXvoid	srandom();
YXvoid	unsetenv();
YX
YX#endif /* _STDLIB_H_ */
YSHAR_EOF
Ychmod 444 '/usr/include/stdlib.h'
Yfi
Yif test -f '/usr/src/bin/df.c'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/bin/df.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/bin/df.c'
YX/*
YX * Copyright (c) 1980, 1990, 1993, 1994
YX *	The Regents of the University of California.  All rights reserved.
YX * (c) UNIX System Laboratories, Inc.
YX * All or some portions of this file are derived from material licensed
YX * to the University of California by American Telephone and Telegraph
YX * Co. or Unix System Laboratories, Inc. and are reproduced herein with
YX * the permission of UNIX System Laboratories, Inc.
YX *
YX * Redistribution and use in source and binary forms, with or without
YX * modification, are permitted provided that the following conditions
YX * are met:
YX * 1. Redistributions of source code must retain the above copyright
YX *    notice, this list of conditions and the following disclaimer.
YX * 2. Redistributions in binary form must reproduce the above copyright
YX *    notice, this list of conditions and the following disclaimer in the
YX *    documentation and/or other materials provided with the distribution.
YX * 3. All advertising materials mentioning features or use of this software
YX *    must display the following acknowledgement:
YX *	This product includes software developed by the University of
YX *	California, Berkeley and its contributors.
YX * 4. Neither the name of the University nor the names of its contributors
YX *    may be used to endorse or promote products derived from this software
YX *    without specific prior written permission.
YX *
YX * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX * SUCH DAMAGE.
YX */
YX
YX#if	!defined(lint) && defined(DOSCCS)
YXstatic char copyright[] =
YX"@(#) Copyright (c) 1980, 1990, 1993, 1994\n\
YX	The Regents of the University of California.  All rights reserved.\n";
YX
YXstatic char sccsid[] = "@(#)df.c	8.7.1 (2.11BSD) 1995/12/26";
YX#endif
YX
YX#include <sys/param.h>
YX#include <sys/stat.h>
YX#include <sys/mount.h>
YX#include <sys/file.h>
YX
YX#include <errno.h>
YX#include <fcntl.h>
YX#include <stdio.h>
YX#include <stdlib.h>
YX#include <string.h>
YX
YXint	 bread();
YXchar	*getmntpt();
YXvoid	 prtstat();
YXvoid	 ufs_df();
YXvoid	 usage();
YX
YXint	iflag;
YX
YXint
YXmain(argc, argv)
YX	int argc;
YX	register char *argv[];
YX{
YX	struct stat stbuf;
YX	struct statfs statfsbuf, *mntbuf;
YX	int mntsize;
YX	int ch, err, i, maxwidth, width;
YX	char *mntpt;
YX
YX	while ((ch = getopt(argc, argv, "i")) != EOF)
YX		switch (ch) {
YX		case 'i':
YX			iflag = 1;
YX			break;
YX		case '?':
YX		default:
YX			usage();
YX		}
YX	argc -= optind;
YX	argv += optind;
YX
YX	mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
YX	maxwidth = 0;
YX	for (i = 0; i < mntsize; i++) {
YX		width = strlen(mntbuf[i].f_mntfromname);
YX		if (width > maxwidth)
YX			maxwidth = width;
YX	}
YX
YX	if (!*argv) {
YX		for (i = 0; i < mntsize; i++)
YX			prtstat(&mntbuf[i], maxwidth);
YX		exit(0);
YX	}
YX
YX	for (; *argv; argv++) {
YX		if (stat(*argv, &stbuf) < 0) {
YX			err = errno;
YX			if ((mntpt = getmntpt(*argv)) == 0) {
YX				warn("%s", *argv);
YX				continue;
YX			}
YX		} else if ((stbuf.st_mode & S_IFMT) == S_IFCHR) {
YX			ufs_df(*argv, maxwidth);
YX			continue;
YX		} else if ((stbuf.st_mode & S_IFMT) == S_IFBLK) {
YX			if ((mntpt = getmntpt(*argv)) == 0) {
YX				ufs_df(*argv, maxwidth);
YX				continue;
YX			}
YX		} else
YX			mntpt = *argv;
YX		/*
YX		 * Statfs does not take a `wait' flag, so we cannot
YX		 * implement nflag here.
YX		 */
YX		if (statfs(mntpt, &statfsbuf) < 0) {
YX			warn("%s", mntpt);
YX			continue;
YX		}
YX		if (argc == 1)
YX			maxwidth = strlen(statfsbuf.f_mntfromname) + 1;
YX		prtstat(&statfsbuf, maxwidth);
YX	}
YX	return (0);
YX}
YX
YXchar *
YXgetmntpt(name)
YX	char *name;
YX{
YX	register int i;
YX	int mntsize;
YX	struct statfs *mntbuf;
YX
YX	mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
YX	for (i = 0; i < mntsize; i++) {
YX		if (!strcmp(mntbuf[i].f_mntfromname, name))
YX			return (mntbuf[i].f_mntonname);
YX	}
YX	return (0);
YX}
YX
YX/*
YX * Convert statfs returned filesystem size into BLOCKSIZE units.
YX * Attempts to avoid overflow for large filesystems.
YX */
YXlong
YXfsbtoblk(num, fsbs, bs)
YX	long	num;
YX	register int	fsbs, bs;
YX	{
YX	return((fsbs != 0 && fsbs < bs) ?
YX		num / (bs / fsbs) : (num) * (fsbs / bs));
YX	}
YX
YX/*
YX * Print out status about a filesystem.
YX */
YXvoid
YXprtstat(sfsp, maxwidth)
YX	register struct statfs *sfsp;
YX	register int maxwidth;
YX{
YX	static int blocksize;
YX	static int headerlen, timesthrough;
YX	static char *header;
YX	long used, availblks;
YX	ino_t	inodes, iused;
YX
YX	if (maxwidth < 11)
YX		maxwidth = 11;
YX	if (++timesthrough == 1) {
YX/*		header = getbsize(&headerlen, &blocksize); */
YX		header = "1K-blocks";
YX		blocksize = 1024;
YX		headerlen = 9;
YX
YX		(void)printf("%-*.*s %s     Used    Avail Capacity",
YX		    maxwidth, maxwidth, "Filesystem", header);
YX		if (iflag)
YX			(void)printf(" iused   ifree  %%iused");
YX		(void)printf("  Mounted on\n");
YX	}
YX	(void)printf("%-*.*s", maxwidth, maxwidth, sfsp->f_mntfromname);
YX	used = sfsp->f_blocks - sfsp->f_bfree;
YX	availblks = sfsp->f_bavail + used;
YX	(void)printf(" %*ld %8ld %8ld", headerlen,
YX	    fsbtoblk(sfsp->f_blocks, sfsp->f_bsize, blocksize),
YX	    fsbtoblk(used, sfsp->f_bsize, blocksize),
YX	    fsbtoblk(sfsp->f_bavail, sfsp->f_bsize, blocksize));
YX	(void)printf(" %5.0f%%",
YX	    availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0);
YX	if (iflag) {
YX		inodes = sfsp->f_files;
YX		iused = inodes - sfsp->f_ffree;
YX		(void)printf(" %7u %7u %5.0f%% ", iused, sfsp->f_ffree,
YX		   inodes == 0 ? 100.0 : (double)iused / (double)inodes * 100.0);
YX	} else 
YX		(void)printf("  ");
YX	(void)printf("  %s\n", sfsp->f_mntonname);
YX}
YX
YX/*
YX * This code constitutes the pre-system call Berkeley df code for extracting
YX * information from filesystem superblocks.
YX */
YX#include <sys/fs.h>
YX#include <fstab.h>
YX
YXunion {
YX	struct fs fs;
YX	char dummy[SBSIZE];
YX} sb;
YX#define sblock sb.fs
YX
YXint	rfd;
YX
YXvoid
YXufs_df(file, maxwidth)
YX	char *file;
YX	int maxwidth;
YX{
YX	struct statfs statfsbuf;
YX	register struct statfs *sfsp;
YX	register char *mntpt;
YX	static int synced;
YX
YX	if (synced++ == 0)
YX		sync();
YX
YX	if ((rfd = open(file, O_RDONLY)) < 0) {
YX		warn("%s", file);
YX		return;
YX	}
YX	if (bread((off_t)SBLOCK * DEV_BSIZE, &sblock, SBSIZE) == 0) {
YX		(void)close(rfd);
YX		return;
YX	}
YX	sfsp = &statfsbuf;
YX	sfsp->f_type = MOUNT_UFS;
YX	sfsp->f_flags = 0;
YX	sfsp->f_bsize = MAXBSIZE;
YX	sfsp->f_iosize = MAXBSIZE;
YX	sfsp->f_blocks = sblock.fs_fsize;
YX	sfsp->f_bfree = sblock.fs_tfree;
YX	sfsp->f_bavail = sblock.fs_tfree;
YX	if (sfsp->f_bavail < 0)
YX		sfsp->f_bavail = 0;
YX	sfsp->f_files =  (sblock.fs_isize - 2) * INOPB;
YX	sfsp->f_ffree = sblock.fs_tinode;
YX	sfsp->f_fsid[0] = 0;
YX	sfsp->f_fsid[1] = 0;
YX	if ((mntpt = getmntpt(file)) == 0)
YX		mntpt = "";
YX	bcopy(mntpt, &sfsp->f_mntonname[0], MNAMELEN);
YX	bcopy(file, &sfsp->f_mntfromname[0], MNAMELEN);
YX	prtstat(sfsp, maxwidth);
YX	(void)close(rfd);
YX}
YX
YXint
YXbread(off, buf, cnt)
YX	off_t off;
YX	void *buf;
YX	register int cnt;
YX{
YX	register int nr;
YX
YX	(void)lseek(rfd, off, L_SET);
YX	if ((nr = read(rfd, buf, cnt)) != cnt) {
YX		/* Probably a dismounted disk if errno == EIO. */
YX		if (errno != EIO)
YX			(void)fprintf(stderr, "\ndf: %ld: %s\n",
YX			    off, strerror(nr > 0 ? EIO : errno));
YX		return (0);
YX	}
YX	return (1);
YX}
YX
YXvoid
YXusage()
YX{
YX	(void)fprintf(stderr, "usage: df [-i] [file | file_system ...]\n");
YX	exit(1);
YX}
YSHAR_EOF
Ychmod 644 '/usr/src/bin/df.c'
Yfi
Yif test ! -d '/usr/src/etc/ping'
Ythen
Y	mkdir '/usr/src/etc/ping'
Yfi
Ycd '/usr/src/etc/ping'
Yif test -f 'Makefile'
Ythen
Y	echo shar: "will not over-write existing file 'Makefile'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > 'Makefile'
YX#
YX#	@(#)Makefile	1.0 (2.11BSD) 1995/12/22
YX#
YX
YXCFLAGS=	-O
YXSEPFLAG= -i
YXLIBC=	/lib/libc.a
YXSRCS=	ping.c
YXOBJS=	ping.o
YXMAN=	ping.0
YXMANSRC=	ping.8
YX
YXall: ping ${MAN}
YX
YXping: ${LIBC}
YX	${CC} ${SEPFLAG} -o $@ ${CFLAGS} $@.c
YX
YXping.0: ${MANSRC}
YX	/usr/man/manroff ${MANSRC} > ${MAN}
YX
YXclean:
YX	rm -f ${OBJS} ${MAN} ping
YX
YXcleandir: clean
YX	rm -f tags .depend
YX
YXdepend: ${SRCS}
YX	mkdep -p ${CFLAGS} ${SRCS}
YX
YXinstall: ${MAN} ping
YX	install -s -o root -g bin -m 4751 ping ${DESTDIR}/etc
YX	install -c -o bin -g bin -m 444 ${MAN} ${DESTDIR}/usr/man/cat8
YX
YXlint: ${SRCS}
YX	lint -haxc ${SRCS}
YX
YXtags: ${SRCS}
YX	ctags ${SRCS}
YSHAR_EOF
Ychmod 644 'Makefile'
Yfi
Yif test -f 'ping.8'
Ythen
Y	echo shar: "will not over-write existing file 'ping.8'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > 'ping.8'
YX.\" Copyright (c) 1985, 1991, 1993
YX.\"	The Regents of the University of California.  All rights reserved.
YX.\"
YX.\" Redistribution and use in source and binary forms, with or without
YX.\" modification, are permitted provided that the following conditions
YX.\" are met:
YX.\" 1. Redistributions of source code must retain the above copyright
YX.\"    notice, this list of conditions and the following disclaimer.
YX.\" 2. Redistributions in binary form must reproduce the above copyright
YX.\"    notice, this list of conditions and the following disclaimer in the
YX.\"    documentation and/or other materials provided with the distribution.
YX.\" 3. All advertising materials mentioning features or use of this software
YX.\"    must display the following acknowledgement:
YX.\"	This product includes software developed by the University of
YX.\"	California, Berkeley and its contributors.
YX.\" 4. Neither the name of the University nor the names of its contributors
YX.\"    may be used to endorse or promote products derived from this software
YX.\"    without specific prior written permission.
YX.\"
YX.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX.\" SUCH DAMAGE.
YX.\"
YX.\"     @(#)ping.8	8.2.1 (2.11BSD) 1995/12/22
YX.\"
YX.TH PING 8 "December 22, 1995"
YX.AT 3
YX.SH NAME
YX\fBping\fP \- send ICMP ECHO_REQUEST packets to network hosts
YX.SH SYNOPSIS
YX.B ping [-dfnqrvR]
YX[\fB-c\fP \fIcount\fP]
YX[\fB-i\fP \fIwait\fP]
YX[\fB-l\fP \fIpreload\fP]
YX[\fB-p\fP \fIpattern\fP]
YX[\fB-s\fP \fIpacketsize\fP]
YX.SH DESCRIPTION
YX.B Ping
YXuses the
YXICMP
YXprotocol's mandatory
YXECHO_REQUEST
YXdatagram to elicit an
YXICMP ECHO_RESPONSE
YXfrom a host or gateway.
YXECHO_REQUEST
YXdatagrams (``pings'') have an IP and
YXICMP
YXheader,
YXfollowed by a
YX``struct timeval''
YXand then an arbitrary number of ``pad'' bytes used to fill out the
YXpacket.
YXThe options are as follows:
YX.TP 15
YX\fB-c\fP \fIcount\fP
YXStop after sending (and receiving)
YX.I count
YXECHO_RESPONSE
YXpackets.
YX.TP 15
YX\fB-d\fP
YXSet the
YXSO_DEBUG
YXoption on the socket being used.
YX.TP 15
YX\fB-f\fP
YXFlood ping.
YXOutputs packets as fast as they come back or one hundred times per second,
YXwhichever is more.
YXFor every
YXECHO_REQUEST
YXsent a period ``.'' is printed, while for every
YXECHO_REPLY
YXreceived a backspace is printed.
YXThis provides a rapid display of how many packets are being dropped.
YXOnly the super-user may use this option.
YX.B This can be very hard on a network and should be used with caution.
YX.TP 15
YX\fB-i\fP \fIwait\fP
YXWait
YX.I wait
YXseconds
YXbetween sending each packet.
YXThe default is to wait for one second between each packet.
YXThis option is incompatible with the
YX\fB-f\fP
YXoption.
YX.TP 15
YX\fB-l\fP \fIpreload\fP
YXIf
YX.I preload
YXis specified,
YX.B ping
YXsends that many packets as fast as possible before falling into its normal
YXmode of behavior.
YX.TP 15
YX\fB-n\fP
YXNumeric output only.
YXNo attempt will be made to lookup symbolic names for host addresses.
YX.TP 15
YX\fB-p\fP \fIpattern\fP
YXYou may specify up to 16 ``pad'' bytes to fill out the packet you send.
YXThis is useful for diagnosing data-dependent problems in a network.
YXFor example,
YX`` \-p ff''
YXwill cause the sent packet to be filled with all
YXones.
YX.TP 15
YX\fB-q\fP
YXQuiet output.
YXNothing is displayed except the summary lines at startup time and
YXwhen finished.
YX.TP 15
YX\fB-R\fP
YXRecord route.
YXIncludes the
YXRECORD_ROUTE
YXoption in the
YXECHO_REQUEST
YXpacket and displays
YXthe route buffer on returned packets.
YXNote that the IP header is only large enough for nine such routes.
YXMany hosts ignore or discard this option.
YX.TP 15
YX\fB-r\fP
YXBypass the normal routing tables and send directly to a host on an attached
YXnetwork.
YXIf the host is not on a directly-attached network, an error is returned.
YXThis option can be used to ping a local host through an interface
YXthat has no route through it (e.g., after the interface was dropped by
YX.BR routed (8).
YX.TP 15
YX\fB-s\fP \fIpacketsize\fP
YXSpecifies the number of data bytes to be sent.  
YXThe default is 56, which translates into 64
YXICMP
YXdata bytes when combined
YXwith the 8 bytes of
YXICMP
YXheader data.
YX.TP 15
YX\fB-v\fP
YXVerbose output.
YXICMP
YXpackets other than
YXECHO_RESPONSE
YXthat are received are listed.
YX.PP
YXWhen using
YX.B ping
YXfor fault isolation, it should first be run on the local host, to verify
YXthat the local network interface is up and running.
YXThen, hosts and gateways further and further away should be ``pinged''.
YXRound-trip times and packet loss statistics are computed.
YXIf duplicate packets are received, they are not included in the packet
YXloss calculation, although the round trip time of these packets is used
YXin calculating the minimum/average/maximum round-trip time numbers.
YXWhen the specified number of packets have been sent (and received) or
YXif the program is terminated with a
YXSIGINT,
YXa brief summary is displayed.
YX.PP
YXThis program is intended for use in network testing, measurement and
YXmanagement.
YXBecause of the load it can impose on the network, it is unwise to use
YX.B ping
YXduring normal operations or from automated scripts.
YX.SH ICMP PACKET DETAILS
YXAn IP header without options is 20 bytes.
YXAn
YXICMP
YXECHO_REQUEST
YXpacket contains an additional 8 bytes worth
YXof
YXICMP
YXheader followed by an arbitrary amount of data.
YXWhen a
YX.I packetsize
YXis given, this indicated the size of this extra piece of data (the
YXdefault is 56).
YXThus the amount of data received inside of an IP packet of type
YXICMP
YXECHO_REPLY
YXwill always be 8 bytes more than the requested data space
YX(the
YXICMP
YXheader).
YX.PP
YXIf the data space is at least eight bytes large,
YX.B ping
YXuses the first eight bytes of this space to include a timestamp which
YXit uses in the computation of round trip times.
YXIf less than eight bytes of pad are specified, no round trip times are
YXgiven.
YX.SH DUPLICATE AND DAMAGED PACKETS
YX.B Ping
YXwill report duplicate and damaged packets.
YXDuplicate packets should never occur, and seem to be caused by
YXinappropriate link-level retransmissions.
YXDuplicates may occur in many situations and are rarely (if ever) a
YXgood sign, although the presence of low levels of duplicates may not
YXalways be cause for alarm.
YX.PP
YXDamaged packets are obviously serious cause for alarm and often
YXindicate broken hardware somewhere in the
YX.B ping
YXpacket's path (in the network or in the hosts).
YX.SH TRYING DIFFERENT DATA PATTERNS
YXThe (inter)network layer should never treat packets differently depending
YXon the data contained in the data portion.
YXUnfortunately, data-dependent problems have been known to sneak into
YXnetworks and remain undetected for long periods of time.
YXIn many cases the particular pattern that will have problems is something
YXthat doesn't have sufficient ``transitions'', such as all ones or all
YXzeros, or a pattern right at the edge, such as almost all zeros.
YXIt isn't necessarily enough to specify a data pattern of all zeros (for
YXexample) on the command line because the pattern that is of interest is
YXat the data link level, and the relationship between what you type and
YXwhat the controllers transmit can be complicated.
YX.PP
YXThis means that if you have a data-dependent problem you will probably
YXhave to do a lot of testing to find it.
YXIf you are lucky, you may manage to find a file that either can't be sent
YXacross your network or that takes much longer to transfer than other
YXsimilar length files.
YXYou can then examine this file for repeated patterns that you can test
YXusing the
YX\fB-p\fP
YXoption of
YX.BR ping .
YX.SH TTL DETAILS
YXThe
YXTTL
YXvalue of an IP packet represents the maximum number of IP routers
YXthat the packet can go through before being thrown away.
YXIn current practice you can expect each router in the Internet to decrement
YXthe
YXTTL
YXfield by exactly one.
YX.PP
YXThe
YXTCP/IP
YXspecification states that the
YXTTL
YXfield for
YXTCP
YXpackets should
YXbe set to 60, but many systems use smaller values (4.3BSD
YXuses 30, 4.2 used
YX15).
YX.PP
YXThe maximum possible value of this field is 255, and most Unix systems set
YXthe
YXTTL
YXfield of
YXICMP ECHO_REQUEST
YXpackets to 255.
YXThis is why you will find you can ``ping'' some hosts, but not reach them
YXwith
YX.BR telnet (1)
YXor
YX.BR ftp (1) .
YX.PP
YXIn normal operation ping prints the ttl value from the packet it receives.
YXWhen a remote system receives a ping packet, it can do one of three things
YXwith the
YXTTL
YXfield in its response:
YX.TP 5
YX\(bu
YXNot change it; this is what Berkeley Unix systems did before the
YX4.3BSD-tahoe
YXrelease.
YXIn this case the
YXTTL
YXvalue in the received packet will be 255 minus the
YXnumber of routers in the round-trip path.
YX.TP 5
YX\(bu
YXSet it to 255; this is what current Berkeley Unix systems do.
YXIn this case the
YXTTL
YXvalue in the received packet will be 255 minus the
YXnumber of routers in the path
YX.B from
YXthe remote system
YX.I to
YXthe
YX\fBping\fP'ing
YXhost.
YX.TP 5
YX\(bu
YXSet it to some other value.
YXSome machines use the same value for
YXICMP
YXpackets that they use for
YXTCP
YXpackets, for example either 30 or 60.
YXOthers may use completely wild values.
YX.SH BUGS
YXMany Hosts and Gateways ignore the
YXRECORD_ROUTE
YXoption.
YX.PP
YXThe maximum IP header length is too small for options like
YXRECORD_ROUTE
YXto
YXbe completely useful.
YXThere's not much that that can be done about this, however.
YX.PP
YXFlood pinging is not recommended in general, and flood pinging the
YXbroadcast address should only be done under very controlled conditions.
YX.SH SEE ALSO
YX.BR netstat (1),
YX.BR ifconfig (8),
YX.BR routed (8)
YX.SH HISTORY
YXThe
YX.B ping
YXcommand appeared in
YX4.3BSD.
YSHAR_EOF
Ychmod 644 'ping.8'
Yfi
Yif test -f 'ping.c'
Ythen
Y	echo shar: "will not over-write existing file 'ping.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > 'ping.c'
YX/*	BSDI	ping.c,v 2.1 1995/02/03 07:30:55 polk Exp	*/
YX
YX/*
YX * Copyright (c) 1989, 1993
YX *	The Regents of the University of California.  All rights reserved.
YX *
YX * This code is derived from software contributed to Berkeley by
YX * Mike Muuss.
YX *
YX * Redistribution and use in source and binary forms, with or without
YX * modification, are permitted provided that the following conditions
YX * are met:
YX * 1. Redistributions of source code must retain the above copyright
YX *    notice, this list of conditions and the following disclaimer.
YX * 2. Redistributions in binary form must reproduce the above copyright
YX *    notice, this list of conditions and the following disclaimer in the
YX *    documentation and/or other materials provided with the distribution.
YX * 3. All advertising materials mentioning features or use of this software
YX *    must display the following acknowledgement:
YX *	This product includes software developed by the University of
YX *	California, Berkeley and its contributors.
YX * 4. Neither the name of the University nor the names of its contributors
YX *    may be used to endorse or promote products derived from this software
YX *    without specific prior written permission.
YX *
YX * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX * SUCH DAMAGE.
YX */
YX
YX#if	!defined(lint) && defined(DOSCCS)
YXstatic char copyright[] =
YX"@(#) Copyright (c) 1989, 1993\n\
YX	The Regents of the University of California.  All rights reserved.\n";
YX
YXstatic char sccsid[] = "@(#)ping.c	8.1 (Berkeley) 6/5/93";
YX#endif /* not lint */
YX
YX/*
YX *			P I N G . C
YX *
YX * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
YX * measure round-trip-delays and packet loss across network paths.
YX *
YX * Author -
YX *	Mike Muuss
YX *	U. S. Army Ballistic Research Laboratory
YX *	December, 1983
YX *
YX * Status -
YX *	Public Domain.  Distribution Unlimited.
YX * Bugs -
YX *	More statistics could always be gathered.
YX *	This program has to run SUID to ROOT to access the ICMP socket.
YX */
YX
YX#include <sys/param.h>
YX#include <sys/socket.h>
YX#include <sys/file.h>
YX#include <sys/time.h>
YX#include <sys/signal.h>
YX
YX#include <netinet/in_systm.h>
YX#include <netinet/in.h>
YX#include <netinet/ip.h>
YX#include <netinet/ip_icmp.h>
YX#include <netinet/ip_var.h>
YX#include <netdb.h>
YX#include <stdio.h>
YX#include <ctype.h>
YX#include <errno.h>
YX#include <string.h>
YX
YX#define	DEFDATALEN	(64 - 8)	/* default data length */
YX#define	MAXIPLEN	60
YX#define	MAXICMPLEN	76
YX#define	MAXPACKET	(4096 - 60 - 8)	/* max packet size */
YX#define	MAXWAIT		10		/* max seconds to wait for response */
YX#define	NROUTES		9		/* number of record route slots */
YX
YX#define	A(bit)		rcvd_tbl[(bit)>>3]	/* identify byte in array */
YX#define	B(bit)		(1 << ((bit) & 0x07))	/* identify bit in byte */
YX#define	SET(bit)	(A(bit) |= B(bit))
YX#define	CLR(bit)	(A(bit) &= (~B(bit)))
YX#define	TST(bit)	(A(bit) & B(bit))
YX
YX/* various options */
YXint options;
YX#define	F_FLOOD		0x001
YX#define	F_INTERVAL	0x002
YX#define	F_NUMERIC	0x004
YX#define	F_PINGFILLED	0x008
YX#define	F_QUIET		0x010
YX#define	F_RROUTE	0x020
YX#define	F_SO_DEBUG	0x040
YX#define	F_SO_DONTROUTE	0x080
YX#define	F_VERBOSE	0x100
YX
YX/*
YX * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
YX * number of received sequence numbers we can keep track of.  Change 512
YX * to 8192 for complete accuracy...
YX */
YX#define	MAX_DUP_CHK	(8 * 512)
YXint mx_dup_ck = MAX_DUP_CHK;
YXchar rcvd_tbl[MAX_DUP_CHK / 8];
YX
YXstruct sockaddr whereto;	/* who to ping */
YXint datalen = DEFDATALEN;
YXint s;				/* socket file descriptor */
YXu_char outpack[MAXPACKET];
YXchar BSPACE = '\b';		/* characters written for flood */
YXchar DOT = '.';
YXchar *hostname;
YXint ident;			/* process id to identify our packets */
YX
YX/* counters */
YXlong npackets;			/* max packets to transmit */
YXlong nreceived;			/* # of packets we got back */
YXlong nrepeats;			/* number of duplicates */
YXlong ntransmitted;		/* sequence # for outbound packets = #sent */
YXint interval = 1;		/* interval between packets */
YX
YX/* timing */
YXint timing;			/* flag to do timing */
YXdouble tmin = 999999999.0;	/* minimum round trip time */
YXdouble tmax = 0.0;		/* maximum round trip time */
YXdouble tsum = 0.0;		/* sum of all times, for doing average */
YX
YXchar *pr_addr();
YXvoid catcher(), finish();
YX
YXmain(argc, argv)
YX	int argc;
YX	char **argv;
YX{
YX	extern int errno, optind;
YX	extern char *optarg;
YX	struct timeval timeout;
YX	struct hostent *hp;
YX	struct sockaddr_in *to;
YX	struct protoent *proto;
YX	register int i;
YX	int ch, fdmask, hold, packlen, preload;
YX	u_char *datap, *packet;
YX	char *target, hnamebuf[MAXHOSTNAMELEN], *malloc();
YX#ifdef IP_OPTIONS
YX	char rspace[3 + 4 * NROUTES + 1];	/* record route space */
YX#endif
YX
YX	preload = 0;
YX	datap = &outpack[8 + sizeof(struct timeval)];
YX	while ((ch = getopt(argc, argv, "Rc:dfh:i:l:np:qrs:v")) != EOF)
YX		switch(ch) {
YX		case 'c':
YX			npackets = atoi(optarg);
YX			if (npackets <= 0) {
YX				(void)fprintf(stderr,
YX				    "ping: bad number of packets to transmit.\n");
YX				exit(1);
YX			}
YX			break;
YX		case 'd':
YX			options |= F_SO_DEBUG;
YX			break;
YX		case 'f':
YX			if (getuid()) {
YX				(void)fprintf(stderr,
YX				    "ping: %s\n", strerror(EPERM));
YX				exit(1);
YX			}
YX			options |= F_FLOOD;
YX			setbuf(stdout, (char *)NULL);
YX			break;
YX		case 'i':		/* wait between sending packets */
YX			interval = atoi(optarg);
YX			if (interval <= 0) {
YX				(void)fprintf(stderr,
YX				    "ping: bad timing interval.\n");
YX				exit(1);
YX			}
YX			options |= F_INTERVAL;
YX			break;
YX		case 'l':
YX			preload = atoi(optarg);
YX			if (preload < 0) {
YX				(void)fprintf(stderr,
YX				    "ping: bad preload value.\n");
YX				exit(1);
YX			}
YX			break;
YX		case 'n':
YX			options |= F_NUMERIC;
YX			break;
YX		case 'p':		/* fill buffer with user pattern */
YX			options |= F_PINGFILLED;
YX			fill((char *)datap, optarg);
YX				break;
YX		case 'q':
YX			options |= F_QUIET;
YX			break;
YX		case 'R':
YX			options |= F_RROUTE;
YX			break;
YX		case 'r':
YX			options |= F_SO_DONTROUTE;
YX			break;
YX		case 's':		/* size of packet to send */
YX			datalen = atoi(optarg);
YX			if (datalen > MAXPACKET) {
YX				(void)fprintf(stderr,
YX				    "ping: packet size too large.\n");
YX				exit(1);
YX			}
YX			if (datalen <= 0) {
YX				(void)fprintf(stderr,
YX				    "ping: illegal packet size.\n");
YX				exit(1);
YX			}
YX			break;
YX		case 'v':
YX			options |= F_VERBOSE;
YX			break;
YX		default:
YX			usage();
YX		}
YX	argc -= optind;
YX	argv += optind;
YX
YX	if (argc != 1)
YX		usage();
YX	target = *argv;
YX
YX	bzero((char *)&whereto, sizeof(struct sockaddr));
YX	to = (struct sockaddr_in *)&whereto;
YX	to->sin_family = AF_INET;
YX	to->sin_addr.s_addr = inet_addr(target);
YX	if (to->sin_addr.s_addr != -1L)
YX		hostname = target;
YX	else {
YX		hp = gethostbyname(target);
YX		if (!hp) {
YX			(void)fprintf(stderr,
YX			    "ping: unknown host %s\n", target);
YX			exit(1);
YX		}
YX		to->sin_family = hp->h_addrtype;
YX		bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length);
YX		(void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1);
YX		hostname = hnamebuf;
YX	}
YX
YX	if (options & F_FLOOD && options & F_INTERVAL) {
YX		(void)fprintf(stderr,
YX		    "ping: -f and -i incompatible options.\n");
YX		exit(1);
YX	}
YX
YX	if (datalen >= sizeof(struct timeval))	/* can we time transfer */
YX		timing = 1;
YX	packlen = datalen + MAXIPLEN + MAXICMPLEN;
YX	if (!(packet = (u_char *)malloc((u_int)packlen))) {
YX		(void)fprintf(stderr, "ping: out of memory.\n");
YX		exit(1);
YX	}
YX	if (!(options & F_PINGFILLED))
YX		for (i = 8; i < datalen; ++i)
YX			*datap++ = i;
YX
YX	ident = getpid() & 0xFFFF;
YX
YX	if (!(proto = getprotobyname("icmp"))) {
YX		(void)fprintf(stderr, "ping: unknown protocol icmp.\n");
YX		exit(1);
YX	}
YX	if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) {
YX		perror("ping: socket");
YX		exit(1);
YX	}
YX	hold = 1;
YX	if (options & F_SO_DEBUG)
YX		(void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold,
YX		    sizeof(hold));
YX	if (options & F_SO_DONTROUTE)
YX		(void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold,
YX		    sizeof(hold));
YX
YX	/* record route option */
YX	if (options & F_RROUTE) {
YX#ifdef IP_OPTIONS
YX		rspace[IPOPT_OPTVAL] = IPOPT_RR;
YX		rspace[IPOPT_OLEN] = sizeof(rspace)-1;
YX		rspace[IPOPT_OFFSET] = IPOPT_MINOFF;
YX		if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace,
YX		    sizeof(rspace)) < 0) {
YX			perror("ping: record route");
YX			exit(1);
YX		}
YX#else
YX		(void)fprintf(stderr,
YX		  "ping: record route not available in this implementation.\n");
YX		exit(1);
YX#endif /* IP_OPTIONS */
YX	}
YX
YX	/*
YX	 * When pinging the broadcast address, you can get a lot of answers.
YX	 * Doing something so evil is useful if you are trying to stress the
YX	 * ethernet, or just want to fill the arp cache to get some stuff for
YX	 * /etc/ethers.
YX	 */
YX	hold = 48 * 1024;
YX	(void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold,
YX	    sizeof(hold));
YX
YX	if (to->sin_family == AF_INET)
YX		(void)printf("PING %s (%s): %d data bytes\n", hostname,
YX		    inet_ntoa(*(struct in_addr *)&to->sin_addr.s_addr),
YX		    datalen);
YX	else
YX		(void)printf("PING %s: %d data bytes\n", hostname, datalen);
YX
YX	(void)signal(SIGINT, finish);
YX	(void)signal(SIGALRM, catcher);
YX
YX	while (preload--)		/* fire off them quickies */
YX		pinger();
YX
YX	if ((options & F_FLOOD) == 0)
YX		catcher();		/* start things going */
YX
YX	for (;;) {
YX		struct sockaddr_in from;
YX		register int cc;
YX		int fromlen;
YX
YX		if (options & F_FLOOD) {
YX			pinger();
YX			timeout.tv_sec = 0;
YX			timeout.tv_usec = 10000;
YX			fdmask = 1 << s;
YX			if (select(s + 1, (fd_set *)&fdmask, (fd_set *)NULL,
YX			    (fd_set *)NULL, &timeout) < 1)
YX				continue;
YX		}
YX		fromlen = sizeof(from);
YX		if ((cc = recvfrom(s, (char *)packet, packlen, 0,
YX		    (struct sockaddr *)&from, &fromlen)) < 0) {
YX			if (errno == EINTR)
YX				continue;
YX			perror("ping: recvfrom");
YX			continue;
YX		}
YX		pr_pack((char *)packet, cc, &from);
YX		if (npackets && nreceived >= npackets)
YX			break;
YX	}
YX	finish();
YX	/* NOTREACHED */
YX}
YX
YX/*
YX * catcher --
YX *	This routine causes another PING to be transmitted, and then
YX * schedules another SIGALRM for 1 second from now.
YX *
YX * bug --
YX *	Our sense of time will slowly skew (i.e., packets will not be
YX * launched exactly at 1-second intervals).  This does not affect the
YX * quality of the delay and loss statistics.
YX */
YXvoid
YXcatcher()
YX{
YX	int waittime;
YX
YX	pinger();
YX	(void)signal(SIGALRM, catcher);
YX	if (!npackets || ntransmitted < npackets)
YX		alarm((u_int)interval);
YX	else {
YX		if (nreceived) {
YX			waittime = 2 * tmax / 1000;
YX			if (!waittime)
YX				waittime = 1;
YX		} else
YX			waittime = MAXWAIT;
YX		(void)signal(SIGALRM, finish);
YX		(void)alarm((u_int)waittime);
YX	}
YX}
YX
YX/*
YX * pinger --
YX *	Compose and transmit an ICMP ECHO REQUEST packet.  The IP packet
YX * will be added on by the kernel.  The ID field is our UNIX process ID,
YX * and the sequence number is an ascending integer.  The first 8 bytes
YX * of the data portion are used to hold a UNIX "timeval" struct in VAX
YX * byte-order, to compute the round-trip time.
YX */
YXpinger()
YX{
YX	register struct icmp *icp;
YX	register int cc;
YX	int i;
YX
YX	icp = (struct icmp *)outpack;
YX	icp->icmp_type = ICMP_ECHO;
YX	icp->icmp_code = 0;
YX	icp->icmp_cksum = 0;
YX	icp->icmp_seq = ntransmitted++;
YX	icp->icmp_id = ident;			/* ID */
YX
YX	CLR(icp->icmp_seq % mx_dup_ck);
YX
YX	if (timing)
YX		(void)gettimeofday((struct timeval *)&outpack[8],
YX		    (struct timezone *)NULL);
YX
YX	cc = datalen + 8;			/* skips ICMP portion */
YX
YX	/* compute ICMP checksum here */
YX	icp->icmp_cksum = in_cksum((u_short *)icp, cc);
YX
YX	i = sendto(s, (char *)outpack, cc, 0, &whereto,
YX	    sizeof(struct sockaddr));
YX
YX	if (i < 0 || i != cc)  {
YX		if (i < 0)
YX			perror("ping: sendto");
YX		(void)printf("ping: wrote %s %d chars, ret=%d\n",
YX		    hostname, cc, i);
YX	}
YX	if (!(options & F_QUIET) && options & F_FLOOD)
YX		(void)write(fileno(stdout), &DOT, 1);
YX}
YX
YX/*
YX * pr_pack --
YX *	Print out the packet, if it came from us.  This logic is necessary
YX * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
YX * which arrive ('tis only fair).  This permits multiple copies of this
YX * program to be run without having intermingled output (or statistics!).
YX */
YXpr_pack(buf, cc, from)
YX	char *buf;
YX	int cc;
YX	struct sockaddr_in *from;
YX{
YX	register struct icmp *icp;
YX	register u_long l;
YX	register int i, j;
YX	register u_char *cp,*dp;
YX	static int old_rrlen;
YX	static char old_rr[MAX_IPOPTLEN];
YX	struct ip *ip;
YX	struct timeval tv, *tp;
YX	double triptime;
YX	int hlen, dupflag;
YX
YX	(void)gettimeofday(&tv, (struct timezone *)NULL);
YX
YX	/* Check the IP header */
YX	ip = (struct ip *)buf;
YX	hlen = ip->ip_hl << 2;
YX	if (cc < hlen + ICMP_MINLEN) {
YX		if (options & F_VERBOSE)
YX			(void)fprintf(stderr,
YX			  "ping: packet too short (%d bytes) from %s\n", cc,
YX			  inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr));
YX		return;
YX	}
YX
YX	/* Now the ICMP part */
YX	cc -= hlen;
YX	icp = (struct icmp *)(buf + hlen);
YX	if (icp->icmp_type == ICMP_ECHOREPLY) {
YX		if (icp->icmp_id != ident)
YX			return;			/* 'Twas not our ECHO */
YX		++nreceived;
YX		if (timing) {
YX#ifndef icmp_data
YX			tp = (struct timeval *)&icp->icmp_ip;
YX#else
YX			tp = (struct timeval *)icp->icmp_data;
YX#endif
YX			tvsub(&tv, tp);
YX			triptime = ((double)tv.tv_sec) * 1000.0 +
YX			    ((double)tv.tv_usec) / 1000.0;
YX			tsum += triptime;
YX			if (triptime < tmin)
YX				tmin = triptime;
YX			if (triptime > tmax)
YX				tmax = triptime;
YX		}
YX
YX		if (TST(icp->icmp_seq % mx_dup_ck)) {
YX			++nrepeats;
YX			--nreceived;
YX			dupflag = 1;
YX		} else {
YX			SET(icp->icmp_seq % mx_dup_ck);
YX			dupflag = 0;
YX		}
YX
YX		if (options & F_QUIET)
YX			return;
YX
YX		if (options & F_FLOOD)
YX			(void)write(fileno(stdout), &BSPACE, 1);
YX		else {
YX			(void)printf("%d bytes from %s: icmp_seq=%u", cc,
YX			   inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr),
YX			   icp->icmp_seq);
YX			(void)printf(" ttl=%d", ip->ip_ttl);
YX			if (timing)
YX				(void)printf(" time=%g ms", triptime);
YX			if (dupflag)
YX				(void)printf(" (DUP!)");
YX			/* check the data */
YX			cp = (u_char*)&icp->icmp_data[8];
YX			dp = &outpack[8 + sizeof(struct timeval)];
YX			for (i = 8; i < datalen; ++i, ++cp, ++dp) {
YX				if (*cp != *dp) {
YX	(void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
YX	    i, *dp, *cp);
YX					cp = (u_char*)&icp->icmp_data[0];
YX					for (i = 8; i < datalen; ++i, ++cp) {
YX						if ((i % 32) == 8)
YX							(void)printf("\n\t");
YX						(void)printf("%x ", *cp);
YX					}
YX					break;
YX				}
YX			}
YX		}
YX	} else {
YX		/* We've got something other than an ECHOREPLY */
YX		if (!(options & F_VERBOSE))
YX			return;
YX		(void)printf("%d bytes from %s: ", cc,
YX		    pr_addr(from->sin_addr.s_addr));
YX		pr_icmph(icp);
YX	}
YX
YX	/* Display any IP options */
YX	cp = (u_char *)buf + sizeof(struct ip);
YX
YX	for (; hlen > (int)sizeof(struct ip); --hlen, ++cp)
YX		switch (*cp) {
YX		case IPOPT_EOL:
YX			hlen = 0;
YX			break;
YX		case IPOPT_LSRR:
YX			(void)printf("\nLSRR: ");
YX			hlen -= 2;
YX			j = *++cp;
YX			++cp;
YX			if (j > IPOPT_MINOFF)
YX				for (;;) {
YX					l = *++cp;
YX					l = (l<<8) + *++cp;
YX					l = (l<<8) + *++cp;
YX					l = (l<<8) + *++cp;
YX					if (l == 0)
YX						(void)printf("\t0.0.0.0");
YX				else
YX					(void)printf("\t%s", pr_addr(ntohl(l)));
YX				hlen -= 4;
YX				j -= 4;
YX				if (j <= IPOPT_MINOFF)
YX					break;
YX				(void)putchar('\n');
YX			}
YX			break;
YX		case IPOPT_RR:
YX			j = *++cp;		/* get length */
YX			i = *++cp;		/* and pointer */
YX			hlen -= 2;
YX			if (i > j)
YX				i = j;
YX			i -= IPOPT_MINOFF;
YX			if (i <= 0)
YX				continue;
YX			if (i == old_rrlen
YX			    && cp == (u_char *)buf + sizeof(struct ip) + 2
YX			    && !bcmp((char *)cp, old_rr, i)
YX			    && !(options & F_FLOOD)) {
YX				(void)printf("\t(same route)");
YX				i = ((i + 3) / 4) * 4;
YX				hlen -= i;
YX				cp += i;
YX				break;
YX			}
YX			old_rrlen = i;
YX			bcopy((char *)cp, old_rr, i);
YX			(void)printf("\nRR: ");
YX			for (;;) {
YX				l = *++cp;
YX				l = (l<<8) + *++cp;
YX				l = (l<<8) + *++cp;
YX				l = (l<<8) + *++cp;
YX				if (l == 0)
YX					(void)printf("\t0.0.0.0");
YX				else
YX					(void)printf("\t%s", pr_addr(ntohl(l)));
YX				hlen -= 4;
YX				i -= 4;
YX				if (i <= 0)
YX					break;
YX				(void)putchar('\n');
YX			}
YX			break;
YX		case IPOPT_NOP:
YX			(void)printf("\nNOP");
YX			break;
YX		default:
YX			(void)printf("\nunknown option %x", *cp);
YX			break;
YX		}
YX	if (!(options & F_FLOOD)) {
YX		(void)putchar('\n');
YX		(void)fflush(stdout);
YX	}
YX}
YX
YX/*
YX * in_cksum --
YX *	Checksum routine for Internet Protocol family headers (C Version)
YX */
YXin_cksum(addr, len)
YX	u_short *addr;
YX	int len;
YX{
YX	register int nleft = len;
YX	register u_short *w = addr;
YX	u_short answer = 0;
YX	long sum = 0;
YX
YX	/*
YX	 * Our algorithm is simple, using a 32 bit accumulator (sum), we add
YX	 * sequential 16 bit words to it, and at the end, fold back all the
YX	 * carry bits from the top 16 bits into the lower 16 bits.
YX	 */
YX	while (nleft > 1)  {
YX		sum += *w++;
YX		nleft -= 2;
YX	}
YX
YX	/* mop up an odd byte, if necessary */
YX	if (nleft == 1) {
YX		*(u_char *)(&answer) = *(u_char *)w ;
YX		sum += answer;
YX	}
YX
YX	/* add back carry outs from top 16 bits to low 16 bits */
YX	sum = (sum >> 16) + (sum & 0xffffL);	/* add hi 16 to low 16 */
YX	sum += (sum >> 16);			/* add carry */
YX	answer = ~sum;				/* truncate to 16 bits */
YX	return(answer);
YX}
YX
YX/*
YX * tvsub --
YX *	Subtract 2 timeval structs:  out = out - in.  Out is assumed to
YX * be >= in.
YX */
YXtvsub(out, in)
YX	register struct timeval *out, *in;
YX{
YX	if ((out->tv_usec -= in->tv_usec) < 0) {
YX		--out->tv_sec;
YX		out->tv_usec += 1000000;
YX	}
YX	out->tv_sec -= in->tv_sec;
YX}
YX
YX/*
YX * finish --
YX *	Print out statistics, and give up.
YX */
YXvoid
YXfinish()
YX{
YX	register int i;
YX
YX	(void)signal(SIGINT, SIG_IGN);
YX	(void)putchar('\n');
YX	(void)fflush(stdout);
YX	(void)printf("--- %s ping statistics ---\n", hostname);
YX	(void)printf("%ld packets transmitted, ", ntransmitted);
YX	(void)printf("%ld packets received, ", nreceived);
YX	if (nrepeats)
YX		(void)printf("+%ld duplicates, ", nrepeats);
YX	if (ntransmitted)
YX		if (nreceived > ntransmitted)
YX			(void)printf("-- somebody's printing up packets!");
YX		else
YX			(void)printf("%d%% packet loss",
YX			    (int) (((ntransmitted - nreceived) * 100) /
YX			    ntransmitted));
YX	(void)putchar('\n');
YX	if (nreceived && timing) {
YX		/* Only display average to microseconds */
YX		i = 1000.0 * tsum / (nreceived + nrepeats);
YX		(void)printf("round-trip min/avg/max = %g/%g/%g ms\n",
YX		    tmin, ((double)i) / 1000.0, tmax);
YX	}
YX	exit(0);
YX}
YX
YX#ifdef notdef
YXstatic char *ttab[] = {
YX	"Echo Reply",		/* ip + seq + udata */
YX	"Dest Unreachable",	/* net, host, proto, port, frag, sr + IP */
YX	"Source Quench",	/* IP */
YX	"Redirect",		/* redirect type, gateway, + IP  */
YX	"Echo",
YX	"Time Exceeded",	/* transit, frag reassem + IP */
YX	"Parameter Problem",	/* pointer + IP */
YX	"Timestamp",		/* id + seq + three timestamps */
YX	"Timestamp Reply",	/* " */
YX	"Info Request",		/* id + sq */
YX	"Info Reply"		/* " */
YX};
YX#endif
YX
YX/*
YX * pr_icmph --
YX *	Print a descriptive string about an ICMP header.
YX */
YXpr_icmph(icp)
YX	struct icmp *icp;
YX{
YX	switch(icp->icmp_type) {
YX	case ICMP_ECHOREPLY:
YX		(void)printf("Echo Reply\n");
YX		/* XXX ID + Seq + Data */
YX		break;
YX	case ICMP_UNREACH:
YX		switch(icp->icmp_code) {
YX		case ICMP_UNREACH_NET:
YX			(void)printf("Destination Net Unreachable\n");
YX			break;
YX		case ICMP_UNREACH_HOST:
YX			(void)printf("Destination Host Unreachable\n");
YX			break;
YX		case ICMP_UNREACH_PROTOCOL:
YX			(void)printf("Destination Protocol Unreachable\n");
YX			break;
YX		case ICMP_UNREACH_PORT:
YX			(void)printf("Destination Port Unreachable\n");
YX			break;
YX		case ICMP_UNREACH_NEEDFRAG:
YX			(void)printf("frag needed and DF set\n");
YX			break;
YX		case ICMP_UNREACH_SRCFAIL:
YX			(void)printf("Source Route Failed\n");
YX			break;
YX		default:
YX			(void)printf("Dest Unreachable, Bad Code: %d\n",
YX			    icp->icmp_code);
YX			break;
YX		}
YX		/* Print returned IP header information */
YX#ifndef icmp_data
YX		pr_retip(&icp->icmp_ip);
YX#else
YX		pr_retip((struct ip *)icp->icmp_data);
YX#endif
YX		break;
YX	case ICMP_SOURCEQUENCH:
YX		(void)printf("Source Quench\n");
YX#ifndef icmp_data
YX		pr_retip(&icp->icmp_ip);
YX#else
YX		pr_retip((struct ip *)icp->icmp_data);
YX#endif
YX		break;
YX	case ICMP_REDIRECT:
YX		switch(icp->icmp_code) {
YX		case ICMP_REDIRECT_NET:
YX			(void)printf("Redirect Network");
YX			break;
YX		case ICMP_REDIRECT_HOST:
YX			(void)printf("Redirect Host");
YX			break;
YX		case ICMP_REDIRECT_TOSNET:
YX			(void)printf("Redirect Type of Service and Network");
YX			break;
YX		case ICMP_REDIRECT_TOSHOST:
YX			(void)printf("Redirect Type of Service and Host");
YX			break;
YX		default:
YX			(void)printf("Redirect, Bad Code: %d", icp->icmp_code);
YX			break;
YX		}
YX		(void)printf("(New addr: 0x%08lx)\n", icp->icmp_gwaddr.s_addr);
YX#ifndef icmp_data
YX		pr_retip(&icp->icmp_ip);
YX#else
YX		pr_retip((struct ip *)icp->icmp_data);
YX#endif
YX		break;
YX	case ICMP_ECHO:
YX		(void)printf("Echo Request\n");
YX		/* XXX ID + Seq + Data */
YX		break;
YX	case ICMP_TIMXCEED:
YX		switch(icp->icmp_code) {
YX		case ICMP_TIMXCEED_INTRANS:
YX			(void)printf("Time to live exceeded\n");
YX			break;
YX		case ICMP_TIMXCEED_REASS:
YX			(void)printf("Frag reassembly time exceeded\n");
YX			break;
YX		default:
YX			(void)printf("Time exceeded, Bad Code: %d\n",
YX			    icp->icmp_code);
YX			break;
YX		}
YX#ifndef icmp_data
YX		pr_retip(&icp->icmp_ip);
YX#else
YX		pr_retip((struct ip *)icp->icmp_data);
YX#endif
YX		break;
YX	case ICMP_PARAMPROB:
YX		(void)printf("Parameter problem: pointer = 0x%02x\n",
YX		    icp->icmp_hun.ih_pptr);
YX#ifndef icmp_data
YX		pr_retip(&icp->icmp_ip);
YX#else
YX		pr_retip((struct ip *)icp->icmp_data);
YX#endif
YX		break;
YX	case ICMP_TSTAMP:
YX		(void)printf("Timestamp\n");
YX		/* XXX ID + Seq + 3 timestamps */
YX		break;
YX	case ICMP_TSTAMPREPLY:
YX		(void)printf("Timestamp Reply\n");
YX		/* XXX ID + Seq + 3 timestamps */
YX		break;
YX	case ICMP_IREQ:
YX		(void)printf("Information Request\n");
YX		/* XXX ID + Seq */
YX		break;
YX	case ICMP_IREQREPLY:
YX		(void)printf("Information Reply\n");
YX		/* XXX ID + Seq */
YX		break;
YX#ifdef ICMP_MASKREQ
YX	case ICMP_MASKREQ:
YX		(void)printf("Address Mask Request\n");
YX		break;
YX#endif
YX#ifdef ICMP_MASKREPLY
YX	case ICMP_MASKREPLY:
YX		(void)printf("Address Mask Reply\n");
YX		break;
YX#endif
YX	default:
YX		(void)printf("Bad ICMP type: %d\n", icp->icmp_type);
YX	}
YX}
YX
YX/*
YX * pr_iph --
YX *	Print an IP header with options.
YX */
YXpr_iph(ip)
YX	struct ip *ip;
YX{
YX	int hlen;
YX	u_char *cp;
YX
YX	hlen = ip->ip_hl << 2;
YX	cp = (u_char *)ip + 20;		/* point to options */
YX
YX	(void)printf("Vr HL TOS  Len   ID Flg  off TTL Pro  cks      Src      Dst Data\n");
YX	(void)printf(" %1x  %1x  %02x %04x %04x",
YX	    ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id);
YX	(void)printf("   %1x %04x", ((ip->ip_off) & 0xe000) >> 13,
YX	    (ip->ip_off) & 0x1fff);
YX	(void)printf("  %02x  %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum);
YX	(void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr));
YX	(void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr));
YX	/* dump and option bytes */
YX	while (hlen-- > 20) {
YX		(void)printf("%02x", *cp++);
YX	}
YX	(void)putchar('\n');
YX}
YX
YX/*
YX * pr_addr --
YX *	Return an ascii host address as a dotted quad and optionally with
YX * a hostname.
YX */
YXchar *
YXpr_addr(l)
YX	u_long l;
YX{
YX	struct hostent *hp;
YX	static char buf[80];
YX
YX	if ((options & F_NUMERIC) ||
YX	    !(hp = gethostbyaddr((char *)&l, 4, AF_INET)))
YX		(void)sprintf(buf, "%s", inet_ntoa(*(struct in_addr *)&l));
YX	else
YX		(void)sprintf(buf, "%s (%s)", hp->h_name,
YX		    inet_ntoa(*(struct in_addr *)&l));
YX	return(buf);
YX}
YX
YX/*
YX * pr_retip --
YX *	Dump some info on a returned (via ICMP) IP packet.
YX */
YXpr_retip(ip)
YX	struct ip *ip;
YX{
YX	int hlen;
YX	u_char *cp;
YX
YX	pr_iph(ip);
YX	hlen = ip->ip_hl << 2;
YX	cp = (u_char *)ip + hlen;
YX
YX	if (ip->ip_p == 6)
YX		(void)printf("TCP: from port %u, to port %u (decimal)\n",
YX		    (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
YX	else if (ip->ip_p == 17)
YX		(void)printf("UDP: from port %u, to port %u (decimal)\n",
YX			(*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
YX}
YX
YXfill(bp, patp)
YX	char *bp, *patp;
YX{
YX	register int ii, jj, kk;
YX	int pat[16];
YX	char *cp;
YX
YX	for (cp = patp; *cp; cp++)
YX		if (!isxdigit(*cp)) {
YX			(void)fprintf(stderr,
YX			    "ping: patterns must be specified as hex digits.\n");
YX			exit(1);
YX		}
YX	ii = sscanf(patp,
YX	    "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
YX	    &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
YX	    &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
YX	    &pat[13], &pat[14], &pat[15]);
YX
YX	if (ii > 0)
YX		for (kk = 0;
YX		    kk <= MAXPACKET - (8 + sizeof(struct timeval) + ii);
YX		    kk += ii)
YX			for (jj = 0; jj < ii; ++jj)
YX				bp[jj + kk] = pat[jj];
YX	if (!(options & F_QUIET)) {
YX		(void)printf("PATTERN: 0x");
YX		for (jj = 0; jj < ii; ++jj)
YX			(void)printf("%02x", bp[jj] & 0xFF);
YX		(void)printf("\n");
YX	}
YX}
YX
YXusage()
YX{
YX	(void)fprintf(stderr,
YX	    "usage: ping [-Rdfnqrv] [-c count] [-i wait] [-l preload]\n\t[-p pattern] [-s packetsize] host\n");
YX	exit(1);
YX}
YSHAR_EOF
Ychmod 644 'ping.c'
Yfi
Ychmod 755 .
Ycd ..
Yif test -f '/usr/src/lib/libc/gen/getmntinfo.c'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/lib/libc/gen/getmntinfo.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/lib/libc/gen/getmntinfo.c'
YX/*
YX * Copyright (c) 1989, 1993
YX *	The Regents of the University of California.  All rights reserved.
YX *
YX * Redistribution and use in source and binary forms, with or without
YX * modification, are permitted provided that the following conditions
YX * are met:
YX * 1. Redistributions of source code must retain the above copyright
YX *    notice, this list of conditions and the following disclaimer.
YX * 2. Redistributions in binary form must reproduce the above copyright
YX *    notice, this list of conditions and the following disclaimer in the
YX *    documentation and/or other materials provided with the distribution.
YX * 3. All advertising materials mentioning features or use of this software
YX *    must display the following acknowledgement:
YX *	This product includes software developed by the University of
YX *	California, Berkeley and its contributors.
YX * 4. Neither the name of the University nor the names of its contributors
YX *    may be used to endorse or promote products derived from this software
YX *    without specific prior written permission.
YX *
YX * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX * SUCH DAMAGE.
YX */
YX
YX#if defined(LIBC_SCCS) && !defined(lint)
YXstatic char sccsid[] = "@(#)getmntinfo.c	8.1.1 (2.11BSD) 1995/12/26";
YX#endif /* LIBC_SCCS and not lint */
YX
YX#include <sys/param.h>
YX#include <sys/mount.h>
YX#include <stdlib.h>
YX
YX/*
YX * Return information about mounted filesystems.
YX */
YXint
YXgetmntinfo(mntbufp, flags)
YX	register struct statfs **mntbufp;
YX	int flags;
YX{
YX	static struct statfs *mntbuf;
YX	static int mntsize;
YX	static int bufsize;
YX
YX	if (mntsize <= 0 && (mntsize = getfsstat(0, 0, MNT_NOWAIT)) < 0)
YX		return (0);
YX	if (bufsize > 0 && (mntsize = getfsstat(mntbuf, bufsize, flags)) < 0)
YX		return (0);
YX	while (bufsize <= mntsize * sizeof(struct statfs)) {
YX		if (mntbuf)
YX			free(mntbuf);
YX		bufsize = (mntsize + 1) * sizeof(struct statfs);
YX		if ((mntbuf = (struct statfs *)malloc(bufsize)) == 0)
YX			return (0);
YX		if ((mntsize = getfsstat(mntbuf, bufsize, flags)) < 0)
YX			return (0);
YX	}
YX	*mntbufp = mntbuf;
YX	return (mntsize);
YX}
YSHAR_EOF
Ychmod 644 '/usr/src/lib/libc/gen/getmntinfo.c'
Yfi
Yif test -f '/usr/src/man/man2/getfsstat.2'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/man/man2/getfsstat.2'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/man/man2/getfsstat.2'
YX.\" Copyright (c) 1989, 1991, 1993
YX.\"	The Regents of the University of California.  All rights reserved.
YX.\"
YX.\" Redistribution and use in source and binary forms, with or without
YX.\" modification, are permitted provided that the following conditions
YX.\" are met:
YX.\" 1. Redistributions of source code must retain the above copyright
YX.\"    notice, this list of conditions and the following disclaimer.
YX.\" 2. Redistributions in binary form must reproduce the above copyright
YX.\"    notice, this list of conditions and the following disclaimer in the
YX.\"    documentation and/or other materials provided with the distribution.
YX.\" 3. All advertising materials mentioning features or use of this software
YX.\"    must display the following acknowledgement:
YX.\"	This product includes software developed by the University of
YX.\"	California, Berkeley and its contributors.
YX.\" 4. Neither the name of the University nor the names of its contributors
YX.\"    may be used to endorse or promote products derived from this software
YX.\"    without specific prior written permission.
YX.\"
YX.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX.\" SUCH DAMAGE.
YX.\"
YX.\"	@(#)getfsstat.2	8.1.1 (2.11BSD) 1995/12/24
YX.\"
YX.TH GETFSSTAT 2 "December 24, 1995"
YX.UC 7
YX.SH NAME
YX\fBgetfsstat\fP \- get list of all mounted filesystems
YX.SH SYNOPSIS
YX.B #include <sys/param.h>
YX.br
YX.B #include <sys/mount.h>
YX.sp
YX.I int
YX.br
YX\fBgetfsstat\fP(buf,bufsize,flags)
YX.br
YX.I struct statfs *buf;
YX.br
YX.I int bufsize;
YX.br
YX.I int flags;
YX.br
YX.SH DESCRIPTION
YX.BR Getfsstat ()
YXreturns information about all mounted filesystems.
YX.I Buf
YXis a pointer to
YX.I statfs
YXstructures defined as follows:
YX.sp
YX.nf
YX.cs R 20
YX
YX#define MNAMELEN 90       /* length of buffer for returned name */
YX
YXstruct statfs {
YXshort   f_type;           /* type of filesystem (see below) */
YXshort   f_flags;          /* copy of mount flags */
YXshort   f_bsize;          /* fundamental file system block size */
YXshort   f_iosize;         /* optimal transfer block size */
YXlong    f_blocks;         /* total data blocks in file system */
YXlong    f_bfree;          /* free blocks in fs */
YXlong    f_bavail;         /* free blocks avail to non-superuser */
YXino_t   f_files;          /* total file nodes in file system */
YXino_t   f_ffree;          /* free file nodes in fs */
YXu_long  f_fsid[2];        /* file system id */
YXlong    f_spare[4];       /* spare for later */
YXchar    f_mntonname[MNAMELEN];    /* mount point */
YXchar    f_mntfromname[MNAMELEN];  /* mounted filesystem */
YX};
YX/*
YX* File system types. - Only UFS is supported so the other types are not
YX* given.
YX*/
YX#define	MOUNT_NONE	0
YX#define	MOUNT_UFS	1	/* Fast Filesystem */
YX.br
YX.fi
YX.cs R
YX.PP
YXFields that are undefined for a particular filesystem are set to -1.
YXThe buffer is filled with an array of
YX.I fsstat
YXstructures, one for each mounted filesystem
YXup to the size specified by
YX.IR bufsize .
YX.PP
YXIf
YX.I buf
YXis given as NULL,
YX.BR getfsstat ()
YXreturns just the number of mounted filesystems.
YX.PP
YXNormally
YX.I flags
YXis currently unused.  In 4.4BSD systems the usage is
YXspecified as
YXMNT_WAIT.
YXIf
YX.I flags
YXis set to
YXMNT_NOWAIT,
YX.BR getfsstat ()
YXwill return the information it has available without requesting
YXan update from each filesystem.
YXThus, some of the information will be out of date, but
YX.BR getfsstat ()
YXwill not block waiting for information from a filesystem that is
YXunable to respond.
YX.SH RETURN VALUES
YXUpon successful completion, the number of 
YX.I fsstat
YXstructures is returned.
YXOtherwise, -1 is returned and the global variable
YX.I errno
YXis set to indicate the error.
YX.SH ERRORS
YX.BR Getfsstat ()
YXfails if one or more of the following are true:
YX.sp
YX.TP 20
YX[EFAULT]
YX.I Buf
YXpoints to an invalid address.
YX.TP 20
YX[EIO]
YXAn I/O
YXerror occurred while reading from or writing to the filesystem.
YX.SH SEE ALSO
YXstatfs(2), fstab(5), mount(8)
YX.SH HISTORY
YXThe
YX.B getfsstat
YXfunction first appeared in 4.4BSD.
YSHAR_EOF
Ychmod 644 '/usr/src/man/man2/getfsstat.2'
Yfi
Yif test -f '/usr/src/man/man2/statfs.2'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/man/man2/statfs.2'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/man/man2/statfs.2'
YX.\" Copyright (c) 1989, 1991, 1993
YX.\"	The Regents of the University of California.  All rights reserved.
YX.\"
YX.\" Redistribution and use in source and binary forms, with or without
YX.\" modification, are permitted provided that the following conditions
YX.\" are met:
YX.\" 1. Redistributions of source code must retain the above copyright
YX.\"    notice, this list of conditions and the following disclaimer.
YX.\" 2. Redistributions in binary form must reproduce the above copyright
YX.\"    notice, this list of conditions and the following disclaimer in the
YX.\"    documentation and/or other materials provided with the distribution.
YX.\" 3. All advertising materials mentioning features or use of this software
YX.\"    must display the following acknowledgement:
YX.\"	This product includes software developed by the University of
YX.\"	California, Berkeley and its contributors.
YX.\" 4. Neither the name of the University nor the names of its contributors
YX.\"    may be used to endorse or promote products derived from this software
YX.\"    without specific prior written permission.
YX.\"
YX.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX.\" SUCH DAMAGE.
YX.\"
YX.\"	@(#)statfs.2	8.3.2 (2.11BSD) 1995/12/26
YX.\"
YX.TH STATFS 2 "December 26, 1995"
YX.UC 7
YX.SH NAME
YX\fBstatfs\fP, \fBfstatfs\fP \- get file system statistics
YX.SH SYNOPSIS
YX.B #include <sys/param.h>
YX.br
YX.B #include <sys/mount.h>
YX.sp
YX.I int
YX.br
YX\fBstatfs\fP(path,buf)
YX.br
YX.I char *path;
YX.br
YX.I struct statfs *buf;
YX.sp
YX.I int
YX.br
YX\fBfstatfs\fP(fd,buf)
YX.br
YX.I int fd;
YX.br
YX.I struct statfs *buf;
YX.SH DESCRIPTION
YX.BR Statfs ()
YXreturns information about a mounted file system.
YX.I Path
YXis the path name of any file within the mounted filesystem.
YX.I Buf
YXis a pointer to a
YX.I statfs
YXstructure defined as follows:
YX.sp
YX.nf
YX.cs R 20
YX
YX#define MNAMELEN 90       /* length of buffer for returned name */
YX
YXstruct statfs {
YXshort   f_type;           /* type of filesystem (see below) */
YXshort   f_flags;          /* copy of mount flags */
YXshort   f_bsize;          /* fundamental file system block size */
YXshort   f_iosize;         /* optimal transfer block size */
YXlong    f_blocks;         /* total data blocks in file system */
YXlong    f_bfree;          /* free blocks in fs */
YXlong    f_bavail;         /* free blocks avail to non-superuser */
YXino_t   f_files;          /* total file nodes in file system */
YXino_t   f_ffree;          /* free file nodes in fs */
YXu_long  f_fsid[2];        /* file system id */
YXlong    f_spare[4];       /* spare for later */
YXchar    f_mntonname[MNAMELEN];    /* mount point */
YXchar    f_mntfromname[MNAMELEN];  /* mounted filesystem */
YX};
YX/*
YX* File system types. - Only UFS is supported so the other types are not
YX* given.
YX*/
YX#define	MOUNT_UFS	1	/* Fast Filesystem */
YX.br
YX.fi
YX.cs R
YX.PP
YXFields that are undefined for a particular file system are set to -1.
YX.BR Fstatfs ()
YXreturns the same information about an open file referenced by descriptor
YX.IR fd .
YX.SH RETURN VALUES
YXUpon successful completion, a value of 0 is returned.
YXOtherwise, -1 is returned and the global variable
YX.I errno
YXis set to indicate the error.
YX.SH ERRORS
YX.BR Statfs ()
YXfails if one or more of the following are true:
YX.sp
YX.TP 20
YX[ENOTDIR]
YXA component of the path prefix of
YX.I Path
YXis not a directory.
YX.TP 20
YX[EINVAL]
YX.I path
YXcontains a character with the high-order bit set.
YX.TP 20
YX[ENAMETOOLONG]
YXThe length of a component of
YX.I path
YXexceeds 63 characters,
YXor the length of
YX.I path
YXexceeds 255 characters.
YX.TP 20
YX[ENOENT]
YXThe file referred to by
YX.I path
YXdoes not exist.
YX.TP 20
YX[EACCES]
YXSearch permission is denied for a component of the path prefix of
YX.IR path .
YX.TP 20
YX[ELOOP]
YXToo many symbolic links were encountered in translating
YX.IR path .
YX.TP 20
YX[EFAULT]
YX.I Buf
YXor
YX.I path
YXpoints to an invalid address.
YX.TP 20
YX[EIO]
YXAn
YXI/O
YXerror occurred while reading from or writing to the file system.
YX.PP
YX.BR Fstatfs ()
YXfails if one or more of the following are true:
YX.sp
YX.TP 20
YX[EBADF]
YX.I Fd
YXis not a valid open file descriptor.
YX.TP 20
YX[EFAULT]
YX.I Buf
YXpoints to an invalid address.
YX.TP 20
YX[EIO]
YXAn
YXI/O
YXerror occurred while reading from or writing to the file system.
YX.SH HISTORY
YXThe
YX.B statfs
YXfunction first appeared in 4.4BSD.
YSHAR_EOF
Ychmod 644 '/usr/src/man/man2/statfs.2'
Yfi
Yif test -f '/usr/src/man/man3/getmntinfo.3'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/man/man3/getmntinfo.3'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/man/man3/getmntinfo.3'
YX.\" Copyright (c) 1989, 1991, 1993
YX.\"	The Regents of the University of California.  All rights reserved.
YX.\"
YX.\" Redistribution and use in source and binary forms, with or without
YX.\" modification, are permitted provided that the following conditions
YX.\" are met:
YX.\" 1. Redistributions of source code must retain the above copyright
YX.\"    notice, this list of conditions and the following disclaimer.
YX.\" 2. Redistributions in binary form must reproduce the above copyright
YX.\"    notice, this list of conditions and the following disclaimer in the
YX.\"    documentation and/or other materials provided with the distribution.
YX.\" 3. All advertising materials mentioning features or use of this software
YX.\"    must display the following acknowledgement:
YX.\"	This product includes software developed by the University of
YX.\"	California, Berkeley and its contributors.
YX.\" 4. Neither the name of the University nor the names of its contributors
YX.\"    may be used to endorse or promote products derived from this software
YX.\"    without specific prior written permission.
YX.\"
YX.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX.\" SUCH DAMAGE.
YX.\"
YX.\"     @(#)getmntinfo.3	8.1.1 (2.11BSD) 1995/12/26
YX.\"
YX.TH GETMNTINFO 3 "December 26, 1995"
YX.UC 7
YX.SH NAME
YX\fBgetmntinfo\fP \- get information about mounted file systems
YX.SH SYNOPSIS
YX.B #include <sys/param.h>
YX.br
YX.B #include <sys/mount.h>
YX.sp
YX.I int
YX.br
YX\fBgetmntinfo\fP(mntbufp,flags)
YX.br
YX.I struct statfs **mntbufp;
YX.br
YX.I int flags
YX.br
YX.SH DESCRIPTION
YXThe
YX.BR getmntinfo ()
YXfunction
YXreturns an array of
YX.I statfs
YXstructures describing each currently mounted file system (see
YX.BR statfs (2).
YX.PP
YXThe
YX.BR getmntinfo ()
YXfunction
YXpasses its
YX.I flags
YXparameter transparently to
YX.BR getfsstat (2).
YX.SH RETURN VALUES
YXOn successful completion,
YX.BR getmntinfo ()
YXreturns a count of the number of elements in the array.
YXThe pointer to the array is stored into
YX.IR mntbufp .
YX.PP
YXIf an error occurs, zero is returned and the external variable
YX.I errno
YXis set to indicate the error.
YXAlthough the pointer 
YX.I mntbufp
YXwill be unmodified, any information previously returned by 
YX.BR getmntinfo ()
YXwill be lost.
YX.SH ERRORS
YXThe
YX.BR getmntinfo ()
YXfunction
YXmay fail and set errno for any of the errors specified for the library 
YXroutines
YX.BR getfsstat (2)
YXor 
YX.BR malloc (3).
YX.SH SEE ALSO
YXgetfsstat(2),
YXstatfs(2),
YXmount(2),
YXmount(8)
YX.SH HISTORY
YXThe
YX.BR getmntinfo ()
YXfunction first appeared in 4.4BSD.
YX.SH BUGS
YXThe
YX.BR getmntinfo ()
YXfunction writes the array of structures to an internal static object
YXand returns
YXa pointer to that object. Subsequent calls to
YX.BR getmntinfo ()
YXwill modify the same object.
YX.PP
YXThe memory allocated by
YX.BR getmntinfo ()
YXcannot be
YX.BR free (2)'d
YXby the application.
YSHAR_EOF
Ychmod 644 '/usr/src/man/man3/getmntinfo.3'
Yfi
Yif test -f '/usr/src/sys/h/stddef.h'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/sys/h/stddef.h'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/sys/h/stddef.h'
YX/*-
YX * Copyright (c) 1990, 1993
YX *	The Regents of the University of California.  All rights reserved.
YX *
YX * Redistribution and use in source and binary forms, with or without
YX * modification, are permitted provided that the following conditions
YX * are met:
YX * 1. Redistributions of source code must retain the above copyright
YX *    notice, this list of conditions and the following disclaimer.
YX * 2. Redistributions in binary form must reproduce the above copyright
YX *    notice, this list of conditions and the following disclaimer in the
YX *    documentation and/or other materials provided with the distribution.
YX * 3. All advertising materials mentioning features or use of this software
YX *    must display the following acknowledgement:
YX *	This product includes software developed by the University of
YX *	California, Berkeley and its contributors.
YX * 4. Neither the name of the University nor the names of its contributors
YX *    may be used to endorse or promote products derived from this software
YX *    without specific prior written permission.
YX *
YX * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX * SUCH DAMAGE.
YX *
YX *	@(#)stddef.h	8.1 (Berkeley) 6/2/93
YX */
YX
YX#ifndef _STDDEF_H_
YX#define _STDDEF_H_
YX
YX/* #include <machine/ansi.h>	*/
YX
YX#define	offsetof(type, member)	((size_t)(&((type *)0)->member))
YX
YX#endif /* _STDDEF_H_ */
YSHAR_EOF
Ychmod 444 '/usr/src/sys/h/stddef.h'
Yfi
Yif test -f '/usr/src/sys/pdp/mscp_common.h'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/sys/pdp/mscp_common.h'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/sys/pdp/mscp_common.h'
YX/*
YX *	1.1	(2.11BSD) 1995/12/12
YX *
YX * Definitions common to both MSCP and TMSCP were moved here from tmscp.h.
YX * Eventually the MSCP driver and include file will be modified to use these
YX * instead of their private versions.
YX*/
YX
YX#ifndef	_MSCP_COMMON_H_
YX#define	_MSCP_COMMON_H_
YX
YX/*
YX * Control message opcodes
YX*/
YX#define	M_OP_ABORT	0x01	/* Abort command */
YX#define	M_OP_GTCMD	0x02	/* Get command status command */
YX#define	M_OP_GTUNT	0x03	/* Get unit status command */
YX#define	M_OP_STCON	0x04	/* Set controller characteristics command */
YX#define	M_OP_ACCNM	0x05	/* Access non volatile memory */
YX#define	M_OP_SEREX	0x07	/* Serious exceptin message */
YX#define	M_OP_AVAIL	0x08	/* Available command */
YX#define	M_OP_ONLIN	0x09	/* Online command */
YX#define	M_OP_STUNT	0x0a	/* Set unit characteristics command */
YX#define	M_OP_DTACP	0x0b	/* Determine access paths command */
YX#define	M_OP_ACCES	0x10	/* Access command */
YX#define	M_OP_CMPCD	0x11	/* Compare controller data command */
YX#define	M_OP_ERASE	0x12	/* Erase command */
YX#define	M_OP_FLUSH	0x13	/* Flush command */
YX#define M_OP_ERGAP	0x16	/* Erase gap command */
YX#define	M_OP_COMP	0x20	/* Compare host data command */
YX#define	M_OP_READ	0x21	/* Read command */
YX#define	M_OP_WRITE	0x22	/* Write command */
YX#define	M_OP_WRITM	0x24	/* Write tape mark command */
YX#define	M_OP_REPOS	0x25	/* Reposition command */
YX				/* 0x28 thru 0x2f reserved */
YX#define	M_OP_AVATN	0x40	/* Available attention message */
YX#define	M_OP_DUPUN	0x41	/* Duplicate unit number attention message */
YX#define	M_OP_ACPTH	0x42	/* Access path attention message */
YX#define	M_OP_RWATN	0x43	/* Rewind attention message */
YX#define	M_OP_END	0x80	/* End message flag */
YX 
YX/*
YX * Generic command modifiers
YX */
YX#define	M_MD_EXPRS	0x8000		/* Express request */
YX#define	M_MD_COMP	0x4000		/* Compare */
YX#define	M_MD_CLSEX	0x2000		/* Clear serious exception */
YX#define	M_MD_CDATL	0x1000		/* Clear cache data lost exception */
YX#define	M_MD_SCCHH	0x0800		/* Suppress caching (high speed) */
YX#define	M_MD_SCCHL	0x0400		/* Suppress caching (low speed) */
YX#define	M_MD_SECOR	0x0200		/* Suppress error correction */
YX#define	M_MD_SEREC	0x0100		/* Suppress error recovery */
YX#define	M_MD_WBKNV	0x0040		/* Write back non volative mem */
YX#define	M_MD_IMMED	0x0040		/* Immediate completion */
YX#define	M_MD_WBKVL	0x0020		/* Write back volatile mem */
YX#define	M_MD_UNLOD	0x0010		/* Unload */
YX#define	M_MD_REVRS	0x0008		/* reverse */
YX 
YX/*
YX * Repositioning command modifiers
YX */
YX#define	M_MD_DLEOT	0x0080		/* delete LEOT */
YX#define	M_MD_OBJCT	0x0004		/* object count */
YX#define	M_MD_REWND	0x0002		/* rewind */
YX 
YX/*
YX * Available command modifiers
YX*/
YX#define	M_MD_ALLCD	0x0002		/* All class drivers */
YX#define	M_MD_SPNDW	0x0001		/* Spin down */
YX
YX/*
YX * Flush command modifiers
YX*/
YX#define	M_MD_VOLTL	0x0002		/* Volatile memory only */
YX#define	M_MD_FLENU	0x0001		/* Flush entire unit's memory */
YX
YX/*
YX * Get unit status command modifiers
YX*/
YX#define	M_MD_NXUNT	0x0001		/* Get next unit */
YX
YX/*
YX * Online and set unit char command modifiers
YX*/
YX#define	M_MD_EXCAC	0x0020		/* Exclusive access */
YX#define	M_MD_STWRP	0x0004		/* Enable write protect */
YX
YX/*
YX * End message flags
YX */
YX#define	M_EF_ERLOG	0x0020	/* Error log generated */
YX#define	M_EF_SEREX	0x0010	/* Serious exception */
YX#define	M_EF_EOT	0x0008	/* End of tape encountered */
YX#define	M_EF_PLS	0x0004	/* Position lost */
YX#define	M_EF_DLS	0x0002	/* Cache data lost */
YX 
YX/*
YX * Controller flags
YX */
YX#define	M_CF_ATTN	0x0080	/* Enable attention messages */
YX#define	M_CF_MISC	0x0040	/* Enable miscellaneous error log messages */
YX#define	M_CF_OTHER	0x0020	/* Enable other host's error log messages */
YX#define	M_CF_THIS	0x0010	/* Enable this host's error log messages */
YX 
YX 
YX/*
YX * Unit flags
YX */
YX#define	M_UF_CACH	0x8000		/* Set if caching capable */
YX#define	M_UF_WRTPH	0x2000		/* Write protect (hardware) */
YX#define	M_UF_WRTPS	0x1000		/* Write protect (software or volume) */
YX#define	M_UF_SCCHH	0x0800		/* Suppress caching */
YX#define	M_UF_EXACC	0x0400		/* Exclusive access */
YX#define	M_UF_LOADR	0x0200		/* Tape loader present */
YX#define	M_UF_WRTPD	0x0100		/* Write protect (data safety) */
YX#define	M_UF_RMVBL	0x0080		/* Removable media */
YX#define	M_UF_WBKNV	0x0040		/* Write back (enables cache) */
YX#define	M_UF_VSMSU	0x0020		/* Variable speed mode suppression */
YX#define	M_UF_VARSP	0x0010		/* Variable speed unit */
YX#define	M_UF_CACFL	0x0004		/* Cache has been flushed */
YX#define	M_UF_CMPWR	0x0002		/* Compare writes */
YX#define	M_UF_CMPRD	0x0001		/* Compare reads */
YX 
YX/*
YX * Status codes
YX */
YX#define	M_ST_MASK	0x1f		/* Status code mask */
YX#define	M_ST_SBCOD	0x20		/* sub code multiplier */
YX#define	M_ST_SBBIT	0x05		/* Sub code starting bit position */
YX
YX#define	M_ST_SUCC	0x00		/* Success */
YX#define	M_ST_ICMD	0x01		/* Invalid command */
YX#define	M_ST_ABRTD	0x02		/* Command aborted */
YX#define	M_ST_OFFLN	0x03		/* Unit offline */
YX#define	M_ST_AVLBL	0x04		/* Unit available */
YX#define	M_ST_MFMTE	0x05		/* Media format error */
YX#define	M_ST_WRTPR	0x06		/* Write protected */
YX#define	M_ST_COMP	0x07		/* Compare error */
YX#define	M_ST_DATA	0x08		/* Data error */
YX#define	M_ST_HSTBF	0x09		/* Host buffer access error */
YX#define	M_ST_CNTLR	0x0a		/* Controller error */
YX#define	M_ST_DRIVE	0x0b		/* Drive error */
YX#define	M_ST_FMTER	0x0c		/* Formatter error */
YX#define	M_ST_BOT	0x0d		/* BOT encountered */
YX#define	M_ST_TAPEM	0x0e		/* Tape mark encountered */
YX#define	M_ST_RDTRN	0x10		/* Record data truncated */
YX#define	M_ST_PLOST	0x11		/* Position lost */
YX#define	M_ST_SEX	0x12		/* Serious exception */
YX#define	M_ST_LED	0x13		/* LEOT detected */
YX#define	M_ST_BBR	0x14		/* Bad block replacement complete */
YX#define	M_ST_IPARM	0x15		/* Invalid parameter */
YX#define	M_ST_INFO	0x16		/* Informational message, not error */
YX#define	M_ST_LOADR	0x17		/* Media loader error */
YX#define	M_ST_DIAG	0x1f		/* Message from internal diagnostic */
YX
YX/*
YX * Success subcodes
YX*/
YX#define	M_SC_NORML	0x0000		/* Normal */
YX#define	M_SC_SDIGN	0x0001		/* Spin down ignored */
YX#define	M_SC_STCON	0x0002		/* Still connected */
YX#define	M_SC_DUPUN	0x0004		/* Duplicate unit number */
YX#define	M_SC_ALONL	0x0008		/* Already online */
YX#define	M_SC_STONL	0x0010		/* Still online */
YX#define	M_SC_UNIGN	0x0011		/* Unload ignored */
YX#define	M_SC_EOT	0x0020		/* EOT seen */
YX#define	M_SC_ROVOL	0x0080		/* Read only volume */
YX
YX/*
YX * Invalid command subcodes
YX*/
YX#define	M_SC_INVML	0x0000		/* Invalid message length */
YX
YX/*
YX * Data error subcodes
YX*/
YX#define	M_SC_LGAP	0x0000		/* Long gap seen */
YX#define	M_SC_UREAD	0x0007		/* Unrecoverable read err */
YX
YX/*
YX * Unit offline subcodes
YX*/
YX#define	M_SC_UNKNO	0x0000		/* Unit unknown */
YX#define	M_SC_NOVOL	0x0001		/* No volume (turned off) */
YX#define	M_SC_INOPR	0x0002		/* Unit is inoperative */
YX#define	M_SC_UDSBL	0x0008		/* Unit disabled */
YX#define	M_SC_EXUSE	0x0010		/* Unit in use elsewhere */
YX#define	M_SC_LOADE	0x0020		/* Loader error */
YX
YX/*
YX * Unit available subcodes
YX*/
YX#define	M_SC_AVAIL	0x0000		/* Success */
YX
YX/*
YX * Write protect subcodes
YX*/
YX#define	M_SC_DATL	0x0008		/* Data loss write protected */
YX#define	M_SC_SOFTW	0x0080		/* Software write protected */
YX#define	M_SC_HARDW	0x0100		/* Hardware write protected */
YX
YX/*
YX * Error Log message format codes
YX */
YX#define	M_FM_CNTERR	0	/* Controller error */
YX#define	M_FM_BUSADDR	1	/* Host memory access error */
YX#define	M_FM_TAPETRN	5	/* Tape transfer error */
YX#define	M_FM_STIERR	6	/* STI communication or command failure */
YX#define	M_FM_STIDEL	7	/* STI drive error log */
YX#define	M_FM_STIFEL   010	/* STI formatter error log */
YX 
YX/*
YX * Error Log message flags
YX */
YX#define	M_LF_SUCC	0x80	/* Operation successful */
YX#define	M_LF_CONT	0x40	/* Operation continuing */
YX#define	M_LF_SQNRS	0x01	/* Sequence number reset */
YX 
YX/*
YX * Tape Format Flag Values
YX */
YX#define	M_TF_800	0x01	/* NRZI 800 bpi */
YX#define	M_TF_PE		0x02	/* Phase Encoded 1600 bpi */
YX#define	M_TF_GCR	0x04	/* Group Code Recording 6250 bpi */
YX#define	M_TF_BLK	0x08	/* Cartridge Block Mode */
YX
YX#endif	/* _MSCP_COMMON_H_ */
YSHAR_EOF
Ychmod 644 '/usr/src/sys/pdp/mscp_common.h'
Yfi
Yif test -f '/usr/src/sys/pdpuba/tmscpdump.c'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/sys/pdpuba/tmscpdump.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/sys/pdpuba/tmscpdump.c'
YX/*
YX * 	1.1	(2.11BSD)	1995/12/14
YX *
YX * This routine was moved from the main TMSCP driver due to size problems.
YX * The driver could become over 8kb in size and would not fit within an
YX * overlay!
YX *
YX * Thought was given to simply deleting this routine altogether - who 
YX * does crash dumps to tape (and the tmscp.c driver is the only one with
YX * a crash dump routine) but in the end the decision was made to retain
YX * the capability but move it to a separate file.
YX*/
YX
YX#include "tms.h"
YX#if	NTMSCP > 0
YX
YX#include "param.h"
YX#include "buf.h"
YX#include "machine/seg.h"
YX#include "tmscpreg.h"
YX#include "pdp/tmscp.h"
YX#include "errno.h"
YX#include "map.h"
YX#include "uba.h"
YX#include "pdp/seg.h"
YX
YX#ifdef	TMSCP_DUMP
YX#define DBSIZE 16
YX
YXextern	memaddr	tmscp[];
YXextern	char	*tmscpfatalerr;
YXextern	struct	tmscp_softc	tmscp_softc[];
YX
YXtmsdump(dev)
YX	dev_t dev;
YX{
YX	register struct tmscpdevice *tmscpaddr;
YX	register struct	tmscp_softc *sc;
YX	register struct	mscp	*mp;
YX	daddr_t bn, dumpsize;
YX	long paddr, maddr;
YX	int unit = TMSUNIT(dev), count, ctlr = TMSCTLR(dev);
YX	struct	ubmap *ubp;
YX	segm seg5;
YX
YX	if (ctlr >= NTMSCP)
YX		return (ENXIO);
YX	sc = &tmscp_softc[ctlr];
YX	tmscpaddr = sc->sc_addr;
YX	if (tmscpaddr == NULL)
YX		return(ENXIO);
YX
YX	paddr = _iomap(tmscp[sc->sc_unit]);
YX	if (ubmap) {
YX		ubp = UBMAP;
YX		ubp->ub_lo = loint(paddr);
YX		ubp->ub_hi = hiint(paddr);
YX	}
YX	paddr += RINGBASE;
YX	saveseg5(seg5);
YX	mapseg5(tmscp[sc->sc_unit], MAPBUFDESC);
YX	mp = sc->sc_com->tmscp_rsp;
YX	sc->sc_com->tmscp_ca.ca_cmdint = sc->sc_com->tmscp_ca.ca_rspint = 0;
YX	bzero(mp, 2 * sizeof (*mp));
YX
YX	tmscpaddr->tmscpip = 0;
YX	while ((tmscpaddr->tmscpsa & TMSCP_STEP1) == 0)
YX		if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT);
YX	tmscpaddr->tmscpsa = TMSCP_ERR;
YX	while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0)
YX		if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT);
YX	tmscpaddr->tmscpsa = loint(paddr);
YX	while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0)
YX		if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT);
YX	tmscpaddr->tmscpsa = hiint(paddr);
YX	while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0)
YX		if(tmscpaddr->tmscpsa & TMSCP_ERR) return(EFAULT);
YX	tmscpaddr->tmscpsa = TMSCP_GO;
YX	
YX	tmsginit(sc, sc->sc_com->tmscp_ca.ca_rspdsc, mp, 0, 2, 0);
YX
YX	if (tmscpcmd(M_OP_STCON, unit, sc) == 0) {
YX		return(EFAULT);
YX	}
YX	sc->sc_com->tmscp_cmd[0].mscp_unit = unit;
YX	if (tmscpcmd(M_OP_ONLIN, unit, sc) == 0) {
YX		return(EFAULT);
YX	}
YX
YX	dumpsize = 8 * 1024L;	 /* XXX */
YX	ubp = &UBMAP[1];
YX	for (paddr = 0; dumpsize > 0; dumpsize -= count) {
YX		count = MIN(dumpsize, DBSIZE);
YX		bn = paddr >> PGSHIFT;
YX		maddr = paddr;
YX		if (ubmap) {
YX			ubp->ub_lo = loint(paddr);
YX			ubp->ub_hi = hiint(paddr);
YX			maddr = (u_int)(1 << 13);
YX		}
YX	/* write it to the tape */
YX	mp = &sc->sc_com->tmscp_rsp[1];
YX	mp->mscp_lbn_l = loint(bn);
YX	mp->mscp_lbn_h = hiint(bn);
YX	mp->mscp_bytecnt = count * NBPG;
YX	mp->mscp_buffer_l = loint(maddr);
YX	mp->mscp_buffer_h = hiint(maddr);
YX	if (tmscpcmd(M_OP_WRITE, unit, sc) == 0)
YX		return(EIO);
YX	paddr += (DBSIZE << PGSHIFT);
YX	}
YX	restorseg5(seg5);
YX	return (0);
YX}
YX
YX/*
YX * Perform a standalone tmscp command.  This routine is only used by tmscpdump.
YX */
YX
YXtmscpcmd(op, unit, sc)
YX	int op;
YX	int unit;
YX	register struct tmscp_softc *sc;
YX{
YX	int i;
YX	register struct mscp *cmp, *rmp;
YX	Trl *rlp;
YX
YX	cmp = &sc->sc_com->tmscp_rsp[1];
YX	rmp = &sc->sc_com->tmscp_rsp[0];
YX	rlp = &sc->sc_com->tmscp_ca.ca_rspdsc[0];
YX
YX	cmp->mscp_opcode = op;
YX	cmp->mscp_unit = unit;
YX	cmp->mscp_header.tmscp_msglen = mscp_msglen;
YX	rmp->mscp_header.tmscp_msglen = mscp_msglen;
YX	rlp[0].hsh |= TMSCP_OWN|TMSCP_INT;
YX	rlp[1].hsh |= TMSCP_OWN|TMSCP_INT;
YX	if (sc->sc_addr->tmscpsa&TMSCP_ERR)
YX		printf(tmscpfatalerr, sc->sc_unit, unit, sc->sc_addr->tmscpsa);
YX	i = sc->sc_addr->tmscpip;
YX
YX	while ((rlp[1].hsh & TMSCP_INT) == 0)
YX		;
YX	while ((rlp[0].hsh & TMSCP_INT) == 0)
YX		;
YX
YX	sc->sc_com->tmscp_ca.ca_rspint = 0;
YX	sc->sc_com->tmscp_ca.ca_cmdint = 0;
YX	if (rmp->mscp_opcode != (op|M_OP_END) ||
YX	    (rmp->mscp_status&M_ST_MASK) != M_ST_SUCC)
YX		{
YX		printf("err: com %d opc 0x%x stat 0x%x\ndump ", op,
YX			rmp->mscp_opcode, rmp->mscp_status);
YX		return(0);
YX		}
YX	return(1);
YX}
YX#endif /* TMSCP_DUMP */
YX#endif /* NTMSCP */
YSHAR_EOF
Ychmod 644 '/usr/src/sys/pdpuba/tmscpdump.c'
Yfi
Yif test -f '/usr/src/sys/sys/ufs_syscalls2.c'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/sys/sys/ufs_syscalls2.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/sys/sys/ufs_syscalls2.c'
YX/*
YX * 	@(#) ufs_syscalls2.c	(2.11BSD) 1995/12/24
YX *
YX * ufs_syscalls was getting too large.  New UFS related system calls are
YX * placed in this file.
YX*/
YX
YX#include "param.h"
YX#include "../machine/seg.h"
YX#include "user.h"
YX#include "inode.h"
YX#include "fs.h"
YX#include "namei.h"
YX#include "mount.h"
YX
YXstatfs()
YX	{
YX	register struct a
YX		{
YX		char	*path;
YX		struct	statfs	*buf;
YX		} *uap = (struct a *)u.u_ap;
YX	register struct	inode	*ip;
YX	register struct nameidata *ndp = &u.u_nd;
YX	struct	mount	*mp;
YX
YX	ndp->ni_nameiop = LOOKUP|FOLLOW;
YX	ndp->ni_segflg = UIO_USERSPACE;
YX	ndp->ni_dirp = uap->path;
YX	ip = namei(ndp);
YX	if	(!ip)
YX		return(u.u_error);
YX	mp = (struct mount *)((int)ip->i_fs - offsetof(struct mount, m_filsys));
YX	irele(ip);
YX	u.u_error = statfs1(mp, uap->buf);
YX	return(u.u_error);
YX	}
YX
YXfstatfs()
YX	{
YX	register struct a
YX		{
YX		int	fd;
YX		struct	statfs *buf;
YX		} *uap = (struct a *)u.u_ap;
YX	register struct inode *ip;
YX	struct	mount *mp;
YX
YX	ip = getinode(uap->fd);
YX	if	(!ip)
YX		return(u.u_error);
YX	mp = (struct mount *)((int)ip->i_fs - offsetof(struct mount, m_filsys));
YX	u.u_error = statfs1(mp, uap->buf);
YX	return(u.u_error);
YX	}
YX
YXstatfs1(mp, sbp)
YX	struct	mount	*mp;
YX	struct	statfs	*sbp;
YX	{
YX	struct	statfs	sfs;
YX	register struct	statfs	*sfsp;
YX	struct	xmount	*xmp = (struct xmount *)SEG5;
YX	struct	fs	*fs = &mp->m_filsys;
YX
YX	sfsp = &sfs;
YX	sfsp->f_type = MOUNT_UFS;
YX	sfsp->f_bsize = MAXBSIZE;
YX	sfsp->f_iosize = MAXBSIZE;
YX	sfsp->f_blocks = fs->fs_fsize;
YX	sfsp->f_bfree = fs->fs_tfree;
YX	sfsp->f_bavail = fs->fs_tfree;
YX	sfsp->f_files = (fs->fs_isize - 2) * INOPB;
YX	sfsp->f_ffree = fs->fs_tinode;
YX
YX	mapseg5(mp->m_extern, XMOUNTDESC);
YX	bcopy(xmp->xm_mnton, sfsp->f_mntonname, MNAMELEN);
YX	bcopy(xmp->xm_mntfrom, sfsp->f_mntfromname, MNAMELEN);
YX	normalseg5();
YX	sfsp->f_flags = mp->m_flags & MNT_VISFLAGMASK;
YX	return(copyout(sfsp, sbp, sizeof (struct statfs)));
YX	}
YX
YXgetfsstat()
YX	{
YX	register struct a
YX		{
YX		struct	statfs	*buf;
YX		int	bufsize;
YX		u_int	flags;
YX		} *uap = (struct a *)u.u_ap;
YX	register struct	mount *mp;
YX	caddr_t	sfsp;
YX	int	count, maxcount, error;
YX
YX	maxcount = uap->bufsize / sizeof (struct statfs);
YX	sfsp = (caddr_t)uap->buf;
YX	count = 0;
YX	for	(mp = mount; mp < &mount[NMOUNT]; mp++)
YX		{
YX		if	(mp->m_inodp == NULL)
YX			continue;
YX		if	(count < maxcount)
YX			{
YX			if	(error = statfs1(mp, sfsp))
YX				return(u.u_error = error);
YX			sfsp += sizeof (struct statfs);
YX			}
YX		count++;
YX		}
YX	if	(sfsp && count > maxcount)
YX		u.u_r.r_val1 = maxcount;
YX	else
YX		u.u_r.r_val1 = count;
YX	return(0);
YX	}
YSHAR_EOF
Ychmod 644 '/usr/src/sys/sys/ufs_syscalls2.c'
Yfi
Yexit 0
Y#	End of shell archive
SHAR_EOF
chmod 640 '/tmp/shar.283'
fi
exit 0
#	End of shell archive