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