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

📄 cmds.c

📁 UNIX FTP client
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1985, 1989 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* * from: @(#)cmds.c	5.26 (Berkeley) 3/5/91 */char cmds_rcsid[] =    "$Id: cmds.c,v 1.19 1997/06/08 20:07:19 dholland Exp $";/* * FTP User Program -- Command Routines. */#include <sys/param.h>#include <sys/wait.h>#include <sys/stat.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/ip.h>#include <arpa/ftp.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <netdb.h>#include <ctype.h>#include <limits.h>#include <time.h>#include <string.h>#include <unistd.h>#ifdef __USE_READLINE__#include <readline/readline.h>#include <readline/history.h>#endif#include "ftp_var.h"#include "pathnames.h"#include "cmds.h"#include "glob.h"void intr(int);extern FILE *cout;extern int data;extern const char *home;extern off_t restart_point;extern char reply_string[];static char *mname;static sigjmp_buf jabort;static sigjmp_buf abortprox;static char *remglob(char *argv[], int doswitch);static char *dotrans(char *name);static char *domap(char *name);static char *globulize(char *str);static int confirm(const char *cmd, const char *file);static int getit(int argc, char *argv[], int restartit, const char *modestr);static void quote1(const char *initial, int argc, char **argv);/* * `Another' gets another argument, and stores the new argc and argv. * It reverts to the top level (via main.c's intr()) on EOF/error. * * Returns false if no new arguments have been added. */intanother(int *pargc, char ***pargv, const char *prompt){	int margc;	char **margv;	unsigned len = strlen(line);	int ret;	if (len >= sizeof(line) - 3) {		printf("sorry, arguments too long\n");		intr(0);	}	printf("(%s) ", prompt);	line[len++] = ' ';	if (fgets(&line[len], sizeof(line) - len, stdin) == NULL)		intr(0);	len += strlen(&line[len]);	if (len > 0 && line[len - 1] == '\n')		line[len - 1] = '\0';	margv = makeargv(&margc, NULL);	ret = margc > *pargc;	*pargc = margc;	*pargv = margv;	return ret;}/* * Connect to peer server and * auto-login, if possible. */voidsetpeer(int argc, char *argv[]){	char *host;	short port;	if (connected) {		printf("Already connected to %s, use close first.\n",			hostname);		code = -1;		return;	}	if (argc < 2)		(void) another(&argc, &argv, "to");	if (argc < 2 || argc > 3) {		printf("usage: %s host-name [port]\n", argv[0]);		code = -1;		return;	}	port = ftp_port;	if (argc > 2) {		port = atoi(argv[2]);		if (port <= 0) {			printf("%s: bad port number-- %s\n", argv[1], argv[2]);			printf ("usage: %s host-name [port]\n", argv[0]);			code = -1;			return;		}		port = htons(port);	}	host = hookup(argv[1], port);	if (host) {		int overbose;		connected = 1;		/*		 * Set up defaults for FTP.		 */		(void) strcpy(typename, "ascii"), type = TYPE_A;		curtype = TYPE_A;		(void) strcpy(formname, "non-print"), form = FORM_N;		(void) strcpy(modename, "stream"), mode = MODE_S;		(void) strcpy(structname, "file"), stru = STRU_F;		(void) strcpy(bytename, "8"), bytesize = 8;		if (autologin)			(void) dologin(argv[1]);#if defined(unix) && CHAR_BIT == 8/* * this ifdef is to keep someone form "porting" this to an incompatible * system and not checking this out. This way they have to think about it. */		overbose = verbose;		if (debug == 0)			verbose = -1;		if (command("SYST") == COMPLETE && overbose) {			register char *cp, c = 0;			cp = index(reply_string+4, ' ');			if (cp == NULL)				cp = index(reply_string+4, '\r');			if (cp) {				if (cp[-1] == '.')					cp--;				c = *cp;				*cp = '\0';			}			printf("Remote system type is %s.\n",				reply_string+4);			if (cp)				*cp = c;		}		if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) {			if (proxy)				unix_proxy = 1;			else				unix_server = 1;			/*			 * Set type to 0 (not specified by user),			 * meaning binary by default, but don't bother			 * telling server.  We can use binary			 * for text files unless changed by the user.			 */			type = 0;			(void) strcpy(typename, "binary");			if (overbose)			    printf("Using %s mode to transfer files.\n",				typename);		} else {			if (proxy)				unix_proxy = 0;			else				unix_server = 0;			if (overbose && 			    !strncmp(reply_string, "215 TOPS20", 10))				printf("Remember to set tenex mode when transfering binary files from this machine.\n");		}		verbose = overbose;#else#warn "Unix auto-mode code skipped"#endif /* unix */	}}struct	types {	const char *t_name;	const char *t_mode;	int t_type;	const char *t_arg;} types[] = {	{ "ascii",	"A",	TYPE_A,	NULL },	{ "binary",	"I",	TYPE_I,	NULL },	{ "image",	"I",	TYPE_I,	NULL },	{ "ebcdic",	"E",	TYPE_E,	NULL },	{ "tenex",	"L",	TYPE_L,	bytename },	{ NULL, NULL, 0, NULL }};/* * Set transfer type. */static voiddo_settype(const char *thetype) {	struct types *p;	int comret;	for (p = types; p->t_name; p++)		if (strcmp(thetype, p->t_name) == 0)			break;	if (p->t_name == 0) {		printf("%s: unknown mode\n", thetype);		code = -1;		return;	}	if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))		comret = command("TYPE %s %s", p->t_mode, p->t_arg);	else		comret = command("TYPE %s", p->t_mode);	if (comret == COMPLETE) {		(void) strcpy(typename, p->t_name);		curtype = type = p->t_type;	}}voidsettype(int argc, char *argv[]){	struct types *p;	if (argc > 2) {		const char *sep;		printf("usage: %s [", argv[0]);		sep = " ";		for (p = types; p->t_name; p++) {			printf("%s%s", sep, p->t_name);			sep = " | ";		}		printf(" ]\n");		code = -1;		return;	}	if (argc < 2) {		printf("Using %s mode to transfer files.\n", typename);		code = 0;		return;	}	do_settype(argv[1]);}/* * Internal form of settype; changes current type in use with server * without changing our notion of the type for data transfers. * Used to change to and from ascii for listings. */voidchangetype(int newtype, int show){	register struct types *p;	int comret, oldverbose = verbose;	int oldtick = tick;	if (newtype == 0)		newtype = TYPE_I;	if (newtype == curtype)		return;	if (debug == 0 && show == 0)		verbose = 0;	tick = 0;	for (p = types; p->t_name; p++)		if (newtype == p->t_type)			break;	if (p->t_name == 0) {		printf("ftp: internal error: unknown type %d\n", newtype);		return;	}	if (newtype == TYPE_L && bytename[0] != '\0')		comret = command("TYPE %s %s", p->t_mode, bytename);	else		comret = command("TYPE %s", p->t_mode);	if (comret == COMPLETE)		curtype = newtype;	verbose = oldverbose;	tick = oldtick;}/* * Set binary transfer type. *//*VARARGS*/voidsetbinary(void){	do_settype("binary");}/* * Set ascii transfer type. *//*VARARGS*/voidsetascii(void){	do_settype("ascii");}/* * Set tenex transfer type. *//*VARARGS*/voidsettenex(void){	do_settype("tenex");}/* * Set file transfer mode. *//*ARGSUSED*/voidsetmode(void){	printf("We only support %s mode, sorry.\n", modename);	code = -1;}/* * Set file transfer format. *//*ARGSUSED*/voidsetform(void){	printf("We only support %s format, sorry.\n", formname);	code = -1;}/* * Set file transfer structure. */voidsetstruct(void){	printf("We only support %s structure, sorry.\n", structname);	code = -1;}/* * Send a single file. */voidput(int argc, char *argv[]){	const char *cmd;	int loc = 0;	char *oldargv1, *oldargv2;	if (argc == 2) {		argc++;		argv[2] = argv[1];		loc++;	}	if (argc < 2 && !another(&argc, &argv, "local-file"))		goto usage;	if (argc < 3 && !another(&argc, &argv, "remote-file")) {usage:		printf("usage: %s local-file remote-file\n", argv[0]);		code = -1;		return;	}	oldargv1 = argv[1];	oldargv2 = argv[2];	argv[1] = globulize(argv[1]);	if (!argv[1]) {		code = -1;		return;	}	/*	 * If "globulize" modifies argv[1], and argv[2] is a copy of	 * the old argv[1], make it a copy of the new argv[1].	 */	if (argv[1] != oldargv1 && argv[2] == oldargv1) {		argv[2] = argv[1];	}	cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR");	if (loc && ntflag) {		argv[2] = dotrans(argv[2]);	}	if (loc && mapflag) {		argv[2] = domap(argv[2]);	}	sendrequest(cmd, argv[1], argv[2],	    argv[1] != oldargv1 || argv[2] != oldargv2);}void mabort(int);/* * Send multiple files. */voidmput(int argc, char *argv[]){	register int i;	void (*oldintr)(int);	int ointer;	char *tp;	if (argc < 2 && !another(&argc, &argv, "local-files")) {		printf("usage: %s local-files\n", argv[0]);		code = -1;		return;	}	mname = argv[0];	mflag = 1;	oldintr = signal(SIGINT, mabort);	(void) sigsetjmp(jabort, 1);	if (proxy) {		char *cp, *tp2, tmpbuf[MAXPATHLEN];		while ((cp = remglob(argv,0)) != NULL) {			if (*cp == 0) {				mflag = 0;				continue;			}			if (mflag && confirm(argv[0], cp)) {				tp = cp;				if (mcase) {					while (*tp && !islower(*tp)) {						tp++;					}					if (!*tp) {						tp = cp;						tp2 = tmpbuf;						while ((*tp2 = *tp) != '\0') {						     if (isupper(*tp2)) {						        *tp2 = 'a' + *tp2 - 'A';						     }						     tp++;						     tp2++;						}					}					tp = tmpbuf;				}				if (ntflag) {					tp = dotrans(tp);				}				if (mapflag) {					tp = domap(tp);				}				sendrequest((sunique) ? "STOU" : "STOR",				    cp, tp, cp != tp || !interactive);				if (!mflag && fromatty) {					ointer = interactive;					interactive = 1;					if (confirm("Continue with","mput")) {						mflag++;					}					interactive = ointer;				}			}		}		(void) signal(SIGINT, oldintr);		mflag = 0;		return;	}	for (i = 1; i < argc; i++) {		register char **cpp, **gargs;		if (!doglob) {			if (mflag && confirm(argv[0], argv[i])) {				tp = (ntflag) ? dotrans(argv[i]) : argv[i];				tp = (mapflag) ? domap(tp) : tp;				sendrequest((sunique) ? "STOU" : "STOR",				    argv[i], tp, tp != argv[i] || !interactive);				if (!mflag && fromatty) {					ointer = interactive;					interactive = 1;					if (confirm("Continue with","mput")) {						mflag++;					}					interactive = ointer;				}			}			continue;		}		gargs = ftpglob(argv[i]);		if (globerr != NULL) {			printf("%s\n", globerr);			if (gargs) {				blkfree(gargs);				free((char *)gargs);			}			continue;		}		for (cpp = gargs; cpp && *cpp != NULL; cpp++) {			if (mflag && confirm(argv[0], *cpp)) {				tp = (ntflag) ? dotrans(*cpp) : *cpp;				tp = (mapflag) ? domap(tp) : tp;				sendrequest((sunique) ? "STOU" : "STOR",				    *cpp, tp, *cpp != tp || !interactive);				if (!mflag && fromatty) {					ointer = interactive;					interactive = 1;					if (confirm("Continue with","mput")) {						mflag++;					}					interactive = ointer;				}			}		}		if (gargs != NULL) {			blkfree(gargs);			free((char *)gargs);		}	}	(void) signal(SIGINT, oldintr);	mflag = 0;}voidreget(int argc, char *argv[]){	(void) getit(argc, argv, 1, "r+w");}voidget(argc, argv)	int argc;	char *argv[];{	(void) getit(argc, argv, 0, restart_point ? "r+w" : "w" );}/* * Receive one file. */static intgetit(int argc, char *argv[], int restartit, const char *modestr){	int loc = 0;	char *oldargv1, *oldargv2;	if (argc == 2) {		argc++;		argv[2] = argv[1];		loc++;	}	if (argc < 2 && !another(&argc, &argv, "remote-file"))		goto usage;	if (argc < 3 && !another(&argc, &argv, "local-file")) {usage:		printf("usage: %s remote-file [ local-file ]\n", argv[0]);		code = -1;		return (0);	}	oldargv1 = argv[1];	oldargv2 = argv[2];	argv[2] = globulize(argv[2]);	if (!argv[2]) {		code = -1;		return (0);	}	if (loc && mcase) {		char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];		while (*tp && !islower(*tp)) {			tp++;		}		if (!*tp) {			tp = argv[2];			tp2 = tmpbuf;			while ((*tp2 = *tp) != '\0') {				if (isupper(*tp2)) {					*tp2 = 'a' + *tp2 - 'A';				}				tp++;				tp2++;			}			argv[2] = tmpbuf;		}	}	if (loc && ntflag)		argv[2] = dotrans(argv[2]);	if (loc && mapflag)		argv[2] = domap(argv[2]);	if (restartit) {		struct stat stbuf;		int ret;		ret = stat(argv[2], &stbuf);		if (restartit == 1) {			if (ret < 0) {				fprintf(stderr, "local: %s: %s\n", argv[2],					strerror(errno));				return (0);			}			restart_point = stbuf.st_size;		} else {			if (ret == 0) {				int overbose;				overbose = verbose;				if (debug == 0)					verbose = -1;				if (command("MDTM %s", argv[1]) == COMPLETE) {					int yy, mo, day, hour, min, sec;					struct tm *tm;					verbose = overbose;					sscanf(reply_string,					    "%*s %04d%02d%02d%02d%02d%02d",					    &yy, &mo, &day, &hour, &min, &sec);					tm = gmtime(&stbuf.st_mtime);					tm->tm_mon++;/* Indentation is misleading, but changes keep small. */					if (tm->tm_year > yy%100)						return (1);					else if (tm->tm_year == yy%100)						if (tm->tm_mon > mo)							return (1);					else if (tm->tm_mon == mo)						if (tm->tm_mday > day)							return (1);					else if (tm->tm_mday == day)						if (tm->tm_hour > hour)							return (1);					else if (tm->tm_hour == hour)						if (tm->tm_min > min)							return (1);					else if (tm->tm_min == min)						if (tm->tm_sec > sec)							return (1);				} else {					printf("%s\n", reply_string);					verbose = overbose;					return (0);				}			}		}	}	recvrequest("RETR", argv[2], argv[1], modestr,		    argv[1] != oldargv1 || argv[2] != oldargv2);	restart_point = 0;	return (0);}voidmabort(int ignore){	int ointer;	(void)ignore;	printf("\n");	(void) fflush(stdout);	if (mflag && fromatty) {		ointer = interactive;		interactive = 1;		if (confirm("Continue with", mname)) {			interactive = ointer;			siglongjmp(jabort,0);		}		interactive = ointer;	}	mflag = 0;	siglongjmp(jabort,0);}/* * Get multiple files. */voidmget(argc, argv)	int argc;	char **argv;{	void (*oldintr)(int);	int ointer;	char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN];	if (argc < 2 && !another(&argc, &argv, "remote-files")) {		printf("usage: %s remote-files\n", argv[0]);		code = -1;		return;	}	mname = argv[0];	mflag = 1;	oldintr = signal(SIGINT,mabort);	(void) sigsetjmp(jabort, 1);	while ((cp = remglob(argv,proxy)) != NULL) {		if (*cp == '\0') {

⌨️ 快捷键说明

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