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

📄 ftpcmd.y

📁 伯克利大学的一个ftp协议的实现源代码,包括客户端和服务器端.
💻 Y
📖 第 1 页 / 共 2 页
字号:
		}	| L SP byte_size		{			cmd_type = TYPE_L;			cmd_bytesz = $3;		}		/* this is for a bug in the BBN ftp */	| L byte_size		{			cmd_type = TYPE_L;			cmd_bytesz = $2;		}	;struct_code	: F		{			$$ = STRU_F;		}	| R		{			$$ = STRU_R;		}	| P		{			$$ = STRU_P;		}	;mode_code	: S		{			$$ = MODE_S;		}	| B		{			$$ = MODE_B;		}	| C		{			$$ = MODE_C;		}	;pathname	: pathstring		{			/*			 * Problem: this production is used for all pathname			 * processing, but only gives a 550 error reply.			 * This is a valid reply in some cases but not in others.			 */			if (logged_in && $1 && *$1 == '~') {				glob_t gl;#ifdef __linux__				/* see popen.c */				int flags = GLOB_NOCHECK;#else				int flags =				 GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;#endif				memset(&gl, 0, sizeof(gl));				if (glob($1, flags, NULL, &gl) ||				    gl.gl_pathc == 0) {					reply(550, "not found");					$$ = NULL;				} else {					$$ = strdup(gl.gl_pathv[0]);				}				globfree(&gl);				free($1);			} else				$$ = $1;		}	;pathstring	: STRING	;octal_number	: NUMBER		{			int ret, dec, multby, digit;			/*			 * Convert a number that was read as decimal number			 * to what it would be if it had been read as octal.			 */			dec = $1;			multby = 1;			ret = 0;			while (dec) {				digit = dec%10;				if (digit > 7) {					ret = -1;					break;				}				ret += digit * multby;				multby *= 8;				dec /= 10;			}			$$ = ret;		}	;check_login	: /* empty */		{			if (logged_in)				$$ = 1;			else {				reply(530, "Please login with USER and PASS.");				$$ = 0;			}		}	;%%extern jmp_buf errcatch;#define	CMD	0	/* beginning of command */#define	ARGS	1	/* expect miscellaneous arguments */#define	STR1	2	/* expect SP followed by STRING */#define	STR2	3	/* expect STRING */#define	OSTR	4	/* optional SP then STRING */#define	ZSTR1	5	/* SP then optional STRING */#define	ZSTR2	6	/* optional STRING after SP */#define	SITECMD	7	/* SITE command */#define	NSTR	8	/* Number followed by a string */struct tab {	const char	*name;	short	token;	short	state;	short	implemented;	/* 1 if command is implemented */	const char	*help;};struct tab cmdtab[] = {		/* In order defined in RFC 765 */	{ "USER", USER, STR1, 1,	"<sp> username" },	{ "PASS", PASS, ZSTR1, 1,	"<sp> password" },	{ "ACCT", ACCT, STR1, 0,	"(specify account)" },	{ "SMNT", SMNT, ARGS, 0,	"(structure mount)" },	{ "REIN", REIN, ARGS, 0,	"(reinitialize server state)" },	{ "QUIT", QUIT, ARGS, 1,	"(terminate service)", },	{ "PORT", PORT, ARGS, 1,	"<sp> b0, b1, b2, b3, b4" },	{ "PASV", PASV, ARGS, 1,	"(set server in passive mode)" },	{ "TYPE", TYPE, ARGS, 1,	"<sp> [ A | E | I | L ]" },	{ "STRU", STRU, ARGS, 1,	"(specify file structure)" },	{ "MODE", MODE, ARGS, 1,	"(specify transfer mode)" },	{ "RETR", RETR, STR1, 1,	"<sp> file-name" },	{ "STOR", STOR, STR1, 1,	"<sp> file-name" },	{ "APPE", APPE, STR1, 1,	"<sp> file-name" },	{ "MLFL", MLFL, OSTR, 0,	"(mail file)" },	{ "MAIL", MAIL, OSTR, 0,	"(mail to user)" },	{ "MSND", MSND, OSTR, 0,	"(mail send to terminal)" },	{ "MSOM", MSOM, OSTR, 0,	"(mail send to terminal or mailbox)" },	{ "MSAM", MSAM, OSTR, 0,	"(mail send to terminal and mailbox)" },	{ "MRSQ", MRSQ, OSTR, 0,	"(mail recipient scheme question)" },	{ "MRCP", MRCP, STR1, 0,	"(mail recipient)" },	{ "ALLO", ALLO, ARGS, 1,	"allocate storage (vacuously)" },	{ "REST", REST, ARGS, 1,	"<sp> offset (restart command)" },	{ "RNFR", RNFR, STR1, 1,	"<sp> file-name" },	{ "RNTO", RNTO, STR1, 1,	"<sp> file-name" },	{ "ABOR", ABOR, ARGS, 1,	"(abort operation)" },	{ "DELE", DELE, STR1, 1,	"<sp> file-name" },	{ "CWD",  CWD,  OSTR, 1,	"[ <sp> directory-name ]" },	{ "XCWD", CWD,	OSTR, 1,	"[ <sp> directory-name ]" },	{ "LIST", LIST, OSTR, 1,	"[ <sp> path-name ]" },	{ "NLST", NLST, OSTR, 1,	"[ <sp> path-name ]" },	{ "SITE", SITE, SITECMD, 1,	"site-cmd [ <sp> arguments ]" },	{ "SYST", SYST, ARGS, 1,	"(get type of operating system)" },	{ "STAT", STAT, OSTR, 1,	"[ <sp> path-name ]" },	{ "HELP", HELP, OSTR, 1,	"[ <sp> <string> ]" },	{ "NOOP", NOOP, ARGS, 1,	"" },	{ "MKD",  MKD,  STR1, 1,	"<sp> path-name" },	{ "XMKD", MKD,  STR1, 1,	"<sp> path-name" },	{ "RMD",  RMD,  STR1, 1,	"<sp> path-name" },	{ "XRMD", RMD,  STR1, 1,	"<sp> path-name" },	{ "PWD",  PWD,  ARGS, 1,	"(return current directory)" },	{ "XPWD", PWD,  ARGS, 1,	"(return current directory)" },	{ "CDUP", CDUP, ARGS, 1,	"(change to parent directory)" },	{ "XCUP", CDUP, ARGS, 1,	"(change to parent directory)" },	{ "STOU", STOU, STR1, 1,	"<sp> file-name" },	{ "SIZE", SIZE, OSTR, 1,	"<sp> path-name" },	{ "MDTM", MDTM, OSTR, 1,	"<sp> path-name" },	{ NULL,   0,    0,    0,	0 }};struct tab sitetab[] = {	{ "UMASK", UMASK, ARGS, 1,	"[ <sp> umask ]" },	{ "IDLE", IDLE, ARGS, 1,	"[ <sp> maximum-idle-time ]" },	{ "CHMOD", CHMOD, NSTR, 1,	"<sp> mode <sp> file-name" },	{ "HELP", HELP, OSTR, 1,	"[ <sp> <string> ]" },	{ NULL,   0,    0,    0,	0 }};static void	 help __P((struct tab *, char *));static struct tab *		 lookup __P((struct tab *, char *));static void	 sizecmd __P((char *));static int	 yylex __P((void));static struct tab *lookup(p, cmd)	struct tab *p;	char *cmd;{	for (; p->name != NULL; p++)		if (strcmp(cmd, p->name) == 0)			return (p);	return (0);}#include <arpa/telnet.h>/* * getline - a hacked up version of fgets to ignore TELNET escape codes. */char *getline(s, n, iop)	char *s;	int n;	FILE *iop;{	int c;	register char *cs;	cs = s;/* tmpline may contain saved command from urgent mode interruption */	for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) {		*cs++ = tmpline[c];		if (tmpline[c] == '\n') {			*cs++ = '\0';			if (debug)				syslog(LOG_DEBUG, "command: %s", s);			tmpline[0] = '\0';			return(s);		}		if (c == 0)			tmpline[0] = '\0';	}	while ((c = getc(iop)) != EOF) {		c &= 0377;		if (c == IAC) {		    if ((c = getc(iop)) != EOF) {			c &= 0377;			switch (c) {			case WILL:			case WONT:				c = getc(iop);				printf("%c%c%c", IAC, DONT, 0377&c);				(void) fflush(stdout);				continue;			case DO:			case DONT:				c = getc(iop);				printf("%c%c%c", IAC, WONT, 0377&c);				(void) fflush(stdout);				continue;			case IAC:				break;			default:				continue;	/* ignore command */			}		    }		}		*cs++ = c;		if (--n <= 0 || c == '\n')			break;	}	if (c == EOF && cs == s)		return (NULL);	*cs++ = '\0';	if (debug) {		if (!guest && strncasecmp("pass ", s, 5) == 0) {			/* Don't syslog passwords */			syslog(LOG_DEBUG, "command: %.5s ???", s);		} else {			register char *cp;			register int len;			/* Don't syslog trailing CR-LF */			len = strlen(s);			cp = s + len - 1;			while (cp >= s && (*cp == '\n' || *cp == '\r')) {				--cp;				--len;			}			syslog(LOG_DEBUG, "command: %.*s", len, s);		}	}	return (s);}voidtoolong(int signo){	(void)signo;	reply(421,	    "Timeout (%d seconds): closing control connection.", timeout);	if (logging)		syslog(LOG_INFO, "User %s timed out after %d seconds",		    (pw ? pw -> pw_name : "unknown"), timeout);	dologout(1);}static intyylex(){	static int cpos, state;	char *cp, *cp2;	struct tab *p;	int n;	char c;	for (;;) {		switch (state) {		case CMD:			(void) signal(SIGALRM, toolong);			(void) alarm((unsigned) timeout);			if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) {				reply(221, "You could at least say goodbye.");				dologout(0);			}			(void) alarm(0);			if ((cp = strchr(cbuf, '\r'))) {				*cp++ = '\n';				*cp = '\0';			}#ifdef HASSETPROCTITLE			if (strncasecmp(cbuf, "PASS", 4) != 0) {				if ((cp = strpbrk(cbuf, "\n"))) {					c = *cp;					*cp = '\0';					setproctitle("%s: %s", proctitle, cbuf);					*cp = c;				}			} else				setproctitle("%s: %s", proctitle, cbuf);#endif /* HASSETPROCTITLE */			if ((cp = strpbrk(cbuf, " \n")))				cpos = cp - cbuf;			if (cpos == 0)				cpos = 4;			c = cbuf[cpos];			cbuf[cpos] = '\0';			upper(cbuf);			p = lookup(cmdtab, cbuf);			cbuf[cpos] = c;			if (p != 0) {				if (p->implemented == 0) {					nack(p->name);					longjmp(errcatch,0);					/* NOTREACHED */				}				state = p->state;				yylval.s = (char *)p->name;  /* XXX */				return (p->token);			}			break;		case SITECMD:			if (cbuf[cpos] == ' ') {				cpos++;				return (SP);			}			cp = &cbuf[cpos];			if ((cp2 = strpbrk(cp, " \n")))				cpos = cp2 - cbuf;			c = cbuf[cpos];			cbuf[cpos] = '\0';			upper(cp);			p = lookup(sitetab, cp);			cbuf[cpos] = c;			if (p != 0) {				if (p->implemented == 0) {					state = CMD;					nack(p->name);					longjmp(errcatch,0);					/* NOTREACHED */				}				state = p->state;				yylval.s = (char *) p->name;  /* XXX */				return (p->token);			}			state = CMD;			break;		case OSTR:			if (cbuf[cpos] == '\n') {				state = CMD;				return (CRLF);			}			/* FALLTHROUGH */		case STR1:		case ZSTR1:		dostr1:			if (cbuf[cpos] == ' ') {				cpos++;				state = state == OSTR ? STR2 : ++state;				return (SP);			}			break;		case ZSTR2:			if (cbuf[cpos] == '\n') {				state = CMD;				return (CRLF);			}			/* FALLTHROUGH */		case STR2:			cp = &cbuf[cpos];			n = strlen(cp);			cpos += n - 1;			/*			 * Make sure the string is nonempty and \n terminated.			 */			if (n > 1 && cbuf[cpos] == '\n') {				cbuf[cpos] = '\0';				yylval.s = strdup(cp);				if (yylval.s == NULL)					fatal("Ran out of memory.");				cbuf[cpos] = '\n';				state = ARGS;				return (STRING);			}			break;		case NSTR:			if (cbuf[cpos] == ' ') {				cpos++;				return (SP);			}			if (isdigit(cbuf[cpos])) {				cp = &cbuf[cpos];				while (isdigit(cbuf[++cpos]))					;				c = cbuf[cpos];				cbuf[cpos] = '\0';				yylval.i = atoi(cp);				cbuf[cpos] = c;				state = STR1;				return (NUMBER);			}			state = STR1;			goto dostr1;		case ARGS:			if (isdigit(cbuf[cpos])) {				cp = &cbuf[cpos];				while (isdigit(cbuf[++cpos]))					;				c = cbuf[cpos];				cbuf[cpos] = '\0';				yylval.i = atoi(cp);				cbuf[cpos] = c;				return (NUMBER);			}			switch (cbuf[cpos++]) {			case '\n':				state = CMD;				return (CRLF);			case ' ':				return (SP);			case ',':				return (COMMA);			case 'A':			case 'a':				return (A);			case 'B':			case 'b':				return (B);			case 'C':			case 'c':				return (C);			case 'E':			case 'e':				return (E);			case 'F':			case 'f':				return (F);			case 'I':			case 'i':				return (I);			case 'L':			case 'l':				return (L);			case 'N':			case 'n':				return (N);			case 'P':			case 'p':				return (P);			case 'R':			case 'r':				return (R);			case 'S':			case 's':				return (S);			case 'T':			case 't':				return (T);			}			break;		default:			fatal("Unknown state in scanner.");		}		yyerror((char *) 0);		state = CMD;		longjmp(errcatch,0);	}}voidupper(s)	char *s;{	while (*s != '\0') {		if (islower(*s))			*s = toupper(*s);		s++;	}}static voidhelp(struct tab *ctab, char *s){	struct tab *c;	int width, NCMDS;	const char *type;	if (ctab == sitetab)		type = "SITE ";	else		type = "";	width = 0, NCMDS = 0;	for (c = ctab; c->name != NULL; c++) {		int len = strlen(c->name);		if (len > width)			width = len;		NCMDS++;	}	width = (width + 8) &~ 7;	if (s == 0) {		int i, j, w;		int columns, lines;		lreply(214, "The following %scommands are recognized %s.",		    type, "(* =>'s unimplemented)");		columns = 76 / width;		if (columns == 0)			columns = 1;		lines = (NCMDS + columns - 1) / columns;		for (i = 0; i < lines; i++) {			printf("   ");			for (j = 0; j < columns; j++) {				c = ctab + j * lines + i;				printf("%s%c", c->name,					c->implemented ? ' ' : '*');				if (c + lines >= &ctab[NCMDS])					break;				w = strlen(c->name) + 1;				while (w < width) {					putchar(' ');					w++;				}			}			printf("\r\n");		}		(void) fflush(stdout);		reply(214, "Direct comments to ftp-bugs@%s.", hostname);		return;	}	upper(s);	c = lookup(ctab, s);	if (c == (struct tab *)0) {		reply(502, "Unknown command %s.", s);		return;	}	if (c->implemented)		reply(214, "Syntax: %s%s %s", type, c->name, c->help);	else		reply(214, "%s%-*s\t%s; unimplemented.", type, width,		    c->name, c->help);}static voidsizecmd(filename)	char *filename;{	switch (type) {	case TYPE_L:	case TYPE_I: {		struct stat stbuf;		if (stat(filename, &stbuf) < 0 || !S_ISREG(stbuf.st_mode))			reply(550, "%s: not a plain file.", filename);		else			reply(213, "%qu", (quad_t) stbuf.st_size);		break; }	case TYPE_A: {		FILE *fin;		int c;		off_t count;		struct stat stbuf;		fin = fopen(filename, "r");		if (fin == NULL) {			perror_reply(550, filename);			return;		}		if (fstat(fileno(fin), &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) {			reply(550, "%s: not a plain file.", filename);			(void) fclose(fin);			return;		}		count = 0;		while((c=getc(fin)) != EOF) {			if (c == '\n')	/* will get expanded to \r\n */				count++;			count++;		}		(void) fclose(fin);		reply(213, "%qd", (quad_t) count);		break; }	default:		reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);	}}

⌨️ 快捷键说明

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