ftp.nice.ch/pub/next/unix/network/filetransfer/ftpd.6.17.N.bs.tar.gz#/ftpd/ftpcmd.c

This is ftpcmd.c in view mode; [Download] [Up]

# line 28 "ftpcmd.y"

#ifndef lint
static char sccsid[] = "@(#)ftpcmd.y	5.23 (Berkeley) 6/1/90";
#endif /* not lint */

#include <sys/param.h>
#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/ftp.h>

#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#include <pwd.h>
#include <setjmp.h>
#include <syslog.h>
#include <sys/stat.h>
#include <time.h>
#include <string.h>
#include "support/ftw.h"

extern	struct sockaddr_in data_dest;
extern	int logged_in;
extern	struct passwd *pw;
extern	int anonymous;
extern	int logging;
extern	int	cmdlogging;
extern	int type;
extern	int form;
extern	int debug;
extern	int timeout;
extern	int maxtimeout;
extern  int pdata;
extern	char hostname[], remotehost[];
extern	char proctitle[];
extern	char *globerr;
extern	int usedefault;
extern  int transflag;
extern  char tmpline[];
extern	int data;
char	**glob();
off_t	restart_point;

extern	char	*strunames[];
extern	char	*typenames[];
extern	char	*modenames[];
extern	char	*formnames[];

static	int cmd_type;
static	int cmd_form;
static	int cmd_bytesz;
char	cbuf[512];
char	*fromname;


# line 105 "ftpcmd.y"
typedef union  {
    char	*String;
    int		Number;
} YYSTYPE;
# define A 257
# define B 258
# define C 259
# define E 260
# define F 261
# define I 262
# define L 263
# define N 264
# define P 265
# define R 266
# define S 267
# define T 268
# define SP 269
# define CRLF 270
# define COMMA 271
# define STRING 272
# define NUMBER 273
# define USER 274
# define PASS 275
# define ACCT 276
# define REIN 277
# define QUIT 278
# define PORT 279
# define PASV 280
# define TYPE 281
# define STRU 282
# define MODE 283
# define RETR 284
# define STOR 285
# define APPE 286
# define MLFL 287
# define MAIL 288
# define MSND 289
# define MSOM 290
# define MSAM 291
# define MRSQ 292
# define MRCP 293
# define ALLO 294
# define REST 295
# define RNFR 296
# define RNTO 297
# define ABOR 298
# define DELE 299
# define CWD 300
# define LIST 301
# define NLST 302
# define SITE 303
# define STAT 304
# define HELP 305
# define NOOP 306
# define MKD 307
# define RMD 308
# define PWD 309
# define CDUP 310
# define STOU 311
# define SMNT 312
# define SYST 313
# define SIZE 314
# define MDTM 315
# define UMASK 316
# define IDLE 317
# define CHMOD 318
# define GROUP 319
# define GPASS 320
# define NEWER 321
# define MINFO 322
# define LEXERR 323
#define yyclearin yychar = -1
#define yyerrok yyerrflag = 0
extern int yychar;
extern short yyerrflag;
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 150
#endif
YYSTYPE yylval, yyval;
# define YYERRCODE 256

# line 766 "ftpcmd.y"


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 */
#define	STR3	9	/* expect STRING followed by optional SP then STRING */

struct tab {
	char	*name;
	short	token;
	short	state;
 	short	implemented;	/* 1 if command is implemented */
	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,	"(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> ]" },
	{ "GROUP", GROUP, STR1, 1,	"<sp> access-group" },
	{ "GPASS", GPASS, STR1, 1,	"<sp> access-password" },
	{ "NEWER", NEWER, STR3, 1,	"<sp> YYYYMMDDHHMMSS [ <sp> path-name ]" },
	{ "MINFO", MINFO, STR3, 1,	"<sp> YYYYMMDDHHMMSS [ <sp> path-name ]" },
	{ NULL,   0,    0,    0,	0 }
};

struct tab *
lookup(p, cmd)
	register 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;
	register FILE *iop;
{
	register 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)
		syslog(LOG_DEBUG, "command: %s", s);
	return (s);
}

static int
toolong()
{
	time_t now;
	extern char *ctime();
	extern time_t time();

	reply(421,
	  "Timeout (%d seconds): closing control connection.", timeout);
	(void) time(&now);
	if (logging) {
		syslog(LOG_INFO,
			"User %s timed out after %d seconds at %.24s",
			(pw ? pw -> pw_name : "unknown"), timeout, ctime(&now));
	}
	dologout(1);
}

yylex()
{
	static int cpos, state;
	register char *cp, *cp2;
	register struct tab *p;
	int n;
	char c, *strpbrk();
	char *copy();

	for (;;) {
		switch (state) {

		case CMD:
			(void) signal(SIGALRM, toolong);
			(void) alarm((unsigned) timeout);
			if (is_shutdown(!logged_in) != 0) {
				reply(221, "Server shutting down.");
				dologout(0);
			}
			if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) {
				reply(221, "You could at least say goodbye.");
				dologout(0);
			}
			(void) alarm(0);
#ifdef SETPROCTITLE
			if (strncasecmp(cbuf, "PASS", 4) != 0 &&
				strncasecmp(cbuf, "GPASS", 5) != 0)
				setproctitle("%s: %s", proctitle, cbuf);
#endif /* SETPROCTITLE */
			if ((cp = strchr(cbuf, '\r'))) {
				*cp++ = '\n';
				*cp = '\0';
			}
			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.String = p->name;
				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.String = p->name;
				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.String = copy(cp);
				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.Number = atoi(cp);
				cbuf[cpos] = c;
				state = STR1;
				return (NUMBER);
			}
			state = STR1;
			goto dostr1;

		case STR3:
			if (cbuf[cpos] == ' ') {
				cpos++;
				return (SP);
			}

			cp = &cbuf[cpos];
			cp2 = strpbrk(cp, " \n");
			if (cp2 != NULL) {
				c = *cp2;
				*cp2 = '\0';
			}
			n = strlen(cp);
			cpos += n;
			/*
			 * Make sure the string is nonempty and SP terminated.
			 */
			if ((cp2 - cp) > 1) {
				yylval.String = copy(cp);
				cbuf[cpos] = c;
				state = OSTR;
				return (STRING);
			}
			break;

		case ARGS:
			if (isdigit(cbuf[cpos])) {
				cp = &cbuf[cpos];
				while (isdigit(cbuf[++cpos]))
					;
				c = cbuf[cpos];
				cbuf[cpos] = '\0';
				yylval.Number = 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 *)NULL);
		state = CMD;
		longjmp(errcatch,0);
	}
}

upper(s)
	register char *s;
{
	while (*s != '\0') {
		if (islower(*s))
			*s = toupper(*s);
		s++;
	}
}

char *
copy(s)
	char *s;
{
	char *p;
	extern char *malloc(), *strcpy();

	p = malloc((unsigned) strlen(s) + 1);
	if (p == NULL)
		fatal("Ran out of memory.");
	(void) strcpy(p, s);
	return (p);
}

help(ctab, s)
	struct tab *ctab;
	char *s;
{
	register struct tab *c;
	register int width, NCMDS;
	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) {
		register 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 *)NULL) {
		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);
}

sizecmd(filename)
char *filename;
{
	switch (type) {
	case TYPE_L:
	case TYPE_I: {
		struct stat stbuf;
		if (stat(filename, &stbuf) < 0 ||
		    (stbuf.st_mode&S_IFMT) != S_IFREG)
			reply(550, "%s: not a plain file.", filename);
		else
			reply(213, "%lu", stbuf.st_size);
		break;}
	case TYPE_A: {
		FILE *fin;
		register int c;
		register long count;
		struct stat stbuf;
		fin = fopen(filename, "r");
		if (fin == NULL) {
			perror_reply(550, filename);
			return;
		}
		if (fstat(fileno(fin), &stbuf) < 0 ||
		    (stbuf.st_mode&S_IFMT) != S_IFREG) {
			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, "%ld", count);
		break;}
	default:
		reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
	}
}
short yyexca[] ={
-1, 1,
	0, -1,
	-2, 0,
	};
# define YYNPROD 80
# define YYLAST 362
short yyact[]={

  34, 132, 228, 226, 221, 124, 208, 207, 200, 187,
 124, 165,  91,  77, 103, 206, 224, 205,   4,   5,
 111,  75,  33,   6,   7,   8,   9,  10,  12,  13,
  14, 112, 114, 113, 115, 116, 117, 118,  11,  36,
  35,  19,  20,  18,  21,  16,  15,  28,  17,  22,
  23,  24,  25,  26,  27,  29,  73,  30,  31,  32,
 183, 141, 106, 227, 225, 216, 214, 213, 215, 196,
 185, 184, 155, 154, 151, 150, 137, 136, 210, 128,
 105, 104,  98,  97,  96,  95,  57,  56, 223, 222,
 217, 212, 211, 209, 202, 198, 195, 194, 193, 192,
 182, 181, 180, 179, 178, 177, 176, 175, 174, 173,
 169, 164, 147, 145, 135, 167, 134, 129, 127, 168,
 126, 101, 125, 110, 109,  69,  68,  65,  58,  54,
  51,  40, 197, 191, 190, 189, 188, 186, 131, 130,
 122, 121, 120, 119, 108, 107, 100,  99,  94,  93,
  92,  89,  90,  71,  63,  53,  44,  43,  42,  41,
  88,  39,  84,  38,  37, 172,  86,  85,  79,  74,
 199,  80,  72,  81,  82,  45, 123,  78, 166,  76,
   3,   2,   1,  83,  87, 102,   0,   0,   0,  46,
  47,  48,  49,  50,  52,   0,   0,  55,   0,   0,
  59,  60,  61,  62,   0,  64,   0,  66,  67,   0,
   0,  70,   0,   0, 138, 139, 140,   0,   0,   0,
 142, 143, 144,   0,   0,   0,   0, 146,   0, 148,
 149,   0,   0,   0,   0,   0,   0,   0,   0,   0,
   0, 160, 161, 162, 163,   0,   0,   0,   0,   0,
   0,   0,   0,   0,   0,   0,   0,   0,   0, 133,
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
   0,   0,   0,   0,   0,   0,   0,   0, 152, 153,
   0, 156, 157, 158, 159,   0,   0,   0,   0,   0,
   0,   0,   0,   0,   0,   0,   0,   0,   0, 171,
 170,   0,   0,   0,   0,   0,   0,   0,   0,   0,
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
   0,   0, 218,   0,   0,   0, 219, 220,   0,   0,
   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
   0,   0,   0,   0,   0,   0,   0, 201,   0, 204,
   0, 203 };
short yypact[]={

-1000,-256,-1000,-1000,-105,-106,-108,-139,-110,-111,
-112,-113,-1000,-1000,-1000,-1000,-1000,-140,-1000,-114,
-141,-1000,-183,-142,-1000,-1000,-1000,-1000,-115,-1000,
-143,-1000,-1000,-144,-145,-1000,-116,-216,-251,-260,
-1000, -89, -99,-107,-261,-119,-120,-121,-185,-187,
-122,-1000,-123,-258,-1000,-189,-1000,-210,-1000,-124,
-125,-146,-147,-285,-126,-1000,-127,-128,-1000,-1000,
-129,-263,-148,-1000,-150,-1000,-152,-192,-153,-130,
-131,-1000,-268,-154,-1000,-1000,-1000,-156,-1000,-1000,
-1000,-193,-258,-258,-258,-1000,-211,-1000,-258,-258,
-258,-157,-1000,-1000,-1000,-258,-158,-258,-258,-1000,
-1000,-195,-1000,-1000,-197,-1000,-1000,-1000,-1000,-258,
-258,-258,-258,-159,-1000,-1000,-1000,-1000,-262,-1000,
-149,-149,-263,-1000,-1000,-1000,-1000,-101,-161,-162,
-163,-164,-165,-166,-167,-1000,-168,-1000,-169,-170,
-1000,-212,-199,-132,-1000,-264,-133,-134,-135,-136,
-171,-172,-173,-174,-1000,-202,-1000,-1000,-1000,-1000,
-1000,-1000,-137,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-175,-1000,-265,-265,-176,-216,-251,
-255,-257,-1000,-1000,-1000,-1000,-266,-267,-1000,-177,
-1000,-191,-1000,-178,-179,-203,-201,-206,-180,-1000,
-258,-1000,-1000,-1000,-258,-258,-269,-1000,-181,-182,
-254,-207,-1000,-1000,-1000,-270,-208,-271,-1000 };
short yypgo[]={

   0, 169, 121, 185, 172, 176, 175, 178, 184, 170,
 183, 182, 181, 180, 179, 177 };
short yyr1[]={

   0,  11,  11,  11,  12,  12,  12,  12,  12,  12,
  12,  12,  12,  12,  12,  12,  12,  12,  12,  12,
  12,  12,  12,  12,  12,  12,  12,  12,  12,  12,
  12,  12,  12,  12,  12,  12,  12,  12,  12,  12,
  12,  12,  12,  12,  12,  12,  12,  12,  12,  12,
  12,  12,  13,  13,   4,   1,   1,   5,  14,   7,
   7,   7,  15,  15,  15,  15,  15,  15,  15,  15,
  10,  10,  10,   8,   8,   8,   2,   3,   9,   6 };
short yyr2[]={

   0,   0,   2,   2,   4,   4,   4,   2,   4,   4,
   4,   4,   8,   5,   5,   5,   3,   5,   3,   5,
   5,   2,   5,   4,   2,   3,   5,   2,   4,   2,
   5,   5,   3,   3,   4,   6,   5,   7,   9,   4,
   6,   7,   7,   7,   9,   9,   5,   2,   5,   5,
   2,   2,   5,   4,   1,   0,   1,   1,  11,   1,
   1,   1,   1,   3,   1,   3,   1,   1,   3,   2,
   1,   1,   1,   1,   1,   1,   1,   1,   1,   0 };
short yychk[]={

-1000, -11, -12, -13, 274, 275, 279, 280, 281, 282,
 283, 294, 284, 285, 286, 302, 301, 304, 299, 297,
 298, 300, 305, 306, 307, 308, 309, 310, 303, 311,
 313, 314, 315, 278, 256, 296, 295, 269, 269, 269,
 270, 269, 269, 269, 269,  -6,  -6,  -6,  -6,  -6,
  -6, 270,  -6, 269, 270,  -6, 270, 269, 270,  -6,
  -6,  -6,  -6, 269,  -6, 270,  -6,  -6, 270, 270,
  -6, 269,  -4, 272,  -1, 272, -14, 273, -15, 257,
 260, 262, 263, -10, 261, 266, 265,  -8, 267, 258,
 259, 273, 269, 269, 269, 270, 269, 270, 269, 269,
 269,  -2,  -3, 272, 270, 269, 272, 269, 269, 270,
 270, 305, 316, 318, 317, 319, 320, 321, 322, 269,
 269, 269, 269,  -5, 273, 270, 270, 270, 271, 270,
 269, 269, 269,  -5, 270, 270, 270, 269,  -2,  -2,
  -2, 272,  -2,  -2,  -2, 270,  -2, 270,  -2,  -2,
 270, 269,  -6,  -6, 270, 269,  -6,  -6,  -6,  -6,
  -2,  -2,  -2,  -2, 270, 273,  -7, 264, 268, 259,
  -7,  -5, 266, 270, 270, 270, 270, 270, 270, 270,
 270, 270, 270, 272, 270, 269, 269, 273, 269, 269,
 269, 269, 270, 270, 270, 270, 271, 269, 270,  -9,
 273,  -9, 270,  -4,  -1, 272, 272, 273, 273, 270,
 269, 270, 270, 270, 269, 269, 271, 270,  -2,  -2,
  -2, 273, 270, 270, 270, 271, 273, 271, 273 };
short yydef[]={

   1,  -2,   2,   3,   0,   0,   0,   0,   0,   0,
   0,   0,  79,  79,  79,  79,  79,  79,  79,   0,
   0,  79,   0,   0,  79,  79,  79,  79,   0,  79,
   0,  79,  79,   0,   0,  79,   0,   0,  55,   0,
   7,   0,   0,   0,   0,   0,   0,   0,   0,   0,
   0,  21,   0,   0,  24,   0,  27,   0,  29,   0,
   0,   0,   0,   0,   0,  47,   0,   0,  50,  51,
   0,   0,   0,  54,   0,  56,   0,   0,   0,  62,
  64,  66,  67,   0,  70,  71,  72,   0,  73,  74,
  75,   0,   0,   0,   0,  16,   0,  18,   0,   0,
   0,   0,  76,  77,  25,   0,   0,   0,   0,  32,
  33,   0,  79,  79,   0,  79,  79,  79,  79,   0,
   0,   0,   0,   0,  57,   4,   5,   6,   0,   8,
   0,   0,   0,  69,   9,  10,  11,   0,   0,   0,
   0,   0,   0,   0,   0,  23,   0,  28,   0,   0,
  34,   0,   0,   0,  39,   0,   0,   0,   0,   0,
   0,   0,   0,   0,  53,   0,  63,  59,  60,  61,
  65,  68,   0,  13,  14,  15,  17,  19,  20,  22,
  26,  30,  31,   0,  36,   0,   0,   0,   0,  55,
   0,   0,  46,  48,  49,  52,   0,   0,  35,   0,
  78,   0,  40,   0,   0,   0,   0,   0,   0,  37,
   0,  41,  42,  43,   0,   0,   0,  12,   0,   0,
   0,   0,  38,  44,  45,   0,   0,   0,  58 };
# line 1 "/usr/lib/yaccpar"
#ifndef lint
static char yaccpar_sccsid[] = "@(#)yaccpar	4.1	(Berkeley)	2/11/83";
#endif not lint

# define YYFLAG -1000
# define YYERROR goto yyerrlab
# define YYACCEPT return(0)
# define YYABORT return(1)

/*	parser for yacc output	*/

#ifdef YYDEBUG
int yydebug = 0; /* 1 for debugging */
#endif
YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */
int yychar = -1; /* current input token number */
int yynerrs = 0;  /* number of errors */
short yyerrflag = 0;  /* error recovery flag */

yyparse() {

	short yys[YYMAXDEPTH];
	short yyj, yym;
	register YYSTYPE *yypvt;
	register short yystate, *yyps, yyn;
	register YYSTYPE *yypv;
	register short *yyxi;

	yystate = 0;
	yychar = -1;
	yynerrs = 0;
	yyerrflag = 0;
	yyps= &yys[-1];
	yypv= &yyv[-1];

 yystack:    /* put a state and value onto the stack */

#ifdef YYDEBUG
	if( yydebug  ) printf( "state %d, char 0%o\n", yystate, yychar );
#endif
		if( ++yyps>= &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); }
		*yyps = yystate;
		++yypv;
		*yypv = yyval;

 yynewstate:

	yyn = yypact[yystate];

	if( yyn<= YYFLAG ) goto yydefault; /* simple state */

	if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0;
	if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault;

	if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */
		yychar = -1;
		yyval = yylval;
		yystate = yyn;
		if( yyerrflag > 0 ) --yyerrflag;
		goto yystack;
		}

 yydefault:
	/* default state action */

	if( (yyn=yydef[yystate]) == -2 ) {
		if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0;
		/* look through exception table */

		for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */

		while( *(yyxi+=2) >= 0 ){
			if( *yyxi == yychar ) break;
			}
		if( (yyn = yyxi[1]) < 0 ) return(0);   /* accept */
		}

	if( yyn == 0 ){ /* error */
		/* error ... attempt to resume parsing */

		switch( yyerrflag ){

		case 0:   /* brand new error */

			yyerror( "syntax error" );
		yyerrlab:
			++yynerrs;

		case 1:
		case 2: /* incompletely recovered error ... try again */

			yyerrflag = 3;

			/* find a state where "error" is a legal shift action */

			while ( yyps >= yys ) {
			   yyn = yypact[*yyps] + YYERRCODE;
			   if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){
			      yystate = yyact[yyn];  /* simulate a shift of "error" */
			      goto yystack;
			      }
			   yyn = yypact[*yyps];

			   /* the current yyps has no shift onn "error", pop stack */

#ifdef YYDEBUG
			   if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] );
#endif
			   --yyps;
			   --yypv;
			   }

			/* there is no state on the stack with an error shift ... abort */

	yyabort:
			return(1);


		case 3:  /* no shift yet; clobber input char */

#ifdef YYDEBUG
			if( yydebug ) printf( "error recovery discards char %d\n", yychar );
#endif

			if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */
			yychar = -1;
			goto yynewstate;   /* try again in the same state */

			}

		}

	/* reduction by production yyn */

#ifdef YYDEBUG
		if( yydebug ) printf("reduce %d\n",yyn);
#endif
		yyps -= yyr2[yyn];
		yypvt = yypv;
		yypv -= yyr2[yyn];
		yyval = yypv[1];
		yym=yyn;
			/* consult goto table to find next state */
		yyn = yyr1[yyn];
		yyj = yypgo[yyn] + *yyps + 1;
		if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]];
		switch(yym){
			
case 2:
# line 120 "ftpcmd.y"
 {
			fromname = 0;
			restart_point = 0;
		} break;
case 4:
# line 128 "ftpcmd.y"
 {
			user(yypvt[-1].String);
			if (cmdlogging) syslog(LOG_INFO, "USER %s", yypvt[-1].String);
			free(yypvt[-1].String);
		} break;
case 5:
# line 134 "ftpcmd.y"
 {
			if (cmdlogging)
				if (anonymous)
					syslog(LOG_INFO, "PASS %s", yypvt[-1].String);
				else
					syslog(LOG_INFO, "PASS password");

			pass(yypvt[-1].String);
			free(yypvt[-1].String);
		} break;
case 6:
# line 145 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "PORT");
			usedefault = 0;
			if (pdata >= 0) {
				(void) close(pdata);
				pdata = -1;
			}
			reply(200, "PORT command successful.");
		} break;
case 7:
# line 155 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "PASV");
			passive();
		} break;
case 8:
# line 160 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "TYPE %s", typenames[cmd_type]);
			switch (cmd_type) {

			case TYPE_A:
				if (cmd_form == FORM_N) {
					reply(200, "Type set to A.");
					type = cmd_type;
					form = cmd_form;
				} else
					reply(504, "Form must be N.");
				break;

			case TYPE_E:
				reply(504, "Type E not implemented.");
				break;

			case TYPE_I:
				reply(200, "Type set to I.");
				type = cmd_type;
				break;

			case TYPE_L:
#if NBBY == 8
				if (cmd_bytesz == 8) {
					reply(200,
					    "Type set to L (byte size 8).");
					type = cmd_type;
				} else
					reply(504, "Byte size must be 8.");
#else /* NBBY == 8 */
				UNIMPLEMENTED for NBBY != 8
#endif /* NBBY == 8 */
			}
		} break;
case 9:
# line 196 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "STRU %s", strunames[yypvt[-1].Number]);
			switch (yypvt[-1].Number) {

			case STRU_F:
				reply(200, "STRU F ok.");
				break;

			default:
				reply(504, "Unimplemented STRU type.");
			}
		} break;
case 10:
# line 209 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "MODE %s", modenames[yypvt[-1].Number]);
			switch (yypvt[-1].Number) {

			case MODE_S:
				reply(200, "MODE S ok.");
				break;

			default:
				reply(502, "Unimplemented MODE type.");
			}
		} break;
case 11:
# line 222 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "ALLO %d", yypvt[-1].Number);
			reply(202, "ALLO command ignored.");
		} break;
case 12:
# line 227 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "ALLO %d R %d", yypvt[-5].Number, yypvt[-1].Number);
			reply(202, "ALLO command ignored.");
		} break;
case 13:
# line 232 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "RETR %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String != NULL)
				retrieve((char *) NULL, yypvt[-1].String);
			if (yypvt[-1].String != NULL)
				free(yypvt[-1].String);
		} break;
case 14:
# line 240 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "STOR %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String != NULL)
				store(yypvt[-1].String, "w", 0);
			if (yypvt[-1].String != NULL)
				free(yypvt[-1].String);
		} break;
case 15:
# line 248 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "APPE %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String != NULL)
				store(yypvt[-1].String, "a", 0);
			if (yypvt[-1].String != NULL)
				free(yypvt[-1].String);
		} break;
case 16:
# line 256 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "NLST");
			if (yypvt[-1].Number)
				send_file_list(".");
		} break;
case 17:
# line 262 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "NLST %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String) {
				send_file_list(yypvt[-1].String);
				free(yypvt[-1].String);
			}
		} break;
case 18:
# line 270 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "LIST");
			if (yypvt[-1].Number)
				retrieve("/bin/ls -lgA", "");
		} break;
case 19:
# line 276 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "LIST %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String != NULL)
				retrieve("/bin/ls -lgA %s", yypvt[-1].String);
			if (yypvt[-1].String != NULL)
				free(yypvt[-1].String);
		} break;
case 20:
# line 284 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "STAT %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String != NULL)
				statfilecmd(yypvt[-1].String);
			if (yypvt[-1].String != NULL)
				free(yypvt[-1].String);
		} break;
case 21:
# line 292 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "STAT");
			statcmd();
		} break;
case 22:
# line 297 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "DELE %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String != NULL)
				delete(yypvt[-1].String);
			if (yypvt[-1].String != NULL)
				free(yypvt[-1].String);
		} break;
case 23:
# line 305 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "RNTO %s", yypvt[-1].String);
			if (fromname) {
				renamecmd(fromname, yypvt[-1].String);
				free(fromname);
				fromname = (char *) NULL;
			} else {
				reply(503, "Bad sequence of commands.");
			}
			free(yypvt[-1].String);
		} break;
case 24:
# line 317 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "ABOR");
			reply(225, "ABOR command successful.");
		} break;
case 25:
# line 322 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "CWD");
			if (yypvt[-1].Number)
				cwd(pw->pw_dir);
		} break;
case 26:
# line 328 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "CWD %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String != NULL)
				cwd(yypvt[-1].String);
			if (yypvt[-1].String != NULL)
				free(yypvt[-1].String);
		} break;
case 27:
# line 336 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "HELP");
			help(cmdtab, (char *) NULL);
		} break;
case 28:
# line 341 "ftpcmd.y"
 {
			register char *cp = (char *)yypvt[-1].String;

			if (cmdlogging) syslog(LOG_INFO, "HELP %s", yypvt[-1].String);
			if (strncasecmp(cp, "SITE", 4) == 0) {
				cp = (char *)yypvt[-1].String + 4;
				if (*cp == ' ')
					cp++;
				if (*cp)
					help(sitetab, cp);
				else
					help(sitetab, (char *) NULL);
			} else
				help(cmdtab, yypvt[-1].String);
		} break;
case 29:
# line 357 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "NOOP");
			reply(200, "NOOP command successful.");
		} break;
case 30:
# line 362 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "MKD %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String != NULL)
				makedir(yypvt[-1].String);
			if (yypvt[-1].String != NULL)
				free(yypvt[-1].String);
		} break;
case 31:
# line 370 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "RMD %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String != NULL)
				removedir(yypvt[-1].String);
			if (yypvt[-1].String != NULL)
				free(yypvt[-1].String);
		} break;
case 32:
# line 378 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "PWD");
			if (yypvt[-1].Number)
				pwd();
		} break;
case 33:
# line 384 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "CDUP");
			if (yypvt[-1].Number)
				cwd("..");
		} break;
case 34:
# line 390 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "SITE HELP");
			help(sitetab, (char *) NULL);
		} break;
case 35:
# line 395 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "SITE HELP %s", yypvt[-1].String);
			help(sitetab, yypvt[-1].String);
		} break;
case 36:
# line 400 "ftpcmd.y"
 {
			int oldmask;

			if (cmdlogging) syslog(LOG_INFO, "SITE UMASK");
			if (yypvt[-1].Number) {
				oldmask = umask(0);
				(void) umask(oldmask);
				reply(200, "Current UMASK is %03o", oldmask);
			}
		} break;
case 37:
# line 411 "ftpcmd.y"
 {
			int oldmask;

			if (cmdlogging) syslog(LOG_INFO, "SITE UMASK %d", yypvt[-1].Number);
			if (yypvt[-3].Number) {
				if ((yypvt[-1].Number == -1) || (yypvt[-1].Number > 0777)) {
					reply(501, "Bad UMASK value");
				} else {
					oldmask = umask(yypvt[-1].Number);
					reply(200,
					    "UMASK set to %03o (was %03o)",
					    yypvt[-1].Number, oldmask);
				}
			}
		} break;
case 38:
# line 427 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "SITE CHMOD %s %s", yypvt[-3].Number, yypvt[-1].String);
			if (yypvt[-5].Number && yypvt[-3].Number && yypvt[-1].String) {
				if (yypvt[-3].Number > 0777)
					reply(501,
				"CHMOD: Mode value must be between 0 and 0777");
				else if (chmod(yypvt[-1].String, yypvt[-3].Number) < 0)
					perror_reply(550, yypvt[-1].String);
				else
					reply(200, "CHMOD command successful.");
				free(yypvt[-1].String);
			}
		} break;
case 39:
# line 441 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "SITE IDLE");
			reply(200,
			    "Current IDLE time limit is %d seconds; max %d",
				timeout, maxtimeout);
		} break;
case 40:
# line 448 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "SITE IDLE %d", yypvt[-1].Number);
			if (yypvt[-1].Number < 30 || yypvt[-1].Number > maxtimeout) {
				reply(501,
			"Maximum IDLE time must be between 30 and %d seconds",
				    maxtimeout);
			} else {
				timeout = yypvt[-1].Number;
				(void) alarm((unsigned) timeout);
				reply(200, "Maximum IDLE time set to %d seconds", timeout);
			}
		} break;
case 41:
# line 461 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "SITE GROUP %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String) priv_group(yypvt[-1].String);
			free(yypvt[-1].String);
		} break;
case 42:
# line 467 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "SITE GPASS password");
			if (yypvt[-3].Number && yypvt[-1].String) priv_gpass(yypvt[-1].String);
			free(yypvt[-1].String);
		} break;
case 43:
# line 473 "ftpcmd.y"
 {
			if (yypvt[-3].Number && yypvt[-1].String) newer(yypvt[-1].String, ".", 0);
			free(yypvt[-1].String);
		} break;
case 44:
# line 478 "ftpcmd.y"
 {
			if (yypvt[-5].Number && yypvt[-3].String && yypvt[-1].String) newer(yypvt[-3].String, yypvt[-1].String, 0);
			free(yypvt[-3].String);
			free(yypvt[-1].String);
		} break;
case 45:
# line 484 "ftpcmd.y"
 {
			if (yypvt[-5].Number && yypvt[-3].String && yypvt[-1].String) newer(yypvt[-3].String, yypvt[-1].String, 1);
			free(yypvt[-3].String);
			free(yypvt[-1].String);
		} break;
case 46:
# line 490 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "STOU %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String) {
				store(yypvt[-1].String, "w", 1);
				free(yypvt[-1].String);
			}
		} break;
case 47:
# line 498 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "SYST");
#ifdef unix
#ifdef BSD
			reply(215, "UNIX Type: L%d Version: BSD-%d",
				NBBY, BSD);
#else /* BSD */
			reply(215, "UNIX Type: L%d", NBBY);
#endif /* BSD */
#else /* unix */
			reply(215, "UNKNOWN Type: L%d", NBBY);
#endif /* unix */
		} break;
case 48:
# line 520 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "SIZE %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String) {
				sizecmd(yypvt[-1].String);
				free(yypvt[-1].String);
			}
		} break;
case 49:
# line 538 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "MDTM %s", yypvt[-1].String);
			if (yypvt[-3].Number && yypvt[-1].String) {
				struct stat stbuf;

				if (stat(yypvt[-1].String, &stbuf) < 0)
					perror_reply(550, yypvt[-1].String);
				else if ((stbuf.st_mode&S_IFMT) != S_IFREG) {
					reply(550, "%s: not a plain file.",
						yypvt[-1].String);
				} else {
					register struct tm *t;
					struct tm *gmtime();
					t = gmtime(&stbuf.st_mtime);
					reply(213,
					    "19%02d%02d%02d%02d%02d%02d",
					    t->tm_year, t->tm_mon+1, t->tm_mday,
					    t->tm_hour, t->tm_min, t->tm_sec);
				}
				free(yypvt[-1].String);
			}
		} break;
case 50:
# line 561 "ftpcmd.y"
 {
			if (cmdlogging) syslog(LOG_INFO, "QUIT");
			reply(221, "Goodbye.");
			dologout(0);
		} break;
case 51:
# line 567 "ftpcmd.y"
 {
			yyerrok;
		} break;
case 52:
# line 572 "ftpcmd.y"
 {
			char *renamefrom();

			if (cmdlogging) syslog(LOG_INFO, "RNFR %s", yypvt[-1].String);
			restart_point = (off_t) 0;
			if (yypvt[-3].Number && yypvt[-1].String) {
				fromname = renamefrom(yypvt[-1].String);
				if (fromname == 0 && yypvt[-1].String) {
					free(yypvt[-1].String);
				}
			}
		} break;
case 53:
# line 585 "ftpcmd.y"
 {
			long atol();

			fromname = 0;
			restart_point = yypvt[-1].Number;
			if (cmdlogging) syslog(LOG_INFO, "REST %d", restart_point);
			reply(350, "Restarting at %ld. %s", restart_point,
			    "Send STORE or RETRIEVE to initiate transfer.");
		} break;
case 55:
# line 600 "ftpcmd.y"
 {
			yyval.String = malloc(1);
			yyval.String[0] = '\0';
		} break;
case 58:
# line 612 "ftpcmd.y"
 {
			register char *a, *p;

			a = (char *)&data_dest.sin_addr;
			a[0] = yypvt[-10].Number; a[1] = yypvt[-8].Number; a[2] = yypvt[-6].Number; a[3] = yypvt[-4].Number;
			p = (char *)&data_dest.sin_port;
			p[0] = yypvt[-2].Number; p[1] = yypvt[-0].Number;
			data_dest.sin_family = AF_INET;
		} break;
case 59:
# line 624 "ftpcmd.y"
 {
		yyval.Number = FORM_N;
	} break;
case 60:
# line 628 "ftpcmd.y"
 {
		yyval.Number = FORM_T;
	} break;
case 61:
# line 632 "ftpcmd.y"
 {
		yyval.Number = FORM_C;
	} break;
case 62:
# line 638 "ftpcmd.y"
 {
		cmd_type = TYPE_A;
		cmd_form = FORM_N;
	} break;
case 63:
# line 643 "ftpcmd.y"
 {
		cmd_type = TYPE_A;
		cmd_form = yypvt[-0].Number;
	} break;
case 64:
# line 648 "ftpcmd.y"
 {
		cmd_type = TYPE_E;
		cmd_form = FORM_N;
	} break;
case 65:
# line 653 "ftpcmd.y"
 {
		cmd_type = TYPE_E;
		cmd_form = yypvt[-0].Number;
	} break;
case 66:
# line 658 "ftpcmd.y"
 {
		cmd_type = TYPE_I;
	} break;
case 67:
# line 662 "ftpcmd.y"
 {
		cmd_type = TYPE_L;
		cmd_bytesz = NBBY;
	} break;
case 68:
# line 667 "ftpcmd.y"
 {
		cmd_type = TYPE_L;
		cmd_bytesz = yypvt[-0].Number;
	} break;
case 69:
# line 673 "ftpcmd.y"
 {
		cmd_type = TYPE_L;
		cmd_bytesz = yypvt[-0].Number;
	} break;
case 70:
# line 680 "ftpcmd.y"
 {
		yyval.Number = STRU_F;
	} break;
case 71:
# line 684 "ftpcmd.y"
 {
		yyval.Number = STRU_R;
	} break;
case 72:
# line 688 "ftpcmd.y"
 {
		yyval.Number = STRU_P;
	} break;
case 73:
# line 694 "ftpcmd.y"
 {
		yyval.Number = MODE_S;
	} break;
case 74:
# line 698 "ftpcmd.y"
 {
		yyval.Number = MODE_B;
	} break;
case 75:
# line 702 "ftpcmd.y"
 {
		yyval.Number = MODE_C;
	} break;
case 76:
# line 708 "ftpcmd.y"
 {
		/*
		 * 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 && yypvt[-0].String && strncmp(yypvt[-0].String, "~", 1) == 0) {
			yyval.String = *glob(yypvt[-0].String);
			if (globerr) {
				reply(550, globerr);
				yyval.String = NULL;
			}
			free(yypvt[-0].String);
		} else
			yyval.String = yypvt[-0].String;
	} break;
case 78:
# line 730 "ftpcmd.y"
 {
		register 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 = yypvt[-0].Number;
		multby = 1;
		ret = 0;
		while (dec) {
			digit = dec%10;
			if (digit > 7) {
				ret = -1;
				break;
			}
			ret += digit * multby;
			multby *= 8;
			dec /= 10;
		}
		yyval.Number = ret;
	} break;
case 79:
# line 755 "ftpcmd.y"
 {
		if (logged_in)
			yyval.Number = 1;
		else {
			if (cmdlogging) syslog(LOG_INFO, "cmd failure - not logged in");
			reply(530, "Please login with USER and PASS.");
			yyval.Number = 0;
		}
	} break;
# line 148 "/usr/lib/yaccpar"

		}
		goto yystack;  /* stack new state and value */

	}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.