[news.software.b] bdf for use in C news

chris@lxn.eds.com (Christopher D. Orr) (07/19/89)

jmm@ecijmm.UUCP (John Macdonald) writes:

>In article <1018@cniysc.cinnet.COM> yun@cinnet.COM (Yun-seng Chao) writes:
>|
>|Uh, wasn't there something called "bdf" posted last year that was able to
>|parse the Sys V "df" command?  Why not use some of that code for usg
>|systems to do some of this parsing (with acknowledgements to the original
>|author, of course)?

>"bdf" was a perl program that converted Sys V df output into a format
>similar to Berkely df.  I kind of doubt that Henry and Geoff would want
>to include perl as a pre-requisite for C news.
>-- 
>John Macdonald



The version of "bdf" that I have is written in 'C'.  The code is very
short so I'll include it with this article for those of you who might
want it.

			--Chris


-------------------------------- CUT HERE ----------------------------------

/* bdf - berkeley DF for system-V systems
 * vix 16jan88 [written - from scratch]
 *
 * This code is public-domain, but please leave this notice intact and give me
 * appropriate credit if you write a man page for it.  If you send me bug fixes
 * and enhancements, I will release new versions from time to time.
 *	Paul Vixie, paul%vixie@uunet.uu.net
 *
 * This is not nearly good enough for the obfuscated C contest.  Next time?
 *
 * Known to work on INTERACTIVE 386/ix, and should therefore work perfectly
 * on Microport/386 and whatever the AT&T 6386 calls its OS.  Should work okay
 * on 3B's.  Should work, in fact, anywhere where the output of 'df -t' is
 * the same as 'System V/386', which may or may not be all SysV.[23] systems.
 */

#include <stdio.h>
#include <string.h>

#define TRUE 1
#define FALSE 0

static char *PROGNAME = "bdf";
static void usage() {
	fprintf(stderr, "usage:  %s [-i]\n", PROGNAME);
	exit(4);
}

main(argc, argv)
	int argc;
	char *argv[];
{
	void bdf();
	int iflag = FALSE;
	int optind = argc;
	char command_buf[300], *ptr = command_buf;

	if (!(PROGNAME = strrchr(argv[0], '/'))) PROGNAME = argv[0];
	if (argc > 1)
		if (argv[1][0] == '-')
			if (argv[1][1] == 'i') { iflag = TRUE; optind = 2; }
			else usage();
		else optind = 1;

	ptr += sprintf(ptr, "/bin/df -t");
	for (;  optind < argc;  optind++)
		ptr += sprintf(ptr, " %s", argv[optind]);

	bdf(iflag, command_buf);
}

static void
bdf(iflag, df_command)
	int iflag;
	char *df_command;
{
	void output_part1(), output_part2(), output_part3();
	void header_part1(), header_part2(), header_part3();
	char filesys[50], device[50];
	int fblocks, finodes, tblocks, tinodes;
	FILE *df;

	if (!(df = popen(df_command, "r"))) {
		fprintf(stderr, "error executing <%s> command\n", df_command);
		perror("popen");
		exit(2);
	}

	header_part1();
	if (iflag) header_part2();
	header_part3();

	while (EOF != fscanf(df, " %[^(] (%[^)]%*s %d blocks %d i-nodes",
				filesys, device, &fblocks, &finodes)) {
		if (EOF == fscanf(df, " total: %d blocks %d i-nodes",
				&tblocks, &tinodes)) {
/*			perror("fscanf#2");
*/			exit(0);
		}

		output_part1(device, fblocks/2, tblocks/2);
		if (iflag)
			output_part2(finodes, tinodes);
		output_part3(filesys);
	}
}

/*************
Filesystem    kbytes    used   avail capacity iused   ifree  %iused  Mounted on
/dev/dsk/0s1 xxxxxxx xxxxxxx xxxxxxx   xxx%  xxxxxx  xxxxxx   xxx%   /foo/bar
*************/

static void
header_part1() {
	printf(" Filesystem   kbytes    used   avail capacity");
}
static void
header_part2() {
	printf(" iused   ifree  %%iused");
}
static void
header_part3() {
	printf("  Mounted on\n");
}

static void
output_part1(device, free_kb, total_kb)
	char *device;
	int free_kb, total_kb;
{
	int used_kb, capacity;
	used_kb = total_kb - free_kb;
	
	if (total_kb != 0)
	  capacity = (100 * used_kb) / total_kb;
	else capacity = 0;

	printf("%12s %7d %7d %7d   %3d%%  ",
		device, total_kb, used_kb, free_kb, capacity);
}

static void
output_part2(free_inodes, total_inodes)
	int free_inodes, total_inodes;
{
	int used_inodes = total_inodes - free_inodes;
	int percent_used = (100 * used_inodes) / total_inodes;

	printf("%6d  %6d   %3d%% ", used_inodes, free_inodes, percent_used);
}

static void
output_part3(filesys)
	char *filesys;
{
	printf("  %s\n", filesys);
}
-- 
Christopher D. Orr                  | US MAIL: Electronic Data Systems (EDS)
UUCP: vu-vlsi!lxn!chris             |          Lanark Building
 or   chris%lxn.uucp@rutgers.edu    |          Center Valley, PA  18034
 or   lehi3b15!lxn!chris            | Voice:   (215) 282-1213

allbery@nc386.UUCP (Brandon S. Allbery) (07/24/89)

There is a very simple way to extract the number of free blocks from a
System V "df"; it's currently working on nc386 (SCO Xenix), telotech (Altos
System V) and ncoast (AT&T System III(!)), each of which has a slightly
different "df" output (in fact, I had to rewrite "bdf"-for-Perl to work on
ncoast).

Extracted from our "spacefor":

## this is set up for the stupid System V df
# which only proves that Collyer and Spencer don't understand System V df....
df $arg | sed 's/^[^ ]*  *([^)][^)]*):  *\([0-9][0-9]*\) .*$/\1/' | awk "{
		nb = (\$1 - $desire) * $dfunit / $1
		if (nb > 10000)
			nb = 10000	# ensure representable as integer
		nb = int(nb)
		if (nb <= 0)
			print 0
		else
			print nb
		exit
	}"

Note the "sed" command in the pipeline; it extracts the "blocks" part of the
"df" output, and does so quite portably.

I left the "awk" mostly as is, but could have written the sed script as part
of the awk script instead or performed other optimizations.

++Brandon
-- 
Brandon S. Allbery, moderator of comp.sources.misc	     allbery@NCoast.ORG
uunet!hal.cwru.edu!ncoast!allbery		    ncoast!allbery@hal.cwru.edu
   * This message brought to you courtesy the "Watcher" for the 4th NCoast *