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