2 /* A Bison parser, made from ftpcmd.y
3 by GNU Bison version 1.28 */
5 #define YYBISON 1 /* Identify Bison output. */
75 static char sccsid[] = "@(#)ftpcmd.y 8.3 (Berkeley) 4/6/94";
82 #include <sys/types.h>
83 #include <sys/param.h>
84 #include <sys/socket.h>
87 #include <netinet/in.h>
99 #ifdef TIME_WITH_SYS_TIME
100 # include <sys/time.h>
103 # ifdef HAVE_SYS_TIME_H
104 # include <sys/time.h>
111 #ifdef HAVE_SYS_UTSNAME_H
112 #include <sys/utsname.h>
114 /* Include glob.h last, because it may define "const" which breaks
115 system headers on some platforms. */
120 #if ! defined (NBBY) && defined (CHAR_BIT)
121 #define NBBY CHAR_BIT
126 static char cbuf[512]; /* Command Buffer. */
127 static char *fromname;
130 static int cmd_bytesz;
137 short implemented; /* 1 if command is implemented */
141 extern struct tab cmdtab[];
142 extern struct tab sitetab[];
143 static char *copy __P ((char *));
144 static void help __P ((struct tab *, char *));
145 static struct tab *lookup __P ((struct tab *, char *));
146 static void sizecmd __P ((char *));
147 static int yylex __P ((void));
148 static void yyerror __P ((const char *s));
167 #define YYFLAG -32768
170 #define YYTRANSLATE(x) ((unsigned)(x) <= 319 ? yytranslate[x] : 81)
172 static const char yytranslate[] = { 0,
173 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
174 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
175 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
176 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
177 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
178 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
179 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
180 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
181 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
182 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
183 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
184 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
185 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
186 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
187 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
188 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
189 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
190 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
191 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
192 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
193 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
194 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
195 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
196 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
197 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
198 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
199 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
200 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
201 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
202 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
203 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
204 57, 58, 59, 60, 61, 62, 63, 64, 65
208 static const short yyprhs[] = { 0,
209 0, 1, 4, 7, 12, 17, 23, 27, 32, 37,
210 42, 47, 56, 62, 68, 74, 78, 84, 88, 94,
211 100, 103, 109, 115, 118, 122, 128, 131, 136, 139,
212 145, 151, 155, 159, 164, 171, 177, 185, 195, 200,
213 208, 214, 217, 223, 229, 232, 235, 241, 246, 248,
214 249, 251, 253, 265, 267, 269, 271, 273, 277, 279,
215 283, 285, 287, 291, 294, 296, 298, 300, 302, 304,
219 static const short yyrhs[] = { -1,
220 66, 67, 0, 66, 68, 0, 18, 15, 69, 16,
221 0, 19, 15, 70, 16, 0, 23, 80, 15, 72,
222 16, 0, 24, 80, 16, 0, 25, 15, 74, 16,
223 0, 26, 15, 75, 16, 0, 27, 15, 76, 16,
224 0, 38, 15, 65, 16, 0, 38, 15, 65, 15,
225 12, 15, 65, 16, 0, 28, 80, 15, 77, 16,
226 0, 29, 80, 15, 77, 16, 0, 30, 80, 15,
227 77, 16, 0, 46, 80, 16, 0, 46, 80, 15,
228 64, 16, 0, 45, 80, 16, 0, 45, 80, 15,
229 77, 16, 0, 48, 80, 15, 77, 16, 0, 48,
230 16, 0, 43, 80, 15, 77, 16, 0, 41, 80,
231 15, 77, 16, 0, 42, 16, 0, 44, 80, 16,
232 0, 44, 80, 15, 77, 16, 0, 49, 16, 0,
233 49, 15, 64, 16, 0, 50, 16, 0, 51, 80,
234 15, 77, 16, 0, 52, 80, 15, 77, 16, 0,
235 53, 80, 16, 0, 54, 80, 16, 0, 47, 15,
236 49, 16, 0, 47, 15, 49, 15, 64, 16, 0,
237 47, 15, 60, 80, 16, 0, 47, 15, 60, 80,
238 15, 79, 16, 0, 47, 15, 62, 80, 15, 79,
239 15, 77, 16, 0, 47, 15, 61, 16, 0, 47,
240 15, 80, 61, 15, 65, 16, 0, 55, 80, 15,
241 77, 16, 0, 57, 16, 0, 58, 80, 15, 77,
242 16, 0, 59, 80, 15, 77, 16, 0, 22, 16,
243 0, 1, 16, 0, 40, 80, 15, 77, 16, 0,
244 39, 15, 71, 16, 0, 64, 0, 0, 64, 0,
245 65, 0, 65, 17, 65, 17, 65, 17, 65, 17,
246 65, 17, 65, 0, 10, 0, 14, 0, 5, 0,
247 3, 0, 3, 15, 73, 0, 6, 0, 6, 15,
248 73, 0, 8, 0, 9, 0, 9, 15, 71, 0,
249 9, 71, 0, 7, 0, 12, 0, 11, 0, 13,
250 0, 4, 0, 5, 0, 78, 0, 64, 0, 65,
257 static const short yyrline[] = { 0,
258 152, 153, 160, 164, 169, 175, 197, 202, 237, 249,
259 261, 265, 269, 276, 283, 290, 295, 302, 307, 314,
260 321, 325, 332, 345, 349, 354, 361, 365, 382, 386,
261 393, 400, 405, 410, 414, 420, 430, 445, 459, 465,
262 481, 488, 534, 551, 573, 578, 584, 595, 610, 614,
263 618, 622, 626, 640, 644, 648, 655, 660, 665, 670,
264 675, 679, 684, 690, 698, 702, 706, 713, 717, 721,
270 #if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
272 static const char * const yytname[] = { "$","error","$undefined.","A","B",
273 "C","E","F","I","L","N","P","R","S","T","SP","CRLF","COMMA","USER","PASS","ACCT",
274 "REIN","QUIT","PORT","PASV","TYPE","STRU","MODE","RETR","STOR","APPE","MLFL",
275 "MAIL","MSND","MSOM","MSAM","MRSQ","MRCP","ALLO","REST","RNFR","RNTO","ABOR",
276 "DELE","CWD","LIST","NLST","SITE","STAT","HELP","NOOP","MKD","RMD","PWD","CDUP",
277 "STOU","SMNT","SYST","SIZE","MDTM","UMASK","IDLE","CHMOD","LEXERR","STRING",
278 "NUMBER","cmd_list","cmd","rcmd","username","password","byte_size","host_port",
279 "form_code","type_code","struct_code","mode_code","pathname","pathstring","octal_number",
284 static const short yyr1[] = { 0,
285 66, 66, 66, 67, 67, 67, 67, 67, 67, 67,
286 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
287 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
288 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
289 67, 67, 67, 67, 67, 67, 68, 68, 69, 70,
290 70, 71, 72, 73, 73, 73, 74, 74, 74, 74,
291 74, 74, 74, 74, 75, 75, 75, 76, 76, 76,
295 static const short yyr2[] = { 0,
296 0, 2, 2, 4, 4, 5, 3, 4, 4, 4,
297 4, 8, 5, 5, 5, 3, 5, 3, 5, 5,
298 2, 5, 5, 2, 3, 5, 2, 4, 2, 5,
299 5, 3, 3, 4, 6, 5, 7, 9, 4, 7,
300 5, 2, 5, 5, 2, 2, 5, 4, 1, 0,
301 1, 1, 11, 1, 1, 1, 1, 3, 1, 3,
302 1, 1, 3, 2, 1, 1, 1, 1, 1, 1,
306 static const short yydefact[] = { 1,
307 0, 0, 0, 0, 0, 74, 74, 0, 0, 0,
308 74, 74, 74, 0, 0, 74, 74, 0, 74, 74,
309 74, 74, 0, 74, 0, 0, 74, 74, 74, 74,
310 74, 0, 74, 74, 2, 3, 46, 0, 50, 45,
311 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
312 0, 0, 24, 0, 0, 0, 0, 0, 21, 0,
313 0, 27, 29, 0, 0, 0, 0, 0, 42, 0,
314 0, 49, 0, 51, 0, 0, 7, 57, 59, 61,
315 62, 0, 65, 67, 66, 0, 69, 70, 68, 0,
316 0, 0, 0, 0, 52, 0, 0, 0, 0, 0,
317 25, 0, 18, 0, 16, 0, 74, 0, 74, 0,
318 0, 0, 0, 0, 32, 33, 0, 0, 0, 4,
319 5, 0, 0, 0, 0, 0, 64, 8, 9, 10,
320 72, 0, 71, 0, 0, 0, 11, 48, 0, 0,
321 0, 0, 0, 0, 0, 34, 0, 39, 0, 0,
322 0, 28, 0, 0, 0, 0, 0, 0, 6, 56,
323 54, 55, 58, 60, 63, 13, 14, 15, 0, 47,
324 23, 22, 26, 19, 17, 0, 0, 36, 0, 0,
325 20, 30, 31, 41, 43, 44, 0, 0, 35, 73,
326 0, 0, 0, 0, 0, 37, 0, 40, 0, 12,
327 0, 0, 38, 0, 0, 0, 0, 53, 0, 0
330 static const short yydefgoto[] = { 1,
331 35, 36, 73, 75, 96, 123, 163, 82, 86, 90,
335 static const short yypact[] = {-32768,
336 42, -7, 8, 20, 24,-32768,-32768, 44, 59, 62,
337 -32768,-32768,-32768, 83, 89,-32768,-32768, 47,-32768,-32768,
338 -32768,-32768, 97, 98, 16, 99,-32768,-32768,-32768,-32768,
339 -32768, 100,-32768,-32768,-32768,-32768,-32768, 49, 53,-32768,
340 103, 104, 70, 6, 7, 106, 107, 108, 54, 60,
341 112, 113,-32768, 114, 39, 41, 87, -46,-32768, 115,
342 67,-32768,-32768, 117, 118, 119, 120, 122,-32768, 123,
343 124,-32768, 125,-32768, 126, 69,-32768, 128, 129,-32768,
344 -13, 130,-32768,-32768,-32768, 131,-32768,-32768,-32768, 132,
345 76, 76, 76, 91,-32768, 133, 76, 76, 76, 76,
346 -32768, 76,-32768, 81,-32768, 93,-32768, 134,-32768, 90,
347 76, 136, 76, 76,-32768,-32768, 76, 76, 76,-32768,
348 -32768, 137, 139, 48, 48, 60,-32768,-32768,-32768,-32768,
349 -32768, 140,-32768, 141, 142, 147,-32768,-32768, 144, 145,
350 146, 148, 149, 150, 105,-32768, 95,-32768, 138, 152,
351 154,-32768, 155, 156, 157, 158, 159, 111,-32768,-32768,
352 -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 153,-32768,
353 -32768,-32768,-32768,-32768,-32768, 161, 116,-32768, 116, 121,
354 -32768,-32768,-32768,-32768,-32768,-32768, 162, 127,-32768,-32768,
355 164, 163, 166, 135, 167,-32768, 76,-32768, 168,-32768,
356 171, 143,-32768, 172, 151, 173, 160,-32768, 184,-32768
359 static const short yypgoto[] = {-32768,
360 -32768,-32768,-32768,-32768, -77,-32768, 38,-32768,-32768,-32768,
368 static const short yytable[] = { 134,
369 135, 126, 106, 127, 139, 140, 141, 142, 37, 143,
370 87, 88, 83, 107, 108, 109, 84, 85, 151, 89,
371 153, 154, 38, 42, 155, 156, 157, 46, 47, 48,
372 61, 62, 51, 52, 39, 54, 55, 56, 57, 40,
373 60, 209, 2, 64, 65, 66, 67, 68, 165, 70,
374 71, 95, 160, 100, 101, 102, 103, 161, 43, 3,
375 4, 162, 53, 5, 6, 7, 8, 9, 10, 11,
376 12, 13, 78, 44, 110, 79, 45, 80, 81, 14,
377 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
378 25, 26, 27, 28, 29, 30, 31, 49, 32, 33,
379 34, 104, 105, 50, 201, 136, 137, 145, 146, 177,
380 178, 58, 72, 59, 63, 69, 74, 76, 94, 77,
381 91, 92, 93, 147, 95, 149, 97, 98, 99, 111,
382 112, 113, 114, 122, 115, 116, 117, 118, 119, 131,
383 120, 121, 124, 125, 144, 128, 129, 130, 138, 148,
384 150, 152, 179, 158, 159, 166, 167, 168, 169, 170,
385 171, 172, 164, 173, 174, 175, 180, 188, 176, 181,
386 182, 183, 184, 185, 186, 187, 189, 197, 194, 196,
387 190, 198, 200, 210, 202, 193, 203, 192, 205, 207,
388 0, 195, 0, 0, 0, 0, 0, 0, 0, 199,
389 0, 0, 0, 0, 0, 0, 0, 204, 0, 0,
390 0, 0, 0, 0, 0, 206, 0, 0, 0, 0,
394 static const short yycheck[] = { 92,
395 93, 15, 49, 81, 97, 98, 99, 100, 16, 102,
396 4, 5, 7, 60, 61, 62, 11, 12, 111, 13,
397 113, 114, 15, 7, 117, 118, 119, 11, 12, 13,
398 15, 16, 16, 17, 15, 19, 20, 21, 22, 16,
399 24, 0, 1, 27, 28, 29, 30, 31, 126, 33,
400 34, 65, 5, 15, 16, 15, 16, 10, 15, 18,
401 19, 14, 16, 22, 23, 24, 25, 26, 27, 28,
402 29, 30, 3, 15, 58, 6, 15, 8, 9, 38,
403 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
404 49, 50, 51, 52, 53, 54, 55, 15, 57, 58,
405 59, 15, 16, 15, 197, 15, 16, 15, 16, 15,
406 16, 15, 64, 16, 16, 16, 64, 15, 65, 16,
407 15, 15, 15, 107, 65, 109, 15, 15, 15, 15,
408 64, 15, 15, 65, 16, 16, 15, 15, 15, 64,
409 16, 16, 15, 15, 64, 16, 16, 16, 16, 16,
410 61, 16, 15, 17, 16, 16, 16, 16, 12, 16,
411 16, 16, 125, 16, 16, 16, 15, 15, 64, 16,
412 16, 16, 16, 16, 16, 65, 16, 15, 17, 16,
413 65, 16, 16, 0, 17, 65, 16, 179, 17, 17,
414 -1, 65, -1, -1, -1, -1, -1, -1, -1, 65,
415 -1, -1, -1, -1, -1, -1, -1, 65, -1, -1,
416 -1, -1, -1, -1, -1, 65, -1, -1, -1, -1,
419 /* -*-C-*- Note some compilers choke on comments on `#line' lines. */
420 #line 3 "/usr/share/bison/bison.simple"
421 /* This file comes from bison-1.28. */
423 /* Skeleton output parser for bison,
424 Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
426 This program is free software; you can redistribute it and/or modify
427 it under the terms of the GNU General Public License as published by
428 the Free Software Foundation; either version 2, or (at your option)
431 This program is distributed in the hope that it will be useful,
432 but WITHOUT ANY WARRANTY; without even the implied warranty of
433 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
434 GNU General Public License for more details.
436 You should have received a copy of the GNU General Public License
437 along with this program; if not, write to the Free Software
438 Foundation, Inc., 59 Temple Place - Suite 330,
439 Boston, MA 02111-1307, USA. */
441 /* As a special exception, when this file is copied by Bison into a
442 Bison output file, you may use that output file without restriction.
443 This special exception was added by the Free Software Foundation
444 in version 1.24 of Bison. */
446 /* This is the parser code that is written into each bison parser
447 when the %semantic_parser declaration is not specified in the grammar.
448 It was written by Richard Stallman by simplifying the hairy parser
449 used when %semantic_parser is specified. */
451 #ifndef YYSTACK_USE_ALLOCA
453 #define YYSTACK_USE_ALLOCA
454 #else /* alloca not defined */
456 #define YYSTACK_USE_ALLOCA
457 #define alloca __builtin_alloca
458 #else /* not GNU C. */
459 #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
460 #define YYSTACK_USE_ALLOCA
462 #else /* not sparc */
463 /* We think this test detects Watcom and Microsoft C. */
464 /* This used to test MSDOS, but that is a bad idea
465 since that symbol is in the user namespace. */
466 #if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
467 #if 0 /* No need for malloc.h, which pollutes the namespace;
468 instead, just don't use alloca. */
471 #else /* not MSDOS, or __TURBOC__ */
473 /* I don't know what this was needed for, but it pollutes the namespace.
474 So I turned it off. rms, 2 May 1997. */
475 /* #include <malloc.h> */
477 #define YYSTACK_USE_ALLOCA
478 #else /* not MSDOS, or __TURBOC__, or _AIX */
480 #ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
481 and on HPUX 10. Eventually we can turn this on. */
482 #define YYSTACK_USE_ALLOCA
483 #define alloca __builtin_alloca
486 #endif /* not _AIX */
487 #endif /* not MSDOS, or __TURBOC__ */
488 #endif /* not sparc */
489 #endif /* not GNU C */
490 #endif /* alloca not defined */
491 #endif /* YYSTACK_USE_ALLOCA not defined */
493 #ifdef YYSTACK_USE_ALLOCA
494 #define YYSTACK_ALLOC alloca
496 #define YYSTACK_ALLOC malloc
499 /* Note: there must be only one dollar sign in this file.
500 It is replaced by the list of actions, each action
501 as one case of the switch. */
503 #define yyerrok (yyerrstatus = 0)
504 #define yyclearin (yychar = YYEMPTY)
507 #define YYACCEPT goto yyacceptlab
508 #define YYABORT goto yyabortlab
509 #define YYERROR goto yyerrlab1
510 /* Like YYERROR except do call yyerror.
511 This remains here temporarily to ease the
512 transition to the new meaning of YYERROR, for GCC.
513 Once GCC version 2 has supplanted version 1, this can go. */
514 #define YYFAIL goto yyerrlab
515 #define YYRECOVERING() (!!yyerrstatus)
516 #define YYBACKUP(token, value) \
518 if (yychar == YYEMPTY && yylen == 1) \
519 { yychar = (token), yylval = (value); \
520 yychar1 = YYTRANSLATE (yychar); \
525 { yyerror ("syntax error: cannot back up"); YYERROR; } \
529 #define YYERRCODE 256
532 #define YYLEX yylex()
538 #define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
540 #define YYLEX yylex(&yylval, &yylloc)
542 #else /* not YYLSP_NEEDED */
544 #define YYLEX yylex(&yylval, YYLEX_PARAM)
546 #define YYLEX yylex(&yylval)
548 #endif /* not YYLSP_NEEDED */
551 /* If nonreentrant, generate the variables here */
555 int yychar; /* the lookahead symbol */
556 YYSTYPE yylval; /* the semantic value of the */
557 /* lookahead symbol */
560 YYLTYPE yylloc; /* location data for the lookahead */
564 int yynerrs; /* number of parse errors so far */
565 #endif /* not YYPURE */
568 int yydebug; /* nonzero means print parse trace */
569 /* Since this is uninitialized, it does not stop multiple parsers
573 /* YYINITDEPTH indicates the initial size of the parser's stacks */
576 #define YYINITDEPTH 200
579 /* YYMAXDEPTH is the maximum size the stacks can grow to
580 (effective only if the built-in stack extension method is used). */
587 #define YYMAXDEPTH 10000
590 /* Define __yy_memcpy. Note that the size argument
591 should be passed with type unsigned int, because that is what the non-GCC
592 definitions require. With GCC, __builtin_memcpy takes an arg
593 of type size_t, but it can handle unsigned int. */
595 #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
596 #define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
597 #else /* not GNU C or C++ */
600 /* This is the most reliable way to avoid incompatibilities
601 in available built-in functions on various systems. */
603 __yy_memcpy (to, from, count)
608 register char *f = from;
609 register char *t = to;
610 register int i = count;
616 #else /* __cplusplus */
618 /* This is the most reliable way to avoid incompatibilities
619 in available built-in functions on various systems. */
621 __yy_memcpy (char *to, char *from, unsigned int count)
623 register char *t = to;
624 register char *f = from;
625 register int i = count;
634 #line 217 "/usr/share/bison/bison.simple"
636 /* The user can define YYPARSE_PARAM as the name of an argument to be passed
637 into yyparse. The argument should have type void *.
638 It should actually point to an object.
639 Grammar actions can access the variable by casting it
640 to the proper pointer type. */
644 #define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
645 #define YYPARSE_PARAM_DECL
646 #else /* not __cplusplus */
647 #define YYPARSE_PARAM_ARG YYPARSE_PARAM
648 #define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
649 #endif /* not __cplusplus */
650 #else /* not YYPARSE_PARAM */
651 #define YYPARSE_PARAM_ARG
652 #define YYPARSE_PARAM_DECL
653 #endif /* not YYPARSE_PARAM */
655 /* Prevent warning if -Wstrict-prototypes. */
658 int yyparse (void *);
665 yyparse(YYPARSE_PARAM_ARG)
668 register int yystate;
670 register short *yyssp;
671 register YYSTYPE *yyvsp;
672 int yyerrstatus; /* number of tokens to shift before error messages enabled */
673 int yychar1 = 0; /* lookahead token as an internal (translated) token number */
675 short yyssa[YYINITDEPTH]; /* the state stack */
676 YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
678 short *yyss = yyssa; /* refer to the stacks thru separate pointers */
679 YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
682 YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
683 YYLTYPE *yyls = yylsa;
686 #define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
688 #define YYPOPSTACK (yyvsp--, yyssp--)
691 int yystacksize = YYINITDEPTH;
692 int yyfree_stacks = 0;
703 YYSTYPE yyval; /* the variable used to return */
704 /* semantic values from the action */
711 fprintf(stderr, "Starting parse\n");
717 yychar = YYEMPTY; /* Cause a token to be read. */
719 /* Initialize stack pointers.
720 Waste one element of value and location stack
721 so that they stay on the same level as the state stack.
722 The wasted elements are never initialized. */
730 /* Push a new state, which is found in yystate . */
731 /* In all cases, when you get here, the value and location stacks
732 have just been pushed. so pushing a state here evens the stacks. */
737 if (yyssp >= yyss + yystacksize - 1)
739 /* Give user a chance to reallocate the stack */
740 /* Use copies of these so that the &'s don't force the real ones into memory. */
741 YYSTYPE *yyvs1 = yyvs;
744 YYLTYPE *yyls1 = yyls;
747 /* Get the current used size of the three stacks, in elements. */
748 int size = yyssp - yyss + 1;
751 /* Each stack pointer address is followed by the size of
752 the data in use in that stack, in bytes. */
754 /* This used to be a conditional around just the two extra args,
755 but that might be undefined if yyoverflow is a macro. */
756 yyoverflow("parser stack overflow",
757 &yyss1, size * sizeof (*yyssp),
758 &yyvs1, size * sizeof (*yyvsp),
759 &yyls1, size * sizeof (*yylsp),
762 yyoverflow("parser stack overflow",
763 &yyss1, size * sizeof (*yyssp),
764 &yyvs1, size * sizeof (*yyvsp),
768 yyss = yyss1; yyvs = yyvs1;
772 #else /* no yyoverflow */
773 /* Extend the stack our own way. */
774 if (yystacksize >= YYMAXDEPTH)
776 yyerror("parser stack overflow");
788 if (yystacksize > YYMAXDEPTH)
789 yystacksize = YYMAXDEPTH;
790 #ifndef YYSTACK_USE_ALLOCA
793 yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
794 __yy_memcpy ((char *)yyss, (char *)yyss1,
795 size * (unsigned int) sizeof (*yyssp));
796 yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
797 __yy_memcpy ((char *)yyvs, (char *)yyvs1,
798 size * (unsigned int) sizeof (*yyvsp));
800 yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
801 __yy_memcpy ((char *)yyls, (char *)yyls1,
802 size * (unsigned int) sizeof (*yylsp));
804 #endif /* no yyoverflow */
806 yyssp = yyss + size - 1;
807 yyvsp = yyvs + size - 1;
809 yylsp = yyls + size - 1;
814 fprintf(stderr, "Stack size increased to %d\n", yystacksize);
817 if (yyssp >= yyss + yystacksize - 1)
823 fprintf(stderr, "Entering state %d\n", yystate);
829 /* Do appropriate processing given the current state. */
830 /* Read a lookahead token if we need one and don't already have one. */
833 /* First try to decide what to do without reference to lookahead token. */
835 yyn = yypact[yystate];
839 /* Not known => get a lookahead token if don't already have one. */
841 /* yychar is either YYEMPTY or YYEOF
842 or a valid token in external form. */
844 if (yychar == YYEMPTY)
848 fprintf(stderr, "Reading a token: ");
853 /* Convert token to internal form (in yychar1) for indexing tables with */
855 if (yychar <= 0) /* This means end of input. */
858 yychar = YYEOF; /* Don't call YYLEX any more */
862 fprintf(stderr, "Now at end of input.\n");
867 yychar1 = YYTRANSLATE(yychar);
872 fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
873 /* Give the individual parser a way to print the precise meaning
874 of a token, for further debugging info. */
876 YYPRINT (stderr, yychar, yylval);
878 fprintf (stderr, ")\n");
884 if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
889 /* yyn is what to do for this token type in this state.
890 Negative => reduce, -yyn is rule number.
891 Positive => shift, yyn is new state.
892 New state is final state => don't bother to shift,
894 0, or most negative number => error. */
909 /* Shift the lookahead token. */
913 fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
916 /* Discard the token being shifted unless it is eof. */
925 /* count tokens shifted since error; after three, turn off error status. */
926 if (yyerrstatus) yyerrstatus--;
931 /* Do the default action for the current state. */
934 yyn = yydefact[yystate];
938 /* Do a reduction. yyn is the number of a rule to reduce with. */
942 yyval = yyvsp[1-yylen]; /* implement default value of the action */
949 fprintf (stderr, "Reducing via rule %d (line %d), ",
952 /* Print the symbols being reduced, and their result. */
953 for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
954 fprintf (stderr, "%s ", yytname[yyrhs[i]]);
955 fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
965 if (fromname != NULL)
967 fromname = (char *) 0;
968 restart_point = (off_t) 0;
982 memset (yyvsp[-1].s, 0, strlen (yyvsp[-1].s));
995 if (memcmp (&his_addr.sin_addr,
997 sizeof (data_dest.sin_addr)) == 0 &&
998 ntohs (data_dest.sin_port) >
1000 reply (200, "PORT command sucessful.");
1003 memset (&data_dest, 0,
1004 sizeof (data_dest));
1005 reply(500, "Illegal PORT Command");
1011 #line 198 "ftpcmd.y"
1018 #line 203 "ftpcmd.y"
1023 if (cmd_form == FORM_N) {
1024 reply(200, "Type set to A.");
1028 reply(504, "Form must be N.");
1032 reply(504, "Type E not implemented.");
1036 reply(200, "Type set to I.");
1041 #if defined (NBBY) && NBBY == 8
1042 if (cmd_bytesz == 8) {
1044 "Type set to L (byte size 8).");
1047 reply(504, "Byte size must be 8.");
1048 #else /* NBBY == 8 */
1049 UNIMPLEMENTED for NBBY != 8
1050 #endif /* NBBY == 8 */
1055 #line 238 "ftpcmd.y"
1057 switch (yyvsp[-1].i) {
1060 reply(200, "STRU F ok.");
1064 reply(504, "Unimplemented STRU type.");
1069 #line 250 "ftpcmd.y"
1071 switch (yyvsp[-1].i) {
1074 reply(200, "MODE S ok.");
1078 reply(502, "Unimplemented MODE type.");
1083 #line 262 "ftpcmd.y"
1085 reply(202, "ALLO command ignored.");
1089 #line 266 "ftpcmd.y"
1091 reply(202, "ALLO command ignored.");
1095 #line 270 "ftpcmd.y"
1097 if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1098 retrieve((char *) 0, yyvsp[-1].s);
1099 if (yyvsp[-1].s != NULL)
1104 #line 277 "ftpcmd.y"
1106 if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1107 store(yyvsp[-1].s, "w", 0);
1108 if (yyvsp[-1].s != NULL)
1113 #line 284 "ftpcmd.y"
1115 if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1116 store(yyvsp[-1].s, "a", 0);
1117 if (yyvsp[-1].s != NULL)
1122 #line 291 "ftpcmd.y"
1125 send_file_list(".");
1129 #line 296 "ftpcmd.y"
1131 if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1132 send_file_list(yyvsp[-1].s);
1133 if (yyvsp[-1].s != NULL)
1138 #line 303 "ftpcmd.y"
1141 retrieve("/bin/ls -lgA", "");
1145 #line 308 "ftpcmd.y"
1147 if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1148 retrieve("/bin/ls -lgA %s", yyvsp[-1].s);
1149 if (yyvsp[-1].s != NULL)
1154 #line 315 "ftpcmd.y"
1156 if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1157 statfilecmd(yyvsp[-1].s);
1158 if (yyvsp[-1].s != NULL)
1163 #line 322 "ftpcmd.y"
1169 #line 326 "ftpcmd.y"
1171 if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1172 delete(yyvsp[-1].s);
1173 if (yyvsp[-1].s != NULL)
1178 #line 333 "ftpcmd.y"
1182 renamecmd(fromname, yyvsp[-1].s);
1184 fromname = (char *) 0;
1186 reply(503, "Bad sequence of commands.");
1193 #line 346 "ftpcmd.y"
1195 reply(225, "ABOR command successful.");
1199 #line 350 "ftpcmd.y"
1206 #line 355 "ftpcmd.y"
1208 if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1210 if (yyvsp[-1].s != NULL)
1215 #line 362 "ftpcmd.y"
1217 help(cmdtab, (char *) 0);
1221 #line 366 "ftpcmd.y"
1223 char *cp = yyvsp[-1].s;
1225 if (strncasecmp(cp, "SITE", 4) == 0) {
1226 cp = yyvsp[-1].s + 4;
1232 help(sitetab, (char *) 0);
1234 help(cmdtab, yyvsp[-1].s);
1235 if (yyvsp[-1].s != NULL)
1240 #line 383 "ftpcmd.y"
1242 reply(200, "NOOP command successful.");
1246 #line 387 "ftpcmd.y"
1248 if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1249 makedir(yyvsp[-1].s);
1250 if (yyvsp[-1].s != NULL)
1255 #line 394 "ftpcmd.y"
1257 if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1258 removedir(yyvsp[-1].s);
1259 if (yyvsp[-1].s != NULL)
1264 #line 401 "ftpcmd.y"
1271 #line 406 "ftpcmd.y"
1278 #line 411 "ftpcmd.y"
1280 help(sitetab, (char *) 0);
1284 #line 415 "ftpcmd.y"
1286 help(sitetab, yyvsp[-1].s);
1287 if (yyvsp[-1].s != NULL)
1292 #line 421 "ftpcmd.y"
1298 (void) umask(oldmask);
1299 reply(200, "Current UMASK is %03o", oldmask);
1304 #line 431 "ftpcmd.y"
1309 if ((yyvsp[-1].i == -1) || (yyvsp[-1].i > 0777)) {
1310 reply(501, "Bad UMASK value");
1312 oldmask = umask(yyvsp[-1].i);
1314 "UMASK set to %03o (was %03o)",
1315 yyvsp[-1].i, oldmask);
1321 #line 446 "ftpcmd.y"
1323 if (yyvsp[-5].i && (yyvsp[-1].s != NULL)) {
1324 if (yyvsp[-3].i > 0777)
1326 "CHMOD: Mode value must be between 0 and 0777");
1327 else if (chmod(yyvsp[-1].s, yyvsp[-3].i) < 0)
1328 perror_reply(550, yyvsp[-1].s);
1330 reply(200, "CHMOD command successful.");
1332 if (yyvsp[-1].s != NULL)
1337 #line 460 "ftpcmd.y"
1340 "Current IDLE time limit is %d seconds; max %d",
1341 timeout, maxtimeout);
1345 #line 466 "ftpcmd.y"
1348 if (yyvsp[-1].i < 30 || yyvsp[-1].i > maxtimeout) {
1350 "Maximum IDLE time must be between 30 and %d seconds",
1353 timeout = yyvsp[-1].i;
1354 (void) alarm((unsigned) timeout);
1356 "Maximum IDLE time set to %d seconds",
1363 #line 482 "ftpcmd.y"
1365 if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1366 store(yyvsp[-1].s, "w", 1);
1367 if (yyvsp[-1].s != NULL)
1372 #line 489 "ftpcmd.y"
1374 const char *sys_type; /* Official rfc-defined os type. */
1375 char *version = 0; /* A more specific type. */
1379 if (uname (&u) == 0) {
1381 malloc (strlen (u.sysname)
1382 + 1 + strlen (u.release) + 1);
1384 sprintf (version, "%s %s",
1385 u.sysname, u.release);
1396 sys_type = "UNKNOWN";
1400 reply(215, "%s Type: L%d Version: %s",
1401 sys_type, NBBY, version);
1403 reply(215, "%s Type: L%d", sys_type, NBBY);
1412 #line 535 "ftpcmd.y"
1414 if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1415 sizecmd(yyvsp[-1].s);
1416 if (yyvsp[-1].s != NULL)
1421 #line 552 "ftpcmd.y"
1423 if (yyvsp[-3].i && yyvsp[-1].s != NULL) {
1425 if (stat(yyvsp[-1].s, &stbuf) < 0)
1426 reply(550, "%s: %s",
1427 yyvsp[-1].s, strerror(errno));
1428 else if (!S_ISREG(stbuf.st_mode)) {
1429 reply(550, "%s: not a plain file.", yyvsp[-1].s);
1432 t = gmtime(&stbuf.st_mtime);
1434 "%04d%02d%02d%02d%02d%02d",
1435 1900 + t->tm_year, t->tm_mon+1,
1436 t->tm_mday, t->tm_hour, t->tm_min,
1440 if (yyvsp[-1].s != NULL)
1445 #line 574 "ftpcmd.y"
1447 reply(221, "Goodbye.");
1452 #line 579 "ftpcmd.y"
1458 #line 585 "ftpcmd.y"
1460 restart_point = (off_t) 0;
1461 if (yyvsp[-3].i && yyvsp[-1].s) {
1462 if (fromname != NULL)
1464 fromname = renamefrom(yyvsp[-1].s);
1466 if (fromname == (char *) 0 && yyvsp[-1].s)
1471 #line 596 "ftpcmd.y"
1473 if (fromname != NULL)
1475 fromname = (char *) 0;
1476 restart_point = yyvsp[-1].i; /* XXX $3 is only "int" */
1478 (sizeof(restart_point) > sizeof(long)
1479 ? "Restarting at %qd. %s"
1480 : "Restarting at %ld. %s"), restart_point,
1481 "Send STORE or RETRIEVE to initiate transfer.");
1485 #line 615 "ftpcmd.y"
1487 yyval.s = (char *)calloc(1, sizeof(char));
1491 #line 628 "ftpcmd.y"
1495 a = (char *)&data_dest.sin_addr;
1496 a[0] = yyvsp[-10].i; a[1] = yyvsp[-8].i; a[2] = yyvsp[-6].i; a[3] = yyvsp[-4].i;
1497 p = (char *)&data_dest.sin_port;
1498 p[0] = yyvsp[-2].i; p[1] = yyvsp[0].i;
1499 data_dest.sin_family = AF_INET;
1503 #line 641 "ftpcmd.y"
1509 #line 645 "ftpcmd.y"
1515 #line 649 "ftpcmd.y"
1521 #line 656 "ftpcmd.y"
1528 #line 661 "ftpcmd.y"
1531 cmd_form = yyvsp[0].i;
1535 #line 666 "ftpcmd.y"
1542 #line 671 "ftpcmd.y"
1545 cmd_form = yyvsp[0].i;
1549 #line 676 "ftpcmd.y"
1555 #line 680 "ftpcmd.y"
1562 #line 685 "ftpcmd.y"
1565 cmd_bytesz = yyvsp[0].i;
1569 #line 691 "ftpcmd.y"
1572 cmd_bytesz = yyvsp[0].i;
1576 #line 699 "ftpcmd.y"
1582 #line 703 "ftpcmd.y"
1588 #line 707 "ftpcmd.y"
1594 #line 714 "ftpcmd.y"
1600 #line 718 "ftpcmd.y"
1606 #line 722 "ftpcmd.y"
1612 #line 729 "ftpcmd.y"
1615 * Problem: this production is used for all pathname
1616 * processing, but only gives a 550 error reply.
1617 * This is a valid reply in some cases but not in others.
1619 if (cred.logged_in && yyvsp[0].s && *yyvsp[0].s == '~') {
1621 int flags = GLOB_NOCHECK;
1624 flags |= GLOB_BRACE;
1627 flags |= GLOB_QUOTE;
1630 flags |= GLOB_TILDE;
1633 memset(&gl, 0, sizeof(gl));
1634 if (glob(yyvsp[0].s, flags, NULL, &gl) ||
1636 reply(550, "not found");
1639 yyval.s = strdup(gl.gl_pathv[0]);
1644 yyval.s = yyvsp[0].s;
1648 #line 770 "ftpcmd.y"
1650 int ret, dec, multby, digit;
1653 * Convert a number that was read as decimal number
1654 * to what it would be if it had been read as octal.
1665 ret += digit * multby;
1673 #line 797 "ftpcmd.y"
1678 reply(530, "Please login with USER and PASS.");
1684 /* the action file gets copied in in place of this dollarsign */
1685 #line 543 "/usr/share/bison/bison.simple"
1696 short *ssp1 = yyss - 1;
1697 fprintf (stderr, "state stack now");
1698 while (ssp1 != yyssp)
1699 fprintf (stderr, " %d", *++ssp1);
1700 fprintf (stderr, "\n");
1710 yylsp->first_line = yylloc.first_line;
1711 yylsp->first_column = yylloc.first_column;
1712 yylsp->last_line = (yylsp-1)->last_line;
1713 yylsp->last_column = (yylsp-1)->last_column;
1718 yylsp->last_line = (yylsp+yylen-1)->last_line;
1719 yylsp->last_column = (yylsp+yylen-1)->last_column;
1723 /* Now "shift" the result of the reduction.
1724 Determine what state that goes to,
1725 based on the state we popped back to
1726 and the rule number reduced by. */
1730 yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
1731 if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1732 yystate = yytable[yystate];
1734 yystate = yydefgoto[yyn - YYNTBASE];
1738 yyerrlab: /* here on detecting error */
1741 /* If not already recovering from an error, report this error. */
1745 #ifdef YYERROR_VERBOSE
1746 yyn = yypact[yystate];
1748 if (yyn > YYFLAG && yyn < YYLAST)
1755 /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
1756 for (x = (yyn < 0 ? -yyn : 0);
1757 x < (sizeof(yytname) / sizeof(char *)); x++)
1758 if (yycheck[x + yyn] == x)
1759 size += strlen(yytname[x]) + 15, count++;
1760 msg = (char *) malloc(size + 15);
1763 strcpy(msg, "parse error");
1768 for (x = (yyn < 0 ? -yyn : 0);
1769 x < (sizeof(yytname) / sizeof(char *)); x++)
1770 if (yycheck[x + yyn] == x)
1772 strcat(msg, count == 0 ? ", expecting `" : " or `");
1773 strcat(msg, yytname[x]);
1782 yyerror ("parse error; also virtual memory exceeded");
1785 #endif /* YYERROR_VERBOSE */
1786 yyerror("parse error");
1790 yyerrlab1: /* here on error raised explicitly by an action */
1792 if (yyerrstatus == 3)
1794 /* if just tried and failed to reuse lookahead token after an error, discard it. */
1796 /* return failure if at end of input */
1797 if (yychar == YYEOF)
1802 fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
1808 /* Else will try to reuse lookahead token
1809 after shifting the error token. */
1811 yyerrstatus = 3; /* Each real token shifted decrements this */
1815 yyerrdefault: /* current state does not do anything special for the error token. */
1818 /* This is wrong; only states that explicitly want error tokens
1819 should shift them. */
1820 yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
1821 if (yyn) goto yydefault;
1824 yyerrpop: /* pop the current state because it cannot handle the error token */
1826 if (yyssp == yyss) YYABORT;
1836 short *ssp1 = yyss - 1;
1837 fprintf (stderr, "Error: state stack now");
1838 while (ssp1 != yyssp)
1839 fprintf (stderr, " %d", *++ssp1);
1840 fprintf (stderr, "\n");
1846 yyn = yypact[yystate];
1851 if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
1870 fprintf(stderr, "Shifting error token, ");
1882 /* YYACCEPT comes here. */
1894 /* YYABORT comes here. */
1905 #line 807 "ftpcmd.y"
1908 #define CMD 0 /* beginning of command */
1909 #define ARGS 1 /* expect miscellaneous arguments */
1910 #define STR1 2 /* expect SP followed by STRING */
1911 #define STR2 3 /* expect STRING */
1912 #define OSTR 4 /* optional SP then STRING */
1913 #define ZSTR1 5 /* SP then optional STRING */
1914 #define ZSTR2 6 /* optional STRING after SP */
1915 #define SITECMD 7 /* SITE command */
1916 #define NSTR 8 /* Number followed by a string */
1918 struct tab cmdtab[] = { /* In order defined in RFC 765 */
1919 { "USER", USER, STR1, 1, "<sp> username" },
1920 { "PASS", PASS, ZSTR1, 1, "<sp> password" },
1921 { "ACCT", ACCT, STR1, 0, "(specify account)" },
1922 { "SMNT", SMNT, ARGS, 0, "(structure mount)" },
1923 { "REIN", REIN, ARGS, 0, "(reinitialize server state)" },
1924 { "QUIT", QUIT, ARGS, 1, "(terminate service)", },
1925 { "PORT", PORT, ARGS, 1, "<sp> b0, b1, b2, b3, b4" },
1926 { "PASV", PASV, ARGS, 1, "(set server in passive mode)" },
1927 { "TYPE", TYPE, ARGS, 1, "<sp> [ A | E | I | L ]" },
1928 { "STRU", STRU, ARGS, 1, "(specify file structure)" },
1929 { "MODE", MODE, ARGS, 1, "(specify transfer mode)" },
1930 { "RETR", RETR, STR1, 1, "<sp> file-name" },
1931 { "STOR", STOR, STR1, 1, "<sp> file-name" },
1932 { "APPE", APPE, STR1, 1, "<sp> file-name" },
1933 { "MLFL", MLFL, OSTR, 0, "(mail file)" },
1934 { "MAIL", MAIL, OSTR, 0, "(mail to user)" },
1935 { "MSND", MSND, OSTR, 0, "(mail send to terminal)" },
1936 { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" },
1937 { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" },
1938 { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" },
1939 { "MRCP", MRCP, STR1, 0, "(mail recipient)" },
1940 { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" },
1941 { "REST", REST, ARGS, 1, "<sp> offset (restart command)" },
1942 { "RNFR", RNFR, STR1, 1, "<sp> file-name" },
1943 { "RNTO", RNTO, STR1, 1, "<sp> file-name" },
1944 { "ABOR", ABOR, ARGS, 1, "(abort operation)" },
1945 { "DELE", DELE, STR1, 1, "<sp> file-name" },
1946 { "CWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
1947 { "XCWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
1948 { "LIST", LIST, OSTR, 1, "[ <sp> path-name ]" },
1949 { "NLST", NLST, OSTR, 1, "[ <sp> path-name ]" },
1950 { "SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]" },
1951 { "SYST", SYST, ARGS, 1, "(get type of operating system)" },
1952 { "STAT", STAT, OSTR, 1, "[ <sp> path-name ]" },
1953 { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
1954 { "NOOP", NOOP, ARGS, 1, "" },
1955 { "MKD", MKD, STR1, 1, "<sp> path-name" },
1956 { "XMKD", MKD, STR1, 1, "<sp> path-name" },
1957 { "RMD", RMD, STR1, 1, "<sp> path-name" },
1958 { "XRMD", RMD, STR1, 1, "<sp> path-name" },
1959 { "PWD", PWD, ARGS, 1, "(return current directory)" },
1960 { "XPWD", PWD, ARGS, 1, "(return current directory)" },
1961 { "CDUP", CDUP, ARGS, 1, "(change to parent directory)" },
1962 { "XCUP", CDUP, ARGS, 1, "(change to parent directory)" },
1963 { "STOU", STOU, STR1, 1, "<sp> file-name" },
1964 { "SIZE", SIZE, OSTR, 1, "<sp> path-name" },
1965 { "MDTM", MDTM, OSTR, 1, "<sp> path-name" },
1966 { NULL, 0, 0, 0, 0 }
1969 struct tab sitetab[] = {
1970 { "UMASK", UMASK, ARGS, 1, "[ <sp> umask ]" },
1971 { "IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]" },
1972 { "CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name" },
1973 { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
1974 { NULL, 0, 0, 0, 0 }
1983 for (; p->name != NULL; p++)
1984 if (strcmp(cmd, p->name) == 0)
1989 #include <arpa/telnet.h>
1992 * getline - a hacked up version of fgets to ignore TELNET escape codes.
1995 telnet_fgets(char *s, int n, FILE *iop)
2001 /* tmpline may contain saved command from urgent mode interruption */
2002 for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) {
2004 if (tmpline[c] == '\n') {
2007 syslog(LOG_DEBUG, "command: %s", s);
2014 while ((c = getc(iop)) != EOF) {
2017 if ((c = getc(iop)) != EOF) {
2023 printf("%c%c%c", IAC, DONT, 0377&c);
2024 (void) fflush(stdout);
2029 printf("%c%c%c", IAC, WONT, 0377&c);
2030 (void) fflush(stdout);
2035 continue; /* ignore command */
2040 if (--n <= 0 || c == '\n')
2043 if (c == EOF && cs == s)
2047 if (!cred.guest && strncasecmp("pass ", s, 5) == 0) {
2048 /* Don't syslog passwords */
2049 syslog(LOG_DEBUG, "command: %.5s ???", s);
2054 /* Don't syslog trailing CR-LF */
2057 while (cp >= s && (*cp == '\n' || *cp == '\r')) {
2061 syslog(LOG_DEBUG, "command: %.*s", len, s);
2072 "Timeout (%d seconds): closing control connection.", timeout);
2074 syslog(LOG_INFO, "User %s timed out after %d seconds",
2075 (cred.name ? cred.name : "unknown"), timeout);
2082 static int cpos, state;
2092 (void) signal(SIGALRM, toolong);
2093 (void) alarm((unsigned) timeout);
2094 if (telnet_fgets(cbuf, sizeof(cbuf)-1, stdin) == NULL) {
2095 reply(221, "You could at least say goodbye.");
2099 #ifdef HAVE_SETPROCTITLE
2100 if (strncasecmp(cbuf, "PASS", 4) != NULL)
2101 setproctitle("%s: %s", proctitle, cbuf);
2102 #endif /* HAVE_SETPROCTITLE */
2103 if ((cp = strchr(cbuf, '\r'))) {
2107 if ((cp = strpbrk(cbuf, " \n")))
2114 p = lookup(cmdtab, cbuf);
2117 if (p->implemented == 0) {
2119 longjmp(errcatch,0);
2129 if (cbuf[cpos] == ' ') {
2134 if ((cp2 = strpbrk(cp, " \n")))
2139 p = lookup(sitetab, cp);
2142 if (p->implemented == 0) {
2145 longjmp(errcatch,0);
2156 if (cbuf[cpos] == '\n') {
2165 if (cbuf[cpos] == ' ') {
2167 state = state == OSTR ? STR2 : ++state;
2173 if (cbuf[cpos] == '\n') {
2184 * Make sure the string is nonempty and \n terminated.
2186 if (n > 1 && cbuf[cpos] == '\n') {
2188 yylval.s = copy(cp);
2196 if (cbuf[cpos] == ' ') {
2200 if (isdigit(cbuf[cpos])) {
2202 while (isdigit(cbuf[++cpos]))
2206 yylval.i = atoi(cp);
2215 if (isdigit(cbuf[cpos])) {
2217 while (isdigit(cbuf[++cpos]))
2221 yylval.i = atoi(cp);
2225 switch (cbuf[cpos++]) {
2289 fatal("Unknown state in scanner.");
2291 yyerror((char *) 0);
2293 longjmp(errcatch,0);
2300 while (*s != '\0') {
2312 p = malloc((unsigned) strlen(s) + 1);
2314 fatal("Ran out of memory.");
2315 (void) strcpy(p, s);
2320 help(struct tab *ctab, char *s)
2324 const char *help_type;
2326 if (ctab == sitetab)
2327 help_type = "SITE ";
2330 width = 0, NCMDS = 0;
2331 for (c = ctab; c->name != NULL; c++) {
2332 int len = strlen(c->name);
2338 width = (width + 8) &~ 7;
2343 lreply(214, "The following %scommands are recognized %s.",
2344 help_type, "(* =>'s unimplemented)");
2345 columns = 76 / width;
2348 lines = (NCMDS + columns - 1) / columns;
2349 for (i = 0; i < lines; i++) {
2351 for (j = 0; j < columns; j++) {
2352 c = ctab + j * lines + i;
2353 printf("%s%c", c->name,
2354 c->implemented ? ' ' : '*');
2355 if (c + lines >= &ctab[NCMDS])
2357 w = strlen(c->name) + 1;
2365 (void) fflush(stdout);
2366 reply(214, "Direct comments to ftp-bugs@%s.", hostname);
2370 c = lookup(ctab, s);
2371 if (c == (struct tab *)0) {
2372 reply(502, "Unknown command %s.", s);
2376 reply(214, "Syntax: %s%s %s", help_type, c->name, c->help);
2378 reply(214, "%s%-*s\t%s; unimplemented.", help_type, width,
2383 sizecmd(char *filename)
2389 if (stat(filename, &stbuf) < 0 || !S_ISREG(stbuf.st_mode))
2390 reply(550, "%s: not a plain file.", filename);
2393 (sizeof (stbuf.st_size) > sizeof(long)
2394 ? "%qu" : "%lu"), stbuf.st_size);
2401 fin = fopen(filename, "r");
2403 perror_reply(550, filename);
2406 if (fstat(fileno(fin), &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) {
2407 reply(550, "%s: not a plain file.", filename);
2413 while((c=getc(fin)) != EOF) {
2414 if (c == '\n') /* will get expanded to \r\n */
2420 reply(213, sizeof(count) > sizeof(long) ? "%qd" : "%ld",
2424 reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
2430 yyerror(const char *s)
2435 cp = strchr(cbuf,'\n');
2438 reply(500, "'%s': command not understood.", cbuf);