]> git.pld-linux.org Git - packages/di.git/commitdiff
- second part of di source
authorcieciwa <cieciwa@pld-linux.org>
Fri, 25 Feb 2000 13:56:35 +0000 (13:56 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    di-distr.002 -> 1.1

di-distr.002 [new file with mode: 0644]

diff --git a/di-distr.002 b/di-distr.002
new file mode 100644 (file)
index 0000000..94dd037
--- /dev/null
@@ -0,0 +1,3536 @@
+#! /bin/sh
+# This is a shell archive.  Remove anything before this line, then unpack
+# it by saving it into a file and typing "sh file".  To overwrite existing
+# files, type "sh file -c".  You can also feed this as standard input via
+# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
+# will see the following message at the end:
+#              "End of archive 2 (of 3)."
+# Contents:  di.c
+# Wrapped by root@seer on Thu Feb 24 10:15:51 2000
+PATH=/bin:/usr/bin:/usr/ucb ; export PATH
+if test -f 'di.c' -a "${1}" != "-c" ; then
+  echo shar: Will not clobber existing file \"'di.c'\"
+else
+echo shar: Extracting \"'di.c'\" \(97566 characters\)
+sed "s/^X//" >'di.c' <<'END_OF_FILE'
+X#ifndef lint
+Xstatic char    di_c_sccsid [] =
+X"@(#)di.c     1.21";
+Xstatic char    di_c_rcsid [] =
+X"$Id$";
+Xstatic char    di_c_source [] =
+X"$Source$";
+Xstatic char    copyright [] =
+X"Copyright 1994-1999 Brad Lanam, Walnut Creek, CA";
+X#endif
+X
+X/*
+X * di.c
+X *
+X *   Copyright 1994-1999 Brad Lanam,  Walnut Creek, CA
+X *
+X *  Warning: Do not replace your systems 'df' command with this program.
+X *           You will in all likelihood break your installation procedures.
+X *
+X *  Usage: di -AafntwWx [file [...]]
+X *            -A   : print all fields (used for debugging)
+X *            -a   : print all mounted devices; normally, those
+X *                   with 0 total blocks are not printed.  e.g.
+X *                   /dev/proc, /dev/fd.
+X *            -d x : size to print blocks in (p, k, m, g, <n>)
+X *            -f x : use format string <x>
+X *            -i x : ignore filesystem type(s) x, where x is a comma
+X *                   separated list.
+X *            -I x : include only filesystem type(s) x, where x is a
+X *                   separated list.
+X *            -l   : local filesystems only
+X *            -n   : don't print header
+X *            -s t : sort type
+X *            -t   : print totals
+X *            -w n : use <n> for the block print width (default 8).
+X *            -W n : use <n> for the inode print width (default 7).
+X *            -x n : debug level <n>
+X *
+X *  All values are reported in K (1024 bytes).
+X *
+X *  Sort types (by name is default):
+X *      n - none (mount order)
+X *      s - special
+X *      r - reverse sort
+X *
+X *  Format string values:
+X *      m - mount point
+X *      M - mount point, full length
+X *      b - total kbytes
+X *      B - total kbytes available for use by the user.
+X *             [ (tot - (free - avail) ]
+X *      u - kbytes used (actual number of kbytes used) [ (tot - free) ]
+X *      c - calculated number of kbytes used [ (tot - avail) ]
+X *      f - kbytes free
+X *      v - kbytes available
+X *      p - percentage not available for use.
+X *          (number of blocks not available for use / total disk space)
+X *             [ (tot - avail) / tot ]
+X *      1 - percentage used.
+X *          (actual number of blocks used / total disk space)
+X *             [ (tot - free) / tot ]
+X *      2 - percentage of user-available space in use (bsd style).
+X *          Note that values over 100% are possible.
+X *          (actual number of blocks used / disk space available to user)
+X *             [ (tot - free) / (tot - (free - avail)) ]
+X *      i - total i-nodes (files)
+X *      U - used i-nodes
+X *      F - free i-nodes
+X *      P - percent i-nodes used     [ (tot - avail) / tot ]
+X *      s - filesystem name (special)
+X *      S - filesystem name (special), full length
+X *      t - disk partition type
+X *      T - disk partition type (full length)
+X *      I - mount time
+X *      O - mount options.
+X *
+X *  System V.4 `/usr/bin/df -v` Has format: msbuf1 (w/-d512 option: 512 byte blocks)
+X *  System V.4 `/usr/bin/df -k` Has format: sbcvpm
+X *  System V.4 `/usr/ucb/df`    Has format: sbuv2m
+X *
+X *  The default format string for this program is: smbuvpT
+X *
+X *  The environment variable "DIFMT" may be set to the desired format
+X *  string.
+X *
+X *  Note that for filesystems that do not have (S512K fs) or systems (SysV.3)
+X *  that do not report available blocks, the number of available blocks is
+X *  equal to the number of free blocks.
+X *
+X *  HISTORY:
+X *     24 feb 2000 bll
+X *          Updated for BeOS.  This required changes to support c++
+X *          compilation (ansi style functions).  Fixes for linux.
+X *     17 dec 99 bll
+X *          Added sys/fs_types.h (Digital Unix (tru64)).
+X *     3 jan 99 bll
+X *          Finalize changes for metaconfig.
+X *          Always get stat() for disk device.
+X *          Remove duplicate disks from display.
+X *          Add NetBSD, Unicos, IRIX changes
+X *     8 sep 97 bll
+X *          Solaris large file version; AIX typo fix
+X *     15 aug 95 bll
+X *          Ignore will check the file system type beforehand if possible.
+X *          Fixed local mount stuff for osf1.
+X *     9 aug 95 bll
+X *          Changed totals to use double; the totals can now be displayed with
+X *          any wanted block size; sizes > one k have a single decimal point.
+X *          -d option specifies block size.
+X *          -l option for local file systems only.
+X *     7 aug 95 bll
+X *          convex fix.
+X *     29 jul 95 bll
+X *          Fixed bsdi variants.  The fragment size wasn't being supported.
+X *     22 jul 95 bll
+X *          fix problem with display widths in conjunction with ignore/include
+X *     20 feb 95 bll
+X *          added ignore/include file system type lists.
+X *     8 jan 95 bll
+X *          Added FreeBsd 2.x
+X *     6 dec 94 bll
+X *          sco nfs 'nothing' fix.
+X *     28 nov 94 bll
+X *          bsdi [bag@clipper.cs.kiev.ua (Andrey Blochintsev)]
+X *     24 nov 94 bll
+X *          Added FreeBsd - like OSF/1, but w/o nice mount name table.
+X *     1 may 94 bll
+X *          removed ill conceived mount options stuff.  Added AIX
+X *          (Erik O'Shaughnessy eriko@risc.austin.ibm.com).
+X *          Added coherent.
+X *     9 apr 94 bll
+X *          T format from Bill Davidsen. SunOS file system type.
+X *          mount options.
+X *     7 apr 94 bll
+X *          cdrom under solaris returning -1 in addition to -2.
+X *          Changed the test to test for any negative value.
+X *    5 apr 94 pm
+X *         Filesystem type info, and whether its read-write, readonly
+X *         etc is in the mntent structure.  Added code to support it.
+X *                  [Pat Myrto <pat@rwing.uucp>]
+X *    25 mar 94 bll
+X *          sun had f_bfree instead of f_bavail!
+X *          Xenix, linux.
+X *          -w, -W options, -B option, fixed width for -f M, -f S.
+X *          Usage.  Allow other characters in format string.
+X *     4 mar 94 bll
+X *          -f B, bug fixes. bcopy.
+X *          Solaris cdrom reports total, not free or avail.
+X *          Allow command line specification of file names.
+X *     3 mar 94 bll
+X *          support for OSF/1 and ULTRIX, -F, -f M, -f S
+X *                  [mogul@wrl.dec.com (Jeffrey Mogul)]
+X *     3 mar 94   bll
+X *          Allow command line specification of filename (s).
+X *          Sort output.  Test of nonexistent return code removed.
+X *     1 mar 94   bll
+X *          # of inodes can be -1L if unreportable.
+X *                  [jjb@jagware.bcc.com (J.J.Bailey)]
+X *                  [Mark Neale <mark@edscom.demon.co.uk>]
+X *          getDiskInfo () returning garbage
+X *                  [costales@ICSI.Berkeley.EDU (Bryan Costales)]
+X *                  [Mark Neale <mark@edscom.demon.co.uk>]
+X *          pyramid #ifdefs
+X *                  [vogelke@c-17igp.wpafb.af.mil (Contr Karl Vogel)]
+X *          name must be maxpathlen
+X *                  [Mark Neale <mark@edscom.demon.co.uk>]
+X *          error prints/compile warnings.
+X *                  [Mark Neale <mark@edscom.demon.co.uk>]
+X *
+X */
+X
+X#include "config.h"
+X
+X#include <stdio.h>
+X#include <ctype.h>
+X#include <errno.h>
+X#if defined (I_STDLIB)
+X# include <stdlib.h>
+X#endif
+X#if defined (I_SYS_TYPES)
+X# include <sys/types.h>
+X#endif
+X#if defined (I_LIMITS)
+X# include <limits.h>
+X#endif
+X#if defined (I_STRING)
+X# include <string.h>
+X#else
+X# include <strings.h>
+X#endif
+X#if defined (I_MEMORY)
+X# include <memory.h>
+X#endif
+X#if defined (I_MALLOC)
+X# include <malloc.h>
+X#endif
+X#if defined (I_UNISTD)
+X# include <unistd.h>
+X#endif
+X#if defined (I_TIME)
+X# include <time.h>
+X#endif
+X#if defined (I_SYS_TIME)
+X# include <sys/time.h>
+X#endif
+X#if defined (I_SYS_STAT)
+X# include <sys/stat.h>
+X#endif
+X#if defined (I_SYS_PARAM)
+X# include <sys/param.h>
+X#endif
+X
+X#if defined (I_SYS_MNTTAB)
+X# include <sys/mnttab.h>
+X#endif
+X#if defined (I_MNTTAB)
+X# include <mnttab.h>
+X#endif
+X#if defined (I_MNTENT)
+X# include <mntent.h>
+X#endif
+X#if defined (I_SYS_MNTENT)
+X# include <sys/mntent.h>
+X#endif
+X#if defined (I_SYS_MOUNT)
+X# include <sys/mount.h>
+X#endif
+X#if defined (I_SYS_FSTYPES)
+X# include <sys/fstypes.h>
+X#endif
+X#if defined (I_SYS_FS_TYPES)
+X# include <sys/fs_types.h>
+X#endif
+X#if defined (I_SYS_MNTCTL)
+X# include <sys/mntctl.h>
+X#endif
+X#if defined (I_SYS_VMOUNT)
+X# include <sys/vmount.h>
+X#endif
+X#if defined (I_SYS_STATFS) && ! defined (I_SYS_STATVFS)
+X# include <sys/statfs.h>
+X#endif
+X#if defined (I_FSHELP)
+X# include <fshelp.h>
+X#endif
+X#if defined (I_SYS_STATVFS)
+X# include <sys/statvfs.h>
+X#endif
+X#if defined (I_SYS_FSTYP)
+X# include <sys/fstyp.h>
+X# define DI_TYPE_LEN          FSTYPSZ
+X#endif
+X#if defined (I_SYS_VFS)
+X# include <sys/vfs.h>
+X#endif
+X#if defined (I_SYS_VFSTAB)
+X# include <sys/vfstab.h>
+X# if ! defined (DI_TYPE_LEN)
+X#  define DI_TYPE_LEN         FSTYPSZ
+X# endif
+X#endif
+X#if defined (I_FSHELP)
+X# include <fshelp.h>
+X#endif
+X
+X#if defined (I_WINDOWS)
+X# include <windows.h>            /* windows */
+X#endif
+X#if defined (I_KERNFSINFO)
+X# include <kernel/fs_info.h>
+X#endif
+X#if defined (I_STOR_DIRECTORY)
+X# include <storage/Directory.h>
+X#endif
+X#if defined (I_STOR_ENTRY)
+X# include <storage/Entry.h>
+X#endif
+X/*#if defined (I_STOR_NODE)
+X# include <storage/Node.h>
+X#endif  */
+X#if defined (I_STOR_PATH)
+X# include <storage/Path.h>
+X#endif
+X
+X#if ! defined (HAS_MEMCPY) && ! defined (memcpy)
+X# if ! defined (HAS_BCOPY)
+X   error No memcpy/bcopy available.
+X# else
+X#  define memcpy(dst, src, cnt)     (bcopy((src), (dst), (cnt)), dst)
+X# endif
+X#endif
+X
+X#if ! defined (MAXPATHLEN)
+X# if defined (_POSIX_PATH_MAX)
+X#  define MAXPATHLEN        _POSIX_PATH_MAX
+X# else
+X#  if defined (PATH_MAX)
+X#   define MAXPATHLEN        PATH_MAX
+X#  endif
+X#  if defined (LPNMAX)
+X#   define MAXPATHLEN         LPNMAX
+X#  endif
+X# endif
+X#endif
+X
+X#if ! defined (DI_TYPE_LEN)
+X# define DI_TYPE_LEN          16
+X#endif
+X
+X#define DI_FSMAGIC 5   /* base AIX configuration has 5 file systems */
+X
+X#if defined (HAS_STATFS_SYSV3) && ! defined (HAS_STATVFS) && \
+X    ! defined (HAS_GETMNTINFO) && ! defined (HAS_GETMNT) /* SYSV.3 */
+X# if defined (Ubsize) && Ubsize != ""
+X#  define UBSIZE            Ubsize
+X# endif
+X# if ! defined (UBSIZE)
+X#  define UBSIZE            512
+X# endif
+X#endif
+X
+X#if (defined (HAS_GETMNTENT) || defined (HAS_STATFS_BSD) || \
+X        defined (HAS_STATFS_SYSV3)) && ! defined (HAS_GETMNTINFO) && \
+X        ! defined (HAS_GETMNT)
+X# if defined (MOUNTED)
+X#  define DI_MOUNT_FILE        MOUNTED
+X# else
+X#  if defined (MNTTAB)
+X#   define DI_MOUNT_FILE       MNTTAB
+X#  else
+X#   define DI_MOUNT_FILE       "/etc/mnttab"
+X#  endif
+X# endif
+X#endif
+X
+X#if ! defined (HAS_MEMSET) && ! defined (memset)
+X# if ! defined (HAS_BZERO)
+X   error No memset/bzero available.
+X# else
+X#  define memset(s,c,n)    (bzero ((s), (n)), s)
+X# endif
+X#endif
+X
+X#if defined (NEED_GETENV_DEF)
+X  extern char *getenv _((char *));
+X#endif
+X
+X#if defined (NEED_STATFS_DEFS)
+X  extern int statfs _((char *, struct statfs *));
+X#endif
+X
+X#if defined (NEED_ERRNO_DEFS)
+Xextern int     errno;
+X#endif
+X
+X#if (defined (_LARGEFILE_SOURCE) || defined (_LARGEFILE64_SOURCE)) && \
+X        _FILE_OFFSET_BITS == 64
+X# define HAS_64BIT_STATFS_FLDS 1
+X#endif
+X
+X#if defined (HAS_64BIT_STATFS_FLDS)
+Xtypedef unsigned long long _fs_size_t;
+Xtypedef long long _s_fs_size_t;
+X#else
+Xtypedef unsigned long _fs_size_t;
+Xtypedef long _s_fs_size_t;
+X#endif
+X
+X#if ! defined (HAS_OPTIND)
+X  extern int optind;
+X  extern char *optarg;
+X#endif
+X
+X/* end of system specific includes/configurations */
+X
+X#if ! defined (TRUE)
+X# define TRUE             1
+X#endif
+X#if ! defined (FALSE)
+X# define FALSE            0
+X#endif
+X
+X#define DI_F_ALL               0x00000001
+X#define DI_F_LOCAL_ONLY        0x00000002
+X#define DI_F_TOTAL             0x00000010
+X#define DI_F_NO_HEADER         0x00000020
+X#define DI_F_DEBUG_HDR         0x00000040
+X
+X    /* mount information */
+X#define DI_FMT_MOUNT           'm'
+X#define DI_FMT_MOUNT_FULL      'M'
+X#define DI_FMT_SPECIAL         's'
+X#define DI_FMT_SPECIAL_FULL    'S'
+X#define DI_FMT_TYPE            't'
+X#define DI_FMT_TYPE_FULL       'T'
+X
+X    /* disk information */
+X#define DI_FMT_BTOT            'b'
+X#define DI_FMT_BTOT_AVAIL      'B'
+X#define DI_FMT_BUSED           'u'
+X#define DI_FMT_BCUSED          'c'
+X#define DI_FMT_BFREE           'f'
+X#define DI_FMT_BAVAIL          'v'
+X#define DI_FMT_BPERC_AVAIL     'p'
+X#define DI_FMT_BPERC_FREE      '1'
+X#define DI_FMT_BPERC_BSD       '2'
+X#define DI_FMT_ITOT            'i'
+X#define DI_FMT_IUSED           'U'
+X#define DI_FMT_IFREE           'F'
+X#define DI_FMT_IPERC           'P'
+X#define DI_FMT_MOUNT_TIME      'I'
+X#define DI_FMT_MOUNT_OPTIONS   'O'
+X
+X#define DI_IGNORE           0
+X#define DI_OK               1
+X#define DI_BAD              2
+X
+X#define DI_SORT_NONE        0
+X#define DI_SORT_NAME        1
+X#define DI_SORT_SPECIAL     2
+X
+X#define DI_SORT_ASCENDING   1
+X#define DI_SORT_DESCENDING  -1
+X
+X#define DI_UNKNOWN_DEV      -1L
+X#define DI_LIST_SEP         ","
+X
+X#define DI_ALL_FORMAT          "MTS\n\tIO\n\tbuf1\n\tbcvp\n\tBuv2\n\tiUFP"
+X
+X#define DI_HALF_K              512.0
+X#define DI_ONE_K               1024.0
+X#define DI_ONE_MEG             1048576.0
+X#define DI_ONE_GIG             1073241824.0
+X
+X#if ! defined (MAXPATHLEN)
+X# define MAXPATHLEN         255
+X#endif
+X#define DI_SPEC_NAME_LEN       MAXPATHLEN
+X#define DI_OPT_LEN             MAXPATHLEN
+X#define DI_MNT_TIME_LEN        24
+X
+X#define DI_RETRY_COUNT         5
+X#define DI_MAX_REMOTE_TYPES    20
+X
+X   /* you may want to change some of these values.  Be sure to change all */
+X   /* related entries.                                                    */
+X/* #define DI_DEFAULT_FORMAT      "mbuvpiUFP" */
+X#if ! defined (DI_DEFAULT_FORMAT)
+X# define DI_DEFAULT_FORMAT      "smbuvpT"
+X#endif
+X#if defined (HAS_MNT_TIME)
+X# define DI_DEF_MOUNT_FORMAT    "MSTIO"
+X#else
+X# define DI_DEF_MOUNT_FORMAT    "MSTO"
+X#endif
+X#define DI_PERC_FMT            "%3.0f%% "
+X#define DI_PERC_LBL_FMT        "%5s"
+X#define DI_NAME_LEN            MAXPATHLEN
+X#define DI_FSTYPE_FMT          "%-7.7s"
+X#define DI_MOUNT_FMT           "%-15.15s"
+X#define DI_SPEC_FMT            "%-18.18s"
+X
+X#define DI_UNKNOWN_FSTYPE      "Unknown fstyp %.2d"
+X
+Xtypedef unsigned long _ulong;
+Xtypedef int (*DI_SORT_FUNC) _((char *, char *));
+X
+Xtypedef struct
+X{
+X    double          totalBlocks;
+X    double          freeBlocks;
+X    double          availBlocks;
+X    _fs_size_t      totalInodes;
+X    _fs_size_t      freeInodes;
+X    _fs_size_t      availInodes;
+X    _ulong          st_dev;                      /* disk device number   */
+X    _ulong          sp_dev;                      /* special device number*/
+X    _ulong          sp_rdev;                     /* special rdev #       */
+X    char            printFlag;                   /* do we want to print  */
+X                                                 /* this entry?          */
+X    char            isLocal;                     /* is this mount point  */
+X                                                 /* local?               */
+X    char            name [DI_NAME_LEN + 1];         /* mount point          */
+X    char            special [DI_SPEC_NAME_LEN + 1]; /* special device name  */
+X    char            fsType [DI_TYPE_LEN + 1];       /* type of file system  */
+X    char            options [DI_OPT_LEN + 1];
+X    char            mountTime [DI_MNT_TIME_LEN + 1];
+X} DiskInfo;
+X
+Xstatic DiskInfo     *diskInfo = { (DiskInfo *) NULL };
+Xstatic int          diCount = { 0 };
+Xstatic int          debug = { 0 };
+Xstatic _ulong       flags = { 0 };
+Xstatic int          sortType = { DI_SORT_NAME };
+Xstatic int          sortOrder = { DI_SORT_ASCENDING };
+Xstatic char         *formatString = { DI_DEFAULT_FORMAT };
+Xstatic char         mountFormat [20];
+X static char         specialFormat [20];
+Xstatic char         typeFormat [20];
+Xstatic char         optFormat [20];
+Xstatic char         mTimeFormat [20];
+Xstatic int          width = { 8 };
+Xstatic int          inodeWidth = { 7 };
+Xstatic char         blockFormat [20];
+Xstatic char         blockLabelFormat [20];
+Xstatic char         inodeFormat [20];
+Xstatic char         inodeLabelFormat [20];
+Xstatic char         **ignoreList = { (char **) NULL };
+Xstatic char         **includeList = { (char **) NULL };
+Xstatic double       dispBlockSize = { DI_ONE_MEG };
+Xstatic int          remoteFileSystemCount = { 0 };
+Xstatic char         remoteFileSystemTypes [DI_MAX_REMOTE_TYPES][DI_TYPE_LEN];
+X
+X
+Xstatic void cleanup             _((void));
+Xstatic void printDiskInfo       _((void));
+Xstatic void printInfo           _((DiskInfo *));
+Xstatic void addTotals           _((DiskInfo *, DiskInfo *));
+Xstatic void printTitle          _((void));
+Xstatic void printPerc           _((double, double, char *));
+Xstatic char *Realloc            _((char *, long));
+Xstatic void sortArray           _((char *, int, int, DI_SORT_FUNC));
+Xstatic int  diCompare           _((char *, char *));
+Xstatic void getDiskStatInfo     _((void));
+Xstatic void getDiskSpecialInfo  _((void));
+Xstatic void printFileInfo       _((int, int, char *[]));
+Xstatic void checkDiskInfo       _((void));
+Xstatic void usage               _((void));
+Xstatic void processArgs         _((int, char *[]));
+Xstatic void parseList           _((char ***, char *));
+Xstatic void checkIgnoreList     _((DiskInfo *));
+Xstatic void checkIncludeList    _((DiskInfo *));
+X
+Xstatic int  getDiskEntries      _((void));
+Xstatic void getDiskInfo         _((void));
+X
+Xint
+X#if defined (CAN_PROTOTYPE)
+Xmain (int argc, char *argv [])
+X#else
+Xmain (argc, argv)
+X    int                 argc;
+X    char                *argv [];
+X#endif
+X{
+X    char                *ptr;
+X
+X
+X    ptr = argv [0] + strlen (argv [0]) - 2;
+X    if (memcmp (ptr, MPROG, 2) == 0)
+X    {
+X        formatString = DI_DEF_MOUNT_FORMAT;
+X    }
+X    else    /* don't use DIFMT env var if running mi. */
+X    {
+X        if ((ptr = getenv ("DIFMT")) != (char *) NULL)
+X        {
+X            formatString = ptr;
+X        }
+X    }
+X
+X    processArgs (argc, argv);
+X    if (debug > 0)
+X    {
+X        printf ("di ver $Revision$\n");
+X    }
+X
+X    if (getDiskEntries () < 0)
+X    {
+X        cleanup ();
+X        exit (1);
+X    }
+X
+X    getDiskInfo ();
+X    getDiskSpecialInfo ();
+X    checkDiskInfo ();
+X    if (optind < argc)
+X    {
+X        getDiskStatInfo ();
+X        printFileInfo (optind, argc, argv);
+X    }
+X    else
+X    {
+X        printDiskInfo ();
+X    }
+X
+X    cleanup ();
+X    exit (0);
+X}
+X
+X/*
+X * cleanup
+X *
+X * free up allocated memory
+X *
+X */
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+Xcleanup (void)
+X#else
+Xcleanup ()
+X#endif
+X{
+X    char        **lptr;
+X
+X
+X    if (diskInfo != (DiskInfo *) NULL)
+X    {
+X        free ((char *) diskInfo);
+X    }
+X
+X    if (ignoreList != (char **) NULL)
+X    {
+X        lptr = ignoreList;
+X        while (*lptr != (char *) NULL)
+X        {
+X            free ((char *) *lptr);
+X            ++lptr;
+X        }
+X        free ((char *) ignoreList);
+X    }
+X
+X    if (includeList != (char **) NULL)
+X    {
+X        lptr = includeList;
+X        while (*lptr != (char *) NULL)
+X        {
+X            free ((char *) *lptr);
+X            ++lptr;
+X        }
+X        free ((char *) includeList);
+X    }
+X}
+X
+X/*
+X * printDiskInfo
+X *
+X * Print out the disk information table.
+X * Loops through all mounted disks, prints and calculates totals.
+X *
+X */
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XprintDiskInfo (void)
+X#else
+XprintDiskInfo ()
+X#endif
+X{
+X    int                 i;
+X    DiskInfo            totals;
+X
+X
+X    memset ((char *) &totals, '\0', sizeof (DiskInfo));
+X    strcpy (totals.name, "Total");
+X    totals.printFlag = DI_OK;
+X
+X    if ((flags & DI_F_NO_HEADER) != DI_F_NO_HEADER)
+X    {
+X        printTitle ();
+X    }
+X
+X    if (sortType != DI_SORT_NONE)
+X    {
+X        sortArray ((char *) diskInfo, sizeof (DiskInfo), diCount, diCompare);
+X    }
+X
+X    for (i = 0; i < diCount; ++i)
+X    {
+X        if (( (flags & DI_F_ALL) == DI_F_ALL &&
+X                diskInfo [i].printFlag != DI_BAD) ||
+X                diskInfo [i].printFlag == DI_OK)
+X        {
+X            printInfo (&diskInfo [i]);
+X            addTotals (&diskInfo [i], &totals);
+X        }
+X    }
+X
+X    if ((flags & DI_F_TOTAL) == DI_F_TOTAL &&
+X            (flags & DI_F_NO_HEADER) != DI_F_NO_HEADER)
+X    {
+X        printInfo (&totals);
+X    }
+X}
+X
+X/*
+X * printInfo
+X *
+X * Print the information for a single partition.  Loop through the
+X * format string and print the particular items wanted.
+X *
+X */
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XprintInfo (DiskInfo *diskInfo)
+X#else
+XprintInfo (diskInfo)
+X    DiskInfo            *diskInfo;
+X#endif
+X{
+X    double              used;
+X    double              totAvail;
+X    char                *ptr;
+X    int                 valid;
+X
+X
+X    ptr = formatString;
+X    while (*ptr)
+X    {
+X        valid = TRUE;
+X
+X        switch (*ptr)
+X        {
+X            case DI_FMT_MOUNT:
+X            {
+X                printf (DI_MOUNT_FMT, diskInfo->name);
+X                break;
+X            }
+X
+X            case DI_FMT_MOUNT_FULL:
+X            {
+X                printf (mountFormat, diskInfo->name);
+X                break;
+X            }
+X
+X            case DI_FMT_BTOT:
+X            {
+X                printf (blockFormat, diskInfo->totalBlocks);
+X                break;
+X            }
+X
+X            case DI_FMT_BTOT_AVAIL:
+X            {
+X                printf (blockFormat, diskInfo->totalBlocks -
+X                        (diskInfo->freeBlocks - diskInfo->availBlocks));
+X                break;
+X            }
+X
+X            case DI_FMT_BUSED:
+X            {
+X                printf (blockFormat, diskInfo->totalBlocks -
+X                        diskInfo->freeBlocks);
+X                break;
+X            }
+X
+X            case DI_FMT_BCUSED:
+X            {
+X                printf (blockFormat, diskInfo->totalBlocks - diskInfo->availBlocks);
+X                break;
+X            }
+X
+X            case DI_FMT_BFREE:
+X            {
+X                printf (blockFormat, diskInfo->freeBlocks);
+X                break;
+X            }
+X
+X            case DI_FMT_BAVAIL:
+X            {
+X                printf (blockFormat, diskInfo->availBlocks);
+X                break;
+X            }
+X
+X            case DI_FMT_BPERC_AVAIL:
+X            {
+X                used = diskInfo->totalBlocks - diskInfo->availBlocks;
+X                totAvail = diskInfo->totalBlocks;
+X                printPerc (used, totAvail, DI_PERC_FMT);
+X                break;
+X            }
+X
+X            case DI_FMT_BPERC_FREE:
+X            {
+X                used = diskInfo->totalBlocks - diskInfo->freeBlocks;
+X                totAvail = diskInfo->totalBlocks;
+X                printPerc (used, totAvail, DI_PERC_FMT);
+X                break;
+X            }
+X
+X            case DI_FMT_BPERC_BSD:
+X            {
+X                used = diskInfo->totalBlocks - diskInfo->freeBlocks;
+X                totAvail = diskInfo->totalBlocks -
+X                        (diskInfo->freeBlocks - diskInfo->availBlocks);
+X                printPerc (used, totAvail, DI_PERC_FMT);
+X                break;
+X            }
+X
+X            case DI_FMT_ITOT:
+X            {
+X                printf (inodeFormat, diskInfo->totalInodes);
+X                break;
+X            }
+X
+X            case DI_FMT_IUSED:
+X            {
+X                printf (inodeFormat, diskInfo->totalInodes - diskInfo->freeInodes);
+X                break;
+X            }
+X
+X            case DI_FMT_IFREE:
+X            {
+X                printf (inodeFormat, diskInfo->freeInodes);
+X                break;
+X            }
+X
+X            case DI_FMT_IPERC:
+X            {
+X                used = diskInfo->totalInodes - diskInfo->availInodes;
+X                totAvail = diskInfo->totalInodes;
+X                printPerc (used, totAvail, DI_PERC_FMT);
+X                break;
+X            }
+X
+X            case DI_FMT_SPECIAL:
+X            {
+X                printf (DI_SPEC_FMT, diskInfo->special);
+X                break;
+X            }
+X
+X            case DI_FMT_SPECIAL_FULL:
+X            {
+X                printf (specialFormat, diskInfo->special);
+X                break;
+X            }
+X
+X            case DI_FMT_TYPE:
+X            {
+X                printf (DI_FSTYPE_FMT, diskInfo->fsType);
+X                break;
+X            }
+X
+X            case DI_FMT_TYPE_FULL:
+X            {
+X                printf (typeFormat, diskInfo->fsType);
+X                break;
+X            }
+X
+X            case DI_FMT_MOUNT_OPTIONS:
+X            {
+X                printf (optFormat, diskInfo->options);
+X                break;
+X            }
+X
+X            case DI_FMT_MOUNT_TIME:
+X            {
+X#if defined (HAS_MNT_TIME)
+X                printf (mTimeFormat, diskInfo->mountTime);
+X#endif
+X                break;
+X            }
+X
+X            default:
+X            {
+X                printf ("%c", *ptr);
+X                valid = FALSE;
+X                break;
+X            }
+X        }
+X
+X        ++ptr;
+X        if (*ptr && valid)
+X        {
+X            printf (" ");
+X        }
+X    }
+X
+X    printf ("\n");
+X}
+X
+X/*
+X * addTotals
+X *
+X * Add up the totals for the blocks/inodes
+X *
+X */
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XaddTotals (DiskInfo *diskInfo, DiskInfo *totals)
+X#else
+XaddTotals (diskInfo, totals)
+X    DiskInfo      *diskInfo;
+X    DiskInfo      *totals;
+X#endif
+X{
+X    totals->totalBlocks += diskInfo->totalBlocks;
+X    totals->freeBlocks += diskInfo->freeBlocks;
+X    totals->availBlocks += diskInfo->availBlocks;
+X    totals->totalInodes += diskInfo->totalInodes;
+X    totals->freeInodes += diskInfo->freeInodes;
+X    totals->availInodes += diskInfo->availInodes;
+X}
+X
+X/*
+X * printTitle
+X *
+X * Loop through the format string and print the appropriate headings.
+X *
+X */
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XprintTitle (void)
+X#else
+XprintTitle ()
+X#endif
+X{
+X    char                *ptr;
+X    int                 valid;
+X    char                tbuff [20];
+X
+X    if ((flags & DI_F_DEBUG_HDR) == DI_F_DEBUG_HDR)
+X    {
+X        printf ("di ver $Revision$ Default Format: %s\n",
+X                DI_DEFAULT_FORMAT);
+X    }
+X
+X    ptr = formatString;
+X
+X    while (*ptr)
+X    {
+X        valid = TRUE;
+X
+X        switch (*ptr)
+X        {
+X            case DI_FMT_MOUNT:
+X            {
+X                printf (DI_MOUNT_FMT, "Mount");
+X                break;
+X            }
+X
+X            case DI_FMT_MOUNT_FULL:
+X            {
+X                printf (mountFormat, "Mount");
+X                break;
+X            }
+X
+X            case DI_FMT_BTOT:
+X            case DI_FMT_BTOT_AVAIL:
+X            {
+X                if (dispBlockSize == DI_ONE_K)
+X                {
+X                    printf (blockLabelFormat, "Kbytes");
+X                }
+X                else if (dispBlockSize == DI_ONE_MEG)
+X                {
+X                    printf (blockLabelFormat, "  Megs");
+X                }
+X                else if (dispBlockSize == DI_ONE_GIG)
+X                {
+X                    printf (blockLabelFormat, "  Gigs");
+X                }
+X                else if (dispBlockSize == DI_HALF_K)
+X                {
+X                    printf (blockLabelFormat, "  512b");
+X                }
+X                else
+X                {
+X                    sprintf (tbuff, "%6.0f", dispBlockSize);
+X                    printf (blockLabelFormat, tbuff);
+X                }
+X                break;
+X            }
+X
+X            case DI_FMT_BUSED:
+X            case DI_FMT_BCUSED:
+X            {
+X                printf (blockLabelFormat, "Used");
+X                break;
+X            }
+X
+X            case DI_FMT_BFREE:
+X            {
+X                printf (blockLabelFormat, "Free");
+X                break;
+X            }
+X
+X            case DI_FMT_BAVAIL:
+X            {
+X                printf (blockLabelFormat, "Avail");
+X                break;
+X            }
+X
+X            case DI_FMT_BPERC_AVAIL:
+X            case DI_FMT_BPERC_FREE:
+X            case DI_FMT_BPERC_BSD:
+X            {
+X                printf (DI_PERC_LBL_FMT, "%used");
+X                break;
+X            }
+X
+X            case DI_FMT_ITOT:
+X            {
+X                printf (inodeLabelFormat, "Inodes");
+X                break;
+X            }
+X
+X            case DI_FMT_IUSED:
+X            {
+X                printf (inodeLabelFormat, "Used");
+X                break;
+X            }
+X
+X            case DI_FMT_IFREE:
+X            {
+X                printf (inodeLabelFormat, "Free");
+X                break;
+X            }
+X
+X            case DI_FMT_IPERC:
+X            {
+X                printf (DI_PERC_LBL_FMT, "%used");
+X                break;
+X            }
+X
+X            case DI_FMT_SPECIAL:
+X            {
+X                printf (DI_SPEC_FMT, "Filesystem");
+X                break;
+X            }
+X
+X            case DI_FMT_SPECIAL_FULL:
+X            {
+X                printf (specialFormat, "Filesystem");
+X                break;
+X            }
+X
+X            case DI_FMT_TYPE:
+X            {
+X                printf (DI_FSTYPE_FMT, "fsType");
+X                break;
+X            }
+X
+X            case DI_FMT_TYPE_FULL:
+X            {
+X                printf (typeFormat, "fs Type");
+X                break;
+X            }
+X
+X            case DI_FMT_MOUNT_OPTIONS:
+X            {
+X                printf (optFormat, "Options");
+X                break;
+X            }
+X
+X            case DI_FMT_MOUNT_TIME:
+X            {
+X#if defined (HAS_MNT_TIME)
+X                printf (mTimeFormat, "Mount Time");
+X#endif
+X                break;
+X            }
+X
+X            default:
+X            {
+X                printf ("%c", *ptr);
+X                valid = FALSE;
+X                break;
+X            }
+X        }
+X
+X        ++ptr;
+X        if (*ptr && valid)
+X        {
+X            printf (" ");
+X        }
+X    }
+X
+X    printf ("\n");
+X}
+X
+X/*
+X * printPerc
+X *
+X * Calculate and print a percentage using the values and format passed.
+X *
+X */
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XprintPerc (double used, double totAvail, char *format)
+X#else
+XprintPerc (used, totAvail, format)
+X    double      used;
+X    double      totAvail;
+X    char        *format;
+X#endif
+X{
+X    double      perc;
+X
+X
+X    if (totAvail > 0.0)
+X    {
+X        perc = used / totAvail;
+X        perc *= 100.0;
+X    }
+X    else
+X    {
+X        perc = 0.0;
+X    }
+X    printf (format, perc);
+X}
+X
+X
+X/*
+X * Realloc
+X *
+X * portable realloc
+X *
+X */
+X
+Xstatic char *
+X#if defined (CAN_PROTOTYPE)
+XRealloc (char *ptr, long size)
+X#else
+XRealloc (ptr, size)
+X    char      *ptr;
+X    long      size;
+X#endif
+X{
+X    if (ptr == (char *) NULL)
+X    {
+X        ptr = (char *) malloc (size);
+X    }
+X    else
+X    {
+X        ptr = (char *) realloc (ptr, size);
+X    }
+X
+X    return ptr;
+X}
+X
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XprintFileInfo (int optind, int argc, char *argv [])
+X#else
+XprintFileInfo (optind, argc, argv)
+X    int                 optind;
+X    int                 argc;
+X    char                *argv [];
+X#endif
+X{
+X    int                 i;
+X    int                 j;
+X    struct stat         statBuf;
+X    DiskInfo            totals;
+X
+X
+X    memset ((char *) &totals, '\0', sizeof (DiskInfo));
+X    strcpy (totals.name, "Total");
+X    totals.printFlag = DI_OK;
+X
+X    if ((flags & DI_F_NO_HEADER) != DI_F_NO_HEADER)
+X    {
+X        printTitle ();
+X    }
+X
+X    for (i = optind; i < argc; ++i)
+X    {
+X        if (stat (argv [i], &statBuf) == 0)
+X        {
+X            for (j = 0; j < diCount; ++j)
+X            {
+X                if (diskInfo [j].printFlag != DI_BAD &&
+X                        diskInfo [j].st_dev != DI_UNKNOWN_DEV &&
+X                        (_ulong) statBuf.st_dev == diskInfo [j].st_dev)
+X                {
+X                    printInfo (&diskInfo [j]);
+X                    addTotals (&diskInfo [j], &totals);
+X                    break; /* out of inner for */
+X                }
+X            }
+X        } /* if stat ok */
+X        else
+X        {
+X            fprintf (stderr, "stat: %s ", argv[i]);
+X            perror ("");
+X        }
+X    } /* for each file specified on command line */
+X
+X    if ((flags & DI_F_TOTAL) == DI_F_TOTAL && (flags & DI_F_NO_HEADER) != DI_F_NO_HEADER)
+X    {
+X        printInfo (&totals);
+X    }
+X}
+X
+X/*
+X *  sortArray ()
+X *
+X *      shellsort!
+X *
+X */
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XsortArray (char *data, int dataSize, int count, DI_SORT_FUNC compareFunc)
+X#else
+XsortArray (data, dataSize, count, compareFunc)
+X    char            *data;
+X    int             dataSize;
+X    int             count;
+X    DI_SORT_FUNC    compareFunc;
+X#endif
+X{
+X    register int    j;
+X    char            *tempData;
+X    int             i;
+X    int             gap;
+X
+X
+X    if (count <= 1)
+X    {
+X        return;
+X    }
+X
+X    tempData = (char *) malloc ((unsigned) dataSize);
+X    if (tempData == (char *) NULL)
+X    {
+X        fprintf (stderr, "malloc failed in sortArray().  errno %d\n", errno);
+X        cleanup ();
+X        exit (1);
+X    }
+X
+X    gap = 1;
+X    while (gap < count)
+X    {
+X        gap = 3 * gap + 1;
+X    }
+X
+X    for (gap /= 3; gap > 0; gap /= 3)
+X    {
+X        for (i = gap; i < count; ++i)
+X        {
+X            memcpy ((char *) tempData, (char *) &(data [i * dataSize]),
+X                    dataSize);
+X            j = i - gap;
+X
+X            while (j >= 0 &&
+X                compareFunc (&(data [j * dataSize]), tempData) > 0)
+X            {
+X                memcpy ((char *) &(data [(j + gap) * dataSize]),
+X                        (char *) &(data [j * dataSize]), dataSize);
+X                j -= gap;
+X            }
+X
+X            j += gap;
+X            if (j != i)
+X            {
+X                memcpy ((char *) &(data [j * dataSize]),
+X                        (char *) tempData, dataSize);
+X            }
+X        }
+X    }
+X
+X    free ((char *) tempData);
+X}
+X
+X
+Xstatic int
+X#if defined (CAN_PROTOTYPE)
+XdiCompare (char *a, char *b)
+X#else
+XdiCompare (a, b)
+X    char        *a;
+X    char        *b;
+X#endif
+X{
+X    DiskInfo    *di1;
+X    DiskInfo    *di2;
+X
+X
+X    di1 = (DiskInfo *) a;
+X    di2 = (DiskInfo *) b;
+X
+X
+X    switch (sortType)
+X    {
+X        case DI_SORT_NONE:
+X        {
+X            break;
+X        }
+X
+X        case DI_SORT_NAME:
+X        {
+X            return (strcmp (di1->name, di2->name) * sortOrder);
+X        }
+X
+X        case DI_SORT_SPECIAL:
+X        {
+X            return (strcmp (di1->special, di2->special) * sortOrder);
+X        }
+X    } /* switch on sort type */
+X
+X    return 0;
+X}
+X
+X
+X/*
+X * getDiskStatInfo
+X *
+X * gets the disk device number for each entry.
+X *
+X */
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XgetDiskStatInfo (void)
+X#else
+XgetDiskStatInfo ()
+X#endif
+X{
+X    int         i;
+X    struct stat statBuf;
+X
+X    for (i = 0; i < diCount; ++i)
+X    {
+X        diskInfo [i].st_dev = (_ulong) DI_UNKNOWN_DEV;
+X
+X        if (stat (diskInfo [i].name, &statBuf) == 0)
+X        {
+X            diskInfo [i].st_dev = (_ulong) statBuf.st_dev;
+X            if (debug > 2)
+X            {
+X                printf ("dev: %s: %ld\n", diskInfo [i].name,
+X                    diskInfo [i].st_dev);
+X            }
+X        }
+X        else
+X        {
+X            fprintf (stderr, "stat: %s ", diskInfo [i].name);
+X            perror ("");
+X        }
+X    }
+X}
+X
+X/*
+X * getDiskSpecialInfo
+X *
+X * gets the disk device number for each entry.
+X *
+X */
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XgetDiskSpecialInfo (void)
+X#else
+XgetDiskSpecialInfo ()
+X#endif
+X{
+X    int         i;
+X    struct stat statBuf;
+X
+X    for (i = 0; i < diCount; ++i)
+X    {
+X        if (stat (diskInfo [i].special, &statBuf) == 0)
+X        {
+X            diskInfo [i].sp_dev = (_ulong) statBuf.st_dev;
+X            diskInfo [i].sp_rdev = (_ulong) statBuf.st_rdev;
+X            if (debug > 2)
+X            {
+X                printf ("special dev: %s: %ld rdev: %ld\n", diskInfo [i].special,
+X                        diskInfo [i].sp_dev, diskInfo [i].sp_rdev);
+X            }
+X        }
+X        else
+X        {
+X            diskInfo [i].sp_dev = 0;
+X            diskInfo [i].sp_rdev = 0;
+X        }
+X    }
+X}
+X
+X/*
+X * checkDiskInfo
+X *
+X * checks the disk information returned for various return values.
+X *
+X */
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XcheckDiskInfo (void)
+X#else
+XcheckDiskInfo ()
+X#endif
+X{
+X    int           i;
+X    int           j;
+X    int           dupCount;
+X    int           len;
+X    int           maxMountString;
+X    int           maxSpecialString;
+X    int           maxTypeString;
+X    int           maxOptString;
+X    int           maxMntTimeString;
+X    _fs_size_t    temp;
+X    _ulong        sp_dev;
+X    _ulong        sp_rdev;
+X
+X
+X    maxMountString = (flags & DI_F_NO_HEADER) == DI_F_NO_HEADER ? 0 : 5;
+X    maxSpecialString = (flags & DI_F_NO_HEADER) == DI_F_NO_HEADER ? 0 : 10;
+X    maxTypeString = (flags & DI_F_NO_HEADER) == DI_F_NO_HEADER ? 0 : 7;
+X    maxOptString = (flags & DI_F_NO_HEADER) == DI_F_NO_HEADER ? 0 : 7;
+X    maxMntTimeString = (flags & DI_F_NO_HEADER) == DI_F_NO_HEADER ? 0 : 26;
+X
+X    for (i = 0; i < diCount; ++i)
+X    {
+X            /* Solaris reports a cdrom as having no free blocks,   */
+X            /* no available.  Their df doesn't always work right!  */
+X            /* -1 is returned.                                     */
+X        if (debug > 2)
+X        {
+X            printf ("chk: %s free: %f\n", diskInfo [i].name,
+X                diskInfo [i].freeBlocks);
+X        }
+X        if (diskInfo [i].freeBlocks < 0.0)
+X        {
+X            diskInfo [i].freeBlocks = 0.0;
+X        }
+X        if (diskInfo [i].availBlocks < 0.0)
+X        {
+X            diskInfo [i].availBlocks = 0.0;
+X        }
+X
+X        temp = ~ 0;
+X        if (diskInfo [i].totalInodes == temp)
+X        {
+X            diskInfo [i].totalInodes = 0;
+X            diskInfo [i].freeInodes = 0;
+X            diskInfo [i].availInodes = 0;
+X        }
+X
+X        if (debug > 2)
+X        {
+X            printf ("chk: %s total: %f\n", diskInfo [i].name,
+X                    diskInfo [i].totalBlocks);
+X        }
+X        if (diskInfo [i].totalBlocks <= 0.0 &&
+X            diskInfo [i].printFlag != DI_BAD)
+X        {
+X            diskInfo [i].printFlag = DI_IGNORE;
+X            if (debug > 2)
+X            {
+X                printf ("chk: ignore: totalBlocks <= 0: %s\n",
+X                        diskInfo [i].name);
+X            }
+X        }
+X
+X        checkIgnoreList (&diskInfo [i]);
+X        checkIncludeList (&diskInfo [i]);
+X    } /* for all disks */
+X
+X        /* this loop sets duplicate entries to be ignored. */
+X    for (i = 0; i < diCount; ++i)
+X    {
+X            /* don't need to bother checking real partitions */
+X            /* don't bother if already ignored               */
+X        if (diskInfo [i].sp_rdev != 0 &&
+X            (diskInfo [i].printFlag == DI_OK ||
+X            ((flags & DI_F_ALL) == DI_F_ALL &&
+X            diskInfo [i].printFlag != DI_BAD)))
+X        {
+X            sp_dev = diskInfo [i].sp_dev;
+X            sp_rdev = diskInfo [i].sp_rdev;
+X            dupCount = 0;
+X
+X            for (j = 0; j < diCount; ++j)
+X            {
+X                if (diskInfo [j].sp_dev == sp_rdev)
+X                {
+X                    ++dupCount;
+X                }
+X            }
+X
+X            if (debug > 2)
+X            {
+X                printf ("dup: chk: %s %ld %ld dup: %d\n", diskInfo [i].name,
+X                    sp_dev, sp_rdev, dupCount);
+X            }
+X
+X            for (j = 0; dupCount > 0 && j < diCount; ++j)
+X            {
+X                if (diskInfo [j].sp_rdev == 0 &&
+X                    diskInfo [j].sp_dev == sp_rdev)
+X                {
+X                    diskInfo [j].printFlag = DI_IGNORE;
+X                    if (debug > 2)
+X                    {
+X                        printf ("chk: ignore: duplicate: %s\n",
+X                                diskInfo [j].name);
+X                    }
+X                }
+X            } /* duplicate check for each disk */
+X        } /* if this is a printable disk */
+X        else
+X        {
+X            if (debug > 2)
+X            {
+X                printf ("chk: dup: not checked: %s prnt: %d dev: %ld rdev: %ld\n",
+X                        diskInfo [i].name, diskInfo [i].printFlag,
+X                        diskInfo [i].sp_dev, diskInfo [i].sp_rdev);
+X            }
+X        }
+X    } /* for each disk */
+X
+X        /* this loop gets the max string lengths */
+X    for (i = 0; i < diCount; ++i)
+X    {
+X        if (diskInfo [i].printFlag == DI_OK || (flags & DI_F_ALL) == DI_F_ALL)
+X        {
+X            len = strlen (diskInfo [i].name);
+X            if (len > maxMountString)
+X            {
+X                maxMountString = len;
+X            }
+X
+X            len = strlen (diskInfo [i].special);
+X            if (len > maxSpecialString)
+X            {
+X                maxSpecialString = len;
+X            }
+X
+X            len = strlen (diskInfo [i].fsType);
+X            if (len > maxTypeString)
+X            {
+X                maxTypeString = len;
+X            }
+X
+X            len = strlen (diskInfo [i].options);
+X            if (len > maxOptString)
+X            {
+X                maxOptString = len;
+X            }
+X
+X            len = strlen (diskInfo [i].mountTime);
+X            if (len > maxMntTimeString)
+X            {
+X                maxMntTimeString = len;
+X            }
+X        } /* if we are printing this item */
+X    } /* for all disks */
+X
+X    sprintf (mountFormat, "%%-%d.%ds", maxMountString, maxMountString);
+X    sprintf (specialFormat, "%%-%d.%ds", maxSpecialString,
+X             maxSpecialString);
+X    sprintf (typeFormat, "%%-%d.%ds", maxTypeString, maxTypeString);
+X    sprintf (optFormat, "%%-%d.%ds", maxOptString, maxOptString);
+X    sprintf (mTimeFormat, "%%-%d.%ds", maxMntTimeString, maxMntTimeString);
+X
+X    if (dispBlockSize <= DI_ONE_K)
+X    {
+X        sprintf (blockFormat, "%%%d.0f", width);
+X    }
+X    else
+X    {
+X        sprintf (blockFormat, "%%%d.1f", width);
+X    }
+X    sprintf (blockLabelFormat, "%%%ds", width);
+X#if defined (HAS_64BIT_STATFS_FLDS)
+X    sprintf (inodeFormat, "%%%dllu", inodeWidth);
+X#else
+X    sprintf (inodeFormat, "%%%dlu", inodeWidth);
+X#endif
+X    sprintf (inodeLabelFormat, "%%%ds", inodeWidth);
+X}
+X
+X/*
+X * usage
+X *
+X */
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+Xusage (void)
+X#else
+Xusage ()
+X#endif
+X{
+X    printf ("di ver $Revision$    Default Format: %s\n", DI_DEFAULT_FORMAT);
+X         /*  12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
+X    printf ("Usage: di [-ant] [-f format] [-s sort-type] [-i ignore-fstyp-list]\n");
+X    printf ("       [-I include-fstyp-list] [-w kbyte-width] [-W inode-width] [file [...]]\n");
+X    printf ("   -a   : print all mounted devices; normally, those with 0 total blocks are\n");
+X    printf ("          not printed.  e.g. /dev/proc, /dev/fd.\n");
+X    printf ("   -d x : size to print blocks in (p - posix (512), k - kbytes,\n");
+X    printf ("          m - megabytes, g - gigabytes, <x> - numeric size).\n");
+X    printf ("   -f x : use format string <x>\n");
+X    printf ("   -i x : ignore file system types in <x>\n");
+X    printf ("   -I x : include only file system types in <x>\n");
+X    printf ("   -l   : display local filesystems only\n");
+X    printf ("   -n   : don't print header\n");
+X    printf ("   -s t : sort type; n - no sort, s - by special device, r - reverse\n");
+X    printf ("   -t   : print totals\n");
+X    printf ("   -w n : use width <n> for kbytes\n");
+X    printf ("   -W n : use width <n> for i-nodes\n");
+X    printf (" Format string values:\n");
+X    printf ("    m - mount point                     M - mount point, full length\n");
+X    printf ("    b - total kbytes                    B - kbytes available for use\n");
+X    printf ("    u - used kbytes                     c - calculated kbytes in use\n");
+X    printf ("    f - kbytes free                     v - kbytes available\n");
+X    printf ("    p - percentage not avail. for use   1 - percentage used\n");
+X    printf ("    2 - percentage of user-available space in use.\n");
+X    printf ("    i - total file slots (i-nodes)      U - used file slots\n");
+X    printf ("    F - free file slots                 P - percentage file slots used\n");
+X    printf ("    s - filesystem name                 S - filesystem name, full length\n");
+X    printf ("    t - disk partition type             T - partition type, full length\n");
+X}
+X
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XprocessArgs (int argc, char *argv [])
+X#else
+XprocessArgs (argc, argv)
+X    int         argc;
+X    char        *argv [];
+X#endif
+X{
+X    int         ch;
+X
+X
+X    while ((ch = getopt (argc, argv, "Aad:f:hi:I:Flns:tw:W:x:")) != -1)
+X    {
+X        switch (ch)
+X        {
+X            case 'A':
+X            {
+X                formatString = DI_ALL_FORMAT;
+X                flags |= DI_F_ALL | DI_F_DEBUG_HDR | DI_F_TOTAL;
+X                flags &= ~ DI_F_NO_HEADER;
+X                width = 10;
+X                inodeWidth = 10;
+X                break;
+X            }
+X
+X            case 'a':
+X            {
+X                flags |= DI_F_ALL;
+X                break;
+X            }
+X
+X            case 'd':
+X            {
+X                switch (tolower (*optarg))
+X                {
+X                    case 'p':
+X                    {
+X                        dispBlockSize = DI_HALF_K;
+X                        break;
+X                    }
+X
+X                    case 'k':
+X                    {
+X                        dispBlockSize = DI_ONE_K;
+X                        break;
+X                    }
+X
+X                    case 'm':
+X                    {
+X                        dispBlockSize = DI_ONE_MEG;
+X                        break;
+X                    }
+X
+X                    case 'g':
+X                    {
+X                        dispBlockSize = DI_ONE_GIG;
+X                        break;
+X                    }
+X
+X                    default:
+X                    {
+X                        if (isdigit ((int) (*optarg)))
+X                        {
+X                            dispBlockSize = atof (optarg);
+X                        }
+X                        break;
+X                    }
+X                }
+X                break;
+X            }
+X
+X            case 'f':
+X            {
+X                formatString = optarg;
+X                break;
+X            }
+X
+X            case 'h':
+X            {
+X                usage ();
+X                cleanup ();
+X                exit (0);
+X            }
+X
+X            case 'i':
+X            {
+X                parseList (&ignoreList, optarg);
+X                break;
+X            }
+X
+X            case 'I':
+X            {
+X                parseList (&includeList, optarg);
+X                break;
+X            }
+X
+X            case 'l':
+X            {
+X                flags |= DI_F_LOCAL_ONLY;
+X                break;
+X            }
+X
+X            case 'n':
+X            {
+X                flags |= DI_F_NO_HEADER;
+X                break;
+X            }
+X
+X            case 's':
+X            {
+X                switch (ch)
+X                {
+X                    case 's':
+X                    {
+X                        sortType = DI_SORT_SPECIAL;
+X                        break;
+X                    }
+X
+X                    case 'n':
+X                    {
+X                        sortType = DI_SORT_NONE;
+X                        break;
+X                    }
+X
+X                    case 'r':
+X                    {
+X                        sortOrder = DI_SORT_DESCENDING;
+X                        break;
+X                    }
+X                }
+X                break;
+X            }
+X
+X            case 't':
+X            {
+X                flags |= DI_F_TOTAL;
+X                break;
+X            }
+X
+X            case 'w':
+X            {
+X                width = atoi (optarg);
+X                break;
+X            }
+X
+X            case 'W':
+X            {
+X                inodeWidth = atoi (optarg);
+X                break;
+X            }
+X
+X            case 'x':
+X            {
+X                debug = atoi (optarg);
+X                break;
+X            }
+X
+X            case '?':
+X            {
+X                usage ();
+X                cleanup ();
+X                exit (1);
+X            }
+X        }
+X    }
+X}
+X
+X    /* list is assumed to be global */
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XparseList (char ***list, char *str)
+X#else
+XparseList (list, str)
+X    char        ***list;
+X    char        *str;
+X#endif
+X{
+X    char        *dstr;
+X    char        *ptr;
+X    char        **lptr;
+X    int         count;
+X    int         i;
+X    int         len;
+X
+X    i = strlen (str);
+X    dstr = (char *) malloc (i + 1);
+X    if (dstr == (char *) NULL)
+X    {
+X        fprintf (stderr, "malloc failed in parseList() (1).  errno %d\n", errno);
+X        cleanup ();
+X        exit (1);
+X    }
+X
+X    memcpy (dstr, str, i + 1);
+X
+X    ptr = strtok (dstr, DI_LIST_SEP);
+X    count = 0;
+X    while (ptr != (char *) NULL)
+X    {
+X        ++count;
+X        ptr = strtok ((char *) NULL, DI_LIST_SEP);
+X    }
+X
+X    *list = (char **) malloc ((count + 1) * sizeof (char *));
+X    if (*list == (char **) NULL)
+X    {
+X        fprintf (stderr, "malloc failed in parseList() (2).  errno %d\n", errno);
+X        cleanup ();
+X        exit (1);
+X    }
+X
+X    ptr = dstr;
+X    lptr = *list;
+X    for (i = 0; i < count; ++i)
+X    {
+X        len = strlen (ptr);
+X        *lptr = (char *) malloc (len + 1);
+X        if (*lptr == (char *) NULL)
+X        {
+X            fprintf (stderr, "malloc failed in parseList() (3).  errno %d\n",
+X                    errno);
+X            cleanup ();
+X            exit (1);
+X        }
+X        strcpy (*lptr, ptr);
+X        ptr += len + 1;
+X        ++lptr;
+X    }
+X
+X    *lptr = (char *) NULL;
+X    free ((char *) dstr);
+X}
+X
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XcheckIgnoreList (DiskInfo *diskInfo)
+X#else
+XcheckIgnoreList (diskInfo)
+X    DiskInfo        *diskInfo;
+X#endif
+X{
+X    char            **ptr;
+X
+X        /* if the file system type is in the ignore list, skip it */
+X    if (ignoreList != (char **) NULL)
+X    {
+X        ptr = ignoreList;
+X        while (*ptr != (char *) NULL)
+X        {
+X            if (strcmp (*ptr, diskInfo->fsType) == 0)
+X            {
+X                diskInfo->printFlag = DI_IGNORE;
+X                if (debug > 2)
+X                {
+X                    printf ("chkign: ignore: fstype %s match: %s\n", *ptr,
+X                            diskInfo->name);
+X                }
+X                break;
+X            }
+X            ++ptr;
+X        }
+X    } /* if an ignore list was specified */
+X}
+X
+Xstatic void
+X#if defined (CAN_PROTOTYPE)
+XcheckIncludeList (DiskInfo *diskInfo)
+X#else
+XcheckIncludeList (diskInfo)
+X    DiskInfo        *diskInfo;
+X#endif
+X{
+X    char            **ptr;
+X
+X        /* if the file system type is not in the include list, skip it */
+X    if (includeList != (char **) NULL)
+X    {
+X        ptr = includeList;
+X        while (*ptr != (char *) NULL)
+X        {
+X            if (strcmp (*ptr, diskInfo->fsType) == 0)
+X            {
+X                diskInfo->printFlag = DI_OK;
+X                break;
+X            }
+X            else
+X            {
+X                diskInfo->printFlag = DI_IGNORE;
+X                if (debug > 2)
+X                {
+X                    printf ("chkinc: ! include: fstype %s match: %s\n", *ptr,
+X                            diskInfo->name);
+X                }
+X            }
+X            ++ptr;
+X        }
+X    } /* if an include list was specified */
+X}
+X
+X
+X#if defined (HAS_FS_INFO)
+X
+X/*
+X * getDiskEntries
+X *
+X * For BeOS.
+X *
+X */
+X
+Xstatic int
+XgetDiskEntries (void)
+X{
+X    status_t        stat;
+X    int             idx;
+X    int32           count;
+X    dev_t           dev;
+X    char            buff [B_FILE_NAME_LENGTH];
+X    fs_info         fsinfo;
+X    double          mult;
+X    node_ref        nref;
+X    BDirectory      *dir;
+X    BEntry          entry;
+X    BPath           path;
+X
+X    count = 0;
+X    while ((dev = next_dev (&count)) != B_BAD_VALUE)
+X    {
+X        if ((stat = fs_stat_dev (dev, &fsinfo)) == B_BAD_VALUE)
+X        {
+X            break;
+X        }
+X
+X        idx = diCount;
+X        ++diCount;
+X        diskInfo = (DiskInfo *) Realloc ((char *) diskInfo,
+X                sizeof (DiskInfo) * diCount);
+X        memset ((char *) &diskInfo [idx], '\0', sizeof (DiskInfo));
+X        diskInfo [idx].printFlag = DI_OK;
+X        *buff = '\0';
+X        nref.device = dev;
+X        nref.node = fsinfo.root;
+X        dir = new BDirectory (&nref);
+X        stat = dir->GetEntry (&entry);
+X        stat = entry.GetPath (&path);
+X        strncpy (diskInfo [idx].name, path.Path (), DI_NAME_LEN);
+X        strncpy (diskInfo [idx].special, fsinfo.device_name, DI_SPEC_NAME_LEN);
+X        strncpy (diskInfo [idx].fsType, fsinfo.fsh_name, DI_TYPE_LEN);
+X        diskInfo [idx].isLocal = TRUE;
+X        mult = (double) (long) fsinfo.block_size / dispBlockSize;
+X        diskInfo [idx].totalBlocks =
+X                ((double) (_s_fs_size_t) fsinfo.total_blocks * mult);
+X        diskInfo [idx].freeBlocks =
+X                ((double) (_s_fs_size_t) fsinfo.free_blocks * mult);
+X        diskInfo [idx].availBlocks =
+X                ((double) (_s_fs_size_t) fsinfo.free_blocks * mult);
+X        diskInfo [idx].totalInodes = fsinfo.total_nodes;
+X        diskInfo [idx].freeInodes = fsinfo.free_nodes;
+X        diskInfo [idx].availInodes = fsinfo.free_nodes;
+X
+X        checkIgnoreList (&diskInfo [idx]);
+X        checkIncludeList (&diskInfo [idx]);
+X
+X        if (debug > 0)
+X        {
+X            printf ("mnt:%s - %s\n", diskInfo [idx].name,
+X                    diskInfo [idx].special);
+X            printf ("dev:%d fs:%s\n", dev, diskInfo [idx].fsType);
+X        }
+X        if (debug > 1)
+X        {
+X            printf ("%s: %s\n", diskInfo [idx].name, diskInfo [idx].fsType);
+X            printf ("\tmult:%f\n", mult);
+X            printf ("\tblocks: tot:%ld free:%ld\n",
+X                    fsinfo.total_blocks, fsinfo.free_blocks);
+X            printf ("\tinodes: tot:%ld free:%ld\n",
+X                    fsinfo.total_nodes, fsinfo.free_nodes);
+X        }
+X    }
+X    return 0;
+X}
+X
+Xstatic void
+XgetDiskInfo (void)
+X{
+X    return;
+X}
+X
+X#endif
+X
+X#if defined (HAS_GETMNTENT) && ! defined (HAS_SETMNTENT)
+X
+X# define DFS_FS_TABLE        "/etc/dfs/fstypes"
+X
+X/*
+X * getDiskEntries
+X *
+X * For SysV.4, we open the file and call getmntent () repeatedly.
+X *
+X */
+X
+Xstatic int
+XgetDiskEntries ()
+X{
+X    FILE            *f;
+X    int             idx;
+X    int             i;
+X    struct mnttab   mntEntry;
+X    char            buff [80];
+X    time_t          mtime;
+X    char            *devp;   /* local ptr to dev entry */
+X
+X
+X    if ((flags & DI_F_LOCAL_ONLY) == DI_F_LOCAL_ONLY)
+X    {
+X        i = remoteFileSystemCount;
+X
+X        if ((f = fopen (DFS_FS_TABLE, "r")) != (FILE *) NULL)
+X        {
+X            fgets (buff, 80, f);
+X            if (debug > 1)
+X            {
+X                printf ("remote file system type: %s\n", buff);
+X            }
+X            sscanf (buff, "%s", remoteFileSystemTypes [i++]);
+X            fclose (f);
+X        }
+X
+X        remoteFileSystemCount = i;
+X    }
+X
+X    if ((f = fopen (DI_MOUNT_FILE, "r")) == (FILE *) NULL)
+X    {
+X        fprintf (stderr, "Unable to open: %s errno %d\n", DI_MOUNT_FILE, errno);
+X        return -1;
+X    }
+X
+X    while (getmntent (f, &mntEntry) == 0)
+X    {
+X        idx = diCount;
+X        ++diCount;
+X        diskInfo = (DiskInfo *) Realloc ((char *) diskInfo,
+X                sizeof (DiskInfo) * diCount);
+X        memset ((char *) &diskInfo [idx], '\0', sizeof (DiskInfo));
+X        diskInfo [idx].printFlag = DI_OK;
+X
+X        strncpy (diskInfo [idx].special, mntEntry.mnt_special,
+X                DI_SPEC_NAME_LEN);
+X        strncpy (diskInfo [idx].name, mntEntry.mnt_mountp, DI_NAME_LEN);
+X# if defined (MNTOPT_IGNORE)
+X        if (strstr (mntEntry.mnt_mntopts, MNTOPT_IGNORE) != (char *) NULL)
+X# else
+X        if (strstr (mntEntry.mnt_mntopts, "ignore") != (char *) NULL)
+X# endif
+X        {
+X            diskInfo [idx].printFlag = DI_IGNORE;
+X            if (debug > 2)
+X            {
+X                printf ("mnt: ignore: mntopt 'ignore': %s\n",
+X                        diskInfo [idx].name);
+X            }
+X        }
+X# if defined (MNTOPT_DEV)
+X        sprintf (buff, "%s=", MNTOPT_DEV);
+X        if ((devp = strstr (mntEntry.mnt_mntopts, buff)) != (char *) NULL)
+X# else
+X        if ((devp = strstr (mntEntry.mnt_mntopts, "dev=")) != (char *) NULL)
+X# endif
+X        {
+X            if (devp != mntEntry.mnt_mntopts)
+X            {
+X                --devp;
+X            }
+X            *devp = 0;   /* point to preceeding comma and cut off */
+X        }
+X        strncpy (diskInfo [idx].options, mntEntry.mnt_mntopts, DI_OPT_LEN);
+X        mtime = atol (mntEntry.mnt_time);
+X        strncpy (diskInfo [idx].mountTime, ctime (&mtime), DI_MNT_TIME_LEN);
+X
+X            /* get the file system type now... */
+X        strncpy (diskInfo [idx].fsType, mntEntry.mnt_fstype, DI_TYPE_LEN);
+X
+X        diskInfo [idx].isLocal = TRUE;
+X        for (i = 0; i < remoteFileSystemCount; ++i)
+X        {
+X            if (strcmp (diskInfo [idx].fsType, remoteFileSystemTypes [i]) == 0)
+X            {
+X                diskInfo [idx].isLocal = FALSE;
+X            }
+X        }
+X
+X        checkIgnoreList (&diskInfo [idx]);
+X        checkIncludeList (&diskInfo [idx]);
+X
+X        if (debug > 0)
+X        {
+X            printf ("mnt:%s - %s\n", diskInfo [idx].name,
+X                    diskInfo [idx].special);
+X        }
+X    }
+X
+X    fclose (f);
+X    return 0;
+X}
+X
+X#endif /* HAS_GETMNTENT */
+X
+X#if ! defined (HAS_GETMNTENT) && ! defined (HAS_MNTCTL) && \
+X        ! defined (HAS_GETMNTINFO) && ! defined (HAS_GETMNT) && \
+X      ! defined (HAS_GETDISKFREESPACE) && ! defined (HAS_FS_INFO)
+X
+X/*
+X * getDiskEntries
+X *
+X * For SysV.3 we open the file and read it ourselves.
+X *
+X */
+X
+Xstatic int
+XgetDiskEntries ()
+X{
+X    FILE             *f;
+X    int              idx;
+X    struct mnttab    mntEntry;
+X
+X
+X    if ((f = fopen (DI_MOUNT_FILE, "r")) == (FILE *) NULL)
+X    {
+X        fprintf (stderr, "Unable to open: %s errno %d\n", DI_MOUNT_FILE, errno);
+X        return -1;
+X    }
+X
+X    while (fread ((char *) &mntEntry, sizeof (struct mnttab), 1, f) == 1)
+X    {
+X            /* xenix allows null mount table entries */
+X            /* sco nfs background mounts are marked as "nothing" */
+X        if (mntEntry.mt_filsys [0] &&
+X                strcmp (mntEntry.mt_filsys, "nothing") != 0)
+X        {
+X            idx = diCount;
+X            ++diCount;
+X            diskInfo = (DiskInfo *) Realloc ((char *) diskInfo,
+X                                             sizeof (DiskInfo) * diCount);
+X            memset ((char *) &diskInfo [idx], '\0', sizeof (DiskInfo));
+X            diskInfo [idx].printFlag = DI_OK;
+X            diskInfo [idx].isLocal = TRUE;
+X
+X# if defined (COHERENT)
+X                /* Coherent seems to have these fields reversed. oh well. */
+X            strncpy (diskInfo [idx].name, mntEntry.mt_dev, DI_NAME_LEN);
+X            strncpy (diskInfo [idx].special, mntEntry.mt_filsys, DI_SPEC_NAME_LEN);
+X# else
+X            strncpy (diskInfo [idx].special, mntEntry.mt_dev, DI_SPEC_NAME_LEN);
+X            strncpy (diskInfo [idx].name, mntEntry.mt_filsys, DI_NAME_LEN);
+X# endif
+X            strncpy (diskInfo [idx].options, mntEntry.mnt_mntopts, DI_OPT_LEN);
+X            strncpy (diskInfo [idx].mountTime, mntEntry.mnt_time,
+X                    DI_MNT_TIME_LEN);
+X        }
+X
+X        if (debug > 0)
+X        {
+X            printf ("mnt:%s - %s\n", diskInfo [idx].name,
+X                    diskInfo [idx].special);
+X        }
+X    }
+X
+X    fclose (f);
+X    return 0;
+X}
+X
+X#endif /* Sys V.3 */
+X
+X#if defined (HAS_GETMNTENT) && defined (HAS_SETMNTENT) && \
+X        defined (HAS_ENDMNTENT)
+X
+X/*
+X * getDiskEntries
+X *
+X * SunOS supplies an open and close routine for the mount table.
+X *
+X */
+X
+Xstatic int
+XgetDiskEntries ()
+X{
+X    FILE            *f;
+X    int             idx;
+X    struct mntent   *mntEntry;
+X    char            *devp;   /* local ptr to dev entry */
+X
+X
+X#if defined (HAS_SETMNTENT_ONE_ARG)
+X    if ((f = setmntent (DI_MOUNT_FILE)) == (FILE *) NULL)
+X#else
+X    if ((f = setmntent (DI_MOUNT_FILE, "r")) == (FILE *) NULL)
+X#endif
+X    {
+X        fprintf (stderr, "Unable to open: %s errno %d\n", DI_MOUNT_FILE, errno);
+X        return -1;
+X    }
+X
+X    while ((mntEntry = getmntent (f)) != (struct mntent *) NULL)
+X    {
+X        idx = diCount;
+X        ++diCount;
+X        diskInfo = (DiskInfo *) Realloc ((char *) diskInfo,
+X                sizeof (DiskInfo) * diCount);
+X        memset ((char *) &diskInfo [idx], '\0', sizeof (DiskInfo));
+X        diskInfo [idx].printFlag = DI_OK;
+X        diskInfo [idx].isLocal = TRUE;
+X
+X        strncpy (diskInfo [idx].special, mntEntry->mnt_fsname, DI_SPEC_NAME_LEN);
+X        strncpy (diskInfo [idx].name, mntEntry->mnt_dir, DI_NAME_LEN);
+X        strncpy (diskInfo [idx].fsType, mntEntry->mnt_type, DI_TYPE_LEN);
+X
+X        if (strcmp (mntEntry->mnt_type, MNTTYPE_IGNORE) == 0)
+X        {
+X            diskInfo [idx].printFlag = DI_IGNORE;
+X            if (debug > 2)
+X            {
+X                printf ("mnt: ignore: mntopt 'ignore': %s\n",
+X                        diskInfo [idx].name);
+X            }
+X        }
+X
+X        if ((devp = strstr (mntEntry->mnt_opts, "dev=")) != (char *) NULL)
+X        {
+X            if (devp != mntEntry->mnt_opts)
+X            {
+X                --devp;
+X            }
+X            *devp = 0;   /* point to preceeding comma and cut off */
+X        }
+X        strncpy (diskInfo [idx].options, mntEntry->mnt_opts, DI_OPT_LEN);
+X
+X        checkIgnoreList (&diskInfo [idx]);
+X        checkIncludeList (&diskInfo [idx]);
+X
+X        if (debug > 0)
+X        {
+X            printf ("mnt:%s - %s : %s\n", diskInfo [idx].name,
+X                    diskInfo [idx].special, diskInfo [idx].fsType);
+X        }
+X    }
+X
+X    endmntent (f);
+X    return 0;
+X}
+X
+X#endif /* HAS_GETMNTENT && HAS_SETMNTENT && HAS_ENDMNTENT */
+X
+X#if defined (HAS_GETMNTINFO)
+X
+X/*
+X * getDiskEntries
+X *
+X * OSF/1 does this with a system call and library routine
+X *
+X *                  [mogul@wrl.dec.com (Jeffrey Mogul)]
+X */
+X
+X#if defined (INITMOUNTNAMES)
+Xstatic char *mnt_names [] = INITMOUNTNAMES;
+X# define MNT_NUMTYPES (MOUNT_MAXTYPE + 1)
+X#endif
+X
+X    /* osf/1 mount flags start w/M_ vs. MNT_     */
+X    /* this saves us from lots of duplicate code */
+X#if defined (M_RDONLY)
+X# define MNT_RDONLY M_RDONLY
+X#endif
+X#if defined (M_SYNCHRONOUS)
+X# define MNT_SYNCHRONOUS M_SYNCHRONOUS
+X#endif
+X#if defined (M_NOEXEC)
+X# define MNT_NOEXEC M_NOEXEC
+X#endif
+X#if defined (M_NOSUID)
+X# define MNT_NOSUID M_NOSUID
+X#endif
+X#if defined (M_NODEV)
+X# define MNT_NODEV M_NODEV
+X#endif
+X#if defined (M_GRPID)
+X# define MNT_GRPID M_GRPID
+X#endif
+X#if defined (M_EXPORTED)
+X# define MNT_EXPORTED M_EXPORTED
+X#endif
+X#if defined (M_EXRDONLY)
+X# define MNT_EXRDONLY M_EXRDONLY
+X#endif
+X#if defined (M_EXRDMOSTLY)
+X# define MNT_EXRDMOSTLY M_EXRDMOSTLY
+X#endif
+X#if defined (M_SECURE)
+X# define MNT_SECURE M_SECURE
+X#endif
+X#if defined (M_LOCAL)
+X# define MNT_LOCAL M_LOCAL
+X#endif
+X#if defined (M_QUOTA)
+X# define MNT_QUOTA M_QUOTA
+X#endif
+X
+Xstatic int
+XgetDiskEntries ()
+X{
+X    int             count;
+X    int             idx;
+X    int             len;
+X    short           fstype;
+X    struct statfs   *mntbufp;
+X    double          mult;
+X
+X    count = getmntinfo (&mntbufp, MNT_WAIT);
+X    if (count < 1)
+X    {
+X        fprintf (stderr, "Unable to do getmntinfo () errno %d\n", errno);
+X        return -1;
+X    }
+X
+X    diCount = count;
+X    diskInfo = (DiskInfo *) malloc (sizeof (DiskInfo) * count);
+X    if (diskInfo == (DiskInfo *) NULL)
+X    {
+X        fprintf (stderr, "malloc failed for diskInfo. errno %d\n", errno);
+X        return -1;
+X    }
+X    memset ((char *) diskInfo, '\0', sizeof (DiskInfo) * count);
+X
+X    if (debug > 1)
+X    {
+X        printf ("type_len %d name_len %d spec_name_len %d\n", DI_TYPE_LEN,
+X                DI_NAME_LEN, DI_SPEC_NAME_LEN);
+X    }
+X
+X    for (idx = 0; idx < count; idx++)
+X    {
+X        diskInfo [idx].printFlag = DI_OK;
+X        diskInfo [idx].isLocal = FALSE;
+X#if defined (MNT_LOCAL)
+X        if ((mntbufp [idx].f_flags & MNT_LOCAL) == MNT_LOCAL)
+X        {
+X            diskInfo [idx].isLocal = TRUE;
+X        }
+X#endif
+X
+X        if (diskInfo [idx].isLocal == FALSE &&
+X                (flags & DI_F_LOCAL_ONLY) == DI_F_LOCAL_ONLY)
+X        {
+X            diskInfo [idx].printFlag = DI_IGNORE;
+X            if (debug > 2)
+X            {
+X                printf ("mnt: ignore: remote: %s\n",
+X                        diskInfo [idx].name);
+X            }
+X        }
+X
+X        strncpy (diskInfo [idx].special, mntbufp [idx].f_mntfromname,
+X                DI_SPEC_NAME_LEN);
+X        strncpy (diskInfo [idx].name, mntbufp [idx].f_mntonname, DI_NAME_LEN);
+X
+X        mult = 1.0;
+X
+X#  if defined (HAS_GETMNTINFO_FSIZE) /* 1.x */
+X        mult = (double) mntbufp [idx].f_fsize / dispBlockSize;
+X#  endif
+X#  if defined (HAS_GETMNTINFO_BSIZE) /* 2.x */
+X        mult = (double) mntbufp [idx].f_bsize / dispBlockSize;
+X#  endif
+X        diskInfo [idx].totalBlocks = ((double) (_s_fs_size_t) mntbufp [idx].f_blocks * mult);
+X        diskInfo [idx].freeBlocks = ((double) (_s_fs_size_t) mntbufp [idx].f_bfree * mult);
+X        diskInfo [idx].availBlocks = ((double) (_s_fs_size_t) mntbufp [idx].f_bavail * mult);
+X
+X        diskInfo [idx].totalInodes = mntbufp [idx].f_files;
+X        diskInfo [idx].freeInodes = mntbufp [idx].f_ffree;
+X        diskInfo [idx].availInodes = mntbufp [idx].f_ffree;
+X
+X        fstype = mntbufp [idx].f_type;
+X# if ! defined (I_SYS_FSTYP) && ! defined (INITMOUNTNAMES) && \
+X    ! defined (HAS_GETMNTINFO_FSTYPENAME)
+X        if ((fstype >= 0) && (fstype <= MOUNT_MAXTYPE))
+X        {
+X            switch (fstype)
+X            {
+X#  if defined (MOUNT_NONE)
+X                case MOUNT_NONE:         /* No Filesystem */
+X                {
+X                    strncpy (diskInfo [idx].fsType, "none", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_UFS)
+X                case MOUNT_UFS:         /* UNIX "Fast" Filesystem */
+X                {
+X                    strncpy (diskInfo [idx].fsType, "ufs", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_NFS)
+X                case MOUNT_NFS:         /* Network Filesystem */
+X                {
+X                    strncpy (diskInfo [idx].fsType, "nfs", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_MFS)
+X                case MOUNT_MFS:         /* Memory Filesystem */
+X                {
+X                    strncpy (diskInfo [idx].fsType, "mfs", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_MSDOS)
+X                case MOUNT_MSDOS:       /* MSDOS Filesystem */
+X                {
+X                    strncpy (diskInfo [idx].fsType, "msdos", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_LFS)
+X                case MOUNT_LFS:
+X                {
+X                    strncpy (diskInfo [idx].fsType, "lfs", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_LOFS)
+X                case MOUNT_LOFS:
+X                {
+X                    strncpy (diskInfo [idx].fsType, "lofs", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_FDESC)
+X                case MOUNT_FDESC:
+X                {
+X                    strncpy (diskInfo [idx].fsType, "fdesc", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_PORTAL)
+X                case MOUNT_PORTAL:
+X                {
+X                    strncpy (diskInfo [idx].fsType, "portal", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_NULL)
+X                case MOUNT_NULL:
+X                {
+X                    strncpy (diskInfo [idx].fsType, "null", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_UMAP)
+X                case MOUNT_UMAP:
+X                {
+X                    strncpy (diskInfo [idx].fsType, "umap", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_KERNFS)
+X                case MOUNT_KERNFS:
+X                {
+X                    strncpy (diskInfo [idx].fsType, "kernfs", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_PROCFS)
+X                case MOUNT_PROCFS:      /* proc filesystem */
+X                {
+X                    strncpy (diskInfo [idx].fsType, "pfs", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_AFS)
+X                case MOUNT_AFS:
+X                {
+X                    strncpy (diskInfo [idx].fsType, "afs", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_ISOFS)
+X                case MOUNT_ISOFS:       /* iso9660 cdrom */
+X                {
+X                    strncpy (diskInfo [idx].fsType, "iso9660fs", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_ISO9660) && ! defined (MOUNT_CD9660)
+X                case MOUNT_ISO9660:       /* iso9660 cdrom */
+X                {
+X                    strncpy (diskInfo [idx].fsType, "iso9660", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_CD9660)
+X                case MOUNT_CD9660:       /* iso9660 cdrom */
+X                {
+X                    strncpy (diskInfo [idx].fsType, "cd9660", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X
+X#  if defined (MOUNT_UNION)
+X                case MOUNT_UNION:
+X                {
+X                    strncpy (diskInfo [idx].fsType, "union", DI_TYPE_LEN);
+X                    break;
+X                }
+X#  endif
+X            } /* switch on mount type */
+X        }
+X# else
+X#  if defined (HAS_GETMNTINFO_FSTYPENAME)
+X        strncpy (diskInfo [idx].fsType, mntbufp [idx].f_fstypename, DI_TYPE_LEN);
+X#  else
+X            /* could use getvfsbytype here... */
+X        if ((fstype >= 0) && (fstype < MNT_NUMTYPES))
+X        {
+X            strncpy (diskInfo [idx].fsType, mnt_names [fstype], DI_TYPE_LEN);
+X        }
+X        else
+X        {
+X            sprintf (diskInfo [idx].fsType, DI_UNKNOWN_FSTYPE, fstype);
+X        }
+X#  endif
+X# endif /* has fs_types.h */
+X
+X#if defined (MNT_RDONLY)
+X        if ((mntbufp [idx].f_flags & MNT_RDONLY) == MNT_RDONLY)
+X        {
+X            strcat (diskInfo [idx].options, "ro,");
+X        }
+X        else
+X        {
+X            strcat (diskInfo [idx].options, "rw,");
+X        }
+X#endif
+X#if defined (MNT_SYNCHRONOUS)
+X        if ((mntbufp [idx].f_flags & MNT_SYNCHRONOUS) == MNT_SYNCHRONOUS)
+X        {
+X            strcat (diskInfo [idx].options, "sync,");
+X        }
+X#endif
+X#if defined (MNT_NOEXEC)
+X        if ((mntbufp [idx].f_flags & MNT_NOEXEC) == MNT_NOEXEC)
+X        {
+X            strcat (diskInfo [idx].options, "noexec,");
+X        }
+X#endif
+X#if defined (MNT_NOSUID)
+X        if ((mntbufp [idx].f_flags & MNT_NOSUID) != MNT_NOSUID)
+X        {
+X            strcat (diskInfo [idx].options, "suid,");
+X        }
+X#endif
+X#if defined (MNT_NODEV)
+X        if ((mntbufp [idx].f_flags & MNT_NODEV) == MNT_NODEV)
+X        {
+X            strcat (diskInfo [idx].options, "nodev,");
+X        }
+X#endif
+X#if defined (MNT_GRPID)
+X        if ((mntbufp [idx].f_flags & MNT_GRPID) == MNT_GRPID)
+X        {
+X            strcat (diskInfo [idx].options, "grpid,");
+X        }
+X#endif
+X#if defined (MNT_UNION)
+X        if ((mntbufp [idx].f_flags & MNT_UNION) == MNT_UNION)
+X        {
+X            strcat (diskInfo [idx].options, "union,");
+X        }
+X#endif
+X#if defined (MNT_ASYNC)
+X        if ((mntbufp [idx].f_flags & MNT_ASYNC) == MNT_ASYNC)
+X        {
+X            strcat (diskInfo [idx].options, "async,");
+X        }
+X#endif
+X#if defined (MNT_EXRDONLY)
+X        if ((mntbufp [idx].f_flags & MNT_EXRDONLY) == MNT_EXRDONLY)
+X        {
+X            strcat (diskInfo [idx].options, "exported ro,");
+X        }
+X#endif
+X#if defined (MNT_EXPORTED)
+X        if ((mntbufp [idx].f_flags & MNT_EXPORTED) == MNT_EXPORTED)
+X        {
+X            strcat (diskInfo [idx].options, "exported,");
+X        }
+X#endif
+X#if defined (MNT_EXRDMOSTLY)
+X        if ((mntbufp [idx].f_flags & MNT_EXRDMOSTLY) == MNT_EXRDMOSTLY)
+X        {
+X                /* what's read-mostly ? */
+X            strcat (diskInfo [idx].options, "exported read-mostly,");
+X        }
+X#endif
+X#if defined (MNT_DEFEXPORTED)
+X        if ((mntbufp [idx].f_flags & MNT_DEFEXPORTED) == MNT_DEFEXPORTED)
+X        {
+X                /* what's this ? */
+X            strcat (diskInfo [idx].options, "exported world,");
+X        }
+X#endif
+X#if defined (MNT_EXPORTANON)
+X        if ((mntbufp [idx].f_flags & MNT_EXPORTANON) == MNT_EXPORTANON)
+X        {
+X            strcat (diskInfo [idx].options, "exported anon,");
+X        }
+X#endif
+X#if defined (MNT_EXKERB)
+X        if ((mntbufp [idx].f_flags & MNT_EXKERB) == MNT_EXKERB)
+X        {
+X            strcat (diskInfo [idx].options, "exported kerberos,");
+X        }
+X#endif
+X#if defined (MNT_LOCAL)
+X        if ((mntbufp [idx].f_flags & MNT_LOCAL) == MNT_LOCAL)
+X        {
+X            strcat (diskInfo [idx].options, "local,");
+X        }
+X#endif
+X#if defined (MNT_QUOTA)
+X        if ((mntbufp [idx].f_flags & MNT_QUOTA) == MNT_QUOTA)
+X        {
+X            strcat (diskInfo [idx].options, "quota,");
+X        }
+X#endif
+X#if defined (MNT_ROOTFS)
+X        if ((mntbufp [idx].f_flags & MNT_ROOTFS) == MNT_ROOTFS)
+X        {
+X            strcat (diskInfo [idx].options, "root,");
+X        }
+X#endif
+X#if defined (MNT_USER)
+X        if ((mntbufp [idx].f_flags & MNT_USER) == MNT_USER)
+X        {
+X            strcat (diskInfo [idx].options, "user,");
+X        }
+X#endif
+X#if defined (MNT_SECURE)
+X        if ((mntbufp [idx].f_flags & MNT_SECURE) == MNT_SECURE)
+X        {
+X            strcat (diskInfo [idx].options, "secure,");
+X        }
+X#endif
+X
+X        len = strlen (diskInfo [idx].options);
+X        if (len > 0)
+X        {
+X            --len;
+X        }
+X        if (diskInfo [idx].options [len]==',')
+X        {
+X            diskInfo [idx].options [len] = '\0';
+X        }
+X
+X        if (debug > 1)
+X        {
+X            printf ("%s: %s\n", diskInfo [idx].name, diskInfo [idx].fsType);
+X            printf ("\tblocks: tot:%ld free:%ld avail:%ld\n",
+X                    mntbufp [idx].f_blocks, mntbufp [idx].f_bfree,
+X                    mntbufp [idx].f_bavail);
+X            printf ("\tmult: %f\n", mult);
+X# if defined (HAS_GETMNTINFO_FSIZE)
+X            printf ("\tfsize:%ld \n", mntbufp [idx].f_fsize);
+X            printf ("\tbsize:%ld \n", mntbufp [idx].f_bsize);
+X# endif
+X# if defined (HAS_GETMNTINFO_BSIZE)
+X            printf ("\tbsize:%ld \n", mntbufp [idx].f_bsize);
+X            printf ("\tiosize:%ld \n", mntbufp [idx].f_iosize);
+X# endif
+X            printf ("\tinodes: tot:%ld free:%ld\n",
+X                    mntbufp [idx].f_files, mntbufp [idx].f_ffree);
+X        }
+X    }
+X
+X    free ((char *) mntbufp);  /* man page says this can't be freed. */
+X                              /* is it ok to try?                   */
+X    return 0;
+X}
+X
+X/* this is a no-op; we have already done all the work */
+Xstatic void
+XgetDiskInfo ()
+X{
+X}
+X
+X#endif /* HAS_GETMNTINFO */
+X
+X#if defined (HAS_GETMNT)
+X
+X/*
+X * getDiskEntries
+X *
+X * ULTRIX does this with a system call.  The system call allows one
+X * to retrieve the information in a series of calls, but coding that
+X * looks a little tricky; I just allocate a huge buffer and do it in
+X * one shot.
+X *
+X *                  [mogul@wrl.dec.com (Jeffrey Mogul)]
+X */
+X
+Xstatic int
+XgetDiskEntries ()
+X{
+X    int             count;
+X    int             bufsize;
+X    int             idx;
+X    short           fstype;
+X    struct fs_data  *fsdbuf;
+X    int             start;
+X    int             len;
+X
+X
+X    bufsize = NMOUNT * sizeof (struct fs_data);  /* enough for max # mounts */
+X    fsdbuf = (struct fs_data *) malloc (bufsize);
+X    if (fsdbuf == (struct fs_data *) NULL)
+X    {
+X        fprintf (stderr, "malloc (%d) for getmnt () failed errno %d\n",
+X                 bufsize, errno);
+X        return -1;
+X    }
+X
+X    start = 0;
+X    count = getmnt (&start, fsdbuf, bufsize, STAT_MANY, 0);
+X    if (count < 1)
+X    {
+X        fprintf (stderr, "Unable to do getmnt () [= %d] errno %d\n",
+X                 count, errno);
+X        free ((char *) fsdbuf);
+X        return -1;
+X    }
+X
+X    diCount = count;
+X    diskInfo = (DiskInfo *) malloc (sizeof (DiskInfo) * count);
+X    if (diskInfo == (DiskInfo *) NULL)
+X    {
+X        fprintf (stderr, "malloc failed for diskInfo. errno %d\n", errno);
+X        free ((char *) fsdbuf);
+X        return -1;
+X    }
+X    memset ((char *) diskInfo, '\0', sizeof (DiskInfo) * count);
+X
+X    for (idx = 0; idx < count; idx++)
+X    {
+X        diskInfo [idx].printFlag = DI_OK;
+X        diskInfo [idx].isLocal = TRUE;
+X
+X        if ((fsdbuf [idx].fd_req.flags & M_LOCAL) != M_LOCAL)
+X        {
+X            diskInfo [idx].isLocal = FALSE;
+X        }
+X
+X        if (diskInfo [idx].isLocal == FALSE &&
+X                (flags & DI_F_LOCAL_ONLY) == DI_F_LOCAL_ONLY)
+X        {
+X            diskInfo [idx].printFlag = DI_IGNORE;
+X            if (debug > 2)
+X            {
+X                printf ("mnt: ignore: remote: %s\n",
+X                        diskInfo [idx].name);
+X            }
+X        }
+X
+X        strncpy (diskInfo [idx].special, fsdbuf [idx].fd_devname, DI_SPEC_NAME_LEN);
+X        strncpy (diskInfo [idx].name, fsdbuf [idx].fd_path, DI_NAME_LEN);
+X
+X            /* ULTRIX keeps these fields in units of 1K byte */
+X        diskInfo [idx].totalBlocks = fsdbuf [idx].fd_btot;
+X        diskInfo [idx].freeBlocks = fsdbuf [idx].fd_bfree;
+X        diskInfo [idx].availBlocks = (int) fsdbuf [idx].fd_bfreen;
+X
+X        diskInfo [idx].totalInodes = fsdbuf [idx].fd_gtot;
+X        diskInfo [idx].freeInodes = fsdbuf [idx].fd_gfree;
+X        diskInfo [idx].availInodes = fsdbuf [idx].fd_gfree;
+X
+X        fstype = fsdbuf [idx].fd_fstype;
+X        if (fstype == GT_UNKWN)
+X        {
+X            diskInfo [idx].printFlag = DI_IGNORE;
+X            if (debug > 2)
+X            {
+X                printf ("mnt: ignore: disk type unknown: %s\n",
+X                        diskInfo [idx].name);
+X            }
+X        }
+X        else if ((fstype > 0) && (fstype < GT_NUMTYPES))
+X        {
+X            strncpy (diskInfo [idx].fsType, gt_names [fstype], DI_TYPE_LEN);
+X        }
+X        else
+X        {
+X            sprintf (diskInfo [idx].fsType, "Unknown fstyp %.2d", fstype);
+X        }
+X
+X        if ((fsdbuf [idx].fd_req.flags & M_RONLY) == M_RONLY)
+X        {
+X            strcat (diskInfo [idx].options, "ro,");
+X        }
+X        else
+X        {
+X            strcat (diskInfo [idx].options, "rw,");
+X        }
+X        if ((fsdbuf [idx].fd_req.flags & M_NOSUID) != M_NOSUID)
+X        {
+X            strcat (diskInfo [idx].options, "suid,");
+X        }
+X        if ((fsdbuf [idx].fd_req.flags & M_QUOTA) == M_QUOTA)
+X        {
+X            strcat (diskInfo [idx].options, "quota,");
+X        }
+X        if ((fsdbuf [idx].fd_req.flags & M_LOCAL) != M_LOCAL)
+X        {
+X            strcat (diskInfo [idx].options, "remote,");
+X        }
+X        if ((fsdbuf [idx].fd_req.flags & M_NODEV) == M_NODEV)
+X        {
+X            strcat (diskInfo [idx].options, "nodev,");
+X        }
+X        if ((fsdbuf [idx].fd_req.flags & M_FORCE) == M_FORCE)
+X        {
+X            strcat (diskInfo [idx].options, "force,");
+X        }
+X        if ((fsdbuf [idx].fd_req.flags & M_SYNC) == M_SYNC)
+X        {
+X            strcat (diskInfo [idx].options, "sync,");
+X        }
+X        if ((fsdbuf [idx].fd_req.flags & M_NOCACHE) == M_NOCACHE)
+X        {
+X            strcat (diskInfo [idx].options, "nocache,");
+X        }
+X        if ((fsdbuf [idx].fd_req.flags & M_EXPORTED) == M_EXPORTED)
+X        {
+X            strcat (diskInfo [idx].options, "exported," );
+X        }
+X        if ((fsdbuf [idx].fd_req.flags & M_EXRONLY) == M_EXRONLY)
+X        {
+X            strcat (diskInfo [idx].options, "exported ro,");
+X        }
+X        if ((fsdbuf [idx].fd_req.flags & M_NOEXEC) == M_NOEXEC)
+X        {
+X            strcat (diskInfo [idx].options, "noexec,");
+X        }
+X
+X        len = strlen (diskInfo [idx].options);
+X        if (len > 0)
+X        {
+X            --len;
+X        }
+X        if (diskInfo [idx].options [len]==',')
+X        {
+X            diskInfo [idx].options [len] = '\0';
+X        }
+X
+X        if (debug > 1)
+X        {
+X            printf ("%s: %s\n", diskInfo [idx].name, diskInfo [idx].fsType);
+X            printf ("\tblocks: tot:%ld free:%ld avail:%ld\n",
+X                    fsdbuf [idx].fd_btot, fsdbuf [idx].fd_bfree,
+X                    (int) fsdbuf [idx].fd_bfreen);
+X            printf ("\tinodes: tot:%ld free:%ld\n",
+X                    fsdbuf [idx].fd_gtot, fsdbuf [idx].fd_gfree);
+X        }
+X    }
+X
+X    free ((char *) fsdbuf);
+X    return 0;
+X}
+X
+X/* this is a no-op; we have already done all the work */
+Xstatic void
+XgetDiskInfo ()
+X{
+X}
+X
+X#endif /* HAS_GETMNT */
+X
+X
+X#if defined (HAS_MNTCTL)
+X
+X/*
+X * getDiskEntries
+X *
+X * AIX V3.2 uses mntctl to find out about mounted file systems
+X *
+X */
+X
+X# define NUM_AIX_FSTYPES         6
+Xstatic char *AIX_fsType [NUM_AIX_FSTYPES] =
+X    { "oaix", "", "nfs", "jfs", "", "cdrom" };
+X
+X/*
+X * from xfsm-1.80:
+X *
+X * MNT_AIX - "aix"
+X * MNT_NFS - "nfs"
+X * MNT_JFS - "jfs"
+X * MNT_CDROM - "cdrom"
+X * other - "user defined"
+X *
+X */
+X
+Xstatic int
+XgetDiskEntries ()
+X{
+X    int             num;        /* number of vmount structs returned    */
+X    char            *vmbuf;     /* buffer for vmount structs returned   */
+X    int             vmbufsz;    /* size in bytes of vmbuf               */
+X    int             i;          /* index for looping and stuff          */
+X    char            *bufp;      /* pointer into vmbuf                   */
+X    struct vmount   *vmtp;      /* pointer into vmbuf                   */
+X    struct vfs_ent  *ve;        /* pointer for file system type entry   */
+X    int             len;
+X
+X
+X    i = 0;
+X    vmbufsz = sizeof (struct vmount) * DI_FSMAGIC; /* initial vmount buffer */
+X
+X    do
+X    {
+X        if ((vmbuf = (char *) malloc (vmbufsz)) == (char *) NULL)
+X        {
+X            fprintf (stderr, "malloc (%d) for mntctl() failed errno %d\n",
+X                    vmbufsz, errno);
+X            return -1;
+X        }
+X
+X        num = mntctl (MCTL_QUERY, vmbufsz, vmbuf);
+X            /*
+X             * vmbuf is too small, could happen for
+X             * following reasons:
+X             * - inital buffer is too small
+X             * - newly mounted file system
+X             */
+X        if (num == 0)
+X        {
+X            memcpy (&vmbufsz, vmbuf, sizeof (vmbufsz)); /* see mntctl(2) */
+X            if (debug > 0)
+X            {
+X                printf ("vmbufsz too small, new size: %d\n", vmbufsz);
+X            }
+X            free ((char *) vmbuf); /* free this last, it's still being used! */
+X            ++i;
+X        }
+X    } while (num == 0 && i < DI_RETRY_COUNT);
+X
+X    if (i >= DI_RETRY_COUNT)
+X    {
+X        free ((char *) vmbuf);
+X        fprintf (stderr, "unable to allocate adequate buffer for mntctl\n");
+X        return -1;
+X    }
+X
+X    switch (num)
+X    {
+X            /* error happened, probably null vmbuf */
+X        case -1:
+X        {
+X            free ((char *) vmbuf);
+X            fprintf (stderr,"%s errno %d\n", strerror (errno), errno);
+X            return -1;
+X        }
+X
+X            /* 'num' vmount structs returned in vmbuf */
+X        default:
+X        {
+X            diCount = num;
+X            diskInfo = (DiskInfo *) calloc (sizeof (DiskInfo), diCount);
+X            if (diskInfo == (DiskInfo *) NULL)
+X            {
+X                fprintf (stderr, "malloc failed for diskInfo. errno %d\n", errno);
+X                return -1;
+X            }
+X
+X            bufp = vmbuf;
+X            for (i = 0; i < num; i++)
+X            {
+X                vmtp = (struct vmount *) bufp;
+X                diskInfo [i].printFlag = DI_OK;
+X                diskInfo [i].isLocal = TRUE;
+X
+X                strncpy (diskInfo [i].special,
+X                        (char *) vmt2dataptr (vmtp, VMT_OBJECT),
+X                        DI_SPEC_NAME_LEN);
+X                strncpy (diskInfo [i].name,
+X                        (char *) vmt2dataptr (vmtp, VMT_STUB), DI_NAME_LEN);
+X
+X                ve = getvfsbytype (vmtp->vmt_gfstype);
+X                if (ve == (struct vfs_ent *) NULL || *ve->vfsent_name == '\0')
+X                {
+X                    if (vmtp->vmt_gfstype >= 0 &&
+X                            (vmtp->vmt_gfstype < NUM_AIX_FSTYPES))
+X                    {
+X                        strncpy (diskInfo [i].fsType,
+X                                AIX_fsType [vmtp->vmt_gfstype], DI_TYPE_LEN);
+X                    }
+X                }
+X                else
+X                {
+X                    strncpy (diskInfo [i].fsType, ve->vfsent_name, DI_TYPE_LEN);
+X                }
+X
+X                if ((vmtp->vmt_flags & MNT_READONLY) == MNT_READONLY)
+X                {
+X                    strcat (diskInfo [i].options, "ro,");
+X                }
+X                else
+X                {
+X                    strcat (diskInfo [i].options, "rw,");
+X                }
+X                if ((vmtp->vmt_flags & MNT_NOSUID) != MNT_NOSUID)
+X                {
+X                    strcat (diskInfo [i].options, "suid,");
+X                }
+X                if ((vmtp->vmt_flags & MNT_REMOVABLE) == MNT_REMOVABLE)
+X                {
+X                    strcat (diskInfo [i].options, "removable,");
+X                }
+X                if ((vmtp->vmt_flags & MNT_DEVICE) == MNT_DEVICE)
+X                {
+X                    strcat (diskInfo [i].options, "device,");
+X                }
+X                if ((vmtp->vmt_flags & MNT_REMOTE) == MNT_REMOTE)
+X                {
+X                    strcat (diskInfo [i].options, "remote,");
+X                    diskInfo [i].isLocal = FALSE;
+X                }
+X                if ((vmtp->vmt_flags & MNT_UNMOUNTING) == MNT_UNMOUNTING)
+X                {
+X                    strcat (diskInfo [i].options, "unmounting,");
+X                }
+X                if ((vmtp->vmt_flags & MNT_SYSV_MOUNT) == MNT_SYSV_MOUNT)
+X                {
+X                    strcat (diskInfo [i].options, "sysv mount,");
+X                }
+X                if ((vmtp->vmt_flags & MNT_NODEV) == MNT_NODEV)
+X                {
+X                    strcat (diskInfo [i].options, "nodev,");
+X                }
+X
+X                    /* remove trailing comma */
+X                len = strlen (diskInfo [i].options);
+X                if (len > 0)
+X                {
+X                    --len;
+X                }
+X                if (diskInfo [i].options [len] == ',')
+X                {
+X                    diskInfo [i].options [len] = '\0';
+X                }
+X
+X                strncpy (diskInfo [i].mountTime, ctime (&vmtp->vmt_time),
+X                        DI_MNT_TIME_LEN);
+X
+X                if (diskInfo [i].isLocal == FALSE &&
+X                        (flags & DI_F_LOCAL_ONLY) == DI_F_LOCAL_ONLY)
+X                {
+X                    diskInfo [i].printFlag = DI_IGNORE;
+X                    if (debug > 2)
+X                    {
+X                        printf ("mnt: ignore: remote: %s\n",
+X                                diskInfo [i].name);
+X                    }
+X                }
+X
+X                bufp += vmtp->vmt_length;
+X            }
+X
+X            if (debug > 0)
+X            {
+X                printf ("mnt:%s - %s : %s\n", diskInfo [i].name,
+X                        diskInfo [i].special, diskInfo [i].fsType);
+X                printf ("\t%s\n", (char *) vmt2dataptr (vmtp, VMT_ARGS));
+X            }
+X
+X            break;
+X        } /* valid value returned */
+X    } /* switch on num */
+X}
+X
+X#endif  /* HAS_MNTCTL */
+X
+X
+X#if defined (HAS_STATVFS)
+X
+X/*
+X * getDiskInfo
+X *
+X * SysV.4.  statvfs () returns both the free and available blocks.
+X *
+X */
+X
+Xstatic void
+XgetDiskInfo ()
+X{
+X    int             i;
+X    double          mult;
+X    struct statvfs  statBuf;
+X
+X    for (i = 0; i < diCount; ++i)
+X    {
+X        if (diskInfo [i].isLocal == FALSE &&
+X                (flags & DI_F_LOCAL_ONLY) == DI_F_LOCAL_ONLY)
+X        {
+X            diskInfo [i].printFlag = DI_IGNORE;
+X            if (debug > 2)
+X            {
+X                printf ("mnt: ignore: remote: %s\n",
+X                        diskInfo [i].name);
+X            }
+X        }
+X
+X        if (diskInfo [i].printFlag == DI_OK || (flags & DI_F_ALL) == DI_F_ALL)
+X        {
+X            if (statvfs (diskInfo [i].name, &statBuf) == 0)
+X            {
+X                    /* data general DG/UX 5.4R3.00 sometime returns 0   */
+X                    /* in the fragment size field.                      */
+X                if (statBuf.f_frsize == 0 && statBuf.f_bsize != 0)
+X                {
+X                    mult = (double) (long) statBuf.f_bsize / dispBlockSize;
+X                }
+X                else
+X                {
+X                    mult = (double) (long) statBuf.f_frsize / dispBlockSize;
+X                }
+X
+X                diskInfo [i].totalBlocks = ((double) (_s_fs_size_t) statBuf.f_blocks * mult);
+X                diskInfo [i].freeBlocks = ((double) (_s_fs_size_t) statBuf.f_bfree * mult);
+X                diskInfo [i].availBlocks = ((double) (_s_fs_size_t) statBuf.f_bavail * mult);
+X
+X                diskInfo [i].totalInodes = statBuf.f_files;
+X                diskInfo [i].freeInodes = statBuf.f_ffree;
+X                diskInfo [i].availInodes = statBuf.f_favail;
+X
+X#if defined (HAS_STATVFS_BASETYPE)
+X                strncpy (diskInfo [i].fsType, statBuf.f_basetype, DI_TYPE_LEN);
+X#endif
+X
+X                if (debug > 1)
+X                {
+X                    printf ("%s: %s\n", diskInfo [i].name, diskInfo [i].fsType);
+X                    printf ("\tmult:%f\n", mult);
+X                    printf ("\tbsize:%ld  frsize:%ld\n", statBuf.f_bsize,
+X                            statBuf.f_frsize);
+X#if defined (HAS_64BIT_STATFS_FLDS)
+X                    printf ("\tblocks: tot:%llu free:%lld avail:%llu\n",
+X                            statBuf.f_blocks, statBuf.f_bfree, statBuf.f_bavail);
+X                    printf ("\tinodes: tot:%llu free:%lld avail:%llu\n",
+X                            statBuf.f_files, statBuf.f_ffree, statBuf.f_favail);
+X#else
+X                    printf ("\tblocks: tot:%lu free:%ld avail:%lu\n",
+X                            statBuf.f_blocks, statBuf.f_bfree, statBuf.f_bavail);
+X                    printf ("\tinodes: tot:%lu free:%ld avail:%lu\n",
+X                            statBuf.f_files, statBuf.f_ffree, statBuf.f_favail);
+X#endif
+X                }
+X            }
+X            else
+X            {
+X                fprintf (stderr, "statvfs: %s ", diskInfo [i].name);
+X                perror ("");
+X            }
+X        }
+X    } /* for each entry */
+X}
+X
+X#endif /* HAS_STATVFS */
+X
+X
+X#if defined (HAS_STATFS_BSD) && ! defined (HAS_STATVFS) && \
+X        ! defined (HAS_GETMNTINFO) && ! defined (HAS_GETMNT)
+X
+X/*
+X * getDiskInfo
+X *
+X * SunOS/BSD/Pyramid
+X *
+X */
+X
+Xstatic void
+XgetDiskInfo ()
+X{
+X    int             i;
+X    double          mult;
+X    struct statfs   statBuf;
+X
+X    for (i = 0; i < diCount; ++i)
+X    {
+X        if (diskInfo [i].printFlag == DI_OK || (flags & DI_F_ALL) == DI_F_ALL)
+X        {
+X            if (statfs (diskInfo [i].name, &statBuf) == 0)
+X            {
+X                mult = (double) statBuf.f_bsize / dispBlockSize;
+X                diskInfo [i].totalBlocks = ((double) (_s_fs_size_t) statBuf.f_blocks * mult);
+X                diskInfo [i].freeBlocks = ((double) (_s_fs_size_t) statBuf.f_bfree * mult);
+X                diskInfo [i].availBlocks = ((double) (_s_fs_size_t) statBuf.f_bavail * mult);
+X
+X                diskInfo [i].totalInodes = statBuf.f_files;
+X                diskInfo [i].freeInodes = statBuf.f_ffree;
+X                diskInfo [i].availInodes = statBuf.f_ffree;
+X# if defined (HAS_SYSFS)
+X                sysfs (GETFSTYP, statBuf.f_fstyp, diskInfo [i].fsType);
+X# endif
+X
+X                if (debug > 1)
+X                {
+X                    printf ("%s: %s\n", diskInfo [i].name, diskInfo [i].fsType);
+X                    printf ("\tmult:%f\n", mult);
+X                    printf ("\tbsize:%ld\n", statBuf.f_bsize);
+X                    printf ("\tblocks: tot:%ld free:%ld avail:%ld\n",
+X                            statBuf.f_blocks, statBuf.f_bfree, statBuf.f_bavail);
+X                    printf ("\tinodes: tot:%ld free:%ld\n",
+X                            statBuf.f_files, statBuf.f_ffree);
+X                }
+X            } /* if we got the info */
+X            else
+X            {
+X                fprintf (stderr, "statfs: %s ", diskInfo [i].name);
+X                perror ("");
+X            }
+X        }
+X    } /* for each entry */
+X}
+X
+X#endif /* HAS_STATFS_BSD */
+X
+X#if defined (HAS_STATFS_SYSV3) && ! defined (HAS_STATVFS) && \
+X        ! defined (HAS_GETMNTINFO) && ! defined (HAS_GETMNT)
+X
+X/*
+X * getDiskInfo
+X *
+X * SysV.3.  We don't have available blocks; just set it to free blocks.
+X * The sysfs () call is used to get the disk type name.
+X *
+X */
+X
+Xstatic void
+XgetDiskInfo ()
+X{
+X    int             i;
+X    double          mult;
+X    struct statfs   statBuf;
+X
+X    for (i = 0; i < diCount; ++i)
+X    {
+X        if (diskInfo [i].printFlag == DI_OK || (flags & DI_F_ALL) == DI_F_ALL)
+X        {
+X            if (statfs (diskInfo [i].name, &statBuf, sizeof (statBuf), 0) == 0)
+X            {
+X# if defined (HAS_STATFS_FRSIZE)
+X                if (statBuf.f_frsize == 0 && statBuf.f_bsize != 0)
+X                {
+X                    mult = (double) (long) statBuf.f_bsize / dispBlockSize;
+X                }
+X                else
+X                {
+X                    mult = (double) (long) statBuf.f_frsize / dispBlockSize;
+X                }
+X# else
+X                mult = (double) UBSIZE / dispBlockSize;
+X# endif
+X                diskInfo [i].totalBlocks = ((double) (_s_fs_size_t) statBuf.f_blocks * mult);
+X                diskInfo [i].freeBlocks = ((double) (_s_fs_size_t) statBuf.f_bfree * mult);
+X                diskInfo [i].availBlocks = ((double) (_s_fs_size_t) statBuf.f_bfree * mult);
+X
+X                diskInfo [i].totalInodes = statBuf.f_files;
+X                diskInfo [i].freeInodes = statBuf.f_ffree;
+X                diskInfo [i].availInodes = statBuf.f_ffree;
+X# if defined (HAS_SYSFS)
+X                sysfs (GETFSTYP, statBuf.f_fstyp, diskInfo [i].fsType);
+X# endif
+X
+X                if (debug > 1)
+X                {
+X                    printf ("%s: %s\n", diskInfo [i].name, diskInfo [i].fsType);
+X                    printf ("\tmult:%f\n", mult);
+X# if defined (HAS_STATFS_FRSIZE)
+X                    printf ("\tbsize:%ld\n", statBuf.f_bsize);
+X                    printf ("\tfrsize:%ld\n", statBuf.f_frsize);
+X# else
+X                    printf ("\tUBSIZE:%ld\n", UBSIZE);
+X# endif
+X                    printf ("\tblocks: tot:%ld free:%ld\n",
+X                            statBuf.f_blocks, statBuf.f_bfree);
+X                    printf ("\tinodes: tot:%ld free:%ld\n",
+X                            statBuf.f_files, statBuf.f_ffree);
+X                }
+X            } /* if we got the info */
+X            else
+X            {
+X                fprintf (stderr, "statfs: %s ", diskInfo [i].name);
+X                perror ("");
+X            }
+X        }
+X    } /* for each entry */
+X}
+X
+X#endif /* HAS_STATFS_SYSV3 */
+X
+X
+X#if defined (HAS_GETDISKFREESPACE)
+X
+X/*
+X * getDiskInfo
+X *
+X * Windows
+X *
+X */
+X
+X# define NUM_MSDOS_FSTYPES          7
+Xstatic char *MSDOS_diskType [NUM_MSDOS_FSTYPES] =
+X    { "unknown", "", "removable", "fixed", "remote", "cdrom", "ramdisk" };
+X# define MSDOS_BUFFER_SIZE          128
+X# define BYTES_PER_LOGICAL_DRIVE    4
+X
+Xstatic int
+XgetDiskEntries ()
+X{
+X    int             i;
+X    int             diskflag;
+X    int             rc;
+X    char            *p;
+X    char            buff [MSDOS_BUFFER_SIZE];
+X
+X
+X    diskflag = DI_IGNORE;
+X    rc = GetLogicalDriveStrings (MSDOS_BUFFER_SIZE, buff);
+X    diCount = rc / BYTES_PER_LOGICAL_DRIVE;
+X
+X    diskInfo = (DiskInfo *) calloc (sizeof (DiskInfo), diCount);
+X    if (diskInfo == (DiskInfo *) NULL)
+X    {
+X        fprintf (stderr, "malloc failed for diskInfo. errno %d\n", errno);
+X        return -1;
+X    }
+X
+X    for (i = 0; i < diCount; ++i)
+X    {
+X        p = buff + (BYTES_PER_LOGICAL_DRIVE * i);
+X        strncpy (diskInfo [i].name, p, DI_NAME_LEN);
+X        rc = GetDriveType (p);
+X        diskInfo [i].printFlag = DI_OK;
+X
+X        if (rc == DRIVE_NO_ROOT_DIR)
+X        {
+X            diskInfo [i].printFlag = DI_BAD;
+X        }
+X
+X            /* assume that any removable drives before the  */
+X            /* first non-removable disk are floppies...     */
+X        else if (rc == DRIVE_REMOVABLE)
+X        {
+X            diskInfo [i].printFlag = diskflag;
+X        }
+X        else
+X        {
+X            diskflag = DI_OK;
+X        }
+X
+X        if (rc != DRIVE_REMOTE)
+X        {
+X            diskInfo [i].isLocal = TRUE;
+X        }
+X        /* strncpy (diskInfo [i].fsType, MSDOS_diskType [rc], DI_TYPE_LEN); */
+X    } /* for each mounted drive */
+X
+X    return diCount;
+X}
+X
+X/*
+X * getDiskInfo
+X *
+X * Windows
+X *
+X */
+X
+Xstatic void
+XgetDiskInfo ()
+X{
+X    int                 i;
+X    int                 rc;
+X    double              mult;
+X    unsigned long       sectorspercluster;
+X    unsigned long       bytespersector;
+X    unsigned long       totalclusters;
+X    unsigned long       freeclusters;
+X    char                tbuff [MSDOS_BUFFER_SIZE];
+X    char                volName [MSDOS_BUFFER_SIZE];
+X    char                fsName [MSDOS_BUFFER_SIZE];
+X    DWORD               serialNo;
+X    DWORD               maxCompLen;
+X    DWORD               fsFlags;
+X
+X
+X    for (i = 0; i < diCount; ++i)
+X    {
+X        if (diskInfo [i].isLocal == FALSE &&
+X                (flags & DI_F_LOCAL_ONLY) == DI_F_LOCAL_ONLY)
+X        {
+X            diskInfo [i].printFlag = DI_IGNORE;
+X            if (debug > 2)
+X            {
+X                printf ("mnt: ignore: remote: %s\n",
+X                        diskInfo [i].name);
+X            }
+X        }
+X
+X        if (diskInfo [i].printFlag == DI_OK || (flags & DI_F_ALL) == DI_F_ALL)
+X        {
+X            rc = GetVolumeInformation (diskInfo [i].name,
+X                    volName, MSDOS_BUFFER_SIZE, &serialNo, &maxCompLen,
+X                    &fsFlags, fsName, MSDOS_BUFFER_SIZE);
+X            /* strcpy (tbuff, diskInfo [i].fsType); */
+X            /* strcat (tbuff, " "); */
+X            strncpy (diskInfo [i].fsType, fsName, DI_TYPE_LEN);
+X            strncpy (diskInfo [i].special, volName, DI_SPEC_NAME_LEN);
+X
+X            rc = GetDiskFreeSpace (diskInfo [i].name,
+X                    (LPDWORD) &sectorspercluster, (LPDWORD) &bytespersector,
+X                    (LPDWORD) &freeclusters, (LPDWORD) &totalclusters);
+X
+X            if (rc > 0)
+X            {
+X                mult = (double) (sectorspercluster *
+X                        bytespersector) / dispBlockSize;
+X                diskInfo [i].totalBlocks = ((double) (_s_fs_size_t) totalclusters * mult);
+X                diskInfo [i].freeBlocks = ((double) (_s_fs_size_t) freeclusters * mult);
+X                diskInfo [i].availBlocks = ((double) (_s_fs_size_t) freeclusters * mult);
+X
+X                diskInfo [i].totalInodes = 0;
+X                diskInfo [i].freeInodes = 0;
+X                diskInfo [i].availInodes = 0;
+X
+X                if (debug > 1)
+X                {
+X                    printf ("%s: %s\n", diskInfo [i].name, diskInfo [i].fsType);
+X                    printf ("\ts/c:%ld  b/s:%ld\n", sectorspercluster,
+X                        bytespersector);
+X                    printf ("\tmult:%f\n", mult);
+X                    printf ("\tclusters: tot:%ld free:%ld\n",
+X                        totalclusters, freeclusters);
+X                }
+X            }
+X            else
+X            {
+X                diskInfo [i].printFlag = DI_BAD;
+X                if (debug)
+X                {
+X                    printf ("disk %s; could not get disk space\n",
+X                            diskInfo [i].name);
+X                }
+X            }
+X        } /* if printable drive */
+X    } /* for each mounted drive */
+X}
+X
+X#endif /* HAS_GETDISKFREESPACE */
+END_OF_FILE
+if test 97566 -ne `wc -c <'di.c'`; then
+    echo shar: \"'di.c'\" unpacked with wrong size!
+fi
+# end of 'di.c'
+fi
+echo shar: End of archive 2 \(of 3\).
+cp /dev/null ark2isdone
+MISSING=""
+for I in 1 2 3 ; do
+    if test ! -f ark${I}isdone ; then
+       MISSING="${MISSING} ${I}"
+    fi
+done
+if test "${MISSING}" = "" ; then
+    echo You have unpacked all 3 archives.
+    rm -f ark[1-9]isdone
+else
+    echo You still need to unpack the following archives:
+    echo "        " ${MISSING}
+fi
+##  End of shell archive.
+exit 0
+
This page took 0.395456 seconds and 4 git commands to generate.