2 static const char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93";
8 #define YYPATCH 20140101
11 #define yyclearin (yychar = YYEMPTY)
12 #define yyerrok (yyerrflag = 0)
13 #define YYRECOVERING() (yyerrflag != 0)
21 /* sccsid[] = "@(#)ftpcmd.y 5.20.1.1 (Berkeley) 3/2/89"; */
23 #include <sys/param.h>
24 #include <sys/socket.h>
26 #include <netinet/in.h>
45 static void yyerror(const char *);
48 extern struct sockaddr_in data_dest;
50 extern struct passwd *pw;
57 extern int maxtimeout;
59 extern char hostname[], remotehost[];
60 extern char proctitle[];
62 extern int usedefault;
64 extern char tmpline[];
66 extern char **glob(char *);
67 extern char *renamefrom(char *);
68 extern void cwd(const char *);
70 extern void dologout(int);
71 extern void fatal(const char *);
72 extern void makedir(const char *);
73 extern void nack(const char *);
74 extern void pass(const char *);
75 extern void passive(void);
76 extern void pwd(void);
77 extern void removedir(char *);
78 extern void renamecmd(char *, char *);
79 extern void retrieve(const char *, const char *);
80 extern void send_file_list(const char *);
81 extern void statcmd(void);
82 extern void statfilecmd(const char *);
83 extern void store(char *, const char *, int);
84 extern void user(const char *);
86 extern void perror_reply(int, const char *, ...);
87 extern void reply(int, const char *, ...);
88 extern void lreply(int, const char *, ...);
92 static int cmd_bytesz;
100 short implemented; /* 1 if command is implemented */
104 static char * copy(const char *);
107 static void sizecmd(char *filename);
108 static void help(struct tab *ctab, char *s);
110 struct tab sitetab[];
114 yyerror(const char *msg)
118 #line 118 "/dev/stdout"
124 /* compatibility with bison */
126 /* compatibility with FreeBSD */
127 # ifdef YYPARSE_PARAM_TYPE
128 # define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
130 # define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
133 # define YYPARSE_DECL() yyparse(void)
136 /* Parameters sent to lex. */
138 # define YYLEX_DECL() yylex(void *YYLEX_PARAM)
139 # define YYLEX yylex(YYLEX_PARAM)
141 # define YYLEX_DECL() yylex(void)
142 # define YYLEX yylex()
145 /* Parameters sent to yyerror. */
147 #define YYERROR_DECL() yyerror(const char *s)
150 #define YYERROR_CALL(msg) yyerror(msg)
153 extern int YYPARSE_DECL();
218 #define YYERRCODE 256
219 static const short yylhs[] = { -1,
220 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
221 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
222 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
223 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
224 1, 1, 1, 1, 1, 1, 2, 3, 4, 4,
225 12, 5, 13, 13, 13, 6, 6, 6, 6, 6,
226 6, 6, 6, 7, 7, 7, 8, 8, 8, 10,
229 static const short yylen[] = { 2,
230 0, 2, 2, 4, 4, 4, 2, 4, 4, 4,
231 4, 8, 5, 5, 5, 3, 5, 3, 5, 5,
232 2, 5, 4, 2, 3, 5, 2, 4, 2, 5,
233 5, 3, 3, 4, 6, 5, 7, 9, 4, 6,
234 5, 2, 5, 5, 2, 2, 5, 1, 0, 1,
235 1, 11, 1, 1, 1, 1, 3, 1, 3, 1,
236 1, 3, 2, 1, 1, 1, 1, 1, 1, 1,
239 static const short yydefred[] = { 1,
240 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
241 73, 73, 73, 0, 73, 0, 0, 73, 73, 73,
242 73, 0, 0, 0, 0, 73, 73, 73, 73, 73,
243 0, 73, 73, 2, 3, 46, 0, 0, 45, 0,
244 7, 0, 0, 0, 0, 0, 0, 0, 0, 0,
245 24, 0, 0, 0, 0, 0, 21, 0, 0, 27,
246 29, 0, 0, 0, 0, 0, 42, 0, 0, 48,
247 0, 50, 0, 0, 0, 0, 0, 60, 0, 0,
248 64, 66, 65, 0, 68, 69, 67, 0, 0, 0,
249 0, 0, 0, 71, 0, 70, 0, 0, 25, 0,
250 18, 0, 16, 0, 73, 0, 73, 0, 0, 0,
251 0, 32, 33, 0, 0, 0, 4, 5, 0, 6,
252 0, 0, 0, 51, 63, 8, 9, 10, 0, 0,
253 0, 0, 11, 0, 23, 0, 0, 0, 0, 0,
254 34, 0, 0, 39, 0, 0, 28, 0, 0, 0,
255 0, 0, 0, 55, 53, 54, 57, 59, 62, 13,
256 14, 15, 0, 47, 22, 26, 19, 17, 0, 0,
257 36, 0, 0, 20, 30, 31, 41, 43, 44, 0,
258 0, 35, 72, 0, 40, 0, 0, 0, 37, 0,
259 0, 12, 0, 0, 38, 0, 0, 0, 52,
261 static const short yydgoto[] = { 1,
262 34, 35, 71, 73, 75, 80, 84, 88, 45, 95,
265 static const short yysindex[] = { 0,
266 -224, -247, -239, -236, -232, -222, -204, -200, -181, -177,
267 0, 0, 0, -166, 0, -161, -199, 0, 0, 0,
268 0, -160, -159, -264, -158, 0, 0, 0, 0, 0,
269 -157, 0, 0, 0, 0, 0, -167, -162, 0, -156,
270 0, -250, -198, -165, -155, -154, -153, -151, -150, -152,
271 0, -145, -252, -229, -217, -302, 0, -144, -146, 0,
272 0, -142, -141, -140, -139, -137, 0, -136, -135, 0,
273 -134, 0, -133, -132, -130, -131, -128, 0, -249, -127,
274 0, 0, 0, -126, 0, 0, 0, -125, -152, -152,
275 -152, -205, -152, 0, -124, 0, -152, -152, 0, -152,
276 0, -143, 0, -173, 0, -171, 0, -152, -123, -152,
277 -152, 0, 0, -152, -152, -152, 0, 0, -138, 0,
278 -164, -164, -122, 0, 0, 0, 0, 0, -121, -120,
279 -118, -148, 0, -117, 0, -116, -115, -114, -113, -112,
280 0, -163, -111, 0, -110, -109, 0, -107, -106, -105,
281 -104, -103, -129, 0, 0, 0, 0, 0, 0, 0,
282 0, 0, -101, 0, 0, 0, 0, 0, -100, -102,
283 0, -98, -102, 0, 0, 0, 0, 0, 0, -99,
284 -97, 0, 0, -95, 0, -96, -94, -92, 0, -152,
285 -93, 0, -91, -90, 0, -88, -87, -86, 0,
287 static const short yyrindex[] = { 0,
288 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
289 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
290 0, 0, -83, 0, 0, 0, 0, 0, 0, 0,
291 0, 0, 0, 0, 0, 0, 0, -82, 0, 0,
292 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
293 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
294 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
295 0, 0, 0, 0, 0, -81, -80, 0, -158, 0,
296 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
297 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
298 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
299 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
300 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
301 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
302 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
303 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
304 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
305 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
306 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
307 0, 0, 0, 0, 0, 0, 0, 0, 0,
309 static const short yygindex[] = { 0,
310 0, 0, 0, 0, 0, 0, 0, 0, 16, -89,
313 #define YYTABLESIZE 190
314 static const short yytable[] = { 129,
315 130, 131, 104, 134, 59, 60, 76, 136, 137, 77,
316 138, 78, 79, 105, 106, 107, 98, 99, 146, 123,
317 148, 149, 36, 124, 150, 151, 152, 46, 47, 37,
318 49, 2, 38, 52, 53, 54, 55, 39, 58, 100,
319 101, 62, 63, 64, 65, 66, 40, 68, 69, 3,
320 4, 102, 103, 5, 6, 7, 8, 9, 10, 11,
321 12, 13, 81, 132, 133, 41, 82, 83, 42, 14,
322 51, 15, 16, 17, 18, 19, 20, 21, 22, 23,
323 24, 25, 26, 27, 28, 29, 30, 43, 31, 32,
324 33, 44, 85, 86, 154, 140, 141, 143, 144, 155,
325 193, 87, 48, 156, 70, 170, 171, 50, 56, 72,
326 57, 61, 67, 89, 90, 91, 74, 163, 93, 94,
327 142, 92, 145, 97, 108, 109, 110, 111, 139, 112,
328 113, 114, 115, 116, 153, 117, 118, 121, 119, 120,
329 122, 180, 126, 127, 128, 135, 147, 186, 160, 161,
330 124, 162, 164, 165, 166, 167, 168, 159, 173, 169,
331 174, 172, 175, 176, 177, 178, 179, 181, 158, 182,
332 183, 185, 190, 187, 189, 188, 191, 192, 195, 194,
333 196, 0, 0, 198, 197, 73, 199, 49, 56, 58,
335 static const short yycheck[] = { 89,
336 90, 91, 305, 93, 269, 270, 257, 97, 98, 260,
337 100, 262, 263, 316, 317, 318, 269, 270, 108, 269,
338 110, 111, 270, 273, 114, 115, 116, 12, 13, 269,
339 15, 256, 269, 18, 19, 20, 21, 270, 23, 269,
340 270, 26, 27, 28, 29, 30, 269, 32, 33, 274,
341 275, 269, 270, 278, 279, 280, 281, 282, 283, 284,
342 285, 286, 261, 269, 270, 270, 265, 266, 269, 294,
343 270, 296, 297, 298, 299, 300, 301, 302, 303, 304,
344 305, 306, 307, 308, 309, 310, 311, 269, 313, 314,
345 315, 269, 258, 259, 259, 269, 270, 269, 270, 264,
346 190, 267, 269, 268, 272, 269, 270, 269, 269, 272,
347 270, 270, 270, 269, 269, 269, 273, 266, 269, 272,
348 105, 273, 107, 269, 269, 272, 269, 269, 272, 270,
349 270, 269, 269, 269, 273, 270, 270, 269, 271, 270,
350 269, 271, 270, 270, 270, 270, 270, 173, 270, 270,
351 273, 270, 270, 270, 270, 270, 270, 123, 269, 272,
352 270, 273, 270, 270, 270, 270, 270, 269, 122, 270,
353 273, 270, 269, 273, 270, 273, 271, 270, 270, 273,
354 271, -1, -1, 271, 273, 269, 273, 270, 270, 270,
360 #define YYMAXTOKEN 319
361 #define YYTRANSLATE(a) ((a) > YYMAXTOKEN ? (YYMAXTOKEN + 1) : (a))
363 static const char *yyname[] = {
365 "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,
366 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
367 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
368 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
369 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
370 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
371 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",
372 "P","R","S","T","SP","CRLF","COMMA","STRING","NUMBER","USER","PASS","ACCT",
373 "REIN","QUIT","PORT","PASV","TYPE","STRU","MODE","RETR","STOR","APPE","MLFL",
374 "MAIL","MSND","MSOM","MSAM","MRSQ","MRCP","ALLO","REST","RNFR","RNTO","ABOR",
375 "DELE","CWD","LIST","NLST","SITE","STAT","HELP","NOOP","MKD","RMD","PWD","CDUP",
376 "STOU","SMNT","SYST","SIZE","MDTM","UMASK","IDLE","CHMOD","LEXERR",
379 static const char *yyrule[] = {
380 "$accept : cmd_list",
382 "cmd_list : cmd_list cmd",
383 "cmd_list : cmd_list rcmd",
384 "cmd : USER SP username CRLF",
385 "cmd : PASS SP password CRLF",
386 "cmd : PORT SP host_port CRLF",
388 "cmd : TYPE SP type_code CRLF",
389 "cmd : STRU SP struct_code CRLF",
390 "cmd : MODE SP mode_code CRLF",
391 "cmd : ALLO SP NUMBER CRLF",
392 "cmd : ALLO SP NUMBER SP R SP NUMBER CRLF",
393 "cmd : RETR check_login SP pathname CRLF",
394 "cmd : STOR check_login SP pathname CRLF",
395 "cmd : APPE check_login SP pathname CRLF",
396 "cmd : NLST check_login CRLF",
397 "cmd : NLST check_login SP STRING CRLF",
398 "cmd : LIST check_login CRLF",
399 "cmd : LIST check_login SP pathname CRLF",
400 "cmd : STAT check_login SP pathname CRLF",
402 "cmd : DELE check_login SP pathname CRLF",
403 "cmd : RNTO SP pathname CRLF",
405 "cmd : CWD check_login CRLF",
406 "cmd : CWD check_login SP pathname CRLF",
408 "cmd : HELP SP STRING CRLF",
410 "cmd : MKD check_login SP pathname CRLF",
411 "cmd : RMD check_login SP pathname CRLF",
412 "cmd : PWD check_login CRLF",
413 "cmd : CDUP check_login CRLF",
414 "cmd : SITE SP HELP CRLF",
415 "cmd : SITE SP HELP SP STRING CRLF",
416 "cmd : SITE SP UMASK check_login CRLF",
417 "cmd : SITE SP UMASK check_login SP octal_number CRLF",
418 "cmd : SITE SP CHMOD check_login SP octal_number SP pathname CRLF",
419 "cmd : SITE SP IDLE CRLF",
420 "cmd : SITE SP IDLE SP NUMBER CRLF",
421 "cmd : STOU check_login SP pathname CRLF",
423 "cmd : SIZE check_login SP pathname CRLF",
424 "cmd : MDTM check_login SP pathname CRLF",
427 "rcmd : RNFR check_login SP pathname CRLF",
431 "byte_size : NUMBER",
432 "host_port : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER",
437 "type_code : A SP form_code",
439 "type_code : E SP form_code",
442 "type_code : L SP byte_size",
443 "type_code : L byte_size",
450 "pathname : pathstring",
451 "pathstring : STRING",
452 "octal_number : NUMBER",
466 /* define the initial stack-sizes */
469 #define YYMAXDEPTH YYSTACKSIZE
472 #define YYSTACKSIZE YYMAXDEPTH
474 #define YYSTACKSIZE 10000
475 #define YYMAXDEPTH 10000
479 #define YYINITSTACKSIZE 200
489 /* variables for the parser stack */
490 static YYSTACKDATA yystack;
494 extern int YYLEX_DECL();
497 extern jmp_buf errcatch;
499 static void upper(char *);
501 #define CMD 0 /* beginning of command */
502 #define ARGS 1 /* expect miscellaneous arguments */
503 #define STR1 2 /* expect SP followed by STRING */
504 #define STR2 3 /* expect STRING */
505 #define OSTR 4 /* optional SP then STRING */
506 #define ZSTR1 5 /* SP then optional STRING */
507 #define ZSTR2 6 /* optional STRING after SP */
508 #define SITECMD 7 /* SITE command */
509 #define NSTR 8 /* Number followed by a string */
511 struct tab cmdtab[] = { /* In order defined in RFC 765 */
512 { "USER", USER, STR1, 1, "<sp> username" },
513 { "PASS", PASS, ZSTR1, 1, "<sp> password" },
514 { "ACCT", ACCT, STR1, 0, "(specify account)" },
515 { "SMNT", SMNT, ARGS, 0, "(structure mount)" },
516 { "REIN", REIN, ARGS, 0, "(reinitialize server state)" },
517 { "QUIT", QUIT, ARGS, 1, "(terminate service)", },
518 { "PORT", PORT, ARGS, 1, "<sp> b0, b1, b2, b3, b4" },
519 { "PASV", PASV, ARGS, 1, "(set server in passive mode)" },
520 { "TYPE", TYPE, ARGS, 1, "<sp> [ A | E | I | L ]" },
521 { "STRU", STRU, ARGS, 1, "(specify file structure)" },
522 { "MODE", MODE, ARGS, 1, "(specify transfer mode)" },
523 { "RETR", RETR, STR1, 1, "<sp> file-name" },
524 { "STOR", STOR, STR1, 1, "<sp> file-name" },
525 { "APPE", APPE, STR1, 1, "<sp> file-name" },
526 { "MLFL", MLFL, OSTR, 0, "(mail file)" },
527 { "MAIL", MAIL, OSTR, 0, "(mail to user)" },
528 { "MSND", MSND, OSTR, 0, "(mail send to terminal)" },
529 { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" },
530 { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" },
531 { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" },
532 { "MRCP", MRCP, STR1, 0, "(mail recipient)" },
533 { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" },
534 { "REST", REST, ARGS, 0, "(restart command)" },
535 { "RNFR", RNFR, STR1, 1, "<sp> file-name" },
536 { "RNTO", RNTO, STR1, 1, "<sp> file-name" },
537 { "ABOR", ABOR, ARGS, 1, "(abort operation)" },
538 { "DELE", DELE, STR1, 1, "<sp> file-name" },
539 { "CWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
540 { "XCWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
541 { "LIST", LIST, OSTR, 1, "[ <sp> path-name ]" },
542 { "NLST", NLST, OSTR, 1, "[ <sp> path-name ]" },
543 { "SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]" },
544 { "SYST", SYST, ARGS, 1, "(get type of operating system)" },
545 { "STAT", STAT, OSTR, 1, "[ <sp> path-name ]" },
546 { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
547 { "NOOP", NOOP, ARGS, 1, "" },
548 { "MKD", MKD, STR1, 1, "<sp> path-name" },
549 { "XMKD", MKD, STR1, 1, "<sp> path-name" },
550 { "RMD", RMD, STR1, 1, "<sp> path-name" },
551 { "XRMD", RMD, STR1, 1, "<sp> path-name" },
552 { "PWD", PWD, ARGS, 1, "(return current directory)" },
553 { "XPWD", PWD, ARGS, 1, "(return current directory)" },
554 { "CDUP", CDUP, ARGS, 1, "(change to parent directory)" },
555 { "XCUP", CDUP, ARGS, 1, "(change to parent directory)" },
556 { "STOU", STOU, STR1, 1, "<sp> file-name" },
557 { "SIZE", SIZE, OSTR, 1, "<sp> path-name" },
558 { "MDTM", MDTM, OSTR, 1, "<sp> path-name" },
562 struct tab sitetab[] = {
563 { "UMASK", UMASK, ARGS, 1, "[ <sp> umask ]" },
564 { "IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]" },
565 { "CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name" },
566 { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
571 lookup(struct tab *p, char *cmd)
574 for (; p->name != 0; p++)
575 if (strcmp(cmd, p->name) == 0)
580 #include <arpa/telnet.h>
583 * get_line - a hacked up version of fgets to ignore TELNET escape codes.
586 get_line(char *s, int n, FILE *iop)
592 /* tmpline may contain saved command from urgent mode interruption */
593 for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) {
595 if (tmpline[c] == '\n') {
598 syslog(LOG_DEBUG, "command: %s", s);
605 while ((c = getc(iop)) != EOF) {
608 if ((c = getc(iop)) != EOF) {
614 printf("%c%c%c", IAC, DONT, 0377&c);
615 (void) fflush(stdout);
620 printf("%c%c%c", IAC, WONT, 0377&c);
621 (void) fflush(stdout);
626 continue; /* ignore command */
631 if (--n <= 0 || c == '\n')
634 if (c == EOF && cs == s)
638 syslog(LOG_DEBUG, "command: %s", s);
649 "Timeout (%d seconds): closing control connection.", timeout);
653 "User %s timed out after %d seconds at %s",
654 (pw ? pw -> pw_name : "unknown"), timeout, ctime(&now));
662 static int cpos, state;
663 register char *cp, *cp2;
664 register struct tab *p;
672 (void) signal(SIGALRM, toolong);
673 (void) alarm((unsigned) timeout);
674 if (get_line(cbuf, sizeof(cbuf)-1, stdin) == 0) {
675 reply(221, "You could at least say goodbye.");
680 if (strncasecmp(cbuf, "PASS", 4) != 0)
681 setproctitle("%s: %s", proctitle, cbuf);
682 #endif /* SETPROCTITLE */
683 if ((cp = strchr(cbuf, '\r'))) {
687 if ((cp = strpbrk(cbuf, " \n")))
694 p = lookup(cmdtab, cbuf);
697 if (p->implemented == 0) {
703 *(const char **)(&yylval) = p->name;
709 if (cbuf[cpos] == ' ') {
714 if ((cp2 = strpbrk(cp, " \n")))
719 p = lookup(sitetab, cp);
722 if (p->implemented == 0) {
729 *(const char **)(&yylval) = p->name;
736 if (cbuf[cpos] == '\n') {
745 if (cbuf[cpos] == ' ') {
756 if (cbuf[cpos] == '\n') {
767 * Make sure the string is nonempty and \n terminated.
769 if (n > 1 && cbuf[cpos] == '\n') {
771 *(char **)&yylval = copy(cp);
779 if (cbuf[cpos] == ' ') {
783 if (isdigit(cbuf[cpos])) {
785 while (isdigit(cbuf[++cpos]))
798 if (isdigit(cbuf[cpos])) {
800 while (isdigit(cbuf[++cpos]))
808 switch (cbuf[cpos++]) {
872 fatal("Unknown state in scanner.");
895 p = (char * )malloc(strlen(s) + 1);
897 fatal("Ran out of memory.");
904 help(struct tab *ctab, char *s)
906 register struct tab *c;
907 register int width, NCMDS;
908 const char *help_type;
914 width = 0, NCMDS = 0;
915 for (c = ctab; c->name != 0; c++) {
916 int len = strlen(c->name);
922 width = (width + 8) &~ 7;
924 register int i, j, w;
927 lreply(214, "The following %scommands are recognized %s.",
928 help_type, "(* =>'s unimplemented)");
929 columns = 76 / width;
932 lines = (NCMDS + columns - 1) / columns;
933 for (i = 0; i < lines; i++) {
935 for (j = 0; j < columns; j++) {
936 c = ctab + j * lines + i;
937 assert(c->name != 0);
938 printf("%s%c", c->name,
939 c->implemented ? ' ' : '*');
940 if (c + lines >= &ctab[NCMDS])
942 w = strlen(c->name) + 1;
950 (void) fflush(stdout);
951 reply(214, "Direct comments to ftp-bugs@%s.", hostname);
956 if (c == (struct tab *)0) {
957 reply(502, "Unknown command %s.", s);
961 reply(214, "Syntax: %s%s %s", help_type, c->name, c->help);
963 reply(214, "%s%-*s\t%s; unimplemented.", help_type, width,
968 sizecmd(char *filename)
974 if (stat(filename, &stbuf) < 0 ||
975 (stbuf.st_mode&S_IFMT) != S_IFREG)
976 reply(550, "%s: not a plain file.", filename);
978 #ifdef HAVE_LONG_LONG
979 reply(213, "%llu", (long long) stbuf.st_size);
981 reply(213, "%lu", stbuf.st_size);
986 register int c, count;
988 fin = fopen(filename, "r");
990 perror_reply(550, filename);
993 if (fstat(fileno(fin), &stbuf) < 0 ||
994 (stbuf.st_mode&S_IFMT) != S_IFREG) {
995 reply(550, "%s: not a plain file.", filename);
1001 while((c=getc(fin)) != EOF) {
1002 if (c == '\n') /* will get expanded to \r\n */
1008 reply(213, "%ld", count);
1011 reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
1014 #line 1013 "/dev/stdout"
1017 #include <stdio.h> /* needed for printf */
1020 #include <stdlib.h> /* needed for malloc, etc */
1021 #include <string.h> /* needed for memset */
1023 /* allocate initial stack or double stack size, up to YYMAXDEPTH */
1024 static int yygrowstack(YYSTACKDATA *data)
1031 if ((newsize = data->stacksize) == 0)
1032 newsize = YYINITSTACKSIZE;
1033 else if (newsize >= YYMAXDEPTH)
1035 else if ((newsize *= 2) > YYMAXDEPTH)
1036 newsize = YYMAXDEPTH;
1038 i = (int) (data->s_mark - data->s_base);
1039 newss = (short *)realloc(data->s_base, newsize * sizeof(*newss));
1043 data->s_base = newss;
1044 data->s_mark = newss + i;
1046 newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs));
1050 data->l_base = newvs;
1051 data->l_mark = newvs + i;
1053 data->stacksize = newsize;
1054 data->s_last = data->s_base + newsize - 1;
1058 #if YYPURE || defined(YY_NO_LEAKS)
1059 static void yyfreestack(YYSTACKDATA *data)
1063 memset(data, 0, sizeof(*data));
1066 #define yyfreestack(data) /* nothing */
1069 #define YYABORT goto yyabort
1070 #define YYREJECT goto yyabort
1071 #define YYACCEPT goto yyaccept
1072 #define YYERROR goto yyerrlab
1077 int yym, yyn, yystate;
1081 if ((yys = getenv("YYDEBUG")) != 0)
1084 if (yyn >= '0' && yyn <= '9')
1085 yydebug = yyn - '0';
1095 memset(&yystack, 0, sizeof(yystack));
1098 if (yystack.s_base == NULL && yygrowstack(&yystack)) goto yyoverflow;
1099 yystack.s_mark = yystack.s_base;
1100 yystack.l_mark = yystack.l_base;
1102 *yystack.s_mark = 0;
1105 if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1108 if ((yychar = YYLEX) < 0) yychar = 0;
1112 yys = yyname[YYTRANSLATE(yychar)];
1113 printf("%sdebug: state %d, reading %d (%s)\n",
1114 YYPREFIX, yystate, yychar, yys);
1118 if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1119 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1123 printf("%sdebug: state %d, shifting to state %d\n",
1124 YYPREFIX, yystate, yytable[yyn]);
1126 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1130 yystate = yytable[yyn];
1131 *++yystack.s_mark = yytable[yyn];
1132 *++yystack.l_mark = yylval;
1134 if (yyerrflag > 0) --yyerrflag;
1137 if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1138 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1143 if (yyerrflag) goto yyinrecovery;
1145 yyerror("syntax error");
1158 if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 &&
1159 yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1163 printf("%sdebug: state %d, error recovery shifting\
1164 to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]);
1166 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1170 yystate = yytable[yyn];
1171 *++yystack.s_mark = yytable[yyn];
1172 *++yystack.l_mark = yylval;
1179 printf("%sdebug: error recovery discarding state %d\n",
1180 YYPREFIX, *yystack.s_mark);
1182 if (yystack.s_mark <= yystack.s_base) goto yyabort;
1190 if (yychar == 0) goto yyabort;
1194 yys = yyname[YYTRANSLATE(yychar)];
1195 printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1196 YYPREFIX, yystate, yychar, yys);
1206 printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1207 YYPREFIX, yystate, yyn, yyrule[yyn]);
1211 yyval = yystack.l_mark[1-yym];
1213 memset(&yyval, 0, sizeof yyval);
1219 fromname = (char *) 0;
1225 user((char *) yystack.l_mark[-1]);
1226 free((char *) yystack.l_mark[-1]);
1232 pass((char *) yystack.l_mark[-1]);
1233 free((char *) yystack.l_mark[-1]);
1241 (void) close(pdata);
1244 reply(200, "PORT command successful.");
1259 if (cmd_form == FORM_N) {
1260 reply(200, "Type set to A.");
1264 reply(504, "Form must be N.");
1268 reply(504, "Type E not implemented.");
1272 reply(200, "Type set to I.");
1278 if (cmd_bytesz == 8) {
1280 "Type set to L (byte size 8).");
1283 reply(504, "Byte size must be 8.");
1284 #else /* NBBY == 8 */
1285 UNIMPLEMENTED for NBBY != 8
1286 #endif /* NBBY == 8 */
1293 switch (yystack.l_mark[-1]) {
1296 reply(200, "STRU F ok.");
1300 reply(504, "Unimplemented STRU type.");
1307 switch (yystack.l_mark[-1]) {
1310 reply(200, "MODE S ok.");
1314 reply(502, "Unimplemented MODE type.");
1321 reply(202, "ALLO command ignored.");
1327 reply(202, "ALLO command ignored.");
1333 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1334 retrieve((char *) 0, (char *) yystack.l_mark[-1]);
1335 if (yystack.l_mark[-1] != 0)
1336 free((char *) yystack.l_mark[-1]);
1342 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1343 store((char *) yystack.l_mark[-1], "w", 0);
1344 if (yystack.l_mark[-1] != 0)
1345 free((char *) yystack.l_mark[-1]);
1351 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1352 store((char *) yystack.l_mark[-1], "a", 0);
1353 if (yystack.l_mark[-1] != 0)
1354 free((char *) yystack.l_mark[-1]);
1360 if (yystack.l_mark[-1])
1361 send_file_list(".");
1367 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1368 send_file_list((char *) yystack.l_mark[-1]);
1369 if (yystack.l_mark[-1] != 0)
1370 free((char *) yystack.l_mark[-1]);
1376 if (yystack.l_mark[-1])
1377 retrieve("/bin/ls -lgA", "");
1383 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1384 retrieve("/bin/ls -lgA %s", (char *) yystack.l_mark[-1]);
1385 if (yystack.l_mark[-1] != 0)
1386 free((char *) yystack.l_mark[-1]);
1392 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1393 statfilecmd((char *) yystack.l_mark[-1]);
1394 if (yystack.l_mark[-1] != 0)
1395 free((char *) yystack.l_mark[-1]);
1407 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1408 remove((char *) yystack.l_mark[-1]);
1409 if (yystack.l_mark[-1] != 0)
1410 free((char *) yystack.l_mark[-1]);
1417 renamecmd(fromname, (char *) yystack.l_mark[-1]);
1419 fromname = (char *) 0;
1421 reply(503, "Bad sequence of commands.");
1423 free((char *) yystack.l_mark[-1]);
1429 reply(225, "ABOR command successful.");
1435 if (yystack.l_mark[-1])
1442 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1443 cwd((char *) yystack.l_mark[-1]);
1444 if (yystack.l_mark[-1] != 0)
1445 free((char *) yystack.l_mark[-1]);
1451 help(cmdtab, (char *) 0);
1457 register char *cp = (char *)yystack.l_mark[-1];
1459 if (strncasecmp(cp, "SITE", 4) == 0) {
1460 cp = (char *)yystack.l_mark[-1] + 4;
1466 help(sitetab, (char *) 0);
1468 help(cmdtab, (char *) yystack.l_mark[-1]);
1474 reply(200, "NOOP command successful.");
1480 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1481 makedir((char *) yystack.l_mark[-1]);
1482 if (yystack.l_mark[-1] != 0)
1483 free((char *) yystack.l_mark[-1]);
1489 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1490 removedir((char *) yystack.l_mark[-1]);
1491 if (yystack.l_mark[-1] != 0)
1492 free((char *) yystack.l_mark[-1]);
1498 if (yystack.l_mark[-1])
1505 if (yystack.l_mark[-1])
1512 help(sitetab, (char *) 0);
1518 help(sitetab, (char *) yystack.l_mark[-1]);
1526 if (yystack.l_mark[-1]) {
1528 (void) umask(oldmask);
1529 reply(200, "Current UMASK is %03o", oldmask);
1538 if (yystack.l_mark[-3]) {
1539 if ((yystack.l_mark[-1] == -1) || (yystack.l_mark[-1] > 0777)) {
1540 reply(501, "Bad UMASK value");
1542 oldmask = umask(yystack.l_mark[-1]);
1544 "UMASK set to %03o (was %03o)",
1545 yystack.l_mark[-1], oldmask);
1553 if (yystack.l_mark[-5] && (yystack.l_mark[-1] != 0)) {
1554 if (yystack.l_mark[-3] > 0777)
1556 "CHMOD: Mode value must be between 0 and 0777");
1557 else if (chmod((char *) yystack.l_mark[-1], yystack.l_mark[-3]) < 0)
1558 perror_reply(550, (char *) yystack.l_mark[-1]);
1560 reply(200, "CHMOD command successful.");
1562 if (yystack.l_mark[-1] != 0)
1563 free((char *) yystack.l_mark[-1]);
1570 "Current IDLE time limit is %d seconds; max %d",
1571 timeout, maxtimeout);
1577 if (yystack.l_mark[-1] < 30 || yystack.l_mark[-1] > maxtimeout) {
1579 "Maximum IDLE time must be between 30 and %d seconds",
1582 timeout = yystack.l_mark[-1];
1583 (void) alarm((unsigned) timeout);
1585 "Maximum IDLE time set to %d seconds",
1593 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1594 store((char *) yystack.l_mark[-1], "w", 1);
1595 if (yystack.l_mark[-1] != 0)
1596 free((char *) yystack.l_mark[-1]);
1604 reply(215, "UNIX Type: L%d Version: BSD-%d",
1607 reply(215, "UNIX Type: L%d", NBBY);
1610 reply(215, "UNKNOWN Type: L%d", NBBY);
1617 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1618 sizecmd((char *) yystack.l_mark[-1]);
1619 if (yystack.l_mark[-1] != 0)
1620 free((char *) yystack.l_mark[-1]);
1626 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0) {
1628 if (stat((char *) yystack.l_mark[-1], &stbuf) < 0)
1629 perror_reply(550, "%s", (char *) yystack.l_mark[-1]);
1630 else if ((stbuf.st_mode&S_IFMT) != S_IFREG) {
1631 reply(550, "%s: not a plain file.",
1632 (char *) yystack.l_mark[-1]);
1634 register struct tm *t;
1635 t = gmtime(&stbuf.st_mtime);
1637 "%04d%02d%02d%02d%02d%02d",
1639 t->tm_mon+1, t->tm_mday,
1640 t->tm_hour, t->tm_min, t->tm_sec);
1643 if (yystack.l_mark[-1] != 0)
1644 free((char *) yystack.l_mark[-1]);
1650 reply(221, "Goodbye.");
1663 if (yystack.l_mark[-3] && yystack.l_mark[-1]) {
1664 fromname = renamefrom((char *) yystack.l_mark[-1]);
1665 if (fromname == (char *) 0 && yystack.l_mark[-1]) {
1666 free((char *) yystack.l_mark[-1]);
1674 *(const char **)(&(yyval)) = "";
1680 register char *a, *p;
1682 a = (char *)&data_dest.sin_addr;
1683 a[0] = yystack.l_mark[-10]; a[1] = yystack.l_mark[-8]; a[2] = yystack.l_mark[-6]; a[3] = yystack.l_mark[-4];
1684 p = (char *)&data_dest.sin_port;
1685 p[0] = yystack.l_mark[-2]; p[1] = yystack.l_mark[0];
1686 data_dest.sin_family = AF_INET;
1718 cmd_form = yystack.l_mark[0];
1732 cmd_form = yystack.l_mark[0];
1752 cmd_bytesz = yystack.l_mark[0];
1759 cmd_bytesz = yystack.l_mark[0];
1802 * Problem: this production is used for all pathname
1803 * processing, but only gives a 550 error reply.
1804 * This is a valid reply in some cases but not in others.
1806 if (logged_in && yystack.l_mark[0] && strncmp((char *) yystack.l_mark[0], "~", 1) == 0) {
1807 *(char **)&(yyval) = *glob((char *) yystack.l_mark[0]);
1809 reply(550, globerr);
1812 free((char *) yystack.l_mark[0]);
1814 yyval = yystack.l_mark[0];
1820 register int ret, dec, multby, digit;
1823 * Convert a number that was read as decimal number
1824 * to what it would be if it had been read as octal.
1826 dec = yystack.l_mark[0];
1835 ret += digit * multby;
1848 reply(530, "Please login with USER and PASS.");
1853 #line 1852 "/dev/stdout"
1855 yystack.s_mark -= yym;
1856 yystate = *yystack.s_mark;
1857 yystack.l_mark -= yym;
1859 if (yystate == 0 && yym == 0)
1863 printf("%sdebug: after reduction, shifting from state 0 to\
1864 state %d\n", YYPREFIX, YYFINAL);
1867 *++yystack.s_mark = YYFINAL;
1868 *++yystack.l_mark = yyval;
1871 if ((yychar = YYLEX) < 0) yychar = 0;
1875 yys = yyname[YYTRANSLATE(yychar)];
1876 printf("%sdebug: state %d, reading %d (%s)\n",
1877 YYPREFIX, YYFINAL, yychar, yys);
1881 if (yychar == 0) goto yyaccept;
1884 if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1885 yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1886 yystate = yytable[yyn];
1888 yystate = yydgoto[yym];
1891 printf("%sdebug: after reduction, shifting from state %d \
1892 to state %d\n", YYPREFIX, *yystack.s_mark, yystate);
1894 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1898 *++yystack.s_mark = (short) yystate;
1899 *++yystack.l_mark = yyval;
1903 yyerror("yacc stack overflow");
1906 yyfreestack(&yystack);
1910 yyfreestack(&yystack);