www.pudn.com > tftp.rar > TFTP_USE.C


/* 
**     This product contains: 
**              "Restricted Materials of IBM" 
**              (c) Copyright IBM Corp. 1987 
**              All Rights Reserved 
**              Licensed Materials-Property of IBM 
** 
**     See Copyright Instructions, G120-2083 
** 
*/ 
 
/*  Copyright 1984 by the Massachusetts Institute of Technology  */ 
/*  See permission and disclaimer notice in file "notice.h"  */ 
#include	 
/* (c) 1986 Copyright IBM Corp.; See file  for permissions */ 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include "tftp.h" 
 
 
/* User TFTP: attempt to transmit or receive a file in the specified mode. */ 
 
extern int NBUF; 
extern long cticks; 
 
long tftpuse(fhost, fname, rmfile, dir, mode, size, deltat, writeEOF) 
 
	in_name fhost; 
	char *fname; 
	char *rmfile; 
	unsigned dir; 
	unsigned mode; 
	long size; 
	long *deltat;  
	int writeEOF; 
	 
{ 
	register struct tfconn *cn; 
	unsigned mysock; 
	PACKET pfill, psnd; 
	int i; 
	long len; 
	unsigned flen; 
	unsigned done; 
	char *data; 
	int temp; 
	unsigned CRSEEN = 0; 
	unsigned HOLDING = 0; 
	char HELD; 
 
#ifdef	DEBUG 
	if(NDEBUG & INFOMSG) 
		printf("tftp_use(%a, %s, %s, %u, %u.\n", fhost, fname, 
							rmfile, dir, mode); 
#endif 
	cn = tfmkcn(dir, mode, MAXBUFSIZE); 
	if(cn == 0) { 
		printf("TFTP: Couldn't make connection.\n"); 
		return 0; 
		} 
	i = 0; 
	while((cn->tf_outp = udp_alloc(NORMLEN, 0)) == 0) /*  grab a buffer */ 
	  { 
	      if (++i < 100)		/*  none free, try to free up some */ 
		{ 
		    tk_yield(); 
		} 
	      else			/*  won't free up, give up.  */ 
	        { 
	        printf("TFTP: Couldn't allocate output packet.\n"); 
		return 0; 
	        } 
	  } 
	   
	cn->tf_ctrlz = (writeEOF && dir == GET && mode == ASCII) ? TRUE : FALSE; 
 
	if(dir == GET) { 
		if(mode == ASCII || mode == OCTET) 
					cn->tf_fd = fopen(fname, "wb"); 
		else if(mode == TEST) cn->tf_fd = (FILE *)1; 
		else { 
			printf("TFTP_USER: Bad mode %u.\n", mode); 
			return 0; 
			} 
 
		if(cn->tf_fd == 0) { 
		   printf("TFTP_USER: Couldn't open local file %s.\n", fname); 
			return 0; 
			} 
		*deltat = cticks; 
 
		mysock = udp_socket(); 
		cn->tf_udp = udp_open(fhost, TFTPSOCK, mysock, tftprcv, cn); 
 
		if(cn->tf_udp == 0) { 
			printf("TFTP_USER: Couldn't open UDP connection.\n"); 
			return 0; 
			} 
 
		tfsndreq(cn, rmfile); 
 
		cn->tf_expected = 1; 
		cn->tf_fport = 0; 
 
		while(1) { 
		cn->tf_state = DATAWAIT; 
		while(cn->tf_state == DATAWAIT) tk_block(); 
 
		if(cn->tf_state == TIMEOUT) { 
			printf("TFTP:  Host not responding, giving up.\n"); 
			tfudperr(cn->tf_udp, cn->tf_outp, ERRTXT, 
					"Retry limit exceeded, giving up"); 
			tfcleanup(cn); 
			return 0; 
			} 
 
		if(cn->tf_state == RCVLASTDATA) { 
			len = tfcleanup(cn); 
			*deltat = cticks - *deltat; 
			if(len == 0) 
			printf("TFTP:  Tried to transfer zero-length file\n"); 
			return len; 
			} 
 
		if(cn->tf_state != RCVDATA) { 
			tfcleanup(cn); 
			return 0; 
			} 
		} 
	} 
 
	else if(dir == PUT) { 
		if(mode == ASCII || mode == OCTET) 
			cn->tf_fd = fopen(fname, "rb"); 
		else { 
			printf("Invalid mode for put.\n"); 
			return 0; 
			} 
 
		if(cn->tf_fd == 0) { 
			printf("TFTP: Couldn't open file %s for read.\n", 
									fname); 
			return 0; 
			} 
 
		*deltat = cticks; 
 
		mysock = udp_socket(); 
		cn->tf_udp = udp_open(fhost, TFTPSOCK, mysock, tftprcv, cn); 
		if(cn->tf_udp == 0) { 
			printf("TFTP: Couldn't open UDP connection.\n"); 
			fclose(cn->tf_fd); 
			return 0; 
			} 
 
		i = 0; 
		while((pfill = udp_alloc(NORMLEN, 0)) == 0) /*  grab buffer */ 
		  { 
		      if (++i < 100)	/*  none free, try to free up some */ 
			{ 
			    tk_yield(); 
			} 
		      else		/*  won't free up, give up.  */ 
			{ 
			    printf("TFTP: Couldn't allocate fill packet.\n"); 
			    return 0; 
			} 
		  } 
		cn->tf_fport = 0; 
		tfsndreq(cn, rmfile); 
		cn->tf_state = ACKWAIT; 
		cn->tf_expected = 0; 
		flen = NORMLEN; 
		done = 0; 
 
		/* Here's how the main loop for putting data blocks works: 
			We make the request packet and then we enter the main 
			loop. 
 
			SEND current pkt	<-----------------------+ 
			If we haven't filled the data pkt, fill it	| 
			Wait for the ACK				| 
			If timeout, ------------------------------------+ 
			Swap the pkt buffers				| 
			GOTO -------------------------------------------+ 
		*/ 
 
	while(1) { 
		data = (char *)tftp_data(pfill); 
		for(flen=0; flentf_fd); 
			if(CRSEEN) { 
				CRSEEN = 0; 
				if(temp == 0x0a) { 
					data[flen] = temp; 
					continue; 
					} 
				else { 
					HOLDING = 1; 
					HELD = temp; 
					data[flen] = 0; 
					continue; 
					} 
				} 
 
			if(cn->tf_mode == ASCII && temp == 0x0d) 
				CRSEEN = 1; 
			if(temp == EOF) break; 
			data[flen] = temp; 
			if(cn->tf_mode == ASCII && temp == DOS_EOF) 
				break; 
			} 
 
		cn->tf_size += flen; 
 
		while(cn->tf_state == ACKWAIT) tk_block(); 
 
		if(cn->tf_state == TIMEOUT) { 
			printf("TFTP:  Host not responding, giving up.\n"); 
			tfudperr(cn->tf_udp, cn->tf_outp, 
				 ERRTXT, "Retry limit exceeded, giving up"); 
			cn->tf_state = DEAD; 
			tfcleanup(cn); 
			udp_free(pfill); 
			return 0; 
			} 
 
		if(cn->tf_state == RCVACK) { 
			cn->tf_expected++; 
 
			/* Check if we're done */ 
			if(done){ 
				len = tfcleanup(cn); 
				udp_free(pfill); 
				*deltat = cticks - *deltat; 
				if(len==0) 
			printf("TFTP:  tried to transfer zero-length file\n"); 
				return len;  
				} 
			/* If not, resume the loop */ 
			psnd = pfill; 
			pfill = cn->tf_outp; 
			cn->tf_outp = psnd; 
			tfsndata(cn, flen); 
			cn->tf_state = ACKWAIT; 
			if(flen < NORMLEN) done = 1; 
			continue; 
			} 
 
		tfcleanup(cn); 
		udp_free(pfill); 
		return 0; 
		} 
		} 
 
	printf("Falling off the edge!\n"); 
	return 0; 
	}