1cc361f65SGavin Atkinson /* $NetBSD: cmds.c,v 1.17 2010/01/12 06:55:47 lukem Exp $ */
2cc361f65SGavin Atkinson /* from NetBSD: cmds.c,v 1.130 2009/07/13 19:05:41 roy Exp */
3f982db4aSGavin Atkinson
4f982db4aSGavin Atkinson /*-
5cc361f65SGavin Atkinson * Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
6f982db4aSGavin Atkinson * All rights reserved.
7f982db4aSGavin Atkinson *
8f982db4aSGavin Atkinson * This code is derived from software contributed to The NetBSD Foundation
9f982db4aSGavin Atkinson * by Luke Mewburn.
10f982db4aSGavin Atkinson *
11f982db4aSGavin Atkinson * This code is derived from software contributed to The NetBSD Foundation
12f982db4aSGavin Atkinson * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
13f982db4aSGavin Atkinson * NASA Ames Research Center.
14f982db4aSGavin Atkinson *
15f982db4aSGavin Atkinson * Redistribution and use in source and binary forms, with or without
16f982db4aSGavin Atkinson * modification, are permitted provided that the following conditions
17f982db4aSGavin Atkinson * are met:
18f982db4aSGavin Atkinson * 1. Redistributions of source code must retain the above copyright
19f982db4aSGavin Atkinson * notice, this list of conditions and the following disclaimer.
20f982db4aSGavin Atkinson * 2. Redistributions in binary form must reproduce the above copyright
21f982db4aSGavin Atkinson * notice, this list of conditions and the following disclaimer in the
22f982db4aSGavin Atkinson * documentation and/or other materials provided with the distribution.
23f982db4aSGavin Atkinson *
24f982db4aSGavin Atkinson * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
25f982db4aSGavin Atkinson * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26f982db4aSGavin Atkinson * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27f982db4aSGavin Atkinson * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
28f982db4aSGavin Atkinson * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29f982db4aSGavin Atkinson * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30f982db4aSGavin Atkinson * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31f982db4aSGavin Atkinson * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32f982db4aSGavin Atkinson * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33f982db4aSGavin Atkinson * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34f982db4aSGavin Atkinson * POSSIBILITY OF SUCH DAMAGE.
35f982db4aSGavin Atkinson */
36f982db4aSGavin Atkinson
37f982db4aSGavin Atkinson /*
38f982db4aSGavin Atkinson * Copyright (c) 1985, 1989, 1993, 1994
39f982db4aSGavin Atkinson * The Regents of the University of California. All rights reserved.
40f982db4aSGavin Atkinson *
41f982db4aSGavin Atkinson * Redistribution and use in source and binary forms, with or without
42f982db4aSGavin Atkinson * modification, are permitted provided that the following conditions
43f982db4aSGavin Atkinson * are met:
44f982db4aSGavin Atkinson * 1. Redistributions of source code must retain the above copyright
45f982db4aSGavin Atkinson * notice, this list of conditions and the following disclaimer.
46f982db4aSGavin Atkinson * 2. Redistributions in binary form must reproduce the above copyright
47f982db4aSGavin Atkinson * notice, this list of conditions and the following disclaimer in the
48f982db4aSGavin Atkinson * documentation and/or other materials provided with the distribution.
49f982db4aSGavin Atkinson * 3. Neither the name of the University nor the names of its contributors
50f982db4aSGavin Atkinson * may be used to endorse or promote products derived from this software
51f982db4aSGavin Atkinson * without specific prior written permission.
52f982db4aSGavin Atkinson *
53f982db4aSGavin Atkinson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54f982db4aSGavin Atkinson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55f982db4aSGavin Atkinson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56f982db4aSGavin Atkinson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57f982db4aSGavin Atkinson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58f982db4aSGavin Atkinson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59f982db4aSGavin Atkinson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60f982db4aSGavin Atkinson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61f982db4aSGavin Atkinson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62f982db4aSGavin Atkinson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63f982db4aSGavin Atkinson * SUCH DAMAGE.
64f982db4aSGavin Atkinson */
65f982db4aSGavin Atkinson
66f982db4aSGavin Atkinson /*
67f982db4aSGavin Atkinson * Copyright (C) 1997 and 1998 WIDE Project.
68f982db4aSGavin Atkinson * All rights reserved.
69f982db4aSGavin Atkinson *
70f982db4aSGavin Atkinson * Redistribution and use in source and binary forms, with or without
71f982db4aSGavin Atkinson * modification, are permitted provided that the following conditions
72f982db4aSGavin Atkinson * are met:
73f982db4aSGavin Atkinson * 1. Redistributions of source code must retain the above copyright
74f982db4aSGavin Atkinson * notice, this list of conditions and the following disclaimer.
75f982db4aSGavin Atkinson * 2. Redistributions in binary form must reproduce the above copyright
76f982db4aSGavin Atkinson * notice, this list of conditions and the following disclaimer in the
77f982db4aSGavin Atkinson * documentation and/or other materials provided with the distribution.
78f982db4aSGavin Atkinson * 3. Neither the name of the project nor the names of its contributors
79f982db4aSGavin Atkinson * may be used to endorse or promote products derived from this software
80f982db4aSGavin Atkinson * without specific prior written permission.
81f982db4aSGavin Atkinson *
82f982db4aSGavin Atkinson * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
83f982db4aSGavin Atkinson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
84f982db4aSGavin Atkinson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
85f982db4aSGavin Atkinson * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
86f982db4aSGavin Atkinson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
87f982db4aSGavin Atkinson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
88f982db4aSGavin Atkinson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
89f982db4aSGavin Atkinson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
90f982db4aSGavin Atkinson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
91f982db4aSGavin Atkinson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
92f982db4aSGavin Atkinson * SUCH DAMAGE.
93f982db4aSGavin Atkinson */
94f982db4aSGavin Atkinson
95cc361f65SGavin Atkinson #include "tnftp.h"
96cc361f65SGavin Atkinson
97cc361f65SGavin Atkinson #if 0 /* tnftp */
98cc361f65SGavin Atkinson
99f982db4aSGavin Atkinson #include <sys/cdefs.h>
100f982db4aSGavin Atkinson #ifndef lint
101f982db4aSGavin Atkinson #if 0
102f982db4aSGavin Atkinson static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94";
103f982db4aSGavin Atkinson #else
104cc361f65SGavin Atkinson __RCSID(" NetBSD: cmds.c,v 1.130 2009/07/13 19:05:41 roy Exp ");
105f982db4aSGavin Atkinson #endif
106f982db4aSGavin Atkinson #endif /* not lint */
107f982db4aSGavin Atkinson
108f982db4aSGavin Atkinson /*
109f982db4aSGavin Atkinson * FTP User Program -- Command Routines.
110f982db4aSGavin Atkinson */
111f982db4aSGavin Atkinson #include <sys/types.h>
112f982db4aSGavin Atkinson #include <sys/socket.h>
113f982db4aSGavin Atkinson #include <sys/stat.h>
114f982db4aSGavin Atkinson #include <sys/wait.h>
115f982db4aSGavin Atkinson #include <arpa/ftp.h>
116f982db4aSGavin Atkinson
117f982db4aSGavin Atkinson #include <ctype.h>
118f982db4aSGavin Atkinson #include <err.h>
119f982db4aSGavin Atkinson #include <glob.h>
120f982db4aSGavin Atkinson #include <limits.h>
121f982db4aSGavin Atkinson #include <netdb.h>
122f982db4aSGavin Atkinson #include <paths.h>
123cc361f65SGavin Atkinson #include <stddef.h>
124f982db4aSGavin Atkinson #include <stdio.h>
125f982db4aSGavin Atkinson #include <stdlib.h>
126f982db4aSGavin Atkinson #include <string.h>
127f982db4aSGavin Atkinson #include <time.h>
128f982db4aSGavin Atkinson #include <unistd.h>
129cc361f65SGavin Atkinson
130cc361f65SGavin Atkinson #endif /* tnftp */
131f982db4aSGavin Atkinson
132f982db4aSGavin Atkinson #include "ftp_var.h"
133f982db4aSGavin Atkinson #include "version.h"
134f982db4aSGavin Atkinson
135cc361f65SGavin Atkinson static struct types {
136cc361f65SGavin Atkinson const char *t_name;
137cc361f65SGavin Atkinson const char *t_mode;
138f982db4aSGavin Atkinson int t_type;
139cc361f65SGavin Atkinson const char *t_arg;
140f982db4aSGavin Atkinson } types[] = {
141f982db4aSGavin Atkinson { "ascii", "A", TYPE_A, 0 },
142f982db4aSGavin Atkinson { "binary", "I", TYPE_I, 0 },
143f982db4aSGavin Atkinson { "image", "I", TYPE_I, 0 },
144f982db4aSGavin Atkinson { "ebcdic", "E", TYPE_E, 0 },
145f982db4aSGavin Atkinson { "tenex", "L", TYPE_L, bytename },
146cc361f65SGavin Atkinson { NULL, NULL, 0, NULL }
147f982db4aSGavin Atkinson };
148f982db4aSGavin Atkinson
149cc361f65SGavin Atkinson static sigjmp_buf jabort;
150f982db4aSGavin Atkinson
151f982db4aSGavin Atkinson static int confirm(const char *, const char *);
152cc361f65SGavin Atkinson static void mintr(int);
153cc361f65SGavin Atkinson static void mabort(const char *);
154cc361f65SGavin Atkinson static void set_type(const char *);
155f982db4aSGavin Atkinson
156f982db4aSGavin Atkinson static const char *doprocess(char *, size_t, const char *, int, int, int);
157f982db4aSGavin Atkinson static const char *domap(char *, size_t, const char *);
158f982db4aSGavin Atkinson static const char *docase(char *, size_t, const char *);
159f982db4aSGavin Atkinson static const char *dotrans(char *, size_t, const char *);
160f982db4aSGavin Atkinson
161cc361f65SGavin Atkinson /*
162cc361f65SGavin Atkinson * Confirm if "cmd" is to be performed upon "file".
163cc361f65SGavin Atkinson * If "file" is NULL, generate a "Continue with" prompt instead.
164cc361f65SGavin Atkinson */
165f982db4aSGavin Atkinson static int
confirm(const char * cmd,const char * file)166f982db4aSGavin Atkinson confirm(const char *cmd, const char *file)
167f982db4aSGavin Atkinson {
168cc361f65SGavin Atkinson const char *errormsg;
169cc361f65SGavin Atkinson char cline[BUFSIZ];
170cc361f65SGavin Atkinson const char *promptleft, *promptright;
171f982db4aSGavin Atkinson
172f982db4aSGavin Atkinson if (!interactive || confirmrest)
173f982db4aSGavin Atkinson return (1);
174cc361f65SGavin Atkinson if (file == NULL) {
175cc361f65SGavin Atkinson promptleft = "Continue with";
176cc361f65SGavin Atkinson promptright = cmd;
177cc361f65SGavin Atkinson } else {
178cc361f65SGavin Atkinson promptleft = cmd;
179cc361f65SGavin Atkinson promptright = file;
180cc361f65SGavin Atkinson }
181f982db4aSGavin Atkinson while (1) {
182cc361f65SGavin Atkinson fprintf(ttyout, "%s %s [anpqy?]? ", promptleft, promptright);
183f982db4aSGavin Atkinson (void)fflush(ttyout);
184cc361f65SGavin Atkinson if (get_line(stdin, cline, sizeof(cline), &errormsg) < 0) {
185f982db4aSGavin Atkinson mflag = 0;
186cc361f65SGavin Atkinson fprintf(ttyout, "%s; %s aborted\n", errormsg, cmd);
187f982db4aSGavin Atkinson return (0);
188f982db4aSGavin Atkinson }
189cc361f65SGavin Atkinson switch (tolower((unsigned char)*cline)) {
190f982db4aSGavin Atkinson case 'a':
191f982db4aSGavin Atkinson confirmrest = 1;
192f982db4aSGavin Atkinson fprintf(ttyout,
193f982db4aSGavin Atkinson "Prompting off for duration of %s.\n", cmd);
194f982db4aSGavin Atkinson break;
195f982db4aSGavin Atkinson case 'p':
196f982db4aSGavin Atkinson interactive = 0;
197f982db4aSGavin Atkinson fputs("Interactive mode: off.\n", ttyout);
198f982db4aSGavin Atkinson break;
199f982db4aSGavin Atkinson case 'q':
200f982db4aSGavin Atkinson mflag = 0;
201cc361f65SGavin Atkinson fprintf(ttyout, "%s aborted.\n", cmd);
202f982db4aSGavin Atkinson /* FALLTHROUGH */
203f982db4aSGavin Atkinson case 'n':
204f982db4aSGavin Atkinson return (0);
205f982db4aSGavin Atkinson case '?':
206f982db4aSGavin Atkinson fprintf(ttyout,
207f982db4aSGavin Atkinson " confirmation options:\n"
208f982db4aSGavin Atkinson "\ta answer `yes' for the duration of %s\n"
209f982db4aSGavin Atkinson "\tn answer `no' for this file\n"
210f982db4aSGavin Atkinson "\tp turn off `prompt' mode\n"
211f982db4aSGavin Atkinson "\tq stop the current %s\n"
212f982db4aSGavin Atkinson "\ty answer `yes' for this file\n"
213f982db4aSGavin Atkinson "\t? this help list\n",
214f982db4aSGavin Atkinson cmd, cmd);
215f982db4aSGavin Atkinson continue; /* back to while(1) */
216f982db4aSGavin Atkinson }
217f982db4aSGavin Atkinson return (1);
218f982db4aSGavin Atkinson }
219f982db4aSGavin Atkinson /* NOTREACHED */
220f982db4aSGavin Atkinson }
221f982db4aSGavin Atkinson
222f982db4aSGavin Atkinson /*
223f982db4aSGavin Atkinson * Set transfer type.
224f982db4aSGavin Atkinson */
225f982db4aSGavin Atkinson void
settype(int argc,char * argv[])226f982db4aSGavin Atkinson settype(int argc, char *argv[])
227f982db4aSGavin Atkinson {
228f982db4aSGavin Atkinson struct types *p;
229f982db4aSGavin Atkinson
230f982db4aSGavin Atkinson if (argc == 0 || argc > 2) {
231cc361f65SGavin Atkinson const char *sep;
232f982db4aSGavin Atkinson
233cc361f65SGavin Atkinson UPRINTF("usage: %s [", argv[0]);
234f982db4aSGavin Atkinson sep = " ";
235f982db4aSGavin Atkinson for (p = types; p->t_name; p++) {
236f982db4aSGavin Atkinson fprintf(ttyout, "%s%s", sep, p->t_name);
237f982db4aSGavin Atkinson sep = " | ";
238f982db4aSGavin Atkinson }
239f982db4aSGavin Atkinson fputs(" ]\n", ttyout);
240f982db4aSGavin Atkinson code = -1;
241f982db4aSGavin Atkinson return;
242f982db4aSGavin Atkinson }
243f982db4aSGavin Atkinson if (argc < 2) {
244f982db4aSGavin Atkinson fprintf(ttyout, "Using %s mode to transfer files.\n", typename);
245f982db4aSGavin Atkinson code = 0;
246f982db4aSGavin Atkinson return;
247f982db4aSGavin Atkinson }
248cc361f65SGavin Atkinson set_type(argv[1]);
249cc361f65SGavin Atkinson }
250cc361f65SGavin Atkinson
251cc361f65SGavin Atkinson void
set_type(const char * ttype)252cc361f65SGavin Atkinson set_type(const char *ttype)
253cc361f65SGavin Atkinson {
254cc361f65SGavin Atkinson struct types *p;
255cc361f65SGavin Atkinson int comret;
256cc361f65SGavin Atkinson
257f982db4aSGavin Atkinson for (p = types; p->t_name; p++)
258cc361f65SGavin Atkinson if (strcmp(ttype, p->t_name) == 0)
259f982db4aSGavin Atkinson break;
260f982db4aSGavin Atkinson if (p->t_name == 0) {
261cc361f65SGavin Atkinson fprintf(ttyout, "%s: unknown mode.\n", ttype);
262f982db4aSGavin Atkinson code = -1;
263f982db4aSGavin Atkinson return;
264f982db4aSGavin Atkinson }
265f982db4aSGavin Atkinson if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
266f982db4aSGavin Atkinson comret = command("TYPE %s %s", p->t_mode, p->t_arg);
267f982db4aSGavin Atkinson else
268f982db4aSGavin Atkinson comret = command("TYPE %s", p->t_mode);
269f982db4aSGavin Atkinson if (comret == COMPLETE) {
270f982db4aSGavin Atkinson (void)strlcpy(typename, p->t_name, sizeof(typename));
271f982db4aSGavin Atkinson curtype = type = p->t_type;
272f982db4aSGavin Atkinson }
273f982db4aSGavin Atkinson }
274f982db4aSGavin Atkinson
275f982db4aSGavin Atkinson /*
276f982db4aSGavin Atkinson * Internal form of settype; changes current type in use with server
277f982db4aSGavin Atkinson * without changing our notion of the type for data transfers.
278f982db4aSGavin Atkinson * Used to change to and from ascii for listings.
279f982db4aSGavin Atkinson */
280f982db4aSGavin Atkinson void
changetype(int newtype,int show)281f982db4aSGavin Atkinson changetype(int newtype, int show)
282f982db4aSGavin Atkinson {
283f982db4aSGavin Atkinson struct types *p;
284f982db4aSGavin Atkinson int comret, oldverbose = verbose;
285f982db4aSGavin Atkinson
286f982db4aSGavin Atkinson if (newtype == 0)
287f982db4aSGavin Atkinson newtype = TYPE_I;
288f982db4aSGavin Atkinson if (newtype == curtype)
289f982db4aSGavin Atkinson return;
290cc361f65SGavin Atkinson if (ftp_debug == 0 && show == 0)
291f982db4aSGavin Atkinson verbose = 0;
292f982db4aSGavin Atkinson for (p = types; p->t_name; p++)
293f982db4aSGavin Atkinson if (newtype == p->t_type)
294f982db4aSGavin Atkinson break;
295f982db4aSGavin Atkinson if (p->t_name == 0) {
296cc361f65SGavin Atkinson errx(1, "changetype: unknown type %d", newtype);
297f982db4aSGavin Atkinson }
298f982db4aSGavin Atkinson if (newtype == TYPE_L && bytename[0] != '\0')
299f982db4aSGavin Atkinson comret = command("TYPE %s %s", p->t_mode, bytename);
300f982db4aSGavin Atkinson else
301f982db4aSGavin Atkinson comret = command("TYPE %s", p->t_mode);
302f982db4aSGavin Atkinson if (comret == COMPLETE)
303f982db4aSGavin Atkinson curtype = newtype;
304f982db4aSGavin Atkinson verbose = oldverbose;
305f982db4aSGavin Atkinson }
306f982db4aSGavin Atkinson
307f982db4aSGavin Atkinson /*
308f982db4aSGavin Atkinson * Set binary transfer type.
309f982db4aSGavin Atkinson */
310f982db4aSGavin Atkinson /*VARARGS*/
311f982db4aSGavin Atkinson void
setbinary(int argc,char * argv[])312f982db4aSGavin Atkinson setbinary(int argc, char *argv[])
313f982db4aSGavin Atkinson {
314f982db4aSGavin Atkinson
315f982db4aSGavin Atkinson if (argc == 0) {
316cc361f65SGavin Atkinson UPRINTF("usage: %s\n", argv[0]);
317f982db4aSGavin Atkinson code = -1;
318f982db4aSGavin Atkinson return;
319f982db4aSGavin Atkinson }
320cc361f65SGavin Atkinson set_type("binary");
321f982db4aSGavin Atkinson }
322f982db4aSGavin Atkinson
323f982db4aSGavin Atkinson /*
324f982db4aSGavin Atkinson * Set ascii transfer type.
325f982db4aSGavin Atkinson */
326f982db4aSGavin Atkinson /*VARARGS*/
327f982db4aSGavin Atkinson void
setascii(int argc,char * argv[])328f982db4aSGavin Atkinson setascii(int argc, char *argv[])
329f982db4aSGavin Atkinson {
330f982db4aSGavin Atkinson
331f982db4aSGavin Atkinson if (argc == 0) {
332cc361f65SGavin Atkinson UPRINTF("usage: %s\n", argv[0]);
333f982db4aSGavin Atkinson code = -1;
334f982db4aSGavin Atkinson return;
335f982db4aSGavin Atkinson }
336cc361f65SGavin Atkinson set_type("ascii");
337f982db4aSGavin Atkinson }
338f982db4aSGavin Atkinson
339f982db4aSGavin Atkinson /*
340f982db4aSGavin Atkinson * Set tenex transfer type.
341f982db4aSGavin Atkinson */
342f982db4aSGavin Atkinson /*VARARGS*/
343f982db4aSGavin Atkinson void
settenex(int argc,char * argv[])344f982db4aSGavin Atkinson settenex(int argc, char *argv[])
345f982db4aSGavin Atkinson {
346f982db4aSGavin Atkinson
347f982db4aSGavin Atkinson if (argc == 0) {
348cc361f65SGavin Atkinson UPRINTF("usage: %s\n", argv[0]);
349f982db4aSGavin Atkinson code = -1;
350f982db4aSGavin Atkinson return;
351f982db4aSGavin Atkinson }
352cc361f65SGavin Atkinson set_type("tenex");
353f982db4aSGavin Atkinson }
354f982db4aSGavin Atkinson
355f982db4aSGavin Atkinson /*
356f982db4aSGavin Atkinson * Set file transfer mode.
357f982db4aSGavin Atkinson */
358f982db4aSGavin Atkinson /*ARGSUSED*/
359f982db4aSGavin Atkinson void
setftmode(int argc,char * argv[])360f982db4aSGavin Atkinson setftmode(int argc, char *argv[])
361f982db4aSGavin Atkinson {
362f982db4aSGavin Atkinson
363f982db4aSGavin Atkinson if (argc != 2) {
364cc361f65SGavin Atkinson UPRINTF("usage: %s mode-name\n", argv[0]);
365f982db4aSGavin Atkinson code = -1;
366f982db4aSGavin Atkinson return;
367f982db4aSGavin Atkinson }
368f982db4aSGavin Atkinson fprintf(ttyout, "We only support %s mode, sorry.\n", modename);
369f982db4aSGavin Atkinson code = -1;
370f982db4aSGavin Atkinson }
371f982db4aSGavin Atkinson
372f982db4aSGavin Atkinson /*
373f982db4aSGavin Atkinson * Set file transfer format.
374f982db4aSGavin Atkinson */
375f982db4aSGavin Atkinson /*ARGSUSED*/
376f982db4aSGavin Atkinson void
setform(int argc,char * argv[])377f982db4aSGavin Atkinson setform(int argc, char *argv[])
378f982db4aSGavin Atkinson {
379f982db4aSGavin Atkinson
380f982db4aSGavin Atkinson if (argc != 2) {
381cc361f65SGavin Atkinson UPRINTF("usage: %s format\n", argv[0]);
382f982db4aSGavin Atkinson code = -1;
383f982db4aSGavin Atkinson return;
384f982db4aSGavin Atkinson }
385f982db4aSGavin Atkinson fprintf(ttyout, "We only support %s format, sorry.\n", formname);
386f982db4aSGavin Atkinson code = -1;
387f982db4aSGavin Atkinson }
388f982db4aSGavin Atkinson
389f982db4aSGavin Atkinson /*
390f982db4aSGavin Atkinson * Set file transfer structure.
391f982db4aSGavin Atkinson */
392f982db4aSGavin Atkinson /*ARGSUSED*/
393f982db4aSGavin Atkinson void
setstruct(int argc,char * argv[])394f982db4aSGavin Atkinson setstruct(int argc, char *argv[])
395f982db4aSGavin Atkinson {
396f982db4aSGavin Atkinson
397f982db4aSGavin Atkinson if (argc != 2) {
398cc361f65SGavin Atkinson UPRINTF("usage: %s struct-mode\n", argv[0]);
399f982db4aSGavin Atkinson code = -1;
400f982db4aSGavin Atkinson return;
401f982db4aSGavin Atkinson }
402f982db4aSGavin Atkinson fprintf(ttyout, "We only support %s structure, sorry.\n", structname);
403f982db4aSGavin Atkinson code = -1;
404f982db4aSGavin Atkinson }
405f982db4aSGavin Atkinson
406f982db4aSGavin Atkinson /*
407f982db4aSGavin Atkinson * Send a single file.
408f982db4aSGavin Atkinson */
409f982db4aSGavin Atkinson void
put(int argc,char * argv[])410f982db4aSGavin Atkinson put(int argc, char *argv[])
411f982db4aSGavin Atkinson {
412f982db4aSGavin Atkinson char buf[MAXPATHLEN];
413cc361f65SGavin Atkinson const char *cmd;
414f982db4aSGavin Atkinson int loc = 0;
415f982db4aSGavin Atkinson char *locfile;
416f982db4aSGavin Atkinson const char *remfile;
417f982db4aSGavin Atkinson
418f982db4aSGavin Atkinson if (argc == 2) {
419f982db4aSGavin Atkinson argc++;
420f982db4aSGavin Atkinson argv[2] = argv[1];
421f982db4aSGavin Atkinson loc++;
422f982db4aSGavin Atkinson }
423f982db4aSGavin Atkinson if (argc == 0 || (argc == 1 && !another(&argc, &argv, "local-file")))
424f982db4aSGavin Atkinson goto usage;
425f982db4aSGavin Atkinson if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) {
426f982db4aSGavin Atkinson usage:
427cc361f65SGavin Atkinson UPRINTF("usage: %s local-file [remote-file]\n", argv[0]);
428f982db4aSGavin Atkinson code = -1;
429f982db4aSGavin Atkinson return;
430f982db4aSGavin Atkinson }
431f982db4aSGavin Atkinson if ((locfile = globulize(argv[1])) == NULL) {
432f982db4aSGavin Atkinson code = -1;
433f982db4aSGavin Atkinson return;
434f982db4aSGavin Atkinson }
435f982db4aSGavin Atkinson remfile = argv[2];
436f982db4aSGavin Atkinson if (loc) /* If argv[2] is a copy of the old argv[1], update it */
437f982db4aSGavin Atkinson remfile = locfile;
438f982db4aSGavin Atkinson cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR");
439f982db4aSGavin Atkinson remfile = doprocess(buf, sizeof(buf), remfile,
440f982db4aSGavin Atkinson 0, loc && ntflag, loc && mapflag);
441f982db4aSGavin Atkinson sendrequest(cmd, locfile, remfile,
442f982db4aSGavin Atkinson locfile != argv[1] || remfile != argv[2]);
443f982db4aSGavin Atkinson free(locfile);
444f982db4aSGavin Atkinson }
445f982db4aSGavin Atkinson
446f982db4aSGavin Atkinson static const char *
doprocess(char * dst,size_t dlen,const char * src,int casef,int transf,int mapf)447f982db4aSGavin Atkinson doprocess(char *dst, size_t dlen, const char *src,
448f982db4aSGavin Atkinson int casef, int transf, int mapf)
449f982db4aSGavin Atkinson {
450f982db4aSGavin Atkinson if (casef)
451f982db4aSGavin Atkinson src = docase(dst, dlen, src);
452f982db4aSGavin Atkinson if (transf)
453f982db4aSGavin Atkinson src = dotrans(dst, dlen, src);
454f982db4aSGavin Atkinson if (mapf)
455f982db4aSGavin Atkinson src = domap(dst, dlen, src);
456f982db4aSGavin Atkinson return src;
457f982db4aSGavin Atkinson }
458f982db4aSGavin Atkinson
459f982db4aSGavin Atkinson /*
460f982db4aSGavin Atkinson * Send multiple files.
461f982db4aSGavin Atkinson */
462f982db4aSGavin Atkinson void
mput(int argc,char * argv[])463f982db4aSGavin Atkinson mput(int argc, char *argv[])
464f982db4aSGavin Atkinson {
465f982db4aSGavin Atkinson int i;
466f982db4aSGavin Atkinson sigfunc oldintr;
467f982db4aSGavin Atkinson int ointer;
468f982db4aSGavin Atkinson const char *tp;
469f982db4aSGavin Atkinson
470f982db4aSGavin Atkinson if (argc == 0 || (argc == 1 && !another(&argc, &argv, "local-files"))) {
471cc361f65SGavin Atkinson UPRINTF("usage: %s local-files\n", argv[0]);
472f982db4aSGavin Atkinson code = -1;
473f982db4aSGavin Atkinson return;
474f982db4aSGavin Atkinson }
475f982db4aSGavin Atkinson mflag = 1;
476f982db4aSGavin Atkinson oldintr = xsignal(SIGINT, mintr);
477f982db4aSGavin Atkinson if (sigsetjmp(jabort, 1))
478cc361f65SGavin Atkinson mabort(argv[0]);
479f982db4aSGavin Atkinson if (proxy) {
480f982db4aSGavin Atkinson char *cp;
481f982db4aSGavin Atkinson
482f982db4aSGavin Atkinson while ((cp = remglob(argv, 0, NULL)) != NULL) {
483f982db4aSGavin Atkinson if (*cp == '\0' || !connected) {
484f982db4aSGavin Atkinson mflag = 0;
485f982db4aSGavin Atkinson continue;
486f982db4aSGavin Atkinson }
487f982db4aSGavin Atkinson if (mflag && confirm(argv[0], cp)) {
488f982db4aSGavin Atkinson char buf[MAXPATHLEN];
489f982db4aSGavin Atkinson tp = doprocess(buf, sizeof(buf), cp,
490f982db4aSGavin Atkinson mcase, ntflag, mapflag);
491f982db4aSGavin Atkinson sendrequest((sunique) ? "STOU" : "STOR",
492f982db4aSGavin Atkinson cp, tp, cp != tp || !interactive);
493f982db4aSGavin Atkinson if (!mflag && fromatty) {
494f982db4aSGavin Atkinson ointer = interactive;
495f982db4aSGavin Atkinson interactive = 1;
496cc361f65SGavin Atkinson if (confirm(argv[0], NULL)) {
497f982db4aSGavin Atkinson mflag++;
498f982db4aSGavin Atkinson }
499f982db4aSGavin Atkinson interactive = ointer;
500f982db4aSGavin Atkinson }
501f982db4aSGavin Atkinson }
502f982db4aSGavin Atkinson }
503f982db4aSGavin Atkinson goto cleanupmput;
504f982db4aSGavin Atkinson }
505f982db4aSGavin Atkinson for (i = 1; i < argc && connected; i++) {
506f982db4aSGavin Atkinson char **cpp;
507f982db4aSGavin Atkinson glob_t gl;
508f982db4aSGavin Atkinson int flags;
509f982db4aSGavin Atkinson
510f982db4aSGavin Atkinson if (!doglob) {
511f982db4aSGavin Atkinson if (mflag && confirm(argv[0], argv[i])) {
512f982db4aSGavin Atkinson char buf[MAXPATHLEN];
513f982db4aSGavin Atkinson tp = doprocess(buf, sizeof(buf), argv[i],
514f982db4aSGavin Atkinson 0, ntflag, mapflag);
515f982db4aSGavin Atkinson sendrequest((sunique) ? "STOU" : "STOR",
516f982db4aSGavin Atkinson argv[i], tp, tp != argv[i] || !interactive);
517f982db4aSGavin Atkinson if (!mflag && fromatty) {
518f982db4aSGavin Atkinson ointer = interactive;
519f982db4aSGavin Atkinson interactive = 1;
520cc361f65SGavin Atkinson if (confirm(argv[0], NULL)) {
521f982db4aSGavin Atkinson mflag++;
522f982db4aSGavin Atkinson }
523f982db4aSGavin Atkinson interactive = ointer;
524f982db4aSGavin Atkinson }
525f982db4aSGavin Atkinson }
526f982db4aSGavin Atkinson continue;
527f982db4aSGavin Atkinson }
528f982db4aSGavin Atkinson
529f982db4aSGavin Atkinson memset(&gl, 0, sizeof(gl));
530f982db4aSGavin Atkinson flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE;
531f982db4aSGavin Atkinson if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
532cc361f65SGavin Atkinson warnx("Glob pattern `%s' not found", argv[i]);
533f982db4aSGavin Atkinson globfree(&gl);
534f982db4aSGavin Atkinson continue;
535f982db4aSGavin Atkinson }
536f982db4aSGavin Atkinson for (cpp = gl.gl_pathv; cpp && *cpp != NULL && connected;
537f982db4aSGavin Atkinson cpp++) {
538f982db4aSGavin Atkinson if (mflag && confirm(argv[0], *cpp)) {
539f982db4aSGavin Atkinson char buf[MAXPATHLEN];
540f982db4aSGavin Atkinson tp = *cpp;
541f982db4aSGavin Atkinson tp = doprocess(buf, sizeof(buf), *cpp,
542f982db4aSGavin Atkinson 0, ntflag, mapflag);
543f982db4aSGavin Atkinson sendrequest((sunique) ? "STOU" : "STOR",
544f982db4aSGavin Atkinson *cpp, tp, *cpp != tp || !interactive);
545f982db4aSGavin Atkinson if (!mflag && fromatty) {
546f982db4aSGavin Atkinson ointer = interactive;
547f982db4aSGavin Atkinson interactive = 1;
548cc361f65SGavin Atkinson if (confirm(argv[0], NULL)) {
549f982db4aSGavin Atkinson mflag++;
550f982db4aSGavin Atkinson }
551f982db4aSGavin Atkinson interactive = ointer;
552f982db4aSGavin Atkinson }
553f982db4aSGavin Atkinson }
554f982db4aSGavin Atkinson }
555f982db4aSGavin Atkinson globfree(&gl);
556f982db4aSGavin Atkinson }
557f982db4aSGavin Atkinson cleanupmput:
558f982db4aSGavin Atkinson (void)xsignal(SIGINT, oldintr);
559f982db4aSGavin Atkinson mflag = 0;
560f982db4aSGavin Atkinson }
561f982db4aSGavin Atkinson
562f982db4aSGavin Atkinson void
reget(int argc,char * argv[])563f982db4aSGavin Atkinson reget(int argc, char *argv[])
564f982db4aSGavin Atkinson {
565f982db4aSGavin Atkinson
566f982db4aSGavin Atkinson (void)getit(argc, argv, 1, "r+");
567f982db4aSGavin Atkinson }
568f982db4aSGavin Atkinson
569f982db4aSGavin Atkinson void
get(int argc,char * argv[])570f982db4aSGavin Atkinson get(int argc, char *argv[])
571f982db4aSGavin Atkinson {
572f982db4aSGavin Atkinson
573f982db4aSGavin Atkinson (void)getit(argc, argv, 0, restart_point ? "r+" : "w" );
574f982db4aSGavin Atkinson }
575f982db4aSGavin Atkinson
576f982db4aSGavin Atkinson /*
577f982db4aSGavin Atkinson * Receive one file.
578f982db4aSGavin Atkinson * If restartit is 1, restart the xfer always.
579f982db4aSGavin Atkinson * If restartit is -1, restart the xfer only if the remote file is newer.
580f982db4aSGavin Atkinson */
581f982db4aSGavin Atkinson int
getit(int argc,char * argv[],int restartit,const char * gmode)582cc361f65SGavin Atkinson getit(int argc, char *argv[], int restartit, const char *gmode)
583f982db4aSGavin Atkinson {
584f982db4aSGavin Atkinson int loc, rval;
585f982db4aSGavin Atkinson char *remfile, *olocfile;
586f982db4aSGavin Atkinson const char *locfile;
587f982db4aSGavin Atkinson char buf[MAXPATHLEN];
588f982db4aSGavin Atkinson
589f982db4aSGavin Atkinson loc = rval = 0;
590f982db4aSGavin Atkinson if (argc == 2) {
591f982db4aSGavin Atkinson argc++;
592f982db4aSGavin Atkinson argv[2] = argv[1];
593f982db4aSGavin Atkinson loc++;
594f982db4aSGavin Atkinson }
595f982db4aSGavin Atkinson if (argc == 0 || (argc == 1 && !another(&argc, &argv, "remote-file")))
596f982db4aSGavin Atkinson goto usage;
597f982db4aSGavin Atkinson if ((argc < 3 && !another(&argc, &argv, "local-file")) || argc > 3) {
598f982db4aSGavin Atkinson usage:
599cc361f65SGavin Atkinson UPRINTF("usage: %s remote-file [local-file]\n", argv[0]);
600f982db4aSGavin Atkinson code = -1;
601f982db4aSGavin Atkinson return (0);
602f982db4aSGavin Atkinson }
603f982db4aSGavin Atkinson remfile = argv[1];
604f982db4aSGavin Atkinson if ((olocfile = globulize(argv[2])) == NULL) {
605f982db4aSGavin Atkinson code = -1;
606f982db4aSGavin Atkinson return (0);
607f982db4aSGavin Atkinson }
608f982db4aSGavin Atkinson locfile = doprocess(buf, sizeof(buf), olocfile,
609f982db4aSGavin Atkinson loc && mcase, loc && ntflag, loc && mapflag);
610f982db4aSGavin Atkinson if (restartit) {
611f982db4aSGavin Atkinson struct stat stbuf;
612f982db4aSGavin Atkinson int ret;
613f982db4aSGavin Atkinson
614f982db4aSGavin Atkinson if (! features[FEAT_REST_STREAM]) {
615f982db4aSGavin Atkinson fprintf(ttyout,
616f982db4aSGavin Atkinson "Restart is not supported by the remote server.\n");
617f982db4aSGavin Atkinson return (0);
618f982db4aSGavin Atkinson }
619f982db4aSGavin Atkinson ret = stat(locfile, &stbuf);
620f982db4aSGavin Atkinson if (restartit == 1) {
621f982db4aSGavin Atkinson if (ret < 0) {
622cc361f65SGavin Atkinson warn("Can't stat `%s'", locfile);
623f982db4aSGavin Atkinson goto freegetit;
624f982db4aSGavin Atkinson }
625f982db4aSGavin Atkinson restart_point = stbuf.st_size;
626f982db4aSGavin Atkinson } else {
627f982db4aSGavin Atkinson if (ret == 0) {
628f982db4aSGavin Atkinson time_t mtime;
629f982db4aSGavin Atkinson
630f982db4aSGavin Atkinson mtime = remotemodtime(argv[1], 0);
631f982db4aSGavin Atkinson if (mtime == -1)
632f982db4aSGavin Atkinson goto freegetit;
633f982db4aSGavin Atkinson if (stbuf.st_mtime >= mtime) {
634f982db4aSGavin Atkinson rval = 1;
635f982db4aSGavin Atkinson goto freegetit;
636f982db4aSGavin Atkinson }
637f982db4aSGavin Atkinson }
638f982db4aSGavin Atkinson }
639f982db4aSGavin Atkinson }
640f982db4aSGavin Atkinson
641cc361f65SGavin Atkinson recvrequest("RETR", locfile, remfile, gmode,
642f982db4aSGavin Atkinson remfile != argv[1] || locfile != argv[2], loc);
643f982db4aSGavin Atkinson restart_point = 0;
644f982db4aSGavin Atkinson freegetit:
645f982db4aSGavin Atkinson (void)free(olocfile);
646f982db4aSGavin Atkinson return (rval);
647f982db4aSGavin Atkinson }
648f982db4aSGavin Atkinson
649f982db4aSGavin Atkinson /* ARGSUSED */
650cc361f65SGavin Atkinson static void
mintr(int signo)651f982db4aSGavin Atkinson mintr(int signo)
652f982db4aSGavin Atkinson {
653f982db4aSGavin Atkinson
654f982db4aSGavin Atkinson alarmtimer(0);
655f982db4aSGavin Atkinson if (fromatty)
656f982db4aSGavin Atkinson write(fileno(ttyout), "\n", 1);
657f982db4aSGavin Atkinson siglongjmp(jabort, 1);
658f982db4aSGavin Atkinson }
659f982db4aSGavin Atkinson
660cc361f65SGavin Atkinson static void
mabort(const char * cmd)661cc361f65SGavin Atkinson mabort(const char *cmd)
662f982db4aSGavin Atkinson {
663f982db4aSGavin Atkinson int ointer, oconf;
664f982db4aSGavin Atkinson
665f982db4aSGavin Atkinson if (mflag && fromatty) {
666f982db4aSGavin Atkinson ointer = interactive;
667f982db4aSGavin Atkinson oconf = confirmrest;
668f982db4aSGavin Atkinson interactive = 1;
669f982db4aSGavin Atkinson confirmrest = 0;
670cc361f65SGavin Atkinson if (confirm(cmd, NULL)) {
671f982db4aSGavin Atkinson interactive = ointer;
672f982db4aSGavin Atkinson confirmrest = oconf;
673f982db4aSGavin Atkinson return;
674f982db4aSGavin Atkinson }
675f982db4aSGavin Atkinson interactive = ointer;
676f982db4aSGavin Atkinson confirmrest = oconf;
677f982db4aSGavin Atkinson }
678f982db4aSGavin Atkinson mflag = 0;
679f982db4aSGavin Atkinson }
680f982db4aSGavin Atkinson
681f982db4aSGavin Atkinson /*
682f982db4aSGavin Atkinson * Get multiple files.
683f982db4aSGavin Atkinson */
684f982db4aSGavin Atkinson void
mget(int argc,char * argv[])685f982db4aSGavin Atkinson mget(int argc, char *argv[])
686f982db4aSGavin Atkinson {
687f982db4aSGavin Atkinson sigfunc oldintr;
688f982db4aSGavin Atkinson int ointer;
689f982db4aSGavin Atkinson char *cp;
690f982db4aSGavin Atkinson const char *tp;
691cc361f65SGavin Atkinson int volatile restartit;
692f982db4aSGavin Atkinson
693f982db4aSGavin Atkinson if (argc == 0 ||
694f982db4aSGavin Atkinson (argc == 1 && !another(&argc, &argv, "remote-files"))) {
695cc361f65SGavin Atkinson UPRINTF("usage: %s remote-files\n", argv[0]);
696f982db4aSGavin Atkinson code = -1;
697f982db4aSGavin Atkinson return;
698f982db4aSGavin Atkinson }
699f982db4aSGavin Atkinson mflag = 1;
700f982db4aSGavin Atkinson restart_point = 0;
701f982db4aSGavin Atkinson restartit = 0;
702f982db4aSGavin Atkinson if (strcmp(argv[0], "mreget") == 0) {
703f982db4aSGavin Atkinson if (! features[FEAT_REST_STREAM]) {
704f982db4aSGavin Atkinson fprintf(ttyout,
705f982db4aSGavin Atkinson "Restart is not supported by the remote server.\n");
706f982db4aSGavin Atkinson return;
707f982db4aSGavin Atkinson }
708f982db4aSGavin Atkinson restartit = 1;
709f982db4aSGavin Atkinson }
710f982db4aSGavin Atkinson oldintr = xsignal(SIGINT, mintr);
711f982db4aSGavin Atkinson if (sigsetjmp(jabort, 1))
712cc361f65SGavin Atkinson mabort(argv[0]);
713f982db4aSGavin Atkinson while ((cp = remglob(argv, proxy, NULL)) != NULL) {
714f982db4aSGavin Atkinson char buf[MAXPATHLEN];
715f982db4aSGavin Atkinson if (*cp == '\0' || !connected) {
716f982db4aSGavin Atkinson mflag = 0;
717f982db4aSGavin Atkinson continue;
718f982db4aSGavin Atkinson }
719f982db4aSGavin Atkinson if (! mflag)
720f982db4aSGavin Atkinson continue;
721f982db4aSGavin Atkinson if (! fileindir(cp, localcwd)) {
722f982db4aSGavin Atkinson fprintf(ttyout, "Skipping non-relative filename `%s'\n",
723f982db4aSGavin Atkinson cp);
724f982db4aSGavin Atkinson continue;
725f982db4aSGavin Atkinson }
726f982db4aSGavin Atkinson if (!confirm(argv[0], cp))
727f982db4aSGavin Atkinson continue;
728f982db4aSGavin Atkinson tp = doprocess(buf, sizeof(buf), cp, mcase, ntflag, mapflag);
729f982db4aSGavin Atkinson if (restartit) {
730f982db4aSGavin Atkinson struct stat stbuf;
731f982db4aSGavin Atkinson
732f982db4aSGavin Atkinson if (stat(tp, &stbuf) == 0)
733f982db4aSGavin Atkinson restart_point = stbuf.st_size;
734f982db4aSGavin Atkinson else
735cc361f65SGavin Atkinson warn("Can't stat `%s'", tp);
736f982db4aSGavin Atkinson }
737f982db4aSGavin Atkinson recvrequest("RETR", tp, cp, restart_point ? "r+" : "w",
738f982db4aSGavin Atkinson tp != cp || !interactive, 1);
739f982db4aSGavin Atkinson restart_point = 0;
740f982db4aSGavin Atkinson if (!mflag && fromatty) {
741f982db4aSGavin Atkinson ointer = interactive;
742f982db4aSGavin Atkinson interactive = 1;
743cc361f65SGavin Atkinson if (confirm(argv[0], NULL))
744f982db4aSGavin Atkinson mflag++;
745f982db4aSGavin Atkinson interactive = ointer;
746f982db4aSGavin Atkinson }
747f982db4aSGavin Atkinson }
748f982db4aSGavin Atkinson (void)xsignal(SIGINT, oldintr);
749f982db4aSGavin Atkinson mflag = 0;
750f982db4aSGavin Atkinson }
751f982db4aSGavin Atkinson
752f982db4aSGavin Atkinson /*
753f982db4aSGavin Atkinson * Read list of filenames from a local file and get those
754f982db4aSGavin Atkinson */
755f982db4aSGavin Atkinson void
fget(int argc,char * argv[])756f982db4aSGavin Atkinson fget(int argc, char *argv[])
757f982db4aSGavin Atkinson {
758cc361f65SGavin Atkinson const char *gmode;
759f982db4aSGavin Atkinson FILE *fp;
760cc361f65SGavin Atkinson char buf[MAXPATHLEN], cmdbuf[MAX_C_NAME];
761f982db4aSGavin Atkinson
762f982db4aSGavin Atkinson if (argc != 2) {
763cc361f65SGavin Atkinson UPRINTF("usage: %s localfile\n", argv[0]);
764f982db4aSGavin Atkinson code = -1;
765f982db4aSGavin Atkinson return;
766f982db4aSGavin Atkinson }
767f982db4aSGavin Atkinson
768f982db4aSGavin Atkinson fp = fopen(argv[1], "r");
769f982db4aSGavin Atkinson if (fp == NULL) {
770cc361f65SGavin Atkinson fprintf(ttyout, "Can't open source file %s\n", argv[1]);
771f982db4aSGavin Atkinson code = -1;
772f982db4aSGavin Atkinson return;
773f982db4aSGavin Atkinson }
774f982db4aSGavin Atkinson
775cc361f65SGavin Atkinson (void)strlcpy(cmdbuf, "get", sizeof(cmdbuf));
776cc361f65SGavin Atkinson argv[0] = cmdbuf;
777cc361f65SGavin Atkinson gmode = restart_point ? "r+" : "w";
778f982db4aSGavin Atkinson
779cc361f65SGavin Atkinson while (get_line(fp, buf, sizeof(buf), NULL) >= 0) {
780f982db4aSGavin Atkinson if (buf[0] == '\0')
781f982db4aSGavin Atkinson continue;
782f982db4aSGavin Atkinson argv[1] = buf;
783cc361f65SGavin Atkinson (void)getit(argc, argv, 0, gmode);
784f982db4aSGavin Atkinson }
785f982db4aSGavin Atkinson fclose(fp);
786f982db4aSGavin Atkinson }
787f982db4aSGavin Atkinson
788cc361f65SGavin Atkinson const char *
onoff(int val)789cc361f65SGavin Atkinson onoff(int val)
790f982db4aSGavin Atkinson {
791f982db4aSGavin Atkinson
792cc361f65SGavin Atkinson return (val ? "on" : "off");
793f982db4aSGavin Atkinson }
794f982db4aSGavin Atkinson
795f982db4aSGavin Atkinson /*
796f982db4aSGavin Atkinson * Show status.
797f982db4aSGavin Atkinson */
798f982db4aSGavin Atkinson /*ARGSUSED*/
799f982db4aSGavin Atkinson void
status(int argc,char * argv[])800f982db4aSGavin Atkinson status(int argc, char *argv[])
801f982db4aSGavin Atkinson {
802f982db4aSGavin Atkinson
803f982db4aSGavin Atkinson if (argc == 0) {
804cc361f65SGavin Atkinson UPRINTF("usage: %s\n", argv[0]);
805f982db4aSGavin Atkinson code = -1;
806f982db4aSGavin Atkinson return;
807f982db4aSGavin Atkinson }
808f982db4aSGavin Atkinson #ifndef NO_STATUS
809f982db4aSGavin Atkinson if (connected)
810f982db4aSGavin Atkinson fprintf(ttyout, "Connected %sto %s.\n",
811f982db4aSGavin Atkinson connected == -1 ? "and logged in" : "", hostname);
812f982db4aSGavin Atkinson else
813f982db4aSGavin Atkinson fputs("Not connected.\n", ttyout);
814f982db4aSGavin Atkinson if (!proxy) {
815f982db4aSGavin Atkinson pswitch(1);
816f982db4aSGavin Atkinson if (connected) {
817f982db4aSGavin Atkinson fprintf(ttyout, "Connected for proxy commands to %s.\n",
818f982db4aSGavin Atkinson hostname);
819f982db4aSGavin Atkinson }
820f982db4aSGavin Atkinson else {
821f982db4aSGavin Atkinson fputs("No proxy connection.\n", ttyout);
822f982db4aSGavin Atkinson }
823f982db4aSGavin Atkinson pswitch(0);
824f982db4aSGavin Atkinson }
825f982db4aSGavin Atkinson fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n", onoff(gatemode),
826f982db4aSGavin Atkinson *gateserver ? gateserver : "(none)", gateport);
827f982db4aSGavin Atkinson fprintf(ttyout, "Passive mode: %s; fallback to active mode: %s.\n",
828f982db4aSGavin Atkinson onoff(passivemode), onoff(activefallback));
829f982db4aSGavin Atkinson fprintf(ttyout, "Mode: %s; Type: %s; Form: %s; Structure: %s.\n",
830f982db4aSGavin Atkinson modename, typename, formname, structname);
831f982db4aSGavin Atkinson fprintf(ttyout, "Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s.\n",
832f982db4aSGavin Atkinson onoff(verbose), onoff(bell), onoff(interactive), onoff(doglob));
833f982db4aSGavin Atkinson fprintf(ttyout, "Store unique: %s; Receive unique: %s.\n",
834f982db4aSGavin Atkinson onoff(sunique), onoff(runique));
835f982db4aSGavin Atkinson fprintf(ttyout, "Preserve modification times: %s.\n", onoff(preserve));
836f982db4aSGavin Atkinson fprintf(ttyout, "Case: %s; CR stripping: %s.\n", onoff(mcase),
837f982db4aSGavin Atkinson onoff(crflag));
838f982db4aSGavin Atkinson if (ntflag) {
839f982db4aSGavin Atkinson fprintf(ttyout, "Ntrans: (in) %s (out) %s\n", ntin, ntout);
840f982db4aSGavin Atkinson }
841f982db4aSGavin Atkinson else {
842f982db4aSGavin Atkinson fputs("Ntrans: off.\n", ttyout);
843f982db4aSGavin Atkinson }
844f982db4aSGavin Atkinson if (mapflag) {
845f982db4aSGavin Atkinson fprintf(ttyout, "Nmap: (in) %s (out) %s\n", mapin, mapout);
846f982db4aSGavin Atkinson }
847f982db4aSGavin Atkinson else {
848f982db4aSGavin Atkinson fputs("Nmap: off.\n", ttyout);
849f982db4aSGavin Atkinson }
850f982db4aSGavin Atkinson fprintf(ttyout,
851f982db4aSGavin Atkinson "Hash mark printing: %s; Mark count: %d; Progress bar: %s.\n",
852f982db4aSGavin Atkinson onoff(hash), mark, onoff(progress));
853f982db4aSGavin Atkinson fprintf(ttyout,
854f982db4aSGavin Atkinson "Get transfer rate throttle: %s; maximum: %d; increment %d.\n",
855f982db4aSGavin Atkinson onoff(rate_get), rate_get, rate_get_incr);
856f982db4aSGavin Atkinson fprintf(ttyout,
857f982db4aSGavin Atkinson "Put transfer rate throttle: %s; maximum: %d; increment %d.\n",
858f982db4aSGavin Atkinson onoff(rate_put), rate_put, rate_put_incr);
859f982db4aSGavin Atkinson fprintf(ttyout,
860f982db4aSGavin Atkinson "Socket buffer sizes: send %d, receive %d.\n",
861f982db4aSGavin Atkinson sndbuf_size, rcvbuf_size);
862f982db4aSGavin Atkinson fprintf(ttyout, "Use of PORT cmds: %s.\n", onoff(sendport));
863f982db4aSGavin Atkinson fprintf(ttyout, "Use of EPSV/EPRT cmds for IPv4: %s%s.\n", onoff(epsv4),
864f982db4aSGavin Atkinson epsv4bad ? " (disabled for this connection)" : "");
865cc361f65SGavin Atkinson fprintf(ttyout, "Use of EPSV/EPRT cmds for IPv6: %s%s.\n", onoff(epsv6),
866cc361f65SGavin Atkinson epsv6bad ? " (disabled for this connection)" : "");
867f982db4aSGavin Atkinson fprintf(ttyout, "Command line editing: %s.\n",
868f982db4aSGavin Atkinson #ifdef NO_EDITCOMPLETE
869f982db4aSGavin Atkinson "support not compiled in"
870f982db4aSGavin Atkinson #else /* !def NO_EDITCOMPLETE */
871f982db4aSGavin Atkinson onoff(editing)
872f982db4aSGavin Atkinson #endif /* !def NO_EDITCOMPLETE */
873f982db4aSGavin Atkinson );
874f982db4aSGavin Atkinson if (macnum > 0) {
875f982db4aSGavin Atkinson int i;
876f982db4aSGavin Atkinson
877f982db4aSGavin Atkinson fputs("Macros:\n", ttyout);
878f982db4aSGavin Atkinson for (i=0; i<macnum; i++) {
879f982db4aSGavin Atkinson fprintf(ttyout, "\t%s\n", macros[i].mac_name);
880f982db4aSGavin Atkinson }
881f982db4aSGavin Atkinson }
882f982db4aSGavin Atkinson #endif /* !def NO_STATUS */
883f982db4aSGavin Atkinson fprintf(ttyout, "Version: %s %s\n", FTP_PRODUCT, FTP_VERSION);
884f982db4aSGavin Atkinson code = 0;
885f982db4aSGavin Atkinson }
886f982db4aSGavin Atkinson
887f982db4aSGavin Atkinson /*
888f982db4aSGavin Atkinson * Toggle a variable
889f982db4aSGavin Atkinson */
890f982db4aSGavin Atkinson int
togglevar(int argc,char * argv[],int * var,const char * mesg)891f982db4aSGavin Atkinson togglevar(int argc, char *argv[], int *var, const char *mesg)
892f982db4aSGavin Atkinson {
893f982db4aSGavin Atkinson if (argc == 1) {
894f982db4aSGavin Atkinson *var = !*var;
895f982db4aSGavin Atkinson } else if (argc == 2 && strcasecmp(argv[1], "on") == 0) {
896f982db4aSGavin Atkinson *var = 1;
897f982db4aSGavin Atkinson } else if (argc == 2 && strcasecmp(argv[1], "off") == 0) {
898f982db4aSGavin Atkinson *var = 0;
899f982db4aSGavin Atkinson } else {
900cc361f65SGavin Atkinson UPRINTF("usage: %s [ on | off ]\n", argv[0]);
901f982db4aSGavin Atkinson return (-1);
902f982db4aSGavin Atkinson }
903f982db4aSGavin Atkinson if (mesg)
904f982db4aSGavin Atkinson fprintf(ttyout, "%s %s.\n", mesg, onoff(*var));
905f982db4aSGavin Atkinson return (*var);
906f982db4aSGavin Atkinson }
907f982db4aSGavin Atkinson
908f982db4aSGavin Atkinson /*
909f982db4aSGavin Atkinson * Set beep on cmd completed mode.
910f982db4aSGavin Atkinson */
911f982db4aSGavin Atkinson /*VARARGS*/
912f982db4aSGavin Atkinson void
setbell(int argc,char * argv[])913f982db4aSGavin Atkinson setbell(int argc, char *argv[])
914f982db4aSGavin Atkinson {
915f982db4aSGavin Atkinson
916f982db4aSGavin Atkinson code = togglevar(argc, argv, &bell, "Bell mode");
917f982db4aSGavin Atkinson }
918f982db4aSGavin Atkinson
919f982db4aSGavin Atkinson /*
920f982db4aSGavin Atkinson * Set command line editing
921f982db4aSGavin Atkinson */
922f982db4aSGavin Atkinson /*VARARGS*/
923f982db4aSGavin Atkinson void
setedit(int argc,char * argv[])924f982db4aSGavin Atkinson setedit(int argc, char *argv[])
925f982db4aSGavin Atkinson {
926f982db4aSGavin Atkinson
927f982db4aSGavin Atkinson #ifdef NO_EDITCOMPLETE
928f982db4aSGavin Atkinson if (argc == 0) {
929cc361f65SGavin Atkinson UPRINTF("usage: %s\n", argv[0]);
930f982db4aSGavin Atkinson code = -1;
931f982db4aSGavin Atkinson return;
932f982db4aSGavin Atkinson }
933f982db4aSGavin Atkinson if (verbose)
934f982db4aSGavin Atkinson fputs("Editing support not compiled in; ignoring command.\n",
935f982db4aSGavin Atkinson ttyout);
936f982db4aSGavin Atkinson #else /* !def NO_EDITCOMPLETE */
937f982db4aSGavin Atkinson code = togglevar(argc, argv, &editing, "Editing mode");
938f982db4aSGavin Atkinson controlediting();
939f982db4aSGavin Atkinson #endif /* !def NO_EDITCOMPLETE */
940f982db4aSGavin Atkinson }
941f982db4aSGavin Atkinson
942f982db4aSGavin Atkinson /*
943f982db4aSGavin Atkinson * Turn on packet tracing.
944f982db4aSGavin Atkinson */
945f982db4aSGavin Atkinson /*VARARGS*/
946f982db4aSGavin Atkinson void
settrace(int argc,char * argv[])947f982db4aSGavin Atkinson settrace(int argc, char *argv[])
948f982db4aSGavin Atkinson {
949f982db4aSGavin Atkinson
950f982db4aSGavin Atkinson code = togglevar(argc, argv, &trace, "Packet tracing");
951f982db4aSGavin Atkinson }
952f982db4aSGavin Atkinson
953f982db4aSGavin Atkinson /*
954f982db4aSGavin Atkinson * Toggle hash mark printing during transfers, or set hash mark bytecount.
955f982db4aSGavin Atkinson */
956f982db4aSGavin Atkinson /*VARARGS*/
957f982db4aSGavin Atkinson void
sethash(int argc,char * argv[])958f982db4aSGavin Atkinson sethash(int argc, char *argv[])
959f982db4aSGavin Atkinson {
960f982db4aSGavin Atkinson if (argc == 1)
961f982db4aSGavin Atkinson hash = !hash;
962f982db4aSGavin Atkinson else if (argc != 2) {
963cc361f65SGavin Atkinson UPRINTF("usage: %s [ on | off | bytecount ]\n",
964f982db4aSGavin Atkinson argv[0]);
965f982db4aSGavin Atkinson code = -1;
966f982db4aSGavin Atkinson return;
967f982db4aSGavin Atkinson } else if (strcasecmp(argv[1], "on") == 0)
968f982db4aSGavin Atkinson hash = 1;
969f982db4aSGavin Atkinson else if (strcasecmp(argv[1], "off") == 0)
970f982db4aSGavin Atkinson hash = 0;
971f982db4aSGavin Atkinson else {
972f982db4aSGavin Atkinson int nmark;
973f982db4aSGavin Atkinson
974f982db4aSGavin Atkinson nmark = strsuftoi(argv[1]);
975f982db4aSGavin Atkinson if (nmark < 1) {
976f982db4aSGavin Atkinson fprintf(ttyout, "mark: bad bytecount value `%s'.\n",
977f982db4aSGavin Atkinson argv[1]);
978f982db4aSGavin Atkinson code = -1;
979f982db4aSGavin Atkinson return;
980f982db4aSGavin Atkinson }
981f982db4aSGavin Atkinson mark = nmark;
982f982db4aSGavin Atkinson hash = 1;
983f982db4aSGavin Atkinson }
984f982db4aSGavin Atkinson fprintf(ttyout, "Hash mark printing %s", onoff(hash));
985f982db4aSGavin Atkinson if (hash)
986f982db4aSGavin Atkinson fprintf(ttyout, " (%d bytes/hash mark)", mark);
987f982db4aSGavin Atkinson fputs(".\n", ttyout);
988f982db4aSGavin Atkinson if (hash)
989f982db4aSGavin Atkinson progress = 0;
990f982db4aSGavin Atkinson code = hash;
991f982db4aSGavin Atkinson }
992f982db4aSGavin Atkinson
993f982db4aSGavin Atkinson /*
994f982db4aSGavin Atkinson * Turn on printing of server echo's.
995f982db4aSGavin Atkinson */
996f982db4aSGavin Atkinson /*VARARGS*/
997f982db4aSGavin Atkinson void
setverbose(int argc,char * argv[])998f982db4aSGavin Atkinson setverbose(int argc, char *argv[])
999f982db4aSGavin Atkinson {
1000f982db4aSGavin Atkinson
1001f982db4aSGavin Atkinson code = togglevar(argc, argv, &verbose, "Verbose mode");
1002f982db4aSGavin Atkinson }
1003f982db4aSGavin Atkinson
1004f982db4aSGavin Atkinson /*
1005f982db4aSGavin Atkinson * Toggle PORT/LPRT cmd use before each data connection.
1006f982db4aSGavin Atkinson */
1007f982db4aSGavin Atkinson /*VARARGS*/
1008f982db4aSGavin Atkinson void
setport(int argc,char * argv[])1009f982db4aSGavin Atkinson setport(int argc, char *argv[])
1010f982db4aSGavin Atkinson {
1011f982db4aSGavin Atkinson
1012f982db4aSGavin Atkinson code = togglevar(argc, argv, &sendport, "Use of PORT/LPRT cmds");
1013f982db4aSGavin Atkinson }
1014f982db4aSGavin Atkinson
1015f982db4aSGavin Atkinson /*
1016f982db4aSGavin Atkinson * Toggle transfer progress bar.
1017f982db4aSGavin Atkinson */
1018f982db4aSGavin Atkinson /*VARARGS*/
1019f982db4aSGavin Atkinson void
setprogress(int argc,char * argv[])1020f982db4aSGavin Atkinson setprogress(int argc, char *argv[])
1021f982db4aSGavin Atkinson {
1022f982db4aSGavin Atkinson
1023f982db4aSGavin Atkinson code = togglevar(argc, argv, &progress, "Progress bar");
1024f982db4aSGavin Atkinson if (progress)
1025f982db4aSGavin Atkinson hash = 0;
1026f982db4aSGavin Atkinson }
1027f982db4aSGavin Atkinson
1028f982db4aSGavin Atkinson /*
1029f982db4aSGavin Atkinson * Turn on interactive prompting during mget, mput, and mdelete.
1030f982db4aSGavin Atkinson */
1031f982db4aSGavin Atkinson /*VARARGS*/
1032f982db4aSGavin Atkinson void
setprompt(int argc,char * argv[])1033f982db4aSGavin Atkinson setprompt(int argc, char *argv[])
1034f982db4aSGavin Atkinson {
1035f982db4aSGavin Atkinson
1036f982db4aSGavin Atkinson code = togglevar(argc, argv, &interactive, "Interactive mode");
1037f982db4aSGavin Atkinson }
1038f982db4aSGavin Atkinson
1039f982db4aSGavin Atkinson /*
1040f982db4aSGavin Atkinson * Toggle gate-ftp mode, or set gate-ftp server
1041f982db4aSGavin Atkinson */
1042f982db4aSGavin Atkinson /*VARARGS*/
1043f982db4aSGavin Atkinson void
setgate(int argc,char * argv[])1044f982db4aSGavin Atkinson setgate(int argc, char *argv[])
1045f982db4aSGavin Atkinson {
1046f982db4aSGavin Atkinson static char gsbuf[MAXHOSTNAMELEN];
1047f982db4aSGavin Atkinson
1048f982db4aSGavin Atkinson if (argc == 0 || argc > 3) {
1049cc361f65SGavin Atkinson UPRINTF(
1050f982db4aSGavin Atkinson "usage: %s [ on | off | gateserver [port] ]\n", argv[0]);
1051f982db4aSGavin Atkinson code = -1;
1052f982db4aSGavin Atkinson return;
1053f982db4aSGavin Atkinson } else if (argc < 2) {
1054f982db4aSGavin Atkinson gatemode = !gatemode;
1055f982db4aSGavin Atkinson } else {
1056f982db4aSGavin Atkinson if (argc == 2 && strcasecmp(argv[1], "on") == 0)
1057f982db4aSGavin Atkinson gatemode = 1;
1058f982db4aSGavin Atkinson else if (argc == 2 && strcasecmp(argv[1], "off") == 0)
1059f982db4aSGavin Atkinson gatemode = 0;
1060f982db4aSGavin Atkinson else {
1061f982db4aSGavin Atkinson if (argc == 3)
1062cc361f65SGavin Atkinson gateport = ftp_strdup(argv[2]);
1063f982db4aSGavin Atkinson (void)strlcpy(gsbuf, argv[1], sizeof(gsbuf));
1064f982db4aSGavin Atkinson gateserver = gsbuf;
1065f982db4aSGavin Atkinson gatemode = 1;
1066f982db4aSGavin Atkinson }
1067f982db4aSGavin Atkinson }
1068f982db4aSGavin Atkinson if (gatemode && (gateserver == NULL || *gateserver == '\0')) {
1069f982db4aSGavin Atkinson fprintf(ttyout,
1070f982db4aSGavin Atkinson "Disabling gate-ftp mode - no gate-ftp server defined.\n");
1071f982db4aSGavin Atkinson gatemode = 0;
1072f982db4aSGavin Atkinson } else {
1073f982db4aSGavin Atkinson fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n",
1074f982db4aSGavin Atkinson onoff(gatemode), *gateserver ? gateserver : "(none)",
1075f982db4aSGavin Atkinson gateport);
1076f982db4aSGavin Atkinson }
1077f982db4aSGavin Atkinson code = gatemode;
1078f982db4aSGavin Atkinson }
1079f982db4aSGavin Atkinson
1080f982db4aSGavin Atkinson /*
1081f982db4aSGavin Atkinson * Toggle metacharacter interpretation on local file names.
1082f982db4aSGavin Atkinson */
1083f982db4aSGavin Atkinson /*VARARGS*/
1084f982db4aSGavin Atkinson void
setglob(int argc,char * argv[])1085f982db4aSGavin Atkinson setglob(int argc, char *argv[])
1086f982db4aSGavin Atkinson {
1087f982db4aSGavin Atkinson
1088f982db4aSGavin Atkinson code = togglevar(argc, argv, &doglob, "Globbing");
1089f982db4aSGavin Atkinson }
1090f982db4aSGavin Atkinson
1091f982db4aSGavin Atkinson /*
1092f982db4aSGavin Atkinson * Toggle preserving modification times on retrieved files.
1093f982db4aSGavin Atkinson */
1094f982db4aSGavin Atkinson /*VARARGS*/
1095f982db4aSGavin Atkinson void
setpreserve(int argc,char * argv[])1096f982db4aSGavin Atkinson setpreserve(int argc, char *argv[])
1097f982db4aSGavin Atkinson {
1098f982db4aSGavin Atkinson
1099f982db4aSGavin Atkinson code = togglevar(argc, argv, &preserve, "Preserve modification times");
1100f982db4aSGavin Atkinson }
1101f982db4aSGavin Atkinson
1102f982db4aSGavin Atkinson /*
1103f982db4aSGavin Atkinson * Set debugging mode on/off and/or set level of debugging.
1104f982db4aSGavin Atkinson */
1105f982db4aSGavin Atkinson /*VARARGS*/
1106f982db4aSGavin Atkinson void
setdebug(int argc,char * argv[])1107f982db4aSGavin Atkinson setdebug(int argc, char *argv[])
1108f982db4aSGavin Atkinson {
1109f982db4aSGavin Atkinson if (argc == 0 || argc > 2) {
1110cc361f65SGavin Atkinson UPRINTF("usage: %s [ on | off | debuglevel ]\n", argv[0]);
1111f982db4aSGavin Atkinson code = -1;
1112f982db4aSGavin Atkinson return;
1113f982db4aSGavin Atkinson } else if (argc == 2) {
1114f982db4aSGavin Atkinson if (strcasecmp(argv[1], "on") == 0)
1115cc361f65SGavin Atkinson ftp_debug = 1;
1116f982db4aSGavin Atkinson else if (strcasecmp(argv[1], "off") == 0)
1117cc361f65SGavin Atkinson ftp_debug = 0;
1118f982db4aSGavin Atkinson else {
1119f982db4aSGavin Atkinson int val;
1120f982db4aSGavin Atkinson
1121f982db4aSGavin Atkinson val = strsuftoi(argv[1]);
1122f982db4aSGavin Atkinson if (val < 0) {
1123f982db4aSGavin Atkinson fprintf(ttyout, "%s: bad debugging value.\n",
1124f982db4aSGavin Atkinson argv[1]);
1125f982db4aSGavin Atkinson code = -1;
1126f982db4aSGavin Atkinson return;
1127f982db4aSGavin Atkinson }
1128cc361f65SGavin Atkinson ftp_debug = val;
1129f982db4aSGavin Atkinson }
1130f982db4aSGavin Atkinson } else
1131cc361f65SGavin Atkinson ftp_debug = !ftp_debug;
1132cc361f65SGavin Atkinson if (ftp_debug)
1133f982db4aSGavin Atkinson options |= SO_DEBUG;
1134f982db4aSGavin Atkinson else
1135f982db4aSGavin Atkinson options &= ~SO_DEBUG;
1136cc361f65SGavin Atkinson fprintf(ttyout, "Debugging %s (ftp_debug=%d).\n", onoff(ftp_debug), ftp_debug);
1137cc361f65SGavin Atkinson code = ftp_debug > 0;
1138f982db4aSGavin Atkinson }
1139f982db4aSGavin Atkinson
1140f982db4aSGavin Atkinson /*
1141f982db4aSGavin Atkinson * Set current working directory on remote machine.
1142f982db4aSGavin Atkinson */
1143f982db4aSGavin Atkinson void
cd(int argc,char * argv[])1144f982db4aSGavin Atkinson cd(int argc, char *argv[])
1145f982db4aSGavin Atkinson {
1146f982db4aSGavin Atkinson int r;
1147f982db4aSGavin Atkinson
1148f982db4aSGavin Atkinson if (argc == 0 || argc > 2 ||
1149f982db4aSGavin Atkinson (argc == 1 && !another(&argc, &argv, "remote-directory"))) {
1150cc361f65SGavin Atkinson UPRINTF("usage: %s remote-directory\n", argv[0]);
1151f982db4aSGavin Atkinson code = -1;
1152f982db4aSGavin Atkinson return;
1153f982db4aSGavin Atkinson }
1154f982db4aSGavin Atkinson r = command("CWD %s", argv[1]);
1155f982db4aSGavin Atkinson if (r == ERROR && code == 500) {
1156f982db4aSGavin Atkinson if (verbose)
1157f982db4aSGavin Atkinson fputs("CWD command not recognized, trying XCWD.\n",
1158f982db4aSGavin Atkinson ttyout);
1159f982db4aSGavin Atkinson r = command("XCWD %s", argv[1]);
1160f982db4aSGavin Atkinson }
1161f982db4aSGavin Atkinson if (r == COMPLETE) {
1162f982db4aSGavin Atkinson dirchange = 1;
1163f982db4aSGavin Atkinson updateremotecwd();
1164f982db4aSGavin Atkinson }
1165f982db4aSGavin Atkinson }
1166f982db4aSGavin Atkinson
1167f982db4aSGavin Atkinson /*
1168f982db4aSGavin Atkinson * Set current working directory on local machine.
1169f982db4aSGavin Atkinson */
1170f982db4aSGavin Atkinson void
lcd(int argc,char * argv[])1171f982db4aSGavin Atkinson lcd(int argc, char *argv[])
1172f982db4aSGavin Atkinson {
1173f982db4aSGavin Atkinson char *locdir;
1174f982db4aSGavin Atkinson
1175f982db4aSGavin Atkinson code = -1;
1176f982db4aSGavin Atkinson if (argc == 1) {
1177f982db4aSGavin Atkinson argc++;
1178f982db4aSGavin Atkinson argv[1] = localhome;
1179f982db4aSGavin Atkinson }
1180f982db4aSGavin Atkinson if (argc != 2) {
1181cc361f65SGavin Atkinson UPRINTF("usage: %s [local-directory]\n", argv[0]);
1182f982db4aSGavin Atkinson return;
1183f982db4aSGavin Atkinson }
1184f982db4aSGavin Atkinson if ((locdir = globulize(argv[1])) == NULL)
1185f982db4aSGavin Atkinson return;
1186f982db4aSGavin Atkinson if (chdir(locdir) == -1)
1187cc361f65SGavin Atkinson warn("Can't chdir `%s'", locdir);
1188f982db4aSGavin Atkinson else {
1189f982db4aSGavin Atkinson updatelocalcwd();
1190f982db4aSGavin Atkinson if (localcwd[0]) {
1191f982db4aSGavin Atkinson fprintf(ttyout, "Local directory now: %s\n", localcwd);
1192f982db4aSGavin Atkinson code = 0;
1193f982db4aSGavin Atkinson } else {
1194f982db4aSGavin Atkinson fprintf(ttyout, "Unable to determine local directory\n");
1195f982db4aSGavin Atkinson }
1196f982db4aSGavin Atkinson }
1197f982db4aSGavin Atkinson (void)free(locdir);
1198f982db4aSGavin Atkinson }
1199f982db4aSGavin Atkinson
1200f982db4aSGavin Atkinson /*
1201f982db4aSGavin Atkinson * Delete a single file.
1202f982db4aSGavin Atkinson */
1203f982db4aSGavin Atkinson void
delete(int argc,char * argv[])1204f982db4aSGavin Atkinson delete(int argc, char *argv[])
1205f982db4aSGavin Atkinson {
1206f982db4aSGavin Atkinson
1207f982db4aSGavin Atkinson if (argc == 0 || argc > 2 ||
1208f982db4aSGavin Atkinson (argc == 1 && !another(&argc, &argv, "remote-file"))) {
1209cc361f65SGavin Atkinson UPRINTF("usage: %s remote-file\n", argv[0]);
1210f982db4aSGavin Atkinson code = -1;
1211f982db4aSGavin Atkinson return;
1212f982db4aSGavin Atkinson }
1213f982db4aSGavin Atkinson if (command("DELE %s", argv[1]) == COMPLETE)
1214f982db4aSGavin Atkinson dirchange = 1;
1215f982db4aSGavin Atkinson }
1216f982db4aSGavin Atkinson
1217f982db4aSGavin Atkinson /*
1218f982db4aSGavin Atkinson * Delete multiple files.
1219f982db4aSGavin Atkinson */
1220f982db4aSGavin Atkinson void
mdelete(int argc,char * argv[])1221f982db4aSGavin Atkinson mdelete(int argc, char *argv[])
1222f982db4aSGavin Atkinson {
1223f982db4aSGavin Atkinson sigfunc oldintr;
1224f982db4aSGavin Atkinson int ointer;
1225f982db4aSGavin Atkinson char *cp;
1226f982db4aSGavin Atkinson
1227f982db4aSGavin Atkinson if (argc == 0 ||
1228f982db4aSGavin Atkinson (argc == 1 && !another(&argc, &argv, "remote-files"))) {
1229cc361f65SGavin Atkinson UPRINTF("usage: %s [remote-files]\n", argv[0]);
1230f982db4aSGavin Atkinson code = -1;
1231f982db4aSGavin Atkinson return;
1232f982db4aSGavin Atkinson }
1233f982db4aSGavin Atkinson mflag = 1;
1234f982db4aSGavin Atkinson oldintr = xsignal(SIGINT, mintr);
1235f982db4aSGavin Atkinson if (sigsetjmp(jabort, 1))
1236cc361f65SGavin Atkinson mabort(argv[0]);
1237f982db4aSGavin Atkinson while ((cp = remglob(argv, 0, NULL)) != NULL) {
1238f982db4aSGavin Atkinson if (*cp == '\0') {
1239f982db4aSGavin Atkinson mflag = 0;
1240f982db4aSGavin Atkinson continue;
1241f982db4aSGavin Atkinson }
1242f982db4aSGavin Atkinson if (mflag && confirm(argv[0], cp)) {
1243f982db4aSGavin Atkinson if (command("DELE %s", cp) == COMPLETE)
1244f982db4aSGavin Atkinson dirchange = 1;
1245f982db4aSGavin Atkinson if (!mflag && fromatty) {
1246f982db4aSGavin Atkinson ointer = interactive;
1247f982db4aSGavin Atkinson interactive = 1;
1248cc361f65SGavin Atkinson if (confirm(argv[0], NULL)) {
1249f982db4aSGavin Atkinson mflag++;
1250f982db4aSGavin Atkinson }
1251f982db4aSGavin Atkinson interactive = ointer;
1252f982db4aSGavin Atkinson }
1253f982db4aSGavin Atkinson }
1254f982db4aSGavin Atkinson }
1255f982db4aSGavin Atkinson (void)xsignal(SIGINT, oldintr);
1256f982db4aSGavin Atkinson mflag = 0;
1257f982db4aSGavin Atkinson }
1258f982db4aSGavin Atkinson
1259f982db4aSGavin Atkinson /*
1260f982db4aSGavin Atkinson * Rename a remote file.
1261f982db4aSGavin Atkinson */
1262f982db4aSGavin Atkinson void
renamefile(int argc,char * argv[])1263f982db4aSGavin Atkinson renamefile(int argc, char *argv[])
1264f982db4aSGavin Atkinson {
1265f982db4aSGavin Atkinson
1266f982db4aSGavin Atkinson if (argc == 0 || (argc == 1 && !another(&argc, &argv, "from-name")))
1267f982db4aSGavin Atkinson goto usage;
1268f982db4aSGavin Atkinson if ((argc < 3 && !another(&argc, &argv, "to-name")) || argc > 3) {
1269f982db4aSGavin Atkinson usage:
1270cc361f65SGavin Atkinson UPRINTF("usage: %s from-name to-name\n", argv[0]);
1271f982db4aSGavin Atkinson code = -1;
1272f982db4aSGavin Atkinson return;
1273f982db4aSGavin Atkinson }
1274f982db4aSGavin Atkinson if (command("RNFR %s", argv[1]) == CONTINUE &&
1275f982db4aSGavin Atkinson command("RNTO %s", argv[2]) == COMPLETE)
1276f982db4aSGavin Atkinson dirchange = 1;
1277f982db4aSGavin Atkinson }
1278f982db4aSGavin Atkinson
1279f982db4aSGavin Atkinson /*
1280f982db4aSGavin Atkinson * Get a directory listing of remote files.
1281f982db4aSGavin Atkinson * Supports being invoked as:
1282f982db4aSGavin Atkinson * cmd runs
1283f982db4aSGavin Atkinson * --- ----
1284f982db4aSGavin Atkinson * dir, ls LIST
1285f982db4aSGavin Atkinson * mlsd MLSD
1286f982db4aSGavin Atkinson * nlist NLST
1287f982db4aSGavin Atkinson * pdir, pls LIST |$PAGER
1288cc361f65SGavin Atkinson * pmlsd MLSD |$PAGER
1289f982db4aSGavin Atkinson */
1290f982db4aSGavin Atkinson void
ls(int argc,char * argv[])1291f982db4aSGavin Atkinson ls(int argc, char *argv[])
1292f982db4aSGavin Atkinson {
1293f982db4aSGavin Atkinson const char *cmd;
1294cc361f65SGavin Atkinson char *remdir, *locbuf;
1295cc361f65SGavin Atkinson const char *locfile;
1296cc361f65SGavin Atkinson int pagecmd, mlsdcmd;
1297f982db4aSGavin Atkinson
1298f982db4aSGavin Atkinson remdir = NULL;
1299cc361f65SGavin Atkinson locbuf = NULL;
1300f982db4aSGavin Atkinson locfile = "-";
1301cc361f65SGavin Atkinson pagecmd = mlsdcmd = 0;
1302f982db4aSGavin Atkinson /*
1303f982db4aSGavin Atkinson * the only commands that start with `p' are
1304f982db4aSGavin Atkinson * the `pager' versions.
1305f982db4aSGavin Atkinson */
1306f982db4aSGavin Atkinson if (argv[0][0] == 'p')
1307f982db4aSGavin Atkinson pagecmd = 1;
1308f982db4aSGavin Atkinson if (strcmp(argv[0] + pagecmd , "mlsd") == 0) {
1309f982db4aSGavin Atkinson if (! features[FEAT_MLST]) {
1310f982db4aSGavin Atkinson fprintf(ttyout,
1311f982db4aSGavin Atkinson "MLSD is not supported by the remote server.\n");
1312f982db4aSGavin Atkinson return;
1313f982db4aSGavin Atkinson }
1314f982db4aSGavin Atkinson mlsdcmd = 1;
1315f982db4aSGavin Atkinson }
1316f982db4aSGavin Atkinson if (argc == 0)
1317f982db4aSGavin Atkinson goto usage;
1318f982db4aSGavin Atkinson
1319f982db4aSGavin Atkinson if (mlsdcmd)
1320f982db4aSGavin Atkinson cmd = "MLSD";
1321f982db4aSGavin Atkinson else if (strcmp(argv[0] + pagecmd, "nlist") == 0)
1322f982db4aSGavin Atkinson cmd = "NLST";
1323f982db4aSGavin Atkinson else
1324f982db4aSGavin Atkinson cmd = "LIST";
1325f982db4aSGavin Atkinson
1326f982db4aSGavin Atkinson if (argc > 1)
1327f982db4aSGavin Atkinson remdir = argv[1];
1328f982db4aSGavin Atkinson if (argc > 2)
1329f982db4aSGavin Atkinson locfile = argv[2];
1330f982db4aSGavin Atkinson if (argc > 3 || ((pagecmd | mlsdcmd) && argc > 2)) {
1331f982db4aSGavin Atkinson usage:
1332f982db4aSGavin Atkinson if (pagecmd || mlsdcmd)
1333cc361f65SGavin Atkinson UPRINTF("usage: %s [remote-path]\n", argv[0]);
1334f982db4aSGavin Atkinson else
1335cc361f65SGavin Atkinson UPRINTF("usage: %s [remote-path [local-file]]\n",
1336f982db4aSGavin Atkinson argv[0]);
1337f982db4aSGavin Atkinson code = -1;
1338f982db4aSGavin Atkinson goto freels;
1339f982db4aSGavin Atkinson }
1340f982db4aSGavin Atkinson
1341f982db4aSGavin Atkinson if (pagecmd) {
1342cc361f65SGavin Atkinson const char *p;
1343cc361f65SGavin Atkinson size_t len;
1344f982db4aSGavin Atkinson
1345f982db4aSGavin Atkinson p = getoptionvalue("pager");
1346f982db4aSGavin Atkinson if (EMPTYSTRING(p))
1347f982db4aSGavin Atkinson p = DEFAULTPAGER;
1348f982db4aSGavin Atkinson len = strlen(p) + 2;
1349cc361f65SGavin Atkinson locbuf = ftp_malloc(len);
1350cc361f65SGavin Atkinson locbuf[0] = '|';
1351cc361f65SGavin Atkinson (void)strlcpy(locbuf + 1, p, len - 1);
1352cc361f65SGavin Atkinson locfile = locbuf;
1353f982db4aSGavin Atkinson } else if ((strcmp(locfile, "-") != 0) && *locfile != '|') {
1354cc361f65SGavin Atkinson if ((locbuf = globulize(locfile)) == NULL ||
1355cc361f65SGavin Atkinson !confirm("output to local-file:", locbuf)) {
1356f982db4aSGavin Atkinson code = -1;
1357f982db4aSGavin Atkinson goto freels;
1358f982db4aSGavin Atkinson }
1359cc361f65SGavin Atkinson locfile = locbuf;
1360f982db4aSGavin Atkinson }
1361f982db4aSGavin Atkinson recvrequest(cmd, locfile, remdir, "w", 0, 0);
1362f982db4aSGavin Atkinson freels:
1363cc361f65SGavin Atkinson if (locbuf)
1364cc361f65SGavin Atkinson (void)free(locbuf);
1365f982db4aSGavin Atkinson }
1366f982db4aSGavin Atkinson
1367f982db4aSGavin Atkinson /*
1368f982db4aSGavin Atkinson * Get a directory listing of multiple remote files.
1369f982db4aSGavin Atkinson */
1370f982db4aSGavin Atkinson void
mls(int argc,char * argv[])1371f982db4aSGavin Atkinson mls(int argc, char *argv[])
1372f982db4aSGavin Atkinson {
1373f982db4aSGavin Atkinson sigfunc oldintr;
1374f982db4aSGavin Atkinson int ointer, i;
1375cc361f65SGavin Atkinson int volatile dolist;
1376cc361f65SGavin Atkinson char * volatile dest, *odest;
1377cc361f65SGavin Atkinson const char *lmode;
1378f982db4aSGavin Atkinson
1379f982db4aSGavin Atkinson if (argc == 0)
1380f982db4aSGavin Atkinson goto usage;
1381f982db4aSGavin Atkinson if (argc < 2 && !another(&argc, &argv, "remote-files"))
1382f982db4aSGavin Atkinson goto usage;
1383f982db4aSGavin Atkinson if (argc < 3 && !another(&argc, &argv, "local-file")) {
1384f982db4aSGavin Atkinson usage:
1385cc361f65SGavin Atkinson UPRINTF("usage: %s remote-files local-file\n", argv[0]);
1386f982db4aSGavin Atkinson code = -1;
1387f982db4aSGavin Atkinson return;
1388f982db4aSGavin Atkinson }
1389f982db4aSGavin Atkinson odest = dest = argv[argc - 1];
1390f982db4aSGavin Atkinson argv[argc - 1] = NULL;
1391f982db4aSGavin Atkinson if (strcmp(dest, "-") && *dest != '|')
1392f982db4aSGavin Atkinson if (((dest = globulize(dest)) == NULL) ||
1393f982db4aSGavin Atkinson !confirm("output to local-file:", dest)) {
1394f982db4aSGavin Atkinson code = -1;
1395f982db4aSGavin Atkinson return;
1396f982db4aSGavin Atkinson }
1397f982db4aSGavin Atkinson dolist = strcmp(argv[0], "mls");
1398f982db4aSGavin Atkinson mflag = 1;
1399f982db4aSGavin Atkinson oldintr = xsignal(SIGINT, mintr);
1400f982db4aSGavin Atkinson if (sigsetjmp(jabort, 1))
1401cc361f65SGavin Atkinson mabort(argv[0]);
1402f982db4aSGavin Atkinson for (i = 1; mflag && i < argc-1 && connected; i++) {
1403cc361f65SGavin Atkinson lmode = (i == 1) ? "w" : "a";
1404cc361f65SGavin Atkinson recvrequest(dolist ? "LIST" : "NLST", dest, argv[i], lmode,
1405f982db4aSGavin Atkinson 0, 0);
1406f982db4aSGavin Atkinson if (!mflag && fromatty) {
1407f982db4aSGavin Atkinson ointer = interactive;
1408f982db4aSGavin Atkinson interactive = 1;
1409cc361f65SGavin Atkinson if (confirm(argv[0], NULL)) {
1410f982db4aSGavin Atkinson mflag++;
1411f982db4aSGavin Atkinson }
1412f982db4aSGavin Atkinson interactive = ointer;
1413f982db4aSGavin Atkinson }
1414f982db4aSGavin Atkinson }
1415f982db4aSGavin Atkinson (void)xsignal(SIGINT, oldintr);
1416f982db4aSGavin Atkinson mflag = 0;
1417f982db4aSGavin Atkinson if (dest != odest) /* free up after globulize() */
1418f982db4aSGavin Atkinson free(dest);
1419f982db4aSGavin Atkinson }
1420f982db4aSGavin Atkinson
1421f982db4aSGavin Atkinson /*
1422f982db4aSGavin Atkinson * Do a shell escape
1423f982db4aSGavin Atkinson */
1424f982db4aSGavin Atkinson /*ARGSUSED*/
1425f982db4aSGavin Atkinson void
shell(int argc,char * argv[])1426f982db4aSGavin Atkinson shell(int argc, char *argv[])
1427f982db4aSGavin Atkinson {
1428f982db4aSGavin Atkinson pid_t pid;
1429f982db4aSGavin Atkinson sigfunc oldintr;
1430cc361f65SGavin Atkinson char shellnam[MAXPATHLEN];
1431cc361f65SGavin Atkinson const char *shellp, *namep;
1432f982db4aSGavin Atkinson int wait_status;
1433f982db4aSGavin Atkinson
1434f982db4aSGavin Atkinson if (argc == 0) {
1435cc361f65SGavin Atkinson UPRINTF("usage: %s [command [args]]\n", argv[0]);
1436f982db4aSGavin Atkinson code = -1;
1437f982db4aSGavin Atkinson return;
1438f982db4aSGavin Atkinson }
1439f982db4aSGavin Atkinson oldintr = xsignal(SIGINT, SIG_IGN);
1440f982db4aSGavin Atkinson if ((pid = fork()) == 0) {
1441d54cfbd1SPedro F. Giffuni (void)closefrom(3);
1442f982db4aSGavin Atkinson (void)xsignal(SIGINT, SIG_DFL);
1443cc361f65SGavin Atkinson shellp = getenv("SHELL");
1444cc361f65SGavin Atkinson if (shellp == NULL)
1445cc361f65SGavin Atkinson shellp = _PATH_BSHELL;
1446cc361f65SGavin Atkinson namep = strrchr(shellp, '/');
1447f982db4aSGavin Atkinson if (namep == NULL)
1448cc361f65SGavin Atkinson namep = shellp;
1449f982db4aSGavin Atkinson else
1450f982db4aSGavin Atkinson namep++;
1451f982db4aSGavin Atkinson (void)strlcpy(shellnam, namep, sizeof(shellnam));
1452cc361f65SGavin Atkinson if (ftp_debug) {
1453cc361f65SGavin Atkinson fputs(shellp, ttyout);
1454f982db4aSGavin Atkinson putc('\n', ttyout);
1455f982db4aSGavin Atkinson }
1456f982db4aSGavin Atkinson if (argc > 1) {
1457cc361f65SGavin Atkinson execl(shellp, shellnam, "-c", altarg, (char *)0);
1458f982db4aSGavin Atkinson }
1459f982db4aSGavin Atkinson else {
1460cc361f65SGavin Atkinson execl(shellp, shellnam, (char *)0);
1461f982db4aSGavin Atkinson }
1462cc361f65SGavin Atkinson warn("Can't execute `%s'", shellp);
1463f982db4aSGavin Atkinson code = -1;
1464f982db4aSGavin Atkinson exit(1);
1465f982db4aSGavin Atkinson }
1466f982db4aSGavin Atkinson if (pid > 0)
1467f982db4aSGavin Atkinson while (wait(&wait_status) != pid)
1468f982db4aSGavin Atkinson ;
1469f982db4aSGavin Atkinson (void)xsignal(SIGINT, oldintr);
1470f982db4aSGavin Atkinson if (pid == -1) {
1471cc361f65SGavin Atkinson warn("Can't fork a subshell; try again later");
1472f982db4aSGavin Atkinson code = -1;
1473f982db4aSGavin Atkinson } else
1474f982db4aSGavin Atkinson code = 0;
1475f982db4aSGavin Atkinson }
1476f982db4aSGavin Atkinson
1477f982db4aSGavin Atkinson /*
1478f982db4aSGavin Atkinson * Send new user information (re-login)
1479f982db4aSGavin Atkinson */
1480f982db4aSGavin Atkinson void
user(int argc,char * argv[])1481f982db4aSGavin Atkinson user(int argc, char *argv[])
1482f982db4aSGavin Atkinson {
1483cc361f65SGavin Atkinson char *password;
1484cc361f65SGavin Atkinson char emptypass[] = "";
1485f982db4aSGavin Atkinson int n, aflag = 0;
1486f982db4aSGavin Atkinson
1487f982db4aSGavin Atkinson if (argc == 0)
1488f982db4aSGavin Atkinson goto usage;
1489f982db4aSGavin Atkinson if (argc < 2)
1490f982db4aSGavin Atkinson (void)another(&argc, &argv, "username");
1491f982db4aSGavin Atkinson if (argc < 2 || argc > 4) {
1492f982db4aSGavin Atkinson usage:
1493cc361f65SGavin Atkinson UPRINTF("usage: %s username [password [account]]\n",
1494f982db4aSGavin Atkinson argv[0]);
1495f982db4aSGavin Atkinson code = -1;
1496f982db4aSGavin Atkinson return;
1497f982db4aSGavin Atkinson }
1498f982db4aSGavin Atkinson n = command("USER %s", argv[1]);
1499f982db4aSGavin Atkinson if (n == CONTINUE) {
1500f982db4aSGavin Atkinson if (argc < 3) {
1501cc361f65SGavin Atkinson password = getpass("Password: ");
1502cc361f65SGavin Atkinson if (password == NULL)
1503cc361f65SGavin Atkinson password = emptypass;
1504cc361f65SGavin Atkinson } else {
1505cc361f65SGavin Atkinson password = argv[2];
1506f982db4aSGavin Atkinson }
1507cc361f65SGavin Atkinson n = command("PASS %s", password);
1508cc361f65SGavin Atkinson memset(password, 0, strlen(password));
1509f982db4aSGavin Atkinson }
1510f982db4aSGavin Atkinson if (n == CONTINUE) {
1511f982db4aSGavin Atkinson aflag++;
1512cc361f65SGavin Atkinson if (argc < 4) {
1513cc361f65SGavin Atkinson password = getpass("Account: ");
1514cc361f65SGavin Atkinson if (password == NULL)
1515cc361f65SGavin Atkinson password = emptypass;
1516cc361f65SGavin Atkinson } else {
1517cc361f65SGavin Atkinson password = argv[3];
1518cc361f65SGavin Atkinson }
1519cc361f65SGavin Atkinson n = command("ACCT %s", password);
1520cc361f65SGavin Atkinson memset(password, 0, strlen(password));
1521f982db4aSGavin Atkinson }
1522f982db4aSGavin Atkinson if (n != COMPLETE) {
1523f982db4aSGavin Atkinson fputs("Login failed.\n", ttyout);
1524f982db4aSGavin Atkinson return;
1525f982db4aSGavin Atkinson }
1526f982db4aSGavin Atkinson if (!aflag && argc == 4) {
1527cc361f65SGavin Atkinson password = argv[3];
1528cc361f65SGavin Atkinson (void)command("ACCT %s", password);
1529cc361f65SGavin Atkinson memset(password, 0, strlen(password));
1530f982db4aSGavin Atkinson }
1531f982db4aSGavin Atkinson connected = -1;
1532f982db4aSGavin Atkinson getremoteinfo();
1533f982db4aSGavin Atkinson }
1534f982db4aSGavin Atkinson
1535f982db4aSGavin Atkinson /*
1536f982db4aSGavin Atkinson * Print working directory on remote machine.
1537f982db4aSGavin Atkinson */
1538f982db4aSGavin Atkinson /*VARARGS*/
1539f982db4aSGavin Atkinson void
pwd(int argc,char * argv[])1540f982db4aSGavin Atkinson pwd(int argc, char *argv[])
1541f982db4aSGavin Atkinson {
1542f982db4aSGavin Atkinson
1543f982db4aSGavin Atkinson code = -1;
1544f982db4aSGavin Atkinson if (argc != 1) {
1545cc361f65SGavin Atkinson UPRINTF("usage: %s\n", argv[0]);
1546f982db4aSGavin Atkinson return;
1547f982db4aSGavin Atkinson }
1548f982db4aSGavin Atkinson if (! remotecwd[0])
1549f982db4aSGavin Atkinson updateremotecwd();
1550f982db4aSGavin Atkinson if (! remotecwd[0])
1551f982db4aSGavin Atkinson fprintf(ttyout, "Unable to determine remote directory\n");
1552f982db4aSGavin Atkinson else {
1553f982db4aSGavin Atkinson fprintf(ttyout, "Remote directory: %s\n", remotecwd);
1554f982db4aSGavin Atkinson code = 0;
1555f982db4aSGavin Atkinson }
1556f982db4aSGavin Atkinson }
1557f982db4aSGavin Atkinson
1558f982db4aSGavin Atkinson /*
1559f982db4aSGavin Atkinson * Print working directory on local machine.
1560f982db4aSGavin Atkinson */
1561f982db4aSGavin Atkinson void
lpwd(int argc,char * argv[])1562f982db4aSGavin Atkinson lpwd(int argc, char *argv[])
1563f982db4aSGavin Atkinson {
1564f982db4aSGavin Atkinson
1565f982db4aSGavin Atkinson code = -1;
1566f982db4aSGavin Atkinson if (argc != 1) {
1567cc361f65SGavin Atkinson UPRINTF("usage: %s\n", argv[0]);
1568f982db4aSGavin Atkinson return;
1569f982db4aSGavin Atkinson }
1570f982db4aSGavin Atkinson if (! localcwd[0])
1571f982db4aSGavin Atkinson updatelocalcwd();
1572f982db4aSGavin Atkinson if (! localcwd[0])
1573f982db4aSGavin Atkinson fprintf(ttyout, "Unable to determine local directory\n");
1574f982db4aSGavin Atkinson else {
1575f982db4aSGavin Atkinson fprintf(ttyout, "Local directory: %s\n", localcwd);
1576f982db4aSGavin Atkinson code = 0;
1577f982db4aSGavin Atkinson }
1578f982db4aSGavin Atkinson }
1579f982db4aSGavin Atkinson
1580f982db4aSGavin Atkinson /*
1581f982db4aSGavin Atkinson * Make a directory.
1582f982db4aSGavin Atkinson */
1583f982db4aSGavin Atkinson void
makedir(int argc,char * argv[])1584f982db4aSGavin Atkinson makedir(int argc, char *argv[])
1585f982db4aSGavin Atkinson {
1586f982db4aSGavin Atkinson int r;
1587f982db4aSGavin Atkinson
1588f982db4aSGavin Atkinson if (argc == 0 || argc > 2 ||
1589f982db4aSGavin Atkinson (argc == 1 && !another(&argc, &argv, "directory-name"))) {
1590cc361f65SGavin Atkinson UPRINTF("usage: %s directory-name\n", argv[0]);
1591f982db4aSGavin Atkinson code = -1;
1592f982db4aSGavin Atkinson return;
1593f982db4aSGavin Atkinson }
1594f982db4aSGavin Atkinson r = command("MKD %s", argv[1]);
1595f982db4aSGavin Atkinson if (r == ERROR && code == 500) {
1596f982db4aSGavin Atkinson if (verbose)
1597f982db4aSGavin Atkinson fputs("MKD command not recognized, trying XMKD.\n",
1598f982db4aSGavin Atkinson ttyout);
1599f982db4aSGavin Atkinson r = command("XMKD %s", argv[1]);
1600f982db4aSGavin Atkinson }
1601f982db4aSGavin Atkinson if (r == COMPLETE)
1602f982db4aSGavin Atkinson dirchange = 1;
1603f982db4aSGavin Atkinson }
1604f982db4aSGavin Atkinson
1605f982db4aSGavin Atkinson /*
1606f982db4aSGavin Atkinson * Remove a directory.
1607f982db4aSGavin Atkinson */
1608f982db4aSGavin Atkinson void
removedir(int argc,char * argv[])1609f982db4aSGavin Atkinson removedir(int argc, char *argv[])
1610f982db4aSGavin Atkinson {
1611f982db4aSGavin Atkinson int r;
1612f982db4aSGavin Atkinson
1613f982db4aSGavin Atkinson if (argc == 0 || argc > 2 ||
1614f982db4aSGavin Atkinson (argc == 1 && !another(&argc, &argv, "directory-name"))) {
1615cc361f65SGavin Atkinson UPRINTF("usage: %s directory-name\n", argv[0]);
1616f982db4aSGavin Atkinson code = -1;
1617f982db4aSGavin Atkinson return;
1618f982db4aSGavin Atkinson }
1619f982db4aSGavin Atkinson r = command("RMD %s", argv[1]);
1620f982db4aSGavin Atkinson if (r == ERROR && code == 500) {
1621f982db4aSGavin Atkinson if (verbose)
1622f982db4aSGavin Atkinson fputs("RMD command not recognized, trying XRMD.\n",
1623f982db4aSGavin Atkinson ttyout);
1624f982db4aSGavin Atkinson r = command("XRMD %s", argv[1]);
1625f982db4aSGavin Atkinson }
1626f982db4aSGavin Atkinson if (r == COMPLETE)
1627f982db4aSGavin Atkinson dirchange = 1;
1628f982db4aSGavin Atkinson }
1629f982db4aSGavin Atkinson
1630f982db4aSGavin Atkinson /*
1631f982db4aSGavin Atkinson * Send a line, verbatim, to the remote machine.
1632f982db4aSGavin Atkinson */
1633f982db4aSGavin Atkinson void
quote(int argc,char * argv[])1634f982db4aSGavin Atkinson quote(int argc, char *argv[])
1635f982db4aSGavin Atkinson {
1636f982db4aSGavin Atkinson
1637f982db4aSGavin Atkinson if (argc == 0 ||
1638f982db4aSGavin Atkinson (argc == 1 && !another(&argc, &argv, "command line to send"))) {
1639cc361f65SGavin Atkinson UPRINTF("usage: %s line-to-send\n", argv[0]);
1640f982db4aSGavin Atkinson code = -1;
1641f982db4aSGavin Atkinson return;
1642f982db4aSGavin Atkinson }
1643f982db4aSGavin Atkinson quote1("", argc, argv);
1644f982db4aSGavin Atkinson }
1645f982db4aSGavin Atkinson
1646f982db4aSGavin Atkinson /*
1647f982db4aSGavin Atkinson * Send a SITE command to the remote machine. The line
1648f982db4aSGavin Atkinson * is sent verbatim to the remote machine, except that the
1649f982db4aSGavin Atkinson * word "SITE" is added at the front.
1650f982db4aSGavin Atkinson */
1651f982db4aSGavin Atkinson void
site(int argc,char * argv[])1652f982db4aSGavin Atkinson site(int argc, char *argv[])
1653f982db4aSGavin Atkinson {
1654f982db4aSGavin Atkinson
1655f982db4aSGavin Atkinson if (argc == 0 ||
1656f982db4aSGavin Atkinson (argc == 1 && !another(&argc, &argv, "arguments to SITE command"))){
1657cc361f65SGavin Atkinson UPRINTF("usage: %s line-to-send\n", argv[0]);
1658f982db4aSGavin Atkinson code = -1;
1659f982db4aSGavin Atkinson return;
1660f982db4aSGavin Atkinson }
1661f982db4aSGavin Atkinson quote1("SITE ", argc, argv);
1662f982db4aSGavin Atkinson }
1663f982db4aSGavin Atkinson
1664f982db4aSGavin Atkinson /*
1665f982db4aSGavin Atkinson * Turn argv[1..argc) into a space-separated string, then prepend initial text.
1666f982db4aSGavin Atkinson * Send the result as a one-line command and get response.
1667f982db4aSGavin Atkinson */
1668f982db4aSGavin Atkinson void
quote1(const char * initial,int argc,char * argv[])1669f982db4aSGavin Atkinson quote1(const char *initial, int argc, char *argv[])
1670f982db4aSGavin Atkinson {
1671f982db4aSGavin Atkinson int i;
1672f982db4aSGavin Atkinson char buf[BUFSIZ]; /* must be >= sizeof(line) */
1673f982db4aSGavin Atkinson
1674f982db4aSGavin Atkinson (void)strlcpy(buf, initial, sizeof(buf));
1675f982db4aSGavin Atkinson for (i = 1; i < argc; i++) {
1676f982db4aSGavin Atkinson (void)strlcat(buf, argv[i], sizeof(buf));
1677f982db4aSGavin Atkinson if (i < (argc - 1))
1678f982db4aSGavin Atkinson (void)strlcat(buf, " ", sizeof(buf));
1679f982db4aSGavin Atkinson }
1680f982db4aSGavin Atkinson if (command("%s", buf) == PRELIM) {
1681f982db4aSGavin Atkinson while (getreply(0) == PRELIM)
1682f982db4aSGavin Atkinson continue;
1683f982db4aSGavin Atkinson }
1684f982db4aSGavin Atkinson dirchange = 1;
1685f982db4aSGavin Atkinson }
1686f982db4aSGavin Atkinson
1687f982db4aSGavin Atkinson void
do_chmod(int argc,char * argv[])1688f982db4aSGavin Atkinson do_chmod(int argc, char *argv[])
1689f982db4aSGavin Atkinson {
1690f982db4aSGavin Atkinson
1691f982db4aSGavin Atkinson if (argc == 0 || (argc == 1 && !another(&argc, &argv, "mode")))
1692f982db4aSGavin Atkinson goto usage;
1693f982db4aSGavin Atkinson if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) {
1694f982db4aSGavin Atkinson usage:
1695cc361f65SGavin Atkinson UPRINTF("usage: %s mode remote-file\n", argv[0]);
1696f982db4aSGavin Atkinson code = -1;
1697f982db4aSGavin Atkinson return;
1698f982db4aSGavin Atkinson }
1699f982db4aSGavin Atkinson (void)command("SITE CHMOD %s %s", argv[1], argv[2]);
1700f982db4aSGavin Atkinson }
1701f982db4aSGavin Atkinson
1702f982db4aSGavin Atkinson #define COMMAND_1ARG(argc, argv, cmd) \
1703f982db4aSGavin Atkinson if (argc == 1) \
1704f982db4aSGavin Atkinson command(cmd); \
1705f982db4aSGavin Atkinson else \
1706f982db4aSGavin Atkinson command(cmd " %s", argv[1])
1707f982db4aSGavin Atkinson
1708f982db4aSGavin Atkinson void
do_umask(int argc,char * argv[])1709f982db4aSGavin Atkinson do_umask(int argc, char *argv[])
1710f982db4aSGavin Atkinson {
1711f982db4aSGavin Atkinson int oldverbose = verbose;
1712f982db4aSGavin Atkinson
1713f982db4aSGavin Atkinson if (argc == 0) {
1714cc361f65SGavin Atkinson UPRINTF("usage: %s [umask]\n", argv[0]);
1715f982db4aSGavin Atkinson code = -1;
1716f982db4aSGavin Atkinson return;
1717f982db4aSGavin Atkinson }
1718f982db4aSGavin Atkinson verbose = 1;
1719f982db4aSGavin Atkinson COMMAND_1ARG(argc, argv, "SITE UMASK");
1720f982db4aSGavin Atkinson verbose = oldverbose;
1721f982db4aSGavin Atkinson }
1722f982db4aSGavin Atkinson
1723f982db4aSGavin Atkinson void
idlecmd(int argc,char * argv[])1724f982db4aSGavin Atkinson idlecmd(int argc, char *argv[])
1725f982db4aSGavin Atkinson {
1726f982db4aSGavin Atkinson int oldverbose = verbose;
1727f982db4aSGavin Atkinson
1728f982db4aSGavin Atkinson if (argc < 1 || argc > 2) {
1729cc361f65SGavin Atkinson UPRINTF("usage: %s [seconds]\n", argv[0]);
1730f982db4aSGavin Atkinson code = -1;
1731f982db4aSGavin Atkinson return;
1732f982db4aSGavin Atkinson }
1733f982db4aSGavin Atkinson verbose = 1;
1734f982db4aSGavin Atkinson COMMAND_1ARG(argc, argv, "SITE IDLE");
1735f982db4aSGavin Atkinson verbose = oldverbose;
1736f982db4aSGavin Atkinson }
1737f982db4aSGavin Atkinson
1738f982db4aSGavin Atkinson /*
1739f982db4aSGavin Atkinson * Ask the other side for help.
1740f982db4aSGavin Atkinson */
1741f982db4aSGavin Atkinson void
rmthelp(int argc,char * argv[])1742f982db4aSGavin Atkinson rmthelp(int argc, char *argv[])
1743f982db4aSGavin Atkinson {
1744f982db4aSGavin Atkinson int oldverbose = verbose;
1745f982db4aSGavin Atkinson
1746f982db4aSGavin Atkinson if (argc == 0) {
1747cc361f65SGavin Atkinson UPRINTF("usage: %s\n", argv[0]);
1748f982db4aSGavin Atkinson code = -1;
1749f982db4aSGavin Atkinson return;
1750f982db4aSGavin Atkinson }
1751f982db4aSGavin Atkinson verbose = 1;
1752f982db4aSGavin Atkinson COMMAND_1ARG(argc, argv, "HELP");
1753f982db4aSGavin Atkinson verbose = oldverbose;
1754f982db4aSGavin Atkinson }
1755f982db4aSGavin Atkinson
1756f982db4aSGavin Atkinson /*
1757f982db4aSGavin Atkinson * Terminate session and exit.
1758f982db4aSGavin Atkinson * May be called with 0, NULL.
1759f982db4aSGavin Atkinson */
1760f982db4aSGavin Atkinson /*VARARGS*/
1761f982db4aSGavin Atkinson void
quit(int argc,char * argv[])1762f982db4aSGavin Atkinson quit(int argc, char *argv[])
1763f982db4aSGavin Atkinson {
1764f982db4aSGavin Atkinson
1765f982db4aSGavin Atkinson /* this may be called with argc == 0, argv == NULL */
1766f982db4aSGavin Atkinson if (argc == 0 && argv != NULL) {
1767cc361f65SGavin Atkinson UPRINTF("usage: %s\n", argv[0]);
1768f982db4aSGavin Atkinson code = -1;
1769f982db4aSGavin Atkinson return;
1770f982db4aSGavin Atkinson }
1771f982db4aSGavin Atkinson if (connected)
1772f982db4aSGavin Atkinson disconnect(0, NULL);
1773f982db4aSGavin Atkinson pswitch(1);
1774f982db4aSGavin Atkinson if (connected)
1775f982db4aSGavin Atkinson disconnect(0, NULL);
1776f982db4aSGavin Atkinson exit(0);
1777f982db4aSGavin Atkinson }
1778f982db4aSGavin Atkinson
1779f982db4aSGavin Atkinson /*
1780f982db4aSGavin Atkinson * Terminate session, but don't exit.
1781f982db4aSGavin Atkinson * May be called with 0, NULL.
1782f982db4aSGavin Atkinson */
1783f982db4aSGavin Atkinson void
disconnect(int argc,char * argv[])1784f982db4aSGavin Atkinson disconnect(int argc, char *argv[])
1785f982db4aSGavin Atkinson {
1786f982db4aSGavin Atkinson
1787f982db4aSGavin Atkinson /* this may be called with argc == 0, argv == NULL */
1788f982db4aSGavin Atkinson if (argc == 0 && argv != NULL) {
1789cc361f65SGavin Atkinson UPRINTF("usage: %s\n", argv[0]);
1790f982db4aSGavin Atkinson code = -1;
1791f982db4aSGavin Atkinson return;
1792f982db4aSGavin Atkinson }
1793f982db4aSGavin Atkinson if (!connected)
1794f982db4aSGavin Atkinson return;
1795f982db4aSGavin Atkinson (void)command("QUIT");
1796f982db4aSGavin Atkinson cleanuppeer();
1797f982db4aSGavin Atkinson }
1798f982db4aSGavin Atkinson
1799f982db4aSGavin Atkinson void
account(int argc,char * argv[])1800f982db4aSGavin Atkinson account(int argc, char *argv[])
1801f982db4aSGavin Atkinson {
1802f982db4aSGavin Atkinson char *ap;
1803cc361f65SGavin Atkinson char emptypass[] = "";
1804f982db4aSGavin Atkinson
1805f982db4aSGavin Atkinson if (argc == 0 || argc > 2) {
1806cc361f65SGavin Atkinson UPRINTF("usage: %s [password]\n", argv[0]);
1807f982db4aSGavin Atkinson code = -1;
1808f982db4aSGavin Atkinson return;
1809f982db4aSGavin Atkinson }
1810f982db4aSGavin Atkinson else if (argc == 2)
1811f982db4aSGavin Atkinson ap = argv[1];
1812cc361f65SGavin Atkinson else {
1813f982db4aSGavin Atkinson ap = getpass("Account:");
1814cc361f65SGavin Atkinson if (ap == NULL)
1815cc361f65SGavin Atkinson ap = emptypass;
1816cc361f65SGavin Atkinson }
1817f982db4aSGavin Atkinson (void)command("ACCT %s", ap);
1818cc361f65SGavin Atkinson memset(ap, 0, strlen(ap));
1819f982db4aSGavin Atkinson }
1820f982db4aSGavin Atkinson
1821f982db4aSGavin Atkinson sigjmp_buf abortprox;
1822f982db4aSGavin Atkinson
1823f982db4aSGavin Atkinson void
proxabort(int notused)1824f982db4aSGavin Atkinson proxabort(int notused)
1825f982db4aSGavin Atkinson {
1826f982db4aSGavin Atkinson
1827f982db4aSGavin Atkinson sigint_raised = 1;
1828f982db4aSGavin Atkinson alarmtimer(0);
1829f982db4aSGavin Atkinson if (!proxy) {
1830f982db4aSGavin Atkinson pswitch(1);
1831f982db4aSGavin Atkinson }
1832f982db4aSGavin Atkinson if (connected) {
1833f982db4aSGavin Atkinson proxflag = 1;
1834f982db4aSGavin Atkinson }
1835f982db4aSGavin Atkinson else {
1836f982db4aSGavin Atkinson proxflag = 0;
1837f982db4aSGavin Atkinson }
1838f982db4aSGavin Atkinson pswitch(0);
1839f982db4aSGavin Atkinson siglongjmp(abortprox, 1);
1840f982db4aSGavin Atkinson }
1841f982db4aSGavin Atkinson
1842f982db4aSGavin Atkinson void
doproxy(int argc,char * argv[])1843f982db4aSGavin Atkinson doproxy(int argc, char *argv[])
1844f982db4aSGavin Atkinson {
1845f982db4aSGavin Atkinson struct cmd *c;
1846f982db4aSGavin Atkinson int cmdpos;
1847f982db4aSGavin Atkinson sigfunc oldintr;
1848cc361f65SGavin Atkinson char cmdbuf[MAX_C_NAME];
1849f982db4aSGavin Atkinson
1850f982db4aSGavin Atkinson if (argc == 0 || (argc == 1 && !another(&argc, &argv, "command"))) {
1851cc361f65SGavin Atkinson UPRINTF("usage: %s command\n", argv[0]);
1852f982db4aSGavin Atkinson code = -1;
1853f982db4aSGavin Atkinson return;
1854f982db4aSGavin Atkinson }
1855f982db4aSGavin Atkinson c = getcmd(argv[1]);
1856f982db4aSGavin Atkinson if (c == (struct cmd *) -1) {
1857f982db4aSGavin Atkinson fputs("?Ambiguous command.\n", ttyout);
1858f982db4aSGavin Atkinson code = -1;
1859f982db4aSGavin Atkinson return;
1860f982db4aSGavin Atkinson }
1861f982db4aSGavin Atkinson if (c == 0) {
1862f982db4aSGavin Atkinson fputs("?Invalid command.\n", ttyout);
1863f982db4aSGavin Atkinson code = -1;
1864f982db4aSGavin Atkinson return;
1865f982db4aSGavin Atkinson }
1866f982db4aSGavin Atkinson if (!c->c_proxy) {
1867f982db4aSGavin Atkinson fputs("?Invalid proxy command.\n", ttyout);
1868f982db4aSGavin Atkinson code = -1;
1869f982db4aSGavin Atkinson return;
1870f982db4aSGavin Atkinson }
1871f982db4aSGavin Atkinson if (sigsetjmp(abortprox, 1)) {
1872f982db4aSGavin Atkinson code = -1;
1873f982db4aSGavin Atkinson return;
1874f982db4aSGavin Atkinson }
1875f982db4aSGavin Atkinson oldintr = xsignal(SIGINT, proxabort);
1876f982db4aSGavin Atkinson pswitch(1);
1877f982db4aSGavin Atkinson if (c->c_conn && !connected) {
1878f982db4aSGavin Atkinson fputs("Not connected.\n", ttyout);
1879f982db4aSGavin Atkinson pswitch(0);
1880f982db4aSGavin Atkinson (void)xsignal(SIGINT, oldintr);
1881f982db4aSGavin Atkinson code = -1;
1882f982db4aSGavin Atkinson return;
1883f982db4aSGavin Atkinson }
1884f982db4aSGavin Atkinson cmdpos = strcspn(line, " \t");
1885f982db4aSGavin Atkinson if (cmdpos > 0) /* remove leading "proxy " from input buffer */
1886f982db4aSGavin Atkinson memmove(line, line + cmdpos + 1, strlen(line) - cmdpos + 1);
1887cc361f65SGavin Atkinson (void)strlcpy(cmdbuf, c->c_name, sizeof(cmdbuf));
1888cc361f65SGavin Atkinson argv[1] = cmdbuf;
1889f982db4aSGavin Atkinson (*c->c_handler)(argc-1, argv+1);
1890f982db4aSGavin Atkinson if (connected) {
1891f982db4aSGavin Atkinson proxflag = 1;
1892f982db4aSGavin Atkinson }
1893f982db4aSGavin Atkinson else {
1894f982db4aSGavin Atkinson proxflag = 0;
1895f982db4aSGavin Atkinson }
1896f982db4aSGavin Atkinson pswitch(0);
1897f982db4aSGavin Atkinson (void)xsignal(SIGINT, oldintr);
1898f982db4aSGavin Atkinson }
1899f982db4aSGavin Atkinson
1900f982db4aSGavin Atkinson void
setcase(int argc,char * argv[])1901f982db4aSGavin Atkinson setcase(int argc, char *argv[])
1902f982db4aSGavin Atkinson {
1903f982db4aSGavin Atkinson
1904f982db4aSGavin Atkinson code = togglevar(argc, argv, &mcase, "Case mapping");
1905f982db4aSGavin Atkinson }
1906f982db4aSGavin Atkinson
1907f982db4aSGavin Atkinson /*
1908f982db4aSGavin Atkinson * convert the given name to lower case if it's all upper case, into
1909f982db4aSGavin Atkinson * a static buffer which is returned to the caller
1910f982db4aSGavin Atkinson */
1911f982db4aSGavin Atkinson static const char *
docase(char * dst,size_t dlen,const char * src)1912f982db4aSGavin Atkinson docase(char *dst, size_t dlen, const char *src)
1913f982db4aSGavin Atkinson {
1914f982db4aSGavin Atkinson size_t i;
1915f982db4aSGavin Atkinson int dochange = 1;
1916f982db4aSGavin Atkinson
1917f982db4aSGavin Atkinson for (i = 0; src[i] != '\0' && i < dlen - 1; i++) {
1918f982db4aSGavin Atkinson dst[i] = src[i];
1919f982db4aSGavin Atkinson if (islower((unsigned char)dst[i]))
1920f982db4aSGavin Atkinson dochange = 0;
1921f982db4aSGavin Atkinson }
1922f982db4aSGavin Atkinson dst[i] = '\0';
1923f982db4aSGavin Atkinson
1924f982db4aSGavin Atkinson if (dochange) {
1925f982db4aSGavin Atkinson for (i = 0; dst[i] != '\0'; i++)
1926f982db4aSGavin Atkinson if (isupper((unsigned char)dst[i]))
1927f982db4aSGavin Atkinson dst[i] = tolower((unsigned char)dst[i]);
1928f982db4aSGavin Atkinson }
1929f982db4aSGavin Atkinson return dst;
1930f982db4aSGavin Atkinson }
1931f982db4aSGavin Atkinson
1932f982db4aSGavin Atkinson void
setcr(int argc,char * argv[])1933f982db4aSGavin Atkinson setcr(int argc, char *argv[])
1934f982db4aSGavin Atkinson {
1935f982db4aSGavin Atkinson
1936f982db4aSGavin Atkinson code = togglevar(argc, argv, &crflag, "Carriage Return stripping");
1937f982db4aSGavin Atkinson }
1938f982db4aSGavin Atkinson
1939f982db4aSGavin Atkinson void
setntrans(int argc,char * argv[])1940f982db4aSGavin Atkinson setntrans(int argc, char *argv[])
1941f982db4aSGavin Atkinson {
1942f982db4aSGavin Atkinson
1943f982db4aSGavin Atkinson if (argc == 0 || argc > 3) {
1944cc361f65SGavin Atkinson UPRINTF("usage: %s [inchars [outchars]]\n", argv[0]);
1945f982db4aSGavin Atkinson code = -1;
1946f982db4aSGavin Atkinson return;
1947f982db4aSGavin Atkinson }
1948f982db4aSGavin Atkinson if (argc == 1) {
1949f982db4aSGavin Atkinson ntflag = 0;
1950f982db4aSGavin Atkinson fputs("Ntrans off.\n", ttyout);
1951f982db4aSGavin Atkinson code = ntflag;
1952f982db4aSGavin Atkinson return;
1953f982db4aSGavin Atkinson }
1954f982db4aSGavin Atkinson ntflag++;
1955f982db4aSGavin Atkinson code = ntflag;
1956f982db4aSGavin Atkinson (void)strlcpy(ntin, argv[1], sizeof(ntin));
1957f982db4aSGavin Atkinson if (argc == 2) {
1958f982db4aSGavin Atkinson ntout[0] = '\0';
1959f982db4aSGavin Atkinson return;
1960f982db4aSGavin Atkinson }
1961f982db4aSGavin Atkinson (void)strlcpy(ntout, argv[2], sizeof(ntout));
1962f982db4aSGavin Atkinson }
1963f982db4aSGavin Atkinson
1964f982db4aSGavin Atkinson static const char *
dotrans(char * dst,size_t dlen,const char * src)1965f982db4aSGavin Atkinson dotrans(char *dst, size_t dlen, const char *src)
1966f982db4aSGavin Atkinson {
1967f982db4aSGavin Atkinson const char *cp1;
1968f982db4aSGavin Atkinson char *cp2 = dst;
1969f982db4aSGavin Atkinson size_t i, ostop;
1970f982db4aSGavin Atkinson
1971f982db4aSGavin Atkinson for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
1972f982db4aSGavin Atkinson continue;
1973f982db4aSGavin Atkinson for (cp1 = src; *cp1; cp1++) {
1974f982db4aSGavin Atkinson int found = 0;
1975f982db4aSGavin Atkinson for (i = 0; *(ntin + i) && i < 16; i++) {
1976f982db4aSGavin Atkinson if (*cp1 == *(ntin + i)) {
1977f982db4aSGavin Atkinson found++;
1978f982db4aSGavin Atkinson if (i < ostop) {
1979f982db4aSGavin Atkinson *cp2++ = *(ntout + i);
1980cc361f65SGavin Atkinson if (cp2 - dst >= (ptrdiff_t)(dlen - 1))
1981f982db4aSGavin Atkinson goto out;
1982f982db4aSGavin Atkinson }
1983f982db4aSGavin Atkinson break;
1984f982db4aSGavin Atkinson }
1985f982db4aSGavin Atkinson }
1986f982db4aSGavin Atkinson if (!found) {
1987f982db4aSGavin Atkinson *cp2++ = *cp1;
1988f982db4aSGavin Atkinson }
1989f982db4aSGavin Atkinson }
1990f982db4aSGavin Atkinson out:
1991f982db4aSGavin Atkinson *cp2 = '\0';
1992f982db4aSGavin Atkinson return dst;
1993f982db4aSGavin Atkinson }
1994f982db4aSGavin Atkinson
1995f982db4aSGavin Atkinson void
setnmap(int argc,char * argv[])1996f982db4aSGavin Atkinson setnmap(int argc, char *argv[])
1997f982db4aSGavin Atkinson {
1998f982db4aSGavin Atkinson char *cp;
1999f982db4aSGavin Atkinson
2000f982db4aSGavin Atkinson if (argc == 1) {
2001f982db4aSGavin Atkinson mapflag = 0;
2002f982db4aSGavin Atkinson fputs("Nmap off.\n", ttyout);
2003f982db4aSGavin Atkinson code = mapflag;
2004f982db4aSGavin Atkinson return;
2005f982db4aSGavin Atkinson }
2006f982db4aSGavin Atkinson if (argc == 0 ||
2007f982db4aSGavin Atkinson (argc < 3 && !another(&argc, &argv, "mapout")) || argc > 3) {
2008cc361f65SGavin Atkinson UPRINTF("usage: %s [mapin mapout]\n", argv[0]);
2009f982db4aSGavin Atkinson code = -1;
2010f982db4aSGavin Atkinson return;
2011f982db4aSGavin Atkinson }
2012f982db4aSGavin Atkinson mapflag = 1;
2013f982db4aSGavin Atkinson code = 1;
2014f982db4aSGavin Atkinson cp = strchr(altarg, ' ');
2015f982db4aSGavin Atkinson if (proxy) {
2016f982db4aSGavin Atkinson while(*++cp == ' ')
2017f982db4aSGavin Atkinson continue;
2018f982db4aSGavin Atkinson altarg = cp;
2019f982db4aSGavin Atkinson cp = strchr(altarg, ' ');
2020f982db4aSGavin Atkinson }
2021f982db4aSGavin Atkinson *cp = '\0';
2022f982db4aSGavin Atkinson (void)strlcpy(mapin, altarg, MAXPATHLEN);
2023f982db4aSGavin Atkinson while (*++cp == ' ')
2024f982db4aSGavin Atkinson continue;
2025f982db4aSGavin Atkinson (void)strlcpy(mapout, cp, MAXPATHLEN);
2026f982db4aSGavin Atkinson }
2027f982db4aSGavin Atkinson
2028f982db4aSGavin Atkinson static const char *
domap(char * dst,size_t dlen,const char * src)2029f982db4aSGavin Atkinson domap(char *dst, size_t dlen, const char *src)
2030f982db4aSGavin Atkinson {
2031f982db4aSGavin Atkinson const char *cp1 = src;
2032f982db4aSGavin Atkinson char *cp2 = mapin;
2033f982db4aSGavin Atkinson const char *tp[9], *te[9];
2034f982db4aSGavin Atkinson int i, toks[9], toknum = 0, match = 1;
2035f982db4aSGavin Atkinson
2036f982db4aSGavin Atkinson for (i=0; i < 9; ++i) {
2037f982db4aSGavin Atkinson toks[i] = 0;
2038f982db4aSGavin Atkinson }
2039f982db4aSGavin Atkinson while (match && *cp1 && *cp2) {
2040f982db4aSGavin Atkinson switch (*cp2) {
2041f982db4aSGavin Atkinson case '\\':
2042f982db4aSGavin Atkinson if (*++cp2 != *cp1) {
2043f982db4aSGavin Atkinson match = 0;
2044f982db4aSGavin Atkinson }
2045f982db4aSGavin Atkinson break;
2046f982db4aSGavin Atkinson case '$':
2047f982db4aSGavin Atkinson if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
2048f982db4aSGavin Atkinson if (*cp1 != *(++cp2+1)) {
2049f982db4aSGavin Atkinson toks[toknum = *cp2 - '1']++;
2050f982db4aSGavin Atkinson tp[toknum] = cp1;
2051f982db4aSGavin Atkinson while (*++cp1 && *(cp2+1)
2052f982db4aSGavin Atkinson != *cp1);
2053f982db4aSGavin Atkinson te[toknum] = cp1;
2054f982db4aSGavin Atkinson }
2055f982db4aSGavin Atkinson cp2++;
2056f982db4aSGavin Atkinson break;
2057f982db4aSGavin Atkinson }
2058f982db4aSGavin Atkinson /* FALLTHROUGH */
2059f982db4aSGavin Atkinson default:
2060f982db4aSGavin Atkinson if (*cp2 != *cp1) {
2061f982db4aSGavin Atkinson match = 0;
2062f982db4aSGavin Atkinson }
2063f982db4aSGavin Atkinson break;
2064f982db4aSGavin Atkinson }
2065f982db4aSGavin Atkinson if (match && *cp1) {
2066f982db4aSGavin Atkinson cp1++;
2067f982db4aSGavin Atkinson }
2068f982db4aSGavin Atkinson if (match && *cp2) {
2069f982db4aSGavin Atkinson cp2++;
2070f982db4aSGavin Atkinson }
2071f982db4aSGavin Atkinson }
2072f982db4aSGavin Atkinson if (!match && *cp1) /* last token mismatch */
2073f982db4aSGavin Atkinson {
2074f982db4aSGavin Atkinson toks[toknum] = 0;
2075f982db4aSGavin Atkinson }
2076f982db4aSGavin Atkinson cp2 = dst;
2077f982db4aSGavin Atkinson *cp2 = '\0';
2078f982db4aSGavin Atkinson cp1 = mapout;
2079f982db4aSGavin Atkinson while (*cp1) {
2080f982db4aSGavin Atkinson match = 0;
2081f982db4aSGavin Atkinson switch (*cp1) {
2082f982db4aSGavin Atkinson case '\\':
2083f982db4aSGavin Atkinson if (*(cp1 + 1)) {
2084f982db4aSGavin Atkinson *cp2++ = *++cp1;
2085f982db4aSGavin Atkinson }
2086f982db4aSGavin Atkinson break;
2087f982db4aSGavin Atkinson case '[':
2088f982db4aSGavin Atkinson LOOP:
2089f982db4aSGavin Atkinson if (*++cp1 == '$' &&
2090f982db4aSGavin Atkinson isdigit((unsigned char)*(cp1+1))) {
2091f982db4aSGavin Atkinson if (*++cp1 == '0') {
2092f982db4aSGavin Atkinson const char *cp3 = src;
2093f982db4aSGavin Atkinson
2094f982db4aSGavin Atkinson while (*cp3) {
2095f982db4aSGavin Atkinson *cp2++ = *cp3++;
2096f982db4aSGavin Atkinson }
2097f982db4aSGavin Atkinson match = 1;
2098f982db4aSGavin Atkinson }
2099f982db4aSGavin Atkinson else if (toks[toknum = *cp1 - '1']) {
2100f982db4aSGavin Atkinson const char *cp3 = tp[toknum];
2101f982db4aSGavin Atkinson
2102f982db4aSGavin Atkinson while (cp3 != te[toknum]) {
2103f982db4aSGavin Atkinson *cp2++ = *cp3++;
2104f982db4aSGavin Atkinson }
2105f982db4aSGavin Atkinson match = 1;
2106f982db4aSGavin Atkinson }
2107f982db4aSGavin Atkinson }
2108f982db4aSGavin Atkinson else {
2109f982db4aSGavin Atkinson while (*cp1 && *cp1 != ',' &&
2110f982db4aSGavin Atkinson *cp1 != ']') {
2111f982db4aSGavin Atkinson if (*cp1 == '\\') {
2112f982db4aSGavin Atkinson cp1++;
2113f982db4aSGavin Atkinson }
2114f982db4aSGavin Atkinson else if (*cp1 == '$' &&
2115f982db4aSGavin Atkinson isdigit((unsigned char)*(cp1+1))) {
2116f982db4aSGavin Atkinson if (*++cp1 == '0') {
2117f982db4aSGavin Atkinson const char *cp3 = src;
2118f982db4aSGavin Atkinson
2119f982db4aSGavin Atkinson while (*cp3) {
2120f982db4aSGavin Atkinson *cp2++ = *cp3++;
2121f982db4aSGavin Atkinson }
2122f982db4aSGavin Atkinson }
2123f982db4aSGavin Atkinson else if (toks[toknum =
2124f982db4aSGavin Atkinson *cp1 - '1']) {
2125f982db4aSGavin Atkinson const char *cp3=tp[toknum];
2126f982db4aSGavin Atkinson
2127f982db4aSGavin Atkinson while (cp3 !=
2128f982db4aSGavin Atkinson te[toknum]) {
2129f982db4aSGavin Atkinson *cp2++ = *cp3++;
2130f982db4aSGavin Atkinson }
2131f982db4aSGavin Atkinson }
2132f982db4aSGavin Atkinson }
2133f982db4aSGavin Atkinson else if (*cp1) {
2134f982db4aSGavin Atkinson *cp2++ = *cp1++;
2135f982db4aSGavin Atkinson }
2136f982db4aSGavin Atkinson }
2137f982db4aSGavin Atkinson if (!*cp1) {
2138f982db4aSGavin Atkinson fputs(
2139f982db4aSGavin Atkinson "nmap: unbalanced brackets.\n",
2140f982db4aSGavin Atkinson ttyout);
2141f982db4aSGavin Atkinson return (src);
2142f982db4aSGavin Atkinson }
2143f982db4aSGavin Atkinson match = 1;
2144f982db4aSGavin Atkinson cp1--;
2145f982db4aSGavin Atkinson }
2146f982db4aSGavin Atkinson if (match) {
2147f982db4aSGavin Atkinson while (*++cp1 && *cp1 != ']') {
2148f982db4aSGavin Atkinson if (*cp1 == '\\' && *(cp1 + 1)) {
2149f982db4aSGavin Atkinson cp1++;
2150f982db4aSGavin Atkinson }
2151f982db4aSGavin Atkinson }
2152f982db4aSGavin Atkinson if (!*cp1) {
2153f982db4aSGavin Atkinson fputs(
2154f982db4aSGavin Atkinson "nmap: unbalanced brackets.\n",
2155f982db4aSGavin Atkinson ttyout);
2156f982db4aSGavin Atkinson return (src);
2157f982db4aSGavin Atkinson }
2158f982db4aSGavin Atkinson break;
2159f982db4aSGavin Atkinson }
2160f982db4aSGavin Atkinson switch (*++cp1) {
2161f982db4aSGavin Atkinson case ',':
2162f982db4aSGavin Atkinson goto LOOP;
2163f982db4aSGavin Atkinson case ']':
2164f982db4aSGavin Atkinson break;
2165f982db4aSGavin Atkinson default:
2166f982db4aSGavin Atkinson cp1--;
2167f982db4aSGavin Atkinson goto LOOP;
2168f982db4aSGavin Atkinson }
2169f982db4aSGavin Atkinson break;
2170f982db4aSGavin Atkinson case '$':
2171f982db4aSGavin Atkinson if (isdigit((unsigned char)*(cp1 + 1))) {
2172f982db4aSGavin Atkinson if (*++cp1 == '0') {
2173f982db4aSGavin Atkinson const char *cp3 = src;
2174f982db4aSGavin Atkinson
2175f982db4aSGavin Atkinson while (*cp3) {
2176f982db4aSGavin Atkinson *cp2++ = *cp3++;
2177f982db4aSGavin Atkinson }
2178f982db4aSGavin Atkinson }
2179f982db4aSGavin Atkinson else if (toks[toknum = *cp1 - '1']) {
2180f982db4aSGavin Atkinson const char *cp3 = tp[toknum];
2181f982db4aSGavin Atkinson
2182f982db4aSGavin Atkinson while (cp3 != te[toknum]) {
2183f982db4aSGavin Atkinson *cp2++ = *cp3++;
2184f982db4aSGavin Atkinson }
2185f982db4aSGavin Atkinson }
2186f982db4aSGavin Atkinson break;
2187f982db4aSGavin Atkinson }
2188f982db4aSGavin Atkinson /* intentional drop through */
2189f982db4aSGavin Atkinson default:
2190f982db4aSGavin Atkinson *cp2++ = *cp1;
2191f982db4aSGavin Atkinson break;
2192f982db4aSGavin Atkinson }
2193f982db4aSGavin Atkinson cp1++;
2194f982db4aSGavin Atkinson }
2195f982db4aSGavin Atkinson *cp2 = '\0';
2196f982db4aSGavin Atkinson return *dst ? dst : src;
2197f982db4aSGavin Atkinson }
2198f982db4aSGavin Atkinson
2199f982db4aSGavin Atkinson void
setpassive(int argc,char * argv[])2200f982db4aSGavin Atkinson setpassive(int argc, char *argv[])
2201f982db4aSGavin Atkinson {
2202f982db4aSGavin Atkinson
2203f982db4aSGavin Atkinson if (argc == 1) {
2204f982db4aSGavin Atkinson passivemode = !passivemode;
2205f982db4aSGavin Atkinson activefallback = passivemode;
2206f982db4aSGavin Atkinson } else if (argc != 2) {
2207f982db4aSGavin Atkinson passiveusage:
2208cc361f65SGavin Atkinson UPRINTF("usage: %s [ on | off | auto ]\n", argv[0]);
2209f982db4aSGavin Atkinson code = -1;
2210f982db4aSGavin Atkinson return;
2211f982db4aSGavin Atkinson } else if (strcasecmp(argv[1], "on") == 0) {
2212f982db4aSGavin Atkinson passivemode = 1;
2213f982db4aSGavin Atkinson activefallback = 0;
2214f982db4aSGavin Atkinson } else if (strcasecmp(argv[1], "off") == 0) {
2215f982db4aSGavin Atkinson passivemode = 0;
2216f982db4aSGavin Atkinson activefallback = 0;
2217f982db4aSGavin Atkinson } else if (strcasecmp(argv[1], "auto") == 0) {
2218f982db4aSGavin Atkinson passivemode = 1;
2219f982db4aSGavin Atkinson activefallback = 1;
2220f982db4aSGavin Atkinson } else
2221f982db4aSGavin Atkinson goto passiveusage;
2222f982db4aSGavin Atkinson fprintf(ttyout, "Passive mode: %s; fallback to active mode: %s.\n",
2223f982db4aSGavin Atkinson onoff(passivemode), onoff(activefallback));
2224f982db4aSGavin Atkinson code = passivemode;
2225f982db4aSGavin Atkinson }
2226f982db4aSGavin Atkinson
2227cc361f65SGavin Atkinson
2228f982db4aSGavin Atkinson void
setepsv4(int argc,char * argv[])2229f982db4aSGavin Atkinson setepsv4(int argc, char *argv[])
2230f982db4aSGavin Atkinson {
2231f982db4aSGavin Atkinson code = togglevar(argc, argv, &epsv4,
2232f982db4aSGavin Atkinson verbose ? "EPSV/EPRT on IPv4" : NULL);
2233f982db4aSGavin Atkinson epsv4bad = 0;
2234f982db4aSGavin Atkinson }
2235f982db4aSGavin Atkinson
2236f982db4aSGavin Atkinson void
setepsv6(int argc,char * argv[])2237cc361f65SGavin Atkinson setepsv6(int argc, char *argv[])
2238cc361f65SGavin Atkinson {
2239cc361f65SGavin Atkinson code = togglevar(argc, argv, &epsv6,
2240cc361f65SGavin Atkinson verbose ? "EPSV/EPRT on IPv6" : NULL);
2241cc361f65SGavin Atkinson epsv6bad = 0;
2242cc361f65SGavin Atkinson }
2243cc361f65SGavin Atkinson
2244cc361f65SGavin Atkinson void
setepsv(int argc,char * argv[])2245cc361f65SGavin Atkinson setepsv(int argc, char*argv[])
2246cc361f65SGavin Atkinson {
2247cc361f65SGavin Atkinson setepsv4(argc,argv);
2248cc361f65SGavin Atkinson setepsv6(argc,argv);
2249cc361f65SGavin Atkinson }
2250cc361f65SGavin Atkinson
2251cc361f65SGavin Atkinson void
setsunique(int argc,char * argv[])2252f982db4aSGavin Atkinson setsunique(int argc, char *argv[])
2253f982db4aSGavin Atkinson {
2254f982db4aSGavin Atkinson
2255f982db4aSGavin Atkinson code = togglevar(argc, argv, &sunique, "Store unique");
2256f982db4aSGavin Atkinson }
2257f982db4aSGavin Atkinson
2258f982db4aSGavin Atkinson void
setrunique(int argc,char * argv[])2259f982db4aSGavin Atkinson setrunique(int argc, char *argv[])
2260f982db4aSGavin Atkinson {
2261f982db4aSGavin Atkinson
2262f982db4aSGavin Atkinson code = togglevar(argc, argv, &runique, "Receive unique");
2263f982db4aSGavin Atkinson }
2264f982db4aSGavin Atkinson
2265f982db4aSGavin Atkinson int
parserate(int argc,char * argv[],int cmdlineopt)2266f982db4aSGavin Atkinson parserate(int argc, char *argv[], int cmdlineopt)
2267f982db4aSGavin Atkinson {
2268f982db4aSGavin Atkinson int dir, max, incr, showonly;
2269f982db4aSGavin Atkinson sigfunc oldusr1, oldusr2;
2270f982db4aSGavin Atkinson
2271f982db4aSGavin Atkinson if (argc > 4 || (argc < (cmdlineopt ? 3 : 2))) {
2272f982db4aSGavin Atkinson usage:
2273f982db4aSGavin Atkinson if (cmdlineopt)
2274cc361f65SGavin Atkinson UPRINTF(
2275f982db4aSGavin Atkinson "usage: %s (all|get|put),maximum-bytes[,increment-bytes]]\n",
2276f982db4aSGavin Atkinson argv[0]);
2277f982db4aSGavin Atkinson else
2278cc361f65SGavin Atkinson UPRINTF(
2279f982db4aSGavin Atkinson "usage: %s (all|get|put) [maximum-bytes [increment-bytes]]\n",
2280f982db4aSGavin Atkinson argv[0]);
2281f982db4aSGavin Atkinson return -1;
2282f982db4aSGavin Atkinson }
2283f982db4aSGavin Atkinson dir = max = incr = showonly = 0;
2284f982db4aSGavin Atkinson #define RATE_GET 1
2285f982db4aSGavin Atkinson #define RATE_PUT 2
2286f982db4aSGavin Atkinson #define RATE_ALL (RATE_GET | RATE_PUT)
2287f982db4aSGavin Atkinson
2288f982db4aSGavin Atkinson if (strcasecmp(argv[1], "all") == 0)
2289f982db4aSGavin Atkinson dir = RATE_ALL;
2290f982db4aSGavin Atkinson else if (strcasecmp(argv[1], "get") == 0)
2291f982db4aSGavin Atkinson dir = RATE_GET;
2292f982db4aSGavin Atkinson else if (strcasecmp(argv[1], "put") == 0)
2293f982db4aSGavin Atkinson dir = RATE_PUT;
2294f982db4aSGavin Atkinson else
2295f982db4aSGavin Atkinson goto usage;
2296f982db4aSGavin Atkinson
2297f982db4aSGavin Atkinson if (argc >= 3) {
2298f982db4aSGavin Atkinson if ((max = strsuftoi(argv[2])) < 0)
2299f982db4aSGavin Atkinson goto usage;
2300f982db4aSGavin Atkinson } else
2301f982db4aSGavin Atkinson showonly = 1;
2302f982db4aSGavin Atkinson
2303f982db4aSGavin Atkinson if (argc == 4) {
2304f982db4aSGavin Atkinson if ((incr = strsuftoi(argv[3])) <= 0)
2305f982db4aSGavin Atkinson goto usage;
2306f982db4aSGavin Atkinson } else
2307f982db4aSGavin Atkinson incr = DEFAULTINCR;
2308f982db4aSGavin Atkinson
2309f982db4aSGavin Atkinson oldusr1 = xsignal(SIGUSR1, SIG_IGN);
2310f982db4aSGavin Atkinson oldusr2 = xsignal(SIGUSR2, SIG_IGN);
2311f982db4aSGavin Atkinson if (dir & RATE_GET) {
2312f982db4aSGavin Atkinson if (!showonly) {
2313f982db4aSGavin Atkinson rate_get = max;
2314f982db4aSGavin Atkinson rate_get_incr = incr;
2315f982db4aSGavin Atkinson }
2316f982db4aSGavin Atkinson if (!cmdlineopt || verbose)
2317f982db4aSGavin Atkinson fprintf(ttyout,
2318f982db4aSGavin Atkinson "Get transfer rate throttle: %s; maximum: %d; increment %d.\n",
2319f982db4aSGavin Atkinson onoff(rate_get), rate_get, rate_get_incr);
2320f982db4aSGavin Atkinson }
2321f982db4aSGavin Atkinson if (dir & RATE_PUT) {
2322f982db4aSGavin Atkinson if (!showonly) {
2323f982db4aSGavin Atkinson rate_put = max;
2324f982db4aSGavin Atkinson rate_put_incr = incr;
2325f982db4aSGavin Atkinson }
2326f982db4aSGavin Atkinson if (!cmdlineopt || verbose)
2327f982db4aSGavin Atkinson fprintf(ttyout,
2328f982db4aSGavin Atkinson "Put transfer rate throttle: %s; maximum: %d; increment %d.\n",
2329f982db4aSGavin Atkinson onoff(rate_put), rate_put, rate_put_incr);
2330f982db4aSGavin Atkinson }
2331f982db4aSGavin Atkinson (void)xsignal(SIGUSR1, oldusr1);
2332f982db4aSGavin Atkinson (void)xsignal(SIGUSR2, oldusr2);
2333f982db4aSGavin Atkinson return 0;
2334f982db4aSGavin Atkinson }
2335f982db4aSGavin Atkinson
2336f982db4aSGavin Atkinson void
setrate(int argc,char * argv[])2337f982db4aSGavin Atkinson setrate(int argc, char *argv[])
2338f982db4aSGavin Atkinson {
2339f982db4aSGavin Atkinson
2340f982db4aSGavin Atkinson code = parserate(argc, argv, 0);
2341f982db4aSGavin Atkinson }
2342f982db4aSGavin Atkinson
2343f982db4aSGavin Atkinson /* change directory to parent directory */
2344f982db4aSGavin Atkinson void
cdup(int argc,char * argv[])2345f982db4aSGavin Atkinson cdup(int argc, char *argv[])
2346f982db4aSGavin Atkinson {
2347f982db4aSGavin Atkinson int r;
2348f982db4aSGavin Atkinson
2349f982db4aSGavin Atkinson if (argc == 0) {
2350cc361f65SGavin Atkinson UPRINTF("usage: %s\n", argv[0]);
2351f982db4aSGavin Atkinson code = -1;
2352f982db4aSGavin Atkinson return;
2353f982db4aSGavin Atkinson }
2354f982db4aSGavin Atkinson r = command("CDUP");
2355f982db4aSGavin Atkinson if (r == ERROR && code == 500) {
2356f982db4aSGavin Atkinson if (verbose)
2357f982db4aSGavin Atkinson fputs("CDUP command not recognized, trying XCUP.\n",
2358f982db4aSGavin Atkinson ttyout);
2359f982db4aSGavin Atkinson r = command("XCUP");
2360f982db4aSGavin Atkinson }
2361f982db4aSGavin Atkinson if (r == COMPLETE) {
2362f982db4aSGavin Atkinson dirchange = 1;
2363f982db4aSGavin Atkinson updateremotecwd();
2364f982db4aSGavin Atkinson }
2365f982db4aSGavin Atkinson }
2366f982db4aSGavin Atkinson
2367f982db4aSGavin Atkinson /*
2368f982db4aSGavin Atkinson * Restart transfer at specific point
2369f982db4aSGavin Atkinson */
2370f982db4aSGavin Atkinson void
restart(int argc,char * argv[])2371f982db4aSGavin Atkinson restart(int argc, char *argv[])
2372f982db4aSGavin Atkinson {
2373f982db4aSGavin Atkinson
2374f982db4aSGavin Atkinson if (argc == 0 || argc > 2) {
2375cc361f65SGavin Atkinson UPRINTF("usage: %s [restart-point]\n", argv[0]);
2376f982db4aSGavin Atkinson code = -1;
2377f982db4aSGavin Atkinson return;
2378f982db4aSGavin Atkinson }
2379f982db4aSGavin Atkinson if (! features[FEAT_REST_STREAM]) {
2380f982db4aSGavin Atkinson fprintf(ttyout,
2381f982db4aSGavin Atkinson "Restart is not supported by the remote server.\n");
2382f982db4aSGavin Atkinson return;
2383f982db4aSGavin Atkinson }
2384f982db4aSGavin Atkinson if (argc == 2) {
2385f982db4aSGavin Atkinson off_t rp;
2386f982db4aSGavin Atkinson char *ep;
2387f982db4aSGavin Atkinson
2388f982db4aSGavin Atkinson rp = STRTOLL(argv[1], &ep, 10);
2389f982db4aSGavin Atkinson if (rp < 0 || *ep != '\0')
2390f982db4aSGavin Atkinson fprintf(ttyout, "restart: Invalid offset `%s'\n",
2391f982db4aSGavin Atkinson argv[1]);
2392f982db4aSGavin Atkinson else
2393f982db4aSGavin Atkinson restart_point = rp;
2394f982db4aSGavin Atkinson }
2395f982db4aSGavin Atkinson if (restart_point == 0)
2396f982db4aSGavin Atkinson fputs("No restart point defined.\n", ttyout);
2397f982db4aSGavin Atkinson else
2398f982db4aSGavin Atkinson fprintf(ttyout,
2399f982db4aSGavin Atkinson "Restarting at " LLF " for next get, put or append\n",
2400f982db4aSGavin Atkinson (LLT)restart_point);
2401f982db4aSGavin Atkinson }
2402f982db4aSGavin Atkinson
2403f982db4aSGavin Atkinson /*
2404f982db4aSGavin Atkinson * Show remote system type
2405f982db4aSGavin Atkinson */
2406f982db4aSGavin Atkinson void
syst(int argc,char * argv[])2407f982db4aSGavin Atkinson syst(int argc, char *argv[])
2408f982db4aSGavin Atkinson {
2409f982db4aSGavin Atkinson int oldverbose = verbose;
2410f982db4aSGavin Atkinson
2411f982db4aSGavin Atkinson if (argc == 0) {
2412cc361f65SGavin Atkinson UPRINTF("usage: %s\n", argv[0]);
2413f982db4aSGavin Atkinson code = -1;
2414f982db4aSGavin Atkinson return;
2415f982db4aSGavin Atkinson }
2416f982db4aSGavin Atkinson verbose = 1; /* If we aren't verbose, this doesn't do anything! */
2417f982db4aSGavin Atkinson (void)command("SYST");
2418f982db4aSGavin Atkinson verbose = oldverbose;
2419f982db4aSGavin Atkinson }
2420f982db4aSGavin Atkinson
2421f982db4aSGavin Atkinson void
macdef(int argc,char * argv[])2422f982db4aSGavin Atkinson macdef(int argc, char *argv[])
2423f982db4aSGavin Atkinson {
2424f982db4aSGavin Atkinson char *tmp;
2425f982db4aSGavin Atkinson int c;
2426f982db4aSGavin Atkinson
2427f982db4aSGavin Atkinson if (argc == 0)
2428f982db4aSGavin Atkinson goto usage;
2429f982db4aSGavin Atkinson if (macnum == 16) {
2430f982db4aSGavin Atkinson fputs("Limit of 16 macros have already been defined.\n",
2431f982db4aSGavin Atkinson ttyout);
2432f982db4aSGavin Atkinson code = -1;
2433f982db4aSGavin Atkinson return;
2434f982db4aSGavin Atkinson }
2435f982db4aSGavin Atkinson if ((argc < 2 && !another(&argc, &argv, "macro name")) || argc > 2) {
2436f982db4aSGavin Atkinson usage:
2437cc361f65SGavin Atkinson UPRINTF("usage: %s macro_name\n", argv[0]);
2438f982db4aSGavin Atkinson code = -1;
2439f982db4aSGavin Atkinson return;
2440f982db4aSGavin Atkinson }
2441f982db4aSGavin Atkinson if (interactive)
2442f982db4aSGavin Atkinson fputs(
2443f982db4aSGavin Atkinson "Enter macro line by line, terminating it with a null line.\n",
2444f982db4aSGavin Atkinson ttyout);
2445f982db4aSGavin Atkinson (void)strlcpy(macros[macnum].mac_name, argv[1],
2446f982db4aSGavin Atkinson sizeof(macros[macnum].mac_name));
2447f982db4aSGavin Atkinson if (macnum == 0)
2448f982db4aSGavin Atkinson macros[macnum].mac_start = macbuf;
2449f982db4aSGavin Atkinson else
2450f982db4aSGavin Atkinson macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
2451f982db4aSGavin Atkinson tmp = macros[macnum].mac_start;
2452f982db4aSGavin Atkinson while (tmp != macbuf+4096) {
2453f982db4aSGavin Atkinson if ((c = getchar()) == EOF) {
2454f982db4aSGavin Atkinson fputs("macdef: end of file encountered.\n", ttyout);
2455f982db4aSGavin Atkinson code = -1;
2456f982db4aSGavin Atkinson return;
2457f982db4aSGavin Atkinson }
2458f982db4aSGavin Atkinson if ((*tmp = c) == '\n') {
2459f982db4aSGavin Atkinson if (tmp == macros[macnum].mac_start) {
2460f982db4aSGavin Atkinson macros[macnum++].mac_end = tmp;
2461f982db4aSGavin Atkinson code = 0;
2462f982db4aSGavin Atkinson return;
2463f982db4aSGavin Atkinson }
2464f982db4aSGavin Atkinson if (*(tmp-1) == '\0') {
2465f982db4aSGavin Atkinson macros[macnum++].mac_end = tmp - 1;
2466f982db4aSGavin Atkinson code = 0;
2467f982db4aSGavin Atkinson return;
2468f982db4aSGavin Atkinson }
2469f982db4aSGavin Atkinson *tmp = '\0';
2470f982db4aSGavin Atkinson }
2471f982db4aSGavin Atkinson tmp++;
2472f982db4aSGavin Atkinson }
2473f982db4aSGavin Atkinson while (1) {
2474f982db4aSGavin Atkinson while ((c = getchar()) != '\n' && c != EOF)
2475f982db4aSGavin Atkinson /* LOOP */;
2476f982db4aSGavin Atkinson if (c == EOF || getchar() == '\n') {
2477f982db4aSGavin Atkinson fputs("Macro not defined - 4K buffer exceeded.\n",
2478f982db4aSGavin Atkinson ttyout);
2479f982db4aSGavin Atkinson code = -1;
2480f982db4aSGavin Atkinson return;
2481f982db4aSGavin Atkinson }
2482f982db4aSGavin Atkinson }
2483f982db4aSGavin Atkinson }
2484f982db4aSGavin Atkinson
2485f982db4aSGavin Atkinson /*
2486f982db4aSGavin Atkinson * Get size of file on remote machine
2487f982db4aSGavin Atkinson */
2488f982db4aSGavin Atkinson void
sizecmd(int argc,char * argv[])2489f982db4aSGavin Atkinson sizecmd(int argc, char *argv[])
2490f982db4aSGavin Atkinson {
2491f982db4aSGavin Atkinson off_t size;
2492f982db4aSGavin Atkinson
2493f982db4aSGavin Atkinson if (argc == 0 || argc > 2 ||
2494f982db4aSGavin Atkinson (argc == 1 && !another(&argc, &argv, "remote-file"))) {
2495cc361f65SGavin Atkinson UPRINTF("usage: %s remote-file\n", argv[0]);
2496f982db4aSGavin Atkinson code = -1;
2497f982db4aSGavin Atkinson return;
2498f982db4aSGavin Atkinson }
2499f982db4aSGavin Atkinson size = remotesize(argv[1], 1);
2500f982db4aSGavin Atkinson if (size != -1)
2501f982db4aSGavin Atkinson fprintf(ttyout,
2502f982db4aSGavin Atkinson "%s\t" LLF "\n", argv[1], (LLT)size);
2503f982db4aSGavin Atkinson code = (size > 0);
2504f982db4aSGavin Atkinson }
2505f982db4aSGavin Atkinson
2506f982db4aSGavin Atkinson /*
2507f982db4aSGavin Atkinson * Get last modification time of file on remote machine
2508f982db4aSGavin Atkinson */
2509f982db4aSGavin Atkinson void
modtime(int argc,char * argv[])2510f982db4aSGavin Atkinson modtime(int argc, char *argv[])
2511f982db4aSGavin Atkinson {
2512f982db4aSGavin Atkinson time_t mtime;
2513f982db4aSGavin Atkinson
2514f982db4aSGavin Atkinson if (argc == 0 || argc > 2 ||
2515f982db4aSGavin Atkinson (argc == 1 && !another(&argc, &argv, "remote-file"))) {
2516cc361f65SGavin Atkinson UPRINTF("usage: %s remote-file\n", argv[0]);
2517f982db4aSGavin Atkinson code = -1;
2518f982db4aSGavin Atkinson return;
2519f982db4aSGavin Atkinson }
2520f982db4aSGavin Atkinson mtime = remotemodtime(argv[1], 1);
2521f982db4aSGavin Atkinson if (mtime != -1)
2522cc361f65SGavin Atkinson fprintf(ttyout, "%s\t%s", argv[1],
2523cc361f65SGavin Atkinson rfc2822time(localtime(&mtime)));
2524f982db4aSGavin Atkinson code = (mtime > 0);
2525f982db4aSGavin Atkinson }
2526f982db4aSGavin Atkinson
2527f982db4aSGavin Atkinson /*
2528f982db4aSGavin Atkinson * Show status on remote machine
2529f982db4aSGavin Atkinson */
2530f982db4aSGavin Atkinson void
rmtstatus(int argc,char * argv[])2531f982db4aSGavin Atkinson rmtstatus(int argc, char *argv[])
2532f982db4aSGavin Atkinson {
2533f982db4aSGavin Atkinson
2534f982db4aSGavin Atkinson if (argc == 0) {
2535cc361f65SGavin Atkinson UPRINTF("usage: %s [remote-file]\n", argv[0]);
2536f982db4aSGavin Atkinson code = -1;
2537f982db4aSGavin Atkinson return;
2538f982db4aSGavin Atkinson }
2539f982db4aSGavin Atkinson COMMAND_1ARG(argc, argv, "STAT");
2540f982db4aSGavin Atkinson }
2541f982db4aSGavin Atkinson
2542f982db4aSGavin Atkinson /*
2543f982db4aSGavin Atkinson * Get file if modtime is more recent than current file
2544f982db4aSGavin Atkinson */
2545f982db4aSGavin Atkinson void
newer(int argc,char * argv[])2546f982db4aSGavin Atkinson newer(int argc, char *argv[])
2547f982db4aSGavin Atkinson {
2548f982db4aSGavin Atkinson
2549f982db4aSGavin Atkinson if (getit(argc, argv, -1, "w"))
2550f982db4aSGavin Atkinson fprintf(ttyout,
2551f982db4aSGavin Atkinson "Local file \"%s\" is newer than remote file \"%s\".\n",
2552f982db4aSGavin Atkinson argv[2], argv[1]);
2553f982db4aSGavin Atkinson }
2554f982db4aSGavin Atkinson
2555f982db4aSGavin Atkinson /*
2556f982db4aSGavin Atkinson * Display one local file through $PAGER.
2557f982db4aSGavin Atkinson */
2558f982db4aSGavin Atkinson void
lpage(int argc,char * argv[])2559f982db4aSGavin Atkinson lpage(int argc, char *argv[])
2560f982db4aSGavin Atkinson {
2561cc361f65SGavin Atkinson size_t len;
2562cc361f65SGavin Atkinson const char *p;
2563cc361f65SGavin Atkinson char *pager, *locfile;
2564f982db4aSGavin Atkinson
2565f982db4aSGavin Atkinson if (argc == 0 || argc > 2 ||
2566f982db4aSGavin Atkinson (argc == 1 && !another(&argc, &argv, "local-file"))) {
2567cc361f65SGavin Atkinson UPRINTF("usage: %s local-file\n", argv[0]);
2568f982db4aSGavin Atkinson code = -1;
2569f982db4aSGavin Atkinson return;
2570f982db4aSGavin Atkinson }
2571f982db4aSGavin Atkinson if ((locfile = globulize(argv[1])) == NULL) {
2572f982db4aSGavin Atkinson code = -1;
2573f982db4aSGavin Atkinson return;
2574f982db4aSGavin Atkinson }
2575f982db4aSGavin Atkinson p = getoptionvalue("pager");
2576f982db4aSGavin Atkinson if (EMPTYSTRING(p))
2577f982db4aSGavin Atkinson p = DEFAULTPAGER;
2578f982db4aSGavin Atkinson len = strlen(p) + strlen(locfile) + 2;
2579cc361f65SGavin Atkinson pager = ftp_malloc(len);
2580f982db4aSGavin Atkinson (void)strlcpy(pager, p, len);
2581f982db4aSGavin Atkinson (void)strlcat(pager, " ", len);
2582f982db4aSGavin Atkinson (void)strlcat(pager, locfile, len);
2583f982db4aSGavin Atkinson system(pager);
2584f982db4aSGavin Atkinson code = 0;
2585f982db4aSGavin Atkinson (void)free(pager);
2586f982db4aSGavin Atkinson (void)free(locfile);
2587f982db4aSGavin Atkinson }
2588f982db4aSGavin Atkinson
2589f982db4aSGavin Atkinson /*
2590f982db4aSGavin Atkinson * Display one remote file through $PAGER.
2591f982db4aSGavin Atkinson */
2592f982db4aSGavin Atkinson void
page(int argc,char * argv[])2593f982db4aSGavin Atkinson page(int argc, char *argv[])
2594f982db4aSGavin Atkinson {
2595cc361f65SGavin Atkinson int ohash, orestart_point, overbose;
2596cc361f65SGavin Atkinson size_t len;
2597cc361f65SGavin Atkinson const char *p;
2598cc361f65SGavin Atkinson char *pager;
2599f982db4aSGavin Atkinson
2600f982db4aSGavin Atkinson if (argc == 0 || argc > 2 ||
2601f982db4aSGavin Atkinson (argc == 1 && !another(&argc, &argv, "remote-file"))) {
2602cc361f65SGavin Atkinson UPRINTF("usage: %s remote-file\n", argv[0]);
2603f982db4aSGavin Atkinson code = -1;
2604f982db4aSGavin Atkinson return;
2605f982db4aSGavin Atkinson }
2606f982db4aSGavin Atkinson p = getoptionvalue("pager");
2607f982db4aSGavin Atkinson if (EMPTYSTRING(p))
2608f982db4aSGavin Atkinson p = DEFAULTPAGER;
2609f982db4aSGavin Atkinson len = strlen(p) + 2;
2610cc361f65SGavin Atkinson pager = ftp_malloc(len);
2611f982db4aSGavin Atkinson pager[0] = '|';
2612f982db4aSGavin Atkinson (void)strlcpy(pager + 1, p, len - 1);
2613f982db4aSGavin Atkinson
2614f982db4aSGavin Atkinson ohash = hash;
2615f982db4aSGavin Atkinson orestart_point = restart_point;
2616f982db4aSGavin Atkinson overbose = verbose;
2617f982db4aSGavin Atkinson hash = restart_point = verbose = 0;
2618f982db4aSGavin Atkinson recvrequest("RETR", pager, argv[1], "r+", 1, 0);
2619f982db4aSGavin Atkinson hash = ohash;
2620f982db4aSGavin Atkinson restart_point = orestart_point;
2621f982db4aSGavin Atkinson verbose = overbose;
2622f982db4aSGavin Atkinson (void)free(pager);
2623f982db4aSGavin Atkinson }
2624f982db4aSGavin Atkinson
2625f982db4aSGavin Atkinson /*
2626f982db4aSGavin Atkinson * Set the socket send or receive buffer size.
2627f982db4aSGavin Atkinson */
2628f982db4aSGavin Atkinson void
setxferbuf(int argc,char * argv[])2629f982db4aSGavin Atkinson setxferbuf(int argc, char *argv[])
2630f982db4aSGavin Atkinson {
2631f982db4aSGavin Atkinson int size, dir;
2632f982db4aSGavin Atkinson
2633f982db4aSGavin Atkinson if (argc != 2) {
2634f982db4aSGavin Atkinson usage:
2635cc361f65SGavin Atkinson UPRINTF("usage: %s size\n", argv[0]);
2636f982db4aSGavin Atkinson code = -1;
2637f982db4aSGavin Atkinson return;
2638f982db4aSGavin Atkinson }
2639f982db4aSGavin Atkinson if (strcasecmp(argv[0], "sndbuf") == 0)
2640f982db4aSGavin Atkinson dir = RATE_PUT;
2641f982db4aSGavin Atkinson else if (strcasecmp(argv[0], "rcvbuf") == 0)
2642f982db4aSGavin Atkinson dir = RATE_GET;
2643f982db4aSGavin Atkinson else if (strcasecmp(argv[0], "xferbuf") == 0)
2644f982db4aSGavin Atkinson dir = RATE_ALL;
2645f982db4aSGavin Atkinson else
2646f982db4aSGavin Atkinson goto usage;
2647f982db4aSGavin Atkinson
2648f982db4aSGavin Atkinson if ((size = strsuftoi(argv[1])) == -1)
2649f982db4aSGavin Atkinson goto usage;
2650f982db4aSGavin Atkinson
2651f982db4aSGavin Atkinson if (size == 0) {
2652f982db4aSGavin Atkinson fprintf(ttyout, "%s: size must be positive.\n", argv[0]);
2653f982db4aSGavin Atkinson goto usage;
2654f982db4aSGavin Atkinson }
2655f982db4aSGavin Atkinson
2656*43092b7dSHiroki Sato if (dir & RATE_PUT) {
2657f982db4aSGavin Atkinson sndbuf_size = size;
2658*43092b7dSHiroki Sato auto_sndbuf = 0;
2659*43092b7dSHiroki Sato }
2660*43092b7dSHiroki Sato if (dir & RATE_GET) {
2661f982db4aSGavin Atkinson rcvbuf_size = size;
2662*43092b7dSHiroki Sato auto_rcvbuf = 0;
2663*43092b7dSHiroki Sato }
2664f982db4aSGavin Atkinson fprintf(ttyout, "Socket buffer sizes: send %d, receive %d.\n",
2665f982db4aSGavin Atkinson sndbuf_size, rcvbuf_size);
2666f982db4aSGavin Atkinson code = 0;
2667f982db4aSGavin Atkinson }
2668f982db4aSGavin Atkinson
2669f982db4aSGavin Atkinson /*
2670f982db4aSGavin Atkinson * Set or display options (defaults are provided by various env vars)
2671f982db4aSGavin Atkinson */
2672f982db4aSGavin Atkinson void
setoption(int argc,char * argv[])2673f982db4aSGavin Atkinson setoption(int argc, char *argv[])
2674f982db4aSGavin Atkinson {
2675f982db4aSGavin Atkinson struct option *o;
2676f982db4aSGavin Atkinson
2677f982db4aSGavin Atkinson code = -1;
2678f982db4aSGavin Atkinson if (argc == 0 || (argc != 1 && argc != 3)) {
2679cc361f65SGavin Atkinson UPRINTF("usage: %s [option value]\n", argv[0]);
2680f982db4aSGavin Atkinson return;
2681f982db4aSGavin Atkinson }
2682f982db4aSGavin Atkinson
2683f982db4aSGavin Atkinson #define OPTIONINDENT ((int) sizeof("http_proxy"))
2684f982db4aSGavin Atkinson if (argc == 1) {
2685f982db4aSGavin Atkinson for (o = optiontab; o->name != NULL; o++) {
2686f982db4aSGavin Atkinson fprintf(ttyout, "%-*s\t%s\n", OPTIONINDENT,
2687f982db4aSGavin Atkinson o->name, o->value ? o->value : "");
2688f982db4aSGavin Atkinson }
2689f982db4aSGavin Atkinson } else {
2690cc361f65SGavin Atkinson set_option(argv[1], argv[2], 1);
2691cc361f65SGavin Atkinson }
2692cc361f65SGavin Atkinson code = 0;
2693cc361f65SGavin Atkinson }
2694cc361f65SGavin Atkinson
2695cc361f65SGavin Atkinson void
set_option(const char * option,const char * value,int doverbose)2696cc361f65SGavin Atkinson set_option(const char * option, const char * value, int doverbose)
2697cc361f65SGavin Atkinson {
2698cc361f65SGavin Atkinson struct option *o;
2699cc361f65SGavin Atkinson
2700cc361f65SGavin Atkinson o = getoption(option);
2701f982db4aSGavin Atkinson if (o == NULL) {
2702cc361f65SGavin Atkinson fprintf(ttyout, "No such option `%s'.\n", option);
2703f982db4aSGavin Atkinson return;
2704f982db4aSGavin Atkinson }
2705f982db4aSGavin Atkinson FREEPTR(o->value);
2706cc361f65SGavin Atkinson o->value = ftp_strdup(value);
2707cc361f65SGavin Atkinson if (verbose && doverbose)
2708f982db4aSGavin Atkinson fprintf(ttyout, "Setting `%s' to `%s'.\n",
2709f982db4aSGavin Atkinson o->name, o->value);
2710f982db4aSGavin Atkinson }
2711f982db4aSGavin Atkinson
2712f982db4aSGavin Atkinson /*
2713f982db4aSGavin Atkinson * Unset an option
2714f982db4aSGavin Atkinson */
2715f982db4aSGavin Atkinson void
unsetoption(int argc,char * argv[])2716f982db4aSGavin Atkinson unsetoption(int argc, char *argv[])
2717f982db4aSGavin Atkinson {
2718f982db4aSGavin Atkinson struct option *o;
2719f982db4aSGavin Atkinson
2720f982db4aSGavin Atkinson code = -1;
2721f982db4aSGavin Atkinson if (argc == 0 || argc != 2) {
2722cc361f65SGavin Atkinson UPRINTF("usage: %s option\n", argv[0]);
2723f982db4aSGavin Atkinson return;
2724f982db4aSGavin Atkinson }
2725f982db4aSGavin Atkinson
2726f982db4aSGavin Atkinson o = getoption(argv[1]);
2727f982db4aSGavin Atkinson if (o == NULL) {
2728f982db4aSGavin Atkinson fprintf(ttyout, "No such option `%s'.\n", argv[1]);
2729f982db4aSGavin Atkinson return;
2730f982db4aSGavin Atkinson }
2731f982db4aSGavin Atkinson FREEPTR(o->value);
2732f982db4aSGavin Atkinson fprintf(ttyout, "Unsetting `%s'.\n", o->name);
2733f982db4aSGavin Atkinson code = 0;
2734f982db4aSGavin Atkinson }
2735f982db4aSGavin Atkinson
2736f982db4aSGavin Atkinson /*
2737f982db4aSGavin Atkinson * Display features supported by the remote host.
2738f982db4aSGavin Atkinson */
2739f982db4aSGavin Atkinson void
feat(int argc,char * argv[])2740f982db4aSGavin Atkinson feat(int argc, char *argv[])
2741f982db4aSGavin Atkinson {
2742f982db4aSGavin Atkinson int oldverbose = verbose;
2743f982db4aSGavin Atkinson
2744f982db4aSGavin Atkinson if (argc == 0) {
2745cc361f65SGavin Atkinson UPRINTF("usage: %s\n", argv[0]);
2746f982db4aSGavin Atkinson code = -1;
2747f982db4aSGavin Atkinson return;
2748f982db4aSGavin Atkinson }
2749f982db4aSGavin Atkinson if (! features[FEAT_FEAT]) {
2750f982db4aSGavin Atkinson fprintf(ttyout,
2751f982db4aSGavin Atkinson "FEAT is not supported by the remote server.\n");
2752f982db4aSGavin Atkinson return;
2753f982db4aSGavin Atkinson }
2754f982db4aSGavin Atkinson verbose = 1; /* If we aren't verbose, this doesn't do anything! */
2755f982db4aSGavin Atkinson (void)command("FEAT");
2756f982db4aSGavin Atkinson verbose = oldverbose;
2757f982db4aSGavin Atkinson }
2758f982db4aSGavin Atkinson
2759f982db4aSGavin Atkinson void
mlst(int argc,char * argv[])2760f982db4aSGavin Atkinson mlst(int argc, char *argv[])
2761f982db4aSGavin Atkinson {
2762f982db4aSGavin Atkinson int oldverbose = verbose;
2763f982db4aSGavin Atkinson
2764f982db4aSGavin Atkinson if (argc < 1 || argc > 2) {
2765cc361f65SGavin Atkinson UPRINTF("usage: %s [remote-path]\n", argv[0]);
2766f982db4aSGavin Atkinson code = -1;
2767f982db4aSGavin Atkinson return;
2768f982db4aSGavin Atkinson }
2769f982db4aSGavin Atkinson if (! features[FEAT_MLST]) {
2770f982db4aSGavin Atkinson fprintf(ttyout,
2771f982db4aSGavin Atkinson "MLST is not supported by the remote server.\n");
2772f982db4aSGavin Atkinson return;
2773f982db4aSGavin Atkinson }
2774f982db4aSGavin Atkinson verbose = 1; /* If we aren't verbose, this doesn't do anything! */
2775f982db4aSGavin Atkinson COMMAND_1ARG(argc, argv, "MLST");
2776f982db4aSGavin Atkinson verbose = oldverbose;
2777f982db4aSGavin Atkinson }
2778f982db4aSGavin Atkinson
2779f982db4aSGavin Atkinson void
opts(int argc,char * argv[])2780f982db4aSGavin Atkinson opts(int argc, char *argv[])
2781f982db4aSGavin Atkinson {
2782f982db4aSGavin Atkinson int oldverbose = verbose;
2783f982db4aSGavin Atkinson
2784f982db4aSGavin Atkinson if (argc < 2 || argc > 3) {
2785cc361f65SGavin Atkinson UPRINTF("usage: %s command [options]\n", argv[0]);
2786f982db4aSGavin Atkinson code = -1;
2787f982db4aSGavin Atkinson return;
2788f982db4aSGavin Atkinson }
2789f982db4aSGavin Atkinson if (! features[FEAT_FEAT]) {
2790f982db4aSGavin Atkinson fprintf(ttyout,
2791f982db4aSGavin Atkinson "OPTS is not supported by the remote server.\n");
2792f982db4aSGavin Atkinson return;
2793f982db4aSGavin Atkinson }
2794f982db4aSGavin Atkinson verbose = 1; /* If we aren't verbose, this doesn't do anything! */
2795f982db4aSGavin Atkinson if (argc == 2)
2796f982db4aSGavin Atkinson command("OPTS %s", argv[1]);
2797f982db4aSGavin Atkinson else
2798f982db4aSGavin Atkinson command("OPTS %s %s", argv[1], argv[2]);
2799f982db4aSGavin Atkinson verbose = oldverbose;
2800f982db4aSGavin Atkinson }
2801