Category : File Managers
Archive   : KOPY12.ZIP
Filename : KOPY.C

Output of file : KOPY.C contained in archive : KOPY12.ZIP
/*Kopy 1.2 - Copy or Find and optionally Delete files Everywhere
by Stephen R. Davis, 1987

Search all subdirectories for a particular file pattern. All files
found matching that pattern are copied to the target path. The
arguments to KOPY are explained in ERRMSG below.

(Note: compiling with the label SWITCH defined in the
Options/Compiler/Defines menu reverses the sense of
the "/S" flag for those that prefer it the other way)
char *banner = {
"This program was developed for Borland's Turbo C (Ver 1.0) by \n"
"Stephen R. Davis for the book:\n\n"
" Turbo C:\n"
" The Art of Advanced Program Design, Optimization and Debugging\n"
" M&T Books\n"
" 501 Galveston Drive\n"
" Redwood City, CA 94063\n\n"
"This program is released into the public domain without charge for\n"
"the use and enjoyment of the public with the single provision that this\n"
"banner remain intact. Anyone wishing to learn more about getting the\n"
"most out of the IBM PC and its clones using Turbo C, can order a copy of\n"
"this book by calling:\n\n"
" 1-800-533-4372\n"
" (in CA, 1-800-356-2002)\n"
" 8 am to 5 pm PST\n\n"};


#define TRUE 1
#define FALSE 0

/*define error message*/
char *errmsg = {
"This program copies all files from the source path and all\n"
"of its subdirectories which match the source pattern to the\n"
"target path. If no target path is given, the current directory\n"
"is assumed. The following switches are defined:\n"
" /D - delete after copying/finding (prompts operator for okay)\n"
" /F - simply find (do not copy)\n"
" /S - search single directory only (no subdirectories)\n"
" /V - requests operator verification before continuing\n"
" /R - copy to the console (may be redirected with >)\n"
" /A - find only files with archive bit set\n"
"For example:\n\n"
"KOPY /D C:\\*.DAT copy and delete all .DAT files from\n"
" all of the directories on disk C to\n"
" the current directory.\n\n"
"KOPY /S \\USER\\*.DAT B:\\COPY copy all the .DAT files from \\USER\n"
" to directory COPY on drive B.\n\n"
"KOPY /F/D \\*.BAK find and delete all *.BAK files on\n"
" current disk\n\n"
"If the target disk fills you will be prompted to insert a new one.\n"

/*prototyping definitions*/
void main (unsigned, char **);
void copyall (char *, char *, char *);
void copy (char *, char *);
void find (char *);
void append (char *, char *, char *);
void addslash (char *);
void closefiles (int, int);
void arg_error (void);
int getyval (char *);
int opennew (char *);

/*define global flags*/

char found_one = FALSE, delete = FALSE, find_only = FALSE;
char verify = FALSE, standardoutput = FALSE;
char archive_only = FALSE;
char quiet = FALSE, keepdate = TRUE;

int thandle, fhandle;
struct ftime time;

char include_subdirs =
#ifdef SWITCH
FALSE; /*default subdirectory search to off*/
TRUE; /* " " " " on*/

/*Main - parse user input and start the ball rolling*/
void main (argc, argv)
unsigned argc;
char *argv [];
char sourcedisk [MAXDRIVE], sourcedir [MAXDIR];
char sourcefile [MAXFILE], sourceext [MAXEXT];
char fromdir [MAXPATH], pattern [MAXFILE+MAXEXT];
char *secondarg, *switchptr, *srcfile;

/*first check for switches -- ignore case and extra '/'s*/

while (*(switchptr = argv [1]) == '/') {
while (*++switchptr) {
switch (tolower (*switchptr)) {
case 'a': archive_only = !archive_only;
case 'd': delete = !delete;
case 'f': find_only = !find_only;
case 'q': quiet = !quiet;
case 's': include_subdirs = !include_subdirs;
case 'u': keepdate = !keepdate;
case 'v': verify = !verify;
case 'r': standardoutput = !standardoutput;

/*now skip over this argument*/
argv [1] = argv [0];

/*check the argument count*/
if (argc == 1 || argc > 3)
arg_error ();

/*parse argument 1 into its two halves
(if no source path given, assume "*.*") */
fnsplit (argv [1], sourcedisk, sourcedir, sourcefile, sourceext);
if (!*(srcfile = sourcefile))
srcfile = "*.*";

/*now reconstruct the two halves*/
fnmerge (fromdir, sourcedisk, sourcedir, 0, 0);
fnmerge (pattern, 0, 0, srcfile, sourceext);

/*if no second argument and not redirected, assume the
current directory*/
if (standardoutput) {
secondarg = " ";
thandle = fileno (stdout);
} else {
if (!(secondarg = argv [2]))
secondarg = ".\\";
addslash (secondarg);

/*now just copy/find them everywhere*/
copyall (fromdir, pattern, secondarg);
if (!found_one) {
fprintf (stderr, "No files found");
if (include_subdirs && (sourcedir [0] != '\\'))
fprintf (stderr, " (use %s\\%s%s to search entire disk)\n",
sourcedisk, sourcefile, sourceext);
fprintf (stderr, "\n");

/*exit normally*/
exit (0);

/*Copyall - copy/find all files matching a given pattern from the
current directory and all subdirectories*/
void copyall (fromdir, pattern, todir)
char *fromdir, *pattern, *todir;
char spath [MAXPATH], tpath [MAXPATH];
struct ffblk block;

/*first copy/find all files patching the pattern*/
append (spath, fromdir, pattern);
if (!findfirst (spath, &block, 0))
if (!archive_only || (block.ff_attrib && FA_ARCH)) {
append (spath, fromdir, block.ff_name);
append (tpath, todir, block.ff_name);
if (!find_only)
copy (spath, tpath);
find (spath);
while (!findnext (&block));

/*now check all subdirectories, if desired*/
if (include_subdirs) {
append (spath, fromdir, "*.*");
if (!findfirst (spath, &block, FA_DIREC))
do {

/*only pay attention to directories*/
if (block.ff_attrib & FA_DIREC)

/*ignore directories '.' and '..'*/
if (block.ff_name [0] != '.') {

/*now tack on name of directory + '\'*/
append (spath, fromdir, block.ff_name);
addslash (spath);

/*and copy its contents too*/
copyall (spath, pattern, todir);
} while (!findnext (&block));

/*Copy - given two patterns, copy the source to the destination file*/
#define NSECT 64
void copy (from, to)
char *from, *to;
int number;
char buffer [NSECT*512], failure;

/*don't copy a file to itself*/
if (!stricmp (to, from))
found_one = TRUE;

do {
/*check for verification before copying*/
fprintf (stderr, "\nCopying %-12s -> %s", from, to);
if (verify)
if (!getyval (" - copy?"))

/*open the source for reading binary*/
_fmode = O_BINARY;
if ((fhandle = open (from, O_RDONLY)) == -1) {
perror ("\nError opening source file");

/*now open the destination, if not standard output*/
if (!standardoutput)
if ((thandle = opennew (to)) == -1) {
if (!getyval (" - overwrite target?")) {
close (fhandle);
if ((thandle = open (to, O_RDWR + O_TRUNC,
S_IWRITE)) == -1) {
perror ("\nError opening target file");

/*now perform the copy*/
failure = FALSE;
while (number = read (fhandle, buffer, NSECT*512))
if (number != _write (thandle, buffer, number))
if (!standardoutput) {

/*disk full, close source and delete target*/
closefiles (fhandle, thandle);
unlink (to);
getyval ("\nDisk full - "
"insert new disk and hit any key");
failure = TRUE;
} while (failure);
fprintf (stderr, " - copied");

/*set target file time to source file time*/
if (keepdate) {
getftime (fhandle, &time);
setftime (thandle, &time);
closefiles (fhandle, thandle);

/*delete source, if requested*/
if (delete)
if (getyval (" - delete source?")) {
unlink (from);
fprintf (stderr, " - deleted");

/*Find - in case of find, ask user permission to delete file if
"/d" switch and whether we should continue if verify enabled*/
void find (fname)
char *fname;
found_one = TRUE;
printf ("\nFound %s", fname);
if (delete)
if (getyval (" - delete?")) {
if (unlink (fname))
perror ("\nError on delete");
fprintf (stderr, " - deleted");

if (verify)
if (!getyval (" - continue?"))
exit (0);

/*Append - concatenate two strings together*/
void append (to, from1, from2)
char *to, *from1, *from2;
/*copy the first string*/
while (*from1)
*to++ = *from1++;

/*now the second*/
while (*from2)
*to++ = *from2++;

/*and then tack on a terminator*/
*to = '\0';

/*Addslash - add a slash onto a directory name which doesn't
already end in '\' or ':'*/
void addslash (dirptr)
char *dirptr;
/*skip to next to last character in path*/
while (*dirptr)

/*now check last character*/
if (*dirptr != '\\' && *dirptr != ':') {
*++dirptr = '\\';
*++dirptr = '\0';

/*closefiles - close the source and, if not stdout, the target*/
void closefiles (fhandle, thandle)
int fhandle, thandle;
close (fhandle);
if (!standardoutput)
close (thandle);

/*Opennew - use creatnew() to create a new file. Since this system
call is not present under DOS 2.x, its function must
be emulated by normal open() calls.*/
int opennew (name)
char *name;
int handle;

if (_osmajor >= 3)
return creatnew (name, 0);

if ((handle = open (name, O_RDONLY)) != -1) {
close (handle);
return -1;
return open (name, O_RDWR + O_CREAT, S_IWRITE);

/*Arg_error - print error message and then abort*/
void arg_error (void)
printf (errmsg);
if (!include_subdirs)
printf ("(Note: This version has the meaning of the "
"/S switch inverted.)");
getyval ("\nEnter any key to continue");
printf ("\n\n\n\n\n\n\n%s", banner);
exit (1);

/*Getyval - out a string and then await a response.
Exit program if Break (Control-C). Return a 1
if entered 'y', else 0. If "quiet" mode is enabled,
just assume a 'y'.*/
int getyval (msg)
char *msg;
char entered;

/*if quiet is enabled, just assume 'Y' in all cases*/
if (quiet)
return 1;

/*otherwise, put up a prompt and await response*/
fprintf (stderr, msg);
if ((entered = getch ()) == 0x03) exit (1);
return (tolower (entered) == 'y');

  3 Responses to “Category : File Managers
Archive   : KOPY12.ZIP
Filename : KOPY.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: