/*
	CP.C
	Written by Leor Zolman, 3/18/82
	Modified for v1.50 9/82

	CP either copies a file from any disk and user area to any other
	disk and user area, or copies a list of files from the current
	disk and user area to some other disk and/or user area.

	Usages:

	A>cp [user#/][d:]<filename> [user#/][d:][<filename>] [options] <cr>
	A>cp [user#/][d:]<filename> { user#/ or d: or . } [options] <cr>
    or 	A>cp [user#/][d:]<filename> . [options] <cr> 
    or	A>cp <afn>  { <user#/> or <d:> } [options] <cr>

	Options:
			-V	Verify by reading after writing
			

	Note that the filename portion of the last argument is optional
	when only one file is being copied, but not permitted at all when
	multiple files are being copied.
	If files are being copied and the destination filename is omitted,
 	CP attempts to copy to the disk and/or user number specified, leaving
	the filename(s) the same. For example, to copy *.com into user area 7:

		cp  *.com  7/ 

	If the entire second argument is a single dot (.), then the destin-
	ation is the CURRENT disk and user area. For example, to copy foo.c
	from user are 4 into the current user area:

		cp 4/foo.c .

	Link with:
		clink cp wildexp -n

	(or) 	l2 cp wildexp
		noboot cp
*/

#include <bdscio.h>

main(argc,argv)
char **argv;
{
	int i,j,k,c,loop;
	int fd1,fd2;
	int bufsects;
	unsigned bufsize;
	unsigned corebuf;
	char cur_disk;			/* currently logged-in disk */
	char destname[30];
	char *lastarg;
	char verify, *vbuf;		/* true when verifying writes */

	verify = FALSE;
	wildexp(&argc,&argv);

	cur_disk = 'A' + bdos(25);

	for (i = argc - 1; i > 2; --i)
		if (*argv[i] == '-')
		{
			switch(argv[i][1])
			{
				case 'V':
					verify = TRUE;
					break;
			}
			argc--;
		}
		else
			break;

	lastarg = argv[argc - 1];

	if (argc < 3 || (argc > 3 &&
	    !((c = lastarg[strlen(lastarg)-1]) == '/' || c == ':')))
	{
		printf("Usages: cp [u/][d:]filename [u/][d:]newname [-v]\n");
		printf("	cp [u/][d:]filename u/ [-v]\n");
		printf("	cp [u/][d:]filename d: [-v]\n");
		printf("	cp [u/][d:]filename .  [-v]\n");
		printf("	cp <afn>  { <u/> or <d:> or <u/d:> } [-v]\n");
		exit();
	}

	if (verify)
		vbuf =  sbrk(SECSIZ);

	corebuf = sbrk(SECSIZ);
	for (bufsize = SECSIZ; sbrk(SECSIZ) != ERROR; bufsize += SECSIZ)
		;
	bufsects = bufsize / SECSIZ;


   for (loop = 1; loop < argc-1; loop++)
   {
	if ((fd1 = open(argv[loop],0)) == ERROR) {
		printf("\nCan't open %s\n",argv[loop]);
		continue;	/* go on to next one anyway. */
	}

	strcpy(destname,lastarg);	/* create output filename */

	if ( (c = destname[strlen(destname) - 1])=='/' || c == ':' ||
		  				!strcmp(destname,"."))
	{
		if (!strcmp(destname,"."))
			*destname = '\0';
		for (i = strlen(argv[loop]) - 1; i >= 0; i--)
			if (argv[loop][i] == '/' || argv[loop][i] == ':')
				break;				
		strcat(destname,&argv[loop][i+1]);
	}

	if ((fd2 = creat(destname)) == ERROR) {
	  	printf("\nCan't create %s\n",destname);
		printf("Assuming out of directory space and aborting.\n");
		exit();	
	}

	if (loop != 1)
		putchar('\n');

	printf("\t copying %s to %s...",argv[loop],destname);

	while (1)
	{
		if (kbhit()) getchar();
		if (!(i = read(fd1,corebuf,bufsects))) break;
		if (i == ERROR)
		{
		    printf("\nRead error: tell(fd1) = %d, \"%s\"\n",
						tell(fd1), errmsg(errno()));
		    break;
		}

		if (kbhit()) getchar();
		if (write(fd2,corebuf,i) != i) {
			printf("\nWrite error: %s\n",errmsg(errno()));
			exit();
		}
		if (verify)
		{	
			puts("(verifying)");
			seek(fd2, -i, 1);
			for (j = 0, k = corebuf; j < i; j++, k += SECSIZ)
			{
				if (read(fd2, vbuf, 1) != 1)
					printf("\nVerify read error on %s\n",
						destname);
				if (memcmp(vbuf, k, SECSIZ))
					continue;
				else
					printf("\nVerify error on %s\n",
						destname);
			}
		}
	}

	if (close(fd2) == ERROR) {
		printf("\nCan't close the output file.\n");;
		exit();
	}
	fabort(fd1);
   }
}

/*
	Return true if the string arg is a filename prefixed by "nn/",
	where "nn" is a user number:
*/

int hasuno(str)
char *str;
{
	char c;
	int sum;

	sum = 0;

	if (!isdigit(*str)) return FALSE;

	while (isdigit(c = *str++))
		sum = sum * 10 + c - '0';
	return (c == '/') ? (sum >= 0 && sum < 32) : FALSE;
}

