#ifdef MSDOS	/* { */
#include	"grep_msd.h"
#endif		/* } */
char sccsID[] = "@(#) cp.c V2.0 Copyright Julian H. Stacey March 87.\n" ;
#undef DEBUG

/*	UNIX - signal handling MISSING
generally NOT NICE compared with real unix cp


FUNCTION:	copies one file  to another file,
		or multiple files to a directory

BUGS

-	self overwrite not checked
	- on unix we could major/minor device no + inode no,
	on msdos we must play with text strings .. too difficult to bother.

-	going from c to	a: puts	it in top directory,
	even if a is logged in as a sub directory

FEATURES
	puts a new date stamp on file, 
	whereas msdos leaves original date stamp
	(unix would put a new date stamp on).

WIBNIS
	wont copy a single file to a directory

	-r for recursive

	could have mv functionality built in a la unix
	add file dating
*/

#include	<stdio.h>
#include	<fcntl.h>
#include	<sys/types.h>
#include 	<sys/stat.h>
#include	<ctype.h>
#ifdef	unix	/* { */
#include 	<sys/file.h>
#endif		/* } */
#define	BUFSIZE	512
#define	PMODE 0644

int	ARGC ; 
char	**ARGV ; 
char	about =	0;		/* 1 if	we must jump about between
					source & target drives */
char	out_drive[4], in_drive[4] ;

extern char	*strrchr();
extern int	getcwd() ;

#define	CWD_LN	200
char	in_dir[CWD_LN];		/* current working directory */
char	out_dir[CWD_LN];	/* current working directory */

/* returns filename without path prefix	*/
char *namebaase(p)
	char	*p ;
	{
	char	*k;
	k = strrchr(p,'/');
	if (k == (char *)0) return(p);
	else return(k+1);
	}

main(argc,argv)
	int	argc ; 
	char	**argv ; 
	{
	struct stat	input,output ;
	char	*destin;	/* destination directory */
	char	out_full[200] ;	/* output full pathname	*/
	int	result = 0;	/* JJ whats this for */

	ARGV = argv ;
#ifdef	VSL	/* { */
#include	"../../include/vsl.h"
#endif		/* } */
	ARGC = argc ;
	printf("%s\n",sccsID);

	if (argc < 3) 
		{
		fprintf(stderr,"%s: insufficient parameters\n",*ARGV);
		exit(1);
		}

	/* get directory name */
	while(--argc)argv++ ;  destin =	*argv ;

	/* In case destination directory is another drive (& not necessarily
		top directory in that drive */

	if (isalpha(*destin) &&	*(destin +1) ==	':')
		{
		about =	1;
		getcwd(in_dir,CWD_LN+2); 
#ifdef DEBUG
		printf("Source directory is %s\n",in_dir);
#endif
		in_drive[0] = in_dir[0] ; in_drive[1] = in_dir[1] ;	
		in_drive[2] = '\n' ; in_drive[3] = '\0' ;
#ifdef DEBUG
		printf("Source drive is	%s\n",in_drive);
#endif

		out_drive[0] = *destin ; out_drive[1] =	*(destin +1) ; 
		out_drive[2] = '\n' ; out_drive[3] = '\0' ;
#ifdef DEBUG
		printf("Target drive is	%s\n",out_drive);
#endif
		destin += 2 ; /* skip z: */
		}
#define	STRADR	&
	if (stat(destin,STRADR output)) { perror(*ARGV); exit(1); }
	if (!(output.st_mode  &	S_IFDIR) && (ARGC > 3) && !about)
	/* for some reason stat	a: says	not dir	even when is, so ignore	it 
		by using `about` */
		{
		printf("%s: Can	not copy multiple files	to non directory %s\n",
			*ARGV,destin);
		exit(1);
		}

	argc = ARGC - 1 ; argv = ARGV ;
	while (--argc)
		{
		argv++;
		result = 0;
#ifdef DEBUG
		printf("Next source is %s\n",*argv);
#endif
		if (stat(*argv,STRADR input)) { perror(*ARGV); exit(1); }
		if (input.st_mode & S_IFDIR)
			{
			fprintf(stderr,
				"%s: Skipping %s (directory).\n",
				*ARGV,*argv);
			result = 1;
			continue ;
			}
		(void) strcpy(out_full,destin);
#ifdef DEBUG
		printf("base %s\n",namebaase(*argv));
#endif
		if ((output.st_mode & S_IFDIR) || about	)
			{
			if (*destin && destin[2]) (void) strcat(out_full,"/");
			(void) strcat(out_full,namebaase(*argv));
			}
#ifdef DEBUG
		printf("a_to_b %s %s\n",*argv,out_full);
#endif
		(void) a_to_b(*argv,out_full);
		if (chmod(out_full,(int)(input.st_mode)))
			{
			perror(*ARGV);
			exit(1);
			}
		}
	}

a_to_b(name_a,name_b)
	char	*name_a, *name_b;
	{
	int	file1, file2, n; char	buf[BUFSIZE];
	if (about) (void)system(in_dir); 
	(void)system("dir");
	if ((file1 = open(name_a,O_RDONLY 
#ifdef	MSDOS	/* { */
					| O_BINARY
#endif		/* } */
							))	== -1)
		{
		fprintf(stderr,"%s: Failed to open %s\n",*ARGV,name_a);
		return(1);
		}
	if (about) /* change directory */ (void)system(out_dir); 
	(void)system("dir");
	if ((file2 = open(name_b,
		O_CREAT	| O_TRUNC 
#ifdef	MSDOS	/* { */
				| O_BINARY
#endif		/* } */
						| O_WRONLY, S_IREAD | S_IWRITE)
		) == -1)
		{
		fprintf(stderr,"%s: Failed to create %s\n",*ARGV,name_b);
		return(1);
		}

	while (	(n = read(file1,buf,BUFSIZE)) >	0)
		if (write(file2,buf,n) != n)
			{
			fprintf(stderr,"%s: Write error	on %s\n",*ARGV,name_b);
			return(1);
			}
	if (close(file1))
		{
		perror(*ARGV);
		exit(1);
		}
	if (close(file2))
		{
		perror(*ARGV);
		exit(1);
		}
	return(0);
	}
