1 #ifndef lint
2 char yysccsid[] = "@(#)yaccpar 1.3 (Berkeley) 01/21/90";
3 #endif
4 #define A 257
5 #define B 258
6 #define C 259
7 #define E 260
8 #define F 261
9 #define I 262
10 #define L 263
11 #define N 264
12 #define P 265
13 #define R 266
14 #define S 267
15 #define T 268
16 #define SP 269
17 #define CRLF 270
18 #define COMMA 271
19 #define STRING 272
20 #define NUMBER 273
21 #define USER 274
22 #define PASS 275
23 #define ACCT 276
24 #define REIN 277
25 #define QUIT 278
26 #define PORT 279
27 #define PASV 280
28 #define TYPE 281
29 #define STRU 282
30 #define MODE 283
31 #define RETR 284
32 #define STOR 285
33 #define APPE 286
34 #define MLFL 287
35 #define MAIL 288
36 #define MSND 289
37 #define MSOM 290
38 #define MSAM 291
39 #define MRSQ 292
40 #define MRCP 293
41 #define ALLO 294
42 #define REST 295
43 #define RNFR 296
44 #define RNTO 297
45 #define ABOR 298
46 #define DELE 299
47 #define CWD 300
48 #define LIST 301
49 #define NLST 302
50 #define SITE 303
51 #define STAT 304
52 #define HELP 305
53 #define NOOP 306
54 #define MKD 307
55 #define RMD 308
56 #define PWD 309
57 #define CDUP 310
58 #define STOU 311
59 #define SMNT 312
60 #define SYST 313
61 #define SIZE 314
62 #define MDTM 315
63 #define UMASK 316
64 #define IDLE 317
65 #define CHMOD 318
66 #define LEXERR 319
67 #define YYERRCODE 256
68 #line 26 "ftp.y"
69
70 #ifndef lint
71 static char sccsid[] = "@(#)ftpcmd.y 5.20.1.1 (Berkeley) 3/2/89";
72 #endif /* not lint */
73
74 #include <sys/param.h>
75 #include <sys/socket.h>
76
77 #include <netinet/in.h>
78
79 #include <arpa/ftp.h>
80
81 #include <stdio.h>
82 #include <signal.h>
83 #include <ctype.h>
84 #include <pwd.h>
85 #include <setjmp.h>
86 #include <syslog.h>
87 #include <sys/stat.h>
88 #include <time.h>
89
90 extern struct sockaddr_in data_dest;
91 extern int logged_in;
92 extern struct passwd *pw;
93 extern int guest;
94 extern int logging;
95 extern int type;
96 extern int form;
97 extern int debug;
98 extern int timeout;
99 extern int maxtimeout;
100 extern int pdata;
101 extern char hostname[], remotehost[];
102 extern char proctitle[];
103 extern char *globerr;
104 extern int usedefault;
105 extern int transflag;
106 extern char tmpline[];
107 char **glob();
108
109 static int cmd_type;
110 static int cmd_form;
111 static int cmd_bytesz;
112 char cbuf[512];
113 char *fromname;
114
115 char *index();
116 #line 116 "ftp.tab.c"
117 short yylhs[] = { -1,
118 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
119 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
120 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
121 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
122 1, 1, 1, 1, 1, 1, 2, 3, 4, 4,
123 12, 5, 13, 13, 13, 6, 6, 6, 6, 6,
124 6, 6, 6, 7, 7, 7, 8, 8, 8, 10,
125 14, 11, 9,
126 };
127 short yylen[] = { 2,
128 0, 2, 2, 4, 4, 4, 2, 4, 4, 4,
129 4, 8, 5, 5, 5, 3, 5, 3, 5, 5,
130 2, 5, 4, 2, 3, 5, 2, 4, 2, 5,
131 5, 3, 3, 4, 6, 5, 7, 9, 4, 6,
132 5, 2, 5, 5, 2, 2, 5, 1, 0, 1,
133 1, 11, 1, 1, 1, 1, 3, 1, 3, 1,
134 1, 3, 2, 1, 1, 1, 1, 1, 1, 1,
135 1, 1, 0,
136 };
137 short yydefred[] = { 1,
138 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
139 73, 73, 73, 0, 73, 0, 0, 73, 73, 73,
140 73, 0, 0, 0, 0, 73, 73, 73, 73, 73,
141 0, 73, 73, 2, 3, 46, 0, 0, 45, 0,
142 7, 0, 0, 0, 0, 0, 0, 0, 0, 0,
143 24, 0, 0, 0, 0, 0, 21, 0, 0, 27,
144 29, 0, 0, 0, 0, 0, 42, 0, 0, 48,
145 0, 50, 0, 0, 0, 0, 0, 60, 0, 0,
146 64, 66, 65, 0, 68, 69, 67, 0, 0, 0,
147 0, 0, 0, 71, 0, 70, 0, 0, 25, 0,
148 18, 0, 16, 0, 73, 0, 73, 0, 0, 0,
149 0, 32, 33, 0, 0, 0, 4, 5, 0, 6,
150 0, 0, 0, 51, 63, 8, 9, 10, 0, 0,
151 0, 0, 11, 0, 23, 0, 0, 0, 0, 0,
152 34, 0, 0, 39, 0, 0, 28, 0, 0, 0,
153 0, 0, 0, 55, 53, 54, 57, 59, 62, 13,
154 14, 15, 0, 47, 22, 26, 19, 17, 0, 0,
155 36, 0, 0, 20, 30, 31, 41, 43, 44, 0,
156 0, 35, 72, 0, 40, 0, 0, 0, 37, 0,
157 0, 12, 0, 0, 38, 0, 0, 0, 52,
158 };
159 short yydgoto[] = { 1,
160 34, 35, 71, 73, 75, 80, 84, 88, 45, 95,
161 184, 125, 157, 96,
162 };
163 short yysindex[] = { 0,
164 -224, -247, -239, -236, -232, -222, -204, -200, -181, -177,
165 0, 0, 0, -166, 0, -161, -199, 0, 0, 0,
166 0, -160, -159, -264, -158, 0, 0, 0, 0, 0,
167 -157, 0, 0, 0, 0, 0, -167, -162, 0, -156,
168 0, -250, -198, -165, -155, -154, -153, -151, -150, -152,
169 0, -145, -252, -229, -217, -302, 0, -144, -146, 0,
170 0, -142, -141, -140, -139, -137, 0, -136, -135, 0,
171 -134, 0, -133, -132, -130, -131, -128, 0, -249, -127,
172 0, 0, 0, -126, 0, 0, 0, -125, -152, -152,
173 -152, -205, -152, 0, -124, 0, -152, -152, 0, -152,
174 0, -143, 0, -173, 0, -171, 0, -152, -123, -152,
175 -152, 0, 0, -152, -152, -152, 0, 0, -138, 0,
176 -164, -164, -122, 0, 0, 0, 0, 0, -121, -120,
177 -118, -148, 0, -117, 0, -116, -115, -114, -113, -112,
178 0, -163, -111, 0, -110, -109, 0, -107, -106, -105,
179 -104, -103, -129, 0, 0, 0, 0, 0, 0, 0,
180 0, 0, -101, 0, 0, 0, 0, 0, -100, -102,
181 0, -98, -102, 0, 0, 0, 0, 0, 0, -99,
182 -97, 0, 0, -95, 0, -96, -94, -92, 0, -152,
183 -93, 0, -91, -90, 0, -88, -87, -86, 0,
184 };
185 short yyrindex[] = { 0,
186 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
187 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
188 0, 0, -83, 0, 0, 0, 0, 0, 0, 0,
189 0, 0, 0, 0, 0, 0, 0, -82, 0, 0,
190 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
191 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
193 0, 0, 0, 0, 0, -81, -80, 0, -158, 0,
194 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
195 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
196 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
197 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
198 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
199 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
202 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
203 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
204 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
205 0, 0, 0, 0, 0, 0, 0, 0, 0,
206 };
207 short yygindex[] = { 0,
208 0, 0, 0, 0, 0, 0, 0, 0, 16, -89,
209 -25, 35, 47, 0,
210 };
211 #define YYTABLESIZE 190
212 short yytable[] = { 129,
213 130, 131, 104, 134, 59, 60, 76, 136, 137, 77,
214 138, 78, 79, 105, 106, 107, 98, 99, 146, 123,
215 148, 149, 36, 124, 150, 151, 152, 46, 47, 37,
216 49, 2, 38, 52, 53, 54, 55, 39, 58, 100,
217 101, 62, 63, 64, 65, 66, 40, 68, 69, 3,
218 4, 102, 103, 5, 6, 7, 8, 9, 10, 11,
219 12, 13, 81, 132, 133, 41, 82, 83, 42, 14,
220 51, 15, 16, 17, 18, 19, 20, 21, 22, 23,
221 24, 25, 26, 27, 28, 29, 30, 43, 31, 32,
222 33, 44, 85, 86, 154, 140, 141, 143, 144, 155,
223 193, 87, 48, 156, 70, 170, 171, 50, 56, 72,
224 57, 61, 67, 89, 90, 91, 74, 163, 93, 94,
225 142, 92, 145, 97, 108, 109, 110, 111, 139, 112,
226 113, 114, 115, 116, 153, 117, 118, 121, 119, 120,
227 122, 180, 126, 127, 128, 135, 147, 186, 160, 161,
228 124, 162, 164, 165, 166, 167, 168, 159, 173, 169,
229 174, 172, 175, 176, 177, 178, 179, 181, 158, 182,
230 183, 185, 190, 187, 189, 188, 191, 192, 195, 194,
231 196, 0, 0, 198, 197, 73, 199, 49, 56, 58,
232 };
233 short yycheck[] = { 89,
234 90, 91, 305, 93, 269, 270, 257, 97, 98, 260,
235 100, 262, 263, 316, 317, 318, 269, 270, 108, 269,
236 110, 111, 270, 273, 114, 115, 116, 12, 13, 269,
237 15, 256, 269, 18, 19, 20, 21, 270, 23, 269,
238 270, 26, 27, 28, 29, 30, 269, 32, 33, 274,
239 275, 269, 270, 278, 279, 280, 281, 282, 283, 284,
240 285, 286, 261, 269, 270, 270, 265, 266, 269, 294,
241 270, 296, 297, 298, 299, 300, 301, 302, 303, 304,
242 305, 306, 307, 308, 309, 310, 311, 269, 313, 314,
243 315, 269, 258, 259, 259, 269, 270, 269, 270, 264,
244 190, 267, 269, 268, 272, 269, 270, 269, 269, 272,
245 270, 270, 270, 269, 269, 269, 273, 266, 269, 272,
246 105, 273, 107, 269, 269, 272, 269, 269, 272, 270,
247 270, 269, 269, 269, 273, 270, 270, 269, 271, 270,
248 269, 271, 270, 270, 270, 270, 270, 173, 270, 270,
249 273, 270, 270, 270, 270, 270, 270, 123, 269, 272,
250 270, 273, 270, 270, 270, 270, 270, 269, 122, 270,
251 273, 270, 269, 273, 270, 273, 271, 270, 270, 273,
252 271, -1, -1, 271, 273, 269, 273, 270, 270, 270,
253 };
254 #define YYFINAL 1
255 #ifndef YYDEBUG
256 #define YYDEBUG 0
257 #endif
258 #define YYMAXTOKEN 319
259 #if YYDEBUG
260 char *yyname[] = {
261 "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,
262 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
263 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
264 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
265 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
266 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
267 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",
268 "P","R","S","T","SP","CRLF","COMMA","STRING","NUMBER","USER","PASS","ACCT",
269 "REIN","QUIT","PORT","PASV","TYPE","STRU","MODE","RETR","STOR","APPE","MLFL",
270 "MAIL","MSND","MSOM","MSAM","MRSQ","MRCP","ALLO","REST","RNFR","RNTO","ABOR",
271 "DELE","CWD","LIST","NLST","SITE","STAT","HELP","NOOP","MKD","RMD","PWD","CDUP",
272 "STOU","SMNT","SYST","SIZE","MDTM","UMASK","IDLE","CHMOD","LEXERR",
273 };
274 char *yyrule[] = {
275 "$accept : cmd_list",
276 "cmd_list :",
277 "cmd_list : cmd_list cmd",
278 "cmd_list : cmd_list rcmd",
279 "cmd : USER SP username CRLF",
280 "cmd : PASS SP password CRLF",
281 "cmd : PORT SP host_port CRLF",
282 "cmd : PASV CRLF",
283 "cmd : TYPE SP type_code CRLF",
284 "cmd : STRU SP struct_code CRLF",
285 "cmd : MODE SP mode_code CRLF",
286 "cmd : ALLO SP NUMBER CRLF",
287 "cmd : ALLO SP NUMBER SP R SP NUMBER CRLF",
288 "cmd : RETR check_login SP pathname CRLF",
289 "cmd : STOR check_login SP pathname CRLF",
290 "cmd : APPE check_login SP pathname CRLF",
291 "cmd : NLST check_login CRLF",
292 "cmd : NLST check_login SP STRING CRLF",
293 "cmd : LIST check_login CRLF",
294 "cmd : LIST check_login SP pathname CRLF",
295 "cmd : STAT check_login SP pathname CRLF",
296 "cmd : STAT CRLF",
297 "cmd : DELE check_login SP pathname CRLF",
298 "cmd : RNTO SP pathname CRLF",
299 "cmd : ABOR CRLF",
300 "cmd : CWD check_login CRLF",
301 "cmd : CWD check_login SP pathname CRLF",
302 "cmd : HELP CRLF",
303 "cmd : HELP SP STRING CRLF",
304 "cmd : NOOP CRLF",
305 "cmd : MKD check_login SP pathname CRLF",
306 "cmd : RMD check_login SP pathname CRLF",
307 "cmd : PWD check_login CRLF",
308 "cmd : CDUP check_login CRLF",
309 "cmd : SITE SP HELP CRLF",
310 "cmd : SITE SP HELP SP STRING CRLF",
311 "cmd : SITE SP UMASK check_login CRLF",
312 "cmd : SITE SP UMASK check_login SP octal_number CRLF",
313 "cmd : SITE SP CHMOD check_login SP octal_number SP pathname CRLF",
314 "cmd : SITE SP IDLE CRLF",
315 "cmd : SITE SP IDLE SP NUMBER CRLF",
316 "cmd : STOU check_login SP pathname CRLF",
317 "cmd : SYST CRLF",
318 "cmd : SIZE check_login SP pathname CRLF",
319 "cmd : MDTM check_login SP pathname CRLF",
320 "cmd : QUIT CRLF",
321 "cmd : error CRLF",
322 "rcmd : RNFR check_login SP pathname CRLF",
323 "username : STRING",
324 "password :",
325 "password : STRING",
326 "byte_size : NUMBER",
327 "host_port : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER",
328 "form_code : N",
329 "form_code : T",
330 "form_code : C",
331 "type_code : A",
332 "type_code : A SP form_code",
333 "type_code : E",
334 "type_code : E SP form_code",
335 "type_code : I",
336 "type_code : L",
337 "type_code : L SP byte_size",
338 "type_code : L byte_size",
339 "struct_code : F",
340 "struct_code : R",
341 "struct_code : P",
342 "mode_code : S",
343 "mode_code : B",
344 "mode_code : C",
345 "pathname : pathstring",
346 "pathstring : STRING",
347 "octal_number : NUMBER",
348 "check_login :",
349 };
350 #endif
351 #ifndef YYSTYPE
352 typedef int YYSTYPE;
353 #endif
354 #define yyclearin (yychar=(-1))
355 #define yyerrok (yyerrflag=0)
356 #ifndef YYSTACKSIZE
357 #ifdef YYMAXDEPTH
358 #define YYSTACKSIZE YYMAXDEPTH
359 #else
360 #define YYSTACKSIZE 300
361 #endif
362 #endif
363 int yydebug;
364 int yynerrs;
365 int yyerrflag;
366 int yychar;
367 short *yyssp;
368 YYSTYPE *yyvsp;
369 YYSTYPE yyval;
370 YYSTYPE yylval;
371 #define yystacksize YYSTACKSIZE
372 short yyss[YYSTACKSIZE];
373 YYSTYPE yyvs[YYSTACKSIZE];
374 #line 658 "ftp.y"
375
376 extern jmp_buf errcatch;
377
378 #define CMD 0 /* beginning of command */
379 #define ARGS 1 /* expect miscellaneous arguments */
380 #define STR1 2 /* expect SP followed by STRING */
381 #define STR2 3 /* expect STRING */
382 #define OSTR 4 /* optional SP then STRING */
383 #define ZSTR1 5 /* SP then optional STRING */
384 #define ZSTR2 6 /* optional STRING after SP */
385 #define SITECMD 7 /* SITE command */
386 #define NSTR 8 /* Number followed by a string */
387
388 struct tab {
389 char *name;
390 short token;
391 short state;
392 short implemented; /* 1 if command is implemented */
393 char *help;
394 };
395
396 struct tab cmdtab[] = { /* In order defined in RFC 765 */
397 { "USER", USER, STR1, 1, "<sp> username" },
398 { "PASS", PASS, ZSTR1, 1, "<sp> password" },
399 { "ACCT", ACCT, STR1, 0, "(specify account)" },
400 { "SMNT", SMNT, ARGS, 0, "(structure mount)" },
401 { "REIN", REIN, ARGS, 0, "(reinitialize server state)" },
402 { "QUIT", QUIT, ARGS, 1, "(terminate service)", },
403 { "PORT", PORT, ARGS, 1, "<sp> b0, b1, b2, b3, b4" },
404 { "PASV", PASV, ARGS, 1, "(set server in passive mode)" },
405 { "TYPE", TYPE, ARGS, 1, "<sp> [ A | E | I | L ]" },
406 { "STRU", STRU, ARGS, 1, "(specify file structure)" },
407 { "MODE", MODE, ARGS, 1, "(specify transfer mode)" },
408 { "RETR", RETR, STR1, 1, "<sp> file-name" },
409 { "STOR", STOR, STR1, 1, "<sp> file-name" },
410 { "APPE", APPE, STR1, 1, "<sp> file-name" },
411 { "MLFL", MLFL, OSTR, 0, "(mail file)" },
412 { "MAIL", MAIL, OSTR, 0, "(mail to user)" },
413 { "MSND", MSND, OSTR, 0, "(mail send to terminal)" },
414 { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" },
415 { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" },
416 { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" },
417 { "MRCP", MRCP, STR1, 0, "(mail recipient)" },
418 { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" },
419 { "REST", REST, ARGS, 0, "(restart command)" },
420 { "RNFR", RNFR, STR1, 1, "<sp> file-name" },
421 { "RNTO", RNTO, STR1, 1, "<sp> file-name" },
422 { "ABOR", ABOR, ARGS, 1, "(abort operation)" },
423 { "DELE", DELE, STR1, 1, "<sp> file-name" },
424 { "CWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
425 { "XCWD", CWD, OSTR, 1, "[ <sp> directory-name ]" },
426 { "LIST", LIST, OSTR, 1, "[ <sp> path-name ]" },
427 { "NLST", NLST, OSTR, 1, "[ <sp> path-name ]" },
428 { "SITE", SITE, SITECMD, 1, "site-cmd [ <sp> arguments ]" },
429 { "SYST", SYST, ARGS, 1, "(get type of operating system)" },
430 { "STAT", STAT, OSTR, 1, "[ <sp> path-name ]" },
431 { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
432 { "NOOP", NOOP, ARGS, 1, "" },
433 { "MKD", MKD, STR1, 1, "<sp> path-name" },
434 { "XMKD", MKD, STR1, 1, "<sp> path-name" },
435 { "RMD", RMD, STR1, 1, "<sp> path-name" },
436 { "XRMD", RMD, STR1, 1, "<sp> path-name" },
437 { "PWD", PWD, ARGS, 1, "(return current directory)" },
438 { "XPWD", PWD, ARGS, 1, "(return current directory)" },
439 { "CDUP", CDUP, ARGS, 1, "(change to parent directory)" },
440 { "XCUP", CDUP, ARGS, 1, "(change to parent directory)" },
441 { "STOU", STOU, STR1, 1, "<sp> file-name" },
442 { "SIZE", SIZE, OSTR, 1, "<sp> path-name" },
443 { "MDTM", MDTM, OSTR, 1, "<sp> path-name" },
444 { NULL, 0, 0, 0, 0 }
445 };
446
447 struct tab sitetab[] = {
448 { "UMASK", UMASK, ARGS, 1, "[ <sp> umask ]" },
449 { "IDLE", IDLE, ARGS, 1, "[ <sp> maximum-idle-time ]" },
450 { "CHMOD", CHMOD, NSTR, 1, "<sp> mode <sp> file-name" },
451 { "HELP", HELP, OSTR, 1, "[ <sp> <string> ]" },
452 { NULL, 0, 0, 0, 0 }
453 };
454
455 struct tab *
lookup(p,cmd)456 lookup(p, cmd)
457 register struct tab *p;
458 char *cmd;
459 {
460
461 for (; p->name != NULL; p++)
462 if (strcmp(cmd, p->name) == 0)
463 return (p);
464 return (0);
465 }
466
467 #include <arpa/telnet.h>
468
469 /*
470 * getline - a hacked up version of fgets to ignore TELNET escape codes.
471 */
472 char *
getline(s,n,iop)473 getline(s, n, iop)
474 char *s;
475 register FILE *iop;
476 {
477 register c;
478 register char *cs;
479
480 cs = s;
481 /* tmpline may contain saved command from urgent mode interruption */
482 for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) {
483 *cs++ = tmpline[c];
484 if (tmpline[c] == '\n') {
485 *cs++ = '\0';
486 if (debug)
487 syslog(LOG_DEBUG, "command: %s", s);
488 tmpline[0] = '\0';
489 return(s);
490 }
491 if (c == 0)
492 tmpline[0] = '\0';
493 }
494 while ((c = getc(iop)) != EOF) {
495 c &= 0377;
496 if (c == IAC) {
497 if ((c = getc(iop)) != EOF) {
498 c &= 0377;
499 switch (c) {
500 case WILL:
501 case WONT:
502 c = getc(iop);
503 printf("%c%c%c", IAC, DONT, 0377&c);
504 (void) fflush(stdout);
505 continue;
506 case DO:
507 case DONT:
508 c = getc(iop);
509 printf("%c%c%c", IAC, WONT, 0377&c);
510 (void) fflush(stdout);
511 continue;
512 case IAC:
513 break;
514 default:
515 continue; /* ignore command */
516 }
517 }
518 }
519 *cs++ = c;
520 if (--n <= 0 || c == '\n')
521 break;
522 }
523 if (c == EOF && cs == s)
524 return (NULL);
525 *cs++ = '\0';
526 if (debug)
527 syslog(LOG_DEBUG, "command: %s", s);
528 return (s);
529 }
530
531 static int
toolong()532 toolong()
533 {
534 time_t now;
535 extern char *ctime();
536 extern time_t time();
537
538 reply(421,
539 "Timeout (%d seconds): closing control connection.", timeout);
540 (void) time(&now);
541 if (logging) {
542 syslog(LOG_INFO,
543 "User %s timed out after %d seconds at %s",
544 (pw ? pw -> pw_name : "unknown"), timeout, ctime(&now));
545 }
546 dologout(1);
547 }
548
yylex()549 yylex()
550 {
551 static int cpos, state;
552 register char *cp, *cp2;
553 register struct tab *p;
554 int n;
555 char c, *strpbrk();
556 char *copy();
557
558 for (;;) {
559 switch (state) {
560
561 case CMD:
562 (void) signal(SIGALRM, toolong);
563 (void) alarm((unsigned) timeout);
564 if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) {
565 reply(221, "You could at least say goodbye.");
566 dologout(0);
567 }
568 (void) alarm(0);
569 #ifdef SETPROCTITLE
570 if (strncasecmp(cbuf, "PASS", 4) != NULL)
571 setproctitle("%s: %s", proctitle, cbuf);
572 #endif /* SETPROCTITLE */
573 if ((cp = index(cbuf, '\r'))) {
574 *cp++ = '\n';
575 *cp = '\0';
576 }
577 if ((cp = strpbrk(cbuf, " \n")))
578 cpos = cp - cbuf;
579 if (cpos == 0)
580 cpos = 4;
581 c = cbuf[cpos];
582 cbuf[cpos] = '\0';
583 upper(cbuf);
584 p = lookup(cmdtab, cbuf);
585 cbuf[cpos] = c;
586 if (p != 0) {
587 if (p->implemented == 0) {
588 nack(p->name);
589 longjmp(errcatch,0);
590 /* NOTREACHED */
591 }
592 state = p->state;
593 *(char **)&yylval = p->name;
594 return (p->token);
595 }
596 break;
597
598 case SITECMD:
599 if (cbuf[cpos] == ' ') {
600 cpos++;
601 return (SP);
602 }
603 cp = &cbuf[cpos];
604 if ((cp2 = strpbrk(cp, " \n")))
605 cpos = cp2 - cbuf;
606 c = cbuf[cpos];
607 cbuf[cpos] = '\0';
608 upper(cp);
609 p = lookup(sitetab, cp);
610 cbuf[cpos] = c;
611 if (p != 0) {
612 if (p->implemented == 0) {
613 state = CMD;
614 nack(p->name);
615 longjmp(errcatch,0);
616 /* NOTREACHED */
617 }
618 state = p->state;
619 *(char **)&yylval = p->name;
620 return (p->token);
621 }
622 state = CMD;
623 break;
624
625 case OSTR:
626 if (cbuf[cpos] == '\n') {
627 state = CMD;
628 return (CRLF);
629 }
630 /* FALLTHROUGH */
631
632 case STR1:
633 case ZSTR1:
634 dostr1:
635 if (cbuf[cpos] == ' ') {
636 cpos++;
637 state = state == OSTR ? STR2 : ++state;
638 return (SP);
639 }
640 break;
641
642 case ZSTR2:
643 if (cbuf[cpos] == '\n') {
644 state = CMD;
645 return (CRLF);
646 }
647 /* FALLTHROUGH */
648
649 case STR2:
650 cp = &cbuf[cpos];
651 n = strlen(cp);
652 cpos += n - 1;
653 /*
654 * Make sure the string is nonempty and \n terminated.
655 */
656 if (n > 1 && cbuf[cpos] == '\n') {
657 cbuf[cpos] = '\0';
658 *(char **)&yylval = copy(cp);
659 cbuf[cpos] = '\n';
660 state = ARGS;
661 return (STRING);
662 }
663 break;
664
665 case NSTR:
666 if (cbuf[cpos] == ' ') {
667 cpos++;
668 return (SP);
669 }
670 if (isdigit(cbuf[cpos])) {
671 cp = &cbuf[cpos];
672 while (isdigit(cbuf[++cpos]))
673 ;
674 c = cbuf[cpos];
675 cbuf[cpos] = '\0';
676 yylval = atoi(cp);
677 cbuf[cpos] = c;
678 state = STR1;
679 return (NUMBER);
680 }
681 state = STR1;
682 goto dostr1;
683
684 case ARGS:
685 if (isdigit(cbuf[cpos])) {
686 cp = &cbuf[cpos];
687 while (isdigit(cbuf[++cpos]))
688 ;
689 c = cbuf[cpos];
690 cbuf[cpos] = '\0';
691 yylval = atoi(cp);
692 cbuf[cpos] = c;
693 return (NUMBER);
694 }
695 switch (cbuf[cpos++]) {
696
697 case '\n':
698 state = CMD;
699 return (CRLF);
700
701 case ' ':
702 return (SP);
703
704 case ',':
705 return (COMMA);
706
707 case 'A':
708 case 'a':
709 return (A);
710
711 case 'B':
712 case 'b':
713 return (B);
714
715 case 'C':
716 case 'c':
717 return (C);
718
719 case 'E':
720 case 'e':
721 return (E);
722
723 case 'F':
724 case 'f':
725 return (F);
726
727 case 'I':
728 case 'i':
729 return (I);
730
731 case 'L':
732 case 'l':
733 return (L);
734
735 case 'N':
736 case 'n':
737 return (N);
738
739 case 'P':
740 case 'p':
741 return (P);
742
743 case 'R':
744 case 'r':
745 return (R);
746
747 case 'S':
748 case 's':
749 return (S);
750
751 case 'T':
752 case 't':
753 return (T);
754
755 }
756 break;
757
758 default:
759 fatal("Unknown state in scanner.");
760 }
761 yyerror((char *) 0);
762 state = CMD;
763 longjmp(errcatch,0);
764 }
765 }
766
upper(s)767 upper(s)
768 register char *s;
769 {
770 while (*s != '\0') {
771 if (islower(*s))
772 *s = toupper(*s);
773 s++;
774 }
775 }
776
777 char *
copy(s)778 copy(s)
779 char *s;
780 {
781 char *p;
782 extern char *malloc(), *strcpy();
783
784 p = malloc((unsigned) strlen(s) + 1);
785 if (p == NULL)
786 fatal("Ran out of memory.");
787 (void) strcpy(p, s);
788 return (p);
789 }
790
791 help(ctab, s)
792 struct tab *ctab;
793 char *s;
794 {
795 register struct tab *c;
796 register int width, NCMDS;
797 char *type;
798
799 if (ctab == sitetab)
800 type = "SITE ";
801 else
802 type = "";
803 width = 0, NCMDS = 0;
804 for (c = ctab; c->name != NULL; c++) {
805 int len = strlen(c->name);
806
807 if (len > width)
808 width = len;
809 NCMDS++;
810 }
811 width = (width + 8) &~ 7;
812 if (s == 0) {
813 register int i, j, w;
814 int columns, lines;
815
816 lreply(214, "The following %scommands are recognized %s.",
817 type, "(* =>'s unimplemented)");
818 columns = 76 / width;
819 if (columns == 0)
820 columns = 1;
821 lines = (NCMDS + columns - 1) / columns;
822 for (i = 0; i < lines; i++) {
823 printf(" ");
824 for (j = 0; j < columns; j++) {
825 c = ctab + j * lines + i;
826 printf("%s%c", c->name,
827 c->implemented ? ' ' : '*');
828 if (c + lines >= &ctab[NCMDS])
829 break;
830 w = strlen(c->name) + 1;
831 while (w < width) {
832 putchar(' ');
833 w++;
834 }
835 }
836 printf("\r\n");
837 }
838 (void) fflush(stdout);
839 reply(214, "Direct comments to ftp-bugs@%s.", hostname);
840 return;
841 }
842 upper(s);
843 c = lookup(ctab, s);
844 if (c == (struct tab *)0) {
845 reply(502, "Unknown command %s.", s);
846 return;
847 }
848 if (c->implemented)
849 reply(214, "Syntax: %s%s %s", type, c->name, c->help);
850 else
851 reply(214, "%s%-*s\t%s; unimplemented.", type, width,
852 c->name, c->help);
853 }
854
sizecmd(filename)855 sizecmd(filename)
856 char *filename;
857 {
858 switch (type) {
859 case TYPE_L:
860 case TYPE_I: {
861 struct stat stbuf;
862 if (stat(filename, &stbuf) < 0 ||
863 (stbuf.st_mode&S_IFMT) != S_IFREG)
864 reply(550, "%s: not a plain file.", filename);
865 else
866 reply(213, "%lu", stbuf.st_size);
867 break;}
868 case TYPE_A: {
869 FILE *fin;
870 register int c, count;
871 struct stat stbuf;
872 fin = fopen(filename, "r");
873 if (fin == NULL) {
874 perror_reply(550, filename);
875 return;
876 }
877 if (fstat(fileno(fin), &stbuf) < 0 ||
878 (stbuf.st_mode&S_IFMT) != S_IFREG) {
879 reply(550, "%s: not a plain file.", filename);
880 (void) fclose(fin);
881 return;
882 }
883
884 count = 0;
885 while((c=getc(fin)) != EOF) {
886 if (c == '\n') /* will get expanded to \r\n */
887 count++;
888 count++;
889 }
890 (void) fclose(fin);
891
892 reply(213, "%ld", count);
893 break;}
894 default:
895 reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
896 }
897 }
898 #line 898 "ftp.tab.c"
899 #define YYABORT goto yyabort
900 #define YYACCEPT goto yyaccept
901 #define YYERROR goto yyerrlab
902 int
yyparse()903 yyparse()
904 {
905 register int yym, yyn, yystate;
906 #if YYDEBUG
907 register char *yys;
908 extern char *getenv();
909
910 if (yys = getenv("YYDEBUG"))
911 {
912 yyn = *yys;
913 if (yyn == '0')
914 yydebug = 0;
915 else if (yyn >= '1' && yyn <= '9')
916 yydebug = yyn - '0';
917 }
918 #endif
919
920 yynerrs = 0;
921 yyerrflag = 0;
922 yychar = (-1);
923
924 yyssp = yyss;
925 yyvsp = yyvs;
926 *yyssp = yystate = 0;
927
928 yyloop:
929 if (yyn = yydefred[yystate]) goto yyreduce;
930 if (yychar < 0)
931 {
932 if ((yychar = yylex()) < 0) yychar = 0;
933 #if YYDEBUG
934 if (yydebug)
935 {
936 yys = 0;
937 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
938 if (!yys) yys = "illegal-symbol";
939 printf("yydebug: state %d, reading %d (%s)\n", yystate,
940 yychar, yys);
941 }
942 #endif
943 }
944 if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
945 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
946 {
947 #if YYDEBUG
948 if (yydebug)
949 printf("yydebug: state %d, shifting to state %d\n",
950 yystate, yytable[yyn]);
951 #endif
952 if (yyssp >= yyss + yystacksize - 1)
953 {
954 goto yyoverflow;
955 }
956 *++yyssp = yystate = yytable[yyn];
957 *++yyvsp = yylval;
958 yychar = (-1);
959 if (yyerrflag > 0) --yyerrflag;
960 goto yyloop;
961 }
962 if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
963 yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
964 {
965 yyn = yytable[yyn];
966 goto yyreduce;
967 }
968 if (yyerrflag) goto yyinrecovery;
969 #ifdef lint
970 goto yynewerror;
971 #endif
972 yynewerror:
973 yyerror("syntax error");
974 #ifdef lint
975 goto yyerrlab;
976 #endif
977 yyerrlab:
978 ++yynerrs;
979 yyinrecovery:
980 if (yyerrflag < 3)
981 {
982 yyerrflag = 3;
983 for (;;)
984 {
985 if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
986 yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
987 {
988 #if YYDEBUG
989 if (yydebug)
990 printf("yydebug: state %d, error recovery shifting\
991 to state %d\n", *yyssp, yytable[yyn]);
992 #endif
993 if (yyssp >= yyss + yystacksize - 1)
994 {
995 goto yyoverflow;
996 }
997 *++yyssp = yystate = yytable[yyn];
998 *++yyvsp = yylval;
999 goto yyloop;
1000 }
1001 else
1002 {
1003 #if YYDEBUG
1004 if (yydebug)
1005 printf("yydebug: error recovery discarding state %d\n",
1006 *yyssp);
1007 #endif
1008 if (yyssp <= yyss) goto yyabort;
1009 --yyssp;
1010 --yyvsp;
1011 }
1012 }
1013 }
1014 else
1015 {
1016 if (yychar == 0) goto yyabort;
1017 #if YYDEBUG
1018 if (yydebug)
1019 {
1020 yys = 0;
1021 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1022 if (!yys) yys = "illegal-symbol";
1023 printf("yydebug: state %d, error recovery discards token %d (%s)\n",
1024 yystate, yychar, yys);
1025 }
1026 #endif
1027 yychar = (-1);
1028 goto yyloop;
1029 }
1030 yyreduce:
1031 #if YYDEBUG
1032 if (yydebug)
1033 printf("yydebug: state %d, reducing by rule %d (%s)\n",
1034 yystate, yyn, yyrule[yyn]);
1035 #endif
1036 yym = yylen[yyn];
1037 yyval = yyvsp[1-yym];
1038 switch (yyn)
1039 {
1040 case 2:
1041 #line 99 "ftp.y"
1042 {
1043 fromname = (char *) 0;
1044 }
1045 break;
1046 case 4:
1047 #line 106 "ftp.y"
1048 {
1049 user((char *) yyvsp[-1]);
1050 free((char *) yyvsp[-1]);
1051 }
1052 break;
1053 case 5:
1054 #line 111 "ftp.y"
1055 {
1056 pass((char *) yyvsp[-1]);
1057 free((char *) yyvsp[-1]);
1058 }
1059 break;
1060 case 6:
1061 #line 116 "ftp.y"
1062 {
1063 usedefault = 0;
1064 if (pdata >= 0) {
1065 (void) close(pdata);
1066 pdata = -1;
1067 }
1068 reply(200, "PORT command successful.");
1069 }
1070 break;
1071 case 7:
1072 #line 125 "ftp.y"
1073 {
1074 passive();
1075 }
1076 break;
1077 case 8:
1078 #line 129 "ftp.y"
1079 {
1080 switch (cmd_type) {
1081
1082 case TYPE_A:
1083 if (cmd_form == FORM_N) {
1084 reply(200, "Type set to A.");
1085 type = cmd_type;
1086 form = cmd_form;
1087 } else
1088 reply(504, "Form must be N.");
1089 break;
1090
1091 case TYPE_E:
1092 reply(504, "Type E not implemented.");
1093 break;
1094
1095 case TYPE_I:
1096 reply(200, "Type set to I.");
1097 type = cmd_type;
1098 break;
1099
1100 case TYPE_L:
1101 #if NBBY == 8
1102 if (cmd_bytesz == 8) {
1103 reply(200,
1104 "Type set to L (byte size 8).");
1105 type = cmd_type;
1106 } else
1107 reply(504, "Byte size must be 8.");
1108 #else /* NBBY == 8 */
1109 UNIMPLEMENTED for NBBY != 8
1110 #endif /* NBBY == 8 */
1111 }
1112 }
1113 break;
1114 case 9:
1115 #line 164 "ftp.y"
1116 {
1117 switch (yyvsp[-1]) {
1118
1119 case STRU_F:
1120 reply(200, "STRU F ok.");
1121 break;
1122
1123 default:
1124 reply(504, "Unimplemented STRU type.");
1125 }
1126 }
1127 break;
1128 case 10:
1129 #line 176 "ftp.y"
1130 {
1131 switch (yyvsp[-1]) {
1132
1133 case MODE_S:
1134 reply(200, "MODE S ok.");
1135 break;
1136
1137 default:
1138 reply(502, "Unimplemented MODE type.");
1139 }
1140 }
1141 break;
1142 case 11:
1143 #line 188 "ftp.y"
1144 {
1145 reply(202, "ALLO command ignored.");
1146 }
1147 break;
1148 case 12:
1149 #line 192 "ftp.y"
1150 {
1151 reply(202, "ALLO command ignored.");
1152 }
1153 break;
1154 case 13:
1155 #line 196 "ftp.y"
1156 {
1157 if (yyvsp[-3] && yyvsp[-1] != NULL)
1158 retrieve((char *) 0, (char *) yyvsp[-1]);
1159 if (yyvsp[-1] != NULL)
1160 free((char *) yyvsp[-1]);
1161 }
1162 break;
1163 case 14:
1164 #line 203 "ftp.y"
1165 {
1166 if (yyvsp[-3] && yyvsp[-1] != NULL)
1167 store((char *) yyvsp[-1], "w", 0);
1168 if (yyvsp[-1] != NULL)
1169 free((char *) yyvsp[-1]);
1170 }
1171 break;
1172 case 15:
1173 #line 210 "ftp.y"
1174 {
1175 if (yyvsp[-3] && yyvsp[-1] != NULL)
1176 store((char *) yyvsp[-1], "a", 0);
1177 if (yyvsp[-1] != NULL)
1178 free((char *) yyvsp[-1]);
1179 }
1180 break;
1181 case 16:
1182 #line 217 "ftp.y"
1183 {
1184 if (yyvsp[-1])
1185 send_file_list(".");
1186 }
1187 break;
1188 case 17:
1189 #line 222 "ftp.y"
1190 {
1191 if (yyvsp[-3] && yyvsp[-1] != NULL)
1192 send_file_list((char *) yyvsp[-1]);
1193 if (yyvsp[-1] != NULL)
1194 free((char *) yyvsp[-1]);
1195 }
1196 break;
1197 case 18:
1198 #line 229 "ftp.y"
1199 {
1200 if (yyvsp[-1])
1201 retrieve("/bin/ls -lgA", "");
1202 }
1203 break;
1204 case 19:
1205 #line 234 "ftp.y"
1206 {
1207 if (yyvsp[-3] && yyvsp[-1] != NULL)
1208 retrieve("/bin/ls -lgA %s", (char *) yyvsp[-1]);
1209 if (yyvsp[-1] != NULL)
1210 free((char *) yyvsp[-1]);
1211 }
1212 break;
1213 case 20:
1214 #line 241 "ftp.y"
1215 {
1216 if (yyvsp[-3] && yyvsp[-1] != NULL)
1217 statfilecmd((char *) yyvsp[-1]);
1218 if (yyvsp[-1] != NULL)
1219 free((char *) yyvsp[-1]);
1220 }
1221 break;
1222 case 21:
1223 #line 248 "ftp.y"
1224 {
1225 statcmd();
1226 }
1227 break;
1228 case 22:
1229 #line 252 "ftp.y"
1230 {
1231 if (yyvsp[-3] && yyvsp[-1] != NULL)
1232 delete((char *) yyvsp[-1]);
1233 if (yyvsp[-1] != NULL)
1234 free((char *) yyvsp[-1]);
1235 }
1236 break;
1237 case 23:
1238 #line 259 "ftp.y"
1239 {
1240 if (fromname) {
1241 renamecmd(fromname, (char *) yyvsp[-1]);
1242 free(fromname);
1243 fromname = (char *) 0;
1244 } else {
1245 reply(503, "Bad sequence of commands.");
1246 }
1247 free((char *) yyvsp[-1]);
1248 }
1249 break;
1250 case 24:
1251 #line 270 "ftp.y"
1252 {
1253 reply(225, "ABOR command successful.");
1254 }
1255 break;
1256 case 25:
1257 #line 274 "ftp.y"
1258 {
1259 if (yyvsp[-1])
1260 cwd(pw->pw_dir);
1261 }
1262 break;
1263 case 26:
1264 #line 279 "ftp.y"
1265 {
1266 if (yyvsp[-3] && yyvsp[-1] != NULL)
1267 cwd((char *) yyvsp[-1]);
1268 if (yyvsp[-1] != NULL)
1269 free((char *) yyvsp[-1]);
1270 }
1271 break;
1272 case 27:
1273 #line 286 "ftp.y"
1274 {
1275 help(cmdtab, (char *) 0);
1276 }
1277 break;
1278 case 28:
1279 #line 290 "ftp.y"
1280 {
1281 register char *cp = (char *)yyvsp[-1];
1282
1283 if (strncasecmp(cp, "SITE", 4) == 0) {
1284 cp = (char *)yyvsp[-1] + 4;
1285 if (*cp == ' ')
1286 cp++;
1287 if (*cp)
1288 help(sitetab, cp);
1289 else
1290 help(sitetab, (char *) 0);
1291 } else
1292 help(cmdtab, (char *) yyvsp[-1]);
1293 }
1294 break;
1295 case 29:
1296 #line 305 "ftp.y"
1297 {
1298 reply(200, "NOOP command successful.");
1299 }
1300 break;
1301 case 30:
1302 #line 309 "ftp.y"
1303 {
1304 if (yyvsp[-3] && yyvsp[-1] != NULL)
1305 makedir((char *) yyvsp[-1]);
1306 if (yyvsp[-1] != NULL)
1307 free((char *) yyvsp[-1]);
1308 }
1309 break;
1310 case 31:
1311 #line 316 "ftp.y"
1312 {
1313 if (yyvsp[-3] && yyvsp[-1] != NULL)
1314 removedir((char *) yyvsp[-1]);
1315 if (yyvsp[-1] != NULL)
1316 free((char *) yyvsp[-1]);
1317 }
1318 break;
1319 case 32:
1320 #line 323 "ftp.y"
1321 {
1322 if (yyvsp[-1])
1323 pwd();
1324 }
1325 break;
1326 case 33:
1327 #line 328 "ftp.y"
1328 {
1329 if (yyvsp[-1])
1330 cwd("..");
1331 }
1332 break;
1333 case 34:
1334 #line 333 "ftp.y"
1335 {
1336 help(sitetab, (char *) 0);
1337 }
1338 break;
1339 case 35:
1340 #line 337 "ftp.y"
1341 {
1342 help(sitetab, (char *) yyvsp[-1]);
1343 }
1344 break;
1345 case 36:
1346 #line 341 "ftp.y"
1347 {
1348 int oldmask;
1349
1350 if (yyvsp[-1]) {
1351 oldmask = umask(0);
1352 (void) umask(oldmask);
1353 reply(200, "Current UMASK is %03o", oldmask);
1354 }
1355 }
1356 break;
1357 case 37:
1358 #line 351 "ftp.y"
1359 {
1360 int oldmask;
1361
1362 if (yyvsp[-3]) {
1363 if ((yyvsp[-1] == -1) || (yyvsp[-1] > 0777)) {
1364 reply(501, "Bad UMASK value");
1365 } else {
1366 oldmask = umask(yyvsp[-1]);
1367 reply(200,
1368 "UMASK set to %03o (was %03o)",
1369 yyvsp[-1], oldmask);
1370 }
1371 }
1372 }
1373 break;
1374 case 38:
1375 #line 366 "ftp.y"
1376 {
1377 if (yyvsp[-5] && (yyvsp[-1] != NULL)) {
1378 if (yyvsp[-3] > 0777)
1379 reply(501,
1380 "CHMOD: Mode value must be between 0 and 0777");
1381 else if (chmod((char *) yyvsp[-1], yyvsp[-3]) < 0)
1382 perror_reply(550, (char *) yyvsp[-1]);
1383 else
1384 reply(200, "CHMOD command successful.");
1385 }
1386 if (yyvsp[-1] != NULL)
1387 free((char *) yyvsp[-1]);
1388 }
1389 break;
1390 case 39:
1391 #line 380 "ftp.y"
1392 {
1393 reply(200,
1394 "Current IDLE time limit is %d seconds; max %d",
1395 timeout, maxtimeout);
1396 }
1397 break;
1398 case 40:
1399 #line 386 "ftp.y"
1400 {
1401 if (yyvsp[-1] < 30 || yyvsp[-1] > maxtimeout) {
1402 reply(501,
1403 "Maximum IDLE time must be between 30 and %d seconds",
1404 maxtimeout);
1405 } else {
1406 timeout = yyvsp[-1];
1407 (void) alarm((unsigned) timeout);
1408 reply(200,
1409 "Maximum IDLE time set to %d seconds",
1410 timeout);
1411 }
1412 }
1413 break;
1414 case 41:
1415 #line 400 "ftp.y"
1416 {
1417 if (yyvsp[-3] && yyvsp[-1] != NULL)
1418 store((char *) yyvsp[-1], "w", 1);
1419 if (yyvsp[-1] != NULL)
1420 free((char *) yyvsp[-1]);
1421 }
1422 break;
1423 case 42:
1424 #line 407 "ftp.y"
1425 {
1426 #ifdef unix
1427 #ifdef BSD
1428 reply(215, "UNIX Type: L%d Version: BSD-%d",
1429 NBBY, BSD);
1430 #else /* BSD */
1431 reply(215, "UNIX Type: L%d", NBBY);
1432 #endif /* BSD */
1433 #else /* unix */
1434 reply(215, "UNKNOWN Type: L%d", NBBY);
1435 #endif /* unix */
1436 }
1437 break;
1438 case 43:
1439 #line 428 "ftp.y"
1440 {
1441 if (yyvsp[-3] && yyvsp[-1] != NULL)
1442 sizecmd((char *) yyvsp[-1]);
1443 if (yyvsp[-1] != NULL)
1444 free((char *) yyvsp[-1]);
1445 }
1446 break;
1447 case 44:
1448 #line 445 "ftp.y"
1449 {
1450 if (yyvsp[-3] && yyvsp[-1] != NULL) {
1451 struct stat stbuf;
1452 if (stat((char *) yyvsp[-1], &stbuf) < 0)
1453 perror_reply(550, "%s", (char *) yyvsp[-1]);
1454 else if ((stbuf.st_mode&S_IFMT) != S_IFREG) {
1455 reply(550, "%s: not a plain file.",
1456 (char *) yyvsp[-1]);
1457 } else {
1458 register struct tm *t;
1459 struct tm *gmtime();
1460 t = gmtime(&stbuf.st_mtime);
1461 reply(213,
1462 "19%02d%02d%02d%02d%02d%02d",
1463 t->tm_year, t->tm_mon+1, t->tm_mday,
1464 t->tm_hour, t->tm_min, t->tm_sec);
1465 }
1466 }
1467 if (yyvsp[-1] != NULL)
1468 free((char *) yyvsp[-1]);
1469 }
1470 break;
1471 case 45:
1472 #line 467 "ftp.y"
1473 {
1474 reply(221, "Goodbye.");
1475 dologout(0);
1476 }
1477 break;
1478 case 46:
1479 #line 472 "ftp.y"
1480 {
1481 yyerrok;
1482 }
1483 break;
1484 case 47:
1485 #line 477 "ftp.y"
1486 {
1487 char *renamefrom();
1488
1489 if (yyvsp[-3] && yyvsp[-1]) {
1490 fromname = renamefrom((char *) yyvsp[-1]);
1491 if (fromname == (char *) 0 && yyvsp[-1]) {
1492 free((char *) yyvsp[-1]);
1493 }
1494 }
1495 }
1496 break;
1497 case 49:
1498 #line 493 "ftp.y"
1499 {
1500 *(char **)&(yyval ) = "";
1501 }
1502 break;
1503 case 52:
1504 #line 504 "ftp.y"
1505 {
1506 register char *a, *p;
1507
1508 a = (char *)&data_dest.sin_addr;
1509 a[0] = yyvsp[-10]; a[1] = yyvsp[-8]; a[2] = yyvsp[-6]; a[3] = yyvsp[-4];
1510 p = (char *)&data_dest.sin_port;
1511 p[0] = yyvsp[-2]; p[1] = yyvsp[0];
1512 data_dest.sin_family = AF_INET;
1513 }
1514 break;
1515 case 53:
1516 #line 516 "ftp.y"
1517 {
1518 yyval = FORM_N;
1519 }
1520 break;
1521 case 54:
1522 #line 520 "ftp.y"
1523 {
1524 yyval = FORM_T;
1525 }
1526 break;
1527 case 55:
1528 #line 524 "ftp.y"
1529 {
1530 yyval = FORM_C;
1531 }
1532 break;
1533 case 56:
1534 #line 530 "ftp.y"
1535 {
1536 cmd_type = TYPE_A;
1537 cmd_form = FORM_N;
1538 }
1539 break;
1540 case 57:
1541 #line 535 "ftp.y"
1542 {
1543 cmd_type = TYPE_A;
1544 cmd_form = yyvsp[0];
1545 }
1546 break;
1547 case 58:
1548 #line 540 "ftp.y"
1549 {
1550 cmd_type = TYPE_E;
1551 cmd_form = FORM_N;
1552 }
1553 break;
1554 case 59:
1555 #line 545 "ftp.y"
1556 {
1557 cmd_type = TYPE_E;
1558 cmd_form = yyvsp[0];
1559 }
1560 break;
1561 case 60:
1562 #line 550 "ftp.y"
1563 {
1564 cmd_type = TYPE_I;
1565 }
1566 break;
1567 case 61:
1568 #line 554 "ftp.y"
1569 {
1570 cmd_type = TYPE_L;
1571 cmd_bytesz = NBBY;
1572 }
1573 break;
1574 case 62:
1575 #line 559 "ftp.y"
1576 {
1577 cmd_type = TYPE_L;
1578 cmd_bytesz = yyvsp[0];
1579 }
1580 break;
1581 case 63:
1582 #line 565 "ftp.y"
1583 {
1584 cmd_type = TYPE_L;
1585 cmd_bytesz = yyvsp[0];
1586 }
1587 break;
1588 case 64:
1589 #line 572 "ftp.y"
1590 {
1591 yyval = STRU_F;
1592 }
1593 break;
1594 case 65:
1595 #line 576 "ftp.y"
1596 {
1597 yyval = STRU_R;
1598 }
1599 break;
1600 case 66:
1601 #line 580 "ftp.y"
1602 {
1603 yyval = STRU_P;
1604 }
1605 break;
1606 case 67:
1607 #line 586 "ftp.y"
1608 {
1609 yyval = MODE_S;
1610 }
1611 break;
1612 case 68:
1613 #line 590 "ftp.y"
1614 {
1615 yyval = MODE_B;
1616 }
1617 break;
1618 case 69:
1619 #line 594 "ftp.y"
1620 {
1621 yyval = MODE_C;
1622 }
1623 break;
1624 case 70:
1625 #line 600 "ftp.y"
1626 {
1627 /*
1628 * Problem: this production is used for all pathname
1629 * processing, but only gives a 550 error reply.
1630 * This is a valid reply in some cases but not in others.
1631 */
1632 if (logged_in && yyvsp[0] && strncmp((char *) yyvsp[0], "~", 1) == 0) {
1633 *(char **)&(yyval ) = *glob((char *) yyvsp[0]);
1634 if (globerr != NULL) {
1635 reply(550, globerr);
1636 yyval = NULL;
1637 }
1638 free((char *) yyvsp[0]);
1639 } else
1640 yyval = yyvsp[0];
1641 }
1642 break;
1643 case 72:
1644 #line 622 "ftp.y"
1645 {
1646 register int ret, dec, multby, digit;
1647
1648 /*
1649 * Convert a number that was read as decimal number
1650 * to what it would be if it had been read as octal.
1651 */
1652 dec = yyvsp[0];
1653 multby = 1;
1654 ret = 0;
1655 while (dec) {
1656 digit = dec%10;
1657 if (digit > 7) {
1658 ret = -1;
1659 break;
1660 }
1661 ret += digit * multby;
1662 multby *= 8;
1663 dec /= 10;
1664 }
1665 yyval = ret;
1666 }
1667 break;
1668 case 73:
1669 #line 647 "ftp.y"
1670 {
1671 if (logged_in)
1672 yyval = 1;
1673 else {
1674 reply(530, "Please login with USER and PASS.");
1675 yyval = 0;
1676 }
1677 }
1678 break;
1679 #line 1679 "ftp.tab.c"
1680 }
1681 yyssp -= yym;
1682 yystate = *yyssp;
1683 yyvsp -= yym;
1684 yym = yylhs[yyn];
1685 if (yystate == 0 && yym == 0)
1686 {
1687 #ifdef YYDEBUG
1688 if (yydebug)
1689 printf("yydebug: after reduction, shifting from state 0 to\
1690 state %d\n", YYFINAL);
1691 #endif
1692 yystate = YYFINAL;
1693 *++yyssp = YYFINAL;
1694 *++yyvsp = yyval;
1695 if (yychar < 0)
1696 {
1697 if ((yychar = yylex()) < 0) yychar = 0;
1698 #if YYDEBUG
1699 if (yydebug)
1700 {
1701 yys = 0;
1702 if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
1703 if (!yys) yys = "illegal-symbol";
1704 printf("yydebug: state %d, reading %d (%s)\n",
1705 YYFINAL, yychar, yys);
1706 }
1707 #endif
1708 }
1709 if (yychar == 0) goto yyaccept;
1710 goto yyloop;
1711 }
1712 if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
1713 yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
1714 yystate = yytable[yyn];
1715 else
1716 yystate = yydgoto[yym];
1717 #ifdef YYDEBUG
1718 if (yydebug)
1719 printf("yydebug: after reduction, shifting from state %d \
1720 to state %d\n", *yyssp, yystate);
1721 #endif
1722 if (yyssp >= yyss + yystacksize - 1)
1723 {
1724 goto yyoverflow;
1725 }
1726 *++yyssp = yystate;
1727 *++yyvsp = yyval;
1728 goto yyloop;
1729 yyoverflow:
1730 yyerror("yacc stack overflow");
1731 yyabort:
1732 return (1);
1733 yyaccept:
1734 return (0);
1735 }
1736