2 static const char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93";
10 #define yyclearin (yychar = YYEMPTY)
11 #define yyerrok (yyerrflag = 0)
12 #define YYRECOVERING() (yyerrflag != 0)
16 #define yyparse ftp_parse
24 #define yyerror ftp_error
28 #define yychar ftp_char
36 #define yylval ftp_lval
40 #define yydebug ftp_debug
44 #define yynerrs ftp_nerrs
48 #define yyerrflag ftp_errflag
49 #endif /* yyerrflag */
60 #define yydefred ftp_defred
64 #define yydgoto ftp_dgoto
68 #define yysindex ftp_sindex
72 #define yyrindex ftp_rindex
76 #define yygindex ftp_gindex
80 #define yytable ftp_table
84 #define yycheck ftp_check
88 #define yyname ftp_name
92 #define yyrule ftp_rule
94 #define YYPREFIX "ftp_"
100 /* sccsid[] = "@(#)ftpcmd.y 5.20.1.1 (Berkeley) 3/2/89"; */
102 #include <sys/param.h>
103 #include <sys/socket.h>
105 #include <netinet/in.h>
107 #include <arpa/ftp.h>
117 #include <sys/stat.h>
124 static void yyerror(const char *);
127 extern struct sockaddr_in data_dest;
128 extern int logged_in;
129 extern struct passwd *pw;
136 extern int maxtimeout;
138 extern char hostname[], remotehost[];
139 extern char proctitle[];
140 extern char *globerr;
141 extern int usedefault;
142 extern int transflag;
143 extern char tmpline[];
145 extern char **glob(char *);
146 extern char *renamefrom(char *);
147 extern void cwd(const char *);
149 extern void dologout(int);
150 extern void fatal(const char *);
151 extern void makedir(const char *);
152 extern void nack(const char *);
153 extern void pass(const char *);
154 extern void passive(void);
155 extern void pwd(void);
156 extern void removedir(char *);
157 extern void renamecmd(char *, char *);
158 extern void retrieve(const char *, const char *);
159 extern void send_file_list(const char *);
160 extern void statcmd(void);
161 extern void statfilecmd(const char *);
162 extern void store(char *, const char *, int);
163 extern void user(const char *);
165 extern void perror_reply(int, const char *, ...);
166 extern void reply(int, const char *, ...);
167 extern void lreply(int, const char *, ...);
171 static int cmd_bytesz;
179 short implemented; /* 1 if command is implemented */
183 static char * copy(const char *);
186 static void sizecmd(char *filename);
187 static void help(struct tab *ctab, char *s);
189 struct tab sitetab[];
193 yyerror(const char *msg)
199 #undef YYSTYPE_IS_DECLARED
200 #define YYSTYPE_IS_DECLARED 1
202 #ifndef YYSTYPE_IS_DECLARED
203 #define YYSTYPE_IS_DECLARED 1
209 #endif /* !YYSTYPE_IS_DECLARED */
210 #line 211 "ftp.tab.c"
212 /* compatibility with bison */
214 /* compatibility with FreeBSD */
215 # ifdef YYPARSE_PARAM_TYPE
216 # define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
218 # define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
221 # define YYPARSE_DECL() yyparse(void)
224 /* Parameters sent to lex. */
226 # define YYLEX_DECL() yylex(void *YYLEX_PARAM)
227 # define YYLEX yylex(YYLEX_PARAM)
229 # define YYLEX_DECL() yylex(void)
230 # define YYLEX yylex()
233 /* Parameters sent to yyerror. */
235 #define YYERROR_DECL() yyerror(const char *s)
238 #define YYERROR_CALL(msg) yyerror(msg)
241 extern int YYPARSE_DECL();
306 #define YYERRCODE 256
307 static 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,
317 static 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,
327 static 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,
349 static const short ftp_dgoto[] = { 1,
350 125, 45, 157, 88, 184, 84, 73, 95, 96, 71,
353 static 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,
375 static 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,
397 static const short ftp_gindex[] = { 0,
398 4, 16, 11, 0, -29, 0, 0, -89, 0, 0,
401 #define YYTABLESIZE 192
402 static 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,
424 static 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,
450 #define YYMAXTOKEN 319
452 static const char *yyname[] = {
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,
455 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,0,
456 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,0,
457 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,0,
458 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,0,
459 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,0,
460 0,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",
467 static const char *yyrule[] = {
468 "$accept : 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",
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",
490 "cmd : DELE check_login SP pathname CRLF",
491 "cmd : RNTO SP pathname CRLF",
493 "cmd : CWD check_login CRLF",
494 "cmd : CWD check_login SP pathname CRLF",
496 "cmd : HELP SP STRING 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",
511 "cmd : SIZE check_login SP pathname CRLF",
512 "cmd : MDTM check_login SP pathname CRLF",
515 "rcmd : RNFR check_login SP pathname CRLF",
519 "byte_size : NUMBER",
520 "host_port : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER",
525 "type_code : A SP form_code",
527 "type_code : E SP form_code",
530 "type_code : L SP byte_size",
531 "type_code : L byte_size",
538 "pathname : pathstring",
539 "pathstring : STRING",
540 "octal_number : NUMBER",
554 /* define the initial stack-sizes */
557 #define YYMAXDEPTH YYSTACKSIZE
560 #define YYSTACKSIZE YYMAXDEPTH
562 #define YYSTACKSIZE 500
563 #define YYMAXDEPTH 500
567 #define YYINITSTACKSIZE 500
577 /* variables for the parser stack */
578 static YYSTACKDATA yystack;
582 extern int YYLEX_DECL();
585 extern jmp_buf errcatch;
587 static void upper(char *);
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 */
599 struct 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" },
650 struct 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> ]" },
659 lookup(struct tab *p, char *cmd)
662 for (; p->name != 0; p++)
663 if (strcmp(cmd, p->name) == 0)
668 #include <arpa/telnet.h>
671 * get_line - a hacked up version of fgets to ignore TELNET escape codes.
674 get_line(char *s, int n, FILE *iop)
680 /* tmpline may contain saved command from urgent mode interruption */
681 for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) {
683 if (tmpline[c] == '\n') {
686 syslog(LOG_DEBUG, "command: %s", s);
693 while ((c = getc(iop)) != EOF) {
696 if ((c = getc(iop)) != EOF) {
702 printf("%c%c%c", IAC, DONT, 0377&c);
703 (void) fflush(stdout);
708 printf("%c%c%c", IAC, WONT, 0377&c);
709 (void) fflush(stdout);
714 continue; /* ignore command */
719 if (--n <= 0 || c == '\n')
722 if (c == EOF && cs == s)
726 syslog(LOG_DEBUG, "command: %s", s);
737 "Timeout (%d seconds): closing control connection.", timeout);
741 "User %s timed out after %d seconds at %s",
742 (pw ? pw -> pw_name : "unknown"), timeout, ctime(&now));
750 static int cpos, state;
751 register char *cp, *cp2;
752 register struct tab *p;
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.");
768 if (strncasecmp(cbuf, "PASS", 4) != 0)
769 setproctitle("%s: %s", proctitle, cbuf);
770 #endif /* SETPROCTITLE */
771 if ((cp = strchr(cbuf, '\r'))) {
775 if ((cp = strpbrk(cbuf, " \n")))
776 cpos = (int) (cp - cbuf);
782 p = lookup(cmdtab, cbuf);
785 if (p->implemented == 0) {
791 *(const char **)(&yylval) = p->name;
797 if (cbuf[cpos] == ' ') {
802 if ((cp2 = strpbrk(cp, " \n")))
803 cpos = (int) (cp2 - cbuf);
807 p = lookup(sitetab, cp);
810 if (p->implemented == 0) {
817 *(const char **)(&yylval) = p->name;
824 if (cbuf[cpos] == '\n') {
833 if (cbuf[cpos] == ' ') {
844 if (cbuf[cpos] == '\n') {
852 n = (int) strlen(cp);
855 * Make sure the string is nonempty and \n terminated.
857 if (n > 1 && cbuf[cpos] == '\n') {
859 *(char **)&yylval = copy(cp);
867 if (cbuf[cpos] == ' ') {
871 if (isdigit(cbuf[cpos])) {
873 while (isdigit(cbuf[++cpos]))
877 yylval.ival = atoi(cp);
886 if (isdigit(cbuf[cpos])) {
888 while (isdigit(cbuf[++cpos]))
892 yylval.ival = atoi(cp);
896 switch (cbuf[cpos++]) {
960 fatal("Unknown state in scanner.");
983 p = (char * )malloc(strlen(s) + 1);
985 fatal("Ran out of memory.");
992 help(struct tab *ctab, char *s)
994 register struct tab *c;
995 register int width, NCMDS;
996 const char *help_type;
1002 width = 0, NCMDS = 0;
1003 for (c = ctab; c->name != 0; c++) {
1004 int len = (int) strlen(c->name);
1010 width = (width + 8) &~ 7;
1012 register int i, j, w;
1015 lreply(214, "The following %scommands are recognized %s.",
1016 help_type, "(* =>'s unimplemented)");
1017 columns = 76 / width;
1020 lines = (NCMDS + columns - 1) / columns;
1021 for (i = 0; i < lines; i++) {
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])
1030 w = (int) strlen(c->name) + 1;
1038 (void) fflush(stdout);
1039 reply(214, "Direct comments to ftp-bugs@%s.", hostname);
1043 c = lookup(ctab, s);
1044 if (c == (struct tab *)0) {
1045 reply(502, "Unknown command %s.", s);
1049 reply(214, "Syntax: %s%s %s", help_type, c->name, c->help);
1051 reply(214, "%s%-*s\t%s; unimplemented.", help_type, width,
1056 sizecmd(char *filename)
1062 if (stat(filename, &stbuf) < 0 ||
1063 (stbuf.st_mode&S_IFMT) != S_IFREG)
1064 reply(550, "%s: not a plain file.", filename);
1066 #ifdef HAVE_LONG_LONG
1067 reply(213, "%llu", (long long) stbuf.st_size);
1069 reply(213, "%lu", stbuf.st_size);
1074 register int c, count;
1076 fin = fopen(filename, "r");
1078 perror_reply(550, filename);
1081 if (fstat(fileno(fin), &stbuf) < 0 ||
1082 (stbuf.st_mode&S_IFMT) != S_IFREG) {
1083 reply(550, "%s: not a plain file.", filename);
1089 while((c=getc(fin)) != EOF) {
1090 if (c == '\n') /* will get expanded to \r\n */
1096 reply(213, "%ld", count);
1099 reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
1102 #line 1103 "ftp.tab.c"
1105 #include <stdio.h> /* needed for printf */
1108 #include <stdlib.h> /* needed for malloc, etc */
1109 #include <string.h> /* needed for memset */
1111 /* allocate initial stack or double stack size, up to YYMAXDEPTH */
1112 static int yygrowstack(YYSTACKDATA *data)
1119 if ((newsize = data->stacksize) == 0)
1120 newsize = YYINITSTACKSIZE;
1121 else if (newsize >= YYMAXDEPTH)
1123 else if ((newsize *= 2) > YYMAXDEPTH)
1124 newsize = YYMAXDEPTH;
1126 i = (int) (data->s_mark - data->s_base);
1127 newss = (short *)realloc(data->s_base, newsize * sizeof(*newss));
1131 data->s_base = newss;
1132 data->s_mark = newss + i;
1134 newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs));
1138 data->l_base = newvs;
1139 data->l_mark = newvs + i;
1141 data->stacksize = newsize;
1142 data->s_last = data->s_base + newsize - 1;
1146 #if YYPURE || defined(YY_NO_LEAKS)
1147 static void yyfreestack(YYSTACKDATA *data)
1151 memset(data, 0, sizeof(*data));
1154 #define yyfreestack(data) /* nothing */
1157 #define YYABORT goto yyabort
1158 #define YYREJECT goto yyabort
1159 #define YYACCEPT goto yyaccept
1160 #define YYERROR goto yyerrlab
1165 int yym, yyn, yystate;
1169 if ((yys = getenv("YYDEBUG")) != 0)
1172 if (yyn >= '0' && yyn <= '9')
1173 yydebug = yyn - '0';
1183 memset(&yystack, 0, sizeof(yystack));
1186 if (yystack.s_base == NULL && yygrowstack(&yystack)) goto yyoverflow;
1187 yystack.s_mark = yystack.s_base;
1188 yystack.l_mark = yystack.l_base;
1190 *yystack.s_mark = 0;
1193 if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1196 if ((yychar = YYLEX) < 0) yychar = 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);
1208 if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1209 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1213 printf("%sdebug: state %d, shifting to state %d\n",
1214 YYPREFIX, yystate, yytable[yyn]);
1216 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1220 yystate = yytable[yyn];
1221 *++yystack.s_mark = yytable[yyn];
1222 *++yystack.l_mark = yylval;
1224 if (yyerrflag > 0) --yyerrflag;
1227 if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1228 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1233 if (yyerrflag) goto yyinrecovery;
1235 yyerror("syntax error");
1248 if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 &&
1249 yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1253 printf("%sdebug: state %d, error recovery shifting\
1254 to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]);
1256 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1260 yystate = yytable[yyn];
1261 *++yystack.s_mark = yytable[yyn];
1262 *++yystack.l_mark = yylval;
1269 printf("%sdebug: error recovery discarding state %d\n",
1270 YYPREFIX, *yystack.s_mark);
1272 if (yystack.s_mark <= yystack.s_base) goto yyabort;
1280 if (yychar == 0) goto yyabort;
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);
1298 printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1299 YYPREFIX, yystate, yyn, yyrule[yyn]);
1303 yyval = yystack.l_mark[1-yym];
1305 memset(&yyval, 0, sizeof yyval);
1311 fromname = (char *) 0;
1317 user(yystack.l_mark[-1].sval);
1318 free(yystack.l_mark[-1].sval);
1324 pass(yystack.l_mark[-1].sval);
1325 free(yystack.l_mark[-1].sval);
1333 (void) close(pdata);
1336 reply(200, "PORT command successful.");
1351 if (cmd_form == FORM_N) {
1352 reply(200, "Type set to A.");
1356 reply(504, "Form must be N.");
1360 reply(504, "Type E not implemented.");
1364 reply(200, "Type set to I.");
1370 if (cmd_bytesz == 8) {
1372 "Type set to L (byte size 8).");
1375 reply(504, "Byte size must be 8.");
1376 #else /* NBBY == 8 */
1377 UNIMPLEMENTED for NBBY != 8
1378 #endif /* NBBY == 8 */
1385 switch (yystack.l_mark[-1].ival) {
1388 reply(200, "STRU F ok.");
1392 reply(504, "Unimplemented STRU type.");
1399 switch (yystack.l_mark[-1].ival) {
1402 reply(200, "MODE S ok.");
1406 reply(502, "Unimplemented MODE type.");
1413 reply(202, "ALLO command ignored.");
1419 reply(202, "ALLO command ignored.");
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);
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);
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);
1452 if (yystack.l_mark[-1].ival)
1453 send_file_list(".");
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);
1468 if (yystack.l_mark[-1].ival)
1469 retrieve("/bin/ls -lgA", "");
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);
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);
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);
1509 renamecmd(fromname, (char *) yystack.l_mark[-1].sval);
1511 fromname = (char *) 0;
1513 reply(503, "Bad sequence of commands.");
1515 free((char *) yystack.l_mark[-1].sval);
1521 reply(225, "ABOR command successful.");
1527 if (yystack.l_mark[-1].ival)
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);
1543 help(cmdtab, (char *) 0);
1549 register char *cp = (char *)yystack.l_mark[-1].sval;
1551 if (strncasecmp(cp, "SITE", 4) == 0) {
1552 cp = (char *)yystack.l_mark[-1].sval + 4;
1558 help(sitetab, (char *) 0);
1560 help(cmdtab, (char *) yystack.l_mark[-1].sval);
1566 reply(200, "NOOP command successful.");
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);
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);
1590 if (yystack.l_mark[-1].ival)
1597 if (yystack.l_mark[-1].ival)
1604 help(sitetab, (char *) 0);
1610 help(sitetab, (char *) yystack.l_mark[-1].sval);
1618 if (yystack.l_mark[-1].ival) {
1620 (void) umask(oldmask);
1621 reply(200, "Current UMASK is %03o", oldmask);
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");
1634 oldmask = umask(yystack.l_mark[-1].ival);
1636 "UMASK set to %03o (was %03o)",
1637 yystack.l_mark[-1].ival, oldmask);
1645 if (yystack.l_mark[-5].ival && (yystack.l_mark[-1].sval != 0)) {
1646 if (yystack.l_mark[-3].ival > 0777)
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);
1652 reply(200, "CHMOD command successful.");
1654 if (yystack.l_mark[-1].sval != 0)
1655 free((char *) yystack.l_mark[-1].sval);
1662 "Current IDLE time limit is %d seconds; max %d",
1663 timeout, maxtimeout);
1669 if (yystack.l_mark[-1].ival < 30 || yystack.l_mark[-1].ival > maxtimeout) {
1671 "Maximum IDLE time must be between 30 and %d seconds",
1674 timeout = yystack.l_mark[-1].ival;
1675 (void) alarm((unsigned) timeout);
1677 "Maximum IDLE time set to %d seconds",
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);
1696 reply(215, "UNIX Type: L%d Version: BSD-%d",
1699 reply(215, "UNIX Type: L%d", NBBY);
1702 reply(215, "UNKNOWN Type: L%d", NBBY);
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);
1718 if (yystack.l_mark[-3].ival && yystack.l_mark[-1].sval != 0) {
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);
1726 register struct tm *t;
1727 t = gmtime(&stbuf.st_mtime);
1729 "%04d%02d%02d%02d%02d%02d",
1731 t->tm_mon+1, t->tm_mday,
1732 t->tm_hour, t->tm_min, t->tm_sec);
1735 if (yystack.l_mark[-1].sval != 0)
1736 free((char *) yystack.l_mark[-1].sval);
1742 reply(221, "Goodbye.");
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);
1766 *(const char **)(&(yyval.sval)) = "";
1772 register char *a, *p;
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;
1788 yyval.ival = FORM_N;
1794 yyval.ival = FORM_T;
1800 yyval.ival = FORM_C;
1814 cmd_form = yystack.l_mark[0].ival;
1828 cmd_form = yystack.l_mark[0].ival;
1848 cmd_bytesz = yystack.l_mark[0].ival;
1855 cmd_bytesz = yystack.l_mark[0].ival;
1861 yyval.ival = STRU_F;
1867 yyval.ival = STRU_R;
1873 yyval.ival = STRU_P;
1879 yyval.ival = MODE_S;
1885 yyval.ival = MODE_B;
1891 yyval.ival = MODE_C;
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.
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);
1905 reply(550, globerr);
1908 free((char *) yystack.l_mark[0].sval);
1910 yyval.sval = yystack.l_mark[0].sval;
1916 register int ret, dec, multby, digit;
1919 * Convert a number that was read as decimal number
1920 * to what it would be if it had been read as octal.
1922 dec = yystack.l_mark[0].ival;
1931 ret += digit * multby;
1944 reply(530, "Please login with USER and PASS.");
1949 #line 1950 "ftp.tab.c"
1951 yystack.s_mark -= yym;
1952 yystate = *yystack.s_mark;
1953 yystack.l_mark -= yym;
1955 if (yystate == 0 && yym == 0)
1959 printf("%sdebug: after reduction, shifting from state 0 to\
1960 state %d\n", YYPREFIX, YYFINAL);
1963 *++yystack.s_mark = YYFINAL;
1964 *++yystack.l_mark = yyval;
1967 if ((yychar = YYLEX) < 0) yychar = 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);
1979 if (yychar == 0) goto yyaccept;
1982 if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1983 yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1984 yystate = yytable[yyn];
1986 yystate = yydgoto[yym];
1989 printf("%sdebug: after reduction, shifting from state %d \
1990 to state %d\n", YYPREFIX, *yystack.s_mark, yystate);
1992 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1996 *++yystack.s_mark = (short) yystate;
1997 *++yystack.l_mark = yyval;
2001 yyerror("yacc stack overflow");
2004 yyfreestack(&yystack);
2008 yyfreestack(&yystack);