/*

inndf [-i] filesystem

Ian Dickinson <cudep@csv.warwick.ac.uk>
Wed Jul 26 10:11:38 BST 1995 (My birthday - 27 today!)

With 2GB sign fixes by Jeff.Garzik@spinne.com

Replacement for 'df | awk' in innwatch.ctl
Reports free kilobytes (not disk blocks) or free inodes.

Doesn't sync, forks less, less complicated, etc
This is non-ANSI C - K&R still lives
It should be easy to port if you have some sort of statfs() syscall

Compile with -DHAVE_STATVFS for these systems:
	System V Release 4.x
	Solaris 2.x
	HP-UX 10.x
	OSF1

Compile with -DHAVE_STATFS for these systems:
	SunOS 4.x/Solaris 1.x
	HP-UX 9.x
	Linux
	NeXTstep 3.x

Thanks to these folks for confirming this runs on various platforms:
	Mahesh Ramachandran <rr@eel.ufl.edu>
	Chuck Swiger <chuck@its.com>
	
Here's the relevant portion of my innwatch.ctl:

##  If load is OK, check space (and inodes) on various filesystems
##  =()<!!! inndf @<_PATH_SPOOL>@ ! lt ! @<INNWATCH_SPOOLSPACE>@ ! throttle ! No space (spool)>()=
!!! inndf /news/spool ! lt ! 18000 ! throttle ! No space (spool)
##  =()<!!! inndf @<_PATH_OVERVIEWDIR>@ ! lt ! @<INNWATCH_NOVSPACE>@ ! throttle ! No space (overview)>()=
!!! inndf /news/lib/nov ! lt ! 1000 ! throttle ! No space (overview)
##  =()<!!! inndf @<_PATH_BATCHDIR>@ ! lt ! @<INNWATCH_BATCHSPACE>@ ! throttle ! No space (newsq)>()=
!!! inndf /news/spool/out.going ! lt ! 11000 ! throttle ! No space (newsq)
##  =()<!!! inndf @<_PATH_NEWSLIB>@ ! lt ! @<INNWATCH_LIBSPACE>@ ! throttle ! No space (newslib)>()=
!!! inndf /news/lib ! lt ! 10000 ! throttle ! No space (newslib)
##  =()<!!! inndf -i @<_PATH_SPOOL>@ ! lt ! @<INNWATCH_SPOOLNODES>@ ! throttle ! No space (spool inodes)>()=
!!! inndf -i /news/spool ! lt ! 1900 ! throttle ! No space (spool inodes)

*/

#include <stdio.h>
#include <sys/types.h>

#ifdef HAVE_STATVFS
#include <sys/statvfs.h>		/* specific includes */
#define STATFUNCT	statvfs		/* function call */
#define STATSTRUC	statvfs		/* structure name */
#define STATAVAIL	f_bavail	/* blocks available */
#define STATMULTI	f_frsize	/* fragment size/block size */
#define STATINODE	f_favail	/* inodes available */
#define STATTYPES	u_long		/* type of f_bavail etc */
#endif /* HAVE_STATVFS */

#ifdef HAVE_STATFS
#include <sys/vfs.h>
#define STATFUNCT	statfs
#define STATSTRUC	statfs
#define STATAVAIL	f_bavail
#define STATMULTI	f_bsize
#define STATINODE	f_ffree;
#define STATTYPES	long
#endif /* HAVE_STATFS */

#define KILOBYTES	1024L

#define STATFORMT	"%lu\n"

int printf(), STATFUNCT();

int
main(argc, argv)
int argc;
char **argv;
{
	struct STATSTRUC buf;
	unsigned long value;
	char *path;
	char inodes = 0;

	/* This argument handling is gross */
	if (argc == 2) {
		path = argv[1];
	} else if (argc == 3) {
		inodes++;
		path = argv[2];
	} else {
		(void) printf(STATFORMT, 0L);
		return(0);
	}

	if (STATFUNCT(path, &buf) != 0) {
		value = 0L;	 /* if there's an error - free space is zero */
	} else {
		if (!inodes) {
			/* this is often the same as just buf.f_bavail */
			/* but we want to cope with different underlying */
			/* block/fragment sizes */
			value = ((unsigned long)buf.STATAVAIL *
				 (unsigned long)buf.STATMULTI) /
					(STATTYPES) KILOBYTES;
		} else {
			value = buf.STATINODE;	  /* simple! */
		}
	}

	(void) printf(STATFORMT, value);
	return(0);
}

