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>
122 extern struct sockaddr_in data_dest;
123 extern int logged_in;
124 extern struct passwd *pw;
131 extern int maxtimeout;
133 extern char hostname[], remotehost[];
134 extern char proctitle[];
135 extern char *globerr;
136 extern int usedefault;
137 extern int transflag;
138 extern char tmpline[];
140 extern char **glob(char *);
141 extern char *renamefrom(char *);
142 extern void cwd(const char *);
144 extern void dologout(int);
145 extern void fatal(const char *);
146 extern void makedir(const char *);
147 extern void nack(const char *);
148 extern void pass(const char *);
149 extern void passive(void);
150 extern void pwd(void);
151 extern void removedir(char *);
152 extern void renamecmd(char *, char *);
153 extern void retrieve(const char *, const char *);
154 extern void send_file_list(const char *);
155 extern void statcmd(void);
156 extern void statfilecmd(const char *);
157 extern void store(char *, const char *, int);
158 extern void user(const char *);
160 extern void perror_reply(int, const char *, ...);
161 extern void reply(int, const char *, ...);
162 extern void lreply(int, const char *, ...);
166 static int cmd_bytesz;
172 static char * copy(const char *);
175 yyerror(const char *msg)
179 #line 180 "ftp.tab.c"
185 /* compatibility with bison */
187 /* compatibility with FreeBSD */
188 # ifdef YYPARSE_PARAM_TYPE
189 # define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
191 # define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
194 # define YYPARSE_DECL() yyparse(void)
197 /* Parameters sent to lex. */
199 # define YYLEX_DECL() yylex(void *YYLEX_PARAM)
200 # define YYLEX yylex(YYLEX_PARAM)
202 # define YYLEX_DECL() yylex(void)
203 # define YYLEX yylex()
206 /* Parameters sent to yyerror. */
207 #define YYERROR_DECL() yyerror(const char *s)
208 #define YYERROR_CALL(msg) yyerror(msg)
210 extern int YYPARSE_DECL();
211 extern int YYLEX_DECL();
276 #define YYERRCODE 256
277 static const short ftp_lhs[] = { -1,
278 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
279 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
280 1, 1, 1, 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, 2, 3, 4, 4,
283 12, 5, 13, 13, 13, 6, 6, 6, 6, 6,
284 6, 6, 6, 7, 7, 7, 8, 8, 8, 10,
287 static const short ftp_len[] = { 2,
288 0, 2, 2, 4, 4, 4, 2, 4, 4, 4,
289 4, 8, 5, 5, 5, 3, 5, 3, 5, 5,
290 2, 5, 4, 2, 3, 5, 2, 4, 2, 5,
291 5, 3, 3, 4, 6, 5, 7, 9, 4, 6,
292 5, 2, 5, 5, 2, 2, 5, 1, 0, 1,
293 1, 11, 1, 1, 1, 1, 3, 1, 3, 1,
294 1, 3, 2, 1, 1, 1, 1, 1, 1, 1,
297 static const short ftp_defred[] = { 1,
298 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
299 73, 73, 73, 0, 73, 0, 0, 73, 73, 73,
300 73, 0, 0, 0, 0, 73, 73, 73, 73, 73,
301 0, 73, 73, 2, 3, 46, 0, 0, 45, 0,
302 7, 0, 0, 0, 0, 0, 0, 0, 0, 0,
303 24, 0, 0, 0, 0, 0, 21, 0, 0, 27,
304 29, 0, 0, 0, 0, 0, 42, 0, 0, 48,
305 0, 50, 0, 0, 0, 0, 0, 60, 0, 0,
306 64, 66, 65, 0, 68, 69, 67, 0, 0, 0,
307 0, 0, 0, 71, 0, 70, 0, 0, 25, 0,
308 18, 0, 16, 0, 73, 0, 73, 0, 0, 0,
309 0, 32, 33, 0, 0, 0, 4, 5, 0, 6,
310 0, 0, 0, 51, 63, 8, 9, 10, 0, 0,
311 0, 0, 11, 0, 23, 0, 0, 0, 0, 0,
312 34, 0, 0, 39, 0, 0, 28, 0, 0, 0,
313 0, 0, 0, 55, 53, 54, 57, 59, 62, 13,
314 14, 15, 0, 47, 22, 26, 19, 17, 0, 0,
315 36, 0, 0, 20, 30, 31, 41, 43, 44, 0,
316 0, 35, 72, 0, 40, 0, 0, 0, 37, 0,
317 0, 12, 0, 0, 38, 0, 0, 0, 52,
319 static const short ftp_dgoto[] = { 1,
320 34, 35, 71, 73, 75, 80, 84, 88, 45, 95,
323 static const short ftp_sindex[] = { 0,
324 -224, -247, -239, -236, -232, -222, -204, -200, -181, -177,
325 0, 0, 0, -166, 0, -161, -199, 0, 0, 0,
326 0, -160, -159, -264, -158, 0, 0, 0, 0, 0,
327 -157, 0, 0, 0, 0, 0, -167, -162, 0, -156,
328 0, -250, -198, -165, -155, -154, -153, -151, -150, -152,
329 0, -145, -252, -229, -217, -302, 0, -144, -146, 0,
330 0, -142, -141, -140, -139, -137, 0, -136, -135, 0,
331 -134, 0, -133, -132, -130, -131, -128, 0, -249, -127,
332 0, 0, 0, -126, 0, 0, 0, -125, -152, -152,
333 -152, -205, -152, 0, -124, 0, -152, -152, 0, -152,
334 0, -143, 0, -173, 0, -171, 0, -152, -123, -152,
335 -152, 0, 0, -152, -152, -152, 0, 0, -138, 0,
336 -164, -164, -122, 0, 0, 0, 0, 0, -121, -120,
337 -118, -148, 0, -117, 0, -116, -115, -114, -113, -112,
338 0, -163, -111, 0, -110, -109, 0, -107, -106, -105,
339 -104, -103, -129, 0, 0, 0, 0, 0, 0, 0,
340 0, 0, -101, 0, 0, 0, 0, 0, -100, -102,
341 0, -98, -102, 0, 0, 0, 0, 0, 0, -99,
342 -97, 0, 0, -95, 0, -96, -94, -92, 0, -152,
343 -93, 0, -91, -90, 0, -88, -87, -86, 0,
345 static const short ftp_rindex[] = { 0,
346 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
347 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
348 0, 0, -83, 0, 0, 0, 0, 0, 0, 0,
349 0, 0, 0, 0, 0, 0, 0, -82, 0, 0,
350 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
351 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
352 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
353 0, 0, 0, 0, 0, -81, -80, 0, -158, 0,
354 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
355 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,
367 static const short ftp_gindex[] = { 0,
368 0, 0, 0, 0, 0, 0, 0, 0, 16, -89,
371 #define YYTABLESIZE 190
372 static const short ftp_table[] = { 129,
373 130, 131, 104, 134, 59, 60, 76, 136, 137, 77,
374 138, 78, 79, 105, 106, 107, 98, 99, 146, 123,
375 148, 149, 36, 124, 150, 151, 152, 46, 47, 37,
376 49, 2, 38, 52, 53, 54, 55, 39, 58, 100,
377 101, 62, 63, 64, 65, 66, 40, 68, 69, 3,
378 4, 102, 103, 5, 6, 7, 8, 9, 10, 11,
379 12, 13, 81, 132, 133, 41, 82, 83, 42, 14,
380 51, 15, 16, 17, 18, 19, 20, 21, 22, 23,
381 24, 25, 26, 27, 28, 29, 30, 43, 31, 32,
382 33, 44, 85, 86, 154, 140, 141, 143, 144, 155,
383 193, 87, 48, 156, 70, 170, 171, 50, 56, 72,
384 57, 61, 67, 89, 90, 91, 74, 163, 93, 94,
385 142, 92, 145, 97, 108, 109, 110, 111, 139, 112,
386 113, 114, 115, 116, 153, 117, 118, 121, 119, 120,
387 122, 180, 126, 127, 128, 135, 147, 186, 160, 161,
388 124, 162, 164, 165, 166, 167, 168, 159, 173, 169,
389 174, 172, 175, 176, 177, 178, 179, 181, 158, 182,
390 183, 185, 190, 187, 189, 188, 191, 192, 195, 194,
391 196, 0, 0, 198, 197, 73, 199, 49, 56, 58,
393 static const short ftp_check[] = { 89,
394 90, 91, 305, 93, 269, 270, 257, 97, 98, 260,
395 100, 262, 263, 316, 317, 318, 269, 270, 108, 269,
396 110, 111, 270, 273, 114, 115, 116, 12, 13, 269,
397 15, 256, 269, 18, 19, 20, 21, 270, 23, 269,
398 270, 26, 27, 28, 29, 30, 269, 32, 33, 274,
399 275, 269, 270, 278, 279, 280, 281, 282, 283, 284,
400 285, 286, 261, 269, 270, 270, 265, 266, 269, 294,
401 270, 296, 297, 298, 299, 300, 301, 302, 303, 304,
402 305, 306, 307, 308, 309, 310, 311, 269, 313, 314,
403 315, 269, 258, 259, 259, 269, 270, 269, 270, 264,
404 190, 267, 269, 268, 272, 269, 270, 269, 269, 272,
405 270, 270, 270, 269, 269, 269, 273, 266, 269, 272,
406 105, 273, 107, 269, 269, 272, 269, 269, 272, 270,
407 270, 269, 269, 269, 273, 270, 270, 269, 271, 270,
408 269, 271, 270, 270, 270, 270, 270, 173, 270, 270,
409 273, 270, 270, 270, 270, 270, 270, 123, 269, 272,
410 270, 273, 270, 270, 270, 270, 270, 269, 122, 270,
411 273, 270, 269, 273, 270, 273, 271, 270, 270, 273,
412 271, -1, -1, 271, 273, 269, 273, 270, 270, 270,
418 #define YYMAXTOKEN 319
420 static const char *yyname[] = {
422 "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,
423 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
424 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
425 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
426 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
427 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
428 0,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",
429 "P","R","S","T","SP","CRLF","COMMA","STRING","NUMBER","USER","PASS","ACCT",
430 "REIN","QUIT","PORT","PASV","TYPE","STRU","MODE","RETR","STOR","APPE","MLFL",
431 "MAIL","MSND","MSOM","MSAM","MRSQ","MRCP","ALLO","REST","RNFR","RNTO","ABOR",
432 "DELE","CWD","LIST","NLST","SITE","STAT","HELP","NOOP","MKD","RMD","PWD","CDUP",
433 "STOU","SMNT","SYST","SIZE","MDTM","UMASK","IDLE","CHMOD","LEXERR",
435 static const char *yyrule[] = {
436 "$accept : cmd_list",
438 "cmd_list : cmd_list cmd",
439 "cmd_list : cmd_list rcmd",
440 "cmd : USER SP username CRLF",
441 "cmd : PASS SP password CRLF",
442 "cmd : PORT SP host_port CRLF",
444 "cmd : TYPE SP type_code CRLF",
445 "cmd : STRU SP struct_code CRLF",
446 "cmd : MODE SP mode_code CRLF",
447 "cmd : ALLO SP NUMBER CRLF",
448 "cmd : ALLO SP NUMBER SP R SP NUMBER CRLF",
449 "cmd : RETR check_login SP pathname CRLF",
450 "cmd : STOR check_login SP pathname CRLF",
451 "cmd : APPE check_login SP pathname CRLF",
452 "cmd : NLST check_login CRLF",
453 "cmd : NLST check_login SP STRING CRLF",
454 "cmd : LIST check_login CRLF",
455 "cmd : LIST check_login SP pathname CRLF",
456 "cmd : STAT check_login SP pathname CRLF",
458 "cmd : DELE check_login SP pathname CRLF",
459 "cmd : RNTO SP pathname CRLF",
461 "cmd : CWD check_login CRLF",
462 "cmd : CWD check_login SP pathname CRLF",
464 "cmd : HELP SP STRING CRLF",
466 "cmd : MKD check_login SP pathname CRLF",
467 "cmd : RMD check_login SP pathname CRLF",
468 "cmd : PWD check_login CRLF",
469 "cmd : CDUP check_login CRLF",
470 "cmd : SITE SP HELP CRLF",
471 "cmd : SITE SP HELP SP STRING CRLF",
472 "cmd : SITE SP UMASK check_login CRLF",
473 "cmd : SITE SP UMASK check_login SP octal_number CRLF",
474 "cmd : SITE SP CHMOD check_login SP octal_number SP pathname CRLF",
475 "cmd : SITE SP IDLE CRLF",
476 "cmd : SITE SP IDLE SP NUMBER CRLF",
477 "cmd : STOU check_login SP pathname CRLF",
479 "cmd : SIZE check_login SP pathname CRLF",
480 "cmd : MDTM check_login SP pathname CRLF",
483 "rcmd : RNFR check_login SP pathname CRLF",
487 "byte_size : NUMBER",
488 "host_port : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER",
493 "type_code : A SP form_code",
495 "type_code : E SP form_code",
498 "type_code : L SP byte_size",
499 "type_code : L byte_size",
506 "pathname : pathstring",
507 "pathstring : STRING",
508 "octal_number : NUMBER",
513 /* define the initial stack-sizes */
516 #define YYMAXDEPTH YYSTACKSIZE
519 #define YYSTACKSIZE YYMAXDEPTH
521 #define YYSTACKSIZE 500
522 #define YYMAXDEPTH 500
526 #define YYINITSTACKSIZE 500
544 /* variables for the parser stack */
545 static YYSTACKDATA yystack;
548 extern jmp_buf errcatch;
550 static void upper(char *);
552 #define CMD 0 /* beginning of command */
553 #define ARGS 1 /* expect miscellaneous arguments */
554 #define STR1 2 /* expect SP followed by STRING */
555 #define STR2 3 /* expect STRING */
556 #define OSTR 4 /* optional SP then STRING */
557 #define ZSTR1 5 /* SP then optional STRING */
558 #define ZSTR2 6 /* optional STRING after SP */
559 #define SITECMD 7 /* SITE command */
560 #define NSTR 8 /* Number followed by a string */
566 short implemented; /* 1 if command is implemented */
570 struct tab cmdtab[] = { /* In order defined in RFC 765 */
571 { "USER", USER, STR1, 1, "<sp> username" },
572 { "PASS", PASS, ZSTR1, 1, "<sp> password" },
573 { "ACCT", ACCT, STR1, 0, "(specify account)" },
574 { "SMNT", SMNT, ARGS, 0, "(structure mount)" },
575 { "REIN", REIN, ARGS, 0, "(reinitialize server state)" },
576 { "QUIT", QUIT, ARGS, 1, "(terminate service)", },
577 { "PORT", PORT, ARGS, 1, "<sp> b0, b1, b2, b3, b4" },
578 { "PASV", PASV, ARGS, 1, "(set server in passive mode)" },
579 { "TYPE", TYPE, ARGS, 1, "<sp> [ A | E | I | L ]" },
580 { "STRU", STRU, ARGS, 1, "(specify file structure)" },
581 { "MODE", MODE, ARGS, 1, "(specify transfer mode)" },
582 { "RETR", RETR, STR1, 1, "<sp> file-name" },
583 { "STOR", STOR, STR1, 1, "<sp> file-name" },
584 { "APPE", APPE, STR1, 1, "<sp> file-name" },
585 { "MLFL", MLFL, OSTR, 0, "(mail file)" },
586 { "MAIL", MAIL, OSTR, 0, "(mail to user)" },
587 { "MSND", MSND, OSTR, 0, "(mail send to terminal)" },
588 { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" },
589 { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" },
590 { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" },
591 { "MRCP", MRCP, STR1, 0, "(mail recipient)" },
592 { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" },
593 { "REST", REST, ARGS, 0, "(restart command)" },
594 { "RNFR", RNFR, STR1, 1, "<sp> file-name" },
595 { "RNTO", RNTO, STR1, 1, "<sp> file-name" },
596 { "ABOR", ABOR, ARGS, 1, "(abort operation)" },
597 { "DELE", DELE, STR1, 1, "<sp> file-name" },
598 { "CWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
599 { "XCWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
600 { "LIST", LIST, OSTR, 1, "[ <sp> path-name ]" },
601 { "NLST", NLST, OSTR, 1, "[ <sp> path-name ]" },
602 { "SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]" },
603 { "SYST", SYST, ARGS, 1, "(get type of operating system)" },
604 { "STAT", STAT, OSTR, 1, "[ <sp> path-name ]" },
605 { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
606 { "NOOP", NOOP, ARGS, 1, "" },
607 { "MKD", MKD, STR1, 1, "<sp> path-name" },
608 { "XMKD", MKD, STR1, 1, "<sp> path-name" },
609 { "RMD", RMD, STR1, 1, "<sp> path-name" },
610 { "XRMD", RMD, STR1, 1, "<sp> path-name" },
611 { "PWD", PWD, ARGS, 1, "(return current directory)" },
612 { "XPWD", PWD, ARGS, 1, "(return current directory)" },
613 { "CDUP", CDUP, ARGS, 1, "(change to parent directory)" },
614 { "XCUP", CDUP, ARGS, 1, "(change to parent directory)" },
615 { "STOU", STOU, STR1, 1, "<sp> file-name" },
616 { "SIZE", SIZE, OSTR, 1, "<sp> path-name" },
617 { "MDTM", MDTM, OSTR, 1, "<sp> path-name" },
621 struct tab sitetab[] = {
622 { "UMASK", UMASK, ARGS, 1, "[ <sp> umask ]" },
623 { "IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]" },
624 { "CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name" },
625 { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
630 lookup(struct tab *p, char *cmd)
633 for (; p->name != 0; p++)
634 if (strcmp(cmd, p->name) == 0)
639 #include <arpa/telnet.h>
642 * get_line - a hacked up version of fgets to ignore TELNET escape codes.
645 get_line(char *s, int n, FILE *iop)
651 /* tmpline may contain saved command from urgent mode interruption */
652 for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) {
654 if (tmpline[c] == '\n') {
657 syslog(LOG_DEBUG, "command: %s", s);
664 while ((c = getc(iop)) != EOF) {
667 if ((c = getc(iop)) != EOF) {
673 printf("%c%c%c", IAC, DONT, 0377&c);
674 (void) fflush(stdout);
679 printf("%c%c%c", IAC, WONT, 0377&c);
680 (void) fflush(stdout);
685 continue; /* ignore command */
690 if (--n <= 0 || c == '\n')
693 if (c == EOF && cs == s)
697 syslog(LOG_DEBUG, "command: %s", s);
708 "Timeout (%d seconds): closing control connection.", timeout);
712 "User %s timed out after %d seconds at %s",
713 (pw ? pw -> pw_name : "unknown"), timeout, ctime(&now));
721 static int cpos, state;
722 register char *cp, *cp2;
723 register struct tab *p;
731 (void) signal(SIGALRM, toolong);
732 (void) alarm((unsigned) timeout);
733 if (get_line(cbuf, sizeof(cbuf)-1, stdin) == 0) {
734 reply(221, "You could at least say goodbye.");
739 if (strncasecmp(cbuf, "PASS", 4) != 0)
740 setproctitle("%s: %s", proctitle, cbuf);
741 #endif /* SETPROCTITLE */
742 if ((cp = strchr(cbuf, '\r'))) {
746 if ((cp = strpbrk(cbuf, " \n")))
753 p = lookup(cmdtab, cbuf);
756 if (p->implemented == 0) {
762 *(const char **)(&yylval) = p->name;
768 if (cbuf[cpos] == ' ') {
773 if ((cp2 = strpbrk(cp, " \n")))
778 p = lookup(sitetab, cp);
781 if (p->implemented == 0) {
788 *(const char **)(&yylval) = p->name;
795 if (cbuf[cpos] == '\n') {
804 if (cbuf[cpos] == ' ') {
815 if (cbuf[cpos] == '\n') {
826 * Make sure the string is nonempty and \n terminated.
828 if (n > 1 && cbuf[cpos] == '\n') {
830 *(char **)&yylval = copy(cp);
838 if (cbuf[cpos] == ' ') {
842 if (isdigit(cbuf[cpos])) {
844 while (isdigit(cbuf[++cpos]))
857 if (isdigit(cbuf[cpos])) {
859 while (isdigit(cbuf[++cpos]))
867 switch (cbuf[cpos++]) {
931 fatal("Unknown state in scanner.");
954 p = (char * )malloc(strlen(s) + 1);
956 fatal("Ran out of memory.");
963 help(struct tab *ctab, char *s)
965 register struct tab *c;
966 register int width, NCMDS;
967 const char *help_type;
973 width = 0, NCMDS = 0;
974 for (c = ctab; c->name != 0; c++) {
975 int len = strlen(c->name);
981 width = (width + 8) &~ 7;
983 register int i, j, w;
986 lreply(214, "The following %scommands are recognized %s.",
987 help_type, "(* =>'s unimplemented)");
988 columns = 76 / width;
991 lines = (NCMDS + columns - 1) / columns;
992 for (i = 0; i < lines; i++) {
994 for (j = 0; j < columns; j++) {
995 c = ctab + j * lines + i;
996 assert(c->name != 0);
997 printf("%s%c", c->name,
998 c->implemented ? ' ' : '*');
999 if (c + lines >= &ctab[NCMDS])
1001 w = strlen(c->name) + 1;
1009 (void) fflush(stdout);
1010 reply(214, "Direct comments to ftp-bugs@%s.", hostname);
1014 c = lookup(ctab, s);
1015 if (c == (struct tab *)0) {
1016 reply(502, "Unknown command %s.", s);
1020 reply(214, "Syntax: %s%s %s", help_type, c->name, c->help);
1022 reply(214, "%s%-*s\t%s; unimplemented.", help_type, width,
1027 sizecmd(char *filename)
1033 if (stat(filename, &stbuf) < 0 ||
1034 (stbuf.st_mode&S_IFMT) != S_IFREG)
1035 reply(550, "%s: not a plain file.", filename);
1037 reply(213, "%lu", stbuf.st_size);
1041 register int c, count;
1043 fin = fopen(filename, "r");
1045 perror_reply(550, filename);
1048 if (fstat(fileno(fin), &stbuf) < 0 ||
1049 (stbuf.st_mode&S_IFMT) != S_IFREG) {
1050 reply(550, "%s: not a plain file.", filename);
1056 while((c=getc(fin)) != EOF) {
1057 if (c == '\n') /* will get expanded to \r\n */
1063 reply(213, "%ld", count);
1066 reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
1069 #line 1070 "ftp.tab.c"
1072 #include <stdio.h> /* needed for printf */
1075 #include <stdlib.h> /* needed for malloc, etc */
1076 #include <string.h> /* needed for memset */
1078 /* allocate initial stack or double stack size, up to YYMAXDEPTH */
1079 static int yygrowstack(YYSTACKDATA *data)
1086 if ((newsize = data->stacksize) == 0)
1087 newsize = YYINITSTACKSIZE;
1088 else if (newsize >= YYMAXDEPTH)
1090 else if ((newsize *= 2) > YYMAXDEPTH)
1091 newsize = YYMAXDEPTH;
1093 i = data->s_mark - data->s_base;
1094 newss = (data->s_base != 0)
1095 ? (short *)realloc(data->s_base, newsize * sizeof(*newss))
1096 : (short *)malloc(newsize * sizeof(*newss));
1100 data->s_base = newss;
1101 data->s_mark = newss + i;
1103 newvs = (data->l_base != 0)
1104 ? (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs))
1105 : (YYSTYPE *)malloc(newsize * sizeof(*newvs));
1109 data->l_base = newvs;
1110 data->l_mark = newvs + i;
1112 data->stacksize = newsize;
1113 data->s_last = data->s_base + newsize - 1;
1117 #if YYPURE || defined(YY_NO_LEAKS)
1118 static void yyfreestack(YYSTACKDATA *data)
1122 memset(data, 0, sizeof(*data));
1125 #define yyfreestack(data) /* nothing */
1128 #define YYABORT goto yyabort
1129 #define YYREJECT goto yyabort
1130 #define YYACCEPT goto yyaccept
1131 #define YYERROR goto yyerrlab
1136 int yym, yyn, yystate;
1140 if ((yys = getenv("YYDEBUG")) != 0)
1143 if (yyn >= '0' && yyn <= '9')
1144 yydebug = yyn - '0';
1154 memset(&yystack, 0, sizeof(yystack));
1157 if (yystack.s_base == NULL && yygrowstack(&yystack)) goto yyoverflow;
1158 yystack.s_mark = yystack.s_base;
1159 yystack.l_mark = yystack.l_base;
1161 *yystack.s_mark = 0;
1164 if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1167 if ((yychar = YYLEX) < 0) yychar = 0;
1172 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1173 if (!yys) yys = "illegal-symbol";
1174 printf("%sdebug: state %d, reading %d (%s)\n",
1175 YYPREFIX, yystate, yychar, yys);
1179 if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1180 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1184 printf("%sdebug: state %d, shifting to state %d\n",
1185 YYPREFIX, yystate, yytable[yyn]);
1187 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1191 yystate = yytable[yyn];
1192 *++yystack.s_mark = yytable[yyn];
1193 *++yystack.l_mark = yylval;
1195 if (yyerrflag > 0) --yyerrflag;
1198 if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1199 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1204 if (yyerrflag) goto yyinrecovery;
1206 yyerror("syntax error");
1219 if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 &&
1220 yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1224 printf("%sdebug: state %d, error recovery shifting\
1225 to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]);
1227 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1231 yystate = yytable[yyn];
1232 *++yystack.s_mark = yytable[yyn];
1233 *++yystack.l_mark = yylval;
1240 printf("%sdebug: error recovery discarding state %d\n",
1241 YYPREFIX, *yystack.s_mark);
1243 if (yystack.s_mark <= yystack.s_base) goto yyabort;
1251 if (yychar == 0) goto yyabort;
1256 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1257 if (!yys) yys = "illegal-symbol";
1258 printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1259 YYPREFIX, yystate, yychar, yys);
1269 printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1270 YYPREFIX, yystate, yyn, yyrule[yyn]);
1274 yyval = yystack.l_mark[1-yym];
1276 memset(&yyval, 0, sizeof yyval);
1282 fromname = (char *) 0;
1288 user((char *) yystack.l_mark[-1]);
1289 free((char *) yystack.l_mark[-1]);
1295 pass((char *) yystack.l_mark[-1]);
1296 free((char *) yystack.l_mark[-1]);
1304 (void) close(pdata);
1307 reply(200, "PORT command successful.");
1322 if (cmd_form == FORM_N) {
1323 reply(200, "Type set to A.");
1327 reply(504, "Form must be N.");
1331 reply(504, "Type E not implemented.");
1335 reply(200, "Type set to I.");
1341 if (cmd_bytesz == 8) {
1343 "Type set to L (byte size 8).");
1346 reply(504, "Byte size must be 8.");
1347 #else /* NBBY == 8 */
1348 UNIMPLEMENTED for NBBY != 8
1349 #endif /* NBBY == 8 */
1356 switch (yystack.l_mark[-1]) {
1359 reply(200, "STRU F ok.");
1363 reply(504, "Unimplemented STRU type.");
1370 switch (yystack.l_mark[-1]) {
1373 reply(200, "MODE S ok.");
1377 reply(502, "Unimplemented MODE type.");
1384 reply(202, "ALLO command ignored.");
1390 reply(202, "ALLO command ignored.");
1396 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1397 retrieve((char *) 0, (char *) yystack.l_mark[-1]);
1398 if (yystack.l_mark[-1] != 0)
1399 free((char *) yystack.l_mark[-1]);
1405 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1406 store((char *) yystack.l_mark[-1], "w", 0);
1407 if (yystack.l_mark[-1] != 0)
1408 free((char *) yystack.l_mark[-1]);
1414 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1415 store((char *) yystack.l_mark[-1], "a", 0);
1416 if (yystack.l_mark[-1] != 0)
1417 free((char *) yystack.l_mark[-1]);
1423 if (yystack.l_mark[-1])
1424 send_file_list(".");
1430 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1431 send_file_list((char *) yystack.l_mark[-1]);
1432 if (yystack.l_mark[-1] != 0)
1433 free((char *) yystack.l_mark[-1]);
1439 if (yystack.l_mark[-1])
1440 retrieve("/bin/ls -lgA", "");
1446 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1447 retrieve("/bin/ls -lgA %s", (char *) yystack.l_mark[-1]);
1448 if (yystack.l_mark[-1] != 0)
1449 free((char *) yystack.l_mark[-1]);
1455 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1456 statfilecmd((char *) yystack.l_mark[-1]);
1457 if (yystack.l_mark[-1] != 0)
1458 free((char *) yystack.l_mark[-1]);
1470 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1471 remove((char *) yystack.l_mark[-1]);
1472 if (yystack.l_mark[-1] != 0)
1473 free((char *) yystack.l_mark[-1]);
1480 renamecmd(fromname, (char *) yystack.l_mark[-1]);
1482 fromname = (char *) 0;
1484 reply(503, "Bad sequence of commands.");
1486 free((char *) yystack.l_mark[-1]);
1492 reply(225, "ABOR command successful.");
1498 if (yystack.l_mark[-1])
1505 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1506 cwd((char *) yystack.l_mark[-1]);
1507 if (yystack.l_mark[-1] != 0)
1508 free((char *) yystack.l_mark[-1]);
1514 help(cmdtab, (char *) 0);
1520 register char *cp = (char *)yystack.l_mark[-1];
1522 if (strncasecmp(cp, "SITE", 4) == 0) {
1523 cp = (char *)yystack.l_mark[-1] + 4;
1529 help(sitetab, (char *) 0);
1531 help(cmdtab, (char *) yystack.l_mark[-1]);
1537 reply(200, "NOOP command successful.");
1543 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1544 makedir((char *) yystack.l_mark[-1]);
1545 if (yystack.l_mark[-1] != 0)
1546 free((char *) yystack.l_mark[-1]);
1552 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1553 removedir((char *) yystack.l_mark[-1]);
1554 if (yystack.l_mark[-1] != 0)
1555 free((char *) yystack.l_mark[-1]);
1561 if (yystack.l_mark[-1])
1568 if (yystack.l_mark[-1])
1575 help(sitetab, (char *) 0);
1581 help(sitetab, (char *) yystack.l_mark[-1]);
1589 if (yystack.l_mark[-1]) {
1591 (void) umask(oldmask);
1592 reply(200, "Current UMASK is %03o", oldmask);
1601 if (yystack.l_mark[-3]) {
1602 if ((yystack.l_mark[-1] == -1) || (yystack.l_mark[-1] > 0777)) {
1603 reply(501, "Bad UMASK value");
1605 oldmask = umask(yystack.l_mark[-1]);
1607 "UMASK set to %03o (was %03o)",
1608 yystack.l_mark[-1], oldmask);
1616 if (yystack.l_mark[-5] && (yystack.l_mark[-1] != 0)) {
1617 if (yystack.l_mark[-3] > 0777)
1619 "CHMOD: Mode value must be between 0 and 0777");
1620 else if (chmod((char *) yystack.l_mark[-1], yystack.l_mark[-3]) < 0)
1621 perror_reply(550, (char *) yystack.l_mark[-1]);
1623 reply(200, "CHMOD command successful.");
1625 if (yystack.l_mark[-1] != 0)
1626 free((char *) yystack.l_mark[-1]);
1633 "Current IDLE time limit is %d seconds; max %d",
1634 timeout, maxtimeout);
1640 if (yystack.l_mark[-1] < 30 || yystack.l_mark[-1] > maxtimeout) {
1642 "Maximum IDLE time must be between 30 and %d seconds",
1645 timeout = yystack.l_mark[-1];
1646 (void) alarm((unsigned) timeout);
1648 "Maximum IDLE time set to %d seconds",
1656 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1657 store((char *) yystack.l_mark[-1], "w", 1);
1658 if (yystack.l_mark[-1] != 0)
1659 free((char *) yystack.l_mark[-1]);
1667 reply(215, "UNIX Type: L%d Version: BSD-%d",
1670 reply(215, "UNIX Type: L%d", NBBY);
1673 reply(215, "UNKNOWN Type: L%d", NBBY);
1680 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1681 sizecmd((char *) yystack.l_mark[-1]);
1682 if (yystack.l_mark[-1] != 0)
1683 free((char *) yystack.l_mark[-1]);
1689 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0) {
1691 if (stat((char *) yystack.l_mark[-1], &stbuf) < 0)
1692 perror_reply(550, "%s", (char *) yystack.l_mark[-1]);
1693 else if ((stbuf.st_mode&S_IFMT) != S_IFREG) {
1694 reply(550, "%s: not a plain file.",
1695 (char *) yystack.l_mark[-1]);
1697 register struct tm *t;
1698 t = gmtime(&stbuf.st_mtime);
1700 "19%02d%02d%02d%02d%02d%02d",
1701 t->tm_year, t->tm_mon+1, t->tm_mday,
1702 t->tm_hour, t->tm_min, t->tm_sec);
1705 if (yystack.l_mark[-1] != 0)
1706 free((char *) yystack.l_mark[-1]);
1712 reply(221, "Goodbye.");
1725 if (yystack.l_mark[-3] && yystack.l_mark[-1]) {
1726 fromname = renamefrom((char *) yystack.l_mark[-1]);
1727 if (fromname == (char *) 0 && yystack.l_mark[-1]) {
1728 free((char *) yystack.l_mark[-1]);
1736 *(const char **)(&(yyval)) = "";
1742 register char *a, *p;
1744 a = (char *)&data_dest.sin_addr;
1745 a[0] = yystack.l_mark[-10]; a[1] = yystack.l_mark[-8]; a[2] = yystack.l_mark[-6]; a[3] = yystack.l_mark[-4];
1746 p = (char *)&data_dest.sin_port;
1747 p[0] = yystack.l_mark[-2]; p[1] = yystack.l_mark[0];
1748 data_dest.sin_family = AF_INET;
1780 cmd_form = yystack.l_mark[0];
1794 cmd_form = yystack.l_mark[0];
1814 cmd_bytesz = yystack.l_mark[0];
1821 cmd_bytesz = yystack.l_mark[0];
1864 * Problem: this production is used for all pathname
1865 * processing, but only gives a 550 error reply.
1866 * This is a valid reply in some cases but not in others.
1868 if (logged_in && yystack.l_mark[0] && strncmp((char *) yystack.l_mark[0], "~", 1) == 0) {
1869 *(char **)&(yyval) = *glob((char *) yystack.l_mark[0]);
1871 reply(550, globerr);
1874 free((char *) yystack.l_mark[0]);
1876 yyval = yystack.l_mark[0];
1882 register int ret, dec, multby, digit;
1885 * Convert a number that was read as decimal number
1886 * to what it would be if it had been read as octal.
1888 dec = yystack.l_mark[0];
1897 ret += digit * multby;
1910 reply(530, "Please login with USER and PASS.");
1915 #line 1916 "ftp.tab.c"
1917 yystack.s_mark -= yym;
1918 yystate = *yystack.s_mark;
1919 yystack.l_mark -= yym;
1921 if (yystate == 0 && yym == 0)
1925 printf("%sdebug: after reduction, shifting from state 0 to\
1926 state %d\n", YYPREFIX, YYFINAL);
1929 *++yystack.s_mark = YYFINAL;
1930 *++yystack.l_mark = yyval;
1933 if ((yychar = YYLEX) < 0) yychar = 0;
1938 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1939 if (!yys) yys = "illegal-symbol";
1940 printf("%sdebug: state %d, reading %d (%s)\n",
1941 YYPREFIX, YYFINAL, yychar, yys);
1945 if (yychar == 0) goto yyaccept;
1948 if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1949 yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1950 yystate = yytable[yyn];
1952 yystate = yydgoto[yym];
1955 printf("%sdebug: after reduction, shifting from state %d \
1956 to state %d\n", YYPREFIX, *yystack.s_mark, yystate);
1958 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1962 *++yystack.s_mark = (short) yystate;
1963 *++yystack.l_mark = yyval;
1967 yyerror("yacc stack overflow");
1970 yyfreestack(&yystack);
1974 yyfreestack(&yystack);