import netbsd ftpd
[minix3.git] / libexec / ftpd / ftpcmd.c
blob582a8e55a42730a63cb27df54be5333544e00c39
1 #ifndef lint
2 static const char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93";
3 #endif
5 #ifdef _LIBC
6 #include "namespace.h"
7 #endif
8 #include <stdlib.h>
9 #include <string.h>
11 #define YYBYACC 1
12 #define YYMAJOR 1
13 #define YYMINOR 9
15 #define YYEMPTY (-1)
16 #define yyclearin (yychar = YYEMPTY)
17 #define yyerrok (yyerrflag = 0)
18 #define YYRECOVERING() (yyerrflag != 0)
20 #define YYPREFIX "yy"
22 #define YYPURE 0
24 #line 69 "ftpcmd.y"
25 #include <sys/cdefs.h>
27 #ifndef lint
28 #if 0
29 static char sccsid[] = "@(#)ftpcmd.y 8.3 (Berkeley) 4/6/94";
30 #else
31 __RCSID("$NetBSD: ftpcmd.y,v 1.93 2011/09/16 16:13:17 plunky Exp $");
32 #endif
33 #endif /* not lint */
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 #include <sys/stat.h>
39 #include <netinet/in.h>
40 #include <arpa/ftp.h>
41 #include <arpa/inet.h>
43 #include <ctype.h>
44 #include <errno.h>
45 #include <pwd.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49 #include <syslog.h>
50 #include <time.h>
51 #include <tzfile.h>
52 #include <unistd.h>
53 #include <netdb.h>
55 #ifdef KERBEROS5
56 #include <krb5/krb5.h>
57 #endif
59 #include "extern.h"
60 #include "version.h"
62 static int cmd_type;
63 static int cmd_form;
64 static int cmd_bytesz;
66 char cbuf[FTP_BUFLEN];
67 char *cmdp;
68 char *fromname;
70 extern int epsvall;
71 struct tab sitetab[];
73 static int check_write(const char *, int);
74 static void help(struct tab *, const char *);
75 static void port_check(const char *, int);
76 int yylex(void);
78 #line 124 "ftpcmd.y"
79 #ifdef YYSTYPE
80 #undef YYSTYPE_IS_DECLARED
81 #define YYSTYPE_IS_DECLARED 1
82 #endif
83 #ifndef YYSTYPE_IS_DECLARED
84 #define YYSTYPE_IS_DECLARED 1
85 typedef union {
86 struct {
87 LLT ll;
88 int i;
89 } u;
90 char *s;
91 const char *cs;
92 } YYSTYPE;
93 #endif /* !YYSTYPE_IS_DECLARED */
94 #line 94 "ftpcmd.c"
96 /* compatibility with bison */
97 #ifdef YYPARSE_PARAM
98 /* compatibility with FreeBSD */
99 # ifdef YYPARSE_PARAM_TYPE
100 # define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)
101 # else
102 # define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)
103 # endif
104 #else
105 # define YYPARSE_DECL() yyparse(void)
106 #endif
108 /* Parameters sent to lex. */
109 #ifdef YYLEX_PARAM
110 # define YYLEX_DECL() yylex(void *YYLEX_PARAM)
111 # define YYLEX yylex(YYLEX_PARAM)
112 #else
113 # define YYLEX_DECL() yylex(void)
114 # define YYLEX yylex()
115 #endif
117 /* Parameters sent to yyerror. */
118 #define YYERROR_DECL() yyerror(const char *s)
119 #define YYERROR_CALL(msg) yyerror(msg)
121 extern int YYPARSE_DECL();
124 #define A 257
125 #define B 258
126 #define C 259
127 #define E 260
128 #define F 261
129 #define I 262
130 #define L 263
131 #define N 264
132 #define P 265
133 #define R 266
134 #define S 267
135 #define T 268
136 #define SP 269
137 #define CRLF 270
138 #define COMMA 271
139 #define ALL 272
140 #define USER 273
141 #define PASS 274
142 #define ACCT 275
143 #define CWD 276
144 #define CDUP 277
145 #define SMNT 278
146 #define QUIT 279
147 #define REIN 280
148 #define PORT 281
149 #define PASV 282
150 #define TYPE 283
151 #define STRU 284
152 #define MODE 285
153 #define RETR 286
154 #define STOR 287
155 #define STOU 288
156 #define APPE 289
157 #define ALLO 290
158 #define REST 291
159 #define RNFR 292
160 #define RNTO 293
161 #define ABOR 294
162 #define DELE 295
163 #define RMD 296
164 #define MKD 297
165 #define PWD 298
166 #define LIST 299
167 #define NLST 300
168 #define SITE 301
169 #define SYST 302
170 #define STAT 303
171 #define HELP 304
172 #define NOOP 305
173 #define AUTH 306
174 #define ADAT 307
175 #define PROT 308
176 #define PBSZ 309
177 #define CCC 310
178 #define MIC 311
179 #define CONF 312
180 #define ENC 313
181 #define FEAT 314
182 #define OPTS 315
183 #define SIZE 316
184 #define MDTM 317
185 #define MLST 318
186 #define MLSD 319
187 #define LPRT 320
188 #define LPSV 321
189 #define EPRT 322
190 #define EPSV 323
191 #define MAIL 324
192 #define MLFL 325
193 #define MRCP 326
194 #define MRSQ 327
195 #define MSAM 328
196 #define MSND 329
197 #define MSOM 330
198 #define CHMOD 331
199 #define IDLE 332
200 #define RATEGET 333
201 #define RATEPUT 334
202 #define UMASK 335
203 #define LEXERR 336
204 #define STRING 337
205 #define NUMBER 338
206 #define YYERRCODE 256
207 static const short yylhs[] = { -1,
208 0, 0, 16, 16, 16, 16, 16, 16, 16, 16,
209 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
210 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
211 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
212 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
213 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
214 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
215 17, 17, 12, 11, 11, 3, 18, 19, 20, 7,
216 7, 7, 6, 6, 6, 6, 6, 6, 6, 6,
217 4, 4, 4, 5, 5, 5, 10, 9, 2, 13,
218 14, 15, 8, 1,
220 static const short yylen[] = { 2,
221 1, 1, 4, 4, 3, 5, 3, 2, 5, 5,
222 5, 5, 3, 3, 5, 5, 3, 5, 5, 5,
223 5, 4, 4, 4, 5, 9, 4, 3, 4, 4,
224 4, 3, 3, 5, 3, 5, 4, 8, 6, 5,
225 7, 5, 7, 5, 7, 5, 7, 2, 5, 2,
226 2, 4, 2, 4, 4, 4, 4, 2, 4, 4,
227 4, 2, 4, 5, 5, 5, 3, 5, 3, 2,
228 5, 4, 1, 0, 1, 1, 11, 17, 41, 1,
229 1, 1, 1, 3, 1, 3, 1, 1, 3, 2,
230 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
231 1, 1, 1, 0,
233 static const short yydefred[] = { 0,
234 0, 0, 0, 104, 104, 0, 104, 104, 104, 104,
235 104, 104, 0, 0, 0, 104, 104, 0, 0, 104,
236 0, 0, 0, 104, 104, 104, 0, 0, 0, 0,
237 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
238 0, 104, 104, 104, 104, 104, 104, 104, 104, 0,
239 1, 2, 70, 0, 0, 0, 0, 8, 0, 0,
240 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
241 0, 0, 0, 0, 0, 0, 0, 0, 0, 48,
242 50, 0, 0, 51, 53, 0, 0, 0, 0, 58,
243 0, 0, 0, 62, 0, 0, 0, 0, 0, 0,
244 0, 0, 0, 73, 0, 75, 0, 0, 5, 7,
245 0, 13, 0, 0, 0, 0, 98, 97, 0, 0,
246 0, 0, 0, 0, 0, 28, 0, 0, 0, 32,
247 0, 33, 0, 35, 0, 0, 104, 104, 104, 104,
248 0, 0, 100, 0, 101, 0, 102, 0, 103, 0,
249 0, 0, 0, 0, 0, 0, 0, 67, 0, 69,
250 0, 14, 0, 0, 17, 3, 4, 0, 0, 0,
251 0, 0, 87, 0, 0, 91, 93, 92, 0, 95,
252 96, 94, 0, 0, 22, 23, 24, 0, 0, 72,
253 27, 29, 30, 31, 0, 0, 0, 37, 0, 0,
254 0, 0, 0, 0, 52, 54, 55, 56, 57, 59,
255 60, 61, 63, 0, 0, 0, 0, 0, 0, 0,
256 0, 0, 0, 6, 0, 9, 0, 0, 0, 76,
257 90, 18, 19, 20, 21, 0, 25, 71, 34, 36,
258 0, 99, 0, 0, 40, 0, 42, 0, 44, 0,
259 46, 49, 64, 65, 66, 68, 0, 10, 11, 12,
260 16, 15, 0, 82, 80, 81, 84, 86, 89, 0,
261 39, 0, 0, 0, 0, 0, 0, 0, 0, 0,
262 41, 43, 45, 47, 0, 0, 0, 38, 0, 0,
263 26, 0, 0, 0, 0, 0, 0, 0, 0, 0,
264 77, 0, 0, 0, 0, 0, 0, 0, 0, 0,
265 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
266 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267 0, 79,
269 static const short yydgoto[] = { 50,
270 56, 243, 231, 179, 183, 175, 267, 150, 118, 119,
271 107, 105, 144, 146, 148, 51, 52, 170, 219, 220,
273 static const short yysindex[] = { -179,
274 -260, -245, -239, 0, 0, -231, 0, 0, 0, 0,
275 0, 0, -228, -225, -205, 0, 0, -203, -199, 0,
276 -195, -181, -177, 0, 0, 0, -173, -194, -171, -257,
277 -169, -124, -109, -108, -107, -106, -104, -103, -102, -101,
278 -99, 0, 0, 0, 0, 0, 0, 0, 0, 0,
279 0, 0, 0, -174, -166, -242, -98, 0, -96, -95,
280 -93, -92, -91, -90, -163, -163, -163, -89, -88, -163,
281 -163, -87, -163, -163, -163, -86, -233, -191, -272, 0,
282 0, -84, -155, 0, 0, -151, -150, -149, -170, 0,
283 -150, -150, -150, 0, -148, -79, -78, -189, -187, -77,
284 -76, -74, -185, 0, -73, 0, -72, -163, 0, 0,
285 -145, 0, -217, -193, -236, -163, 0, 0, -71, -70,
286 -69, -142, -136, -67, -65, 0, -63, -62, -61, 0,
287 -163, 0, -163, 0, -183, -59, 0, 0, 0, 0,
288 -163, -58, 0, -57, 0, -56, 0, -55, 0, -54,
289 -53, -52, -51, -50, -163, -163, -163, 0, -163, 0,
290 -134, 0, -126, -269, 0, 0, 0, -49, -48, -46,
291 -47, -43, 0, -267, -45, 0, 0, 0, -42, 0,
292 0, 0, -41, -40, 0, 0, 0, -119, -39, 0,
293 0, 0, 0, 0, -38, -37, -110, 0, -100, -117,
294 -115, -113, -111, -36, 0, 0, 0, 0, 0, 0,
295 0, 0, 0, -35, -34, -33, -31, -30, -28, -27,
296 -26, -25, -24, 0, -85, 0, -253, -253, -83, 0,
297 0, 0, 0, 0, 0, -19, 0, 0, 0, 0,
298 -22, 0, -29, -82, 0, -80, 0, -75, 0, -100,
299 0, 0, 0, 0, 0, 0, -68, 0, 0, 0,
300 0, 0, -21, 0, 0, 0, 0, 0, 0, -20,
301 0, -163, -18, -16, -12, -11, -10, -64, -60, -7,
302 0, 0, 0, 0, -32, -6, -4, 0, -3, -23,
303 0, -17, -2, 1, -15, -14, 2, 4, -13, -9,
304 0, 5, -8, 6, -5, 8, -1, 10, 3, 11,
305 7, 12, 13, 14, 15, 16, 17, 18, 19, 20,
306 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
307 31, 0,
309 static const short yyrindex[] = { 0,
310 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
311 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
312 0, 0, 0, 0, 0, 0, 0, 0, 33, 0,
313 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
314 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
315 0, 0, 0, 0, 34, 0, 0, 0, 0, 0,
316 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
317 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
318 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
319 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
320 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
321 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
322 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
323 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
324 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
325 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
326 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
327 35, -169, 0, 37, 0, 0, 0, 0, 0, 0,
328 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
329 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
330 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
331 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
332 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
333 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
334 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
335 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
336 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
337 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
338 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
339 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
340 0, 0, 0, 0, 0, 0, 0, 38, 0, 0,
341 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
342 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
343 0, 0,
345 static const short yygindex[] = { 0,
346 9, 36, 42, 0, 0, 0, 32, 0, 0, -66,
347 0, 0, 0, -44, 0, 0, 0, 0, 0, 0,
349 #define YYTABLESIZE 369
350 static const short yytable[] = { 120,
351 121, 229, 222, 124, 125, 264, 127, 128, 129, 53,
352 265, 83, 84, 57, 266, 59, 60, 61, 62, 63,
353 64, 180, 181, 54, 68, 69, 108, 109, 72, 55,
354 182, 135, 76, 77, 78, 131, 132, 82, 58, 171,
355 65, 168, 172, 66, 173, 174, 151, 152, 153, 184,
356 96, 97, 98, 99, 100, 101, 102, 103, 136, 137,
357 138, 139, 140, 67, 195, 70, 196, 176, 223, 71,
358 230, 177, 178, 73, 204, 80, 1, 133, 134, 157,
359 158, 159, 160, 164, 165, 197, 198, 74, 214, 215,
360 216, 75, 217, 2, 3, 79, 4, 5, 81, 6,
361 85, 7, 8, 9, 10, 11, 12, 13, 14, 15,
362 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
363 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
364 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
365 46, 47, 48, 49, 86, 200, 201, 202, 203, 236,
366 237, 244, 245, 246, 247, 248, 249, 250, 251, 87,
367 88, 89, 104, 90, 91, 92, 93, 149, 94, 95,
368 106, 110, 111, 117, 112, 113, 114, 115, 116, 122,
369 123, 142, 126, 130, 141, 143, 145, 147, 154, 155,
370 156, 161, 169, 162, 163, 188, 166, 167, 185, 186,
371 187, 189, 190, 218, 191, 280, 192, 193, 194, 199,
372 221, 205, 206, 207, 208, 209, 210, 211, 212, 213,
373 224, 227, 225, 226, 232, 228, 241, 233, 234, 235,
374 238, 239, 240, 252, 253, 254, 255, 242, 256, 272,
375 257, 258, 259, 260, 261, 262, 270, 271, 279, 278,
376 0, 281, 263, 282, 230, 273, 274, 283, 284, 268,
377 285, 275, 288, 0, 290, 291, 0, 292, 295, 277,
378 269, 296, 299, 286, 300, 303, 305, 287, 307, 0,
379 309, 311, 313, 0, 315, 276, 317, 0, 319, 0,
380 321, 0, 323, 0, 325, 0, 327, 0, 329, 0,
381 331, 104, 0, 74, 83, 289, 88, 78, 0, 0,
382 0, 0, 0, 0, 293, 0, 0, 0, 0, 0,
383 294, 0, 297, 298, 301, 0, 0, 0, 302, 304,
384 0, 0, 306, 0, 0, 0, 308, 0, 0, 0,
385 310, 0, 0, 0, 312, 0, 0, 0, 0, 0,
386 314, 0, 316, 0, 318, 0, 320, 0, 322, 0,
387 324, 0, 326, 0, 328, 0, 330, 0, 332,
389 static const short yycheck[] = { 66,
390 67, 269, 272, 70, 71, 259, 73, 74, 75, 270,
391 264, 269, 270, 5, 268, 7, 8, 9, 10, 11,
392 12, 258, 259, 269, 16, 17, 269, 270, 20, 269,
393 267, 304, 24, 25, 26, 269, 270, 29, 270, 257,
394 269, 108, 260, 269, 262, 263, 91, 92, 93, 116,
395 42, 43, 44, 45, 46, 47, 48, 49, 331, 332,
396 333, 334, 335, 269, 131, 269, 133, 261, 338, 269,
397 338, 265, 266, 269, 141, 270, 256, 269, 270, 269,
398 270, 269, 270, 269, 270, 269, 270, 269, 155, 156,
399 157, 269, 159, 273, 274, 269, 276, 277, 270, 279,
400 270, 281, 282, 283, 284, 285, 286, 287, 288, 289,
401 290, 291, 292, 293, 294, 295, 296, 297, 298, 299,
402 300, 301, 302, 303, 304, 305, 306, 307, 308, 309,
403 310, 311, 312, 313, 314, 315, 316, 317, 318, 319,
404 320, 321, 322, 323, 269, 137, 138, 139, 140, 269,
405 270, 269, 270, 269, 270, 269, 270, 269, 270, 269,
406 269, 269, 337, 270, 269, 269, 269, 338, 270, 269,
407 337, 270, 269, 337, 270, 269, 269, 269, 269, 269,
408 269, 337, 270, 270, 269, 337, 337, 337, 337, 269,
409 269, 269, 338, 270, 269, 338, 270, 270, 270, 270,
410 270, 338, 270, 338, 270, 272, 270, 270, 270, 269,
411 337, 270, 270, 270, 270, 270, 270, 270, 270, 270,
412 270, 269, 271, 270, 270, 269, 337, 270, 270, 270,
413 270, 270, 270, 270, 270, 270, 270, 338, 270, 269,
414 271, 270, 270, 270, 270, 270, 266, 270, 269, 271,
415 -1, 270, 338, 270, 338, 338, 337, 270, 270, 228,
416 271, 337, 270, -1, 271, 270, -1, 271, 271, 338,
417 229, 271, 271, 338, 271, 271, 271, 338, 271, -1,
418 271, 271, 271, -1, 271, 250, 271, -1, 271, -1,
419 271, -1, 271, -1, 271, -1, 271, -1, 271, -1,
420 271, 269, -1, 270, 270, 338, 270, 270, -1, -1,
421 -1, -1, -1, -1, 338, -1, -1, -1, -1, -1,
422 338, -1, 338, 338, 338, -1, -1, -1, 338, 338,
423 -1, -1, 338, -1, -1, -1, 338, -1, -1, -1,
424 338, -1, -1, -1, 338, -1, -1, -1, -1, -1,
425 338, -1, 338, -1, 338, -1, 338, -1, 338, -1,
426 338, -1, 338, -1, 338, -1, 338, -1, 338,
428 #define YYFINAL 50
429 #ifndef YYDEBUG
430 #define YYDEBUG 0
431 #endif
432 #define YYMAXTOKEN 338
433 #if YYDEBUG
434 static const char *yyname[] = {
436 "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,
437 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
438 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
439 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
440 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
441 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
442 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",
443 "P","R","S","T","SP","CRLF","COMMA","ALL","USER","PASS","ACCT","CWD","CDUP",
444 "SMNT","QUIT","REIN","PORT","PASV","TYPE","STRU","MODE","RETR","STOR","STOU",
445 "APPE","ALLO","REST","RNFR","RNTO","ABOR","DELE","RMD","MKD","PWD","LIST",
446 "NLST","SITE","SYST","STAT","HELP","NOOP","AUTH","ADAT","PROT","PBSZ","CCC",
447 "MIC","CONF","ENC","FEAT","OPTS","SIZE","MDTM","MLST","MLSD","LPRT","LPSV",
448 "EPRT","EPSV","MAIL","MLFL","MRCP","MRSQ","MSAM","MSND","MSOM","CHMOD","IDLE",
449 "RATEGET","RATEPUT","UMASK","LEXERR","STRING","NUMBER",
451 static const char *yyrule[] = {
452 "$accept : cmd_sel",
453 "cmd_sel : cmd",
454 "cmd_sel : rcmd",
455 "cmd : USER SP username CRLF",
456 "cmd : PASS SP password CRLF",
457 "cmd : CWD check_login CRLF",
458 "cmd : CWD check_login SP pathname CRLF",
459 "cmd : CDUP check_login CRLF",
460 "cmd : QUIT CRLF",
461 "cmd : PORT check_login SP host_port CRLF",
462 "cmd : LPRT check_login SP host_long_port4 CRLF",
463 "cmd : LPRT check_login SP host_long_port6 CRLF",
464 "cmd : EPRT check_login SP STRING CRLF",
465 "cmd : PASV check_login CRLF",
466 "cmd : LPSV check_login CRLF",
467 "cmd : EPSV check_login SP NUMBER CRLF",
468 "cmd : EPSV check_login SP ALL CRLF",
469 "cmd : EPSV check_login CRLF",
470 "cmd : TYPE check_login SP type_code CRLF",
471 "cmd : STRU check_login SP struct_code CRLF",
472 "cmd : MODE check_login SP mode_code CRLF",
473 "cmd : RETR check_login SP pathname CRLF",
474 "cmd : STOR SP pathname CRLF",
475 "cmd : STOU SP pathname CRLF",
476 "cmd : APPE SP pathname CRLF",
477 "cmd : ALLO check_login SP NUMBER CRLF",
478 "cmd : ALLO check_login SP NUMBER SP R SP NUMBER CRLF",
479 "cmd : RNTO SP pathname CRLF",
480 "cmd : ABOR check_login CRLF",
481 "cmd : DELE SP pathname CRLF",
482 "cmd : RMD SP pathname CRLF",
483 "cmd : MKD SP pathname CRLF",
484 "cmd : PWD check_login CRLF",
485 "cmd : LIST check_login CRLF",
486 "cmd : LIST check_login SP pathname CRLF",
487 "cmd : NLST check_login CRLF",
488 "cmd : NLST check_login SP pathname CRLF",
489 "cmd : SITE SP HELP CRLF",
490 "cmd : SITE SP CHMOD SP octal_number SP pathname CRLF",
491 "cmd : SITE SP HELP SP STRING CRLF",
492 "cmd : SITE SP IDLE check_login CRLF",
493 "cmd : SITE SP IDLE check_login SP NUMBER CRLF",
494 "cmd : SITE SP RATEGET check_login CRLF",
495 "cmd : SITE SP RATEGET check_login SP STRING CRLF",
496 "cmd : SITE SP RATEPUT check_login CRLF",
497 "cmd : SITE SP RATEPUT check_login SP STRING CRLF",
498 "cmd : SITE SP UMASK check_login CRLF",
499 "cmd : SITE SP UMASK check_login SP octal_number CRLF",
500 "cmd : SYST CRLF",
501 "cmd : STAT check_login SP pathname CRLF",
502 "cmd : STAT CRLF",
503 "cmd : HELP CRLF",
504 "cmd : HELP SP STRING CRLF",
505 "cmd : NOOP CRLF",
506 "cmd : AUTH SP mechanism_name CRLF",
507 "cmd : ADAT SP base64data CRLF",
508 "cmd : PROT SP prot_code CRLF",
509 "cmd : PBSZ SP decimal_integer CRLF",
510 "cmd : CCC CRLF",
511 "cmd : MIC SP base64data CRLF",
512 "cmd : CONF SP base64data CRLF",
513 "cmd : ENC SP base64data CRLF",
514 "cmd : FEAT CRLF",
515 "cmd : OPTS SP STRING CRLF",
516 "cmd : SIZE check_login SP pathname CRLF",
517 "cmd : MDTM check_login SP pathname CRLF",
518 "cmd : MLST check_login SP pathname CRLF",
519 "cmd : MLST check_login CRLF",
520 "cmd : MLSD check_login SP pathname CRLF",
521 "cmd : MLSD check_login CRLF",
522 "cmd : error CRLF",
523 "rcmd : REST check_login SP NUMBER CRLF",
524 "rcmd : RNFR SP pathname CRLF",
525 "username : STRING",
526 "password :",
527 "password : STRING",
528 "byte_size : NUMBER",
529 "host_port : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER",
530 "host_long_port4 : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER",
531 "host_long_port6 : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER",
532 "form_code : N",
533 "form_code : T",
534 "form_code : C",
535 "type_code : A",
536 "type_code : A SP form_code",
537 "type_code : E",
538 "type_code : E SP form_code",
539 "type_code : I",
540 "type_code : L",
541 "type_code : L SP byte_size",
542 "type_code : L byte_size",
543 "struct_code : F",
544 "struct_code : R",
545 "struct_code : P",
546 "mode_code : S",
547 "mode_code : B",
548 "mode_code : C",
549 "pathname : pathstring",
550 "pathstring : STRING",
551 "octal_number : NUMBER",
552 "mechanism_name : STRING",
553 "base64data : STRING",
554 "prot_code : STRING",
555 "decimal_integer : NUMBER",
556 "check_login :",
559 #endif
561 int yydebug;
562 int yynerrs;
564 int yyerrflag;
565 int yychar;
566 YYSTYPE yyval;
567 YYSTYPE yylval;
569 /* define the initial stack-sizes */
570 #ifdef YYSTACKSIZE
571 #undef YYMAXDEPTH
572 #define YYMAXDEPTH YYSTACKSIZE
573 #else
574 #ifdef YYMAXDEPTH
575 #define YYSTACKSIZE YYMAXDEPTH
576 #else
577 #define YYSTACKSIZE 500
578 #define YYMAXDEPTH 500
579 #endif
580 #endif
582 #define YYINITSTACKSIZE 500
584 typedef struct {
585 unsigned stacksize;
586 short *s_base;
587 short *s_mark;
588 short *s_last;
589 YYSTYPE *l_base;
590 YYSTYPE *l_mark;
591 } YYSTACKDATA;
592 /* variables for the parser stack */
593 static YYSTACKDATA yystack;
594 #line 1208 "ftpcmd.y"
596 #define CMD 0 /* beginning of command */
597 #define ARGS 1 /* expect miscellaneous arguments */
598 #define STR1 2 /* expect SP followed by STRING */
599 #define STR2 3 /* expect STRING */
600 #define OSTR 4 /* optional SP then STRING */
601 #define ZSTR1 5 /* SP then optional STRING */
602 #define ZSTR2 6 /* optional STRING after SP */
603 #define SITECMD 7 /* SITE command */
604 #define NSTR 8 /* Number followed by a string */
605 #define NOARGS 9 /* No arguments allowed */
606 #define EOLN 10 /* End of line */
608 struct tab cmdtab[] = {
609 /* From RFC 959, in order defined (5.3.1) */
610 { "USER", USER, STR1, 1, "<sp> username", 0, },
611 { "PASS", PASS, ZSTR1, 1, "<sp> password", 0, },
612 { "ACCT", ACCT, STR1, 0, "(specify account)", 0, },
613 { "CWD", CWD, OSTR, 1, "[ <sp> directory-name ]", 0, },
614 { "CDUP", CDUP, NOARGS, 1, "(change to parent directory)", 0, },
615 { "SMNT", SMNT, ARGS, 0, "(structure mount)", 0, },
616 { "QUIT", QUIT, NOARGS, 1, "(terminate service)", 0, },
617 { "REIN", REIN, NOARGS, 0, "(reinitialize server state)", 0, },
618 { "PORT", PORT, ARGS, 1, "<sp> b0, b1, b2, b3, b4, b5", 0, },
619 { "LPRT", LPRT, ARGS, 1, "<sp> af, hal, h1, h2, h3,..., pal, p1, p2...", 0, },
620 { "EPRT", EPRT, STR1, 1, "<sp> |af|addr|port|", 0, },
621 { "PASV", PASV, NOARGS, 1, "(set server in passive mode)", 0, },
622 { "LPSV", LPSV, ARGS, 1, "(set server in passive mode)", 0, },
623 { "EPSV", EPSV, ARGS, 1, "[<sp> af|ALL]", 0, },
624 { "TYPE", TYPE, ARGS, 1, "<sp> [ A | E | I | L ]", 0, },
625 { "STRU", STRU, ARGS, 1, "(specify file structure)", 0, },
626 { "MODE", MODE, ARGS, 1, "(specify transfer mode)", 0, },
627 { "RETR", RETR, STR1, 1, "<sp> file-name", 0, },
628 { "STOR", STOR, STR1, 1, "<sp> file-name", 0, },
629 { "STOU", STOU, STR1, 1, "<sp> file-name", 0, },
630 { "APPE", APPE, STR1, 1, "<sp> file-name", 0, },
631 { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)", 0, },
632 { "REST", REST, ARGS, 1, "<sp> offset (restart command)", 0, },
633 { "RNFR", RNFR, STR1, 1, "<sp> file-name", 0, },
634 { "RNTO", RNTO, STR1, 1, "<sp> file-name", 0, },
635 { "ABOR", ABOR, NOARGS, 4, "(abort operation)", 0, },
636 { "DELE", DELE, STR1, 1, "<sp> file-name", 0, },
637 { "RMD", RMD, STR1, 1, "<sp> path-name", 0, },
638 { "MKD", MKD, STR1, 1, "<sp> path-name", 0, },
639 { "PWD", PWD, NOARGS, 1, "(return current directory)", 0, },
640 { "LIST", LIST, OSTR, 1, "[ <sp> path-name ]", 0, },
641 { "NLST", NLST, OSTR, 1, "[ <sp> path-name ]", 0, },
642 { "SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]", 0, },
643 { "SYST", SYST, NOARGS, 1, "(get type of operating system)", 0, },
644 { "STAT", STAT, OSTR, 4, "[ <sp> path-name ]", 0, },
645 { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]", 0, },
646 { "NOOP", NOOP, NOARGS, 2, "", 0, },
648 /* From RFC 2228, in order defined */
649 { "AUTH", AUTH, STR1, 1, "<sp> mechanism-name", 0, },
650 { "ADAT", ADAT, STR1, 1, "<sp> base-64-data", 0, },
651 { "PROT", PROT, STR1, 1, "<sp> prot-code", 0, },
652 { "PBSZ", PBSZ, ARGS, 1, "<sp> decimal-integer", 0, },
653 { "CCC", CCC, NOARGS, 1, "(Disable data protection)", 0, },
654 { "MIC", MIC, STR1, 4, "<sp> base64data", 0, },
655 { "CONF", CONF, STR1, 4, "<sp> base64data", 0, },
656 { "ENC", ENC, STR1, 4, "<sp> base64data", 0, },
658 /* From RFC 2389, in order defined */
659 { "FEAT", FEAT, NOARGS, 1, "(display extended features)", 0, },
660 { "OPTS", OPTS, STR1, 1, "<sp> command [ <sp> options ]", 0, },
662 /* From RFC 3659, in order defined */
663 { "MDTM", MDTM, OSTR, 1, "<sp> path-name", 0, },
664 { "SIZE", SIZE, OSTR, 1, "<sp> path-name", 0, },
665 { "MLST", MLST, OSTR, 2, "[ <sp> path-name ]", 0, },
666 { "MLSD", MLSD, OSTR, 1, "[ <sp> directory-name ]", 0, },
668 /* obsolete commands */
669 { "MAIL", MAIL, OSTR, 0, "(mail to user)", 0, },
670 { "MLFL", MLFL, OSTR, 0, "(mail file)", 0, },
671 { "MRCP", MRCP, STR1, 0, "(mail recipient)", 0, },
672 { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)", 0, },
673 { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)", 0, },
674 { "MSND", MSND, OSTR, 0, "(mail send to terminal)", 0, },
675 { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)", 0, },
676 { "XCUP", CDUP, NOARGS, 1, "(change to parent directory)", 0, },
677 { "XCWD", CWD, OSTR, 1, "[ <sp> directory-name ]", 0, },
678 { "XMKD", MKD, STR1, 1, "<sp> path-name", 0, },
679 { "XPWD", PWD, NOARGS, 1, "(return current directory)", 0, },
680 { "XRMD", RMD, STR1, 1, "<sp> path-name", 0, },
682 { NULL, 0, 0, 0, 0, 0, }
685 struct tab sitetab[] = {
686 { "CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name", 0, },
687 { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]", 0, },
688 { "IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]", 0, },
689 { "RATEGET", RATEGET,OSTR, 1, "[ <sp> get-throttle-rate ]", 0, },
690 { "RATEPUT", RATEPUT,OSTR, 1, "[ <sp> put-throttle-rate ]", 0, },
691 { "UMASK", UMASK, ARGS, 1, "[ <sp> umask ]", 0, },
692 { NULL, 0, 0, 0, 0, 0, }
696 * Check if a filename is allowed to be modified (isupload == 0) or
697 * uploaded (isupload == 1), and if necessary, check the filename is `sane'.
698 * If the filename is NULL, fail.
699 * If the filename is "", don't do the sane name check.
701 static int
702 check_write(const char *file, int isupload)
704 if (file == NULL)
705 return (0);
706 if (! logged_in) {
707 reply(530, "Please login with USER and PASS.");
708 return (0);
710 /* checking modify */
711 if (! isupload && ! CURCLASS_FLAGS_ISSET(modify)) {
712 reply(502, "No permission to use this command.");
713 return (0);
715 /* checking upload */
716 if (isupload && ! CURCLASS_FLAGS_ISSET(upload)) {
717 reply(502, "No permission to use this command.");
718 return (0);
721 /* checking sanenames */
722 if (file[0] != '\0' && CURCLASS_FLAGS_ISSET(sanenames)) {
723 const char *p;
725 if (file[0] == '.')
726 goto insane_name;
727 for (p = file; *p; p++) {
728 if (isalnum((unsigned char)*p) || *p == '-' || *p == '+' ||
729 *p == ',' || *p == '.' || *p == '_')
730 continue;
731 insane_name:
732 reply(553, "File name `%s' not allowed.", file);
733 return (0);
736 return (1);
739 struct tab *
740 lookup(struct tab *p, const char *cmd)
743 for (; p->name != NULL; p++)
744 if (strcasecmp(cmd, p->name) == 0)
745 return (p);
746 return (0);
749 #include <arpa/telnet.h>
752 * get_line - a hacked up version of fgets to ignore TELNET escape codes.
753 * `s' is the buffer to read into.
754 * `n' is the 1 less than the size of the buffer, to allow trailing NUL
755 * `iop' is the FILE to read from.
756 * Returns 0 on success, -1 on EOF, -2 if the command was too long.
759 get_line(char *s, int n, FILE *iop)
761 int c;
762 char *cs;
764 cs = s;
765 /* tmpline may contain saved command from urgent mode interruption */
766 for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) {
767 *cs++ = tmpline[c];
768 if (tmpline[c] == '\n') {
769 *cs++ = '\0';
770 if (ftpd_debug)
771 syslog(LOG_DEBUG, "command: %s", s);
772 tmpline[0] = '\0';
773 return(0);
775 if (c == 0)
776 tmpline[0] = '\0';
778 while ((c = getc(iop)) != EOF) {
779 total_bytes++;
780 total_bytes_in++;
781 c &= 0377;
782 if (c == IAC) {
783 if ((c = getc(iop)) != EOF) {
784 total_bytes++;
785 total_bytes_in++;
786 c &= 0377;
787 switch (c) {
788 case WILL:
789 case WONT:
790 c = getc(iop);
791 total_bytes++;
792 total_bytes_in++;
793 cprintf(stdout, "%c%c%c", IAC, DONT, 0377&c);
794 (void) fflush(stdout);
795 continue;
796 case DO:
797 case DONT:
798 c = getc(iop);
799 total_bytes++;
800 total_bytes_in++;
801 cprintf(stdout, "%c%c%c", IAC, WONT, 0377&c);
802 (void) fflush(stdout);
803 continue;
804 case IAC:
805 break;
806 default:
807 continue; /* ignore command */
811 *cs++ = c;
812 if (--n <= 0) {
814 * If command doesn't fit into buffer, discard the
815 * rest of the command and indicate truncation.
816 * This prevents the command to be split up into
817 * multiple commands.
819 if (ftpd_debug)
820 syslog(LOG_DEBUG,
821 "command too long, last char: %d", c);
822 while (c != '\n' && (c = getc(iop)) != EOF)
823 continue;
824 return (-2);
826 if (c == '\n')
827 break;
829 if (c == EOF && cs == s)
830 return (-1);
831 *cs++ = '\0';
832 if (ftpd_debug) {
833 if ((curclass.type != CLASS_GUEST &&
834 strncasecmp(s, "PASS ", 5) == 0) ||
835 strncasecmp(s, "ACCT ", 5) == 0) {
836 /* Don't syslog passwords */
837 syslog(LOG_DEBUG, "command: %.4s ???", s);
838 } else {
839 char *cp;
840 int len;
842 /* Don't syslog trailing CR-LF */
843 len = strlen(s);
844 cp = s + len - 1;
845 while (cp >= s && (*cp == '\n' || *cp == '\r')) {
846 --cp;
847 --len;
849 syslog(LOG_DEBUG, "command: %.*s", len, s);
852 return (0);
855 void
856 ftp_handle_line(char *cp)
859 cmdp = cp;
860 yyparse();
863 void
864 ftp_loop(void)
866 int ret;
868 while (1) {
869 (void) alarm(curclass.timeout);
870 ret = get_line(cbuf, sizeof(cbuf)-1, stdin);
871 (void) alarm(0);
872 if (ret == -1) {
873 reply(221, "You could at least say goodbye.");
874 dologout(0);
875 } else if (ret == -2) {
876 reply(500, "Command too long.");
877 } else {
878 ftp_handle_line(cbuf);
881 /*NOTREACHED*/
885 yylex(void)
887 static int cpos, state;
888 char *cp, *cp2;
889 struct tab *p;
890 int n;
891 char c;
893 switch (state) {
895 case CMD:
896 hasyyerrored = 0;
897 if ((cp = strchr(cmdp, '\r'))) {
898 *cp = '\0';
899 #if defined(HAVE_SETPROCTITLE)
900 if (strncasecmp(cmdp, "PASS", 4) != 0 &&
901 strncasecmp(cmdp, "ACCT", 4) != 0)
902 setproctitle("%s: %s", proctitle, cmdp);
903 #endif /* defined(HAVE_SETPROCTITLE) */
904 *cp++ = '\n';
905 *cp = '\0';
907 if ((cp = strpbrk(cmdp, " \n")))
908 cpos = cp - cmdp;
909 if (cpos == 0)
910 cpos = 4;
911 c = cmdp[cpos];
912 cmdp[cpos] = '\0';
913 p = lookup(cmdtab, cmdp);
914 cmdp[cpos] = c;
915 if (p != NULL) {
916 if (is_oob && ! CMD_OOB(p)) {
917 /* command will be handled in-band */
918 return (0);
919 } else if (! CMD_IMPLEMENTED(p)) {
920 reply(502, "%s command not implemented.",
921 p->name);
922 hasyyerrored = 1;
923 break;
925 state = p->state;
926 yylval.cs = p->name;
927 return (p->token);
929 break;
931 case SITECMD:
932 if (cmdp[cpos] == ' ') {
933 cpos++;
934 return (SP);
936 cp = &cmdp[cpos];
937 if ((cp2 = strpbrk(cp, " \n")))
938 cpos = cp2 - cmdp;
939 c = cmdp[cpos];
940 cmdp[cpos] = '\0';
941 p = lookup(sitetab, cp);
942 cmdp[cpos] = c;
943 if (p != NULL) {
944 if (!CMD_IMPLEMENTED(p)) {
945 reply(502, "SITE %s command not implemented.",
946 p->name);
947 hasyyerrored = 1;
948 break;
950 state = p->state;
951 yylval.cs = p->name;
952 return (p->token);
954 break;
956 case OSTR:
957 if (cmdp[cpos] == '\n') {
958 state = EOLN;
959 return (CRLF);
961 /* FALLTHROUGH */
963 case STR1:
964 case ZSTR1:
965 dostr1:
966 if (cmdp[cpos] == ' ') {
967 cpos++;
968 state = state == OSTR ? STR2 : state+1;
969 return (SP);
971 break;
973 case ZSTR2:
974 if (cmdp[cpos] == '\n') {
975 state = EOLN;
976 return (CRLF);
978 /* FALLTHROUGH */
980 case STR2:
981 cp = &cmdp[cpos];
982 n = strlen(cp);
983 cpos += n - 1;
985 * Make sure the string is nonempty and \n terminated.
987 if (n > 1 && cmdp[cpos] == '\n') {
988 cmdp[cpos] = '\0';
989 yylval.s = ftpd_strdup(cp);
990 cmdp[cpos] = '\n';
991 state = ARGS;
992 return (STRING);
994 break;
996 case NSTR:
997 if (cmdp[cpos] == ' ') {
998 cpos++;
999 return (SP);
1001 if (isdigit((unsigned char)cmdp[cpos])) {
1002 cp = &cmdp[cpos];
1003 while (isdigit((unsigned char)cmdp[++cpos]))
1005 c = cmdp[cpos];
1006 cmdp[cpos] = '\0';
1007 yylval.u.i = atoi(cp);
1008 cmdp[cpos] = c;
1009 state = STR1;
1010 return (NUMBER);
1012 state = STR1;
1013 goto dostr1;
1015 case ARGS:
1016 if (isdigit((unsigned char)cmdp[cpos])) {
1017 cp = &cmdp[cpos];
1018 while (isdigit((unsigned char)cmdp[++cpos]))
1020 c = cmdp[cpos];
1021 cmdp[cpos] = '\0';
1022 yylval.u.i = atoi(cp);
1023 yylval.u.ll = STRTOLL(cp, NULL, 10);
1024 cmdp[cpos] = c;
1025 return (NUMBER);
1027 if (strncasecmp(&cmdp[cpos], "ALL", 3) == 0
1028 && !isalnum((unsigned char)cmdp[cpos + 3])) {
1029 cpos += 3;
1030 return (ALL);
1032 switch (cmdp[cpos++]) {
1034 case '\n':
1035 state = EOLN;
1036 return (CRLF);
1038 case ' ':
1039 return (SP);
1041 case ',':
1042 return (COMMA);
1044 case 'A':
1045 case 'a':
1046 return (A);
1048 case 'B':
1049 case 'b':
1050 return (B);
1052 case 'C':
1053 case 'c':
1054 return (C);
1056 case 'E':
1057 case 'e':
1058 return (E);
1060 case 'F':
1061 case 'f':
1062 return (F);
1064 case 'I':
1065 case 'i':
1066 return (I);
1068 case 'L':
1069 case 'l':
1070 return (L);
1072 case 'N':
1073 case 'n':
1074 return (N);
1076 case 'P':
1077 case 'p':
1078 return (P);
1080 case 'R':
1081 case 'r':
1082 return (R);
1084 case 'S':
1085 case 's':
1086 return (S);
1088 case 'T':
1089 case 't':
1090 return (T);
1093 break;
1095 case NOARGS:
1096 if (cmdp[cpos] == '\n') {
1097 state = EOLN;
1098 return (CRLF);
1100 c = cmdp[cpos];
1101 cmdp[cpos] = '\0';
1102 reply(501, "'%s' command does not take any arguments.", cmdp);
1103 hasyyerrored = 1;
1104 cmdp[cpos] = c;
1105 break;
1107 case EOLN:
1108 state = CMD;
1109 return (0);
1111 default:
1112 fatal("Unknown state in scanner.");
1114 yyerror(NULL);
1115 state = CMD;
1116 return (0);
1119 /* ARGSUSED */
1120 void
1121 yyerror(const char *s)
1123 char *cp;
1125 if (hasyyerrored || is_oob)
1126 return;
1127 if ((cp = strchr(cmdp,'\n')) != NULL)
1128 *cp = '\0';
1129 reply(500, "'%s': command not understood.", cmdp);
1130 hasyyerrored = 1;
1133 static void
1134 help(struct tab *ctab, const char *s)
1136 struct tab *c;
1137 int width, NCMDS;
1138 const char *htype;
1140 if (ctab == sitetab)
1141 htype = "SITE ";
1142 else
1143 htype = "";
1144 width = 0, NCMDS = 0;
1145 for (c = ctab; c->name != NULL; c++) {
1146 int len = strlen(c->name);
1148 if (len > width)
1149 width = len;
1150 NCMDS++;
1152 width = (width + 8) &~ 7;
1153 if (s == 0) {
1154 int i, j, w;
1155 int columns, lines;
1157 reply(-214, "%s", "");
1158 reply(0, "The following %scommands are recognized.", htype);
1159 reply(0, "(`-' = not implemented, `+' = supports options)");
1160 columns = 76 / width;
1161 if (columns == 0)
1162 columns = 1;
1163 lines = (NCMDS + columns - 1) / columns;
1164 for (i = 0; i < lines; i++) {
1165 cprintf(stdout, " ");
1166 for (j = 0; j < columns; j++) {
1167 c = ctab + j * lines + i;
1168 cprintf(stdout, "%s", c->name);
1169 w = strlen(c->name);
1170 if (! CMD_IMPLEMENTED(c)) {
1171 CPUTC('-', stdout);
1172 w++;
1174 if (CMD_HAS_OPTIONS(c)) {
1175 CPUTC('+', stdout);
1176 w++;
1178 if (c + lines >= &ctab[NCMDS])
1179 break;
1180 while (w < width) {
1181 CPUTC(' ', stdout);
1182 w++;
1185 cprintf(stdout, "\r\n");
1187 (void) fflush(stdout);
1188 reply(214, "Direct comments to ftp-bugs@%s.", hostname);
1189 return;
1191 c = lookup(ctab, s);
1192 if (c == (struct tab *)0) {
1193 reply(502, "Unknown command '%s'.", s);
1194 return;
1196 if (CMD_IMPLEMENTED(c))
1197 reply(214, "Syntax: %s%s %s", htype, c->name, c->help);
1198 else
1199 reply(504, "%s%-*s\t%s; not implemented.", htype, width,
1200 c->name, c->help);
1204 * Check that the structures used for a PORT, LPRT or EPRT command are
1205 * valid (data_dest, his_addr), and if necessary, detect ftp bounce attacks.
1206 * If family != -1 check that his_addr.su_family == family.
1208 static void
1209 port_check(const char *cmd, int family)
1211 char h1[NI_MAXHOST], h2[NI_MAXHOST];
1212 char s1[NI_MAXHOST], s2[NI_MAXHOST];
1213 #ifdef NI_WITHSCOPEID
1214 const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID;
1215 #else
1216 const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
1217 #endif
1219 if (epsvall) {
1220 reply(501, "%s disallowed after EPSV ALL", cmd);
1221 return;
1224 if (family != -1 && his_addr.su_family != family) {
1225 port_check_fail:
1226 reply(500, "Illegal %s command rejected", cmd);
1227 return;
1230 if (data_dest.su_family != his_addr.su_family)
1231 goto port_check_fail;
1233 /* be paranoid, if told so */
1234 if (CURCLASS_FLAGS_ISSET(checkportcmd)) {
1235 #ifdef INET6
1237 * be paranoid, there are getnameinfo implementation that does
1238 * not present scopeid portion
1240 if (data_dest.su_family == AF_INET6 &&
1241 data_dest.su_scope_id != his_addr.su_scope_id)
1242 goto port_check_fail;
1243 #endif
1245 if (getnameinfo((struct sockaddr *)&data_dest, data_dest.su_len,
1246 h1, sizeof(h1), s1, sizeof(s1), niflags))
1247 goto port_check_fail;
1248 if (getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
1249 h2, sizeof(h2), s2, sizeof(s2), niflags))
1250 goto port_check_fail;
1252 if (atoi(s1) < IPPORT_RESERVED || strcmp(h1, h2) != 0)
1253 goto port_check_fail;
1256 usedefault = 0;
1257 if (pdata >= 0) {
1258 (void) close(pdata);
1259 pdata = -1;
1261 reply(200, "%s command successful.", cmd);
1263 #line 1263 "ftpcmd.c"
1265 #if YYDEBUG
1266 #include <stdio.h> /* needed for printf */
1267 #endif
1269 #include <stdlib.h> /* needed for malloc, etc */
1270 #include <string.h> /* needed for memset */
1272 /* allocate initial stack or double stack size, up to YYMAXDEPTH */
1273 static int yygrowstack(YYSTACKDATA *data)
1275 int i;
1276 unsigned newsize;
1277 short *newss;
1278 YYSTYPE *newvs;
1280 if ((newsize = data->stacksize) == 0)
1281 newsize = YYINITSTACKSIZE;
1282 else if (newsize >= YYMAXDEPTH)
1283 return -1;
1284 else if ((newsize *= 2) > YYMAXDEPTH)
1285 newsize = YYMAXDEPTH;
1287 i = data->s_mark - data->s_base;
1288 newss = (short *)realloc(data->s_base, newsize * sizeof(*newss));
1289 if (newss == 0)
1290 return -1;
1292 data->s_base = newss;
1293 data->s_mark = newss + i;
1295 newvs = (YYSTYPE *)realloc(data->l_base, newsize * sizeof(*newvs));
1296 if (newvs == 0)
1297 return -1;
1299 data->l_base = newvs;
1300 data->l_mark = newvs + i;
1302 data->stacksize = newsize;
1303 data->s_last = data->s_base + newsize - 1;
1304 return 0;
1307 #if YYPURE || defined(YY_NO_LEAKS)
1308 static void yyfreestack(YYSTACKDATA *data)
1310 free(data->s_base);
1311 free(data->l_base);
1312 memset(data, 0, sizeof(*data));
1314 #else
1315 #define yyfreestack(data) /* nothing */
1316 #endif
1318 #define YYABORT goto yyabort
1319 #define YYREJECT goto yyabort
1320 #define YYACCEPT goto yyaccept
1321 #define YYERROR goto yyerrlab
1324 YYPARSE_DECL()
1326 int yym, yyn, yystate;
1327 #if YYDEBUG
1328 const char *yys;
1330 if ((yys = getenv("YYDEBUG")) != 0)
1332 yyn = *yys;
1333 if (yyn >= '0' && yyn <= '9')
1334 yydebug = yyn - '0';
1336 #endif
1338 yynerrs = 0;
1339 yyerrflag = 0;
1340 yychar = YYEMPTY;
1341 yystate = 0;
1343 #if YYPURE
1344 memset(&yystack, 0, sizeof(yystack));
1345 #endif
1347 if (yystack.s_base == NULL && yygrowstack(&yystack)) goto yyoverflow;
1348 yystack.s_mark = yystack.s_base;
1349 yystack.l_mark = yystack.l_base;
1350 yystate = 0;
1351 *yystack.s_mark = 0;
1353 yyloop:
1354 if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
1355 if (yychar < 0)
1357 if ((yychar = YYLEX) < 0) yychar = 0;
1358 #if YYDEBUG
1359 if (yydebug)
1361 yys = 0;
1362 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1363 if (!yys) yys = "illegal-symbol";
1364 printf("%sdebug: state %d, reading %d (%s)\n",
1365 YYPREFIX, yystate, yychar, yys);
1367 #endif
1369 if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
1370 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1372 #if YYDEBUG
1373 if (yydebug)
1374 printf("%sdebug: state %d, shifting to state %d\n",
1375 YYPREFIX, yystate, yytable[yyn]);
1376 #endif
1377 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1379 goto yyoverflow;
1381 yystate = yytable[yyn];
1382 *++yystack.s_mark = yytable[yyn];
1383 *++yystack.l_mark = yylval;
1384 yychar = YYEMPTY;
1385 if (yyerrflag > 0) --yyerrflag;
1386 goto yyloop;
1388 if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
1389 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
1391 yyn = yytable[yyn];
1392 goto yyreduce;
1394 if (yyerrflag) goto yyinrecovery;
1396 yyerror("syntax error");
1398 goto yyerrlab;
1400 yyerrlab:
1401 ++yynerrs;
1403 yyinrecovery:
1404 if (yyerrflag < 3)
1406 yyerrflag = 3;
1407 for (;;)
1409 if ((yyn = yysindex[*yystack.s_mark]) && (yyn += YYERRCODE) >= 0 &&
1410 yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
1412 #if YYDEBUG
1413 if (yydebug)
1414 printf("%sdebug: state %d, error recovery shifting\
1415 to state %d\n", YYPREFIX, *yystack.s_mark, yytable[yyn]);
1416 #endif
1417 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
1419 goto yyoverflow;
1421 yystate = yytable[yyn];
1422 *++yystack.s_mark = yytable[yyn];
1423 *++yystack.l_mark = yylval;
1424 goto yyloop;
1426 else
1428 #if YYDEBUG
1429 if (yydebug)
1430 printf("%sdebug: error recovery discarding state %d\n",
1431 YYPREFIX, *yystack.s_mark);
1432 #endif
1433 if (yystack.s_mark <= yystack.s_base) goto yyabort;
1434 --yystack.s_mark;
1435 --yystack.l_mark;
1439 else
1441 if (yychar == 0) goto yyabort;
1442 #if YYDEBUG
1443 if (yydebug)
1445 yys = 0;
1446 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1447 if (!yys) yys = "illegal-symbol";
1448 printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
1449 YYPREFIX, yystate, yychar, yys);
1451 #endif
1452 yychar = YYEMPTY;
1453 goto yyloop;
1456 yyreduce:
1457 #if YYDEBUG
1458 if (yydebug)
1459 printf("%sdebug: state %d, reducing by rule %d (%s)\n",
1460 YYPREFIX, yystate, yyn, yyrule[yyn]);
1461 #endif
1462 yym = yylen[yyn];
1463 if (yym)
1464 yyval = yystack.l_mark[1-yym];
1465 else
1466 memset(&yyval, 0, sizeof yyval);
1467 switch (yyn)
1469 case 1:
1470 #line 176 "ftpcmd.y"
1472 REASSIGN(fromname, NULL);
1473 restart_point = (off_t) 0;
1475 break;
1476 case 3:
1477 #line 188 "ftpcmd.y"
1479 user(yystack.l_mark[-1].s);
1480 free(yystack.l_mark[-1].s);
1482 break;
1483 case 4:
1484 #line 194 "ftpcmd.y"
1486 pass(yystack.l_mark[-1].s);
1487 memset(yystack.l_mark[-1].s, 0, strlen(yystack.l_mark[-1].s));
1488 free(yystack.l_mark[-1].s);
1490 break;
1491 case 5:
1492 #line 201 "ftpcmd.y"
1494 if (yystack.l_mark[-1].u.i)
1495 cwd(homedir);
1497 break;
1498 case 6:
1499 #line 207 "ftpcmd.y"
1501 if (yystack.l_mark[-3].u.i && yystack.l_mark[-1].s != NULL)
1502 cwd(yystack.l_mark[-1].s);
1503 if (yystack.l_mark[-1].s != NULL)
1504 free(yystack.l_mark[-1].s);
1506 break;
1507 case 7:
1508 #line 215 "ftpcmd.y"
1510 if (yystack.l_mark[-1].u.i)
1511 cwd("..");
1513 break;
1514 case 8:
1515 #line 221 "ftpcmd.y"
1517 if (logged_in) {
1518 reply(-221, "%s", "");
1519 reply(0,
1520 "Data traffic for this session was " LLF " byte%s in " LLF " file%s.",
1521 (LLT)total_data, PLURAL(total_data),
1522 (LLT)total_files, PLURAL(total_files));
1523 reply(0,
1524 "Total traffic for this session was " LLF " byte%s in " LLF " transfer%s.",
1525 (LLT)total_bytes, PLURAL(total_bytes),
1526 (LLT)total_xfers, PLURAL(total_xfers));
1528 reply(221,
1529 "Thank you for using the FTP service on %s.",
1530 hostname);
1531 if (logged_in && logging) {
1532 syslog(LOG_INFO,
1533 "Data traffic: " LLF " byte%s in " LLF " file%s",
1534 (LLT)total_data, PLURAL(total_data),
1535 (LLT)total_files, PLURAL(total_files));
1536 syslog(LOG_INFO,
1537 "Total traffic: " LLF " byte%s in " LLF " transfer%s",
1538 (LLT)total_bytes, PLURAL(total_bytes),
1539 (LLT)total_xfers, PLURAL(total_xfers));
1542 dologout(0);
1544 break;
1545 case 9:
1546 #line 251 "ftpcmd.y"
1548 if (yystack.l_mark[-3].u.i)
1549 port_check("PORT", AF_INET);
1551 break;
1552 case 10:
1553 #line 257 "ftpcmd.y"
1555 if (yystack.l_mark[-3].u.i)
1556 port_check("LPRT", AF_INET);
1558 break;
1559 case 11:
1560 #line 263 "ftpcmd.y"
1562 #ifdef INET6
1563 if (yystack.l_mark[-3].u.i)
1564 port_check("LPRT", AF_INET6);
1565 #else
1566 reply(500, "IPv6 support not available.");
1567 #endif
1569 break;
1570 case 12:
1571 #line 273 "ftpcmd.y"
1573 if (yystack.l_mark[-3].u.i) {
1574 if (extended_port(yystack.l_mark[-1].s) == 0)
1575 port_check("EPRT", -1);
1577 free(yystack.l_mark[-1].s);
1579 break;
1580 case 13:
1581 #line 282 "ftpcmd.y"
1583 if (yystack.l_mark[-1].u.i) {
1584 if (CURCLASS_FLAGS_ISSET(passive))
1585 passive();
1586 else
1587 reply(500, "PASV mode not available.");
1590 break;
1591 case 14:
1592 #line 292 "ftpcmd.y"
1594 if (yystack.l_mark[-1].u.i) {
1595 if (CURCLASS_FLAGS_ISSET(passive)) {
1596 if (epsvall)
1597 reply(501,
1598 "LPSV disallowed after EPSV ALL");
1599 else
1600 long_passive("LPSV", PF_UNSPEC);
1601 } else
1602 reply(500, "LPSV mode not available.");
1605 break;
1606 case 15:
1607 #line 306 "ftpcmd.y"
1609 if (yystack.l_mark[-3].u.i) {
1610 if (CURCLASS_FLAGS_ISSET(passive))
1611 long_passive("EPSV",
1612 epsvproto2af(yystack.l_mark[-1].u.i));
1613 else
1614 reply(500, "EPSV mode not available.");
1617 break;
1618 case 16:
1619 #line 317 "ftpcmd.y"
1621 if (yystack.l_mark[-3].u.i) {
1622 if (CURCLASS_FLAGS_ISSET(passive)) {
1623 reply(200,
1624 "EPSV ALL command successful.");
1625 epsvall++;
1626 } else
1627 reply(500, "EPSV mode not available.");
1630 break;
1631 case 17:
1632 #line 329 "ftpcmd.y"
1634 if (yystack.l_mark[-1].u.i) {
1635 if (CURCLASS_FLAGS_ISSET(passive))
1636 long_passive("EPSV", PF_UNSPEC);
1637 else
1638 reply(500, "EPSV mode not available.");
1641 break;
1642 case 18:
1643 #line 339 "ftpcmd.y"
1645 if (yystack.l_mark[-3].u.i) {
1647 switch (cmd_type) {
1649 case TYPE_A:
1650 if (cmd_form == FORM_N) {
1651 reply(200, "Type set to A.");
1652 type = cmd_type;
1653 form = cmd_form;
1654 } else
1655 reply(504, "Form must be N.");
1656 break;
1658 case TYPE_E:
1659 reply(504, "Type E not implemented.");
1660 break;
1662 case TYPE_I:
1663 reply(200, "Type set to I.");
1664 type = cmd_type;
1665 break;
1667 case TYPE_L:
1668 #if NBBY == 8
1669 if (cmd_bytesz == 8) {
1670 reply(200,
1671 "Type set to L (byte size 8).");
1672 type = cmd_type;
1673 } else
1674 reply(504, "Byte size must be 8.");
1675 #else /* NBBY == 8 */
1676 UNIMPLEMENTED for NBBY != 8
1677 #endif /* NBBY == 8 */
1682 break;
1683 case 19:
1684 #line 379 "ftpcmd.y"
1686 if (yystack.l_mark[-3].u.i) {
1687 switch (yystack.l_mark[-1].u.i) {
1689 case STRU_F:
1690 reply(200, "STRU F ok.");
1691 break;
1693 default:
1694 reply(504, "Unimplemented STRU type.");
1698 break;
1699 case 20:
1700 #line 394 "ftpcmd.y"
1702 if (yystack.l_mark[-3].u.i) {
1703 switch (yystack.l_mark[-1].u.i) {
1705 case MODE_S:
1706 reply(200, "MODE S ok.");
1707 break;
1709 default:
1710 reply(502, "Unimplemented MODE type.");
1714 break;
1715 case 21:
1716 #line 409 "ftpcmd.y"
1718 if (yystack.l_mark[-3].u.i && yystack.l_mark[-1].s != NULL)
1719 retrieve(NULL, yystack.l_mark[-1].s);
1720 if (yystack.l_mark[-1].s != NULL)
1721 free(yystack.l_mark[-1].s);
1723 break;
1724 case 22:
1725 #line 417 "ftpcmd.y"
1727 if (check_write(yystack.l_mark[-1].s, 1))
1728 store(yystack.l_mark[-1].s, "w", 0);
1729 if (yystack.l_mark[-1].s != NULL)
1730 free(yystack.l_mark[-1].s);
1732 break;
1733 case 23:
1734 #line 425 "ftpcmd.y"
1736 if (check_write(yystack.l_mark[-1].s, 1))
1737 store(yystack.l_mark[-1].s, "w", 1);
1738 if (yystack.l_mark[-1].s != NULL)
1739 free(yystack.l_mark[-1].s);
1741 break;
1742 case 24:
1743 #line 433 "ftpcmd.y"
1745 if (check_write(yystack.l_mark[-1].s, 1))
1746 store(yystack.l_mark[-1].s, "a", 0);
1747 if (yystack.l_mark[-1].s != NULL)
1748 free(yystack.l_mark[-1].s);
1750 break;
1751 case 25:
1752 #line 441 "ftpcmd.y"
1754 if (yystack.l_mark[-3].u.i)
1755 reply(202, "ALLO command ignored.");
1757 break;
1758 case 26:
1759 #line 447 "ftpcmd.y"
1761 if (yystack.l_mark[-7].u.i)
1762 reply(202, "ALLO command ignored.");
1764 break;
1765 case 27:
1766 #line 453 "ftpcmd.y"
1768 if (check_write(yystack.l_mark[-1].s, 0)) {
1769 if (fromname) {
1770 renamecmd(fromname, yystack.l_mark[-1].s);
1771 REASSIGN(fromname, NULL);
1772 } else {
1773 reply(503, "Bad sequence of commands.");
1776 if (yystack.l_mark[-1].s != NULL)
1777 free(yystack.l_mark[-1].s);
1779 break;
1780 case 28:
1781 #line 467 "ftpcmd.y"
1783 if (is_oob)
1784 abor();
1785 else if (yystack.l_mark[-1].u.i)
1786 reply(225, "ABOR command successful.");
1788 break;
1789 case 29:
1790 #line 475 "ftpcmd.y"
1792 if (check_write(yystack.l_mark[-1].s, 0))
1793 delete(yystack.l_mark[-1].s);
1794 if (yystack.l_mark[-1].s != NULL)
1795 free(yystack.l_mark[-1].s);
1797 break;
1798 case 30:
1799 #line 483 "ftpcmd.y"
1801 if (check_write(yystack.l_mark[-1].s, 0))
1802 removedir(yystack.l_mark[-1].s);
1803 if (yystack.l_mark[-1].s != NULL)
1804 free(yystack.l_mark[-1].s);
1806 break;
1807 case 31:
1808 #line 491 "ftpcmd.y"
1810 if (check_write(yystack.l_mark[-1].s, 0))
1811 makedir(yystack.l_mark[-1].s);
1812 if (yystack.l_mark[-1].s != NULL)
1813 free(yystack.l_mark[-1].s);
1815 break;
1816 case 32:
1817 #line 499 "ftpcmd.y"
1819 if (yystack.l_mark[-1].u.i)
1820 pwd();
1822 break;
1823 case 33:
1824 #line 505 "ftpcmd.y"
1826 const char *argv[] = { INTERNAL_LS, "-lgA", NULL };
1828 if (CURCLASS_FLAGS_ISSET(hidesymlinks))
1829 argv[1] = "-LlgA";
1830 if (yystack.l_mark[-1].u.i)
1831 retrieve(argv, "");
1833 break;
1834 case 34:
1835 #line 515 "ftpcmd.y"
1837 const char *argv[] = { INTERNAL_LS, "-lgA", NULL, NULL };
1839 if (CURCLASS_FLAGS_ISSET(hidesymlinks))
1840 argv[1] = "-LlgA";
1841 if (yystack.l_mark[-3].u.i && yystack.l_mark[-1].s != NULL) {
1842 argv[2] = yystack.l_mark[-1].s;
1843 retrieve(argv, yystack.l_mark[-1].s);
1845 if (yystack.l_mark[-1].s != NULL)
1846 free(yystack.l_mark[-1].s);
1848 break;
1849 case 35:
1850 #line 529 "ftpcmd.y"
1852 if (yystack.l_mark[-1].u.i)
1853 send_file_list(".");
1855 break;
1856 case 36:
1857 #line 535 "ftpcmd.y"
1859 if (yystack.l_mark[-3].u.i)
1860 send_file_list(yystack.l_mark[-1].s);
1861 free(yystack.l_mark[-1].s);
1863 break;
1864 case 37:
1865 #line 542 "ftpcmd.y"
1867 help(sitetab, NULL);
1869 break;
1870 case 38:
1871 #line 547 "ftpcmd.y"
1873 if (check_write(yystack.l_mark[-1].s, 0)) {
1874 if ((yystack.l_mark[-3].u.i == -1) || (yystack.l_mark[-3].u.i > 0777))
1875 reply(501,
1876 "CHMOD: Mode value must be between 0 and 0777");
1877 else if (chmod(yystack.l_mark[-1].s, yystack.l_mark[-3].u.i) < 0)
1878 perror_reply(550, yystack.l_mark[-1].s);
1879 else
1880 reply(200, "CHMOD command successful.");
1882 if (yystack.l_mark[-1].s != NULL)
1883 free(yystack.l_mark[-1].s);
1885 break;
1886 case 39:
1887 #line 562 "ftpcmd.y"
1889 help(sitetab, yystack.l_mark[-1].s);
1890 free(yystack.l_mark[-1].s);
1892 break;
1893 case 40:
1894 #line 568 "ftpcmd.y"
1896 if (yystack.l_mark[-1].u.i) {
1897 reply(200,
1898 "Current IDLE time limit is " LLF
1899 " seconds; max " LLF,
1900 (LLT)curclass.timeout,
1901 (LLT)curclass.maxtimeout);
1904 break;
1905 case 41:
1906 #line 579 "ftpcmd.y"
1908 if (yystack.l_mark[-3].u.i) {
1909 if (yystack.l_mark[-1].u.i < 30 || yystack.l_mark[-1].u.i > curclass.maxtimeout) {
1910 reply(501,
1911 "IDLE time limit must be between 30 and "
1912 LLF " seconds",
1913 (LLT)curclass.maxtimeout);
1914 } else {
1915 curclass.timeout = yystack.l_mark[-1].u.i;
1916 (void) alarm(curclass.timeout);
1917 reply(200,
1918 "IDLE time limit set to "
1919 LLF " seconds",
1920 (LLT)curclass.timeout);
1924 break;
1925 case 42:
1926 #line 598 "ftpcmd.y"
1928 if (yystack.l_mark[-1].u.i) {
1929 reply(200,
1930 "Current RATEGET is " LLF " bytes/sec",
1931 (LLT)curclass.rateget);
1934 break;
1935 case 43:
1936 #line 607 "ftpcmd.y"
1938 char errbuf[100];
1939 char *p = yystack.l_mark[-1].s;
1940 LLT rate;
1942 if (yystack.l_mark[-3].u.i) {
1943 rate = strsuftollx("RATEGET", p, 0,
1944 curclass.maxrateget
1945 ? curclass.maxrateget
1946 : LLTMAX, errbuf, sizeof(errbuf));
1947 if (errbuf[0])
1948 reply(501, "%s", errbuf);
1949 else {
1950 curclass.rateget = rate;
1951 reply(200,
1952 "RATEGET set to " LLF " bytes/sec",
1953 (LLT)curclass.rateget);
1956 free(yystack.l_mark[-1].s);
1958 break;
1959 case 44:
1960 #line 630 "ftpcmd.y"
1962 if (yystack.l_mark[-1].u.i) {
1963 reply(200,
1964 "Current RATEPUT is " LLF " bytes/sec",
1965 (LLT)curclass.rateput);
1968 break;
1969 case 45:
1970 #line 639 "ftpcmd.y"
1972 char errbuf[100];
1973 char *p = yystack.l_mark[-1].s;
1974 LLT rate;
1976 if (yystack.l_mark[-3].u.i) {
1977 rate = strsuftollx("RATEPUT", p, 0,
1978 curclass.maxrateput
1979 ? curclass.maxrateput
1980 : LLTMAX, errbuf, sizeof(errbuf));
1981 if (errbuf[0])
1982 reply(501, "%s", errbuf);
1983 else {
1984 curclass.rateput = rate;
1985 reply(200,
1986 "RATEPUT set to " LLF " bytes/sec",
1987 (LLT)curclass.rateput);
1990 free(yystack.l_mark[-1].s);
1992 break;
1993 case 46:
1994 #line 662 "ftpcmd.y"
1996 int oldmask;
1998 if (yystack.l_mark[-1].u.i) {
1999 oldmask = umask(0);
2000 (void) umask(oldmask);
2001 reply(200, "Current UMASK is %03o", oldmask);
2004 break;
2005 case 47:
2006 #line 673 "ftpcmd.y"
2008 int oldmask;
2010 if (yystack.l_mark[-3].u.i && check_write("", 0)) {
2011 if ((yystack.l_mark[-1].u.i == -1) || (yystack.l_mark[-1].u.i > 0777)) {
2012 reply(501, "Bad UMASK value");
2013 } else {
2014 oldmask = umask(yystack.l_mark[-1].u.i);
2015 reply(200,
2016 "UMASK set to %03o (was %03o)",
2017 yystack.l_mark[-1].u.i, oldmask);
2021 break;
2022 case 48:
2023 #line 689 "ftpcmd.y"
2025 if (EMPTYSTR(version))
2026 reply(215, "UNIX Type: L%d", NBBY);
2027 else
2028 reply(215, "UNIX Type: L%d Version: %s", NBBY,
2029 version);
2031 break;
2032 case 49:
2033 #line 698 "ftpcmd.y"
2035 if (yystack.l_mark[-3].u.i && yystack.l_mark[-1].s != NULL)
2036 statfilecmd(yystack.l_mark[-1].s);
2037 if (yystack.l_mark[-1].s != NULL)
2038 free(yystack.l_mark[-1].s);
2040 break;
2041 case 50:
2042 #line 706 "ftpcmd.y"
2044 if (is_oob)
2045 statxfer();
2046 else
2047 statcmd();
2049 break;
2050 case 51:
2051 #line 714 "ftpcmd.y"
2053 help(cmdtab, NULL);
2055 break;
2056 case 52:
2057 #line 719 "ftpcmd.y"
2059 char *cp = yystack.l_mark[-1].s;
2061 if (strncasecmp(cp, "SITE", 4) == 0) {
2062 cp = yystack.l_mark[-1].s + 4;
2063 if (*cp == ' ')
2064 cp++;
2065 if (*cp)
2066 help(sitetab, cp);
2067 else
2068 help(sitetab, NULL);
2069 } else
2070 help(cmdtab, yystack.l_mark[-1].s);
2071 free(yystack.l_mark[-1].s);
2073 break;
2074 case 53:
2075 #line 736 "ftpcmd.y"
2077 reply(200, "NOOP command successful.");
2079 break;
2080 case 54:
2081 #line 742 "ftpcmd.y"
2083 reply(502, "RFC 2228 authentication not implemented.");
2084 free(yystack.l_mark[-1].s);
2086 break;
2087 case 55:
2088 #line 748 "ftpcmd.y"
2090 reply(503,
2091 "Please set authentication state with AUTH.");
2092 free(yystack.l_mark[-1].s);
2094 break;
2095 case 56:
2096 #line 755 "ftpcmd.y"
2098 reply(503,
2099 "Please set protection buffer size with PBSZ.");
2100 free(yystack.l_mark[-1].s);
2102 break;
2103 case 57:
2104 #line 762 "ftpcmd.y"
2106 reply(503,
2107 "Please set authentication state with AUTH.");
2109 break;
2110 case 58:
2111 #line 768 "ftpcmd.y"
2113 reply(533, "No protection enabled.");
2115 break;
2116 case 59:
2117 #line 773 "ftpcmd.y"
2119 reply(502, "RFC 2228 authentication not implemented.");
2120 free(yystack.l_mark[-1].s);
2122 break;
2123 case 60:
2124 #line 779 "ftpcmd.y"
2126 reply(502, "RFC 2228 authentication not implemented.");
2127 free(yystack.l_mark[-1].s);
2129 break;
2130 case 61:
2131 #line 785 "ftpcmd.y"
2133 reply(502, "RFC 2228 authentication not implemented.");
2134 free(yystack.l_mark[-1].s);
2136 break;
2137 case 62:
2138 #line 792 "ftpcmd.y"
2141 feat();
2143 break;
2144 case 63:
2145 #line 798 "ftpcmd.y"
2148 opts(yystack.l_mark[-1].s);
2149 free(yystack.l_mark[-1].s);
2151 break;
2152 case 64:
2153 #line 812 "ftpcmd.y"
2155 if (yystack.l_mark[-3].u.i && yystack.l_mark[-1].s != NULL)
2156 sizecmd(yystack.l_mark[-1].s);
2157 if (yystack.l_mark[-1].s != NULL)
2158 free(yystack.l_mark[-1].s);
2160 break;
2161 case 65:
2162 #line 826 "ftpcmd.y"
2164 if (yystack.l_mark[-3].u.i && yystack.l_mark[-1].s != NULL) {
2165 struct stat stbuf;
2166 if (stat(yystack.l_mark[-1].s, &stbuf) < 0)
2167 perror_reply(550, yystack.l_mark[-1].s);
2168 else if (!S_ISREG(stbuf.st_mode)) {
2169 reply(550, "%s: not a plain file.", yystack.l_mark[-1].s);
2170 } else {
2171 struct tm *t;
2173 t = gmtime(&stbuf.st_mtime);
2174 reply(213,
2175 "%04d%02d%02d%02d%02d%02d",
2176 TM_YEAR_BASE + t->tm_year,
2177 t->tm_mon+1, t->tm_mday,
2178 t->tm_hour, t->tm_min, t->tm_sec);
2181 if (yystack.l_mark[-1].s != NULL)
2182 free(yystack.l_mark[-1].s);
2184 break;
2185 case 66:
2186 #line 849 "ftpcmd.y"
2188 if (yystack.l_mark[-3].u.i && yystack.l_mark[-1].s != NULL)
2189 mlst(yystack.l_mark[-1].s);
2190 if (yystack.l_mark[-1].s != NULL)
2191 free(yystack.l_mark[-1].s);
2193 break;
2194 case 67:
2195 #line 857 "ftpcmd.y"
2197 mlst(NULL);
2199 break;
2200 case 68:
2201 #line 862 "ftpcmd.y"
2203 if (yystack.l_mark[-3].u.i && yystack.l_mark[-1].s != NULL)
2204 mlsd(yystack.l_mark[-1].s);
2205 if (yystack.l_mark[-1].s != NULL)
2206 free(yystack.l_mark[-1].s);
2208 break;
2209 case 69:
2210 #line 870 "ftpcmd.y"
2212 mlsd(NULL);
2214 break;
2215 case 70:
2216 #line 875 "ftpcmd.y"
2218 yyerrok;
2220 break;
2221 case 71:
2222 #line 882 "ftpcmd.y"
2224 if (yystack.l_mark[-3].u.i) {
2225 REASSIGN(fromname, NULL);
2226 restart_point = (off_t)yystack.l_mark[-1].u.ll;
2227 reply(350,
2228 "Restarting at " LLF ". Send STORE or RETRIEVE to initiate transfer.",
2229 (LLT)restart_point);
2232 break;
2233 case 72:
2234 #line 893 "ftpcmd.y"
2236 restart_point = (off_t) 0;
2237 if (check_write(yystack.l_mark[-1].s, 0)) {
2238 REASSIGN(fromname, NULL);
2239 fromname = renamefrom(yystack.l_mark[-1].s);
2241 if (yystack.l_mark[-1].s != NULL)
2242 free(yystack.l_mark[-1].s);
2244 break;
2245 case 74:
2246 #line 910 "ftpcmd.y"
2248 yyval.s = (char *)calloc(1, sizeof(char));
2250 break;
2251 case 76:
2252 #line 919 "ftpcmd.y"
2254 yyval.u.i = yystack.l_mark[0].u.i;
2256 break;
2257 case 77:
2258 #line 927 "ftpcmd.y"
2260 char *a, *p;
2262 memset(&data_dest, 0, sizeof(data_dest));
2263 data_dest.su_len = sizeof(struct sockaddr_in);
2264 data_dest.su_family = AF_INET;
2265 p = (char *)&data_dest.su_port;
2266 p[0] = yystack.l_mark[-2].u.i; p[1] = yystack.l_mark[0].u.i;
2267 a = (char *)&data_dest.su_addr;
2268 a[0] = yystack.l_mark[-10].u.i; a[1] = yystack.l_mark[-8].u.i; a[2] = yystack.l_mark[-6].u.i; a[3] = yystack.l_mark[-4].u.i;
2270 break;
2271 case 78:
2272 #line 944 "ftpcmd.y"
2274 char *a, *p;
2276 memset(&data_dest, 0, sizeof(data_dest));
2277 data_dest.su_len = sizeof(struct sockaddr_in);
2278 data_dest.su_family = AF_INET;
2279 p = (char *)&data_dest.su_port;
2280 p[0] = yystack.l_mark[-2].u.i; p[1] = yystack.l_mark[0].u.i;
2281 a = (char *)&data_dest.su_addr;
2282 a[0] = yystack.l_mark[-12].u.i; a[1] = yystack.l_mark[-10].u.i; a[2] = yystack.l_mark[-8].u.i; a[3] = yystack.l_mark[-6].u.i;
2284 /* reject invalid LPRT command */
2285 if (yystack.l_mark[-16].u.i != 4 || yystack.l_mark[-14].u.i != 4 || yystack.l_mark[-4].u.i != 2)
2286 memset(&data_dest, 0, sizeof(data_dest));
2288 break;
2289 case 79:
2290 #line 968 "ftpcmd.y"
2292 #ifdef INET6
2293 unsigned char buf[16];
2295 (void)memset(&data_dest, 0, sizeof(data_dest));
2296 data_dest.su_len = sizeof(struct sockaddr_in6);
2297 data_dest.su_family = AF_INET6;
2298 buf[0] = yystack.l_mark[-2].u.i; buf[1] = yystack.l_mark[0].u.i;
2299 (void)memcpy(&data_dest.su_port, buf,
2300 sizeof(data_dest.su_port));
2301 buf[0] = yystack.l_mark[-36].u.i; buf[1] = yystack.l_mark[-34].u.i;
2302 buf[2] = yystack.l_mark[-32].u.i; buf[3] = yystack.l_mark[-30].u.i;
2303 buf[4] = yystack.l_mark[-28].u.i; buf[5] = yystack.l_mark[-26].u.i;
2304 buf[6] = yystack.l_mark[-24].u.i; buf[7] = yystack.l_mark[-22].u.i;
2305 buf[8] = yystack.l_mark[-20].u.i; buf[9] = yystack.l_mark[-18].u.i;
2306 buf[10] = yystack.l_mark[-16].u.i; buf[11] = yystack.l_mark[-14].u.i;
2307 buf[12] = yystack.l_mark[-12].u.i; buf[13] = yystack.l_mark[-10].u.i;
2308 buf[14] = yystack.l_mark[-8].u.i; buf[15] = yystack.l_mark[-6].u.i;
2309 (void)memcpy(&data_dest.si_su.su_sin6.sin6_addr,
2310 buf, sizeof(data_dest.si_su.su_sin6.sin6_addr));
2311 if (his_addr.su_family == AF_INET6) {
2312 /* XXX: more sanity checks! */
2313 data_dest.su_scope_id = his_addr.su_scope_id;
2315 #else
2316 memset(&data_dest, 0, sizeof(data_dest));
2317 #endif /* INET6 */
2318 /* reject invalid LPRT command */
2319 if (yystack.l_mark[-40].u.i != 6 || yystack.l_mark[-38].u.i != 16 || yystack.l_mark[-4].u.i != 2)
2320 memset(&data_dest, 0, sizeof(data_dest));
2322 break;
2323 case 80:
2324 #line 1003 "ftpcmd.y"
2326 yyval.u.i = FORM_N;
2328 break;
2329 case 81:
2330 #line 1008 "ftpcmd.y"
2332 yyval.u.i = FORM_T;
2334 break;
2335 case 82:
2336 #line 1013 "ftpcmd.y"
2338 yyval.u.i = FORM_C;
2340 break;
2341 case 83:
2342 #line 1020 "ftpcmd.y"
2344 cmd_type = TYPE_A;
2345 cmd_form = FORM_N;
2347 break;
2348 case 84:
2349 #line 1026 "ftpcmd.y"
2351 cmd_type = TYPE_A;
2352 cmd_form = yystack.l_mark[0].u.i;
2354 break;
2355 case 85:
2356 #line 1032 "ftpcmd.y"
2358 cmd_type = TYPE_E;
2359 cmd_form = FORM_N;
2361 break;
2362 case 86:
2363 #line 1038 "ftpcmd.y"
2365 cmd_type = TYPE_E;
2366 cmd_form = yystack.l_mark[0].u.i;
2368 break;
2369 case 87:
2370 #line 1044 "ftpcmd.y"
2372 cmd_type = TYPE_I;
2374 break;
2375 case 88:
2376 #line 1049 "ftpcmd.y"
2378 cmd_type = TYPE_L;
2379 cmd_bytesz = NBBY;
2381 break;
2382 case 89:
2383 #line 1055 "ftpcmd.y"
2385 cmd_type = TYPE_L;
2386 cmd_bytesz = yystack.l_mark[0].u.i;
2388 break;
2389 case 90:
2390 #line 1062 "ftpcmd.y"
2392 cmd_type = TYPE_L;
2393 cmd_bytesz = yystack.l_mark[0].u.i;
2395 break;
2396 case 91:
2397 #line 1070 "ftpcmd.y"
2399 yyval.u.i = STRU_F;
2401 break;
2402 case 92:
2403 #line 1075 "ftpcmd.y"
2405 yyval.u.i = STRU_R;
2407 break;
2408 case 93:
2409 #line 1080 "ftpcmd.y"
2411 yyval.u.i = STRU_P;
2413 break;
2414 case 94:
2415 #line 1087 "ftpcmd.y"
2417 yyval.u.i = MODE_S;
2419 break;
2420 case 95:
2421 #line 1092 "ftpcmd.y"
2423 yyval.u.i = MODE_B;
2425 break;
2426 case 96:
2427 #line 1097 "ftpcmd.y"
2429 yyval.u.i = MODE_C;
2431 break;
2432 case 97:
2433 #line 1104 "ftpcmd.y"
2436 * Problem: this production is used for all pathname
2437 * processing, but only gives a 550 error reply.
2438 * This is a valid reply in some cases but not in
2439 * others.
2441 if (logged_in && yystack.l_mark[0].s && *yystack.l_mark[0].s == '~') {
2442 char *path, *home, *result;
2443 size_t len;
2445 path = strchr(yystack.l_mark[0].s + 1, '/');
2446 if (path != NULL)
2447 *path++ = '\0';
2448 if (yystack.l_mark[0].s[1] == '\0')
2449 home = homedir;
2450 else {
2451 struct passwd *hpw;
2453 if ((hpw = getpwnam(yystack.l_mark[0].s + 1)) != NULL)
2454 home = hpw->pw_dir;
2455 else
2456 home = yystack.l_mark[0].s;
2458 len = strlen(home) + 1;
2459 if (path != NULL)
2460 len += strlen(path) + 1;
2461 if ((result = malloc(len)) == NULL)
2462 fatal("Local resource failure: malloc");
2463 strlcpy(result, home, len);
2464 if (path != NULL) {
2465 strlcat(result, "/", len);
2466 strlcat(result, path, len);
2468 yyval.s = result;
2469 free(yystack.l_mark[0].s);
2470 } else
2471 yyval.s = yystack.l_mark[0].s;
2473 break;
2474 case 99:
2475 #line 1151 "ftpcmd.y"
2477 int ret, dec, multby, digit;
2480 * Convert a number that was read as decimal number
2481 * to what it would be if it had been read as octal.
2483 dec = yystack.l_mark[0].u.i;
2484 multby = 1;
2485 ret = 0;
2486 while (dec) {
2487 digit = dec%10;
2488 if (digit > 7) {
2489 ret = -1;
2490 break;
2492 ret += digit * multby;
2493 multby *= 8;
2494 dec /= 10;
2496 yyval.u.i = ret;
2498 break;
2499 case 103:
2500 #line 1189 "ftpcmd.y"
2502 yyval.u.i = yystack.l_mark[0].u.i;
2504 break;
2505 case 104:
2506 #line 1196 "ftpcmd.y"
2508 if (logged_in)
2509 yyval.u.i = 1;
2510 else {
2511 reply(530, "Please login with USER and PASS.");
2512 yyval.u.i = 0;
2513 hasyyerrored = 1;
2516 break;
2517 #line 2517 "ftpcmd.c"
2519 yystack.s_mark -= yym;
2520 yystate = *yystack.s_mark;
2521 yystack.l_mark -= yym;
2522 yym = yylhs[yyn];
2523 if (yystate == 0 && yym == 0)
2525 #if YYDEBUG
2526 if (yydebug)
2527 printf("%sdebug: after reduction, shifting from state 0 to\
2528 state %d\n", YYPREFIX, YYFINAL);
2529 #endif
2530 yystate = YYFINAL;
2531 *++yystack.s_mark = YYFINAL;
2532 *++yystack.l_mark = yyval;
2533 if (yychar < 0)
2535 if ((yychar = YYLEX) < 0) yychar = 0;
2536 #if YYDEBUG
2537 if (yydebug)
2539 yys = 0;
2540 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
2541 if (!yys) yys = "illegal-symbol";
2542 printf("%sdebug: state %d, reading %d (%s)\n",
2543 YYPREFIX, YYFINAL, yychar, yys);
2545 #endif
2547 if (yychar == 0) goto yyaccept;
2548 goto yyloop;
2550 if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
2551 yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
2552 yystate = yytable[yyn];
2553 else
2554 yystate = yydgoto[yym];
2555 #if YYDEBUG
2556 if (yydebug)
2557 printf("%sdebug: after reduction, shifting from state %d \
2558 to state %d\n", YYPREFIX, *yystack.s_mark, yystate);
2559 #endif
2560 if (yystack.s_mark >= yystack.s_last && yygrowstack(&yystack))
2562 goto yyoverflow;
2564 *++yystack.s_mark = (short) yystate;
2565 *++yystack.l_mark = yyval;
2566 goto yyloop;
2568 yyoverflow:
2569 yyerror("yacc stack overflow");
2571 yyabort:
2572 yyfreestack(&yystack);
2573 return (1);
2575 yyaccept:
2576 yyfreestack(&yystack);
2577 return (0);