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)
20 /* sccsid[] = "@(#)ftpcmd.y 5.20.1.1 (Berkeley) 3/2/89"; */
22 #include <sys/param.h>
23 #include <sys/socket.h>
25 #include <netinet/in.h>
44 static void yyerror(const char *);
47 extern struct sockaddr_in data_dest;
49 extern struct passwd *pw;
56 extern int maxtimeout;
58 extern char hostname[], remotehost[];
59 extern char proctitle[];
61 extern int usedefault;
63 extern char tmpline[];
65 extern char **glob(char *);
66 extern char *renamefrom(char *);
67 extern void cwd(const char *);
69 extern void dologout(int);
70 extern void fatal(const char *);
71 extern void makedir(const char *);
72 extern void nack(const char *);
73 extern void pass(const char *);
74 extern void passive(void);
75 extern void pwd(void);
76 extern void removedir(char *);
77 extern void renamecmd(char *, char *);
78 extern void retrieve(const char *, const char *);
79 extern void send_file_list(const char *);
80 extern void statcmd(void);
81 extern void statfilecmd(const char *);
82 extern void store(char *, const char *, int);
83 extern void user(const char *);
85 extern void perror_reply(int, const char *, ...);
86 extern void reply(int, const char *, ...);
87 extern void lreply(int, const char *, ...);
91 static int cmd_bytesz;
99 short implemented; /* 1 if command is implemented */
103 static char * copy(const char *);
106 static void sizecmd(char *filename);
107 static void help(struct tab *ctab, char *s);
109 struct tab sitetab[];
113 yyerror(const char *msg)
117 #line 117 "/dev/stdout"
123 /* compatibility with bison */
125 /* compatibility with FreeBSD */
126 # ifdef YYPARSE_PARAM_TYPE
127 # define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
129 # define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
132 # define YYPARSE_DECL() yyparse(void)
135 /* Parameters sent to lex. */
137 # define YYLEX_DECL() yylex(void *YYLEX_PARAM)
138 # define YYLEX yylex(YYLEX_PARAM)
140 # define YYLEX_DECL() yylex(void)
141 # define YYLEX yylex()
144 /* Parameters sent to yyerror. */
146 #define YYERROR_DECL() yyerror(const char *s)
149 #define YYERROR_CALL(msg) yyerror(msg)
152 extern int YYPARSE_DECL();
217 #define YYERRCODE 256
218 static const short yylhs[] = { -1,
219 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
220 1, 1, 1, 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, 2, 3, 4, 4,
224 12, 5, 13, 13, 13, 6, 6, 6, 6, 6,
225 6, 6, 6, 7, 7, 7, 8, 8, 8, 10,
228 static const short yylen[] = { 2,
229 0, 2, 2, 4, 4, 4, 2, 4, 4, 4,
230 4, 8, 5, 5, 5, 3, 5, 3, 5, 5,
231 2, 5, 4, 2, 3, 5, 2, 4, 2, 5,
232 5, 3, 3, 4, 6, 5, 7, 9, 4, 6,
233 5, 2, 5, 5, 2, 2, 5, 1, 0, 1,
234 1, 11, 1, 1, 1, 1, 3, 1, 3, 1,
235 1, 3, 2, 1, 1, 1, 1, 1, 1, 1,
238 static const short yydefred[] = { 1,
239 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
240 73, 73, 73, 0, 73, 0, 0, 73, 73, 73,
241 73, 0, 0, 0, 0, 73, 73, 73, 73, 73,
242 0, 73, 73, 2, 3, 46, 0, 0, 45, 0,
243 7, 0, 0, 0, 0, 0, 0, 0, 0, 0,
244 24, 0, 0, 0, 0, 0, 21, 0, 0, 27,
245 29, 0, 0, 0, 0, 0, 42, 0, 0, 48,
246 0, 50, 0, 0, 0, 0, 0, 60, 0, 0,
247 64, 66, 65, 0, 68, 69, 67, 0, 0, 0,
248 0, 0, 0, 71, 0, 70, 0, 0, 25, 0,
249 18, 0, 16, 0, 73, 0, 73, 0, 0, 0,
250 0, 32, 33, 0, 0, 0, 4, 5, 0, 6,
251 0, 0, 0, 51, 63, 8, 9, 10, 0, 0,
252 0, 0, 11, 0, 23, 0, 0, 0, 0, 0,
253 34, 0, 0, 39, 0, 0, 28, 0, 0, 0,
254 0, 0, 0, 55, 53, 54, 57, 59, 62, 13,
255 14, 15, 0, 47, 22, 26, 19, 17, 0, 0,
256 36, 0, 0, 20, 30, 31, 41, 43, 44, 0,
257 0, 35, 72, 0, 40, 0, 0, 0, 37, 0,
258 0, 12, 0, 0, 38, 0, 0, 0, 52,
260 static const short yydgoto[] = { 1,
261 34, 35, 71, 73, 75, 80, 84, 88, 45, 95,
264 static const short yysindex[] = { 0,
265 -224, -247, -239, -236, -232, -222, -204, -200, -181, -177,
266 0, 0, 0, -166, 0, -161, -199, 0, 0, 0,
267 0, -160, -159, -264, -158, 0, 0, 0, 0, 0,
268 -157, 0, 0, 0, 0, 0, -167, -162, 0, -156,
269 0, -250, -198, -165, -155, -154, -153, -151, -150, -152,
270 0, -145, -252, -229, -217, -302, 0, -144, -146, 0,
271 0, -142, -141, -140, -139, -137, 0, -136, -135, 0,
272 -134, 0, -133, -132, -130, -131, -128, 0, -249, -127,
273 0, 0, 0, -126, 0, 0, 0, -125, -152, -152,
274 -152, -205, -152, 0, -124, 0, -152, -152, 0, -152,
275 0, -143, 0, -173, 0, -171, 0, -152, -123, -152,
276 -152, 0, 0, -152, -152, -152, 0, 0, -138, 0,
277 -164, -164, -122, 0, 0, 0, 0, 0, -121, -120,
278 -118, -148, 0, -117, 0, -116, -115, -114, -113, -112,
279 0, -163, -111, 0, -110, -109, 0, -107, -106, -105,
280 -104, -103, -129, 0, 0, 0, 0, 0, 0, 0,
281 0, 0, -101, 0, 0, 0, 0, 0, -100, -102,
282 0, -98, -102, 0, 0, 0, 0, 0, 0, -99,
283 -97, 0, 0, -95, 0, -96, -94, -92, 0, -152,
284 -93, 0, -91, -90, 0, -88, -87, -86, 0,
286 static const short yyrindex[] = { 0,
287 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
288 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
289 0, 0, -83, 0, 0, 0, 0, 0, 0, 0,
290 0, 0, 0, 0, 0, 0, 0, -82, 0, 0,
291 0, 0, 0, 0, 0, 0, 0, 0, 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, -81, -80, 0, -158, 0,
295 0, 0, 0, 0, 0, 0, 0, 0, 0, 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,
308 static const short yygindex[] = { 0,
309 0, 0, 0, 0, 0, 0, 0, 0, 16, -89,
312 #define YYTABLESIZE 190
313 static const short yytable[] = { 129,
314 130, 131, 104, 134, 59, 60, 76, 136, 137, 77,
315 138, 78, 79, 105, 106, 107, 98, 99, 146, 123,
316 148, 149, 36, 124, 150, 151, 152, 46, 47, 37,
317 49, 2, 38, 52, 53, 54, 55, 39, 58, 100,
318 101, 62, 63, 64, 65, 66, 40, 68, 69, 3,
319 4, 102, 103, 5, 6, 7, 8, 9, 10, 11,
320 12, 13, 81, 132, 133, 41, 82, 83, 42, 14,
321 51, 15, 16, 17, 18, 19, 20, 21, 22, 23,
322 24, 25, 26, 27, 28, 29, 30, 43, 31, 32,
323 33, 44, 85, 86, 154, 140, 141, 143, 144, 155,
324 193, 87, 48, 156, 70, 170, 171, 50, 56, 72,
325 57, 61, 67, 89, 90, 91, 74, 163, 93, 94,
326 142, 92, 145, 97, 108, 109, 110, 111, 139, 112,
327 113, 114, 115, 116, 153, 117, 118, 121, 119, 120,
328 122, 180, 126, 127, 128, 135, 147, 186, 160, 161,
329 124, 162, 164, 165, 166, 167, 168, 159, 173, 169,
330 174, 172, 175, 176, 177, 178, 179, 181, 158, 182,
331 183, 185, 190, 187, 189, 188, 191, 192, 195, 194,
332 196, 0, 0, 198, 197, 73, 199, 49, 56, 58,
334 static const short yycheck[] = { 89,
335 90, 91, 305, 93, 269, 270, 257, 97, 98, 260,
336 100, 262, 263, 316, 317, 318, 269, 270, 108, 269,
337 110, 111, 270, 273, 114, 115, 116, 12, 13, 269,
338 15, 256, 269, 18, 19, 20, 21, 270, 23, 269,
339 270, 26, 27, 28, 29, 30, 269, 32, 33, 274,
340 275, 269, 270, 278, 279, 280, 281, 282, 283, 284,
341 285, 286, 261, 269, 270, 270, 265, 266, 269, 294,
342 270, 296, 297, 298, 299, 300, 301, 302, 303, 304,
343 305, 306, 307, 308, 309, 310, 311, 269, 313, 314,
344 315, 269, 258, 259, 259, 269, 270, 269, 270, 264,
345 190, 267, 269, 268, 272, 269, 270, 269, 269, 272,
346 270, 270, 270, 269, 269, 269, 273, 266, 269, 272,
347 105, 273, 107, 269, 269, 272, 269, 269, 272, 270,
348 270, 269, 269, 269, 273, 270, 270, 269, 271, 270,
349 269, 271, 270, 270, 270, 270, 270, 173, 270, 270,
350 273, 270, 270, 270, 270, 270, 270, 123, 269, 272,
351 270, 273, 270, 270, 270, 270, 270, 269, 122, 270,
352 273, 270, 269, 273, 270, 273, 271, 270, 270, 273,
353 271, -1, -1, 271, 273, 269, 273, 270, 270, 270,
359 #define YYMAXTOKEN 319
361 static const char *yyname[] = {
363 "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,
364 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
365 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,"A","B","C","E","F","I","L","N",
370 "P","R","S","T","SP","CRLF","COMMA","STRING","NUMBER","USER","PASS","ACCT",
371 "REIN","QUIT","PORT","PASV","TYPE","STRU","MODE","RETR","STOR","APPE","MLFL",
372 "MAIL","MSND","MSOM","MSAM","MRSQ","MRCP","ALLO","REST","RNFR","RNTO","ABOR",
373 "DELE","CWD","LIST","NLST","SITE","STAT","HELP","NOOP","MKD","RMD","PWD","CDUP",
374 "STOU","SMNT","SYST","SIZE","MDTM","UMASK","IDLE","CHMOD","LEXERR",
376 static const char *yyrule[] = {
377 "$accept : cmd_list",
379 "cmd_list : cmd_list cmd",
380 "cmd_list : cmd_list rcmd",
381 "cmd : USER SP username CRLF",
382 "cmd : PASS SP password CRLF",
383 "cmd : PORT SP host_port CRLF",
385 "cmd : TYPE SP type_code CRLF",
386 "cmd : STRU SP struct_code CRLF",
387 "cmd : MODE SP mode_code CRLF",
388 "cmd : ALLO SP NUMBER CRLF",
389 "cmd : ALLO SP NUMBER SP R SP NUMBER CRLF",
390 "cmd : RETR check_login SP pathname CRLF",
391 "cmd : STOR check_login SP pathname CRLF",
392 "cmd : APPE check_login SP pathname CRLF",
393 "cmd : NLST check_login CRLF",
394 "cmd : NLST check_login SP STRING CRLF",
395 "cmd : LIST check_login CRLF",
396 "cmd : LIST check_login SP pathname CRLF",
397 "cmd : STAT check_login SP pathname CRLF",
399 "cmd : DELE check_login SP pathname CRLF",
400 "cmd : RNTO SP pathname CRLF",
402 "cmd : CWD check_login CRLF",
403 "cmd : CWD check_login SP pathname CRLF",
405 "cmd : HELP SP STRING CRLF",
407 "cmd : MKD check_login SP pathname CRLF",
408 "cmd : RMD check_login SP pathname CRLF",
409 "cmd : PWD check_login CRLF",
410 "cmd : CDUP check_login CRLF",
411 "cmd : SITE SP HELP CRLF",
412 "cmd : SITE SP HELP SP STRING CRLF",
413 "cmd : SITE SP UMASK check_login CRLF",
414 "cmd : SITE SP UMASK check_login SP octal_number CRLF",
415 "cmd : SITE SP CHMOD check_login SP octal_number SP pathname CRLF",
416 "cmd : SITE SP IDLE CRLF",
417 "cmd : SITE SP IDLE SP NUMBER CRLF",
418 "cmd : STOU check_login SP pathname CRLF",
420 "cmd : SIZE check_login SP pathname CRLF",
421 "cmd : MDTM check_login SP pathname CRLF",
424 "rcmd : RNFR check_login SP pathname CRLF",
428 "byte_size : NUMBER",
429 "host_port : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER",
434 "type_code : A SP form_code",
436 "type_code : E SP form_code",
439 "type_code : L SP byte_size",
440 "type_code : L byte_size",
447 "pathname : pathstring",
448 "pathstring : STRING",
449 "octal_number : NUMBER",
463 /* define the initial stack-sizes */
466 #define YYMAXDEPTH YYSTACKSIZE
469 #define YYSTACKSIZE YYMAXDEPTH
471 #define YYSTACKSIZE 500
472 #define YYMAXDEPTH 500
476 #define YYINITSTACKSIZE 500
486 /* variables for the parser stack */
487 static YYSTACKDATA yystack;
491 extern int YYLEX_DECL();
494 extern jmp_buf errcatch;
496 static void upper(char *);
498 #define CMD 0 /* beginning of command */
499 #define ARGS 1 /* expect miscellaneous arguments */
500 #define STR1 2 /* expect SP followed by STRING */
501 #define STR2 3 /* expect STRING */
502 #define OSTR 4 /* optional SP then STRING */
503 #define ZSTR1 5 /* SP then optional STRING */
504 #define ZSTR2 6 /* optional STRING after SP */
505 #define SITECMD 7 /* SITE command */
506 #define NSTR 8 /* Number followed by a string */
508 struct tab cmdtab[] = { /* In order defined in RFC 765 */
509 { "USER", USER, STR1, 1, "<sp> username" },
510 { "PASS", PASS, ZSTR1, 1, "<sp> password" },
511 { "ACCT", ACCT, STR1, 0, "(specify account)" },
512 { "SMNT", SMNT, ARGS, 0, "(structure mount)" },
513 { "REIN", REIN, ARGS, 0, "(reinitialize server state)" },
514 { "QUIT", QUIT, ARGS, 1, "(terminate service)", },
515 { "PORT", PORT, ARGS, 1, "<sp> b0, b1, b2, b3, b4" },
516 { "PASV", PASV, ARGS, 1, "(set server in passive mode)" },
517 { "TYPE", TYPE, ARGS, 1, "<sp> [ A | E | I | L ]" },
518 { "STRU", STRU, ARGS, 1, "(specify file structure)" },
519 { "MODE", MODE, ARGS, 1, "(specify transfer mode)" },
520 { "RETR", RETR, STR1, 1, "<sp> file-name" },
521 { "STOR", STOR, STR1, 1, "<sp> file-name" },
522 { "APPE", APPE, STR1, 1, "<sp> file-name" },
523 { "MLFL", MLFL, OSTR, 0, "(mail file)" },
524 { "MAIL", MAIL, OSTR, 0, "(mail to user)" },
525 { "MSND", MSND, OSTR, 0, "(mail send to terminal)" },
526 { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" },
527 { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" },
528 { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" },
529 { "MRCP", MRCP, STR1, 0, "(mail recipient)" },
530 { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" },
531 { "REST", REST, ARGS, 0, "(restart command)" },
532 { "RNFR", RNFR, STR1, 1, "<sp> file-name" },
533 { "RNTO", RNTO, STR1, 1, "<sp> file-name" },
534 { "ABOR", ABOR, ARGS, 1, "(abort operation)" },
535 { "DELE", DELE, STR1, 1, "<sp> file-name" },
536 { "CWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
537 { "XCWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
538 { "LIST", LIST, OSTR, 1, "[ <sp> path-name ]" },
539 { "NLST", NLST, OSTR, 1, "[ <sp> path-name ]" },
540 { "SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]" },
541 { "SYST", SYST, ARGS, 1, "(get type of operating system)" },
542 { "STAT", STAT, OSTR, 1, "[ <sp> path-name ]" },
543 { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
544 { "NOOP", NOOP, ARGS, 1, "" },
545 { "MKD", MKD, STR1, 1, "<sp> path-name" },
546 { "XMKD", MKD, STR1, 1, "<sp> path-name" },
547 { "RMD", RMD, STR1, 1, "<sp> path-name" },
548 { "XRMD", RMD, STR1, 1, "<sp> path-name" },
549 { "PWD", PWD, ARGS, 1, "(return current directory)" },
550 { "XPWD", PWD, ARGS, 1, "(return current directory)" },
551 { "CDUP", CDUP, ARGS, 1, "(change to parent directory)" },
552 { "XCUP", CDUP, ARGS, 1, "(change to parent directory)" },
553 { "STOU", STOU, STR1, 1, "<sp> file-name" },
554 { "SIZE", SIZE, OSTR, 1, "<sp> path-name" },
555 { "MDTM", MDTM, OSTR, 1, "<sp> path-name" },
559 struct tab sitetab[] = {
560 { "UMASK", UMASK, ARGS, 1, "[ <sp> umask ]" },
561 { "IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]" },
562 { "CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name" },
563 { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
568 lookup(struct tab *p, char *cmd)
571 for (; p->name != 0; p++)
572 if (strcmp(cmd, p->name) == 0)
577 #include <arpa/telnet.h>
580 * get_line - a hacked up version of fgets to ignore TELNET escape codes.
583 get_line(char *s, int n, FILE *iop)
589 /* tmpline may contain saved command from urgent mode interruption */
590 for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) {
592 if (tmpline[c] == '\n') {
595 syslog(LOG_DEBUG, "command: %s", s);
602 while ((c = getc(iop)) != EOF) {
605 if ((c = getc(iop)) != EOF) {
611 printf("%c%c%c", IAC, DONT, 0377&c);
612 (void) fflush(stdout);
617 printf("%c%c%c", IAC, WONT, 0377&c);
618 (void) fflush(stdout);
623 continue; /* ignore command */
628 if (--n <= 0 || c == '\n')
631 if (c == EOF && cs == s)
635 syslog(LOG_DEBUG, "command: %s", s);
646 "Timeout (%d seconds): closing control connection.", timeout);
650 "User %s timed out after %d seconds at %s",
651 (pw ? pw -> pw_name : "unknown"), timeout, ctime(&now));
659 static int cpos, state;
660 register char *cp, *cp2;
661 register struct tab *p;
669 (void) signal(SIGALRM, toolong);
670 (void) alarm((unsigned) timeout);
671 if (get_line(cbuf, sizeof(cbuf)-1, stdin) == 0) {
672 reply(221, "You could at least say goodbye.");
677 if (strncasecmp(cbuf, "PASS", 4) != 0)
678 setproctitle("%s: %s", proctitle, cbuf);
679 #endif /* SETPROCTITLE */
680 if ((cp = strchr(cbuf, '\r'))) {
684 if ((cp = strpbrk(cbuf, " \n")))
691 p = lookup(cmdtab, cbuf);
694 if (p->implemented == 0) {
700 *(const char **)(&yylval) = p->name;
706 if (cbuf[cpos] == ' ') {
711 if ((cp2 = strpbrk(cp, " \n")))
716 p = lookup(sitetab, cp);
719 if (p->implemented == 0) {
726 *(const char **)(&yylval) = p->name;
733 if (cbuf[cpos] == '\n') {
742 if (cbuf[cpos] == ' ') {
753 if (cbuf[cpos] == '\n') {
764 * Make sure the string is nonempty and \n terminated.
766 if (n > 1 && cbuf[cpos] == '\n') {
768 *(char **)&yylval = copy(cp);
776 if (cbuf[cpos] == ' ') {
780 if (isdigit(cbuf[cpos])) {
782 while (isdigit(cbuf[++cpos]))
795 if (isdigit(cbuf[cpos])) {
797 while (isdigit(cbuf[++cpos]))
805 switch (cbuf[cpos++]) {
869 fatal("Unknown state in scanner.");
892 p = (char * )malloc(strlen(s) + 1);
894 fatal("Ran out of memory.");
901 help(struct tab *ctab, char *s)
903 register struct tab *c;
904 register int width, NCMDS;
905 const char *help_type;
911 width = 0, NCMDS = 0;
912 for (c = ctab; c->name != 0; c++) {
913 int len = strlen(c->name);
919 width = (width + 8) &~ 7;
921 register int i, j, w;
924 lreply(214, "The following %scommands are recognized %s.",
925 help_type, "(* =>'s unimplemented)");
926 columns = 76 / width;
929 lines = (NCMDS + columns - 1) / columns;
930 for (i = 0; i < lines; i++) {
932 for (j = 0; j < columns; j++) {
933 c = ctab + j * lines + i;
934 assert(c->name != 0);
935 printf("%s%c", c->name,
936 c->implemented ? ' ' : '*');
937 if (c + lines >= &ctab[NCMDS])
939 w = strlen(c->name) + 1;
947 (void) fflush(stdout);
948 reply(214, "Direct comments to ftp-bugs@%s.", hostname);
953 if (c == (struct tab *)0) {
954 reply(502, "Unknown command %s.", s);
958 reply(214, "Syntax: %s%s %s", help_type, c->name, c->help);
960 reply(214, "%s%-*s\t%s; unimplemented.", help_type, width,
965 sizecmd(char *filename)
971 if (stat(filename, &stbuf) < 0 ||
972 (stbuf.st_mode&S_IFMT) != S_IFREG)
973 reply(550, "%s: not a plain file.", filename);
975 #ifdef HAVE_LONG_LONG
976 reply(213, "%llu", (long long) stbuf.st_size);
978 reply(213, "%lu", stbuf.st_size);
983 register int c, count;
985 fin = fopen(filename, "r");
987 perror_reply(550, filename);
990 if (fstat(fileno(fin), &stbuf) < 0 ||
991 (stbuf.st_mode&S_IFMT) != S_IFREG) {
992 reply(550, "%s: not a plain file.", filename);
998 while((c=getc(fin)) != EOF) {
999 if (c == '\n') /* will get expanded to \r\n */
1005 reply(213, "%ld", count);
1008 reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
1011 #line 1011 "/dev/stdout"
1014 #include <stdio.h> /* needed for printf */
1017 #include <stdlib.h> /* needed for malloc, etc */
1018 #include <string.h> /* needed for memset */
1020 /* allocate initial stack or double stack size, up to YYMAXDEPTH */
1021 static int yygrowstack(YYSTACKDATA *data)
1028 if ((newsize = data->stacksize) == 0)
1029 newsize = YYINITSTACKSIZE;
1030 else if (newsize >= YYMAXDEPTH)
1032 else if ((newsize *= 2) > YYMAXDEPTH)
1033 newsize = YYMAXDEPTH;
1035 i = data->s_mark - data->s_base;
1036 newss = (short *)realloc(data->s_base, newsize * sizeof(*newss));
1040 data->s_base = newss;
1041 data->s_mark = newss + i;
1043 newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs));
1047 data->l_base = newvs;
1048 data->l_mark = newvs + i;
1050 data->stacksize = newsize;
1051 data->s_last = data->s_base + newsize - 1;
1055 #if YYPURE || defined(YY_NO_LEAKS)
1056 static void yyfreestack(YYSTACKDATA *data)
1060 memset(data, 0, sizeof(*data));
1063 #define yyfreestack(data) /* nothing */
1066 #define YYABORT goto yyabort
1067 #define YYREJECT goto yyabort
1068 #define YYACCEPT goto yyaccept
1069 #define YYERROR goto yyerrlab
1074 int yym, yyn, yystate;
1078 if ((yys = getenv("YYDEBUG")) != 0)
1081 if (yyn >= '0' && yyn <= '9')
1082 yydebug = yyn - '0';
1092 memset(&yystack, 0, sizeof(yystack));
1095 if (yystack.s_base == NULL && yygrowstack(&yystack)) goto yyoverflow;
1096 yystack.s_mark = yystack.s_base;
1097 yystack.l_mark = yystack.l_base;
1099 *yystack.s_mark = 0;
1102 if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1105 if ((yychar = YYLEX) < 0) yychar = 0;
1110 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1111 if (!yys) yys = "illegal-symbol";
1112 printf("%sdebug: state %d, reading %d (%s)\n",
1113 YYPREFIX, yystate, yychar, yys);
1117 if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1118 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1122 printf("%sdebug: state %d, shifting to state %d\n",
1123 YYPREFIX, yystate, yytable[yyn]);
1125 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1129 yystate = yytable[yyn];
1130 *++yystack.s_mark = yytable[yyn];
1131 *++yystack.l_mark = yylval;
1133 if (yyerrflag > 0) --yyerrflag;
1136 if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1137 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1142 if (yyerrflag) goto yyinrecovery;
1144 yyerror("syntax error");
1157 if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 &&
1158 yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1162 printf("%sdebug: state %d, error recovery shifting\
1163 to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]);
1165 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1169 yystate = yytable[yyn];
1170 *++yystack.s_mark = yytable[yyn];
1171 *++yystack.l_mark = yylval;
1178 printf("%sdebug: error recovery discarding state %d\n",
1179 YYPREFIX, *yystack.s_mark);
1181 if (yystack.s_mark <= yystack.s_base) goto yyabort;
1189 if (yychar == 0) goto yyabort;
1194 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1195 if (!yys) yys = "illegal-symbol";
1196 printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1197 YYPREFIX, yystate, yychar, yys);
1207 printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1208 YYPREFIX, yystate, yyn, yyrule[yyn]);
1212 yyval = yystack.l_mark[1-yym];
1214 memset(&yyval, 0, sizeof yyval);
1220 fromname = (char *) 0;
1226 user((char *) yystack.l_mark[-1]);
1227 free((char *) yystack.l_mark[-1]);
1233 pass((char *) yystack.l_mark[-1]);
1234 free((char *) yystack.l_mark[-1]);
1242 (void) close(pdata);
1245 reply(200, "PORT command successful.");
1260 if (cmd_form == FORM_N) {
1261 reply(200, "Type set to A.");
1265 reply(504, "Form must be N.");
1269 reply(504, "Type E not implemented.");
1273 reply(200, "Type set to I.");
1279 if (cmd_bytesz == 8) {
1281 "Type set to L (byte size 8).");
1284 reply(504, "Byte size must be 8.");
1285 #else /* NBBY == 8 */
1286 UNIMPLEMENTED for NBBY != 8
1287 #endif /* NBBY == 8 */
1294 switch (yystack.l_mark[-1]) {
1297 reply(200, "STRU F ok.");
1301 reply(504, "Unimplemented STRU type.");
1308 switch (yystack.l_mark[-1]) {
1311 reply(200, "MODE S ok.");
1315 reply(502, "Unimplemented MODE type.");
1322 reply(202, "ALLO command ignored.");
1328 reply(202, "ALLO command ignored.");
1334 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1335 retrieve((char *) 0, (char *) yystack.l_mark[-1]);
1336 if (yystack.l_mark[-1] != 0)
1337 free((char *) yystack.l_mark[-1]);
1343 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1344 store((char *) yystack.l_mark[-1], "w", 0);
1345 if (yystack.l_mark[-1] != 0)
1346 free((char *) yystack.l_mark[-1]);
1352 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1353 store((char *) yystack.l_mark[-1], "a", 0);
1354 if (yystack.l_mark[-1] != 0)
1355 free((char *) yystack.l_mark[-1]);
1361 if (yystack.l_mark[-1])
1362 send_file_list(".");
1368 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1369 send_file_list((char *) yystack.l_mark[-1]);
1370 if (yystack.l_mark[-1] != 0)
1371 free((char *) yystack.l_mark[-1]);
1377 if (yystack.l_mark[-1])
1378 retrieve("/bin/ls -lgA", "");
1384 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1385 retrieve("/bin/ls -lgA %s", (char *) yystack.l_mark[-1]);
1386 if (yystack.l_mark[-1] != 0)
1387 free((char *) yystack.l_mark[-1]);
1393 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1394 statfilecmd((char *) yystack.l_mark[-1]);
1395 if (yystack.l_mark[-1] != 0)
1396 free((char *) yystack.l_mark[-1]);
1408 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1409 remove((char *) yystack.l_mark[-1]);
1410 if (yystack.l_mark[-1] != 0)
1411 free((char *) yystack.l_mark[-1]);
1418 renamecmd(fromname, (char *) yystack.l_mark[-1]);
1420 fromname = (char *) 0;
1422 reply(503, "Bad sequence of commands.");
1424 free((char *) yystack.l_mark[-1]);
1430 reply(225, "ABOR command successful.");
1436 if (yystack.l_mark[-1])
1443 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1444 cwd((char *) yystack.l_mark[-1]);
1445 if (yystack.l_mark[-1] != 0)
1446 free((char *) yystack.l_mark[-1]);
1452 help(cmdtab, (char *) 0);
1458 register char *cp = (char *)yystack.l_mark[-1];
1460 if (strncasecmp(cp, "SITE", 4) == 0) {
1461 cp = (char *)yystack.l_mark[-1] + 4;
1467 help(sitetab, (char *) 0);
1469 help(cmdtab, (char *) yystack.l_mark[-1]);
1475 reply(200, "NOOP command successful.");
1481 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1482 makedir((char *) yystack.l_mark[-1]);
1483 if (yystack.l_mark[-1] != 0)
1484 free((char *) yystack.l_mark[-1]);
1490 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1491 removedir((char *) yystack.l_mark[-1]);
1492 if (yystack.l_mark[-1] != 0)
1493 free((char *) yystack.l_mark[-1]);
1499 if (yystack.l_mark[-1])
1506 if (yystack.l_mark[-1])
1513 help(sitetab, (char *) 0);
1519 help(sitetab, (char *) yystack.l_mark[-1]);
1527 if (yystack.l_mark[-1]) {
1529 (void) umask(oldmask);
1530 reply(200, "Current UMASK is %03o", oldmask);
1539 if (yystack.l_mark[-3]) {
1540 if ((yystack.l_mark[-1] == -1) || (yystack.l_mark[-1] > 0777)) {
1541 reply(501, "Bad UMASK value");
1543 oldmask = umask(yystack.l_mark[-1]);
1545 "UMASK set to %03o (was %03o)",
1546 yystack.l_mark[-1], oldmask);
1554 if (yystack.l_mark[-5] && (yystack.l_mark[-1] != 0)) {
1555 if (yystack.l_mark[-3] > 0777)
1557 "CHMOD: Mode value must be between 0 and 0777");
1558 else if (chmod((char *) yystack.l_mark[-1], yystack.l_mark[-3]) < 0)
1559 perror_reply(550, (char *) yystack.l_mark[-1]);
1561 reply(200, "CHMOD command successful.");
1563 if (yystack.l_mark[-1] != 0)
1564 free((char *) yystack.l_mark[-1]);
1571 "Current IDLE time limit is %d seconds; max %d",
1572 timeout, maxtimeout);
1578 if (yystack.l_mark[-1] < 30 || yystack.l_mark[-1] > maxtimeout) {
1580 "Maximum IDLE time must be between 30 and %d seconds",
1583 timeout = yystack.l_mark[-1];
1584 (void) alarm((unsigned) timeout);
1586 "Maximum IDLE time set to %d seconds",
1594 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1595 store((char *) yystack.l_mark[-1], "w", 1);
1596 if (yystack.l_mark[-1] != 0)
1597 free((char *) yystack.l_mark[-1]);
1605 reply(215, "UNIX Type: L%d Version: BSD-%d",
1608 reply(215, "UNIX Type: L%d", NBBY);
1611 reply(215, "UNKNOWN Type: L%d", NBBY);
1618 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0)
1619 sizecmd((char *) yystack.l_mark[-1]);
1620 if (yystack.l_mark[-1] != 0)
1621 free((char *) yystack.l_mark[-1]);
1627 if (yystack.l_mark[-3] && yystack.l_mark[-1] != 0) {
1629 if (stat((char *) yystack.l_mark[-1], &stbuf) < 0)
1630 perror_reply(550, "%s", (char *) yystack.l_mark[-1]);
1631 else if ((stbuf.st_mode&S_IFMT) != S_IFREG) {
1632 reply(550, "%s: not a plain file.",
1633 (char *) yystack.l_mark[-1]);
1635 register struct tm *t;
1636 t = gmtime(&stbuf.st_mtime);
1638 "%04d%02d%02d%02d%02d%02d",
1640 t->tm_mon+1, t->tm_mday,
1641 t->tm_hour, t->tm_min, t->tm_sec);
1644 if (yystack.l_mark[-1] != 0)
1645 free((char *) yystack.l_mark[-1]);
1651 reply(221, "Goodbye.");
1664 if (yystack.l_mark[-3] && yystack.l_mark[-1]) {
1665 fromname = renamefrom((char *) yystack.l_mark[-1]);
1666 if (fromname == (char *) 0 && yystack.l_mark[-1]) {
1667 free((char *) yystack.l_mark[-1]);
1675 *(const char **)(&(yyval)) = "";
1681 register char *a, *p;
1683 a = (char *)&data_dest.sin_addr;
1684 a[0] = yystack.l_mark[-10]; a[1] = yystack.l_mark[-8]; a[2] = yystack.l_mark[-6]; a[3] = yystack.l_mark[-4];
1685 p = (char *)&data_dest.sin_port;
1686 p[0] = yystack.l_mark[-2]; p[1] = yystack.l_mark[0];
1687 data_dest.sin_family = AF_INET;
1719 cmd_form = yystack.l_mark[0];
1733 cmd_form = yystack.l_mark[0];
1753 cmd_bytesz = yystack.l_mark[0];
1760 cmd_bytesz = yystack.l_mark[0];
1803 * Problem: this production is used for all pathname
1804 * processing, but only gives a 550 error reply.
1805 * This is a valid reply in some cases but not in others.
1807 if (logged_in && yystack.l_mark[0] && strncmp((char *) yystack.l_mark[0], "~", 1) == 0) {
1808 *(char **)&(yyval) = *glob((char *) yystack.l_mark[0]);
1810 reply(550, globerr);
1813 free((char *) yystack.l_mark[0]);
1815 yyval = yystack.l_mark[0];
1821 register int ret, dec, multby, digit;
1824 * Convert a number that was read as decimal number
1825 * to what it would be if it had been read as octal.
1827 dec = yystack.l_mark[0];
1836 ret += digit * multby;
1849 reply(530, "Please login with USER and PASS.");
1854 #line 1854 "/dev/stdout"
1856 yystack.s_mark -= yym;
1857 yystate = *yystack.s_mark;
1858 yystack.l_mark -= yym;
1860 if (yystate == 0 && yym == 0)
1864 printf("%sdebug: after reduction, shifting from state 0 to\
1865 state %d\n", YYPREFIX, YYFINAL);
1868 *++yystack.s_mark = YYFINAL;
1869 *++yystack.l_mark = yyval;
1872 if ((yychar = YYLEX) < 0) yychar = 0;
1877 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1878 if (!yys) yys = "illegal-symbol";
1879 printf("%sdebug: state %d, reading %d (%s)\n",
1880 YYPREFIX, YYFINAL, yychar, yys);
1884 if (yychar == 0) goto yyaccept;
1887 if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1888 yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1889 yystate = yytable[yyn];
1891 yystate = yydgoto[yym];
1894 printf("%sdebug: after reduction, shifting from state %d \
1895 to state %d\n", YYPREFIX, *yystack.s_mark, yystate);
1897 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1901 *++yystack.s_mark = (short) yystate;
1902 *++yystack.l_mark = yyval;
1906 yyerror("yacc stack overflow");
1909 yyfreestack(&yystack);
1913 yyfreestack(&yystack);