OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / user / ftpd / ftpcmd.c
1
2 /*  A Bison parser, made from ftpcmd.y
3     by GNU Bison version 1.28  */
4
5 #define YYBISON 1  /* Identify Bison output.  */
6
7 #define A       257
8 #define B       258
9 #define C       259
10 #define E       260
11 #define F       261
12 #define I       262
13 #define L       263
14 #define N       264
15 #define P       265
16 #define R       266
17 #define S       267
18 #define T       268
19 #define SP      269
20 #define CRLF    270
21 #define COMMA   271
22 #define USER    272
23 #define PASS    273
24 #define ACCT    274
25 #define REIN    275
26 #define QUIT    276
27 #define PORT    277
28 #define PASV    278
29 #define TYPE    279
30 #define STRU    280
31 #define MODE    281
32 #define RETR    282
33 #define STOR    283
34 #define APPE    284
35 #define MLFL    285
36 #define MAIL    286
37 #define MSND    287
38 #define MSOM    288
39 #define MSAM    289
40 #define MRSQ    290
41 #define MRCP    291
42 #define ALLO    292
43 #define REST    293
44 #define RNFR    294
45 #define RNTO    295
46 #define ABOR    296
47 #define DELE    297
48 #define CWD     298
49 #define LIST    299
50 #define NLST    300
51 #define SITE    301
52 #define STAT    302
53 #define HELP    303
54 #define NOOP    304
55 #define MKD     305
56 #define RMD     306
57 #define PWD     307
58 #define CDUP    308
59 #define STOU    309
60 #define SMNT    310
61 #define SYST    311
62 #define SIZE    312
63 #define MDTM    313
64 #define UMASK   314
65 #define IDLE    315
66 #define CHMOD   316
67 #define LEXERR  317
68 #define STRING  318
69 #define NUMBER  319
70
71 #line 37 "ftpcmd.y"
72
73
74 #ifndef lint
75 static char sccsid[] = "@(#)ftpcmd.y    8.3 (Berkeley) 4/6/94";
76 #endif /* not lint */
77
78 #ifdef HAVE_CONFIG_H
79 #include <config.h>
80 #endif
81
82 #include <sys/types.h>
83 #include <sys/param.h>
84 #include <sys/socket.h>
85 #include <sys/stat.h>
86
87 #include <netinet/in.h>
88 #include <arpa/ftp.h>
89
90 #include <ctype.h>
91 #include <errno.h>
92 #include <pwd.h>
93 #include <setjmp.h>
94 #include <signal.h>
95 #include <stdio.h>
96 #include <stdlib.h>
97 #include <string.h>
98 #include <syslog.h>
99 #ifdef TIME_WITH_SYS_TIME
100 # include <sys/time.h>
101 # include <time.h>
102 #else
103 # ifdef HAVE_SYS_TIME_H
104 #  include <sys/time.h>
105 # else
106 #  include <time.h>
107 # endif
108 #endif
109 #include <unistd.h>
110 #include <limits.h>
111 #ifdef HAVE_SYS_UTSNAME_H
112 #include <sys/utsname.h>
113 #endif
114 /* Include glob.h last, because it may define "const" which breaks
115    system headers on some platforms. */
116 #include <glob.h>
117
118 #include "extern.h"
119
120 #if ! defined (NBBY) && defined (CHAR_BIT)
121 #define NBBY CHAR_BIT
122 #endif
123
124 off_t restart_point;
125
126 static char cbuf[512];           /* Command Buffer.  */
127 static char *fromname;
128 static int cmd_type;
129 static int cmd_form;
130 static int cmd_bytesz;
131
132 struct tab
133 {
134   const char    *name;
135   short token;
136   short state;
137   short implemented;    /* 1 if command is implemented */
138   const char    *help;
139 };
140
141 extern struct tab cmdtab[];
142 extern struct tab sitetab[];
143 static char *copy         __P ((char *));
144 static void help          __P ((struct tab *, char *));
145 static struct tab *lookup __P ((struct tab *, char *));
146 static void sizecmd       __P ((char *));
147 static int yylex          __P ((void));
148 static void yyerror       __P ((const char *s));
149
150
151 #line 117 "ftpcmd.y"
152 typedef union {
153         int     i;
154         char   *s;
155 } YYSTYPE;
156 #include <stdio.h>
157
158 #ifndef __cplusplus
159 #ifndef __STDC__
160 #define const
161 #endif
162 #endif
163
164
165
166 #define YYFINAL         210
167 #define YYFLAG          -32768
168 #define YYNTBASE        66
169
170 #define YYTRANSLATE(x) ((unsigned)(x) <= 319 ? yytranslate[x] : 81)
171
172 static const char yytranslate[] = {     0,
173      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
174      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
175      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
176      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
177      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
178      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
179      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
180      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
181      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
182      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
183      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
184      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
185      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
186      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
187      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
188      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
189      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
190      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
191      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
192      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
193      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
194      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
195      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
196      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
197      2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
198      2,     2,     2,     2,     2,     1,     3,     4,     5,     6,
199      7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
200     17,    18,    19,    20,    21,    22,    23,    24,    25,    26,
201     27,    28,    29,    30,    31,    32,    33,    34,    35,    36,
202     37,    38,    39,    40,    41,    42,    43,    44,    45,    46,
203     47,    48,    49,    50,    51,    52,    53,    54,    55,    56,
204     57,    58,    59,    60,    61,    62,    63,    64,    65
205 };
206
207 #if YYDEBUG != 0
208 static const short yyprhs[] = {     0,
209      0,     1,     4,     7,    12,    17,    23,    27,    32,    37,
210     42,    47,    56,    62,    68,    74,    78,    84,    88,    94,
211    100,   103,   109,   115,   118,   122,   128,   131,   136,   139,
212    145,   151,   155,   159,   164,   171,   177,   185,   195,   200,
213    208,   214,   217,   223,   229,   232,   235,   241,   246,   248,
214    249,   251,   253,   265,   267,   269,   271,   273,   277,   279,
215    283,   285,   287,   291,   294,   296,   298,   300,   302,   304,
216    306,   308,   310,   312
217 };
218
219 static const short yyrhs[] = {    -1,
220     66,    67,     0,    66,    68,     0,    18,    15,    69,    16,
221      0,    19,    15,    70,    16,     0,    23,    80,    15,    72,
222     16,     0,    24,    80,    16,     0,    25,    15,    74,    16,
223      0,    26,    15,    75,    16,     0,    27,    15,    76,    16,
224      0,    38,    15,    65,    16,     0,    38,    15,    65,    15,
225     12,    15,    65,    16,     0,    28,    80,    15,    77,    16,
226      0,    29,    80,    15,    77,    16,     0,    30,    80,    15,
227     77,    16,     0,    46,    80,    16,     0,    46,    80,    15,
228     64,    16,     0,    45,    80,    16,     0,    45,    80,    15,
229     77,    16,     0,    48,    80,    15,    77,    16,     0,    48,
230     16,     0,    43,    80,    15,    77,    16,     0,    41,    80,
231     15,    77,    16,     0,    42,    16,     0,    44,    80,    16,
232      0,    44,    80,    15,    77,    16,     0,    49,    16,     0,
233     49,    15,    64,    16,     0,    50,    16,     0,    51,    80,
234     15,    77,    16,     0,    52,    80,    15,    77,    16,     0,
235     53,    80,    16,     0,    54,    80,    16,     0,    47,    15,
236     49,    16,     0,    47,    15,    49,    15,    64,    16,     0,
237     47,    15,    60,    80,    16,     0,    47,    15,    60,    80,
238     15,    79,    16,     0,    47,    15,    62,    80,    15,    79,
239     15,    77,    16,     0,    47,    15,    61,    16,     0,    47,
240     15,    80,    61,    15,    65,    16,     0,    55,    80,    15,
241     77,    16,     0,    57,    16,     0,    58,    80,    15,    77,
242     16,     0,    59,    80,    15,    77,    16,     0,    22,    16,
243      0,     1,    16,     0,    40,    80,    15,    77,    16,     0,
244     39,    15,    71,    16,     0,    64,     0,     0,    64,     0,
245     65,     0,    65,    17,    65,    17,    65,    17,    65,    17,
246     65,    17,    65,     0,    10,     0,    14,     0,     5,     0,
247      3,     0,     3,    15,    73,     0,     6,     0,     6,    15,
248     73,     0,     8,     0,     9,     0,     9,    15,    71,     0,
249      9,    71,     0,     7,     0,    12,     0,    11,     0,    13,
250      0,     4,     0,     5,     0,    78,     0,    64,     0,    65,
251      0,     0
252 };
253
254 #endif
255
256 #if YYDEBUG != 0
257 static const short yyrline[] = { 0,
258    152,   153,   160,   164,   169,   175,   197,   202,   237,   249,
259    261,   265,   269,   276,   283,   290,   295,   302,   307,   314,
260    321,   325,   332,   345,   349,   354,   361,   365,   382,   386,
261    393,   400,   405,   410,   414,   420,   430,   445,   459,   465,
262    481,   488,   534,   551,   573,   578,   584,   595,   610,   614,
263    618,   622,   626,   640,   644,   648,   655,   660,   665,   670,
264    675,   679,   684,   690,   698,   702,   706,   713,   717,   721,
265    728,   765,   769,   796
266 };
267 #endif
268
269
270 #if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
271
272 static const char * const yytname[] = {   "$","error","$undefined.","A","B",
273 "C","E","F","I","L","N","P","R","S","T","SP","CRLF","COMMA","USER","PASS","ACCT",
274 "REIN","QUIT","PORT","PASV","TYPE","STRU","MODE","RETR","STOR","APPE","MLFL",
275 "MAIL","MSND","MSOM","MSAM","MRSQ","MRCP","ALLO","REST","RNFR","RNTO","ABOR",
276 "DELE","CWD","LIST","NLST","SITE","STAT","HELP","NOOP","MKD","RMD","PWD","CDUP",
277 "STOU","SMNT","SYST","SIZE","MDTM","UMASK","IDLE","CHMOD","LEXERR","STRING",
278 "NUMBER","cmd_list","cmd","rcmd","username","password","byte_size","host_port",
279 "form_code","type_code","struct_code","mode_code","pathname","pathstring","octal_number",
280 "check_login", NULL
281 };
282 #endif
283
284 static const short yyr1[] = {     0,
285     66,    66,    66,    67,    67,    67,    67,    67,    67,    67,
286     67,    67,    67,    67,    67,    67,    67,    67,    67,    67,
287     67,    67,    67,    67,    67,    67,    67,    67,    67,    67,
288     67,    67,    67,    67,    67,    67,    67,    67,    67,    67,
289     67,    67,    67,    67,    67,    67,    68,    68,    69,    70,
290     70,    71,    72,    73,    73,    73,    74,    74,    74,    74,
291     74,    74,    74,    74,    75,    75,    75,    76,    76,    76,
292     77,    78,    79,    80
293 };
294
295 static const short yyr2[] = {     0,
296      0,     2,     2,     4,     4,     5,     3,     4,     4,     4,
297      4,     8,     5,     5,     5,     3,     5,     3,     5,     5,
298      2,     5,     5,     2,     3,     5,     2,     4,     2,     5,
299      5,     3,     3,     4,     6,     5,     7,     9,     4,     7,
300      5,     2,     5,     5,     2,     2,     5,     4,     1,     0,
301      1,     1,    11,     1,     1,     1,     1,     3,     1,     3,
302      1,     1,     3,     2,     1,     1,     1,     1,     1,     1,
303      1,     1,     1,     0
304 };
305
306 static const short yydefact[] = {     1,
307      0,     0,     0,     0,     0,    74,    74,     0,     0,     0,
308     74,    74,    74,     0,     0,    74,    74,     0,    74,    74,
309     74,    74,     0,    74,     0,     0,    74,    74,    74,    74,
310     74,     0,    74,    74,     2,     3,    46,     0,    50,    45,
311      0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
312      0,     0,    24,     0,     0,     0,     0,     0,    21,     0,
313      0,    27,    29,     0,     0,     0,     0,     0,    42,     0,
314      0,    49,     0,    51,     0,     0,     7,    57,    59,    61,
315     62,     0,    65,    67,    66,     0,    69,    70,    68,     0,
316      0,     0,     0,     0,    52,     0,     0,     0,     0,     0,
317     25,     0,    18,     0,    16,     0,    74,     0,    74,     0,
318      0,     0,     0,     0,    32,    33,     0,     0,     0,     4,
319      5,     0,     0,     0,     0,     0,    64,     8,     9,    10,
320     72,     0,    71,     0,     0,     0,    11,    48,     0,     0,
321      0,     0,     0,     0,     0,    34,     0,    39,     0,     0,
322      0,    28,     0,     0,     0,     0,     0,     0,     6,    56,
323     54,    55,    58,    60,    63,    13,    14,    15,     0,    47,
324     23,    22,    26,    19,    17,     0,     0,    36,     0,     0,
325     20,    30,    31,    41,    43,    44,     0,     0,    35,    73,
326      0,     0,     0,     0,     0,    37,     0,    40,     0,    12,
327      0,     0,    38,     0,     0,     0,     0,    53,     0,     0
328 };
329
330 static const short yydefgoto[] = {     1,
331     35,    36,    73,    75,    96,   123,   163,    82,    86,    90,
332    132,   133,   191,    41
333 };
334
335 static const short yypact[] = {-32768,
336     42,    -7,     8,    20,    24,-32768,-32768,    44,    59,    62,
337 -32768,-32768,-32768,    83,    89,-32768,-32768,    47,-32768,-32768,
338 -32768,-32768,    97,    98,    16,    99,-32768,-32768,-32768,-32768,
339 -32768,   100,-32768,-32768,-32768,-32768,-32768,    49,    53,-32768,
340    103,   104,    70,     6,     7,   106,   107,   108,    54,    60,
341    112,   113,-32768,   114,    39,    41,    87,   -46,-32768,   115,
342     67,-32768,-32768,   117,   118,   119,   120,   122,-32768,   123,
343    124,-32768,   125,-32768,   126,    69,-32768,   128,   129,-32768,
344    -13,   130,-32768,-32768,-32768,   131,-32768,-32768,-32768,   132,
345     76,    76,    76,    91,-32768,   133,    76,    76,    76,    76,
346 -32768,    76,-32768,    81,-32768,    93,-32768,   134,-32768,    90,
347     76,   136,    76,    76,-32768,-32768,    76,    76,    76,-32768,
348 -32768,   137,   139,    48,    48,    60,-32768,-32768,-32768,-32768,
349 -32768,   140,-32768,   141,   142,   147,-32768,-32768,   144,   145,
350    146,   148,   149,   150,   105,-32768,    95,-32768,   138,   152,
351    154,-32768,   155,   156,   157,   158,   159,   111,-32768,-32768,
352 -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,   153,-32768,
353 -32768,-32768,-32768,-32768,-32768,   161,   116,-32768,   116,   121,
354 -32768,-32768,-32768,-32768,-32768,-32768,   162,   127,-32768,-32768,
355    164,   163,   166,   135,   167,-32768,    76,-32768,   168,-32768,
356    171,   143,-32768,   172,   151,   173,   160,-32768,   184,-32768
357 };
358
359 static const short yypgoto[] = {-32768,
360 -32768,-32768,-32768,-32768,   -77,-32768,    38,-32768,-32768,-32768,
361    -92,-32768,     9,    17
362 };
363
364
365 #define YYLAST          225
366
367
368 static const short yytable[] = {   134,
369    135,   126,   106,   127,   139,   140,   141,   142,    37,   143,
370     87,    88,    83,   107,   108,   109,    84,    85,   151,    89,
371    153,   154,    38,    42,   155,   156,   157,    46,    47,    48,
372     61,    62,    51,    52,    39,    54,    55,    56,    57,    40,
373     60,   209,     2,    64,    65,    66,    67,    68,   165,    70,
374     71,    95,   160,   100,   101,   102,   103,   161,    43,     3,
375      4,   162,    53,     5,     6,     7,     8,     9,    10,    11,
376     12,    13,    78,    44,   110,    79,    45,    80,    81,    14,
377     15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
378     25,    26,    27,    28,    29,    30,    31,    49,    32,    33,
379     34,   104,   105,    50,   201,   136,   137,   145,   146,   177,
380    178,    58,    72,    59,    63,    69,    74,    76,    94,    77,
381     91,    92,    93,   147,    95,   149,    97,    98,    99,   111,
382    112,   113,   114,   122,   115,   116,   117,   118,   119,   131,
383    120,   121,   124,   125,   144,   128,   129,   130,   138,   148,
384    150,   152,   179,   158,   159,   166,   167,   168,   169,   170,
385    171,   172,   164,   173,   174,   175,   180,   188,   176,   181,
386    182,   183,   184,   185,   186,   187,   189,   197,   194,   196,
387    190,   198,   200,   210,   202,   193,   203,   192,   205,   207,
388      0,   195,     0,     0,     0,     0,     0,     0,     0,   199,
389      0,     0,     0,     0,     0,     0,     0,   204,     0,     0,
390      0,     0,     0,     0,     0,   206,     0,     0,     0,     0,
391      0,     0,     0,     0,   208
392 };
393
394 static const short yycheck[] = {    92,
395     93,    15,    49,    81,    97,    98,    99,   100,    16,   102,
396      4,     5,     7,    60,    61,    62,    11,    12,   111,    13,
397    113,   114,    15,     7,   117,   118,   119,    11,    12,    13,
398     15,    16,    16,    17,    15,    19,    20,    21,    22,    16,
399     24,     0,     1,    27,    28,    29,    30,    31,   126,    33,
400     34,    65,     5,    15,    16,    15,    16,    10,    15,    18,
401     19,    14,    16,    22,    23,    24,    25,    26,    27,    28,
402     29,    30,     3,    15,    58,     6,    15,     8,     9,    38,
403     39,    40,    41,    42,    43,    44,    45,    46,    47,    48,
404     49,    50,    51,    52,    53,    54,    55,    15,    57,    58,
405     59,    15,    16,    15,   197,    15,    16,    15,    16,    15,
406     16,    15,    64,    16,    16,    16,    64,    15,    65,    16,
407     15,    15,    15,   107,    65,   109,    15,    15,    15,    15,
408     64,    15,    15,    65,    16,    16,    15,    15,    15,    64,
409     16,    16,    15,    15,    64,    16,    16,    16,    16,    16,
410     61,    16,    15,    17,    16,    16,    16,    16,    12,    16,
411     16,    16,   125,    16,    16,    16,    15,    15,    64,    16,
412     16,    16,    16,    16,    16,    65,    16,    15,    17,    16,
413     65,    16,    16,     0,    17,    65,    16,   179,    17,    17,
414     -1,    65,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    65,
415     -1,    -1,    -1,    -1,    -1,    -1,    -1,    65,    -1,    -1,
416     -1,    -1,    -1,    -1,    -1,    65,    -1,    -1,    -1,    -1,
417     -1,    -1,    -1,    -1,    65
418 };
419 /* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
420 #line 3 "/usr/share/bison/bison.simple"
421 /* This file comes from bison-1.28.  */
422
423 /* Skeleton output parser for bison,
424    Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
425
426    This program is free software; you can redistribute it and/or modify
427    it under the terms of the GNU General Public License as published by
428    the Free Software Foundation; either version 2, or (at your option)
429    any later version.
430
431    This program is distributed in the hope that it will be useful,
432    but WITHOUT ANY WARRANTY; without even the implied warranty of
433    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
434    GNU General Public License for more details.
435
436    You should have received a copy of the GNU General Public License
437    along with this program; if not, write to the Free Software
438    Foundation, Inc., 59 Temple Place - Suite 330,
439    Boston, MA 02111-1307, USA.  */
440
441 /* As a special exception, when this file is copied by Bison into a
442    Bison output file, you may use that output file without restriction.
443    This special exception was added by the Free Software Foundation
444    in version 1.24 of Bison.  */
445
446 /* This is the parser code that is written into each bison parser
447   when the %semantic_parser declaration is not specified in the grammar.
448   It was written by Richard Stallman by simplifying the hairy parser
449   used when %semantic_parser is specified.  */
450
451 #ifndef YYSTACK_USE_ALLOCA
452 #ifdef alloca
453 #define YYSTACK_USE_ALLOCA
454 #else /* alloca not defined */
455 #ifdef __GNUC__
456 #define YYSTACK_USE_ALLOCA
457 #define alloca __builtin_alloca
458 #else /* not GNU C.  */
459 #if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
460 #define YYSTACK_USE_ALLOCA
461 #include <alloca.h>
462 #else /* not sparc */
463 /* We think this test detects Watcom and Microsoft C.  */
464 /* This used to test MSDOS, but that is a bad idea
465    since that symbol is in the user namespace.  */
466 #if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
467 #if 0 /* No need for malloc.h, which pollutes the namespace;
468          instead, just don't use alloca.  */
469 #include <malloc.h>
470 #endif
471 #else /* not MSDOS, or __TURBOC__ */
472 #if defined(_AIX)
473 /* I don't know what this was needed for, but it pollutes the namespace.
474    So I turned it off.   rms, 2 May 1997.  */
475 /* #include <malloc.h>  */
476  #pragma alloca
477 #define YYSTACK_USE_ALLOCA
478 #else /* not MSDOS, or __TURBOC__, or _AIX */
479 #if 0
480 #ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
481                  and on HPUX 10.  Eventually we can turn this on.  */
482 #define YYSTACK_USE_ALLOCA
483 #define alloca __builtin_alloca
484 #endif /* __hpux */
485 #endif
486 #endif /* not _AIX */
487 #endif /* not MSDOS, or __TURBOC__ */
488 #endif /* not sparc */
489 #endif /* not GNU C */
490 #endif /* alloca not defined */
491 #endif /* YYSTACK_USE_ALLOCA not defined */
492
493 #ifdef YYSTACK_USE_ALLOCA
494 #define YYSTACK_ALLOC alloca
495 #else
496 #define YYSTACK_ALLOC malloc
497 #endif
498
499 /* Note: there must be only one dollar sign in this file.
500    It is replaced by the list of actions, each action
501    as one case of the switch.  */
502
503 #define yyerrok         (yyerrstatus = 0)
504 #define yyclearin       (yychar = YYEMPTY)
505 #define YYEMPTY         -2
506 #define YYEOF           0
507 #define YYACCEPT        goto yyacceptlab
508 #define YYABORT         goto yyabortlab
509 #define YYERROR         goto yyerrlab1
510 /* Like YYERROR except do call yyerror.
511    This remains here temporarily to ease the
512    transition to the new meaning of YYERROR, for GCC.
513    Once GCC version 2 has supplanted version 1, this can go.  */
514 #define YYFAIL          goto yyerrlab
515 #define YYRECOVERING()  (!!yyerrstatus)
516 #define YYBACKUP(token, value) \
517 do                                                              \
518   if (yychar == YYEMPTY && yylen == 1)                          \
519     { yychar = (token), yylval = (value);                       \
520       yychar1 = YYTRANSLATE (yychar);                           \
521       YYPOPSTACK;                                               \
522       goto yybackup;                                            \
523     }                                                           \
524   else                                                          \
525     { yyerror ("syntax error: cannot back up"); YYERROR; }      \
526 while (0)
527
528 #define YYTERROR        1
529 #define YYERRCODE       256
530
531 #ifndef YYPURE
532 #define YYLEX           yylex()
533 #endif
534
535 #ifdef YYPURE
536 #ifdef YYLSP_NEEDED
537 #ifdef YYLEX_PARAM
538 #define YYLEX           yylex(&yylval, &yylloc, YYLEX_PARAM)
539 #else
540 #define YYLEX           yylex(&yylval, &yylloc)
541 #endif
542 #else /* not YYLSP_NEEDED */
543 #ifdef YYLEX_PARAM
544 #define YYLEX           yylex(&yylval, YYLEX_PARAM)
545 #else
546 #define YYLEX           yylex(&yylval)
547 #endif
548 #endif /* not YYLSP_NEEDED */
549 #endif
550
551 /* If nonreentrant, generate the variables here */
552
553 #ifndef YYPURE
554
555 int     yychar;                 /*  the lookahead symbol                */
556 YYSTYPE yylval;                 /*  the semantic value of the           */
557                                 /*  lookahead symbol                    */
558
559 #ifdef YYLSP_NEEDED
560 YYLTYPE yylloc;                 /*  location data for the lookahead     */
561                                 /*  symbol                              */
562 #endif
563
564 int yynerrs;                    /*  number of parse errors so far       */
565 #endif  /* not YYPURE */
566
567 #if YYDEBUG != 0
568 int yydebug;                    /*  nonzero means print parse trace     */
569 /* Since this is uninitialized, it does not stop multiple parsers
570    from coexisting.  */
571 #endif
572
573 /*  YYINITDEPTH indicates the initial size of the parser's stacks       */
574
575 #ifndef YYINITDEPTH
576 #define YYINITDEPTH 200
577 #endif
578
579 /*  YYMAXDEPTH is the maximum size the stacks can grow to
580     (effective only if the built-in stack extension method is used).  */
581
582 #if YYMAXDEPTH == 0
583 #undef YYMAXDEPTH
584 #endif
585
586 #ifndef YYMAXDEPTH
587 #define YYMAXDEPTH 10000
588 #endif
589 \f
590 /* Define __yy_memcpy.  Note that the size argument
591    should be passed with type unsigned int, because that is what the non-GCC
592    definitions require.  With GCC, __builtin_memcpy takes an arg
593    of type size_t, but it can handle unsigned int.  */
594
595 #if __GNUC__ > 1                /* GNU C and GNU C++ define this.  */
596 #define __yy_memcpy(TO,FROM,COUNT)      __builtin_memcpy(TO,FROM,COUNT)
597 #else                           /* not GNU C or C++ */
598 #ifndef __cplusplus
599
600 /* This is the most reliable way to avoid incompatibilities
601    in available built-in functions on various systems.  */
602 static void
603 __yy_memcpy (to, from, count)
604      char *to;
605      char *from;
606      unsigned int count;
607 {
608   register char *f = from;
609   register char *t = to;
610   register int i = count;
611
612   while (i-- > 0)
613     *t++ = *f++;
614 }
615
616 #else /* __cplusplus */
617
618 /* This is the most reliable way to avoid incompatibilities
619    in available built-in functions on various systems.  */
620 static void
621 __yy_memcpy (char *to, char *from, unsigned int count)
622 {
623   register char *t = to;
624   register char *f = from;
625   register int i = count;
626
627   while (i-- > 0)
628     *t++ = *f++;
629 }
630
631 #endif
632 #endif
633 \f
634 #line 217 "/usr/share/bison/bison.simple"
635
636 /* The user can define YYPARSE_PARAM as the name of an argument to be passed
637    into yyparse.  The argument should have type void *.
638    It should actually point to an object.
639    Grammar actions can access the variable by casting it
640    to the proper pointer type.  */
641
642 #ifdef YYPARSE_PARAM
643 #ifdef __cplusplus
644 #define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
645 #define YYPARSE_PARAM_DECL
646 #else /* not __cplusplus */
647 #define YYPARSE_PARAM_ARG YYPARSE_PARAM
648 #define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
649 #endif /* not __cplusplus */
650 #else /* not YYPARSE_PARAM */
651 #define YYPARSE_PARAM_ARG
652 #define YYPARSE_PARAM_DECL
653 #endif /* not YYPARSE_PARAM */
654
655 /* Prevent warning if -Wstrict-prototypes.  */
656 #ifdef __GNUC__
657 #ifdef YYPARSE_PARAM
658 int yyparse (void *);
659 #else
660 int yyparse (void);
661 #endif
662 #endif
663
664 int
665 yyparse(YYPARSE_PARAM_ARG)
666      YYPARSE_PARAM_DECL
667 {
668   register int yystate;
669   register int yyn;
670   register short *yyssp;
671   register YYSTYPE *yyvsp;
672   int yyerrstatus;      /*  number of tokens to shift before error messages enabled */
673   int yychar1 = 0;              /*  lookahead token as an internal (translated) token number */
674
675   short yyssa[YYINITDEPTH];     /*  the state stack                     */
676   YYSTYPE yyvsa[YYINITDEPTH];   /*  the semantic value stack            */
677
678   short *yyss = yyssa;          /*  refer to the stacks thru separate pointers */
679   YYSTYPE *yyvs = yyvsa;        /*  to allow yyoverflow to reallocate them elsewhere */
680
681 #ifdef YYLSP_NEEDED
682   YYLTYPE yylsa[YYINITDEPTH];   /*  the location stack                  */
683   YYLTYPE *yyls = yylsa;
684   YYLTYPE *yylsp;
685
686 #define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
687 #else
688 #define YYPOPSTACK   (yyvsp--, yyssp--)
689 #endif
690
691   int yystacksize = YYINITDEPTH;
692   int yyfree_stacks = 0;
693
694 #ifdef YYPURE
695   int yychar;
696   YYSTYPE yylval;
697   int yynerrs;
698 #ifdef YYLSP_NEEDED
699   YYLTYPE yylloc;
700 #endif
701 #endif
702
703   YYSTYPE yyval;                /*  the variable used to return         */
704                                 /*  semantic values from the action     */
705                                 /*  routines                            */
706
707   int yylen;
708
709 #if YYDEBUG != 0
710   if (yydebug)
711     fprintf(stderr, "Starting parse\n");
712 #endif
713
714   yystate = 0;
715   yyerrstatus = 0;
716   yynerrs = 0;
717   yychar = YYEMPTY;             /* Cause a token to be read.  */
718
719   /* Initialize stack pointers.
720      Waste one element of value and location stack
721      so that they stay on the same level as the state stack.
722      The wasted elements are never initialized.  */
723
724   yyssp = yyss - 1;
725   yyvsp = yyvs;
726 #ifdef YYLSP_NEEDED
727   yylsp = yyls;
728 #endif
729
730 /* Push a new state, which is found in  yystate  .  */
731 /* In all cases, when you get here, the value and location stacks
732    have just been pushed. so pushing a state here evens the stacks.  */
733 yynewstate:
734
735   *++yyssp = yystate;
736
737   if (yyssp >= yyss + yystacksize - 1)
738     {
739       /* Give user a chance to reallocate the stack */
740       /* Use copies of these so that the &'s don't force the real ones into memory. */
741       YYSTYPE *yyvs1 = yyvs;
742       short *yyss1 = yyss;
743 #ifdef YYLSP_NEEDED
744       YYLTYPE *yyls1 = yyls;
745 #endif
746
747       /* Get the current used size of the three stacks, in elements.  */
748       int size = yyssp - yyss + 1;
749
750 #ifdef yyoverflow
751       /* Each stack pointer address is followed by the size of
752          the data in use in that stack, in bytes.  */
753 #ifdef YYLSP_NEEDED
754       /* This used to be a conditional around just the two extra args,
755          but that might be undefined if yyoverflow is a macro.  */
756       yyoverflow("parser stack overflow",
757                  &yyss1, size * sizeof (*yyssp),
758                  &yyvs1, size * sizeof (*yyvsp),
759                  &yyls1, size * sizeof (*yylsp),
760                  &yystacksize);
761 #else
762       yyoverflow("parser stack overflow",
763                  &yyss1, size * sizeof (*yyssp),
764                  &yyvs1, size * sizeof (*yyvsp),
765                  &yystacksize);
766 #endif
767
768       yyss = yyss1; yyvs = yyvs1;
769 #ifdef YYLSP_NEEDED
770       yyls = yyls1;
771 #endif
772 #else /* no yyoverflow */
773       /* Extend the stack our own way.  */
774       if (yystacksize >= YYMAXDEPTH)
775         {
776           yyerror("parser stack overflow");
777           if (yyfree_stacks)
778             {
779               free (yyss);
780               free (yyvs);
781 #ifdef YYLSP_NEEDED
782               free (yyls);
783 #endif
784             }
785           return 2;
786         }
787       yystacksize *= 2;
788       if (yystacksize > YYMAXDEPTH)
789         yystacksize = YYMAXDEPTH;
790 #ifndef YYSTACK_USE_ALLOCA
791       yyfree_stacks = 1;
792 #endif
793       yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
794       __yy_memcpy ((char *)yyss, (char *)yyss1,
795                    size * (unsigned int) sizeof (*yyssp));
796       yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
797       __yy_memcpy ((char *)yyvs, (char *)yyvs1,
798                    size * (unsigned int) sizeof (*yyvsp));
799 #ifdef YYLSP_NEEDED
800       yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
801       __yy_memcpy ((char *)yyls, (char *)yyls1,
802                    size * (unsigned int) sizeof (*yylsp));
803 #endif
804 #endif /* no yyoverflow */
805
806       yyssp = yyss + size - 1;
807       yyvsp = yyvs + size - 1;
808 #ifdef YYLSP_NEEDED
809       yylsp = yyls + size - 1;
810 #endif
811
812 #if YYDEBUG != 0
813       if (yydebug)
814         fprintf(stderr, "Stack size increased to %d\n", yystacksize);
815 #endif
816
817       if (yyssp >= yyss + yystacksize - 1)
818         YYABORT;
819     }
820
821 #if YYDEBUG != 0
822   if (yydebug)
823     fprintf(stderr, "Entering state %d\n", yystate);
824 #endif
825
826   goto yybackup;
827  yybackup:
828
829 /* Do appropriate processing given the current state.  */
830 /* Read a lookahead token if we need one and don't already have one.  */
831 /* yyresume: */
832
833   /* First try to decide what to do without reference to lookahead token.  */
834
835   yyn = yypact[yystate];
836   if (yyn == YYFLAG)
837     goto yydefault;
838
839   /* Not known => get a lookahead token if don't already have one.  */
840
841   /* yychar is either YYEMPTY or YYEOF
842      or a valid token in external form.  */
843
844   if (yychar == YYEMPTY)
845     {
846 #if YYDEBUG != 0
847       if (yydebug)
848         fprintf(stderr, "Reading a token: ");
849 #endif
850       yychar = YYLEX;
851     }
852
853   /* Convert token to internal form (in yychar1) for indexing tables with */
854
855   if (yychar <= 0)              /* This means end of input. */
856     {
857       yychar1 = 0;
858       yychar = YYEOF;           /* Don't call YYLEX any more */
859
860 #if YYDEBUG != 0
861       if (yydebug)
862         fprintf(stderr, "Now at end of input.\n");
863 #endif
864     }
865   else
866     {
867       yychar1 = YYTRANSLATE(yychar);
868
869 #if YYDEBUG != 0
870       if (yydebug)
871         {
872           fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
873           /* Give the individual parser a way to print the precise meaning
874              of a token, for further debugging info.  */
875 #ifdef YYPRINT
876           YYPRINT (stderr, yychar, yylval);
877 #endif
878           fprintf (stderr, ")\n");
879         }
880 #endif
881     }
882
883   yyn += yychar1;
884   if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
885     goto yydefault;
886
887   yyn = yytable[yyn];
888
889   /* yyn is what to do for this token type in this state.
890      Negative => reduce, -yyn is rule number.
891      Positive => shift, yyn is new state.
892        New state is final state => don't bother to shift,
893        just return success.
894      0, or most negative number => error.  */
895
896   if (yyn < 0)
897     {
898       if (yyn == YYFLAG)
899         goto yyerrlab;
900       yyn = -yyn;
901       goto yyreduce;
902     }
903   else if (yyn == 0)
904     goto yyerrlab;
905
906   if (yyn == YYFINAL)
907     YYACCEPT;
908
909   /* Shift the lookahead token.  */
910
911 #if YYDEBUG != 0
912   if (yydebug)
913     fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
914 #endif
915
916   /* Discard the token being shifted unless it is eof.  */
917   if (yychar != YYEOF)
918     yychar = YYEMPTY;
919
920   *++yyvsp = yylval;
921 #ifdef YYLSP_NEEDED
922   *++yylsp = yylloc;
923 #endif
924
925   /* count tokens shifted since error; after three, turn off error status.  */
926   if (yyerrstatus) yyerrstatus--;
927
928   yystate = yyn;
929   goto yynewstate;
930
931 /* Do the default action for the current state.  */
932 yydefault:
933
934   yyn = yydefact[yystate];
935   if (yyn == 0)
936     goto yyerrlab;
937
938 /* Do a reduction.  yyn is the number of a rule to reduce with.  */
939 yyreduce:
940   yylen = yyr2[yyn];
941   if (yylen > 0)
942     yyval = yyvsp[1-yylen]; /* implement default value of the action */
943
944 #if YYDEBUG != 0
945   if (yydebug)
946     {
947       int i;
948
949       fprintf (stderr, "Reducing via rule %d (line %d), ",
950                yyn, yyrline[yyn]);
951
952       /* Print the symbols being reduced, and their result.  */
953       for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
954         fprintf (stderr, "%s ", yytname[yyrhs[i]]);
955       fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
956     }
957 #endif
958
959
960   switch (yyn) {
961
962 case 2:
963 #line 154 "ftpcmd.y"
964 {
965                         if (fromname != NULL)
966                                 free (fromname);
967                         fromname = (char *) 0;
968                         restart_point = (off_t) 0;
969                 ;
970     break;}
971 case 4:
972 #line 165 "ftpcmd.y"
973 {
974                         user(yyvsp[-1].s);
975                         free(yyvsp[-1].s);
976                 ;
977     break;}
978 case 5:
979 #line 170 "ftpcmd.y"
980 {
981                         pass(yyvsp[-1].s);
982                         memset (yyvsp[-1].s, 0, strlen (yyvsp[-1].s));
983                         free(yyvsp[-1].s);
984                 ;
985     break;}
986 case 6:
987 #line 176 "ftpcmd.y"
988 {
989                         usedefault = 0;
990                         if (pdata >= 0) {
991                                 (void) close(pdata);
992                                 pdata = -1;
993                         }
994                         if (yyvsp[-3].i) {
995                                 if (memcmp (&his_addr.sin_addr,
996                                         &data_dest.sin_addr,
997                                         sizeof (data_dest.sin_addr)) == 0 &&
998                                         ntohs (data_dest.sin_port) >
999                                         IPPORT_RESERVED) {
1000                                         reply (200, "PORT command sucessful.");
1001                                 }
1002                                 else {
1003                                         memset (&data_dest, 0,
1004                                                 sizeof (data_dest));
1005                                         reply(500, "Illegal PORT Command");
1006                                 }
1007                         }
1008                 ;
1009     break;}
1010 case 7:
1011 #line 198 "ftpcmd.y"
1012 {
1013                         if (yyvsp[-1].i)
1014                                 passive();
1015                 ;
1016     break;}
1017 case 8:
1018 #line 203 "ftpcmd.y"
1019 {
1020                         switch (cmd_type) {
1021
1022                         case TYPE_A:
1023                                 if (cmd_form == FORM_N) {
1024                                         reply(200, "Type set to A.");
1025                                         type = cmd_type;
1026                                         form = cmd_form;
1027                                 } else
1028                                         reply(504, "Form must be N.");
1029                                 break;
1030
1031                         case TYPE_E:
1032                                 reply(504, "Type E not implemented.");
1033                                 break;
1034
1035                         case TYPE_I:
1036                                 reply(200, "Type set to I.");
1037                                 type = cmd_type;
1038                                 break;
1039
1040                         case TYPE_L:
1041 #if defined (NBBY) && NBBY == 8
1042                                 if (cmd_bytesz == 8) {
1043                                         reply(200,
1044                                             "Type set to L (byte size 8).");
1045                                         type = cmd_type;
1046                                 } else
1047                                         reply(504, "Byte size must be 8.");
1048 #else /* NBBY == 8 */
1049                                 UNIMPLEMENTED for NBBY != 8
1050 #endif /* NBBY == 8 */
1051                         }
1052                 ;
1053     break;}
1054 case 9:
1055 #line 238 "ftpcmd.y"
1056 {
1057                         switch (yyvsp[-1].i) {
1058
1059                         case STRU_F:
1060                                 reply(200, "STRU F ok.");
1061                                 break;
1062
1063                         default:
1064                                 reply(504, "Unimplemented STRU type.");
1065                         }
1066                 ;
1067     break;}
1068 case 10:
1069 #line 250 "ftpcmd.y"
1070 {
1071                         switch (yyvsp[-1].i) {
1072
1073                         case MODE_S:
1074                                 reply(200, "MODE S ok.");
1075                                 break;
1076
1077                         default:
1078                                 reply(502, "Unimplemented MODE type.");
1079                         }
1080                 ;
1081     break;}
1082 case 11:
1083 #line 262 "ftpcmd.y"
1084 {
1085                         reply(202, "ALLO command ignored.");
1086                 ;
1087     break;}
1088 case 12:
1089 #line 266 "ftpcmd.y"
1090 {
1091                         reply(202, "ALLO command ignored.");
1092                 ;
1093     break;}
1094 case 13:
1095 #line 270 "ftpcmd.y"
1096 {
1097                         if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1098                                 retrieve((char *) 0, yyvsp[-1].s);
1099                         if (yyvsp[-1].s != NULL)
1100                                 free(yyvsp[-1].s);
1101                 ;
1102     break;}
1103 case 14:
1104 #line 277 "ftpcmd.y"
1105 {
1106                         if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1107                                 store(yyvsp[-1].s, "w", 0);
1108                         if (yyvsp[-1].s != NULL)
1109                                 free(yyvsp[-1].s);
1110                 ;
1111     break;}
1112 case 15:
1113 #line 284 "ftpcmd.y"
1114 {
1115                         if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1116                                 store(yyvsp[-1].s, "a", 0);
1117                         if (yyvsp[-1].s != NULL)
1118                                 free(yyvsp[-1].s);
1119                 ;
1120     break;}
1121 case 16:
1122 #line 291 "ftpcmd.y"
1123 {
1124                         if (yyvsp[-1].i)
1125                                 send_file_list(".");
1126                 ;
1127     break;}
1128 case 17:
1129 #line 296 "ftpcmd.y"
1130 {
1131                         if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1132                                 send_file_list(yyvsp[-1].s);
1133                         if (yyvsp[-1].s != NULL)
1134                                 free(yyvsp[-1].s);
1135                 ;
1136     break;}
1137 case 18:
1138 #line 303 "ftpcmd.y"
1139 {
1140                         if (yyvsp[-1].i)
1141                                 retrieve("/bin/ls -lgA", "");
1142                 ;
1143     break;}
1144 case 19:
1145 #line 308 "ftpcmd.y"
1146 {
1147                         if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1148                                 retrieve("/bin/ls -lgA %s", yyvsp[-1].s);
1149                         if (yyvsp[-1].s != NULL)
1150                                 free(yyvsp[-1].s);
1151                 ;
1152     break;}
1153 case 20:
1154 #line 315 "ftpcmd.y"
1155 {
1156                         if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1157                                 statfilecmd(yyvsp[-1].s);
1158                         if (yyvsp[-1].s != NULL)
1159                                 free(yyvsp[-1].s);
1160                 ;
1161     break;}
1162 case 21:
1163 #line 322 "ftpcmd.y"
1164 {
1165                         statcmd();
1166                 ;
1167     break;}
1168 case 22:
1169 #line 326 "ftpcmd.y"
1170 {
1171                         if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1172                                 delete(yyvsp[-1].s);
1173                         if (yyvsp[-1].s != NULL)
1174                                 free(yyvsp[-1].s);
1175                 ;
1176     break;}
1177 case 23:
1178 #line 333 "ftpcmd.y"
1179 {
1180                     if (yyvsp[-3].i) {
1181                         if (fromname) {
1182                                 renamecmd(fromname, yyvsp[-1].s);
1183                                 free(fromname);
1184                                 fromname = (char *) 0;
1185                         } else {
1186                                 reply(503, "Bad sequence of commands.");
1187                         }
1188                     }
1189                     free (yyvsp[-1].s);
1190                 ;
1191     break;}
1192 case 24:
1193 #line 346 "ftpcmd.y"
1194 {
1195                         reply(225, "ABOR command successful.");
1196                 ;
1197     break;}
1198 case 25:
1199 #line 350 "ftpcmd.y"
1200 {
1201                         if (yyvsp[-1].i)
1202                                 cwd(cred.homedir);
1203                 ;
1204     break;}
1205 case 26:
1206 #line 355 "ftpcmd.y"
1207 {
1208                         if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1209                                 cwd(yyvsp[-1].s);
1210                         if (yyvsp[-1].s != NULL)
1211                                 free(yyvsp[-1].s);
1212                 ;
1213     break;}
1214 case 27:
1215 #line 362 "ftpcmd.y"
1216 {
1217                         help(cmdtab, (char *) 0);
1218                 ;
1219     break;}
1220 case 28:
1221 #line 366 "ftpcmd.y"
1222 {
1223                         char *cp = yyvsp[-1].s;
1224
1225                         if (strncasecmp(cp, "SITE", 4) == 0) {
1226                                 cp = yyvsp[-1].s + 4;
1227                                 if (*cp == ' ')
1228                                         cp++;
1229                                 if (*cp)
1230                                         help(sitetab, cp);
1231                                 else
1232                                         help(sitetab, (char *) 0);
1233                         } else
1234                                 help(cmdtab, yyvsp[-1].s);
1235                         if (yyvsp[-1].s != NULL)
1236                             free (yyvsp[-1].s);
1237                 ;
1238     break;}
1239 case 29:
1240 #line 383 "ftpcmd.y"
1241 {
1242                         reply(200, "NOOP command successful.");
1243                 ;
1244     break;}
1245 case 30:
1246 #line 387 "ftpcmd.y"
1247 {
1248                         if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1249                                 makedir(yyvsp[-1].s);
1250                         if (yyvsp[-1].s != NULL)
1251                                 free(yyvsp[-1].s);
1252                 ;
1253     break;}
1254 case 31:
1255 #line 394 "ftpcmd.y"
1256 {
1257                         if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1258                                 removedir(yyvsp[-1].s);
1259                         if (yyvsp[-1].s != NULL)
1260                                 free(yyvsp[-1].s);
1261                 ;
1262     break;}
1263 case 32:
1264 #line 401 "ftpcmd.y"
1265 {
1266                         if (yyvsp[-1].i)
1267                                 pwd();
1268                 ;
1269     break;}
1270 case 33:
1271 #line 406 "ftpcmd.y"
1272 {
1273                         if (yyvsp[-1].i)
1274                                 cwd("..");
1275                 ;
1276     break;}
1277 case 34:
1278 #line 411 "ftpcmd.y"
1279 {
1280                         help(sitetab, (char *) 0);
1281                 ;
1282     break;}
1283 case 35:
1284 #line 415 "ftpcmd.y"
1285 {
1286                         help(sitetab, yyvsp[-1].s);
1287                         if (yyvsp[-1].s != NULL)
1288                             free (yyvsp[-1].s);
1289                 ;
1290     break;}
1291 case 36:
1292 #line 421 "ftpcmd.y"
1293 {
1294                         int oldmask;
1295
1296                         if (yyvsp[-1].i) {
1297                                 oldmask = umask(0);
1298                                 (void) umask(oldmask);
1299                                 reply(200, "Current UMASK is %03o", oldmask);
1300                         }
1301                 ;
1302     break;}
1303 case 37:
1304 #line 431 "ftpcmd.y"
1305 {
1306                         int oldmask;
1307
1308                         if (yyvsp[-3].i) {
1309                                 if ((yyvsp[-1].i == -1) || (yyvsp[-1].i > 0777)) {
1310                                         reply(501, "Bad UMASK value");
1311                                 } else {
1312                                         oldmask = umask(yyvsp[-1].i);
1313                                         reply(200,
1314                                             "UMASK set to %03o (was %03o)",
1315                                             yyvsp[-1].i, oldmask);
1316                                 }
1317                         }
1318                 ;
1319     break;}
1320 case 38:
1321 #line 446 "ftpcmd.y"
1322 {
1323                         if (yyvsp[-5].i && (yyvsp[-1].s != NULL)) {
1324                                 if (yyvsp[-3].i > 0777)
1325                                         reply(501,
1326                                 "CHMOD: Mode value must be between 0 and 0777");
1327                                 else if (chmod(yyvsp[-1].s, yyvsp[-3].i) < 0)
1328                                         perror_reply(550, yyvsp[-1].s);
1329                                 else
1330                                         reply(200, "CHMOD command successful.");
1331                         }
1332                         if (yyvsp[-1].s != NULL)
1333                                 free(yyvsp[-1].s);
1334                 ;
1335     break;}
1336 case 39:
1337 #line 460 "ftpcmd.y"
1338 {
1339                         reply(200,
1340                             "Current IDLE time limit is %d seconds; max %d",
1341                                 timeout, maxtimeout);
1342                 ;
1343     break;}
1344 case 40:
1345 #line 466 "ftpcmd.y"
1346 {
1347                         if (yyvsp[-4].i) {
1348                             if (yyvsp[-1].i < 30 || yyvsp[-1].i > maxtimeout) {
1349                                 reply (501,
1350                         "Maximum IDLE time must be between 30 and %d seconds",
1351                                         maxtimeout);
1352                             } else {
1353                                 timeout = yyvsp[-1].i;
1354                                 (void) alarm((unsigned) timeout);
1355                                 reply(200,
1356                                         "Maximum IDLE time set to %d seconds",
1357                                         timeout);
1358                             }
1359                         }
1360                 ;
1361     break;}
1362 case 41:
1363 #line 482 "ftpcmd.y"
1364 {
1365                         if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1366                                 store(yyvsp[-1].s, "w", 1);
1367                         if (yyvsp[-1].s != NULL)
1368                                 free(yyvsp[-1].s);
1369                 ;
1370     break;}
1371 case 42:
1372 #line 489 "ftpcmd.y"
1373 {
1374                         const char *sys_type; /* Official rfc-defined os type.  */
1375                         char *version = 0; /* A more specific type. */
1376
1377 #ifdef HAVE_UNAME
1378                         struct utsname u;
1379                         if (uname (&u) == 0) {
1380                                 version =
1381                                   malloc (strlen (u.sysname)
1382                                           + 1 + strlen (u.release) + 1);
1383                                 if (version)
1384                                         sprintf (version, "%s %s",
1385                                                  u.sysname, u.release);
1386                         }
1387 #else
1388 #ifdef BSD
1389                         version = "BSD";
1390 #endif
1391 #endif
1392
1393 #ifdef unix
1394                         sys_type = "UNIX";
1395 #else
1396                         sys_type = "UNKNOWN";
1397 #endif
1398
1399                         if (version)
1400                                 reply(215, "%s Type: L%d Version: %s",
1401                                       sys_type, NBBY, version);
1402                         else
1403                                 reply(215, "%s Type: L%d", sys_type, NBBY);
1404
1405 #ifdef HAVE_UNAME
1406                         if (version)
1407                                 free (version);
1408 #endif
1409                 ;
1410     break;}
1411 case 43:
1412 #line 535 "ftpcmd.y"
1413 {
1414                         if (yyvsp[-3].i && yyvsp[-1].s != NULL)
1415                                 sizecmd(yyvsp[-1].s);
1416                         if (yyvsp[-1].s != NULL)
1417                                 free(yyvsp[-1].s);
1418                 ;
1419     break;}
1420 case 44:
1421 #line 552 "ftpcmd.y"
1422 {
1423                         if (yyvsp[-3].i && yyvsp[-1].s != NULL) {
1424                                 struct stat stbuf;
1425                                 if (stat(yyvsp[-1].s, &stbuf) < 0)
1426                                         reply(550, "%s: %s",
1427                                             yyvsp[-1].s, strerror(errno));
1428                                 else if (!S_ISREG(stbuf.st_mode)) {
1429                                         reply(550, "%s: not a plain file.", yyvsp[-1].s);
1430                                 } else {
1431                                         struct tm *t;
1432                                         t = gmtime(&stbuf.st_mtime);
1433                                         reply(213,
1434                                             "%04d%02d%02d%02d%02d%02d",
1435                                             1900 + t->tm_year, t->tm_mon+1,
1436                                             t->tm_mday, t->tm_hour, t->tm_min,
1437                                             t->tm_sec);
1438                                 }
1439                         }
1440                         if (yyvsp[-1].s != NULL)
1441                                 free(yyvsp[-1].s);
1442                 ;
1443     break;}
1444 case 45:
1445 #line 574 "ftpcmd.y"
1446 {
1447                         reply(221, "Goodbye.");
1448                         dologout(0);
1449                 ;
1450     break;}
1451 case 46:
1452 #line 579 "ftpcmd.y"
1453 {
1454                         yyerrok;
1455                 ;
1456     break;}
1457 case 47:
1458 #line 585 "ftpcmd.y"
1459 {
1460                         restart_point = (off_t) 0;
1461                         if (yyvsp[-3].i && yyvsp[-1].s) {
1462                             if (fromname != NULL)
1463                                 free (fromname);
1464                             fromname = renamefrom(yyvsp[-1].s);
1465                         }
1466                         if (fromname == (char *) 0 && yyvsp[-1].s)
1467                             free(yyvsp[-1].s);
1468                 ;
1469     break;}
1470 case 48:
1471 #line 596 "ftpcmd.y"
1472 {
1473                         if (fromname != NULL)
1474                                 free (fromname);
1475                         fromname = (char *) 0;
1476                         restart_point = yyvsp[-1].i;    /* XXX $3 is only "int" */
1477                         reply(350,
1478                               (sizeof(restart_point) > sizeof(long)
1479                                ? "Restarting at %qd. %s"
1480                                : "Restarting at %ld. %s"), restart_point,
1481                             "Send STORE or RETRIEVE to initiate transfer.");
1482                 ;
1483     break;}
1484 case 50:
1485 #line 615 "ftpcmd.y"
1486 {
1487                         yyval.s = (char *)calloc(1, sizeof(char));
1488                 ;
1489     break;}
1490 case 53:
1491 #line 628 "ftpcmd.y"
1492 {
1493                         char *a, *p;
1494
1495                         a = (char *)&data_dest.sin_addr;
1496                         a[0] = yyvsp[-10].i; a[1] = yyvsp[-8].i; a[2] = yyvsp[-6].i; a[3] = yyvsp[-4].i;
1497                         p = (char *)&data_dest.sin_port;
1498                         p[0] = yyvsp[-2].i; p[1] = yyvsp[0].i;
1499                         data_dest.sin_family = AF_INET;
1500                 ;
1501     break;}
1502 case 54:
1503 #line 641 "ftpcmd.y"
1504 {
1505                         yyval.i = FORM_N;
1506                 ;
1507     break;}
1508 case 55:
1509 #line 645 "ftpcmd.y"
1510 {
1511                         yyval.i = FORM_T;
1512                 ;
1513     break;}
1514 case 56:
1515 #line 649 "ftpcmd.y"
1516 {
1517                         yyval.i = FORM_C;
1518                 ;
1519     break;}
1520 case 57:
1521 #line 656 "ftpcmd.y"
1522 {
1523                         cmd_type = TYPE_A;
1524                         cmd_form = FORM_N;
1525                 ;
1526     break;}
1527 case 58:
1528 #line 661 "ftpcmd.y"
1529 {
1530                         cmd_type = TYPE_A;
1531                         cmd_form = yyvsp[0].i;
1532                 ;
1533     break;}
1534 case 59:
1535 #line 666 "ftpcmd.y"
1536 {
1537                         cmd_type = TYPE_E;
1538                         cmd_form = FORM_N;
1539                 ;
1540     break;}
1541 case 60:
1542 #line 671 "ftpcmd.y"
1543 {
1544                         cmd_type = TYPE_E;
1545                         cmd_form = yyvsp[0].i;
1546                 ;
1547     break;}
1548 case 61:
1549 #line 676 "ftpcmd.y"
1550 {
1551                         cmd_type = TYPE_I;
1552                 ;
1553     break;}
1554 case 62:
1555 #line 680 "ftpcmd.y"
1556 {
1557                         cmd_type = TYPE_L;
1558                         cmd_bytesz = NBBY;
1559                 ;
1560     break;}
1561 case 63:
1562 #line 685 "ftpcmd.y"
1563 {
1564                         cmd_type = TYPE_L;
1565                         cmd_bytesz = yyvsp[0].i;
1566                 ;
1567     break;}
1568 case 64:
1569 #line 691 "ftpcmd.y"
1570 {
1571                         cmd_type = TYPE_L;
1572                         cmd_bytesz = yyvsp[0].i;
1573                 ;
1574     break;}
1575 case 65:
1576 #line 699 "ftpcmd.y"
1577 {
1578                         yyval.i = STRU_F;
1579                 ;
1580     break;}
1581 case 66:
1582 #line 703 "ftpcmd.y"
1583 {
1584                         yyval.i = STRU_R;
1585                 ;
1586     break;}
1587 case 67:
1588 #line 707 "ftpcmd.y"
1589 {
1590                         yyval.i = STRU_P;
1591                 ;
1592     break;}
1593 case 68:
1594 #line 714 "ftpcmd.y"
1595 {
1596                         yyval.i = MODE_S;
1597                 ;
1598     break;}
1599 case 69:
1600 #line 718 "ftpcmd.y"
1601 {
1602                         yyval.i = MODE_B;
1603                 ;
1604     break;}
1605 case 70:
1606 #line 722 "ftpcmd.y"
1607 {
1608                         yyval.i = MODE_C;
1609                 ;
1610     break;}
1611 case 71:
1612 #line 729 "ftpcmd.y"
1613 {
1614                         /*
1615                          * Problem: this production is used for all pathname
1616                          * processing, but only gives a 550 error reply.
1617                          * This is a valid reply in some cases but not in others.
1618                          */
1619                         if (cred.logged_in && yyvsp[0].s && *yyvsp[0].s == '~') {
1620                                 glob_t gl;
1621                                 int flags = GLOB_NOCHECK;
1622
1623 #ifdef GLOB_BRACE
1624                                 flags |= GLOB_BRACE;
1625 #endif
1626 #ifdef GLOB_QUOTE
1627                                 flags |= GLOB_QUOTE;
1628 #endif
1629 #ifdef GLOB_TILDE
1630                                 flags |= GLOB_TILDE;
1631 #endif
1632
1633                                 memset(&gl, 0, sizeof(gl));
1634                                 if (glob(yyvsp[0].s, flags, NULL, &gl) ||
1635                                     gl.gl_pathc == 0) {
1636                                         reply(550, "not found");
1637                                         yyval.s = NULL;
1638                                 } else {
1639                                         yyval.s = strdup(gl.gl_pathv[0]);
1640                                 }
1641                                 globfree(&gl);
1642                                 free(yyvsp[0].s);
1643                         } else
1644                                 yyval.s = yyvsp[0].s;
1645                 ;
1646     break;}
1647 case 73:
1648 #line 770 "ftpcmd.y"
1649 {
1650                         int ret, dec, multby, digit;
1651
1652                         /*
1653                          * Convert a number that was read as decimal number
1654                          * to what it would be if it had been read as octal.
1655                          */
1656                         dec = yyvsp[0].i;
1657                         multby = 1;
1658                         ret = 0;
1659                         while (dec) {
1660                                 digit = dec%10;
1661                                 if (digit > 7) {
1662                                         ret = -1;
1663                                         break;
1664                                 }
1665                                 ret += digit * multby;
1666                                 multby *= 8;
1667                                 dec /= 10;
1668                         }
1669                         yyval.i = ret;
1670                 ;
1671     break;}
1672 case 74:
1673 #line 797 "ftpcmd.y"
1674 {
1675                         if (cred.logged_in)
1676                                 yyval.i = 1;
1677                         else {
1678                                 reply(530, "Please login with USER and PASS.");
1679                                 yyval.i = 0;
1680                         }
1681                 ;
1682     break;}
1683 }
1684    /* the action file gets copied in in place of this dollarsign */
1685 #line 543 "/usr/share/bison/bison.simple"
1686 \f
1687   yyvsp -= yylen;
1688   yyssp -= yylen;
1689 #ifdef YYLSP_NEEDED
1690   yylsp -= yylen;
1691 #endif
1692
1693 #if YYDEBUG != 0
1694   if (yydebug)
1695     {
1696       short *ssp1 = yyss - 1;
1697       fprintf (stderr, "state stack now");
1698       while (ssp1 != yyssp)
1699         fprintf (stderr, " %d", *++ssp1);
1700       fprintf (stderr, "\n");
1701     }
1702 #endif
1703
1704   *++yyvsp = yyval;
1705
1706 #ifdef YYLSP_NEEDED
1707   yylsp++;
1708   if (yylen == 0)
1709     {
1710       yylsp->first_line = yylloc.first_line;
1711       yylsp->first_column = yylloc.first_column;
1712       yylsp->last_line = (yylsp-1)->last_line;
1713       yylsp->last_column = (yylsp-1)->last_column;
1714       yylsp->text = 0;
1715     }
1716   else
1717     {
1718       yylsp->last_line = (yylsp+yylen-1)->last_line;
1719       yylsp->last_column = (yylsp+yylen-1)->last_column;
1720     }
1721 #endif
1722
1723   /* Now "shift" the result of the reduction.
1724      Determine what state that goes to,
1725      based on the state we popped back to
1726      and the rule number reduced by.  */
1727
1728   yyn = yyr1[yyn];
1729
1730   yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
1731   if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
1732     yystate = yytable[yystate];
1733   else
1734     yystate = yydefgoto[yyn - YYNTBASE];
1735
1736   goto yynewstate;
1737
1738 yyerrlab:   /* here on detecting error */
1739
1740   if (! yyerrstatus)
1741     /* If not already recovering from an error, report this error.  */
1742     {
1743       ++yynerrs;
1744
1745 #ifdef YYERROR_VERBOSE
1746       yyn = yypact[yystate];
1747
1748       if (yyn > YYFLAG && yyn < YYLAST)
1749         {
1750           int size = 0;
1751           char *msg;
1752           int x, count;
1753
1754           count = 0;
1755           /* Start X at -yyn if nec to avoid negative indexes in yycheck.  */
1756           for (x = (yyn < 0 ? -yyn : 0);
1757                x < (sizeof(yytname) / sizeof(char *)); x++)
1758             if (yycheck[x + yyn] == x)
1759               size += strlen(yytname[x]) + 15, count++;
1760           msg = (char *) malloc(size + 15);
1761           if (msg != 0)
1762             {
1763               strcpy(msg, "parse error");
1764
1765               if (count < 5)
1766                 {
1767                   count = 0;
1768                   for (x = (yyn < 0 ? -yyn : 0);
1769                        x < (sizeof(yytname) / sizeof(char *)); x++)
1770                     if (yycheck[x + yyn] == x)
1771                       {
1772                         strcat(msg, count == 0 ? ", expecting `" : " or `");
1773                         strcat(msg, yytname[x]);
1774                         strcat(msg, "'");
1775                         count++;
1776                       }
1777                 }
1778               yyerror(msg);
1779               free(msg);
1780             }
1781           else
1782             yyerror ("parse error; also virtual memory exceeded");
1783         }
1784       else
1785 #endif /* YYERROR_VERBOSE */
1786         yyerror("parse error");
1787     }
1788
1789   goto yyerrlab1;
1790 yyerrlab1:   /* here on error raised explicitly by an action */
1791
1792   if (yyerrstatus == 3)
1793     {
1794       /* if just tried and failed to reuse lookahead token after an error, discard it.  */
1795
1796       /* return failure if at end of input */
1797       if (yychar == YYEOF)
1798         YYABORT;
1799
1800 #if YYDEBUG != 0
1801       if (yydebug)
1802         fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
1803 #endif
1804
1805       yychar = YYEMPTY;
1806     }
1807
1808   /* Else will try to reuse lookahead token
1809      after shifting the error token.  */
1810
1811   yyerrstatus = 3;              /* Each real token shifted decrements this */
1812
1813   goto yyerrhandle;
1814
1815 yyerrdefault:  /* current state does not do anything special for the error token. */
1816
1817 #if 0
1818   /* This is wrong; only states that explicitly want error tokens
1819      should shift them.  */
1820   yyn = yydefact[yystate];  /* If its default is to accept any token, ok.  Otherwise pop it.*/
1821   if (yyn) goto yydefault;
1822 #endif
1823
1824 yyerrpop:   /* pop the current state because it cannot handle the error token */
1825
1826   if (yyssp == yyss) YYABORT;
1827   yyvsp--;
1828   yystate = *--yyssp;
1829 #ifdef YYLSP_NEEDED
1830   yylsp--;
1831 #endif
1832
1833 #if YYDEBUG != 0
1834   if (yydebug)
1835     {
1836       short *ssp1 = yyss - 1;
1837       fprintf (stderr, "Error: state stack now");
1838       while (ssp1 != yyssp)
1839         fprintf (stderr, " %d", *++ssp1);
1840       fprintf (stderr, "\n");
1841     }
1842 #endif
1843
1844 yyerrhandle:
1845
1846   yyn = yypact[yystate];
1847   if (yyn == YYFLAG)
1848     goto yyerrdefault;
1849
1850   yyn += YYTERROR;
1851   if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
1852     goto yyerrdefault;
1853
1854   yyn = yytable[yyn];
1855   if (yyn < 0)
1856     {
1857       if (yyn == YYFLAG)
1858         goto yyerrpop;
1859       yyn = -yyn;
1860       goto yyreduce;
1861     }
1862   else if (yyn == 0)
1863     goto yyerrpop;
1864
1865   if (yyn == YYFINAL)
1866     YYACCEPT;
1867
1868 #if YYDEBUG != 0
1869   if (yydebug)
1870     fprintf(stderr, "Shifting error token, ");
1871 #endif
1872
1873   *++yyvsp = yylval;
1874 #ifdef YYLSP_NEEDED
1875   *++yylsp = yylloc;
1876 #endif
1877
1878   yystate = yyn;
1879   goto yynewstate;
1880
1881  yyacceptlab:
1882   /* YYACCEPT comes here.  */
1883   if (yyfree_stacks)
1884     {
1885       free (yyss);
1886       free (yyvs);
1887 #ifdef YYLSP_NEEDED
1888       free (yyls);
1889 #endif
1890     }
1891   return 0;
1892
1893  yyabortlab:
1894   /* YYABORT comes here.  */
1895   if (yyfree_stacks)
1896     {
1897       free (yyss);
1898       free (yyvs);
1899 #ifdef YYLSP_NEEDED
1900       free (yyls);
1901 #endif
1902     }
1903   return 1;
1904 }
1905 #line 807 "ftpcmd.y"
1906
1907
1908 #define CMD     0       /* beginning of command */
1909 #define ARGS    1       /* expect miscellaneous arguments */
1910 #define STR1    2       /* expect SP followed by STRING */
1911 #define STR2    3       /* expect STRING */
1912 #define OSTR    4       /* optional SP then STRING */
1913 #define ZSTR1   5       /* SP then optional STRING */
1914 #define ZSTR2   6       /* optional STRING after SP */
1915 #define SITECMD 7       /* SITE command */
1916 #define NSTR    8       /* Number followed by a string */
1917
1918 struct tab cmdtab[] = {         /* In order defined in RFC 765 */
1919         { "USER", USER, STR1, 1,        "<sp> username" },
1920         { "PASS", PASS, ZSTR1, 1,       "<sp> password" },
1921         { "ACCT", ACCT, STR1, 0,        "(specify account)" },
1922         { "SMNT", SMNT, ARGS, 0,        "(structure mount)" },
1923         { "REIN", REIN, ARGS, 0,        "(reinitialize server state)" },
1924         { "QUIT", QUIT, ARGS, 1,        "(terminate service)", },
1925         { "PORT", PORT, ARGS, 1,        "<sp> b0, b1, b2, b3, b4" },
1926         { "PASV", PASV, ARGS, 1,        "(set server in passive mode)" },
1927         { "TYPE", TYPE, ARGS, 1,        "<sp> [ A | E | I | L ]" },
1928         { "STRU", STRU, ARGS, 1,        "(specify file structure)" },
1929         { "MODE", MODE, ARGS, 1,        "(specify transfer mode)" },
1930         { "RETR", RETR, STR1, 1,        "<sp> file-name" },
1931         { "STOR", STOR, STR1, 1,        "<sp> file-name" },
1932         { "APPE", APPE, STR1, 1,        "<sp> file-name" },
1933         { "MLFL", MLFL, OSTR, 0,        "(mail file)" },
1934         { "MAIL", MAIL, OSTR, 0,        "(mail to user)" },
1935         { "MSND", MSND, OSTR, 0,        "(mail send to terminal)" },
1936         { "MSOM", MSOM, OSTR, 0,        "(mail send to terminal or mailbox)" },
1937         { "MSAM", MSAM, OSTR, 0,        "(mail send to terminal and mailbox)" },
1938         { "MRSQ", MRSQ, OSTR, 0,        "(mail recipient scheme question)" },
1939         { "MRCP", MRCP, STR1, 0,        "(mail recipient)" },
1940         { "ALLO", ALLO, ARGS, 1,        "allocate storage (vacuously)" },
1941         { "REST", REST, ARGS, 1,        "<sp> offset (restart command)" },
1942         { "RNFR", RNFR, STR1, 1,        "<sp> file-name" },
1943         { "RNTO", RNTO, STR1, 1,        "<sp> file-name" },
1944         { "ABOR", ABOR, ARGS, 1,        "(abort operation)" },
1945         { "DELE", DELE, STR1, 1,        "<sp> file-name" },
1946         { "CWD",  CWD,  OSTR, 1,        "[ <sp> directory-name ]" },
1947         { "XCWD", CWD,  OSTR, 1,        "[ <sp> directory-name ]" },
1948         { "LIST", LIST, OSTR, 1,        "[ <sp> path-name ]" },
1949         { "NLST", NLST, OSTR, 1,        "[ <sp> path-name ]" },
1950         { "SITE", SITE, SITECMD, 1,     "site-cmd [ <sp> arguments ]" },
1951         { "SYST", SYST, ARGS, 1,        "(get type of operating system)" },
1952         { "STAT", STAT, OSTR, 1,        "[ <sp> path-name ]" },
1953         { "HELP", HELP, OSTR, 1,        "[ <sp> <string> ]" },
1954         { "NOOP", NOOP, ARGS, 1,        "" },
1955         { "MKD",  MKD,  STR1, 1,        "<sp> path-name" },
1956         { "XMKD", MKD,  STR1, 1,        "<sp> path-name" },
1957         { "RMD",  RMD,  STR1, 1,        "<sp> path-name" },
1958         { "XRMD", RMD,  STR1, 1,        "<sp> path-name" },
1959         { "PWD",  PWD,  ARGS, 1,        "(return current directory)" },
1960         { "XPWD", PWD,  ARGS, 1,        "(return current directory)" },
1961         { "CDUP", CDUP, ARGS, 1,        "(change to parent directory)" },
1962         { "XCUP", CDUP, ARGS, 1,        "(change to parent directory)" },
1963         { "STOU", STOU, STR1, 1,        "<sp> file-name" },
1964         { "SIZE", SIZE, OSTR, 1,        "<sp> path-name" },
1965         { "MDTM", MDTM, OSTR, 1,        "<sp> path-name" },
1966         { NULL,   0,    0,    0,        0 }
1967 };
1968
1969 struct tab sitetab[] = {
1970         { "UMASK", UMASK, ARGS, 1,      "[ <sp> umask ]" },
1971         { "IDLE", IDLE, ARGS, 1,        "[ <sp> maximum-idle-time ]" },
1972         { "CHMOD", CHMOD, NSTR, 1,      "<sp> mode <sp> file-name" },
1973         { "HELP", HELP, OSTR, 1,        "[ <sp> <string> ]" },
1974         { NULL,   0,    0,    0,        0 }
1975 };
1976
1977 static struct tab *
1978 lookup(p, cmd)
1979         struct tab *p;
1980         char *cmd;
1981 {
1982
1983         for (; p->name != NULL; p++)
1984                 if (strcmp(cmd, p->name) == 0)
1985                         return (p);
1986         return (0);
1987 }
1988
1989 #include <arpa/telnet.h>
1990
1991 /*
1992  * getline - a hacked up version of fgets to ignore TELNET escape codes.
1993  */
1994 char *
1995 telnet_fgets(char *s, int n, FILE *iop)
1996 {
1997         int c;
1998         register char *cs;
1999
2000         cs = s;
2001 /* tmpline may contain saved command from urgent mode interruption */
2002         for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) {
2003                 *cs++ = tmpline[c];
2004                 if (tmpline[c] == '\n') {
2005                         *cs++ = '\0';
2006                         if (debug)
2007                                 syslog(LOG_DEBUG, "command: %s", s);
2008                         tmpline[0] = '\0';
2009                         return(s);
2010                 }
2011                 if (c == 0)
2012                         tmpline[0] = '\0';
2013         }
2014         while ((c = getc(iop)) != EOF) {
2015                 c &= 0377;
2016                 if (c == IAC) {
2017                     if ((c = getc(iop)) != EOF) {
2018                         c &= 0377;
2019                         switch (c) {
2020                         case WILL:
2021                         case WONT:
2022                                 c = getc(iop);
2023                                 printf("%c%c%c", IAC, DONT, 0377&c);
2024                                 (void) fflush(stdout);
2025                                 continue;
2026                         case DO:
2027                         case DONT:
2028                                 c = getc(iop);
2029                                 printf("%c%c%c", IAC, WONT, 0377&c);
2030                                 (void) fflush(stdout);
2031                                 continue;
2032                         case IAC:
2033                                 break;
2034                         default:
2035                                 continue;       /* ignore command */
2036                         }
2037                     }
2038                 }
2039                 *cs++ = c;
2040                 if (--n <= 0 || c == '\n')
2041                         break;
2042         }
2043         if (c == EOF && cs == s)
2044             return (NULL);
2045         *cs++ = '\0';
2046         if (debug) {
2047                 if (!cred.guest && strncasecmp("pass ", s, 5) == 0) {
2048                         /* Don't syslog passwords */
2049                         syslog(LOG_DEBUG, "command: %.5s ???", s);
2050                 } else {
2051                         register char *cp;
2052                         register int len;
2053
2054                         /* Don't syslog trailing CR-LF */
2055                         len = strlen(s);
2056                         cp = s + len - 1;
2057                         while (cp >= s && (*cp == '\n' || *cp == '\r')) {
2058                                 --cp;
2059                                 --len;
2060                         }
2061                         syslog(LOG_DEBUG, "command: %.*s", len, s);
2062                 }
2063         }
2064         return (s);
2065 }
2066
2067 void
2068 toolong(int signo)
2069 {
2070   (void)signo;
2071         reply(421,
2072             "Timeout (%d seconds): closing control connection.", timeout);
2073         if (logging)
2074                 syslog(LOG_INFO, "User %s timed out after %d seconds",
2075                     (cred.name ? cred.name : "unknown"), timeout);
2076         dologout(1);
2077 }
2078
2079 static int
2080 yylex()
2081 {
2082         static int cpos, state;
2083         char *cp, *cp2;
2084         struct tab *p;
2085         int n;
2086         char c;
2087
2088         for (;;) {
2089                 switch (state) {
2090
2091                 case CMD:
2092                         (void) signal(SIGALRM, toolong);
2093                         (void) alarm((unsigned) timeout);
2094                         if (telnet_fgets(cbuf, sizeof(cbuf)-1, stdin) == NULL) {
2095                                 reply(221, "You could at least say goodbye.");
2096                                 dologout(0);
2097                         }
2098                         (void) alarm(0);
2099 #ifdef HAVE_SETPROCTITLE
2100                         if (strncasecmp(cbuf, "PASS", 4) != NULL)
2101                                 setproctitle("%s: %s", proctitle, cbuf);
2102 #endif /* HAVE_SETPROCTITLE */
2103                         if ((cp = strchr(cbuf, '\r'))) {
2104                                 *cp++ = '\n';
2105                                 *cp = '\0';
2106                         }
2107                         if ((cp = strpbrk(cbuf, " \n")))
2108                                 cpos = cp - cbuf;
2109                         if (cpos == 0)
2110                                 cpos = 4;
2111                         c = cbuf[cpos];
2112                         cbuf[cpos] = '\0';
2113                         upper(cbuf);
2114                         p = lookup(cmdtab, cbuf);
2115                         cbuf[cpos] = c;
2116                         if (p != 0) {
2117                                 if (p->implemented == 0) {
2118                                         nack(p->name);
2119                                         longjmp(errcatch,0);
2120                                         /* NOTREACHED */
2121                                 }
2122                                 state = p->state;
2123                                 yylval.s = p->name;
2124                                 return (p->token);
2125                         }
2126                         break;
2127
2128                 case SITECMD:
2129                         if (cbuf[cpos] == ' ') {
2130                                 cpos++;
2131                                 return (SP);
2132                         }
2133                         cp = &cbuf[cpos];
2134                         if ((cp2 = strpbrk(cp, " \n")))
2135                                 cpos = cp2 - cbuf;
2136                         c = cbuf[cpos];
2137                         cbuf[cpos] = '\0';
2138                         upper(cp);
2139                         p = lookup(sitetab, cp);
2140                         cbuf[cpos] = c;
2141                         if (p != 0) {
2142                                 if (p->implemented == 0) {
2143                                         state = CMD;
2144                                         nack(p->name);
2145                                         longjmp(errcatch,0);
2146                                         /* NOTREACHED */
2147                                 }
2148                                 state = p->state;
2149                                 yylval.s = p->name;
2150                                 return (p->token);
2151                         }
2152                         state = CMD;
2153                         break;
2154
2155                 case OSTR:
2156                         if (cbuf[cpos] == '\n') {
2157                                 state = CMD;
2158                                 return (CRLF);
2159                         }
2160                         /* FALLTHROUGH */
2161
2162                 case STR1:
2163                 case ZSTR1:
2164                 dostr1:
2165                         if (cbuf[cpos] == ' ') {
2166                                 cpos++;
2167                                 state = state == OSTR ? STR2 : ++state;
2168                                 return (SP);
2169                         }
2170                         break;
2171
2172                 case ZSTR2:
2173                         if (cbuf[cpos] == '\n') {
2174                                 state = CMD;
2175                                 return (CRLF);
2176                         }
2177                         /* FALLTHROUGH */
2178
2179                 case STR2:
2180                         cp = &cbuf[cpos];
2181                         n = strlen(cp);
2182                         cpos += n - 1;
2183                         /*
2184                          * Make sure the string is nonempty and \n terminated.
2185                          */
2186                         if (n > 1 && cbuf[cpos] == '\n') {
2187                                 cbuf[cpos] = '\0';
2188                                 yylval.s = copy(cp);
2189                                 cbuf[cpos] = '\n';
2190                                 state = ARGS;
2191                                 return (STRING);
2192                         }
2193                         break;
2194
2195                 case NSTR:
2196                         if (cbuf[cpos] == ' ') {
2197                                 cpos++;
2198                                 return (SP);
2199                         }
2200                         if (isdigit(cbuf[cpos])) {
2201                                 cp = &cbuf[cpos];
2202                                 while (isdigit(cbuf[++cpos]))
2203                                         ;
2204                                 c = cbuf[cpos];
2205                                 cbuf[cpos] = '\0';
2206                                 yylval.i = atoi(cp);
2207                                 cbuf[cpos] = c;
2208                                 state = STR1;
2209                                 return (NUMBER);
2210                         }
2211                         state = STR1;
2212                         goto dostr1;
2213
2214                 case ARGS:
2215                         if (isdigit(cbuf[cpos])) {
2216                                 cp = &cbuf[cpos];
2217                                 while (isdigit(cbuf[++cpos]))
2218                                         ;
2219                                 c = cbuf[cpos];
2220                                 cbuf[cpos] = '\0';
2221                                 yylval.i = atoi(cp);
2222                                 cbuf[cpos] = c;
2223                                 return (NUMBER);
2224                         }
2225                         switch (cbuf[cpos++]) {
2226
2227                         case '\n':
2228                                 state = CMD;
2229                                 return (CRLF);
2230
2231                         case ' ':
2232                                 return (SP);
2233
2234                         case ',':
2235                                 return (COMMA);
2236
2237                         case 'A':
2238                         case 'a':
2239                                 return (A);
2240
2241                         case 'B':
2242                         case 'b':
2243                                 return (B);
2244
2245                         case 'C':
2246                         case 'c':
2247                                 return (C);
2248
2249                         case 'E':
2250                         case 'e':
2251                                 return (E);
2252
2253                         case 'F':
2254                         case 'f':
2255                                 return (F);
2256
2257                         case 'I':
2258                         case 'i':
2259                                 return (I);
2260
2261                         case 'L':
2262                         case 'l':
2263                                 return (L);
2264
2265                         case 'N':
2266                         case 'n':
2267                                 return (N);
2268
2269                         case 'P':
2270                         case 'p':
2271                                 return (P);
2272
2273                         case 'R':
2274                         case 'r':
2275                                 return (R);
2276
2277                         case 'S':
2278                         case 's':
2279                                 return (S);
2280
2281                         case 'T':
2282                         case 't':
2283                                 return (T);
2284
2285                         }
2286                         break;
2287
2288                 default:
2289                         fatal("Unknown state in scanner.");
2290                 }
2291                 yyerror((char *) 0);
2292                 state = CMD;
2293                 longjmp(errcatch,0);
2294         }
2295 }
2296
2297 void
2298 upper(char *s)
2299 {
2300         while (*s != '\0') {
2301                 if (islower(*s))
2302                         *s = toupper(*s);
2303                 s++;
2304         }
2305 }
2306
2307 static char *
2308 copy(char *s)
2309 {
2310         char *p;
2311
2312         p = malloc((unsigned) strlen(s) + 1);
2313         if (p == NULL)
2314                 fatal("Ran out of memory.");
2315         (void) strcpy(p, s);
2316         return (p);
2317 }
2318
2319 static void
2320 help(struct tab *ctab, char *s)
2321 {
2322         struct tab *c;
2323         int width, NCMDS;
2324         const char *help_type;
2325
2326         if (ctab == sitetab)
2327                 help_type = "SITE ";
2328         else
2329                 help_type = "";
2330         width = 0, NCMDS = 0;
2331         for (c = ctab; c->name != NULL; c++) {
2332                 int len = strlen(c->name);
2333
2334                 if (len > width)
2335                         width = len;
2336                 NCMDS++;
2337         }
2338         width = (width + 8) &~ 7;
2339         if (s == 0) {
2340                 int i, j, w;
2341                 int columns, lines;
2342
2343                 lreply(214, "The following %scommands are recognized %s.",
2344                     help_type, "(* =>'s unimplemented)");
2345                 columns = 76 / width;
2346                 if (columns == 0)
2347                         columns = 1;
2348                 lines = (NCMDS + columns - 1) / columns;
2349                 for (i = 0; i < lines; i++) {
2350                         printf("   ");
2351                         for (j = 0; j < columns; j++) {
2352                                 c = ctab + j * lines + i;
2353                                 printf("%s%c", c->name,
2354                                         c->implemented ? ' ' : '*');
2355                                 if (c + lines >= &ctab[NCMDS])
2356                                         break;
2357                                 w = strlen(c->name) + 1;
2358                                 while (w < width) {
2359                                         putchar(' ');
2360                                         w++;
2361                                 }
2362                         }
2363                         printf("\r\n");
2364                 }
2365                 (void) fflush(stdout);
2366                 reply(214, "Direct comments to ftp-bugs@%s.", hostname);
2367                 return;
2368         }
2369         upper(s);
2370         c = lookup(ctab, s);
2371         if (c == (struct tab *)0) {
2372                 reply(502, "Unknown command %s.", s);
2373                 return;
2374         }
2375         if (c->implemented)
2376                 reply(214, "Syntax: %s%s %s", help_type, c->name, c->help);
2377         else
2378                 reply(214, "%s%-*s\t%s; unimplemented.", help_type, width,
2379                     c->name, c->help);
2380 }
2381
2382 static void
2383 sizecmd(char *filename)
2384 {
2385         switch (type) {
2386         case TYPE_L:
2387         case TYPE_I: {
2388                 struct stat stbuf;
2389                 if (stat(filename, &stbuf) < 0 || !S_ISREG(stbuf.st_mode))
2390                         reply(550, "%s: not a plain file.", filename);
2391                 else
2392                         reply(213,
2393                               (sizeof (stbuf.st_size) > sizeof(long)
2394                                ? "%qu" : "%lu"), stbuf.st_size);
2395                 break; }
2396         case TYPE_A: {
2397                 FILE *fin;
2398                 int c;
2399                 off_t count;
2400                 struct stat stbuf;
2401                 fin = fopen(filename, "r");
2402                 if (fin == NULL) {
2403                         perror_reply(550, filename);
2404                         return;
2405                 }
2406                 if (fstat(fileno(fin), &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) {
2407                         reply(550, "%s: not a plain file.", filename);
2408                         (void) fclose(fin);
2409                         return;
2410                 }
2411
2412                 count = 0;
2413                 while((c=getc(fin)) != EOF) {
2414                         if (c == '\n')  /* will get expanded to \r\n */
2415                                 count++;
2416                         count++;
2417                 }
2418                 (void) fclose(fin);
2419
2420                 reply(213, sizeof(count) > sizeof(long) ? "%qd" : "%ld",
2421                       count);
2422                 break; }
2423         default:
2424                 reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]);
2425         }
2426 }
2427
2428 /* ARGSUSED */
2429 static void
2430 yyerror(const char *s)
2431 {
2432   char *cp;
2433
2434   (void)s;
2435   cp = strchr(cbuf,'\n');
2436   if (cp != NULL)
2437     *cp = '\0';
2438   reply(500, "'%s': command not understood.", cbuf);
2439 }