/****************************************************************************
*	$Id: ftpsubr.c 1.4 94/02/02 14:38:13 ROOT_DOS Exp $
*	22 Dec 93	1.2		GT	Fix "hash" output.								
*	24 Jan 93	1.3		GT	Fix hash mark wrap column.						
*	01 Feb 94	1.4		GT	Remove broken wrap code.
*
*  Atari Version by David Nash - dnash@chaos.demon.co.uk
*
*  Add V_BYTE verbosity level
*
****************************************************************************/

/* Routines common to both the FTP client and server
 * Copyright 1991 Phil Karn, KA9Q
 */
#include <stdio.h>
#include "global.h"
#include "mbuf.h"
#include "socket.h"
#include "proc.h"
#include "ftp.h"
#include "ftpcli.h"

extern int16 Tcp_mss;

static void hashit __ARGS((int hash, long total, long *hmark, int *col,
						   int wrapcol));

/* Send a file (opened by caller) on a network socket.
 * Normal return: count of bytes sent
 * Error return: -1
 */
long
sendfile(fp,s,mode,hash, wrapcol)
FILE *fp;	/* File to be sent */
int s;		/* Socket to be sent on */
int mode;	/* Transfer mode */
int hash;	/* Print hash marks every BLKSIZE bytes */
int wrapcol;	/* wrap column when hashing			*/
{
	register struct mbuf *bp;
	int c,oldf;
	long total = 0;
	long hmark = 0;
	int col = 0;

 	if (hash == V_BYTE)
 		tprintf("         : Bytes Sent\r");

	switch(mode){
	default:
	case LOGICAL_TYPE:
	case IMAGE_TYPE:
		sockmode(s,SOCK_BINARY);
		for(;;){
			bp = ambufw(BLKSIZE);
			if((bp->cnt = fread(bp->data,1,BLKSIZE,fp)) == 0){
				free_p(bp);
				break;
			}
			total += bp->cnt;
			if(send_mbuf(s,bp,0,NULLCHAR,0) == -1){
				total = -1;
				break;
			}

			hashit (hash, total, &hmark, &col, wrapcol);
		}
		break;
	case ASCII_TYPE:
		oldf = setflush(s,-1);
		/* Let the newline mapping code in usputc() do the work */
		sockmode(s,SOCK_ASCII);
		while((c = getc(fp)) != EOF){
#if !defined(UNIX) && !defined(__TURBOC__)
			if(c == '\r'){
				/* Needed only if the OS uses a CR/LF
				 * convention and getc doesn't do
				 * an automatic translation
				 */
				continue;
			}
#endif
			if(usputc(s,(char)c) == -1){
				total = -1;
				break;
			}
			total++;
			hashit (hash, total, &hmark, &col, wrapcol);
		}
		usflush(s);
		setflush(s,oldf);		
		break;
	}
	if(hash)
		tputc('\n');
	return total;
}
/* Receive a file (opened by caller) from a network socket.
 * Normal return: count of bytes received
 * Error return: -1
 */
long
recvfile(fp,s,mode,hash, wrapcol)
FILE *fp;
int s;
int mode;
int hash;
int wrapcol;
{
	int cnt,c;
	struct mbuf *bp;
	long total = 0;
	long hmark = 0;
	int col = 0;

	if (hash == V_BYTE)
		tprintf("         : Bytes Received\r");

	switch(mode){
	default:
	case LOGICAL_TYPE:
	case IMAGE_TYPE:
		sockmode(s,SOCK_BINARY);
		while((cnt = recv_mbuf(s,&bp,0,NULLCHAR,0)) != 0){
			if(cnt == -1){
				total = -1;
				break;
			}
			total += cnt;
			hashit (hash, total, &hmark, &col, wrapcol);
			if(fp != NULLFILE){
				if(write_p(fp,bp) == -1){
					free_p(bp);
					total = -1;
					break;
				}
				free_p(bp);
			} else {
				send_mbuf(Curproc->output, bp, 0, NULLCHAR, 0);
			}
		}
		break;
	case ASCII_TYPE:
		sockmode(s,SOCK_ASCII);
		while((c = recvchar(s)) != EOF){
			if(fp != NULLFILE){
#if !defined(UNIX) && !defined(__TURBOC__) && !defined(AMIGA)
				if(c == '\n'){
					/* Needed only if the OS uses a CR/LF
					 * convention and putc doesn't do
					 * an automatic translation
					 */
					putc('\r',fp);
				}
#endif
				if(putc(c,fp) == EOF){
					total = -1;
					break;
				}
			} else {
				tputc((char)c);
			}
			total++;
			hashit (hash, total, &hmark, &col, wrapcol);
		}
		/* Detect an abnormal close */
		if(socklen(s,0) == -1)
			total = -1;
		break;
	}
	if(hash)
		tputc('\n');
	return total;
}

/****************************************************************************
*	Print hash mark if required.											*
****************************************************************************/

static void hashit(int hash, long total, long *hmark, int *col, int wrapcol)
{
	while (hash == V_BYTE && total >= *hmark + 1024) {
		tprintf("%8ld\r", total);
		*hmark += 1024;

		return;
	}
	
	while (hash && total >= *hmark + 1024) {
		tputc ('#');
		*hmark += 1024;

		if (wrapcol != 0 && ++(*col) >= wrapcol) {
			*col = 0;
			tputc ('\n');
		}				
	}
}


/* Determine if a file appears to be binary (i.e., non-text).
 * Return 1 if binary, 0 if ascii text after rewinding the file pointer.
 *
 * Used by FTP to warn users when transferring a binary file in text mode.
 */
int
isbinary(fp)
FILE *fp;
{
	int c,i;
	int rval;

	rval = 0;
	for(i=0;i<512;i++){
		if((c = getc(fp)) == EOF)
			break;
		if(c & 0x80){
			/* High bit is set, probably not text */
			rval = 1;
			break;
		}
	}
	/* Assume it was at beginning */
	fseek(fp,0L,SEEK_SET);
	return rval;
}

