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

📄 minincftp.c

📁 实现ftp协议客户端的源代码
💻 C
字号:
/* minincftp.c * * Example of a command-line shell interface to FTP using the library. */#define VERSION "3.1.0"#ifdef HAVE_CONFIG_H#	include <config.h>#endif#include <ncftp.h>				/* Library header. */#include <Strn.h>				/* Library header. */#define kKilobyte 1024#define kMegabyte (kKilobyte * 1024)#define kGigabyte ((long) kMegabyte * 1024L)#define kTerabyte ((double) kGigabyte * 1024.0)#if defined(WIN32) || defined(_WINDOWS)#	define sleep WinSleep#endifFTPLibraryInfo li;FTPConnectionInfo fi;static voidUsage(void){	fprintf(stderr, "MiniNcFTP, copyright 1995 by Mike Gleason, NcFTP Software.\n");	fprintf(stderr, "Usage: minincftp [-P port] [-u user] [-p password] hostname\n");	fprintf(stderr, "Library version: %s.\n", gLibNcFTPVersion + 5);#ifdef UNAME	fprintf(stderr, "System: %s.\n", UNAME);#endif	DisposeWinsock();	exit(2);}	/* Usage */static voidAbort(int sigNum){	signal(sigNum, Abort);	/* Hopefully the I/O operation in progress	 * will complete, and we'll abort before	 * it starts a new block.	 */	fi.cancelXfer++;	/* If the user appears to be getting impatient,	 * restore the default signal handler so the	 * next ^C abends the program.	 */	if (fi.cancelXfer >= 2)		signal(sigNum, SIG_DFL);}	/* Abort *//* This will abbreviate a string so that it fits into max characters. * It will use ellipses as appropriate.  Make sure the string has * at least max + 1 characters allocated for it. */static voidAbbrevStr(char *dst, const char *src, size_t max, int mode){	int len;	len = (int) strlen(src);	if (len > (int) max) {		if (mode == 0) {			/* ...Put ellipses at left */			(void) strcpy(dst, "...");			(void) Strncat(dst, src + len - (int) max + 3, max + 1);		} else {			/* Put ellipses at right... */			(void) Strncpy(dst, src, max + 1);			(void) strcpy(dst + max - 3, "...");		}	} else {		(void) Strncpy(dst, src, max + 1);	}}	/* AbbrevStr */static doubleFileSize(double size, const char **uStr0, double *uMult0){	double uMult, uTotal;	const char *uStr;	/* The comparisons below may look odd, but the reason	 * for them is that we only want a maximum of 3 digits	 * before the decimal point.  (I.e., we don't want to	 * see "1017.2 kB", instead we want "0.99 MB".	 */	if (size > (999.5 * kGigabyte)) {		uStr = "TB";		uMult = kTerabyte;	} else if (size > (999.5 * kMegabyte)) {		uStr = "GB";		uMult = kGigabyte;	} else if (size > (999.5 * kKilobyte)) {		uStr = "MB";		uMult = kMegabyte;	} else if (size > 999.5) {		uStr = "kB";		uMult = 1024;	} else {		uStr = "B";		uMult = 1;	}	if (uStr0 != NULL)		*uStr0 = uStr;	if (uMult0 != NULL)		*uMult0 = uMult;	uTotal = size / ((double) uMult);	if (uTotal < 0.0)		uTotal = 0.0;	return (uTotal);}	/* FileSize */static voidPrSizeAndRateMeter(const FTPCIPtr cip, int mode){	double rate;	const char *rStr;	char localName[32];	char line[128];	size_t i;	switch (mode) {		case kPrInitMsg:			if (cip->lname == NULL) {				localName[0] = '\0';			} else {				AbbrevStr(localName, cip->lname, sizeof(localName) - 2, 0);				(void) STRNCAT(localName, ":");			}			(void) fprintf(stderr, "%-32s", localName);			break;		case kPrUpdateMsg:			rate = FileSize(cip->kBytesPerSec * 1024.0, &rStr, NULL);			if (cip->lname == NULL) {				localName[0] = '\0';			} else {				AbbrevStr(localName, cip->lname, sizeof(localName) - 2, 0);				(void) STRNCAT(localName, ":");			}#ifdef PRINTF_LONG_LONG_LLD			(void) sprintf(line, "%-32s  %10lld bytes  %6.2f %s/s",				localName,				(longest_int) (cip->bytesTransferred + cip->startPoint),				rate,				rStr			);#elif defined(PRINTF_LONG_LONG_QD)			(void) sprintf(line, "%-32s  %10qd bytes  %6.2f %s/s",				localName,				(longest_int) (cip->bytesTransferred + cip->startPoint),				rate,				rStr			);#else			(void) sprintf(line, "%-32s  %10ld bytes  %6.2f %s/s",				localName,				(long) (cip->bytesTransferred + cip->startPoint),				rate,				rStr			);#endif			/* Pad the rest of the line with spaces, to erase any			 * stuff that might have been left over from the last			 * update.			 */			for (i=strlen(line); i < 80 - 2; i++)				line[i] = ' ';			line[i] = '\0';			/* Print the updated information. */			(void) fprintf(stderr, "\r%s", line);			break;		case kPrEndMsg:			(void) fprintf(stderr, "\n\r");			break;	}}	/* PrSizeAndRateMeter */static intLs(const FTPCIPtr cip, char *cmdstr, char *lsflag){	int cmd;	int result;	cmd = (cmdstr[0] == 'd') ? 1 : 0;	fflush(stdout);	result = FTPList(cip, STDOUT_FILENO, cmd, lsflag);	return result;}	/* Ls */static voidShell(const FTPCIPtr cip){	char line[256];	char argv[10][80], *cp, *token;	char s1[256];	int i, c1, code;	int argc;	time_t mdtm;	longest_int size;	if (fi.dataPortMode != kPassiveMode) {		printf("Using PORT (non-passive) mode for data connections.\n");	} else {		printf("Using PASV (passive) mode for data connections.\n");	}	printf("Type \"passive\" to toggle between PORT and PASV.\n");	printf("\n");	for (;;) {nextcmd:		code = kNoErr;		printf("MiniNcFTP> ");		memset(line, 0, sizeof(line));		memset(argv, 0, sizeof(argv));		if (fgets(line, sizeof(line), stdin) == NULL)			break;		cp = line;		for (argc=0; argc<10; argc++) {			argv[argc][0] = '\0';			token = strtok(cp, " \n\t\r");			if (token == NULL)				break;			STRNCPY(argv[argc], token);			if (argv[argc][sizeof(argv[0]) - 1] != '\0') {				fprintf(stderr, "parameter too long\n");				goto nextcmd;			}			cp = NULL;		}		printf("\n");		c1 = argv[0][0];		cip->errNo = 0;#define USAGECHECK(a,n) if ((argc - 1) < n) { fprintf(stderr, "Error: \"%s\" requires %d parameter%s.\n", #a, n, "s"); goto nextcmd; }#define USAGECHECK1(a) if ((argc - 1) < 1) { fprintf(stderr, "Error: \"%s\" requires %d parameter%s.\n", #a, 1, ""); goto nextcmd; }		switch (c1) {			case 'c':				if (strcasecmp(argv[0], "cd") == 0) {					/* chdir, cd */					USAGECHECK1(cd)					code = FTPChdir(cip, argv[1]);				} else if (strcasecmp(argv[0], "chmod") == 0) {					USAGECHECK(chmod, 2)					code = FTPChmod(cip, argv[2], argv[1], kGlobYes);				} else goto bad;				break;			case 'd':				if (strcasecmp(argv[0], "dir") == 0) {					code = Ls(cip, argv[0], argv[1]); /* dir */				} else if (strcasecmp(argv[0], "delete") == 0) {					USAGECHECK1(delete)					code = FTPDelete(cip, argv[1], kRecursiveNo, kGlobYes);				} else goto bad;				break;			case 'g':				if (strcasecmp(argv[0], "get1") == 0) {					USAGECHECK(get1, 2)					(void) signal(SIGINT, Abort);					code = FTPGetOneFile3(cip, argv[1], argv[2], kTypeBinary, (-1), kResumeYes, kAppendNo, kDeleteNo, kNoFTPConfirmResumeDownloadProc, 0);					(void) signal(SIGINT, SIG_DFL);					if (cip->bytesTransferred > 0L)						printf("%lu bytes transferred, %.2f kB/sec.\n", (unsigned long) cip->bytesTransferred, cip->kBytesPerSec);				} else if (strcasecmp(argv[0], "get") == 0) {					USAGECHECK1(get)					(void) signal(SIGINT, Abort);					code = FTPGetFiles3(cip, argv[1], argv[2], kRecursiveNo, kGlobYes, kTypeBinary, kResumeYes, kAppendNo, kDeleteNo, kTarNo, kNoFTPConfirmResumeDownloadProc, 0);					(void) signal(SIGINT, SIG_DFL);					if (cip->bytesTransferred > 0L)						printf("%lu bytes transferred, %.2f kB/sec.\n", (unsigned long) cip->bytesTransferred, cip->kBytesPerSec);				} else goto bad;				break;			case 'l':				if (strcasecmp(argv[0], "ls") == 0) {					(void) signal(SIGINT, Abort);					code = Ls(cip, argv[0], argv[1]);					(void) signal(SIGINT, SIG_DFL);					if (cip->bytesTransferred > 0L)						printf("%lu bytes transferred, %.2f kB/sec.\n", (unsigned long) cip->bytesTransferred, cip->kBytesPerSec);				} else if (strcasecmp(argv[0], "lcd") == 0) {					USAGECHECK1(lcd)					if (chdir(argv[1]) < 0) {						perror(argv[1]);					} else {						if (FTPGetLocalCWD(line, sizeof(line)) != NULL) {							printf("Current local directory is: %s\n", line);						}					}				} else goto bad;				break;			case 'm':				if (strcasecmp(argv[0], "mkdir") == 0) {					USAGECHECK1(mkdir)					code = FTPMkdir(cip, argv[1], kRecursiveYes);				} else if (strcasecmp(argv[0], "modtime") == 0) {					USAGECHECK1(modtime)					code = FTPFileModificationTime(cip, argv[1], &mdtm);					printf("%s modtime = %lu.\n",						argv[1], (unsigned long) mdtm);				} else goto bad;				break;			case 'p':				if (strcasecmp(argv[0], "passive") == 0) {					if (fi.dataPortMode == kPassiveMode) {						fi.dataPortMode = kSendPortMode;						printf("Using PORT (non-passive) mode for data connections.\n");					} else {						fi.dataPortMode = kPassiveMode;						printf("Using PASV (passive) mode for data connections.\n");					}				} else if (strcasecmp(argv[0], "pwd") == 0) {					code = FTPGetCWD(cip, s1, sizeof(s1));	/* pwd */					printf("cwd = [%s]\n", s1);				} else if (strcasecmp(argv[0], "put1") == 0) {					USAGECHECK(put1, 2)					(void) signal(SIGINT, Abort);					code = FTPPutOneFile(cip, argv[1], argv[2]);					(void) signal(SIGINT, SIG_DFL);					if (cip->bytesTransferred > 0L)						printf("%lu bytes transferred, %.2f kB/sec.\n", (unsigned long) cip->bytesTransferred, cip->kBytesPerSec);				} else if (strcasecmp(argv[0], "put") == 0) {					USAGECHECK1(put)					(void) signal(SIGINT, Abort);					code = FTPPutFiles(cip, argv[1], argv[2], kRecursiveNo, kGlobYes);					(void) signal(SIGINT, SIG_DFL);					if (cip->bytesTransferred > 0L)						printf("%lu bytes transferred, %.2f kB/sec.\n", (unsigned long) cip->bytesTransferred, cip->kBytesPerSec);				} else goto bad;				break;			case 'q':			case 'Q':				if (strcasecmp(argv[0], "quote") == 0) {					USAGECHECK1(quote)					STRNCPY(s1, argv[1]);					for (i=2; i<10; i++) {						if (argv[i][0] == '\0') break;						STRNCAT(s1, " ");						STRNCAT(s1, argv[i]);					}					FTPCmd(cip, "%s", s1);				} else if (strcasecmp(argv[0], "quit") == 0) {					return;				} else goto bad;				break;			case 'r':				if (strcasecmp(argv[0], "rename") == 0) {					USAGECHECK(rename, 2)					code = FTPRename(cip, argv[1], argv[2]);				} else if (strcasecmp(argv[0], "rmdir") == 0) {					USAGECHECK1(rmdir)					code = FTPRmdir(cip, argv[1], kRecursiveNo, kGlobYes);				} else goto bad;				break;			case 's':				if (strcasecmp(argv[0], "size") == 0) {					USAGECHECK1(size)#ifdef PRINTF_LONG_LONG					code = FTPFileSize(cip, argv[1], &size, 'I');					printf("%s size = " PRINTF_LONG_LONG ".\n", argv[1], size);#else					code = FTPFileSize(cip, argv[1], &size, 'I');					printf("%s size = %lu.\n", argv[1], (unsigned long) size);#endif				} else goto bad;				break;			case 'u':				if (strcasecmp(argv[0], "umask") == 0) {					USAGECHECK1(umask)					code = FTPUmask(cip, argv[1]);				} else goto bad;				break;			case 'X':			case 'x':				return;			case '\0':				break;			default:			bad:				printf("Commands are:  cd      dir    ls      passive quit   rmdir\n");				printf("               chmod   get    mkdir   put     quote  size\n");				printf("               delete  lcd    modtime pwd     rename umask\n");		}		if (code != kNoErr) {			fprintf(stderr, "Return code for %s was %d (%s).\n", argv[0], code, FTPStrError(code));		}	}}	/* Shell */main_void_return_tmain(int argc, char **argv){	int result, c;	GetoptInfo opt;	InitWinsock();	result = FTPInitLibrary(&li);	if (result < 0) {		fprintf(stderr, "Init library error %d.\n", result);		DisposeWinsock();		exit(1);	}	result = FTPInitConnectionInfo(&li, &fi, kDefaultFTPBufSize);	if (result < 0) {		fprintf(stderr, "Init connection info error %d.\n", result);		DisposeWinsock();		exit(1);	}	fi.debugLog = stdout;	fi.errLog = stderr;	fi.progress = PrSizeAndRateMeter;	fi.dataPortMode = kSendPortMode;	STRNCPY(fi.user, "anonymous");	GetoptReset(&opt);	while ((c = Getopt(&opt, argc, argv, "d:e:P:p:u:F")) > 0) switch(c) {		case 'P':			fi.port = atoi(opt.arg);				break;		case 'u':			STRNCPY(fi.user, opt.arg);			break;		case 'p':			STRNCPY(fi.pass, opt.arg);	/* Don't recommend doing this! */			break;		case 'e':			fi.errLog = fopen(opt.arg, "a");			break;		case 'd':			fi.debugLog = fopen(opt.arg, "a");			break;		case 'F':			if (fi.dataPortMode == kPassiveMode)				fi.dataPortMode = kSendPortMode;			else				fi.dataPortMode = kPassiveMode;			break;		default:			Usage();	}	if (opt.ind > argc - 1)		Usage();	if ((strcmp(fi.user, "anonymous") != 0) && (strcmp(fi.user, "ftp") != 0) && (fi.pass[0] == '\0'))		(void) GetPass("Password: ", fi.pass, sizeof(fi.pass));	STRNCPY(fi.host, argv[opt.ind]);	if ((result = FTPOpenHost(&fi)) < 0) {		fprintf(stderr, "Cannot open host: %s.\n", FTPStrError(result));		DisposeWinsock();		exit(1);	}	Shell(&fi);	FTPCloseHost(&fi);	DisposeWinsock();	exit(0);}	/* main */

⌨️ 快捷键说明

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