/*
 * cp: do what you'd expect it to do
 */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <os2.h>		/* for copytimes(), copymodes() */
#include "glob.h"		/* and DosQFileMode() */

#define CBFRSIZ	10240
static char bfr[CBFRSIZ];
char inquire=0;			/* ask if we want to copy the file */
char verbose=0;			/* show filenames as we copy them */
char preserve=0;		/* preserve attributes and times */

extern char *basename();

extern int getopt();
extern int optind, opterr;
extern char *optarg;

/* 
 * masscopy() does the work of copying a file from one place to
 * another.
 */
masscopy(in, out)
register in, out;
{
    register size;

    while ((size=read(in, bfr, CBFRSIZ)) > 0)
	write(out, bfr, size);
} /* masscopy */


/*
 * copymodes() copies the attributes from the src to the dst file
 */
copymodes(src, dst)
char *src, *dst;
{
    short attrib;
    
    if (DosQFileMode(src, &attrib, 0L) == 0) {
	DosSetFileMode(dst, attrib, 0L);
	return 0;
    }
    return 1;
} /* copymodes */


/*
 * copytimes() makes the dates of the dst file the same as the src file.
 */
copytimes(src, dst)
{
    FILESTATUS dates;

    if (DosQFileInfo(src, 1, &dates, sizeof dates) == 0) {
	DosSetFileInfo(dst, 1, (PBYTE)&dates, sizeof dates);
	return 0;
    }
    return 1;
} /* copytimes */


/*
 * docp() copies a single file
 */
void
docp(src, dest)
char *src, *dest;
{
    register srcfd, dstfd;
    char ans[80];

    if (inquire) {
	fprintf(stderr, "%s? ", src);
	fflush(stderr);
	gets(ans);
	if (ans[0] != 'Y' && ans[0] != 'y')
	    return;
    }

    if ((srcfd = open(src, O_RDONLY|O_BINARY)) >= 0) {
	dstfd = open(dest, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0666);
	if (dstfd < 0) {
	    close(srcfd);
	    fprintf(stderr, "cp: couldn't create %s (destination)\n", dest);
	    return;
	}
	masscopy(srcfd, dstfd);
	if (preserve && copytimes(srcfd, dstfd) != 0 && verbose)
	    fprintf(stderr, "cp: couldn't copy times of %s\n", src);

	close(srcfd);
	close(dstfd);

	if (preserve && copymodes(src, dest) != 0 && verbose)
	    fprintf(stderr, "cp: couldn't copy attributes of %s\n", src);
	else if (verbose && !inquire)
	    puts(src);
    }
    else
	fprintf(stderr, "cp: can't open %s (source)\n",src);
} /* docp */


/*
 * badboy() complains about bad use of arguments, then retires
 */
badboy()
{
    fprintf(stderr, "usage: cp [-fipv] src dst\n");
    fprintf(stderr, "       cp [-fipv] src1 .. srcn dir\n");
    exit(1);
} /* badboy */


/*
 * cp, in the flesh
 */
main(argc, argv)
char **argv;
{
    register i;
    register destisdir = 0;
    static char destfile[512];
    short attrib;
    char *fn, *fbn;
    char c;

    opterr=1;
    while ((i=getopt(argc, argv, "fipv")) != EOF) {
	switch (i) {
	case 'v': verbose = 1; break;
	case 'i': inquire = 1; break;
	case 'f': inquire = 0; break;
	case 'p': preserve= 1; break;
	default:  badboy();
	}
    }

    optind--;
    expand_arglist(argc-optind, argv+optind, (struct args_t*)0);
    if (myargc < 2)
	badboy();

    fn = myargv[myargc-1];
    fbn = basename(fn);
    c = fn[strlen(fn)-1];

    if (c == '/' || c == '\\' || c == ':')
	destisdir = 1;
    else if (DosQFileMode(fn, &attrib, 0L) == 0 && (attrib & F_DIRECT)) {
	c = fn[strlen(fn)-1];
	destisdir = 1;
    }
    else if (strcmp(fbn, ".") == 0 || strcmp(fbn, "..") == 0) {
	c = '.';
	destisdir = 1;
    }

    if (myargc > 2 && !destisdir) {
	fprintf(stderr, "cp: destination is not a directory\n");
	exit(0);
    }

    if (destisdir) {
	strcpy(destfile, fn);
	if (c != '/' && c != '\\')
	    strcat(destfile, "/");
	fn = destfile+strlen(destfile);
	    
	for (i=0; i < myargc-1; i++) {
	    strcpy(fn, basename(myargv[i]));
	    docp(myargv[i], destfile);
	}
    }
    else
	docp(myargv[0], myargv[1]);

    exit(0);
} /* main */