home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
dskutl
/
free151.arc
/
FREE.C
< prev
next >
Wrap
Text File
|
1989-02-08
|
28KB
|
596 lines
/****************************************************************************
FREE : free.c checks disk free space, with options
Author : Howard S. Kapustein
Program, Source, Documentation Copyright (c) 1988,1989 all rights reserved.
Compiled code may be used in your library, and linked to your programs
BUT, the source code nor a library based on the compiled modules may be
commercially distributed.
I retain all rights to the source (this is all lawyer talk. I just don't
want someone making money off my efforts.)
No donation is expected. If you like FREE, send me a picture postcard
or, if you must, $5. I am a poor starving college student and will
gladly accept all comments, questions, suggestions and/or donations.
For a quick start try FREE -?
I know this is a pretty simple program. There are plenty of versions
of free disk space programs in the public domain, but none suited my
needs. I needed 3 features besides the standard disk space free:
1) Check more than 1 drive per run
2) Optionally check all drives
3) Optionally wait for a keypress after execution for use
with DESQview (tm)
FREE.C, FREE.EXE and FREE.DOC must be distributed together.
FREE was compiled with Turbo C (tm) 2.0 on an IBM PC with the Tiny
memory model optimized on Speed and all optimizations turned on
(Register and Jump optimization).
Release notes: 2-2-88 Version 1.0 - Initial release
2-22-88 Version 1.1
- checks for drive ready before checking
free space
- skips drive B: only 1 drive present
(B: is a logical drive, not a physical
drive)
- optional wait after execution can now
wait for a specific key (specify its
decimal scan code, only valid for keys
1-255 (no extended keys i.e. Alt-C, etc.)
- fixed a bug with the strtocomma() function.
If a 4-digit number (i.e. 9216) was passed
to it it would not insert any commas
- I no longer make FREE.COM, for some reason
under DESQview FREE.COM 1.0 still needed
approx 70K, so until I can figure out how
to get FREE to use appropriate only the 11K
or so it needs, I'm not going to bother
playing with COM files
2-29-88 Version 1.2
- recompiled under Turbo C 1.5 (it only took
them 6 weeks instead of the 2-3 it should
have...) I turned on ALL optimizations
(speed, use regs, optimize regs and jumps.)
Previous versions were only compiled with
speed and use registers.
- modified the parsing for more coherent
program flow
- made waitforkey() after having extensive
difficulties getting the -w option to work.
This seems to have fixed the runtime bugs
I was getting after recompiling with TC 1.5
- changed the HEAP and STACK size so it will
run with less memory
- removed some needless comments left over
from old coding
- include a DESQview .DVP file for use with
DESQview.
3-19-88 Version 1.3
- fixed the bug with multiple drives
specified on the command line. It seems
that TC 1.5 DOES NOT let you use the
generic argc and argv as in
main(int argc, char *argv[]) Now Borland
wants you to use their global variables
(extern int argc, etc.). Nice of them not
to mention the fact that the old method
no longer works.
3-23-88 Version 1.31 - Internal release only
- if you try to do a FREE - with no
parms free would check the default drive.
This has been fixed to display the help
(technically, doing FREE - is wrong)
- version 1.2 allowed -w[n] option to check
for extended key codes, but I forgot to
document it. Use this formula to get the
value for the wait option:
extended * 256 + scancode
where extended is 0 if False and 1 if True
and scancode is the scan code returned by
the key (refer to one of Norton's books
or some other reference guide for a list
of IBM extended scan codes.)
4-10-88 Version 1.32 - Internal release only
- I removed a printf() left over from
debugging
- included info about contacting me during
the school year
5-6-88 Version 1.33 - Internal release only
- included % free
5-11-88 Version 1.34 - Internal release only
- fixed -w option, was skipping past
1st digit of keycode ([n])
- also, discovered the problem with the
-w option. Compiled w/full optimization,
the waitkey value was stored in a
register which was destroyed during the
absread(). This is a problem of the
TC library itself. I don't remember
who it was who discovered this flaw, but
if you drop me a line I'll update these
docs. He has notified Borland, so
hopefully the next TC will have this bug
fixed (if not sooner, but I'm not
holding my breath.) Thank you for the
debugging, it gave me many a restless
hour. DO NOT compile FREE with register
variables on, or unknown results may
(and probably will) occur
11-9-88 Version 1.4
- recompiled under TC 2.0 in Small model,
Merge duplicate strings On, Standard
stack frame Off, and all Debug info
left out. Couldn't compile under Tiny
(Cannot generate COM file: segment-
relocatable items present) probably because
of the FP emulator - see below
- added optional message if wait for key
- added -f and -n (search only floppies,
non-floppies). The -x option is equivalent
to -fn
- added -e option (full error display, useful
if you want to see any errors during a -f,
-n, or -x run). This setting is turned on
automatically for single mode (if -f, -n
and -x are not specified)
- minor code tinkering for aesthetics
- DESQview 2.2 .DVP file
- for some reason, FREE running under
DV 2.2 now requires 65K. According to my
estimates, it needs anywhere from 44K to
66K. I think this is related to the Tiny
problem (inability to make .COM file). If
anyone can figure out why, please let me
know. Without the FP emulator, I can't
display a % free, but requiring 65K to get
a free disk space count is ridiculous
2-7-89 Version 1.5
- new option -N, Network compatibility,
skips the absolute disk read before
checking free space. If a free space
request is attempted on drive A: with
no floppy in the drive, DOS bombs out to
the Abort,Ignore,Retry message. Turning on
this option should allow execution on
drives not physically available (networks,
those accessed via device drivers, etc.)
- changed option letter -N to -H to allow
network compatibility. The -H option
will scan non-floppy drives (generally
fixed disks, C: and up.)
- no longer compiled with the FP emulation,
the % free real number is now achieved via
integers. Without the FP emulation FREE can
be compiled with the Tiny memory model.
- added check for DOS environment variable
FREEOPT for options
- changed the Heap size to 4K and the stack
to 1K
- changed the command line parsing to a
separate function, and no longer copy each
*_argv before processing it. The pointer
char *temp replace the older char temp[30]
for several reasons: instead of a strcpy()
we can just do a temp = *_argv, and if an
argument string was longer than 29
characters, we would have problems copying
to temp[30]. Pointers make life simpler
- you can now check multiple drives via
command line switch, and specific drives
via drive letter, in the same run (i.e.
FREE /F B: checks all floppy drives and
drive B:)
- IMPORTANT! FREE is now distributed as a
.COM file! If you are using an earlier
verison with a .EXE extension, make sure
you delete it otherwise DOS may not find
the proper file to run. See above regarding
FP emulation as to why we're back to a
.COM file.
Note: I've enclosed the substitute division
function within a conditional #if...#endif
set so you can recompile easily with the
emulation or 8087 library and not have
unnecessary code. If MATH_FP87 or MATH_EMU
is #defined, the rdiv() function will not
be compiled. Otherwise, no math library
will be linked in, and the final .COM
will only need ~15K to run.
2-8-89 Version 1.51
- if no command line arguments given, only
the current drive would be checked, even
if FREEOPT=X. Fixed
I can be reached at:
Home: Howard S. Kapustein
1695 Barbara Lane
East Meadow, New York 11554
Phone: (516) 481-9612
College (until 5-19-89): Howard S. Kapustein
404 Davison
Rensselaer Polytechnic Institute
Troy, NY 12180
(518) 276-7381
Modem: The BOSS (201) 568-7293 ***Support BBS
Software Society (201) 729-7410
Computer Connection (202) 547-2008
GEnie
Until graduation (May 19, 1989) please try to contact me
at college. If you call my home while I'm in Troy you're not
likely to get much information (my parents aren't exactly
computer people.)
****************************************************************************/
#include <ctype.h>
#include <bios.h>
#include <dos.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <dir.h>
typedef struct rdiv_t {
long rint; /* real - integer */
long rfrac; /* real - fraction */
};
#define TRUE 1
#define FALSE 0
#define boolean char
#define BUFF_LEN 512 /* buffer length for disk read */
#define FLOPPY 0x10
#define FIXED 0x20
#define ALLDRIVES (FIXED|FLOPPY)
#define isBlogical() ((biosequip()&0xB0)?FALSE:TRUE)
typedef struct options {
char scandrives;
boolean network;
boolean errormsg;
boolean wait;
boolean waitmsg;
int waitkey;
};
/* Global variables */
struct options flag;
/* function prototypes */
void main(); /* prevents compiler warning */
void check(int drive); /* actual free space check and output */
char *strtocomma(char *source); /* convert a string to xx,xxx,xxx format */
void help(void); /* help */
void waitforkey(int keycode, boolean msg); /* wait for keypress when done */
void parsecommandline(char *cmdline); /* parse a command line */
void bye(int errcode); /* generalized quit routine */
struct rdiv_t rdiv(long int numer, long int denom, int precision); /* real division without FP emulator library */
void main()
{
extern int _argc;
extern char **_argv;
extern unsigned _heaplen, _stklen;
char *temp;
boolean Blogical;
int i, floppies;
_heaplen = 4096u; /* heap = 4K */
_stklen = 1024u; /* stack = 1K */
_argc--;
_argv++;
flag.scandrives = FALSE; /* initialize settings */
flag.network = FALSE;
flag.errormsg = FALSE;
flag.wait = FALSE;
flag.waitmsg = TRUE;
flag.waitkey = 0;
if ((temp = getenv("FREEOPT")) != NULL)
parsecommandline(temp);
if (_argc > 0) /* check for options */
for (temp = *_argv; (temp[0] == '-') || (temp[0] == '/'); temp = *_argv) {
if (temp[1] == '\0')
help();
parsecommandline(temp+1);
_argc--;
_argv++;
if (_argc == 0)
break;
}
if (flag.scandrives) { /* check multiple drives? */
floppies = ((biosequip() & 0xB0) >> 6) + 1;
Blogical = (floppies > 1) ? FALSE : TRUE;
if (flag.scandrives & FLOPPY) /* check floppy drives? */
for (i=1; i<=floppies; i++) /* check floppies */
if (!(i==2 && Blogical))
check(i);
if (flag.scandrives & FIXED) { /* check non-floppies? */
i = Blogical ? 3 : ++floppies;
for (; i<=26; i++) /* check hard drives */
check(i);
}
}
if ((_argc == 0) && !flag.scandrives) { /* ok, just parms (no drive specified) */
flag.errormsg = TRUE; /* force error message display for non-multiple mode */
check(0);
if (flag.wait)
waitforkey(flag.waitkey,flag.waitmsg);
bye(3);
}
flag.errormsg = TRUE; /* force error message display for non-multiple mode */
for (; _argc>0; _argc--, _argv++) {
strcpy(temp,*_argv);
if (!isalpha(temp[0]=toupper(temp[0])))
printf("Invalid drive: %c\n",temp[0]);
else
check(temp[0]-64);
}
if (flag.wait)
waitforkey(flag.waitkey,flag.waitmsg);
}
void check(int drive)
{
extern struct options flag;
struct dfree df;
char size[30];
unsigned char buffer[BUFF_LEN];
long avail, total;
#if defined(MATH_FP87) || defined(MATH_EMU) /* using 80x87 or Emulation math library */
double percent;
#else /* using No math library */
struct rdiv_t percent;
#endif
if (drive==0)
drive = getdisk() + 1;
if (!flag.network && absread(drive-1,1,0,buffer)==-1) { /* error */
if (flag.errormsg)
printf("Drive %c: is not available (drive not ready)\n",drive+64);
} else {
getdfree(drive,&df);
if (df.df_sclus == (unsigned)(-1)) { /* error */
if (flag.errormsg)
printf("Drive %c: is not available (can't get free space)\n",drive+64);
} else {
avail = (long)df.df_avail * df.df_bsec * df.df_sclus;
total = (long)df.df_total * df.df_bsec * df.df_sclus;
ltoa(avail,size,10);
#if defined(MATH_FP87) || defined(MATH_EMU) /* using 80x87 or Emulation math library */
percent = (avail * 100.0) / ((long)df.df_total * df.df_bsec * df.df_sclus);
printf("Drive %c: has %s bytes free (%.2lf %%)\n",drive+64,strtocomma(size),percent);
#else /* using No math library */
percent = rdiv(avail,total,4);
printf("Drive %c: has %s bytes free (%ld.%02ld %%)\n",drive+64,strtocomma(size),percent.rint*100+percent.rfrac/100,percent.rfrac%100);
#endif
}
}
}
char *strtocomma(char *source) /* convert a string to xx,xxx,xxx format */
{
char temp[80],*t,*s;
int i,len;
len = strlen(source) * 4/3 + 1;
strcpy(temp,"");
if ((len = strlen(source)) <= 3)
strcpy(temp,source);
else
for (i=len, t=temp, s=source; i>0; i--) {
if ((i%3 == 0) && (i != len))
*t++ = ',';
*t++ = *s++;
}
*t = '\0';
strcpy(source,temp);
return(source);
}
void help(void)
{
fputs("FREE Free disk space Version 1.51 2-8-89 FREE/?\n",stdout);
fputs("Copyright (c) 1988,1989 Howard Kapustein. All Rights Reserved for help\n\n",stdout);
fputs("Usage: FREE [options] [drive] [drive] [drive] ...\n",stdout);
fputs("Options are:\n",stdout);
fputs(" -e = display all error messages -f = check all floppy drives\n",stdout);
fputs(" -n = network compatibility -h = check all non-floppy drives\n",stdout);
fputs(" -w[0][n] = wait for keypress when done -x = check all drives\n",stdout);
fputs(" -? = help\n\n",stdout);
fputs("If you like FREE send me a picture postcard or $5. I can be reached at:\n\n",stdout);
fputs("VOICE: Howard Kapustein MODEM: The BOSS (201) 568-7293 **Support BBS\n",stdout);
fputs(" 1695 Barbara Lane Software Society (201) 729-7410\n",stdout);
fputs(" East Meadow, New York 11554 Computer Connection (202) 547-2008\n",stdout);
fputs(" Phone: (516) 481-9612 GEnie: Howard S. Kapustein\n\n",stdout);
fputs("I am a poor starving college senior, 404 Davison\n",stdout);
fputs("so all donations (and job offers) Rensselaer Polytechnic Institute\n",stdout);
fputs("will be appreciated. Until graduation Troy, NY 12180\n",stdout);
fputs("(May 19, 1989) PLEASE contact me at -> Phone: (518) 276-7381\n\n",stdout);
fputs("I also write Subtree Find (the Fastest file finder, also supports paths),\n",stdout);
fputs("TCHK (a Turbo C library for Turbo C 2.0, over 200 functions) and more.",stdout);
bye(9);
}
void waitforkey(int keycode, boolean msg) /* wait for keypress when done */
{
int key;
if (msg) {
if (keycode == 0)
fputs("Press any key to end...",stdout);
else
printf("Press key #%d to end...",keycode);
}
if (keycode == 0)
bioskey(0);
else
do {
key = bioskey(0);
if (key & 0xFF)
key = key & 0xFF;
else
key = ((key & 0xFF00) >> 8) + 256;
} while (key != keycode);
}
void parsecommandline(char *cmdline)
{
extern struct options flag;
int i;
for (i=0; cmdline[i]!='\0'; i++)
switch (toupper(cmdline[i])) {
case '/': { if (cmdline[++i] == '\0')
bye(67);
break; }
case 'N': { switch (cmdline[i+1]) {
case '-': { flag.network = FALSE;
i++;
break; }
case '*': { flag.network ^= TRUE;
i++;
break; }
case '+': i++;
default: flag.network = TRUE; break;
}
break; }
case 'E': { switch (cmdline[i+1]) {
case '-': { flag.errormsg = FALSE;
i++;
break; }
case '*': { flag.errormsg ^= TRUE;
i++;
break; }
case '+': i++;
default: flag.errormsg = TRUE; break;
}
break; }
case 'F': { switch (cmdline[i+1]) {
case '-': { flag.scandrives &= ~FLOPPY;
i++;
break; }
case '*': { flag.scandrives ^= FLOPPY;
i++;
break; }
case '+': i++;
default: flag.scandrives |= FLOPPY; break;
}
break; }
case 'H': { switch (cmdline[i+1]) {
case '-': { flag.scandrives &= ~FIXED;
i++;
break; }
case '*': { flag.scandrives ^= FIXED;
i++;
break; }
case '+': i++;
default: flag.scandrives |= FIXED; break;
}
break; }
case 'X': { switch (cmdline[i+1]) {
case '-': { flag.scandrives &= ~ALLDRIVES;
i++;
break; }
case '*': { flag.scandrives ^= ALLDRIVES;
i++;
break; }
case '+': i++;
default: flag.scandrives |= ALLDRIVES; break;
}
break; }
case 'W': { if (isdigit(cmdline[i+1])) {
flag.waitmsg = (cmdline[++i] == '0') ? FALSE : TRUE;
flag.waitkey = atoi(cmdline+i);
for (; isdigit(cmdline[i+1]); i++);
} else
flag.waitkey = 0;
switch (cmdline[i+1]) {
case '-': { flag.wait = FALSE;
i++;
break; }
case '*': { flag.wait ^= TRUE;
i++;
break; }
case '+': i++;
default: flag.wait = TRUE; break;
}
break; }
case '?': help();
default : { printf("Unknown parameter: %c\n",cmdline[i]); bye(11); }
}
}
void bye(int errcode) /* generalized quit routine */
{
exit(errcode);
}
#if !defined(MATH_FP87) && !defined(MATH_EMU) /* using no math library */
struct rdiv_t rdiv(long int numer, long int denom, int precision) /* real division without FP emulator library */
{
struct rdiv_t retval;
long i;
if (denom == 0l) {
retval.rint = -1;
retval.rfrac = -1;
return(retval);
}
retval.rint = numer / denom;
denom -= numer * retval.rint;
retval.rfrac = 0l;
if (denom == 0l)
return(retval);
for (; precision >= 0; precision--) {
numer *= 10l;
i = numer / denom;
if (precision != 0)
retval.rfrac = retval.rfrac * 10l + i;
else
if (numer / denom >= 5l) /* round off last decimal place */
retval.rfrac++;
numer = numer - i * denom;
}
return(retval);
}
#endif