⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pncftp.c

📁 实现ftp协议客户端的源代码
💻 C
字号:
/* pncftp.c */#ifdef HAVE_CONFIG_H#	include <config.h>#endif#include <ncftp.h>				/* Library header. */#include <Strn.h>				/* Library header. */#include <sio.h>				/* Library header. */#define VERSION "0.9.0 (2004-05-26)"FTPLibraryInfo li;FTPConnectionInfo srcci, dstci;FTPCIPtr pasvhost, porthost;FILE *debugLog = NULL;int timeout = -1;static voidUsage(void){	FILE *fp;	fp = stdout;	(void) fprintf(fp, "Proxy NcFTP %s.\n\n", VERSION);	(void) fprintf(fp, "Usage:\n");	(void) fprintf(fp, "  pncftp [flags] source-host source-path dest-host dest-path\n");	(void) fprintf(fp, "\nHost Parameters:\n\  Are actually allowed to have the following formats:\n\         [user[:pass]@]host[:port]\n\         [user[/path/to/password.txt]@]host[:port]\n\  This allows you to optionally specify usernames, passwords, and port numbers.\n\  Defaults are anonymous user and port 21.\n");	(void) fprintf(fp, "\nFlags:\n\  -a     Use ASCII transfer type instead of binary.\n\  -A     Use PASV on source host and PORT on destination host (default)\n\  -B     Use PORT on source host and PASV on destination host\n\  -d XX  Use the file XX for debug logging (for stdout, use \"-\").\n\  -DD    Attempt to delete the source file after successfully uploading it.\n\  -f     Force overwrite of destination file if it already exists.\n\  -m     Attempt to mkdir the dstdir before copying.\n\  -o XX  Start transferring from offset XX bytes.\n\  -O XX  Specify miscellaneous options (see documentation).\n\  -t XX  Timeout after XX seconds.\n\  -U XX  Attempt to use value XX for the umask on destination host.\n\  -z     Resume transfer of destination file if it already exists.\n");	(void) fprintf(fp, "\nExample:\n\  pncftp -d - joeuser:joespassword@ftp.joe.com /joesfiles/6gigs ftp.example.com /pub/incoming/sixgigfile\n");	(void) fprintf(fp, "\nLibrary version: %s.\n", gLibNcFTPVersion + 5);	(void) fprintf(fp, "\nThis is a freeware program by Mike Gleason (http://www.NcFTP.com/contact/).\n");	(void) fprintf(fp, "This was built using LibNcFTP (http://www.ncftp.com/libncftp).\n");	DisposeWinsock();	exit(2);}	/* Usage */static voidPNcFTPLogProc(const FTPCIPtr cip, char *line){	const char *pfx;	time_t t;	char tstr[64];		if (debugLog == NULL)		return;			time(&t);	strftime(tstr, sizeof(tstr) - 1, "%Y-%m-%d %H:%M:%S", localtime(&t));	if (cip == &srcci) {		pfx = "SRC";	} else {		pfx = "DST";	}	fprintf(debugLog, "%s | %s | %s", tstr, pfx, line);	if (line[strlen(line) - 1] != '\n')		fprintf(debugLog, "\n");		fflush(debugLog);}	/* PNcFTPLogProc */static longest_inta_to_ll(const char *const str){	longest_int ll;#if defined(HAVE_LONG_LONG) && defined(SCANF_LONG_LONG)	ll = (longest_int) 0;	(void) sscanf(str, SCANF_LONG_LONG, &ll);#elif defined(HAVE_LONG_LONG) && defined(HAVE_STRTOQ)	ll = (longest_int) strtoq(str, NULL, 0);#else	ll = (longest_int) 0;	(void) sscanf(str, "%ld", &ll);#endif	return (ll);}	/* a_to_ll */static intGet1Response(const FTPCIPtr cip){	int result;	int respCode;	ResponsePtr rp;	rp = InitResponse();	if (rp == NULL) {		cip->errNo = kErrMallocFailed;		result = cip->errNo;		return (result);	}	result = GetResponse(cip, rp);	if (result < 0)		return (result);	respCode = rp->codeType;	DoneWithResponse(cip, rp);	if (respCode > 2) {		result = -1;	} else {		result = kNoErr;	}		return (result);}	/* Get1Response */#if (defined(WIN32) || defined(_WINDOWS)) && !defined(__CYGWIN__)#       define MY_FD_ZERO FD_ZERO#       define MY_FD_SET(s,set) FD_SET((SOCKET) (s), set)#       define MY_FD_CLR(s,set) FD_CLR((SOCKET) (s), set)#       define MY_FD_ISSET FD_ISSET#else#       define MY_FD_ZERO FD_ZERO#       define MY_FD_SET FD_SET#       define MY_FD_CLR FD_CLR#       define MY_FD_ISSET FD_ISSET#endifstatic voidWaitForResponses(int srcfd, int *srcrc, int dstfd, int *dstrc, int stopearlyiferr, int secs){	int result;	fd_set ss;	struct timeval tv;	int fdmax;	int srcdone = 0, dstdone = 0;	int rc;	int secsWaited = 0;		*srcrc = *dstrc = 0;	fdmax = srcci.ctrlSocketR;	if (srcci.ctrlSocketR < dstci.ctrlSocketR)		fdmax = dstci.ctrlSocketR;			forever {		if (srcfd < 0)			srcdone++;		if (dstfd < 0)			dstdone++;		if (srcdone && dstdone)			break;		if (!srcdone && !dstdone)			PrintF(&srcci, "Waiting for %s and %s to reply.\n", srcci.host, dstci.host);		else if (!dstdone)			PrintF(&dstci, "Waiting for %s to reply.\n", dstci.host);		else if (!srcdone)			PrintF(&srcci, "Waiting for %s to reply.\n", srcci.host);		MY_FD_ZERO(&ss);#if defined(__DECC) || defined(__DECCXX)#pragma message save#pragma message disable trunclongint#endif		if (srcfd >= 0)			MY_FD_SET(srcfd, &ss);		if (dstfd >= 0)			MY_FD_SET(dstfd, &ss);#if defined(__DECC) || defined(__DECCXX)#pragma message restore#endif		tv.tv_sec = (tv_sec_t) secs;		tv.tv_usec = 0;		do {			errno = 0;			result = select(fdmax + 1, SELECT_TYPE_ARG234 &ss, NULL, NULL, &tv);		} while ((result < 0) && (errno == EINTR));		if (result > 0) {			if ((srcfd >= 0) && MY_FD_ISSET(srcfd, &ss)) {				*srcrc = rc = Get1Response(&srcci);				if ((rc < 0) && (stopearlyiferr != 0)) {					/* Close the other one early */					FTPCloseControlConnection(&dstci);					return;				}				srcdone++;			}			if ((dstfd >= 0) && MY_FD_ISSET(dstfd, &ss)) {				*dstrc = rc = Get1Response(&dstci);				if ((rc < 0) && (stopearlyiferr != 0)) {					/* Close the other one early */					FTPCloseControlConnection(&srcci);					return;				}				dstdone++;			}		} else if (result == 0) {			secsWaited += secs;			if (secsWaited >= timeout) {				PrintF(&srcci, "Timed-out (%d seconds), aborting.\n", timeout);				FTPCloseControlConnection(&srcci);				FTPCloseControlConnection(&dstci);				return;			}		}	}}	/* WaitForResponses */main_void_return_tmain(int argc, char **argv){	int c;	int es = 0;	int rc, srcrc, dstrc;	longest_int startPoint = (longest_int) 0;	GetoptInfo opt;	struct sockaddr_in pasvaddr;	int type = kTypeBinary;	char *srcpath, *dstpath, *dstdir = NULL, *cp;	int sfd, dfd;	struct timeval t0;	double elapsed = -1.0;	longest_int dstsize = kSizeUnknown;	longest_int srcsize = kSizeUnknown;	time_t srcmdtm = kModTimeUnknown;	time_t dstmdtm = kModTimeUnknown;	int forceOverwrite = 0, tryResume = 0;	char *Umask = NULL;	int nD = 0;	int wantMkdir = 0;	char dstcwd[128];		InitWinsock();	rc = FTPInitLibrary(&li);	if (rc < 0) {		fprintf(stderr, "pncftp: init library error %d (%s).\n", rc, FTPStrError(rc));		exit(1);	}	rc = FTPInitConnectionInfo(&li, &srcci, kDefaultFTPBufSize);	if (rc < 0) {		fprintf(stderr, "pncftp: init connection info error %d (%s).\n", rc, FTPStrError(rc));		exit(3);	}	rc = FTPInitConnectionInfo(&li, &dstci, kDefaultFTPBufSize);	if (rc < 0) {		fprintf(stderr, "pncftp: init connection info error %d (%s).\n", rc, FTPStrError(rc));		exit(3);	}	GetoptReset(&opt);	srcci.debugLogProc = PNcFTPLogProc;	dstci.debugLogProc = PNcFTPLogProc;	srcci.maxDials = 1;	dstci.maxDials = 1;	pasvhost = &srcci;	porthost = &dstci;		while ((c = Getopt(&opt, argc, argv, "ABad:Dfmto:O:U:z")) > 0) switch(c) {		case 'A':			pasvhost = &srcci;			porthost = &dstci;			break;		case 'B':			pasvhost = &dstci;			porthost = &srcci;			break;		case 'd':			if (opt.arg[0] == '-')				debugLog = stdout;			else if (strcmp(opt.arg, "stderr") == 0)				debugLog = stderr;			else if (strcmp(opt.arg, "stdout") == 0)				debugLog = stdout;			else				debugLog = fopen(opt.arg, "a");			break;		case 'D':			/* Require two -D's in case they typo. */			nD++;			break;		case 'f':			forceOverwrite = 1;			break;		case 'm':			wantMkdir = 1;			break;		case 't':			timeout = atoi(optarg);			break;		case 'z':			tryResume = 1;			break;		case 'o':			startPoint = a_to_ll(opt.arg);			break;		case 'O':			srcci.manualOverrideFeatures = opt.arg;			dstci.manualOverrideFeatures = opt.arg;			break;		case 'U':			Umask = opt.arg;			break;		default:			Usage();	}	if (opt.ind > argc - 4)		Usage();	/* Get the hostnames */	rc = FTPDecodeHostName(&srcci, argv[opt.ind]);	if (rc < 0) {		(void) fprintf(stderr, "Malformed source hostname: %s\n", argv[opt.ind]);		DisposeWinsock();		exit(4);	}	srcpath = argv[opt.ind + 1];	rc = FTPDecodeHostName(&dstci, argv[opt.ind + 2]);	if (rc < 0) {		(void) fprintf(stderr, "Malformed destination hostname: %s\n", argv[opt.ind + 2]);		DisposeWinsock();		exit(4);	}	dstpath = argv[opt.ind + 3];			/* Open the hosts */	(void) gettimeofday(&t0, NULL);	if ((rc = FTPOpenHost(&dstci)) < 0) {		FTPPerror(&dstci, rc, 0, "Could not open destination host", dstci.host);		DisposeWinsock();		exit(5);	}	if ((rc = FTPOpenHost(&srcci)) < 0) {		FTPPerror(&srcci, rc, 0, "Could not open source host", srcci.host);		FTPCloseHost(&dstci);		DisposeWinsock();		exit(6);	}	/* Try to create the remote destination directory, if asked. */	if ((wantMkdir != 0) && (Dynscpy(&dstdir, dstpath, 0) != NULL)) {		cp = StrRFindLocalPathDelim(dstdir + 1);		if (cp != NULL) {			*cp = '\0';			rc = FTPGetCWD(&dstci, dstcwd, sizeof(dstcwd));			rc = FTPChdir3(&dstci, dstdir, NULL, 0, kChdirFullPath|kChdirOneSubdirAtATime|kChdirAndMkdir);			if (rc != kNoErr) {				PrintF(&dstci, "Could not create remote directory on destination host %s.\n", dstci.host);			}			rc = FTPChdir(&dstci, dstcwd);		}	}			/* Check the source file's size, if possible. */	rc = FTPFileSizeAndModificationTime(&srcci, srcpath, &srcsize, kTypeBinary, &srcmdtm);	rc = FTPFileSizeAndModificationTime(&dstci, dstpath, &dstsize, kTypeBinary, &dstmdtm);	if (dstsize > 0) {		if ((srcsize > 0) && (tryResume != 0)) {			if (dstsize > srcsize) {				PrintF(&srcci, "Destination file exists and is larger than the source file, aborting.\n");				es = 7;				goto quit;			} else if (dstsize == srcsize) {				PrintF(&srcci, "Destination file exists and is already the same size as the source file.\n");				exit(0);	/* Not an error */			} else {				startPoint = dstsize;			}		} else if (forceOverwrite == 0) {			PrintF(&srcci, "Destination file exists, aborting.\n");			es = 8;			goto quit;		}	}	/* Set the umask on the destination host, if asked. */        if (Umask != NULL) {                rc = FTPUmask(&dstci, Umask);                if (rc != 0)                        FTPPerror(&dstci, rc, kErrUmaskFailed, "Could not set umask", Umask);        }	/* Set TYPE I or A on each host */	if ((rc = FTPSetTransferType(&srcci, type)) < 0) {		FTPPerror(porthost, rc, 0, "Could not set TYPE on source host", srcci.host);		es = 9;		goto quit;	}			if ((rc = FTPSetTransferType(&dstci, type)) < 0) {		FTPPerror(porthost, rc, kErrTYPEFailed, "Could not set TYPE on destination host", dstci.host);		es = 10;		goto quit;	}		/* Setup the data connection addresses. */	if ((rc = FTPSendPassive(pasvhost, &pasvaddr, NULL)) != 0) {		FTPPerror(pasvhost, rc, kErrPASVFailed, "PASV failed on host", pasvhost->host);		es = 11;		goto quit;	}	if ((rc = FTPSendPort(porthost, &pasvaddr)) != 0) {		FTPPerror(porthost, rc, kErrPORTFailed, "PORT failed on host", porthost->host);		es = 12;		goto quit;	}	/* If asked, attempt to start at a later position in the remote file. */	if (startPoint != (longest_int) 0) {		if ((startPoint == kSizeUnknown) || ((rc = FTPSetStartOffset(&dstci, startPoint)) != 0))			startPoint = (longest_int) 0;		if ((startPoint == kSizeUnknown) || ((rc = FTPSetStartOffset(&srcci, startPoint)) != 0))			startPoint = (longest_int) 0;	}	dstci.startPoint = startPoint;	srcci.startPoint = startPoint;	/* Start the proxy transfer. */	PrintF(&srcci, "Attempting proxy transfer from source host %s to destination host %s.\n", srcci.host, dstci.host);	(void) gettimeofday(&t0, NULL);	if (pasvhost == &srcci) {		if ((rc = FTPCmdNoResponse(&srcci, "RETR %s", srcpath)) != 0) {			FTPPerror(porthost, rc, kErrCouldNotStartDataTransfer, "Could not start download on source host", srcci.host);			es = 13;			goto quit;		}		if ((rc = FTPCmdNoResponse(&dstci, "STOR %s", dstpath)) != 0) {			FTPPerror(porthost, rc, kErrCouldNotStartDataTransfer, "Could not start upload on destination host", dstci.host);			es = 14;			goto quit;		}	} else {		if ((rc = FTPCmdNoResponse(&dstci, "STOR %s", dstpath)) != 0) {			FTPPerror(porthost, rc, kErrCouldNotStartDataTransfer, "Could not start upload on destination host", dstci.host);			es = 14;			goto quit;		}		if ((rc = FTPCmdNoResponse(&srcci, "RETR %s", srcpath)) != 0) {			FTPPerror(porthost, rc, kErrCouldNotStartDataTransfer, "Could not start download on source host", srcci.host);			es = 13;			goto quit;		}	}	dfd = dstci.ctrlSocketR;	sfd = srcci.ctrlSocketR;	WaitForResponses(sfd, &srcrc, dfd, &dstrc, 1, 5);	if (srcrc != 0) {		PrintF(&srcci, "Could not start download on source host %s.\n", srcci.host);		es = 15;		sfd = -1;	}	if (dstrc != 0) {		PrintF(&dstci, "Could not start upload on destination host %s.\n", dstci.host);		es = 16;		dfd = -1;	}	if (es == 0) {		if (srcsize > 0) {			PrintF(&srcci, "Proxy transfer of " PRINTF_LONG_LONG " bytes from source host %s to destination host %s has started.\n", srcsize, srcci.host, dstci.host);		} else {			PrintF(&srcci, "Proxy transfer from source host %s to destination host %s has started.\n", srcci.host, dstci.host);		}		WaitForResponses(sfd, &srcrc, dfd, &dstrc, 0, 60);		if (srcrc != 0) {			PrintF(&dstci, "Download from source host %s failed.\n", srcci.host);			es = 17;		}		if (dstrc != 0) {			PrintF(&dstci, "Upload to destination host %s failed.\n", dstci.host);			es = 18;		}		elapsed = FTPDuration(&t0);		if (es == 0) {			if ((nD >= 2) && (FTPDelete(&srcci, srcpath, kRecursiveNo, kGlobNo) != kNoErr)) {				PrintF(&srcci, "Could not delete source file %s after successful transfer to destination host.\n", srcpath);			}			(void) FTPUtime(&dstci, dstpath, srcmdtm, srcmdtm, srcmdtm);			rc = FTPFileSizeAndModificationTime(&dstci, dstpath, &dstsize, kTypeBinary, &dstmdtm);		}	}	quit:	if (elapsed < 0)		elapsed = FTPDuration(&t0);	FTPCloseHost(&dstci);	FTPCloseHost(&srcci);	DisposeWinsock();	if (es == 0) {		if (dstsize > 0) {			printf("Done.  "  PRINTF_LONG_LONG " bytes in %.2f seconds (%.1f kB/sec).\n", dstsize, elapsed, (double) dstsize / 1024.0);		} else if (srcsize > 0) {			printf("Done.  "  PRINTF_LONG_LONG " bytes in %.2f seconds (%.1f kB/sec).\n", dstsize, elapsed, (double) srcsize / 1024.0);		} else {			printf("Done.  Elapsed Time = %.2f seconds.\n", elapsed);		}	} else {		printf("ERROR(%d).  Elapsed Time = %.2f seconds.\n", es, elapsed);	}	exit(es);}	/* main *//* EOF pncftp.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -