1#ifndef lint
2static const char yysccsid[] = "@(#)yaccpar	1.9 (Berkeley) 02/21/93";
3#endif
4
5#define YYBYACC 1
6#define YYMAJOR 1
7#define YYMINOR 9
8
9#define YYEMPTY        (-1)
10#define yyclearin      (yychar = YYEMPTY)
11#define yyerrok        (yyerrflag = 0)
12#define YYRECOVERING() (yyerrflag != 0)
13
14
15#ifndef yyparse
16#define yyparse    ftp_parse
17#endif /* yyparse */
18
19#ifndef yylex
20#define yylex      ftp_lex
21#endif /* yylex */
22
23#ifndef yyerror
24#define yyerror    ftp_error
25#endif /* yyerror */
26
27#ifndef yychar
28#define yychar     ftp_char
29#endif /* yychar */
30
31#ifndef yyval
32#define yyval      ftp_val
33#endif /* yyval */
34
35#ifndef yylval
36#define yylval     ftp_lval
37#endif /* yylval */
38
39#ifndef yydebug
40#define yydebug    ftp_debug
41#endif /* yydebug */
42
43#ifndef yynerrs
44#define yynerrs    ftp_nerrs
45#endif /* yynerrs */
46
47#ifndef yyerrflag
48#define yyerrflag  ftp_errflag
49#endif /* yyerrflag */
50
51#ifndef yylhs
52#define yylhs      ftp_lhs
53#endif /* yylhs */
54
55#ifndef yylen
56#define yylen      ftp_len
57#endif /* yylen */
58
59#ifndef yydefred
60#define yydefred   ftp_defred
61#endif /* yydefred */
62
63#ifndef yydgoto
64#define yydgoto    ftp_dgoto
65#endif /* yydgoto */
66
67#ifndef yysindex
68#define yysindex   ftp_sindex
69#endif /* yysindex */
70
71#ifndef yyrindex
72#define yyrindex   ftp_rindex
73#endif /* yyrindex */
74
75#ifndef yygindex
76#define yygindex   ftp_gindex
77#endif /* yygindex */
78
79#ifndef yytable
80#define yytable    ftp_table
81#endif /* yytable */
82
83#ifndef yycheck
84#define yycheck    ftp_check
85#endif /* yycheck */
86
87#ifndef yyname
88#define yyname     ftp_name
89#endif /* yyname */
90
91#ifndef yyrule
92#define yyrule     ftp_rule
93#endif /* yyrule */
94#define YYPREFIX "ftp_"
95
96#define YYPURE 0
97
98#line 26 "ftp.y"
99
100/* sccsid[] = "@(#)ftpcmd.y	5.20.1.1 (Berkeley) 3/2/89"; */
101
102#include <sys/param.h>
103#include <sys/socket.h>
104
105#include <netinet/in.h>
106
107#include <arpa/ftp.h>
108
109#include <stdlib.h>
110#include <unistd.h>
111#include <stdio.h>
112#include <signal.h>
113#include <ctype.h>
114#include <pwd.h>
115#include <setjmp.h>
116#include <syslog.h>
117#include <sys/stat.h>
118#include <string.h>
119#include <time.h>
120#include <assert.h>
121
122#ifdef YYBISON
123int yylex(void);
124static void yyerror(const char *);
125#endif
126
127extern	struct sockaddr_in data_dest;
128extern	int logged_in;
129extern	struct passwd *pw;
130extern	int guest;
131extern	int logging;
132extern	int type;
133extern	int form;
134extern	int debug;
135extern	int timeout;
136extern	int maxtimeout;
137extern  int pdata;
138extern	char hostname[], remotehost[];
139extern	char proctitle[];
140extern	char *globerr;
141extern	int usedefault;
142extern  int transflag;
143extern  char tmpline[];
144
145extern char **glob(char *);
146extern char *renamefrom(char *);
147extern void cwd(const char *);
148
149extern void dologout(int);
150extern void fatal(const char *);
151extern void makedir(const char *);
152extern void nack(const char *);
153extern void pass(const char *);
154extern void passive(void);
155extern void pwd(void);
156extern void removedir(char *);
157extern void renamecmd(char *, char *);
158extern void retrieve(const char *, const char *);
159extern void send_file_list(const char *);
160extern void statcmd(void);
161extern void statfilecmd(const char *);
162extern void store(char *, const char *, int);
163extern void user(const char *);
164
165extern void perror_reply(int, const char *, ...);
166extern void reply(int, const char *, ...);
167extern void lreply(int, const char *, ...);
168
169static	int cmd_type;
170static	int cmd_form;
171static	int cmd_bytesz;
172char	cbuf[512];
173char	*fromname;
174
175struct tab {
176	const char *name;
177	short	token;
178	short	state;
179	short	implemented;	/* 1 if command is implemented */
180	const char *help;
181};
182
183static char * copy(const char *);
184
185#ifdef YYBISON
186static void sizecmd(char *filename);
187static void help(struct tab *ctab, char *s);
188struct tab cmdtab[];
189struct tab sitetab[];
190#endif
191
192static void
193yyerror(const char *msg)
194{
195	perror(msg);
196}
197#line 126 "ftp.y"
198#ifdef YYSTYPE
199#undef  YYSTYPE_IS_DECLARED
200#define YYSTYPE_IS_DECLARED 1
201#endif
202#ifndef YYSTYPE_IS_DECLARED
203#define YYSTYPE_IS_DECLARED 1
204typedef union
205{
206	int ival;
207	char *sval;
208} YYSTYPE;
209#endif /* !YYSTYPE_IS_DECLARED */
210#line 211 "ftp.tab.c"
211
212/* compatibility with bison */
213#ifdef YYPARSE_PARAM
214/* compatibility with FreeBSD */
215# ifdef YYPARSE_PARAM_TYPE
216#  define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
217# else
218#  define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
219# endif
220#else
221# define YYPARSE_DECL() yyparse(void)
222#endif
223
224/* Parameters sent to lex. */
225#ifdef YYLEX_PARAM
226# define YYLEX_DECL() yylex(void *YYLEX_PARAM)
227# define YYLEX yylex(YYLEX_PARAM)
228#else
229# define YYLEX_DECL() yylex(void)
230# define YYLEX yylex()
231#endif
232
233/* Parameters sent to yyerror. */
234#ifndef YYERROR_DECL
235#define YYERROR_DECL() yyerror(const char *s)
236#endif
237#ifndef YYERROR_CALL
238#define YYERROR_CALL(msg) yyerror(msg)
239#endif
240
241extern int YYPARSE_DECL();
242
243#define NUMBER 257
244#define STRING 258
245#define A 259
246#define B 260
247#define C 261
248#define E 262
249#define F 263
250#define I 264
251#define L 265
252#define N 266
253#define P 267
254#define R 268
255#define S 269
256#define T 270
257#define SP 271
258#define CRLF 272
259#define COMMA 273
260#define USER 274
261#define PASS 275
262#define ACCT 276
263#define REIN 277
264#define QUIT 278
265#define PORT 279
266#define PASV 280
267#define TYPE 281
268#define STRU 282
269#define MODE 283
270#define RETR 284
271#define STOR 285
272#define APPE 286
273#define MLFL 287
274#define MAIL 288
275#define MSND 289
276#define MSOM 290
277#define MSAM 291
278#define MRSQ 292
279#define MRCP 293
280#define ALLO 294
281#define REST 295
282#define RNFR 296
283#define RNTO 297
284#define ABOR 298
285#define DELE 299
286#define CWD 300
287#define LIST 301
288#define NLST 302
289#define SITE 303
290#define STAT 304
291#define HELP 305
292#define NOOP 306
293#define MKD 307
294#define RMD 308
295#define PWD 309
296#define CDUP 310
297#define STOU 311
298#define SMNT 312
299#define SYST 313
300#define SIZE 314
301#define MDTM 315
302#define UMASK 316
303#define IDLE 317
304#define CHMOD 318
305#define LEXERR 319
306#define YYERRCODE 256
307static const short ftp_lhs[] = {                         -1,
308    0,    0,    0,   11,   11,   11,   11,   11,   11,   11,
309   11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
310   11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
311   11,   11,   11,   11,   11,   11,   11,   11,   11,   11,
312   11,   11,   11,   11,   11,   11,   12,   10,    7,    7,
313    1,   13,    3,    3,    3,   14,   14,   14,   14,   14,
314   14,   14,   14,    6,    6,    6,    4,    4,    4,    8,
315    9,    5,    2,
316};
317static const short ftp_len[] = {                          2,
318    0,    2,    2,    4,    4,    4,    2,    4,    4,    4,
319    4,    8,    5,    5,    5,    3,    5,    3,    5,    5,
320    2,    5,    4,    2,    3,    5,    2,    4,    2,    5,
321    5,    3,    3,    4,    6,    5,    7,    9,    4,    6,
322    5,    2,    5,    5,    2,    2,    5,    1,    0,    1,
323    1,   11,    1,    1,    1,    1,    3,    1,    3,    1,
324    1,    3,    2,    1,    1,    1,    1,    1,    1,    1,
325    1,    1,    0,
326};
327static const short ftp_defred[] = {                       1,
328    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
329   73,   73,   73,    0,   73,    0,    0,   73,   73,   73,
330   73,    0,    0,    0,    0,   73,   73,   73,   73,   73,
331    0,   73,   73,    2,    3,   46,    0,    0,   45,    0,
332    7,    0,    0,    0,    0,    0,    0,    0,    0,    0,
333   24,    0,    0,    0,    0,    0,   21,    0,    0,   27,
334   29,    0,    0,    0,    0,    0,   42,    0,    0,   48,
335    0,   50,    0,    0,    0,    0,    0,   60,    0,    0,
336   64,   66,   65,    0,   68,   69,   67,    0,    0,    0,
337    0,    0,    0,   71,    0,   70,    0,    0,   25,    0,
338   18,    0,   16,    0,   73,    0,   73,    0,    0,    0,
339    0,   32,   33,    0,    0,    0,    4,    5,    0,    6,
340    0,    0,   51,    0,   63,    8,    9,   10,    0,    0,
341    0,    0,   11,    0,   23,    0,    0,    0,    0,    0,
342   34,    0,    0,   39,    0,    0,   28,    0,    0,    0,
343    0,    0,    0,   55,   53,   54,   57,   59,   62,   13,
344   14,   15,    0,   47,   22,   26,   19,   17,    0,    0,
345   36,    0,    0,   20,   30,   31,   41,   43,   44,    0,
346    0,   35,   72,    0,   40,    0,    0,    0,   37,    0,
347    0,   12,    0,    0,   38,    0,    0,    0,   52,
348};
349static const short ftp_dgoto[] = {                        1,
350  125,   45,  157,   88,  184,   84,   73,   95,   96,   71,
351   34,   35,   75,   80,
352};
353static const short ftp_sindex[] = {                       0,
354 -224, -256, -248, -241, -239, -233, -225, -218, -200, -165,
355    0,    0,    0, -164,    0, -163, -176,    0,    0,    0,
356    0, -162, -161, -231, -160,    0,    0,    0,    0,    0,
357 -159,    0,    0,    0,    0,    0, -240, -148,    0, -143,
358    0, -252, -175, -255, -156, -155, -154, -139, -152, -138,
359    0, -149, -205, -203, -177, -253,    0, -147, -133,    0,
360    0, -145, -144, -142, -141, -137,    0, -136, -135,    0,
361 -140,    0, -134, -132, -130, -131, -128,    0, -254, -127,
362    0,    0,    0, -126,    0,    0,    0, -125, -138, -138,
363 -138, -174, -138,    0, -124,    0, -138, -138,    0, -138,
364    0, -129,    0, -172,    0, -169,    0, -138, -123, -138,
365 -138,    0,    0, -138, -138, -138,    0,    0, -120,    0,
366 -246, -246,    0, -118,    0,    0,    0,    0, -122, -121,
367 -119, -116,    0, -117,    0, -115, -114, -113, -112, -104,
368    0, -167, -101,    0, -110, -109,    0, -108, -107, -106,
369 -105, -103, -111,    0,    0,    0,    0,    0,    0,    0,
370    0,    0, -100,    0,    0,    0,    0,    0, -102,  -85,
371    0,  -99,  -85,    0,    0,    0,    0,    0,    0,  -83,
372  -82,    0,    0,  -96,    0,  -94,  -95,  -93,    0, -138,
373  -77,    0,  -91,  -90,    0,  -75,  -88,  -73,    0,
374};
375static const short ftp_rindex[] = {                       0,
376    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
377    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
378    0,    0,  -84,    0,    0,    0,    0,    0,    0,    0,
379    0,    0,    0,    0,    0,    0,    0,  -86,    0,    0,
380    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
381    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
382    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
383    0,    0,    0,    0,    0,  -81,  -80,    0, -160,    0,
384    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
385    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
386    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
387    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
388    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
389    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
390    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
391    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
392    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
393    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
394    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
395    0,    0,    0,    0,    0,    0,    0,    0,    0,
396};
397static const short ftp_gindex[] = {                       0,
398    4,   16,   11,    0,  -29,    0,    0,  -89,    0,    0,
399    0,    0,    0,    0,
400};
401#define YYTABLESIZE 192
402static const short ftp_table[] = {                      129,
403  130,  131,  123,  134,   85,   86,   76,  136,  137,   77,
404  138,   78,   79,   87,  154,   36,  124,   70,  146,  155,
405  148,  149,   37,  156,  150,  151,  152,   46,   47,   38,
406   49,    2,   39,   52,   53,   54,   55,   40,   58,   59,
407   60,   62,   63,   64,   65,   66,   41,   68,   69,    3,
408    4,  104,   42,    5,    6,    7,    8,    9,   10,   11,
409   12,   13,  105,  106,  107,   98,   99,  100,  101,   14,
410   43,   15,   16,   17,   18,   19,   20,   21,   22,   23,
411   24,   25,   26,   27,   28,   29,   30,   81,   31,   32,
412   33,   82,   83,  102,  103,   51,  132,  133,  140,  141,
413  193,  143,  144,  170,  171,   44,   48,   50,   56,   72,
414   57,   61,   67,   74,   89,   90,   91,   92,   93,   94,
415  142,   97,  145,  108,  109,  110,  111,  159,  139,  112,
416  113,  117,  158,  114,  115,  116,  153,  118,  123,  121,
417  119,  120,  122,  186,  126,  127,  128,  135,  147,  160,
418  161,  163,  162,  169,  164,  172,  165,  166,  167,  168,
419  173,  180,  174,  175,  176,  177,  178,    0,  179,  182,
420  181,  183,  185,  187,  188,  189,  190,  191,  192,  194,
421  195,  197,  196,  199,  198,   49,   73,    0,    0,    0,
422   56,   58,
423};
424static const short ftp_check[] = {                       89,
425   90,   91,  257,   93,  260,  261,  259,   97,   98,  262,
426  100,  264,  265,  269,  261,  272,  271,  258,  108,  266,
427  110,  111,  271,  270,  114,  115,  116,   12,   13,  271,
428   15,  256,  272,   18,   19,   20,   21,  271,   23,  271,
429  272,   26,   27,   28,   29,   30,  272,   32,   33,  274,
430  275,  305,  271,  278,  279,  280,  281,  282,  283,  284,
431  285,  286,  316,  317,  318,  271,  272,  271,  272,  294,
432  271,  296,  297,  298,  299,  300,  301,  302,  303,  304,
433  305,  306,  307,  308,  309,  310,  311,  263,  313,  314,
434  315,  267,  268,  271,  272,  272,  271,  272,  271,  272,
435  190,  271,  272,  271,  272,  271,  271,  271,  271,  258,
436  272,  272,  272,  257,  271,  271,  271,  257,  271,  258,
437  105,  271,  107,  271,  258,  271,  271,  124,  258,  272,
438  272,  272,  122,  271,  271,  271,  257,  272,  257,  271,
439  273,  272,  271,  173,  272,  272,  272,  272,  272,  272,
440  272,  268,  272,  258,  272,  257,  272,  272,  272,  272,
441  271,  273,  272,  272,  272,  272,  272,   -1,  272,  272,
442  271,  257,  272,  257,  257,  272,  271,  273,  272,  257,
443  272,  257,  273,  257,  273,  272,  271,   -1,   -1,   -1,
444  272,  272,
445};
446#define YYFINAL 1
447#ifndef YYDEBUG
448#define YYDEBUG 0
449#endif
450#define YYMAXTOKEN 319
451#if YYDEBUG
452static const char *yyname[] = {
453
454"end-of-file",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,0,0,0,0,0,
4550,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,0,0,0,0,0,0,0,0,0,0,0,
4560,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,0,0,0,0,0,0,0,0,0,0,0,
4570,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,0,0,0,0,0,0,0,0,0,0,0,
4580,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,0,0,0,0,0,0,0,0,0,0,0,
4590,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,0,0,0,0,0,0,0,0,0,0,0,
4600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"NUMBER","STRING","A","B","C","E",
461"F","I","L","N","P","R","S","T","SP","CRLF","COMMA","USER","PASS","ACCT","REIN",
462"QUIT","PORT","PASV","TYPE","STRU","MODE","RETR","STOR","APPE","MLFL","MAIL",
463"MSND","MSOM","MSAM","MRSQ","MRCP","ALLO","REST","RNFR","RNTO","ABOR","DELE",
464"CWD","LIST","NLST","SITE","STAT","HELP","NOOP","MKD","RMD","PWD","CDUP","STOU",
465"SMNT","SYST","SIZE","MDTM","UMASK","IDLE","CHMOD","LEXERR",
466};
467static const char *yyrule[] = {
468"$accept : cmd_list",
469"cmd_list :",
470"cmd_list : cmd_list cmd",
471"cmd_list : cmd_list rcmd",
472"cmd : USER SP username CRLF",
473"cmd : PASS SP password CRLF",
474"cmd : PORT SP host_port CRLF",
475"cmd : PASV CRLF",
476"cmd : TYPE SP type_code CRLF",
477"cmd : STRU SP struct_code CRLF",
478"cmd : MODE SP mode_code CRLF",
479"cmd : ALLO SP NUMBER CRLF",
480"cmd : ALLO SP NUMBER SP R SP NUMBER CRLF",
481"cmd : RETR check_login SP pathname CRLF",
482"cmd : STOR check_login SP pathname CRLF",
483"cmd : APPE check_login SP pathname CRLF",
484"cmd : NLST check_login CRLF",
485"cmd : NLST check_login SP STRING CRLF",
486"cmd : LIST check_login CRLF",
487"cmd : LIST check_login SP pathname CRLF",
488"cmd : STAT check_login SP pathname CRLF",
489"cmd : STAT CRLF",
490"cmd : DELE check_login SP pathname CRLF",
491"cmd : RNTO SP pathname CRLF",
492"cmd : ABOR CRLF",
493"cmd : CWD check_login CRLF",
494"cmd : CWD check_login SP pathname CRLF",
495"cmd : HELP CRLF",
496"cmd : HELP SP STRING CRLF",
497"cmd : NOOP CRLF",
498"cmd : MKD check_login SP pathname CRLF",
499"cmd : RMD check_login SP pathname CRLF",
500"cmd : PWD check_login CRLF",
501"cmd : CDUP check_login CRLF",
502"cmd : SITE SP HELP CRLF",
503"cmd : SITE SP HELP SP STRING CRLF",
504"cmd : SITE SP UMASK check_login CRLF",
505"cmd : SITE SP UMASK check_login SP octal_number CRLF",
506"cmd : SITE SP CHMOD check_login SP octal_number SP pathname CRLF",
507"cmd : SITE SP IDLE CRLF",
508"cmd : SITE SP IDLE SP NUMBER CRLF",
509"cmd : STOU check_login SP pathname CRLF",
510"cmd : SYST CRLF",
511"cmd : SIZE check_login SP pathname CRLF",
512"cmd : MDTM check_login SP pathname CRLF",
513"cmd : QUIT CRLF",
514"cmd : error CRLF",
515"rcmd : RNFR check_login SP pathname CRLF",
516"username : STRING",
517"password :",
518"password : STRING",
519"byte_size : NUMBER",
520"host_port : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER",
521"form_code : N",
522"form_code : T",
523"form_code : C",
524"type_code : A",
525"type_code : A SP form_code",
526"type_code : E",
527"type_code : E SP form_code",
528"type_code : I",
529"type_code : L",
530"type_code : L SP byte_size",
531"type_code : L byte_size",
532"struct_code : F",
533"struct_code : R",
534"struct_code : P",
535"mode_code : S",
536"mode_code : B",
537"mode_code : C",
538"pathname : pathstring",
539"pathstring : STRING",
540"octal_number : NUMBER",
541"check_login :",
542
543};
544#endif
545
546int      yydebug;
547int      yynerrs;
548
549int      yyerrflag;
550int      yychar;
551YYSTYPE  yyval;
552YYSTYPE  yylval;
553
554/* define the initial stack-sizes */
555#ifdef YYSTACKSIZE
556#undef YYMAXDEPTH
557#define YYMAXDEPTH  YYSTACKSIZE
558#else
559#ifdef YYMAXDEPTH
560#define YYSTACKSIZE YYMAXDEPTH
561#else
562#define YYSTACKSIZE 500
563#define YYMAXDEPTH  500
564#endif
565#endif
566
567#define YYINITSTACKSIZE 500
568
569typedef struct {
570    unsigned stacksize;
571    short    *s_base;
572    short    *s_mark;
573    short    *s_last;
574    YYSTYPE  *l_base;
575    YYSTYPE  *l_mark;
576} YYSTACKDATA;
577/* variables for the parser stack */
578static YYSTACKDATA yystack;
579#line 733 "ftp.y"
580
581#ifdef YYBYACC
582extern int YYLEX_DECL();
583#endif
584
585extern jmp_buf errcatch;
586
587static void upper(char *);
588
589#define	CMD	0	/* beginning of command */
590#define	ARGS	1	/* expect miscellaneous arguments */
591#define	STR1	2	/* expect SP followed by STRING */
592#define	STR2	3	/* expect STRING */
593#define	OSTR	4	/* optional SP then STRING */
594#define	ZSTR1	5	/* SP then optional STRING */
595#define	ZSTR2	6	/* optional STRING after SP */
596#define	SITECMD	7	/* SITE command */
597#define	NSTR	8	/* Number followed by a string */
598
599struct tab cmdtab[] = {		/* In order defined in RFC 765 */
600	{ "USER", USER, STR1, 1,	"<sp> username" },
601	{ "PASS", PASS, ZSTR1, 1,	"<sp> password" },
602	{ "ACCT", ACCT, STR1, 0,	"(specify account)" },
603	{ "SMNT", SMNT, ARGS, 0,	"(structure mount)" },
604	{ "REIN", REIN, ARGS, 0,	"(reinitialize server state)" },
605	{ "QUIT", QUIT, ARGS, 1,	"(terminate service)", },
606	{ "PORT", PORT, ARGS, 1,	"<sp> b0, b1, b2, b3, b4" },
607	{ "PASV", PASV, ARGS, 1,	"(set server in passive mode)" },
608	{ "TYPE", TYPE, ARGS, 1,	"<sp> [ A | E | I | L ]" },
609	{ "STRU", STRU, ARGS, 1,	"(specify file structure)" },
610	{ "MODE", MODE, ARGS, 1,	"(specify transfer mode)" },
611	{ "RETR", RETR, STR1, 1,	"<sp> file-name" },
612	{ "STOR", STOR, STR1, 1,	"<sp> file-name" },
613	{ "APPE", APPE, STR1, 1,	"<sp> file-name" },
614	{ "MLFL", MLFL, OSTR, 0,	"(mail file)" },
615	{ "MAIL", MAIL, OSTR, 0,	"(mail to user)" },
616	{ "MSND", MSND, OSTR, 0,	"(mail send to terminal)" },
617	{ "MSOM", MSOM, OSTR, 0,	"(mail send to terminal or mailbox)" },
618	{ "MSAM", MSAM, OSTR, 0,	"(mail send to terminal and mailbox)" },
619	{ "MRSQ", MRSQ, OSTR, 0,	"(mail recipient scheme question)" },
620	{ "MRCP", MRCP, STR1, 0,	"(mail recipient)" },
621	{ "ALLO", ALLO, ARGS, 1,	"allocate storage (vacuously)" },
622	{ "REST", REST, ARGS, 0,	"(restart command)" },
623	{ "RNFR", RNFR, STR1, 1,	"<sp> file-name" },
624	{ "RNTO", RNTO, STR1, 1,	"<sp> file-name" },
625	{ "ABOR", ABOR, ARGS, 1,	"(abort operation)" },
626	{ "DELE", DELE, STR1, 1,	"<sp> file-name" },
627	{ "CWD",  CWD,  OSTR, 1,	"[ <sp> directory-name ]" },
628	{ "XCWD", CWD,	OSTR, 1,	"[ <sp> directory-name ]" },
629	{ "LIST", LIST, OSTR, 1,	"[ <sp> path-name ]" },
630	{ "NLST", NLST, OSTR, 1,	"[ <sp> path-name ]" },
631	{ "SITE", SITE, SITECMD, 1,	"site-cmd [ <sp> arguments ]" },
632	{ "SYST", SYST, ARGS, 1,	"(get type of operating system)" },
633	{ "STAT", STAT, OSTR, 1,	"[ <sp> path-name ]" },
634	{ "HELP", HELP, OSTR, 1,	"[ <sp> <string> ]" },
635	{ "NOOP", NOOP, ARGS, 1,	"" },
636	{ "MKD",  MKD,  STR1, 1,	"<sp> path-name" },
637	{ "XMKD", MKD,  STR1, 1,	"<sp> path-name" },
638	{ "RMD",  RMD,  STR1, 1,	"<sp> path-name" },
639	{ "XRMD", RMD,  STR1, 1,	"<sp> path-name" },
640	{ "PWD",  PWD,  ARGS, 1,	"(return current directory)" },
641	{ "XPWD", PWD,  ARGS, 1,	"(return current directory)" },
642	{ "CDUP", CDUP, ARGS, 1,	"(change to parent directory)" },
643	{ "XCUP", CDUP, ARGS, 1,	"(change to parent directory)" },
644	{ "STOU", STOU, STR1, 1,	"<sp> file-name" },
645	{ "SIZE", SIZE, OSTR, 1,	"<sp> path-name" },
646	{ "MDTM", MDTM, OSTR, 1,	"<sp> path-name" },
647	{ 0,   0,    0,    0,	0 }
648};
649
650struct tab sitetab[] = {
651	{ "UMASK", UMASK, ARGS, 1,	"[ <sp> umask ]" },
652	{ "IDLE", IDLE, ARGS, 1,	"[ <sp> maximum-idle-time ]" },
653	{ "CHMOD", CHMOD, NSTR, 1,	"<sp> mode <sp> file-name" },
654	{ "HELP", HELP, OSTR, 1,	"[ <sp> <string> ]" },
655	{ 0,   0,    0,    0,	0 }
656};
657
658static struct tab *
659lookup(struct tab *p, char *cmd)
660{
661
662	for (; p->name != 0; p++)
663		if (strcmp(cmd, p->name) == 0)
664			return (p);
665	return (0);
666}
667
668#include <arpa/telnet.h>
669
670/*
671 * get_line - a hacked up version of fgets to ignore TELNET escape codes.
672 */
673static char *
674get_line(char *s, int n, FILE *iop)
675{
676	register int c;
677	register char *cs;
678
679	cs = s;
680/* tmpline may contain saved command from urgent mode interruption */
681	for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) {
682		*cs++ = tmpline[c];
683		if (tmpline[c] == '\n') {
684			*cs = '\0';
685			if (debug)
686				syslog(LOG_DEBUG, "command: %s", s);
687			tmpline[0] = '\0';
688			return(s);
689		}
690		if (c == 0)
691			tmpline[0] = '\0';
692	}
693	while ((c = getc(iop)) != EOF) {
694		c &= 0377;
695		if (c == IAC) {
696		    if ((c = getc(iop)) != EOF) {
697			c &= 0377;
698			switch (c) {
699			case WILL:
700			case WONT:
701				c = getc(iop);
702				printf("%c%c%c", IAC, DONT, 0377&c);
703				(void) fflush(stdout);
704				continue;
705			case DO:
706			case DONT:
707				c = getc(iop);
708				printf("%c%c%c", IAC, WONT, 0377&c);
709				(void) fflush(stdout);
710				continue;
711			case IAC:
712				break;
713			default:
714				continue;	/* ignore command */
715			}
716		    }
717		}
718		*cs++ = (char) c;
719		if (--n <= 0 || c == '\n')
720			break;
721	}
722	if (c == EOF && cs == s)
723		return (0);
724	*cs = '\0';
725	if (debug)
726		syslog(LOG_DEBUG, "command: %s", s);
727	return (s);
728}
729
730static void
731toolong(int sig)
732{
733	time_t now;
734
735	(void) sig;
736	reply(421,
737	  "Timeout (%d seconds): closing control connection.", timeout);
738	(void) time(&now);
739	if (logging) {
740		syslog(LOG_INFO,
741			"User %s timed out after %d seconds at %s",
742			(pw ? pw -> pw_name : "unknown"), timeout, ctime(&now));
743	}
744	dologout(1);
745}
746
747int
748yylex(void)
749{
750	static int cpos, state;
751	register char *cp, *cp2;
752	register struct tab *p;
753	int n;
754	char c;
755
756	for (;;) {
757		switch (state) {
758
759		case CMD:
760			(void) signal(SIGALRM, toolong);
761			(void) alarm((unsigned) timeout);
762			if (get_line(cbuf, sizeof(cbuf)-1, stdin) == 0) {
763				reply(221, "You could at least say goodbye.");
764				dologout(0);
765			}
766			(void) alarm(0);
767#ifdef SETPROCTITLE
768			if (strncasecmp(cbuf, "PASS", 4) != 0)
769				setproctitle("%s: %s", proctitle, cbuf);
770#endif /* SETPROCTITLE */
771			if ((cp = strchr(cbuf, '\r'))) {
772				*cp++ = '\n';
773				*cp = '\0';
774			}
775			if ((cp = strpbrk(cbuf, " \n")))
776				cpos = (int) (cp - cbuf);
777			if (cpos == 0)
778				cpos = 4;
779			c = cbuf[cpos];
780			cbuf[cpos] = '\0';
781			upper(cbuf);
782			p = lookup(cmdtab, cbuf);
783			cbuf[cpos] = c;
784			if (p != 0) {
785				if (p->implemented == 0) {
786					nack(p->name);
787					longjmp(errcatch,0);
788					/* NOTREACHED */
789				}
790				state = p->state;
791				*(const char **)(&yylval) = p->name;
792				return (p->token);
793			}
794			break;
795
796		case SITECMD:
797			if (cbuf[cpos] == ' ') {
798				cpos++;
799				return (SP);
800			}
801			cp = &cbuf[cpos];
802			if ((cp2 = strpbrk(cp, " \n")))
803				cpos = (int) (cp2 - cbuf);
804			c = cbuf[cpos];
805			cbuf[cpos] = '\0';
806			upper(cp);
807			p = lookup(sitetab, cp);
808			cbuf[cpos] = c;
809			if (p != 0) {
810				if (p->implemented == 0) {
811					state = CMD;
812					nack(p->name);
813					longjmp(errcatch,0);
814					/* NOTREACHED */
815				}
816				state = p->state;
817				*(const char **)(&yylval) = p->name;
818				return (p->token);
819			}
820			state = CMD;
821			break;
822
823		case OSTR:
824			if (cbuf[cpos] == '\n') {
825				state = CMD;
826				return (CRLF);
827			}
828			/* FALLTHROUGH */
829
830		case STR1:
831		case ZSTR1:
832		dostr1:
833			if (cbuf[cpos] == ' ') {
834				cpos++;
835				if (state == OSTR)
836					state = STR2;
837				else
838					++state;
839				return (SP);
840			}
841			break;
842
843		case ZSTR2:
844			if (cbuf[cpos] == '\n') {
845				state = CMD;
846				return (CRLF);
847			}
848			/* FALLTHROUGH */
849
850		case STR2:
851			cp = &cbuf[cpos];
852			n = (int) strlen(cp);
853			cpos += n - 1;
854			/*
855			 * Make sure the string is nonempty and \n terminated.
856			 */
857			if (n > 1 && cbuf[cpos] == '\n') {
858				cbuf[cpos] = '\0';
859				*(char **)&yylval = copy(cp);
860				cbuf[cpos] = '\n';
861				state = ARGS;
862				return (STRING);
863			}
864			break;
865
866		case NSTR:
867			if (cbuf[cpos] == ' ') {
868				cpos++;
869				return (SP);
870			}
871			if (isdigit(cbuf[cpos])) {
872				cp = &cbuf[cpos];
873				while (isdigit(cbuf[++cpos]))
874					;
875				c = cbuf[cpos];
876				cbuf[cpos] = '\0';
877				yylval.ival = atoi(cp);
878				cbuf[cpos] = c;
879				state = STR1;
880				return (NUMBER);
881			}
882			state = STR1;
883			goto dostr1;
884
885		case ARGS:
886			if (isdigit(cbuf[cpos])) {
887				cp = &cbuf[cpos];
888				while (isdigit(cbuf[++cpos]))
889					;
890				c = cbuf[cpos];
891				cbuf[cpos] = '\0';
892				yylval.ival = atoi(cp);
893				cbuf[cpos] = c;
894				return (NUMBER);
895			}
896			switch (cbuf[cpos++]) {
897
898			case '\n':
899				state = CMD;
900				return (CRLF);
901
902			case ' ':
903				return (SP);
904
905			case ',':
906				return (COMMA);
907
908			case 'A':
909			case 'a':
910				return (A);
911
912			case 'B':
913			case 'b':
914				return (B);
915
916			case 'C':
917			case 'c':
918				return (C);
919
920			case 'E':
921			case 'e':
922				return (E);
923
924			case 'F':
925			case 'f':
926				return (F);
927
928			case 'I':
929			case 'i':
930				return (I);
931
932			case 'L':
933			case 'l':
934				return (L);
935
936			case 'N':
937			case 'n':
938				return (N);
939
940			case 'P':
941			case 'p':
942				return (P);
943
944			case 'R':
945			case 'r':
946				return (R);
947
948			case 'S':
949			case 's':
950				return (S);
951
952			case 'T':
953			case 't':
954				return (T);
955
956			}
957			break;
958
959		default:
960			fatal("Unknown state in scanner.");
961		}
962		yyerror((char *) 0);
963		state = CMD;
964		longjmp(errcatch,0);
965	}
966}
967
968static void
969upper(char *s)
970{
971	while (*s != '\0') {
972		if (islower(*s))
973			*s = toupper(*s);
974		s++;
975	}
976}
977
978static char *
979copy(const char *s)
980{
981	char *p;
982
983	p = (char * )malloc(strlen(s) + 1);
984	if (p == 0)
985		fatal("Ran out of memory.");
986	else
987		(void) strcpy(p, s);
988	return (p);
989}
990
991static void
992help(struct tab *ctab, char *s)
993{
994	register struct tab *c;
995	register int width, NCMDS;
996	const char *help_type;
997
998	if (ctab == sitetab)
999		help_type = "SITE ";
1000	else
1001		help_type = "";
1002	width = 0, NCMDS = 0;
1003	for (c = ctab; c->name != 0; c++) {
1004		int len = (int) strlen(c->name);
1005
1006		if (len > width)
1007			width = len;
1008		NCMDS++;
1009	}
1010	width = (width + 8) &~ 7;
1011	if (s == 0) {
1012		register int i, j, w;
1013		int columns, lines;
1014
1015		lreply(214, "The following %scommands are recognized %s.",
1016		    help_type, "(* =>'s unimplemented)");
1017		columns = 76 / width;
1018		if (columns == 0)
1019			columns = 1;
1020		lines = (NCMDS + columns - 1) / columns;
1021		for (i = 0; i < lines; i++) {
1022			printf("   ");
1023			for (j = 0; j < columns; j++) {
1024				c = ctab + j * lines + i;
1025				assert(c->name != 0);
1026				printf("%s%c", c->name,
1027					c->implemented ? ' ' : '*');
1028				if (c + lines >= &ctab[NCMDS])
1029					break;
1030				w = (int) strlen(c->name) + 1;
1031				while (w < width) {
1032					putchar(' ');
1033					w++;
1034				}
1035			}
1036			printf("\r\n");
1037		}
1038		(void) fflush(stdout);
1039		reply(214, "Direct comments to ftp-bugs@%s.", hostname);
1040		return;
1041	}
1042	upper(s);
1043	c = lookup(ctab, s);
1044	if (c == (struct tab *)0) {
1045		reply(502, "Unknown command %s.", s);
1046		return;
1047	}
1048	if (c->implemented)
1049		reply(214, "Syntax: %s%s %s", help_type, c->name, c->help);
1050	else
1051		reply(214, "%s%-*s\t%s; unimplemented.", help_type, width,
1052		    c->name, c->help);
1053}
1054
1055static void
1056sizecmd(char *filename)
1057{
1058	switch (type) {
1059	case TYPE_L:
1060	case TYPE_I: {
1061		struct stat stbuf;
1062		if (stat(filename, &stbuf) < 0 ||
1063		    (stbuf.st_mode&S_IFMT) != S_IFREG)
1064			reply(550, "%s: not a plain file.", filename);
1065		else
1066#ifdef HAVE_LONG_LONG
1067			reply(213, "%llu", (long long) stbuf.st_size);
1068#else
1069			reply(213, "%lu", stbuf.st_size);
1070#endif
1071		break;}
1072	case TYPE_A: {
1073		FILE *fin;
1074		register int c, count;
1075		struct stat stbuf;
1076		fin = fopen(filename, "r");
1077		if (fin == 0) {
1078			perror_reply(550, filename);
1079			return;
1080		}
1081		if (fstat(fileno(fin), &stbuf) < 0 ||
1082		    (stbuf.st_mode&S_IFMT) != S_IFREG) {
1083			reply(550, "%s: not a plain file.", filename);
1084			(void) fclose(fin);
1085			return;
1086		}
1087
1088		count = 0;
1089		while((c=getc(fin)) != EOF) {
1090			if (c == '\n')	/* will get expanded to \r\n */
1091				count++;
1092			count++;
1093		}
1094		(void) fclose(fin);
1095
1096		reply(213, "%ld", count);
1097		break;}
1098	default:
1099		reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
1100	}
1101}
1102#line 1103 "ftp.tab.c"
1103
1104#if YYDEBUG
1105#include <stdio.h>		/* needed for printf */
1106#endif
1107
1108#include <stdlib.h>	/* needed for malloc, etc */
1109#include <string.h>	/* needed for memset */
1110
1111/* allocate initial stack or double stack size, up to YYMAXDEPTH */
1112static int yygrowstack(YYSTACKDATA *data)
1113{
1114    int i;
1115    unsigned newsize;
1116    short *newss;
1117    YYSTYPE *newvs;
1118
1119    if ((newsize = data->stacksize) == 0)
1120        newsize = YYINITSTACKSIZE;
1121    else if (newsize >= YYMAXDEPTH)
1122        return -1;
1123    else if ((newsize *= 2) > YYMAXDEPTH)
1124        newsize = YYMAXDEPTH;
1125
1126    i = (int) (data->s_mark - data->s_base);
1127    newss = (short *)realloc(data->s_base, newsize * sizeof(*newss));
1128    if (newss == 0)
1129        return -1;
1130
1131    data->s_base = newss;
1132    data->s_mark = newss + i;
1133
1134    newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs));
1135    if (newvs == 0)
1136        return -1;
1137
1138    data->l_base = newvs;
1139    data->l_mark = newvs + i;
1140
1141    data->stacksize = newsize;
1142    data->s_last = data->s_base + newsize - 1;
1143    return 0;
1144}
1145
1146#if YYPURE || defined(YY_NO_LEAKS)
1147static void yyfreestack(YYSTACKDATA *data)
1148{
1149    free(data->s_base);
1150    free(data->l_base);
1151    memset(data, 0, sizeof(*data));
1152}
1153#else
1154#define yyfreestack(data) /* nothing */
1155#endif
1156
1157#define YYABORT  goto yyabort
1158#define YYREJECT goto yyabort
1159#define YYACCEPT goto yyaccept
1160#define YYERROR  goto yyerrlab
1161
1162int
1163YYPARSE_DECL()
1164{
1165    int yym, yyn, yystate;
1166#if YYDEBUG
1167    const char *yys;
1168
1169    if ((yys = getenv("YYDEBUG")) != 0)
1170    {
1171        yyn = *yys;
1172        if (yyn >= '0' && yyn <= '9')
1173            yydebug = yyn - '0';
1174    }
1175#endif
1176
1177    yynerrs = 0;
1178    yyerrflag = 0;
1179    yychar = YYEMPTY;
1180    yystate = 0;
1181
1182#if YYPURE
1183    memset(&yystack, 0, sizeof(yystack));
1184#endif
1185
1186    if (yystack.s_base == NULL && yygrowstack(&yystack)) goto yyoverflow;
1187    yystack.s_mark = yystack.s_base;
1188    yystack.l_mark = yystack.l_base;
1189    yystate = 0;
1190    *yystack.s_mark = 0;
1191
1192yyloop:
1193    if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1194    if (yychar < 0)
1195    {
1196        if ((yychar = YYLEX) < 0) yychar = 0;
1197#if YYDEBUG
1198        if (yydebug)
1199        {
1200            yys = 0;
1201            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1202            if (!yys) yys = "illegal-symbol";
1203            printf("%sdebug: state %d, reading %d (%s)\n",
1204                    YYPREFIX, yystate, yychar, yys);
1205        }
1206#endif
1207    }
1208    if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1209            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1210    {
1211#if YYDEBUG
1212        if (yydebug)
1213            printf("%sdebug: state %d, shifting to state %d\n",
1214                    YYPREFIX, yystate, yytable[yyn]);
1215#endif
1216        if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1217        {
1218            goto yyoverflow;
1219        }
1220        yystate = yytable[yyn];
1221        *++yystack.s_mark = yytable[yyn];
1222        *++yystack.l_mark = yylval;
1223        yychar = YYEMPTY;
1224        if (yyerrflag > 0)  --yyerrflag;
1225        goto yyloop;
1226    }
1227    if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1228            yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1229    {
1230        yyn = yytable[yyn];
1231        goto yyreduce;
1232    }
1233    if (yyerrflag) goto yyinrecovery;
1234
1235    yyerror("syntax error");
1236
1237    goto yyerrlab;
1238
1239yyerrlab:
1240    ++yynerrs;
1241
1242yyinrecovery:
1243    if (yyerrflag < 3)
1244    {
1245        yyerrflag = 3;
1246        for (;;)
1247        {
1248            if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 &&
1249                    yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1250            {
1251#if YYDEBUG
1252                if (yydebug)
1253                    printf("%sdebug: state %d, error recovery shifting\
1254 to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]);
1255#endif
1256                if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1257                {
1258                    goto yyoverflow;
1259                }
1260                yystate = yytable[yyn];
1261                *++yystack.s_mark = yytable[yyn];
1262                *++yystack.l_mark = yylval;
1263                goto yyloop;
1264            }
1265            else
1266            {
1267#if YYDEBUG
1268                if (yydebug)
1269                    printf("%sdebug: error recovery discarding state %d\n",
1270                            YYPREFIX, *yystack.s_mark);
1271#endif
1272                if (yystack.s_mark <= yystack.s_base) goto yyabort;
1273                --yystack.s_mark;
1274                --yystack.l_mark;
1275            }
1276        }
1277    }
1278    else
1279    {
1280        if (yychar == 0) goto yyabort;
1281#if YYDEBUG
1282        if (yydebug)
1283        {
1284            yys = 0;
1285            if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1286            if (!yys) yys = "illegal-symbol";
1287            printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1288                    YYPREFIX, yystate, yychar, yys);
1289        }
1290#endif
1291        yychar = YYEMPTY;
1292        goto yyloop;
1293    }
1294
1295yyreduce:
1296#if YYDEBUG
1297    if (yydebug)
1298        printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1299                YYPREFIX, yystate, yyn, yyrule[yyn]);
1300#endif
1301    yym = yylen[yyn];
1302    if (yym)
1303        yyval = yystack.l_mark[1-yym];
1304    else
1305        memset(&yyval, 0, sizeof yyval);
1306    switch (yyn)
1307    {
1308case 2:
1309#line 172 "ftp.y"
1310	{
1311			fromname = (char *) 0;
1312		}
1313break;
1314case 4:
1315#line 179 "ftp.y"
1316	{
1317			user(yystack.l_mark[-1].sval);
1318			free(yystack.l_mark[-1].sval);
1319		}
1320break;
1321case 5:
1322#line 184 "ftp.y"
1323	{
1324			pass(yystack.l_mark[-1].sval);
1325			free(yystack.l_mark[-1].sval);
1326		}
1327break;
1328case 6:
1329#line 189 "ftp.y"
1330	{
1331			usedefault = 0;
1332			if (pdata >= 0) {
1333				(void) close(pdata);
1334				pdata = -1;
1335			}
1336			reply(200, "PORT command successful.");
1337		}
1338break;
1339case 7:
1340#line 198 "ftp.y"
1341	{
1342			passive();
1343		}
1344break;
1345case 8:
1346#line 202 "ftp.y"
1347	{
1348			switch (cmd_type) {
1349
1350			case TYPE_A:
1351				if (cmd_form == FORM_N) {
1352					reply(200, "Type set to A.");
1353					type = cmd_type;
1354					form = cmd_form;
1355				} else
1356					reply(504, "Form must be N.");
1357				break;
1358
1359			case TYPE_E:
1360				reply(504, "Type E not implemented.");
1361				break;
1362
1363			case TYPE_I:
1364				reply(200, "Type set to I.");
1365				type = cmd_type;
1366				break;
1367
1368			case TYPE_L:
1369#if NBBY == 8
1370				if (cmd_bytesz == 8) {
1371					reply(200,
1372					    "Type set to L (byte size 8).");
1373					type = cmd_type;
1374				} else
1375					reply(504, "Byte size must be 8.");
1376#else /* NBBY == 8 */
1377				UNIMPLEMENTED for NBBY != 8
1378#endif /* NBBY == 8 */
1379			}
1380		}
1381break;
1382case 9:
1383#line 237 "ftp.y"
1384	{
1385			switch (yystack.l_mark[-1].ival) {
1386
1387			case STRU_F:
1388				reply(200, "STRU F ok.");
1389				break;
1390
1391			default:
1392				reply(504, "Unimplemented STRU type.");
1393			}
1394		}
1395break;
1396case 10:
1397#line 249 "ftp.y"
1398	{
1399			switch (yystack.l_mark[-1].ival) {
1400
1401			case MODE_S:
1402				reply(200, "MODE S ok.");
1403				break;
1404
1405			default:
1406				reply(502, "Unimplemented MODE type.");
1407			}
1408		}
1409break;
1410case 11:
1411#line 261 "ftp.y"
1412	{
1413			reply(202, "ALLO command ignored.");
1414		}
1415break;
1416case 12:
1417#line 265 "ftp.y"
1418	{
1419			reply(202, "ALLO command ignored.");
1420		}
1421break;
1422case 13:
1423#line 269 "ftp.y"
1424	{
1425			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0)
1426				retrieve((char *) 0, yystack.l_mark[-1].sval);
1427			if (yystack.l_mark[-1].sval != 0)
1428				free(yystack.l_mark[-1].sval);
1429		}
1430break;
1431case 14:
1432#line 276 "ftp.y"
1433	{
1434			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0)
1435				store(yystack.l_mark[-1].sval, "w", 0);
1436			if (yystack.l_mark[-1].sval != 0)
1437				free(yystack.l_mark[-1].sval);
1438		}
1439break;
1440case 15:
1441#line 283 "ftp.y"
1442	{
1443			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0)
1444				store(yystack.l_mark[-1].sval, "a", 0);
1445			if (yystack.l_mark[-1].sval != 0)
1446				free(yystack.l_mark[-1].sval);
1447		}
1448break;
1449case 16:
1450#line 290 "ftp.y"
1451	{
1452			if (yystack.l_mark[-1].ival)
1453				send_file_list(".");
1454		}
1455break;
1456case 17:
1457#line 295 "ftp.y"
1458	{
1459			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0)
1460				send_file_list((char *) yystack.l_mark[-1].sval);
1461			if (yystack.l_mark[-1].sval != 0)
1462				free((char *) yystack.l_mark[-1].sval);
1463		}
1464break;
1465case 18:
1466#line 302 "ftp.y"
1467	{
1468			if (yystack.l_mark[-1].ival)
1469				retrieve("/bin/ls -lgA", "");
1470		}
1471break;
1472case 19:
1473#line 307 "ftp.y"
1474	{
1475			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0)
1476				retrieve("/bin/ls -lgA %s", yystack.l_mark[-1].sval);
1477			if (yystack.l_mark[-1].sval != 0)
1478				free(yystack.l_mark[-1].sval);
1479		}
1480break;
1481case 20:
1482#line 314 "ftp.y"
1483	{
1484			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0)
1485				statfilecmd(yystack.l_mark[-1].sval);
1486			if (yystack.l_mark[-1].sval != 0)
1487				free(yystack.l_mark[-1].sval);
1488		}
1489break;
1490case 21:
1491#line 321 "ftp.y"
1492	{
1493			statcmd();
1494		}
1495break;
1496case 22:
1497#line 325 "ftp.y"
1498	{
1499			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0)
1500				remove((char *) yystack.l_mark[-1].sval);
1501			if (yystack.l_mark[-1].sval != 0)
1502				free((char *) yystack.l_mark[-1].sval);
1503		}
1504break;
1505case 23:
1506#line 332 "ftp.y"
1507	{
1508			if (fromname) {
1509				renamecmd(fromname, (char *) yystack.l_mark[-1].sval);
1510				free(fromname);
1511				fromname = (char *) 0;
1512			} else {
1513				reply(503, "Bad sequence of commands.");
1514			}
1515			free((char *) yystack.l_mark[-1].sval);
1516		}
1517break;
1518case 24:
1519#line 343 "ftp.y"
1520	{
1521			reply(225, "ABOR command successful.");
1522		}
1523break;
1524case 25:
1525#line 347 "ftp.y"
1526	{
1527			if (yystack.l_mark[-1].ival)
1528				cwd(pw->pw_dir);
1529		}
1530break;
1531case 26:
1532#line 352 "ftp.y"
1533	{
1534			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0)
1535				cwd((char *) yystack.l_mark[-1].sval);
1536			if (yystack.l_mark[-1].sval != 0)
1537				free((char *) yystack.l_mark[-1].sval);
1538		}
1539break;
1540case 27:
1541#line 359 "ftp.y"
1542	{
1543			help(cmdtab, (char *) 0);
1544		}
1545break;
1546case 28:
1547#line 363 "ftp.y"
1548	{
1549			register char *cp = (char *)yystack.l_mark[-1].sval;
1550
1551			if (strncasecmp(cp, "SITE", 4) == 0) {
1552				cp = (char *)yystack.l_mark[-1].sval + 4;
1553				if (*cp == ' ')
1554					cp++;
1555				if (*cp)
1556					help(sitetab, cp);
1557				else
1558					help(sitetab, (char *) 0);
1559			} else
1560				help(cmdtab, (char *) yystack.l_mark[-1].sval);
1561		}
1562break;
1563case 29:
1564#line 378 "ftp.y"
1565	{
1566			reply(200, "NOOP command successful.");
1567		}
1568break;
1569case 30:
1570#line 382 "ftp.y"
1571	{
1572			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0)
1573				makedir((char *) yystack.l_mark[-1].sval);
1574			if (yystack.l_mark[-1].sval != 0)
1575				free((char *) yystack.l_mark[-1].sval);
1576		}
1577break;
1578case 31:
1579#line 389 "ftp.y"
1580	{
1581			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0)
1582				removedir((char *) yystack.l_mark[-1].sval);
1583			if (yystack.l_mark[-1].sval != 0)
1584				free((char *) yystack.l_mark[-1].sval);
1585		}
1586break;
1587case 32:
1588#line 396 "ftp.y"
1589	{
1590			if (yystack.l_mark[-1].ival)
1591				pwd();
1592		}
1593break;
1594case 33:
1595#line 401 "ftp.y"
1596	{
1597			if (yystack.l_mark[-1].ival)
1598				cwd("..");
1599		}
1600break;
1601case 34:
1602#line 406 "ftp.y"
1603	{
1604			help(sitetab, (char *) 0);
1605		}
1606break;
1607case 35:
1608#line 410 "ftp.y"
1609	{
1610			help(sitetab, (char *) yystack.l_mark[-1].sval);
1611		}
1612break;
1613case 36:
1614#line 414 "ftp.y"
1615	{
1616			int oldmask;
1617
1618			if (yystack.l_mark[-1].ival) {
1619				oldmask = umask(0);
1620				(void) umask(oldmask);
1621				reply(200, "Current UMASK is %03o", oldmask);
1622			}
1623		}
1624break;
1625case 37:
1626#line 424 "ftp.y"
1627	{
1628			int oldmask;
1629
1630			if (yystack.l_mark[-3].ival) {
1631				if ((yystack.l_mark[-1].ival == -1) || (yystack.l_mark[-1].ival > 0777)) {
1632					reply(501, "Bad UMASK value");
1633				} else {
1634					oldmask = umask(yystack.l_mark[-1].ival);
1635					reply(200,
1636					    "UMASK set to %03o (was %03o)",
1637					    yystack.l_mark[-1].ival, oldmask);
1638				}
1639			}
1640		}
1641break;
1642case 38:
1643#line 439 "ftp.y"
1644	{
1645			if (yystack.l_mark[-5].ival && (yystack.l_mark[-1].sval != 0)) {
1646				if (yystack.l_mark[-3].ival > 0777)
1647					reply(501,
1648				"CHMOD: Mode value must be between 0 and 0777");
1649				else if (chmod((char *) yystack.l_mark[-1].sval, yystack.l_mark[-3].ival) < 0)
1650					perror_reply(550, (char *) yystack.l_mark[-1].sval);
1651				else
1652					reply(200, "CHMOD command successful.");
1653			}
1654			if (yystack.l_mark[-1].sval != 0)
1655				free((char *) yystack.l_mark[-1].sval);
1656		}
1657break;
1658case 39:
1659#line 453 "ftp.y"
1660	{
1661			reply(200,
1662			    "Current IDLE time limit is %d seconds; max %d",
1663				timeout, maxtimeout);
1664		}
1665break;
1666case 40:
1667#line 459 "ftp.y"
1668	{
1669			if (yystack.l_mark[-1].ival < 30 || yystack.l_mark[-1].ival > maxtimeout) {
1670				reply(501,
1671			"Maximum IDLE time must be between 30 and %d seconds",
1672				    maxtimeout);
1673			} else {
1674				timeout = yystack.l_mark[-1].ival;
1675				(void) alarm((unsigned) timeout);
1676				reply(200,
1677				    "Maximum IDLE time set to %d seconds",
1678				    timeout);
1679			}
1680		}
1681break;
1682case 41:
1683#line 473 "ftp.y"
1684	{
1685			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0)
1686				store((char *) yystack.l_mark[-1].sval, "w", 1);
1687			if (yystack.l_mark[-1].sval != 0)
1688				free((char *) yystack.l_mark[-1].sval);
1689		}
1690break;
1691case 42:
1692#line 480 "ftp.y"
1693	{
1694#ifdef unix
1695#ifdef BSD
1696			reply(215, "UNIX Type: L%d Version: BSD-%d",
1697				NBBY, BSD);
1698#else /* BSD */
1699			reply(215, "UNIX Type: L%d", NBBY);
1700#endif /* BSD */
1701#else /* unix */
1702			reply(215, "UNKNOWN Type: L%d", NBBY);
1703#endif /* unix */
1704		}
1705break;
1706case 43:
1707#line 501 "ftp.y"
1708	{
1709			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0)
1710				sizecmd((char *) yystack.l_mark[-1].sval);
1711			if (yystack.l_mark[-1].sval != 0)
1712				free((char *) yystack.l_mark[-1].sval);
1713		}
1714break;
1715case 44:
1716#line 518 "ftp.y"
1717	{
1718			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0) {
1719				struct stat stbuf;
1720				if (stat((char *) yystack.l_mark[-1].sval, &stbuf) < 0)
1721					perror_reply(550, "%s", (char *) yystack.l_mark[-1].sval);
1722				else if ((stbuf.st_mode&S_IFMT) != S_IFREG) {
1723					reply(550, "%s: not a plain file.",
1724						(char *) yystack.l_mark[-1].sval);
1725				} else {
1726					register struct tm *t;
1727					t = gmtime(&stbuf.st_mtime);
1728					reply(213,
1729					    "%04d%02d%02d%02d%02d%02d",
1730					    1900 + t->tm_year,
1731					    t->tm_mon+1, t->tm_mday,
1732					    t->tm_hour, t->tm_min, t->tm_sec);
1733				}
1734			}
1735			if (yystack.l_mark[-1].sval != 0)
1736				free((char *) yystack.l_mark[-1].sval);
1737		}
1738break;
1739case 45:
1740#line 540 "ftp.y"
1741	{
1742			reply(221, "Goodbye.");
1743			dologout(0);
1744		}
1745break;
1746case 46:
1747#line 545 "ftp.y"
1748	{
1749			yyerrok;
1750		}
1751break;
1752case 47:
1753#line 550 "ftp.y"
1754	{
1755			if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval) {
1756				fromname = renamefrom((char *) yystack.l_mark[-1].sval);
1757				if (fromname == (char *) 0 && yystack.l_mark[-1].sval) {
1758					free((char *) yystack.l_mark[-1].sval);
1759				}
1760			}
1761		}
1762break;
1763case 49:
1764#line 564 "ftp.y"
1765	{
1766			*(const char **)(&(yyval.sval)) = "";
1767		}
1768break;
1769case 52:
1770#line 575 "ftp.y"
1771	{
1772			register char *a, *p;
1773
1774			a = (char *)&data_dest.sin_addr;
1775			a[0] = (char) yystack.l_mark[-10].ival;
1776			a[1] = (char) yystack.l_mark[-8].ival;
1777			a[2] = (char) yystack.l_mark[-6].ival;
1778			a[3] = (char) yystack.l_mark[-4].ival;
1779			p = (char *)&data_dest.sin_port;
1780			p[0] = (char) yystack.l_mark[-2].ival;
1781			p[1] = (char) yystack.l_mark[0].ival;
1782			data_dest.sin_family = AF_INET;
1783		}
1784break;
1785case 53:
1786#line 591 "ftp.y"
1787	{
1788		yyval.ival = FORM_N;
1789	}
1790break;
1791case 54:
1792#line 595 "ftp.y"
1793	{
1794		yyval.ival = FORM_T;
1795	}
1796break;
1797case 55:
1798#line 599 "ftp.y"
1799	{
1800		yyval.ival = FORM_C;
1801	}
1802break;
1803case 56:
1804#line 605 "ftp.y"
1805	{
1806		cmd_type = TYPE_A;
1807		cmd_form = FORM_N;
1808	}
1809break;
1810case 57:
1811#line 610 "ftp.y"
1812	{
1813		cmd_type = TYPE_A;
1814		cmd_form = yystack.l_mark[0].ival;
1815	}
1816break;
1817case 58:
1818#line 615 "ftp.y"
1819	{
1820		cmd_type = TYPE_E;
1821		cmd_form = FORM_N;
1822	}
1823break;
1824case 59:
1825#line 620 "ftp.y"
1826	{
1827		cmd_type = TYPE_E;
1828		cmd_form = yystack.l_mark[0].ival;
1829	}
1830break;
1831case 60:
1832#line 625 "ftp.y"
1833	{
1834		cmd_type = TYPE_I;
1835	}
1836break;
1837case 61:
1838#line 629 "ftp.y"
1839	{
1840		cmd_type = TYPE_L;
1841		cmd_bytesz = NBBY;
1842	}
1843break;
1844case 62:
1845#line 634 "ftp.y"
1846	{
1847		cmd_type = TYPE_L;
1848		cmd_bytesz = yystack.l_mark[0].ival;
1849	}
1850break;
1851case 63:
1852#line 640 "ftp.y"
1853	{
1854		cmd_type = TYPE_L;
1855		cmd_bytesz = yystack.l_mark[0].ival;
1856	}
1857break;
1858case 64:
1859#line 647 "ftp.y"
1860	{
1861		yyval.ival = STRU_F;
1862	}
1863break;
1864case 65:
1865#line 651 "ftp.y"
1866	{
1867		yyval.ival = STRU_R;
1868	}
1869break;
1870case 66:
1871#line 655 "ftp.y"
1872	{
1873		yyval.ival = STRU_P;
1874	}
1875break;
1876case 67:
1877#line 661 "ftp.y"
1878	{
1879		yyval.ival = MODE_S;
1880	}
1881break;
1882case 68:
1883#line 665 "ftp.y"
1884	{
1885		yyval.ival = MODE_B;
1886	}
1887break;
1888case 69:
1889#line 669 "ftp.y"
1890	{
1891		yyval.ival = MODE_C;
1892	}
1893break;
1894case 70:
1895#line 675 "ftp.y"
1896	{
1897		/*
1898		 * Problem: this production is used for all pathname
1899		 * processing, but only gives a 550 error reply.
1900		 * This is a valid reply in some cases but not in others.
1901		 */
1902		if (logged_in && yystack.l_mark[0].sval && strncmp((char *) yystack.l_mark[0].sval, "~", 1) == 0) {
1903			*(char **)&(yyval.sval) = *glob((char *) yystack.l_mark[0].sval);
1904			if (globerr != 0) {
1905				reply(550, globerr);
1906				yyval.sval = 0;
1907			}
1908			free((char *) yystack.l_mark[0].sval);
1909		} else
1910			yyval.sval = yystack.l_mark[0].sval;
1911	}
1912break;
1913case 72:
1914#line 697 "ftp.y"
1915	{
1916		register int ret, dec, multby, digit;
1917
1918		/*
1919		 * Convert a number that was read as decimal number
1920		 * to what it would be if it had been read as octal.
1921		 */
1922		dec = yystack.l_mark[0].ival;
1923		multby = 1;
1924		ret = 0;
1925		while (dec) {
1926			digit = dec%10;
1927			if (digit > 7) {
1928				ret = -1;
1929				break;
1930			}
1931			ret += digit * multby;
1932			multby *= 8;
1933			dec /= 10;
1934		}
1935		yyval.ival = ret;
1936	}
1937break;
1938case 73:
1939#line 722 "ftp.y"
1940	{
1941		if (logged_in)
1942			yyval.ival = 1;
1943		else {
1944			reply(530, "Please login with USER and PASS.");
1945			yyval.ival = 0;
1946		}
1947	}
1948break;
1949#line 1950 "ftp.tab.c"
1950    }
1951    yystack.s_mark -= yym;
1952    yystate = *yystack.s_mark;
1953    yystack.l_mark -= yym;
1954    yym = yylhs[yyn];
1955    if (yystate == 0 && yym == 0)
1956    {
1957#if YYDEBUG
1958        if (yydebug)
1959            printf("%sdebug: after reduction, shifting from state 0 to\
1960 state %d\n", YYPREFIX, YYFINAL);
1961#endif
1962        yystate = YYFINAL;
1963        *++yystack.s_mark = YYFINAL;
1964        *++yystack.l_mark = yyval;
1965        if (yychar < 0)
1966        {
1967            if ((yychar = YYLEX) < 0) yychar = 0;
1968#if YYDEBUG
1969            if (yydebug)
1970            {
1971                yys = 0;
1972                if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1973                if (!yys) yys = "illegal-symbol";
1974                printf("%sdebug: state %d, reading %d (%s)\n",
1975                        YYPREFIX, YYFINAL, yychar, yys);
1976            }
1977#endif
1978        }
1979        if (yychar == 0) goto yyaccept;
1980        goto yyloop;
1981    }
1982    if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1983            yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1984        yystate = yytable[yyn];
1985    else
1986        yystate = yydgoto[yym];
1987#if YYDEBUG
1988    if (yydebug)
1989        printf("%sdebug: after reduction, shifting from state %d \
1990to state %d\n", YYPREFIX, *yystack.s_mark, yystate);
1991#endif
1992    if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1993    {
1994        goto yyoverflow;
1995    }
1996    *++yystack.s_mark = (short) yystate;
1997    *++yystack.l_mark = yyval;
1998    goto yyloop;
1999
2000yyoverflow:
2001    yyerror("yacc stack overflow");
2002
2003yyabort:
2004    yyfreestack(&yystack);
2005    return (1);
2006
2007yyaccept:
2008    yyfreestack(&yystack);
2009    return (0);
2010}
2011