1*5b133f3fSguenther /* $OpenBSD: cmds.c,v 1.85 2023/03/08 04:43:11 guenther Exp $ */
2bfd817adSflorian /* $NetBSD: cmds.c,v 1.27 1997/08/18 10:20:15 lukem Exp $ */
3bfd817adSflorian
4bfd817adSflorian /*
5bfd817adSflorian * Copyright (C) 1997 and 1998 WIDE Project.
6bfd817adSflorian * All rights reserved.
7bfd817adSflorian *
8bfd817adSflorian * Redistribution and use in source and binary forms, with or without
9bfd817adSflorian * modification, are permitted provided that the following conditions
10bfd817adSflorian * are met:
11bfd817adSflorian * 1. Redistributions of source code must retain the above copyright
12bfd817adSflorian * notice, this list of conditions and the following disclaimer.
13bfd817adSflorian * 2. Redistributions in binary form must reproduce the above copyright
14bfd817adSflorian * notice, this list of conditions and the following disclaimer in the
15bfd817adSflorian * documentation and/or other materials provided with the distribution.
16bfd817adSflorian * 3. Neither the name of the project nor the names of its contributors
17bfd817adSflorian * may be used to endorse or promote products derived from this software
18bfd817adSflorian * without specific prior written permission.
19bfd817adSflorian *
20bfd817adSflorian * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21bfd817adSflorian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22bfd817adSflorian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23bfd817adSflorian * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24bfd817adSflorian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25bfd817adSflorian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26bfd817adSflorian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27bfd817adSflorian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28bfd817adSflorian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29bfd817adSflorian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30bfd817adSflorian * SUCH DAMAGE.
31bfd817adSflorian */
32bfd817adSflorian
33bfd817adSflorian /*
34bfd817adSflorian * Copyright (c) 1985, 1989, 1993, 1994
35bfd817adSflorian * The Regents of the University of California. All rights reserved.
36bfd817adSflorian *
37bfd817adSflorian * Redistribution and use in source and binary forms, with or without
38bfd817adSflorian * modification, are permitted provided that the following conditions
39bfd817adSflorian * are met:
40bfd817adSflorian * 1. Redistributions of source code must retain the above copyright
41bfd817adSflorian * notice, this list of conditions and the following disclaimer.
42bfd817adSflorian * 2. Redistributions in binary form must reproduce the above copyright
43bfd817adSflorian * notice, this list of conditions and the following disclaimer in the
44bfd817adSflorian * documentation and/or other materials provided with the distribution.
45bfd817adSflorian * 3. Neither the name of the University nor the names of its contributors
46bfd817adSflorian * may be used to endorse or promote products derived from this software
47bfd817adSflorian * without specific prior written permission.
48bfd817adSflorian *
49bfd817adSflorian * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50bfd817adSflorian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51bfd817adSflorian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52bfd817adSflorian * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53bfd817adSflorian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54bfd817adSflorian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55bfd817adSflorian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56bfd817adSflorian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57bfd817adSflorian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58bfd817adSflorian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59bfd817adSflorian * SUCH DAMAGE.
60bfd817adSflorian */
61bfd817adSflorian
62bfd817adSflorian #ifndef SMALL
63bfd817adSflorian
64bfd817adSflorian /*
65bfd817adSflorian * FTP User Program -- Command Routines.
66bfd817adSflorian */
67bfd817adSflorian #include <sys/types.h>
68bfd817adSflorian #include <sys/socket.h>
69bfd817adSflorian #include <sys/stat.h>
70bfd817adSflorian #include <sys/wait.h>
71bfd817adSflorian #include <arpa/ftp.h>
72bfd817adSflorian
73bfd817adSflorian #include <ctype.h>
74bfd817adSflorian #include <err.h>
75bfd817adSflorian #include <fnmatch.h>
76bfd817adSflorian #include <glob.h>
77bfd817adSflorian #include <netdb.h>
78bfd817adSflorian #include <stdio.h>
79bfd817adSflorian #include <stdlib.h>
80bfd817adSflorian #include <string.h>
81bfd817adSflorian #include <unistd.h>
82bfd817adSflorian #include <errno.h>
83bfd817adSflorian
84bfd817adSflorian #include "ftp_var.h"
85bfd817adSflorian #include "pathnames.h"
86bfd817adSflorian #include "cmds.h"
87bfd817adSflorian
88bfd817adSflorian /*
89bfd817adSflorian * Set ascii transfer type.
90bfd817adSflorian */
91bfd817adSflorian void
setascii(int argc,char * argv[])92bfd817adSflorian setascii(int argc, char *argv[])
93bfd817adSflorian {
94bfd817adSflorian
95bfd817adSflorian stype[1] = "ascii";
96bfd817adSflorian settype(2, stype);
97bfd817adSflorian }
98bfd817adSflorian
99bfd817adSflorian /*
100bfd817adSflorian * Set file transfer mode.
101bfd817adSflorian */
102bfd817adSflorian void
setftmode(int argc,char * argv[])103bfd817adSflorian setftmode(int argc, char *argv[])
104bfd817adSflorian {
105bfd817adSflorian
106bfd817adSflorian fprintf(ttyout, "We only support %s mode, sorry.\n", modename);
107bfd817adSflorian code = -1;
108bfd817adSflorian }
109bfd817adSflorian
110bfd817adSflorian /*
111bfd817adSflorian * Set file transfer format.
112bfd817adSflorian */
113bfd817adSflorian void
setform(int argc,char * argv[])114bfd817adSflorian setform(int argc, char *argv[])
115bfd817adSflorian {
116bfd817adSflorian
117bfd817adSflorian fprintf(ttyout, "We only support %s format, sorry.\n", formname);
118bfd817adSflorian code = -1;
119bfd817adSflorian }
120bfd817adSflorian
121bfd817adSflorian /*
122bfd817adSflorian * Set file transfer structure.
123bfd817adSflorian */
124bfd817adSflorian void
setstruct(int argc,char * argv[])125bfd817adSflorian setstruct(int argc, char *argv[])
126bfd817adSflorian {
127bfd817adSflorian
128bfd817adSflorian fprintf(ttyout, "We only support %s structure, sorry.\n", structname);
129bfd817adSflorian code = -1;
130bfd817adSflorian }
131bfd817adSflorian
132bfd817adSflorian void
reput(int argc,char * argv[])133bfd817adSflorian reput(int argc, char *argv[])
134bfd817adSflorian {
135bfd817adSflorian
136bfd817adSflorian (void)putit(argc, argv, 1);
137bfd817adSflorian }
138bfd817adSflorian
139bfd817adSflorian void
put(int argc,char * argv[])140bfd817adSflorian put(int argc, char *argv[])
141bfd817adSflorian {
142bfd817adSflorian
143bfd817adSflorian (void)putit(argc, argv, 0);
144bfd817adSflorian }
145bfd817adSflorian
146bfd817adSflorian /*
147bfd817adSflorian * Send a single file.
148bfd817adSflorian */
149bfd817adSflorian void
putit(int argc,char * argv[],int restartit)150bfd817adSflorian putit(int argc, char *argv[], int restartit)
151bfd817adSflorian {
152bfd817adSflorian char *cmd;
153bfd817adSflorian int loc = 0;
154bfd817adSflorian char *oldargv1, *oldargv2;
155bfd817adSflorian
156bfd817adSflorian if (argc == 2) {
157bfd817adSflorian argc++;
158bfd817adSflorian argv[2] = argv[1];
159bfd817adSflorian loc++;
160bfd817adSflorian }
161bfd817adSflorian if (argc < 2 && !another(&argc, &argv, "local-file"))
162bfd817adSflorian goto usage;
163bfd817adSflorian if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) {
164bfd817adSflorian usage:
165bfd817adSflorian fprintf(ttyout, "usage: %s local-file [remote-file]\n",
166bfd817adSflorian argv[0]);
167bfd817adSflorian code = -1;
168bfd817adSflorian return;
169bfd817adSflorian }
170bfd817adSflorian oldargv1 = argv[1];
171bfd817adSflorian oldargv2 = argv[2];
172bfd817adSflorian if (!globulize(&argv[1])) {
173bfd817adSflorian code = -1;
174bfd817adSflorian return;
175bfd817adSflorian }
176bfd817adSflorian /*
177bfd817adSflorian * If "globulize" modifies argv[1], and argv[2] is a copy of
178bfd817adSflorian * the old argv[1], make it a copy of the new argv[1].
179bfd817adSflorian */
180bfd817adSflorian if (argv[1] != oldargv1 && argv[2] == oldargv1) {
181bfd817adSflorian argv[2] = argv[1];
182bfd817adSflorian }
183bfd817adSflorian if (restartit == 1) {
184bfd817adSflorian if (curtype != type)
185bfd817adSflorian changetype(type, 0);
186bfd817adSflorian restart_point = remotesize(argv[2], 1);
187bfd817adSflorian if (restart_point < 0) {
188bfd817adSflorian restart_point = 0;
189bfd817adSflorian code = -1;
190bfd817adSflorian return;
191bfd817adSflorian }
192bfd817adSflorian }
193bfd817adSflorian if (strcmp(argv[0], "append") == 0) {
194bfd817adSflorian restartit = 1;
195bfd817adSflorian }
196bfd817adSflorian cmd = restartit ? "APPE" : ((sunique) ? "STOU" : "STOR");
197bfd817adSflorian if (loc && ntflag) {
198bfd817adSflorian argv[2] = dotrans(argv[2]);
199bfd817adSflorian }
200bfd817adSflorian if (loc && mapflag) {
201bfd817adSflorian argv[2] = domap(argv[2]);
202bfd817adSflorian }
203bfd817adSflorian sendrequest(cmd, argv[1], argv[2],
204bfd817adSflorian argv[1] != oldargv1 || argv[2] != oldargv2);
205bfd817adSflorian restart_point = 0;
206bfd817adSflorian if (oldargv1 != argv[1]) /* free up after globulize() */
207bfd817adSflorian free(argv[1]);
208bfd817adSflorian }
209bfd817adSflorian
210bfd817adSflorian /*
211bfd817adSflorian * Send multiple files.
212bfd817adSflorian */
213bfd817adSflorian void
mput(int argc,char * argv[])214bfd817adSflorian mput(int argc, char *argv[])
215bfd817adSflorian {
216bfd817adSflorian extern int optind, optreset;
217bfd817adSflorian int ch, i, restartit = 0;
218bfd817adSflorian sig_t oldintr;
219bfd817adSflorian char *cmd, *tp, *xargv[] = { argv[0], NULL, NULL };
220bfd817adSflorian const char *errstr;
221bfd817adSflorian static int depth = 0, max_depth = 0;
222bfd817adSflorian
223bfd817adSflorian optind = optreset = 1;
224bfd817adSflorian
225bfd817adSflorian if (depth)
226bfd817adSflorian depth++;
227bfd817adSflorian
228bfd817adSflorian while ((ch = getopt(argc, argv, "cd:r")) != -1) {
229bfd817adSflorian switch(ch) {
230bfd817adSflorian case 'c':
231bfd817adSflorian restartit = 1;
232bfd817adSflorian break;
233bfd817adSflorian case 'd':
234bfd817adSflorian max_depth = strtonum(optarg, 0, INT_MAX, &errstr);
235bfd817adSflorian if (errstr != NULL) {
236bfd817adSflorian fprintf(ttyout, "bad depth value, %s: %s\n",
237bfd817adSflorian errstr, optarg);
238bfd817adSflorian code = -1;
239bfd817adSflorian return;
240bfd817adSflorian }
241bfd817adSflorian break;
242bfd817adSflorian case 'r':
243bfd817adSflorian depth = 1;
244bfd817adSflorian break;
245bfd817adSflorian default:
246bfd817adSflorian goto usage;
247bfd817adSflorian }
248bfd817adSflorian }
249bfd817adSflorian
250bfd817adSflorian if (argc - optind < 1 && !another(&argc, &argv, "local-files")) {
251bfd817adSflorian usage:
252bfd817adSflorian fprintf(ttyout, "usage: %s [-cr] [-d depth] local-files\n",
253bfd817adSflorian argv[0]);
254bfd817adSflorian code = -1;
255bfd817adSflorian return;
256bfd817adSflorian }
257bfd817adSflorian
258bfd817adSflorian argv[optind - 1] = argv[0];
259bfd817adSflorian argc -= optind - 1;
260bfd817adSflorian argv += optind - 1;
261bfd817adSflorian
262bfd817adSflorian mname = argv[0];
263bfd817adSflorian mflag = 1;
264bfd817adSflorian
265bfd817adSflorian oldintr = signal(SIGINT, mabort);
266bfd817adSflorian (void)setjmp(jabort);
267bfd817adSflorian if (proxy) {
268bfd817adSflorian char *cp, *tp2, tmpbuf[PATH_MAX];
269bfd817adSflorian
270bfd817adSflorian while ((cp = remglob(argv, 0, NULL)) != NULL) {
271bfd817adSflorian if (*cp == '\0') {
272bfd817adSflorian mflag = 0;
273bfd817adSflorian continue;
274bfd817adSflorian }
275bfd817adSflorian if (mflag && confirm(argv[0], cp)) {
276bfd817adSflorian tp = cp;
277bfd817adSflorian if (mcase) {
278bfd817adSflorian while (*tp && !islower((unsigned char)*tp)) {
279bfd817adSflorian tp++;
280bfd817adSflorian }
281bfd817adSflorian if (!*tp) {
282bfd817adSflorian tp = cp;
283bfd817adSflorian tp2 = tmpbuf;
284bfd817adSflorian while ((*tp2 = *tp) != '\0') {
285bfd817adSflorian if (isupper((unsigned char)*tp2)) {
286bfd817adSflorian *tp2 =
287bfd817adSflorian tolower((unsigned char)*tp2);
288bfd817adSflorian }
289bfd817adSflorian tp++;
290bfd817adSflorian tp2++;
291bfd817adSflorian }
292bfd817adSflorian }
293bfd817adSflorian tp = tmpbuf;
294bfd817adSflorian }
295bfd817adSflorian if (ntflag) {
296bfd817adSflorian tp = dotrans(tp);
297bfd817adSflorian }
298bfd817adSflorian if (mapflag) {
299bfd817adSflorian tp = domap(tp);
300bfd817adSflorian }
301bfd817adSflorian if (restartit == 1) {
302bfd817adSflorian off_t ret;
303bfd817adSflorian
304bfd817adSflorian if (curtype != type)
305bfd817adSflorian changetype(type, 0);
306bfd817adSflorian ret = remotesize(tp, 0);
307bfd817adSflorian restart_point = (ret < 0) ? 0 : ret;
308bfd817adSflorian }
309bfd817adSflorian cmd = restartit ? "APPE" : ((sunique) ?
310bfd817adSflorian "STOU" : "STOR");
311bfd817adSflorian sendrequest(cmd, cp, tp,
312bfd817adSflorian cp != tp || !interactive);
313bfd817adSflorian restart_point = 0;
314bfd817adSflorian if (!mflag && fromatty) {
315bfd817adSflorian if (confirm(argv[0], NULL))
316bfd817adSflorian mflag = 1;
317bfd817adSflorian }
318bfd817adSflorian }
319bfd817adSflorian }
320bfd817adSflorian (void)signal(SIGINT, oldintr);
321bfd817adSflorian mflag = 0;
322bfd817adSflorian return;
323bfd817adSflorian }
324bfd817adSflorian
325bfd817adSflorian for (i = 1; i < argc; i++) {
326bfd817adSflorian char **cpp;
327bfd817adSflorian glob_t gl;
328bfd817adSflorian int flags;
329bfd817adSflorian
330bfd817adSflorian /* Copy files without word expansion */
331bfd817adSflorian if (!doglob) {
332bfd817adSflorian if (mflag && confirm(argv[0], argv[i])) {
333bfd817adSflorian tp = (ntflag) ? dotrans(argv[i]) : argv[i];
334bfd817adSflorian tp = (mapflag) ? domap(tp) : tp;
335bfd817adSflorian if (restartit == 1) {
336bfd817adSflorian off_t ret;
337bfd817adSflorian
338bfd817adSflorian if (curtype != type)
339bfd817adSflorian changetype(type, 0);
340bfd817adSflorian ret = remotesize(tp, 0);
341bfd817adSflorian restart_point = (ret < 0) ? 0 : ret;
342bfd817adSflorian }
343bfd817adSflorian cmd = restartit ? "APPE" : ((sunique) ?
344bfd817adSflorian "STOU" : "STOR");
345bfd817adSflorian sendrequest(cmd, argv[i], tp,
346bfd817adSflorian tp != argv[i] || !interactive);
347bfd817adSflorian restart_point = 0;
348bfd817adSflorian if (!mflag && fromatty) {
349bfd817adSflorian if (confirm(argv[0], NULL))
350bfd817adSflorian mflag = 1;
351bfd817adSflorian }
352bfd817adSflorian }
353bfd817adSflorian continue;
354bfd817adSflorian }
355bfd817adSflorian
356bfd817adSflorian /* expanding file names */
357bfd817adSflorian memset(&gl, 0, sizeof(gl));
358bfd817adSflorian flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
359bfd817adSflorian if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
360bfd817adSflorian warnx("%s: not found", argv[i]);
361bfd817adSflorian globfree(&gl);
362bfd817adSflorian continue;
363bfd817adSflorian }
364bfd817adSflorian
365bfd817adSflorian /* traverse all expanded file names */
366bfd817adSflorian for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) {
367bfd817adSflorian struct stat filestat;
368bfd817adSflorian
369bfd817adSflorian if (!mflag)
370bfd817adSflorian continue;
371bfd817adSflorian if (stat(*cpp, &filestat) != 0) {
372bfd817adSflorian warn("local: %s", *cpp);
373bfd817adSflorian continue;
374bfd817adSflorian }
375bfd817adSflorian if (S_ISDIR(filestat.st_mode) && depth == max_depth)
376bfd817adSflorian continue;
377bfd817adSflorian if (!confirm(argv[0], *cpp))
378bfd817adSflorian continue;
379bfd817adSflorian
380bfd817adSflorian /*
381bfd817adSflorian * If file is a directory then create a new one
382bfd817adSflorian * at the remote machine.
383bfd817adSflorian */
384bfd817adSflorian if (S_ISDIR(filestat.st_mode)) {
385bfd817adSflorian xargv[1] = *cpp;
386bfd817adSflorian makedir(2, xargv);
387bfd817adSflorian cd(2, xargv);
388bfd817adSflorian if (dirchange != 1) {
389bfd817adSflorian warnx("remote: %s", *cpp);
390bfd817adSflorian continue;
391bfd817adSflorian }
392bfd817adSflorian
393bfd817adSflorian if (chdir(*cpp) != 0) {
394bfd817adSflorian warn("local: %s", *cpp);
395bfd817adSflorian goto out;
396bfd817adSflorian }
397bfd817adSflorian
398bfd817adSflorian /* Copy the whole directory recursively. */
399bfd817adSflorian xargv[1] = "*";
400bfd817adSflorian mput(2, xargv);
401bfd817adSflorian
402bfd817adSflorian if (chdir("..") != 0) {
403bfd817adSflorian mflag = 0;
404bfd817adSflorian warn("local: %s", *cpp);
405bfd817adSflorian goto out;
406bfd817adSflorian }
407bfd817adSflorian
408bfd817adSflorian out:
409bfd817adSflorian xargv[1] = "..";
410bfd817adSflorian cd(2, xargv);
411bfd817adSflorian if (dirchange != 1) {
412bfd817adSflorian warnx("remote: %s", *cpp);
413bfd817adSflorian mflag = 0;
414bfd817adSflorian }
415bfd817adSflorian continue;
416bfd817adSflorian }
417bfd817adSflorian
418bfd817adSflorian tp = (ntflag) ? dotrans(*cpp) : *cpp;
419bfd817adSflorian tp = (mapflag) ? domap(tp) : tp;
420bfd817adSflorian if (restartit == 1) {
421bfd817adSflorian off_t ret;
422bfd817adSflorian
423bfd817adSflorian if (curtype != type)
424bfd817adSflorian changetype(type, 0);
425bfd817adSflorian ret = remotesize(tp, 0);
426bfd817adSflorian restart_point = (ret < 0) ? 0 : ret;
427bfd817adSflorian }
428bfd817adSflorian cmd = restartit ? "APPE" : ((sunique) ?
429bfd817adSflorian "STOU" : "STOR");
430bfd817adSflorian sendrequest(cmd, *cpp, tp,
431bfd817adSflorian *cpp != tp || !interactive);
432bfd817adSflorian restart_point = 0;
433bfd817adSflorian if (!mflag && fromatty) {
434bfd817adSflorian if (confirm(argv[0], NULL))
435bfd817adSflorian mflag = 1;
436bfd817adSflorian }
437bfd817adSflorian }
438bfd817adSflorian globfree(&gl);
439bfd817adSflorian }
440bfd817adSflorian
441bfd817adSflorian (void)signal(SIGINT, oldintr);
442bfd817adSflorian
443bfd817adSflorian if (depth)
444bfd817adSflorian depth--;
445bfd817adSflorian if (depth == 0 || mflag == 0)
446bfd817adSflorian depth = max_depth = mflag = 0;
447bfd817adSflorian }
448bfd817adSflorian
449bfd817adSflorian void
reget(int argc,char * argv[])450bfd817adSflorian reget(int argc, char *argv[])
451bfd817adSflorian {
452bfd817adSflorian
453bfd817adSflorian (void)getit(argc, argv, 1, "a+w");
454bfd817adSflorian }
455bfd817adSflorian
456bfd817adSflorian char *
onoff(int bool)457bfd817adSflorian onoff(int bool)
458bfd817adSflorian {
459bfd817adSflorian
460bfd817adSflorian return (bool ? "on" : "off");
461bfd817adSflorian }
462bfd817adSflorian
463bfd817adSflorian /*
464bfd817adSflorian * Show status.
465bfd817adSflorian */
466bfd817adSflorian void
status(int argc,char * argv[])467bfd817adSflorian status(int argc, char *argv[])
468bfd817adSflorian {
469bfd817adSflorian int i;
470bfd817adSflorian
471bfd817adSflorian if (connected)
472bfd817adSflorian fprintf(ttyout, "Connected %sto %s.\n",
473bfd817adSflorian connected == -1 ? "and logged in" : "", hostname);
474bfd817adSflorian else
475bfd817adSflorian fputs("Not connected.\n", ttyout);
476bfd817adSflorian if (!proxy) {
477bfd817adSflorian pswitch(1);
478bfd817adSflorian if (connected) {
479bfd817adSflorian fprintf(ttyout, "Connected for proxy commands to %s.\n",
480bfd817adSflorian hostname);
481bfd817adSflorian }
482bfd817adSflorian else {
483bfd817adSflorian fputs("No proxy connection.\n", ttyout);
484bfd817adSflorian }
485bfd817adSflorian pswitch(0);
486bfd817adSflorian }
487bfd817adSflorian fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n", onoff(gatemode),
488bfd817adSflorian *gateserver ? gateserver : "(none)", gateport);
489bfd817adSflorian fprintf(ttyout, "Passive mode: %s.\n", onoff(passivemode));
490bfd817adSflorian fprintf(ttyout, "Mode: %s; Type: %s; Form: %s; Structure: %s.\n",
491bfd817adSflorian modename, typename, formname, structname);
492bfd817adSflorian fprintf(ttyout, "Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s.\n",
493bfd817adSflorian onoff(verbose), onoff(bell), onoff(interactive),
494bfd817adSflorian onoff(doglob));
495bfd817adSflorian fprintf(ttyout, "Store unique: %s; Receive unique: %s.\n", onoff(sunique),
496bfd817adSflorian onoff(runique));
497bfd817adSflorian fprintf(ttyout, "Preserve modification times: %s.\n", onoff(preserve));
498bfd817adSflorian fprintf(ttyout, "Case: %s; CR stripping: %s.\n", onoff(mcase), onoff(crflag));
499bfd817adSflorian if (ntflag) {
500bfd817adSflorian fprintf(ttyout, "Ntrans: (in) %s (out) %s\n", ntin, ntout);
501bfd817adSflorian }
502bfd817adSflorian else {
503bfd817adSflorian fputs("Ntrans: off.\n", ttyout);
504bfd817adSflorian }
505bfd817adSflorian if (mapflag) {
506bfd817adSflorian fprintf(ttyout, "Nmap: (in) %s (out) %s\n", mapin, mapout);
507bfd817adSflorian }
508bfd817adSflorian else {
509bfd817adSflorian fputs("Nmap: off.\n", ttyout);
510bfd817adSflorian }
511bfd817adSflorian fprintf(ttyout, "Hash mark printing: %s; Mark count: %d; Progress bar: %s.\n",
512bfd817adSflorian onoff(hash), mark, onoff(progress));
513bfd817adSflorian fprintf(ttyout, "Use of PORT/LPRT cmds: %s.\n", onoff(sendport));
514bfd817adSflorian fprintf(ttyout, "Use of EPSV/EPRT cmds for IPv4: %s%s.\n", onoff(epsv4),
515bfd817adSflorian epsv4bad ? " (disabled for this connection)" : "");
516bfd817adSflorian fprintf(ttyout, "Command line editing: %s.\n", onoff(editing));
517bfd817adSflorian if (macnum > 0) {
518bfd817adSflorian fputs("Macros:\n", ttyout);
519bfd817adSflorian for (i=0; i<macnum; i++) {
520bfd817adSflorian fprintf(ttyout, "\t%s\n", macros[i].mac_name);
521bfd817adSflorian }
522bfd817adSflorian }
523bfd817adSflorian code = 0;
524bfd817adSflorian }
525bfd817adSflorian
526bfd817adSflorian /*
527bfd817adSflorian * Toggle a variable
528bfd817adSflorian */
529bfd817adSflorian int
togglevar(int argc,char * argv[],int * var,const char * mesg)530bfd817adSflorian togglevar(int argc, char *argv[], int *var, const char *mesg)
531bfd817adSflorian {
532bfd817adSflorian if (argc < 2) {
533bfd817adSflorian *var = !*var;
534bfd817adSflorian } else if (argc == 2 && strcasecmp(argv[1], "on") == 0) {
535bfd817adSflorian *var = 1;
536bfd817adSflorian } else if (argc == 2 && strcasecmp(argv[1], "off") == 0) {
537bfd817adSflorian *var = 0;
538bfd817adSflorian } else {
539bfd817adSflorian fprintf(ttyout, "usage: %s [on | off]\n", argv[0]);
540bfd817adSflorian return (-1);
541bfd817adSflorian }
542bfd817adSflorian if (mesg)
543bfd817adSflorian fprintf(ttyout, "%s %s.\n", mesg, onoff(*var));
544bfd817adSflorian return (*var);
545bfd817adSflorian }
546bfd817adSflorian
547bfd817adSflorian /*
548bfd817adSflorian * Set beep on cmd completed mode.
549bfd817adSflorian */
550bfd817adSflorian void
setbell(int argc,char * argv[])551bfd817adSflorian setbell(int argc, char *argv[])
552bfd817adSflorian {
553bfd817adSflorian
554bfd817adSflorian code = togglevar(argc, argv, &bell, "Bell mode");
555bfd817adSflorian }
556bfd817adSflorian
557bfd817adSflorian /*
558bfd817adSflorian * Set command line editing
559bfd817adSflorian */
560bfd817adSflorian void
setedit(int argc,char * argv[])561bfd817adSflorian setedit(int argc, char *argv[])
562bfd817adSflorian {
563bfd817adSflorian
564bfd817adSflorian code = togglevar(argc, argv, &editing, "Editing mode");
565bfd817adSflorian controlediting();
566bfd817adSflorian }
567bfd817adSflorian
568bfd817adSflorian /*
569bfd817adSflorian * Toggle use of IPv4 EPSV/EPRT
570bfd817adSflorian */
571bfd817adSflorian void
setepsv4(int argc,char * argv[])572bfd817adSflorian setepsv4(int argc, char *argv[])
573bfd817adSflorian {
574bfd817adSflorian
575bfd817adSflorian code = togglevar(argc, argv, &epsv4, "EPSV/EPRT on IPv4");
576bfd817adSflorian epsv4bad = 0;
577bfd817adSflorian }
578bfd817adSflorian
579bfd817adSflorian /*
580bfd817adSflorian * Turn on packet tracing.
581bfd817adSflorian */
582bfd817adSflorian void
settrace(int argc,char * argv[])583bfd817adSflorian settrace(int argc, char *argv[])
584bfd817adSflorian {
585bfd817adSflorian
586bfd817adSflorian code = togglevar(argc, argv, &trace, "Packet tracing");
587bfd817adSflorian }
588bfd817adSflorian
589bfd817adSflorian /*
590bfd817adSflorian * Toggle hash mark printing during transfers, or set hash mark bytecount.
591bfd817adSflorian */
592bfd817adSflorian void
sethash(int argc,char * argv[])593bfd817adSflorian sethash(int argc, char *argv[])
594bfd817adSflorian {
595bfd817adSflorian if (argc == 1)
596bfd817adSflorian hash = !hash;
597bfd817adSflorian else if (argc != 2) {
598bfd817adSflorian fprintf(ttyout, "usage: %s [on | off | size]\n", argv[0]);
599bfd817adSflorian code = -1;
600bfd817adSflorian return;
601bfd817adSflorian } else if (strcasecmp(argv[1], "on") == 0)
602bfd817adSflorian hash = 1;
603bfd817adSflorian else if (strcasecmp(argv[1], "off") == 0)
604bfd817adSflorian hash = 0;
605bfd817adSflorian else {
606bfd817adSflorian int nmark;
607bfd817adSflorian const char *errstr;
608bfd817adSflorian
609bfd817adSflorian nmark = strtonum(argv[1], 1, INT_MAX, &errstr);
610bfd817adSflorian if (errstr) {
611bfd817adSflorian fprintf(ttyout, "bytecount value is %s: %s\n",
612bfd817adSflorian errstr, argv[1]);
613bfd817adSflorian code = -1;
614bfd817adSflorian return;
615bfd817adSflorian }
616bfd817adSflorian mark = nmark;
617bfd817adSflorian hash = 1;
618bfd817adSflorian }
619bfd817adSflorian fprintf(ttyout, "Hash mark printing %s", onoff(hash));
620bfd817adSflorian if (hash)
621bfd817adSflorian fprintf(ttyout, " (%d bytes/hash mark)", mark);
622bfd817adSflorian fputs(".\n", ttyout);
623bfd817adSflorian code = hash;
624bfd817adSflorian }
625bfd817adSflorian
626bfd817adSflorian /*
627bfd817adSflorian * Turn on printing of server echo's.
628bfd817adSflorian */
629bfd817adSflorian void
setverbose(int argc,char * argv[])630bfd817adSflorian setverbose(int argc, char *argv[])
631bfd817adSflorian {
632bfd817adSflorian
633bfd817adSflorian code = togglevar(argc, argv, &verbose, "Verbose mode");
634bfd817adSflorian }
635bfd817adSflorian
636bfd817adSflorian /*
637bfd817adSflorian * Toggle PORT/LPRT cmd use before each data connection.
638bfd817adSflorian */
639bfd817adSflorian void
setport(int argc,char * argv[])640bfd817adSflorian setport(int argc, char *argv[])
641bfd817adSflorian {
642bfd817adSflorian
643bfd817adSflorian code = togglevar(argc, argv, &sendport, "Use of PORT/LPRT cmds");
644bfd817adSflorian }
645bfd817adSflorian
646bfd817adSflorian /*
647bfd817adSflorian * Toggle transfer progress bar.
648bfd817adSflorian */
649bfd817adSflorian void
setprogress(int argc,char * argv[])650bfd817adSflorian setprogress(int argc, char *argv[])
651bfd817adSflorian {
652bfd817adSflorian
653bfd817adSflorian code = togglevar(argc, argv, &progress, "Progress bar");
654bfd817adSflorian }
655bfd817adSflorian
656bfd817adSflorian /*
657bfd817adSflorian * Turn on interactive prompting during mget, mput, and mdelete.
658bfd817adSflorian */
659bfd817adSflorian void
setprompt(int argc,char * argv[])660bfd817adSflorian setprompt(int argc, char *argv[])
661bfd817adSflorian {
662bfd817adSflorian
663bfd817adSflorian code = togglevar(argc, argv, &interactive, "Interactive mode");
664bfd817adSflorian }
665bfd817adSflorian
666bfd817adSflorian /*
667bfd817adSflorian * Toggle gate-ftp mode, or set gate-ftp server
668bfd817adSflorian */
669bfd817adSflorian void
setgate(int argc,char * argv[])670bfd817adSflorian setgate(int argc, char *argv[])
671bfd817adSflorian {
672bfd817adSflorian static char gsbuf[HOST_NAME_MAX+1];
673bfd817adSflorian
674bfd817adSflorian if (argc > 3) {
675bfd817adSflorian fprintf(ttyout, "usage: %s [on | off | host [port]]\n",
676bfd817adSflorian argv[0]);
677bfd817adSflorian code = -1;
678bfd817adSflorian return;
679bfd817adSflorian } else if (argc < 2) {
680bfd817adSflorian gatemode = !gatemode;
681bfd817adSflorian } else {
682bfd817adSflorian if (argc == 2 && strcasecmp(argv[1], "on") == 0)
683bfd817adSflorian gatemode = 1;
684bfd817adSflorian else if (argc == 2 && strcasecmp(argv[1], "off") == 0)
685bfd817adSflorian gatemode = 0;
686bfd817adSflorian else {
687bfd817adSflorian if (argc == 3) {
688bfd817adSflorian gateport = strdup(argv[2]);
689bfd817adSflorian if (gateport == NULL)
690bfd817adSflorian err(1, NULL);
691bfd817adSflorian }
692bfd817adSflorian strlcpy(gsbuf, argv[1], sizeof(gsbuf));
693bfd817adSflorian gateserver = gsbuf;
694bfd817adSflorian gatemode = 1;
695bfd817adSflorian }
696bfd817adSflorian }
697bfd817adSflorian if (gatemode && (gateserver == NULL || *gateserver == '\0')) {
698bfd817adSflorian fprintf(ttyout,
699bfd817adSflorian "Disabling gate-ftp mode - no gate-ftp server defined.\n");
700bfd817adSflorian gatemode = 0;
701bfd817adSflorian } else {
702bfd817adSflorian fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n",
703bfd817adSflorian onoff(gatemode),
704bfd817adSflorian *gateserver ? gateserver : "(none)", gateport);
705bfd817adSflorian }
706bfd817adSflorian code = gatemode;
707bfd817adSflorian }
708bfd817adSflorian
709bfd817adSflorian /*
710bfd817adSflorian * Toggle metacharacter interpretation on local file names.
711bfd817adSflorian */
712bfd817adSflorian void
setglob(int argc,char * argv[])713bfd817adSflorian setglob(int argc, char *argv[])
714bfd817adSflorian {
715bfd817adSflorian
716bfd817adSflorian code = togglevar(argc, argv, &doglob, "Globbing");
717bfd817adSflorian }
718bfd817adSflorian
719bfd817adSflorian /*
720bfd817adSflorian * Toggle preserving modification times on retrieved files.
721bfd817adSflorian */
722bfd817adSflorian void
setpreserve(int argc,char * argv[])723bfd817adSflorian setpreserve(int argc, char *argv[])
724bfd817adSflorian {
725bfd817adSflorian
726bfd817adSflorian code = togglevar(argc, argv, &preserve, "Preserve modification times");
727bfd817adSflorian }
728bfd817adSflorian
729bfd817adSflorian /*
730bfd817adSflorian * Set debugging mode on/off and/or set level of debugging.
731bfd817adSflorian */
732bfd817adSflorian void
setdebug(int argc,char * argv[])733bfd817adSflorian setdebug(int argc, char *argv[])
734bfd817adSflorian {
735bfd817adSflorian if (argc > 2) {
736bfd817adSflorian fprintf(ttyout, "usage: %s [on | off | debuglevel]\n", argv[0]);
737bfd817adSflorian code = -1;
738bfd817adSflorian return;
739bfd817adSflorian } else if (argc == 2) {
740bfd817adSflorian if (strcasecmp(argv[1], "on") == 0)
741bfd817adSflorian debug = 1;
742bfd817adSflorian else if (strcasecmp(argv[1], "off") == 0)
743bfd817adSflorian debug = 0;
744bfd817adSflorian else {
745bfd817adSflorian const char *errstr;
746bfd817adSflorian int val;
747bfd817adSflorian
748bfd817adSflorian val = strtonum(argv[1], 0, INT_MAX, &errstr);
749bfd817adSflorian if (errstr) {
750bfd817adSflorian fprintf(ttyout, "debugging value is %s: %s\n",
751bfd817adSflorian errstr, argv[1]);
752bfd817adSflorian code = -1;
753bfd817adSflorian return;
754bfd817adSflorian }
755bfd817adSflorian debug = val;
756bfd817adSflorian }
757bfd817adSflorian } else
758bfd817adSflorian debug = !debug;
759bfd817adSflorian if (debug)
760bfd817adSflorian options |= SO_DEBUG;
761bfd817adSflorian else
762bfd817adSflorian options &= ~SO_DEBUG;
763bfd817adSflorian fprintf(ttyout, "Debugging %s (debug=%d).\n", onoff(debug), debug);
764bfd817adSflorian code = debug > 0;
765bfd817adSflorian }
766bfd817adSflorian
767bfd817adSflorian /*
768bfd817adSflorian * Set current working directory on local machine.
769bfd817adSflorian */
770bfd817adSflorian void
lcd(int argc,char * argv[])771bfd817adSflorian lcd(int argc, char *argv[])
772bfd817adSflorian {
773bfd817adSflorian char buf[PATH_MAX];
774bfd817adSflorian char *oldargv1;
775bfd817adSflorian
776bfd817adSflorian if (argc < 2)
777bfd817adSflorian argc++, argv[1] = home;
778bfd817adSflorian if (argc != 2) {
779bfd817adSflorian fprintf(ttyout, "usage: %s [local-directory]\n", argv[0]);
780bfd817adSflorian code = -1;
781bfd817adSflorian return;
782bfd817adSflorian }
783bfd817adSflorian oldargv1 = argv[1];
784bfd817adSflorian if (!globulize(&argv[1])) {
785bfd817adSflorian code = -1;
786bfd817adSflorian return;
787bfd817adSflorian }
7883aaa63ebSderaadt if (chdir(argv[1]) == -1) {
789bfd817adSflorian warn("local: %s", argv[1]);
790bfd817adSflorian code = -1;
791bfd817adSflorian } else {
792bfd817adSflorian if (getcwd(buf, sizeof(buf)) != NULL)
793bfd817adSflorian fprintf(ttyout, "Local directory now %s\n", buf);
794bfd817adSflorian else
795bfd817adSflorian warn("getcwd: %s", argv[1]);
796bfd817adSflorian code = 0;
797bfd817adSflorian }
798bfd817adSflorian if (oldargv1 != argv[1]) /* free up after globulize() */
799bfd817adSflorian free(argv[1]);
800bfd817adSflorian }
801bfd817adSflorian
802bfd817adSflorian /*
803bfd817adSflorian * Delete a single file.
804bfd817adSflorian */
805bfd817adSflorian void
deletecmd(int argc,char * argv[])806bfd817adSflorian deletecmd(int argc, char *argv[])
807bfd817adSflorian {
808bfd817adSflorian
809bfd817adSflorian if ((argc < 2 && !another(&argc, &argv, "remote-file")) || argc > 2) {
810bfd817adSflorian fprintf(ttyout, "usage: %s remote-file\n", argv[0]);
811bfd817adSflorian code = -1;
812bfd817adSflorian return;
813bfd817adSflorian }
814bfd817adSflorian (void)command("DELE %s", argv[1]);
815bfd817adSflorian }
816bfd817adSflorian
817bfd817adSflorian /*
818bfd817adSflorian * Delete multiple files.
819bfd817adSflorian */
820bfd817adSflorian void
mdelete(int argc,char * argv[])821bfd817adSflorian mdelete(int argc, char *argv[])
822bfd817adSflorian {
823bfd817adSflorian sig_t oldintr;
824bfd817adSflorian char *cp;
825bfd817adSflorian
826bfd817adSflorian if (argc < 2 && !another(&argc, &argv, "remote-files")) {
827bfd817adSflorian fprintf(ttyout, "usage: %s remote-files\n", argv[0]);
828bfd817adSflorian code = -1;
829bfd817adSflorian return;
830bfd817adSflorian }
831bfd817adSflorian mname = argv[0];
832bfd817adSflorian mflag = 1;
833bfd817adSflorian oldintr = signal(SIGINT, mabort);
834bfd817adSflorian (void)setjmp(jabort);
835bfd817adSflorian while ((cp = remglob(argv, 0, NULL)) != NULL) {
836bfd817adSflorian if (*cp == '\0') {
837bfd817adSflorian mflag = 0;
838bfd817adSflorian continue;
839bfd817adSflorian }
840bfd817adSflorian if (mflag && confirm(argv[0], cp)) {
841bfd817adSflorian (void)command("DELE %s", cp);
842bfd817adSflorian if (!mflag && fromatty) {
843bfd817adSflorian if (confirm(argv[0], NULL))
844bfd817adSflorian mflag = 1;
845bfd817adSflorian }
846bfd817adSflorian }
847bfd817adSflorian }
848bfd817adSflorian (void)signal(SIGINT, oldintr);
849bfd817adSflorian mflag = 0;
850bfd817adSflorian }
851bfd817adSflorian
852bfd817adSflorian /*
853bfd817adSflorian * Rename a remote file.
854bfd817adSflorian */
855bfd817adSflorian void
renamefile(int argc,char * argv[])856bfd817adSflorian renamefile(int argc, char *argv[])
857bfd817adSflorian {
858bfd817adSflorian
859bfd817adSflorian if (argc < 2 && !another(&argc, &argv, "from-name"))
860bfd817adSflorian goto usage;
861bfd817adSflorian if ((argc < 3 && !another(&argc, &argv, "to-name")) || argc > 3) {
862bfd817adSflorian usage:
863bfd817adSflorian fprintf(ttyout, "usage: %s from-name to-name\n", argv[0]);
864bfd817adSflorian code = -1;
865bfd817adSflorian return;
866bfd817adSflorian }
867bfd817adSflorian if (command("RNFR %s", argv[1]) == CONTINUE)
868bfd817adSflorian (void)command("RNTO %s", argv[2]);
869bfd817adSflorian }
870bfd817adSflorian
871bfd817adSflorian /*
872bfd817adSflorian * Get a directory listing of remote files.
873bfd817adSflorian */
874bfd817adSflorian void
ls(int argc,char * argv[])875bfd817adSflorian ls(int argc, char *argv[])
876bfd817adSflorian {
877bfd817adSflorian const char *cmd;
878bfd817adSflorian char *oldargv2, *globargv2;
879bfd817adSflorian
880bfd817adSflorian if (argc < 2)
881bfd817adSflorian argc++, argv[1] = NULL;
882bfd817adSflorian if (argc < 3)
883bfd817adSflorian argc++, argv[2] = "-";
884bfd817adSflorian if (argc > 3) {
885bfd817adSflorian fprintf(ttyout, "usage: %s [remote-directory [local-file]]\n",
886bfd817adSflorian argv[0]);
887bfd817adSflorian code = -1;
888bfd817adSflorian return;
889bfd817adSflorian }
890bfd817adSflorian cmd = strcmp(argv[0], "nlist") == 0 ? "NLST" : "LIST";
891bfd817adSflorian oldargv2 = argv[2];
892bfd817adSflorian if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
893bfd817adSflorian code = -1;
894bfd817adSflorian return;
895bfd817adSflorian }
896bfd817adSflorian globargv2 = argv[2];
897bfd817adSflorian if (strcmp(argv[2], "-") && *argv[2] != '|' && (!globulize(&argv[2]) ||
898bfd817adSflorian !confirm("output to local-file:", argv[2]))) {
899bfd817adSflorian code = -1;
900bfd817adSflorian goto freels;
901bfd817adSflorian }
902bfd817adSflorian recvrequest(cmd, argv[2], argv[1], "w", 0, 0);
903bfd817adSflorian
904bfd817adSflorian /* flush results in case commands are coming from a pipe */
905bfd817adSflorian fflush(ttyout);
906bfd817adSflorian freels:
907bfd817adSflorian if (argv[2] != globargv2) /* free up after globulize() */
908bfd817adSflorian free(argv[2]);
909bfd817adSflorian if (globargv2 != oldargv2)
910bfd817adSflorian free(globargv2);
911bfd817adSflorian }
912bfd817adSflorian
913bfd817adSflorian /*
914bfd817adSflorian * Get a directory listing of multiple remote files.
915bfd817adSflorian */
916bfd817adSflorian void
mls(int argc,char * argv[])917bfd817adSflorian mls(int argc, char *argv[])
918bfd817adSflorian {
919bfd817adSflorian sig_t oldintr;
920bfd817adSflorian int i;
921bfd817adSflorian char lmode[1], *dest, *odest;
922bfd817adSflorian
923bfd817adSflorian if (argc < 2 && !another(&argc, &argv, "remote-files"))
924bfd817adSflorian goto usage;
925bfd817adSflorian if (argc < 3 && !another(&argc, &argv, "local-file")) {
926bfd817adSflorian usage:
927bfd817adSflorian fprintf(ttyout, "usage: %s remote-files local-file\n", argv[0]);
928bfd817adSflorian code = -1;
929bfd817adSflorian return;
930bfd817adSflorian }
931bfd817adSflorian odest = dest = argv[argc - 1];
932bfd817adSflorian argv[argc - 1] = NULL;
933bfd817adSflorian if (strcmp(dest, "-") && *dest != '|')
934bfd817adSflorian if (!globulize(&dest) ||
935bfd817adSflorian !confirm("output to local-file:", dest)) {
936bfd817adSflorian code = -1;
937bfd817adSflorian return;
938bfd817adSflorian }
939bfd817adSflorian mname = argv[0];
940bfd817adSflorian mflag = 1;
941bfd817adSflorian oldintr = signal(SIGINT, mabort);
942bfd817adSflorian (void)setjmp(jabort);
943bfd817adSflorian for (i = 1; mflag && i < argc-1; ++i) {
944bfd817adSflorian *lmode = (i == 1) ? 'w' : 'a';
945bfd817adSflorian recvrequest("LIST", dest, argv[i], lmode, 0, 0);
946bfd817adSflorian if (!mflag && fromatty) {
947bfd817adSflorian if (confirm(argv[0], NULL))
948bfd817adSflorian mflag ++;
949bfd817adSflorian }
950bfd817adSflorian }
951bfd817adSflorian (void)signal(SIGINT, oldintr);
952bfd817adSflorian mflag = 0;
953bfd817adSflorian if (dest != odest) /* free up after globulize() */
954bfd817adSflorian free(dest);
955bfd817adSflorian }
956bfd817adSflorian
957bfd817adSflorian /*
958bfd817adSflorian * Do a shell escape
959bfd817adSflorian */
960bfd817adSflorian void
shell(int argc,char * argv[])961bfd817adSflorian shell(int argc, char *argv[])
962bfd817adSflorian {
963bfd817adSflorian pid_t pid;
964bfd817adSflorian sig_t old1, old2;
965bfd817adSflorian char shellnam[PATH_MAX], *shellp, *namep;
966bfd817adSflorian int wait_status;
967bfd817adSflorian
968bfd817adSflorian old1 = signal (SIGINT, SIG_IGN);
969bfd817adSflorian old2 = signal (SIGQUIT, SIG_IGN);
970bfd817adSflorian if ((pid = fork()) == 0) {
971bfd817adSflorian (void)closefrom(3);
972bfd817adSflorian (void)signal(SIGINT, SIG_DFL);
973bfd817adSflorian (void)signal(SIGQUIT, SIG_DFL);
974bfd817adSflorian shellp = getenv("SHELL");
975bfd817adSflorian if (shellp == NULL || *shellp == '\0')
976bfd817adSflorian shellp = _PATH_BSHELL;
977bfd817adSflorian namep = strrchr(shellp, '/');
978bfd817adSflorian if (namep == NULL)
979bfd817adSflorian namep = shellp;
980bfd817adSflorian shellnam[0] = '-';
981bfd817adSflorian (void)strlcpy(shellnam + 1, ++namep, sizeof(shellnam) - 1);
982bfd817adSflorian if (strcmp(namep, "sh") != 0)
983bfd817adSflorian shellnam[0] = '+';
984bfd817adSflorian if (debug) {
985bfd817adSflorian fputs(shellp, ttyout);
986bfd817adSflorian fputc('\n', ttyout);
987bfd817adSflorian (void)fflush(ttyout);
988bfd817adSflorian }
989bfd817adSflorian if (argc > 1) {
990bfd817adSflorian execl(shellp, shellnam, "-c", altarg, (char *)NULL);
991bfd817adSflorian }
992bfd817adSflorian else {
993bfd817adSflorian execl(shellp, shellnam, (char *)NULL);
994bfd817adSflorian }
995bfd817adSflorian warn("%s", shellp);
996bfd817adSflorian code = -1;
997bfd817adSflorian exit(1);
998bfd817adSflorian }
999bfd817adSflorian if (pid > 0)
1000bfd817adSflorian while (wait(&wait_status) != pid)
1001bfd817adSflorian ;
1002bfd817adSflorian (void)signal(SIGINT, old1);
1003bfd817adSflorian (void)signal(SIGQUIT, old2);
1004bfd817adSflorian if (pid == -1) {
1005bfd817adSflorian warn("Try again later");
1006bfd817adSflorian code = -1;
1007bfd817adSflorian }
1008bfd817adSflorian else {
1009bfd817adSflorian code = 0;
1010bfd817adSflorian }
1011bfd817adSflorian }
1012bfd817adSflorian
1013bfd817adSflorian /*
1014bfd817adSflorian * Send new user information (re-login)
1015bfd817adSflorian */
1016bfd817adSflorian void
user(int argc,char * argv[])1017bfd817adSflorian user(int argc, char *argv[])
1018bfd817adSflorian {
1019bfd817adSflorian char acctname[80];
1020bfd817adSflorian int n, aflag = 0;
1021bfd817adSflorian
1022bfd817adSflorian if (argc < 2)
1023bfd817adSflorian (void)another(&argc, &argv, "username");
1024bfd817adSflorian if (argc < 2 || argc > 4) {
1025bfd817adSflorian fprintf(ttyout, "usage: %s username [password [account]]\n",
1026bfd817adSflorian argv[0]);
1027bfd817adSflorian code = -1;
1028bfd817adSflorian return;
1029bfd817adSflorian }
1030bfd817adSflorian n = command("USER %s", argv[1]);
1031bfd817adSflorian if (n == CONTINUE) {
1032bfd817adSflorian if (argc < 3 )
1033bfd817adSflorian argv[2] = getpass("Password:"), argc++;
1034bfd817adSflorian n = command("PASS %s", argv[2]);
1035bfd817adSflorian }
1036bfd817adSflorian if (n == CONTINUE) {
1037bfd817adSflorian if (argc < 4) {
1038bfd817adSflorian (void)fputs("Account: ", ttyout);
1039bfd817adSflorian (void)fflush(ttyout);
1040bfd817adSflorian if (fgets(acctname, sizeof(acctname), stdin) == NULL) {
1041bfd817adSflorian clearerr(stdin);
1042bfd817adSflorian goto fail;
1043bfd817adSflorian }
1044bfd817adSflorian
1045bfd817adSflorian acctname[strcspn(acctname, "\n")] = '\0';
1046bfd817adSflorian
1047bfd817adSflorian argv[3] = acctname;
1048bfd817adSflorian argc++;
1049bfd817adSflorian }
1050bfd817adSflorian n = command("ACCT %s", argv[3]);
1051bfd817adSflorian aflag++;
1052bfd817adSflorian }
1053bfd817adSflorian if (n != COMPLETE) {
1054bfd817adSflorian fail:
1055bfd817adSflorian fputs("Login failed.\n", ttyout);
1056bfd817adSflorian return;
1057bfd817adSflorian }
1058bfd817adSflorian if (!aflag && argc == 4) {
1059bfd817adSflorian (void)command("ACCT %s", argv[3]);
1060bfd817adSflorian }
1061bfd817adSflorian connected = -1;
1062bfd817adSflorian }
1063bfd817adSflorian
1064bfd817adSflorian /*
1065bfd817adSflorian * Print working directory on remote machine.
1066bfd817adSflorian */
1067bfd817adSflorian void
pwd(int argc,char * argv[])1068bfd817adSflorian pwd(int argc, char *argv[])
1069bfd817adSflorian {
1070bfd817adSflorian int oldverbose = verbose;
1071bfd817adSflorian
1072bfd817adSflorian /*
1073bfd817adSflorian * If we aren't verbose, this doesn't do anything!
1074bfd817adSflorian */
1075bfd817adSflorian verbose = 1;
1076bfd817adSflorian if (command("PWD") == ERROR && code == 500) {
1077bfd817adSflorian fputs("PWD command not recognized, trying XPWD.\n", ttyout);
1078bfd817adSflorian (void)command("XPWD");
1079bfd817adSflorian }
1080bfd817adSflorian verbose = oldverbose;
1081bfd817adSflorian }
1082bfd817adSflorian
1083bfd817adSflorian /*
1084bfd817adSflorian * Print working directory on local machine.
1085bfd817adSflorian */
1086bfd817adSflorian void
lpwd(int argc,char * argv[])1087bfd817adSflorian lpwd(int argc, char *argv[])
1088bfd817adSflorian {
1089bfd817adSflorian char buf[PATH_MAX];
1090bfd817adSflorian
1091bfd817adSflorian if (getcwd(buf, sizeof(buf)) != NULL)
1092bfd817adSflorian fprintf(ttyout, "Local directory %s\n", buf);
1093bfd817adSflorian else
1094bfd817adSflorian warn("getcwd");
1095bfd817adSflorian code = 0;
1096bfd817adSflorian }
1097bfd817adSflorian
1098bfd817adSflorian /*
1099bfd817adSflorian * Make a directory.
1100bfd817adSflorian */
1101bfd817adSflorian void
makedir(int argc,char * argv[])1102bfd817adSflorian makedir(int argc, char *argv[])
1103bfd817adSflorian {
1104bfd817adSflorian
1105bfd817adSflorian if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1106bfd817adSflorian argc > 2) {
1107bfd817adSflorian fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1108bfd817adSflorian code = -1;
1109bfd817adSflorian return;
1110bfd817adSflorian }
1111bfd817adSflorian if (command("MKD %s", argv[1]) == ERROR && code == 500) {
1112bfd817adSflorian if (verbose)
1113bfd817adSflorian fputs("MKD command not recognized, trying XMKD.\n", ttyout);
1114bfd817adSflorian (void)command("XMKD %s", argv[1]);
1115bfd817adSflorian }
1116bfd817adSflorian }
1117bfd817adSflorian
1118bfd817adSflorian /*
1119bfd817adSflorian * Remove a directory.
1120bfd817adSflorian */
1121bfd817adSflorian void
removedir(int argc,char * argv[])1122bfd817adSflorian removedir(int argc, char *argv[])
1123bfd817adSflorian {
1124bfd817adSflorian
1125bfd817adSflorian if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1126bfd817adSflorian argc > 2) {
1127bfd817adSflorian fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1128bfd817adSflorian code = -1;
1129bfd817adSflorian return;
1130bfd817adSflorian }
1131bfd817adSflorian if (command("RMD %s", argv[1]) == ERROR && code == 500) {
1132bfd817adSflorian if (verbose)
1133bfd817adSflorian fputs("RMD command not recognized, trying XRMD.\n", ttyout);
1134bfd817adSflorian (void)command("XRMD %s", argv[1]);
1135bfd817adSflorian }
1136bfd817adSflorian }
1137bfd817adSflorian
1138bfd817adSflorian /*
1139bfd817adSflorian * Send a line, verbatim, to the remote machine.
1140bfd817adSflorian */
1141bfd817adSflorian void
quote(int argc,char * argv[])1142bfd817adSflorian quote(int argc, char *argv[])
1143bfd817adSflorian {
1144bfd817adSflorian
1145bfd817adSflorian if (argc < 2 && !another(&argc, &argv, "command line to send")) {
1146bfd817adSflorian fprintf(ttyout, "usage: %s arg ...\n", argv[0]);
1147bfd817adSflorian code = -1;
1148bfd817adSflorian return;
1149bfd817adSflorian }
1150bfd817adSflorian quote1("", argc, argv);
1151bfd817adSflorian }
1152bfd817adSflorian
1153bfd817adSflorian /*
1154bfd817adSflorian * Send a SITE command to the remote machine. The line
1155bfd817adSflorian * is sent verbatim to the remote machine, except that the
1156bfd817adSflorian * word "SITE" is added at the front.
1157bfd817adSflorian */
1158bfd817adSflorian void
site(int argc,char * argv[])1159bfd817adSflorian site(int argc, char *argv[])
1160bfd817adSflorian {
1161bfd817adSflorian
1162bfd817adSflorian if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) {
1163bfd817adSflorian fprintf(ttyout, "usage: %s arg ...\n", argv[0]);
1164bfd817adSflorian code = -1;
1165bfd817adSflorian return;
1166bfd817adSflorian }
1167bfd817adSflorian quote1("SITE", argc, argv);
1168bfd817adSflorian }
1169bfd817adSflorian
1170bfd817adSflorian /*
1171bfd817adSflorian * Turn argv[1..argc) into a space-separated string, then prepend initial text.
1172bfd817adSflorian * Send the result as a one-line command and get response.
1173bfd817adSflorian */
1174bfd817adSflorian void
quote1(const char * initial,int argc,char * argv[])1175bfd817adSflorian quote1(const char *initial, int argc, char *argv[])
1176bfd817adSflorian {
1177bfd817adSflorian int i, len;
1178bfd817adSflorian char buf[BUFSIZ]; /* must be >= sizeof(line) */
1179bfd817adSflorian
1180bfd817adSflorian (void)strlcpy(buf, initial, sizeof(buf));
1181bfd817adSflorian if (argc > 1) {
1182bfd817adSflorian for (i = 1, len = strlen(buf); i < argc && len < sizeof(buf)-1; i++) {
1183bfd817adSflorian /* Space for next arg */
1184bfd817adSflorian if (len > 1)
1185bfd817adSflorian buf[len++] = ' ';
1186bfd817adSflorian
1187bfd817adSflorian /* Sanity check */
1188bfd817adSflorian if (len >= sizeof(buf) - 1)
1189bfd817adSflorian break;
1190bfd817adSflorian
1191bfd817adSflorian /* Copy next argument, NUL terminate always */
1192bfd817adSflorian strlcpy(&buf[len], argv[i], sizeof(buf) - len);
1193bfd817adSflorian
1194bfd817adSflorian /* Update string length */
1195bfd817adSflorian len = strlen(buf);
1196bfd817adSflorian }
1197bfd817adSflorian }
1198bfd817adSflorian
1199bfd817adSflorian /* Make double (triple?) sure the sucker is NUL terminated */
1200bfd817adSflorian buf[sizeof(buf) - 1] = '\0';
1201bfd817adSflorian
1202bfd817adSflorian if (command("%s", buf) == PRELIM) {
1203bfd817adSflorian while (getreply(0) == PRELIM)
1204bfd817adSflorian continue;
1205bfd817adSflorian }
1206bfd817adSflorian }
1207bfd817adSflorian
1208bfd817adSflorian void
do_chmod(int argc,char * argv[])1209bfd817adSflorian do_chmod(int argc, char *argv[])
1210bfd817adSflorian {
1211bfd817adSflorian
1212bfd817adSflorian if (argc < 2 && !another(&argc, &argv, "mode"))
1213bfd817adSflorian goto usage;
1214bfd817adSflorian if ((argc < 3 && !another(&argc, &argv, "file")) || argc > 3) {
1215bfd817adSflorian usage:
1216bfd817adSflorian fprintf(ttyout, "usage: %s mode file\n", argv[0]);
1217bfd817adSflorian code = -1;
1218bfd817adSflorian return;
1219bfd817adSflorian }
1220bfd817adSflorian (void)command("SITE CHMOD %s %s", argv[1], argv[2]);
1221bfd817adSflorian }
1222bfd817adSflorian
1223bfd817adSflorian void
do_umask(int argc,char * argv[])1224bfd817adSflorian do_umask(int argc, char *argv[])
1225bfd817adSflorian {
1226bfd817adSflorian int oldverbose = verbose;
1227bfd817adSflorian
1228bfd817adSflorian verbose = 1;
1229bfd817adSflorian (void)command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
1230bfd817adSflorian verbose = oldverbose;
1231bfd817adSflorian }
1232bfd817adSflorian
1233bfd817adSflorian void
idle(int argc,char * argv[])1234bfd817adSflorian idle(int argc, char *argv[])
1235bfd817adSflorian {
1236bfd817adSflorian int oldverbose = verbose;
1237bfd817adSflorian
1238bfd817adSflorian verbose = 1;
1239bfd817adSflorian (void)command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
1240bfd817adSflorian verbose = oldverbose;
1241bfd817adSflorian }
1242bfd817adSflorian
1243bfd817adSflorian /*
1244bfd817adSflorian * Ask the other side for help.
1245bfd817adSflorian */
1246bfd817adSflorian void
rmthelp(int argc,char * argv[])1247bfd817adSflorian rmthelp(int argc, char *argv[])
1248bfd817adSflorian {
1249bfd817adSflorian int oldverbose = verbose;
1250bfd817adSflorian
1251bfd817adSflorian verbose = 1;
1252bfd817adSflorian (void)command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
1253bfd817adSflorian verbose = oldverbose;
1254bfd817adSflorian }
1255bfd817adSflorian
1256bfd817adSflorian /*
1257bfd817adSflorian * Terminate session and exit.
1258bfd817adSflorian */
1259bfd817adSflorian void
quit(int argc,char * argv[])1260bfd817adSflorian quit(int argc, char *argv[])
1261bfd817adSflorian {
1262bfd817adSflorian
1263bfd817adSflorian if (connected)
1264bfd817adSflorian disconnect(0, 0);
1265bfd817adSflorian pswitch(1);
1266bfd817adSflorian if (connected) {
1267bfd817adSflorian disconnect(0, 0);
1268bfd817adSflorian }
1269bfd817adSflorian exit(0);
1270bfd817adSflorian }
1271bfd817adSflorian
1272bfd817adSflorian void
account(int argc,char * argv[])1273bfd817adSflorian account(int argc, char *argv[])
1274bfd817adSflorian {
1275bfd817adSflorian char *ap;
1276bfd817adSflorian
1277bfd817adSflorian if (argc > 2) {
1278bfd817adSflorian fprintf(ttyout, "usage: %s [password]\n", argv[0]);
1279bfd817adSflorian code = -1;
1280bfd817adSflorian return;
1281bfd817adSflorian }
1282bfd817adSflorian else if (argc == 2)
1283bfd817adSflorian ap = argv[1];
1284bfd817adSflorian else
1285bfd817adSflorian ap = getpass("Account:");
1286bfd817adSflorian (void)command("ACCT %s", ap);
1287bfd817adSflorian }
1288bfd817adSflorian
1289bfd817adSflorian jmp_buf abortprox;
1290bfd817adSflorian
1291bfd817adSflorian void
proxabort(int signo)1292bfd817adSflorian proxabort(int signo)
1293bfd817adSflorian {
1294bfd817adSflorian int save_errno = errno;
1295bfd817adSflorian
1296bfd817adSflorian alarmtimer(0);
1297bfd817adSflorian if (!proxy) {
1298bfd817adSflorian pswitch(1);
1299bfd817adSflorian }
1300bfd817adSflorian if (connected) {
1301bfd817adSflorian proxflag = 1;
1302bfd817adSflorian }
1303bfd817adSflorian else {
1304bfd817adSflorian proxflag = 0;
1305bfd817adSflorian }
1306bfd817adSflorian pswitch(0);
1307bfd817adSflorian errno = save_errno;
1308bfd817adSflorian longjmp(abortprox, 1);
1309bfd817adSflorian }
1310bfd817adSflorian
1311bfd817adSflorian void
doproxy(int argc,char * argv[])1312bfd817adSflorian doproxy(int argc, char *argv[])
1313bfd817adSflorian {
1314bfd817adSflorian struct cmd *c;
1315bfd817adSflorian int cmdpos;
1316bfd817adSflorian sig_t oldintr;
1317bfd817adSflorian
1318bfd817adSflorian if (argc < 2 && !another(&argc, &argv, "command")) {
1319bfd817adSflorian fprintf(ttyout, "usage: %s command\n", argv[0]);
1320bfd817adSflorian code = -1;
1321bfd817adSflorian return;
1322bfd817adSflorian }
1323bfd817adSflorian c = getcmd(argv[1]);
1324bfd817adSflorian if (c == (struct cmd *) -1) {
1325bfd817adSflorian fputs("?Ambiguous command.\n", ttyout);
1326bfd817adSflorian (void)fflush(ttyout);
1327bfd817adSflorian code = -1;
1328bfd817adSflorian return;
1329bfd817adSflorian }
1330bfd817adSflorian if (c == 0) {
1331bfd817adSflorian fputs("?Invalid command.\n", ttyout);
1332bfd817adSflorian (void)fflush(ttyout);
1333bfd817adSflorian code = -1;
1334bfd817adSflorian return;
1335bfd817adSflorian }
1336bfd817adSflorian if (!c->c_proxy) {
1337bfd817adSflorian fputs("?Invalid proxy command.\n", ttyout);
1338bfd817adSflorian (void)fflush(ttyout);
1339bfd817adSflorian code = -1;
1340bfd817adSflorian return;
1341bfd817adSflorian }
1342bfd817adSflorian if (setjmp(abortprox)) {
1343bfd817adSflorian code = -1;
1344bfd817adSflorian return;
1345bfd817adSflorian }
1346bfd817adSflorian oldintr = signal(SIGINT, proxabort);
1347bfd817adSflorian pswitch(1);
1348bfd817adSflorian if (c->c_conn && !connected) {
1349bfd817adSflorian fputs("Not connected.\n", ttyout);
1350bfd817adSflorian (void)fflush(ttyout);
1351bfd817adSflorian pswitch(0);
1352bfd817adSflorian (void)signal(SIGINT, oldintr);
1353bfd817adSflorian code = -1;
1354bfd817adSflorian return;
1355bfd817adSflorian }
1356bfd817adSflorian cmdpos = strcspn(line, " \t");
1357bfd817adSflorian if (cmdpos > 0) /* remove leading "proxy " from input buffer */
1358bfd817adSflorian memmove(line, line + cmdpos + 1, strlen(line) - cmdpos + 1);
1359bfd817adSflorian (*c->c_handler)(argc-1, argv+1);
1360bfd817adSflorian if (connected) {
1361bfd817adSflorian proxflag = 1;
1362bfd817adSflorian }
1363bfd817adSflorian else {
1364bfd817adSflorian proxflag = 0;
1365bfd817adSflorian }
1366bfd817adSflorian pswitch(0);
1367bfd817adSflorian (void)signal(SIGINT, oldintr);
1368bfd817adSflorian }
1369bfd817adSflorian
1370bfd817adSflorian void
setcase(int argc,char * argv[])1371bfd817adSflorian setcase(int argc, char *argv[])
1372bfd817adSflorian {
1373bfd817adSflorian
1374bfd817adSflorian code = togglevar(argc, argv, &mcase, "Case mapping");
1375bfd817adSflorian }
1376bfd817adSflorian
1377bfd817adSflorian void
setcr(int argc,char * argv[])1378bfd817adSflorian setcr(int argc, char *argv[])
1379bfd817adSflorian {
1380bfd817adSflorian
1381bfd817adSflorian code = togglevar(argc, argv, &crflag, "Carriage Return stripping");
1382bfd817adSflorian }
1383bfd817adSflorian
1384bfd817adSflorian void
setntrans(int argc,char * argv[])1385bfd817adSflorian setntrans(int argc, char *argv[])
1386bfd817adSflorian {
1387bfd817adSflorian if (argc == 1) {
1388bfd817adSflorian ntflag = 0;
1389bfd817adSflorian fputs("Ntrans off.\n", ttyout);
1390bfd817adSflorian code = ntflag;
1391bfd817adSflorian return;
1392bfd817adSflorian }
1393bfd817adSflorian ntflag++;
1394bfd817adSflorian code = ntflag;
1395bfd817adSflorian (void)strlcpy(ntin, argv[1], sizeof(ntin));
1396bfd817adSflorian if (argc == 2) {
1397bfd817adSflorian ntout[0] = '\0';
1398bfd817adSflorian return;
1399bfd817adSflorian }
1400bfd817adSflorian (void)strlcpy(ntout, argv[2], sizeof(ntout));
1401bfd817adSflorian }
1402bfd817adSflorian
1403bfd817adSflorian void
setnmap(int argc,char * argv[])1404bfd817adSflorian setnmap(int argc, char *argv[])
1405bfd817adSflorian {
1406bfd817adSflorian char *cp;
1407bfd817adSflorian
1408bfd817adSflorian if (argc == 1) {
1409bfd817adSflorian mapflag = 0;
1410bfd817adSflorian fputs("Nmap off.\n", ttyout);
1411bfd817adSflorian code = mapflag;
1412bfd817adSflorian return;
1413bfd817adSflorian }
1414bfd817adSflorian if ((argc < 3 && !another(&argc, &argv, "outpattern")) || argc > 3) {
1415bfd817adSflorian fprintf(ttyout, "usage: %s [inpattern outpattern]\n", argv[0]);
1416bfd817adSflorian code = -1;
1417bfd817adSflorian return;
1418bfd817adSflorian }
1419bfd817adSflorian mapflag = 1;
1420bfd817adSflorian code = 1;
1421bfd817adSflorian cp = strchr(altarg, ' ');
1422bfd817adSflorian if (proxy) {
1423bfd817adSflorian while(*++cp == ' ')
1424bfd817adSflorian continue;
1425bfd817adSflorian altarg = cp;
1426bfd817adSflorian cp = strchr(altarg, ' ');
1427bfd817adSflorian }
1428bfd817adSflorian *cp = '\0';
1429bfd817adSflorian (void)strncpy(mapin, altarg, PATH_MAX - 1);
1430bfd817adSflorian while (*++cp == ' ')
1431bfd817adSflorian continue;
1432bfd817adSflorian (void)strncpy(mapout, cp, PATH_MAX - 1);
1433bfd817adSflorian }
1434bfd817adSflorian
1435bfd817adSflorian void
setpassive(int argc,char * argv[])1436bfd817adSflorian setpassive(int argc, char *argv[])
1437bfd817adSflorian {
1438bfd817adSflorian
1439bfd817adSflorian code = togglevar(argc, argv, &passivemode,
1440bfd817adSflorian verbose ? "Passive mode" : NULL);
1441bfd817adSflorian }
1442bfd817adSflorian
1443bfd817adSflorian void
setsunique(int argc,char * argv[])1444bfd817adSflorian setsunique(int argc, char *argv[])
1445bfd817adSflorian {
1446bfd817adSflorian
1447bfd817adSflorian code = togglevar(argc, argv, &sunique, "Store unique");
1448bfd817adSflorian }
1449bfd817adSflorian
1450bfd817adSflorian void
setrunique(int argc,char * argv[])1451bfd817adSflorian setrunique(int argc, char *argv[])
1452bfd817adSflorian {
1453bfd817adSflorian
1454bfd817adSflorian code = togglevar(argc, argv, &runique, "Receive unique");
1455bfd817adSflorian }
1456bfd817adSflorian
1457bfd817adSflorian /* change directory to parent directory */
1458bfd817adSflorian void
cdup(int argc,char * argv[])1459bfd817adSflorian cdup(int argc, char *argv[])
1460bfd817adSflorian {
1461bfd817adSflorian int r;
1462bfd817adSflorian
1463bfd817adSflorian r = command("CDUP");
1464bfd817adSflorian if (r == ERROR && code == 500) {
1465bfd817adSflorian if (verbose)
1466bfd817adSflorian fputs("CDUP command not recognized, trying XCUP.\n", ttyout);
1467bfd817adSflorian r = command("XCUP");
1468bfd817adSflorian }
1469bfd817adSflorian if (r == COMPLETE)
1470bfd817adSflorian dirchange = 1;
1471bfd817adSflorian }
1472bfd817adSflorian
1473bfd817adSflorian /*
1474bfd817adSflorian * Restart transfer at specific point
1475bfd817adSflorian */
1476bfd817adSflorian void
restart(int argc,char * argv[])1477bfd817adSflorian restart(int argc, char *argv[])
1478bfd817adSflorian {
1479bfd817adSflorian off_t nrestart_point;
1480bfd817adSflorian char *ep;
1481bfd817adSflorian
1482bfd817adSflorian if (argc != 2)
1483bfd817adSflorian fputs("restart: offset not specified.\n", ttyout);
1484bfd817adSflorian else {
1485bfd817adSflorian nrestart_point = strtoll(argv[1], &ep, 10);
1486bfd817adSflorian if (nrestart_point == LLONG_MAX || *ep != '\0')
1487bfd817adSflorian fputs("restart: invalid offset.\n", ttyout);
1488bfd817adSflorian else {
1489bfd817adSflorian fprintf(ttyout, "Restarting at %lld. Execute get, put "
1490bfd817adSflorian "or append to initiate transfer\n",
1491bfd817adSflorian (long long)nrestart_point);
1492bfd817adSflorian restart_point = nrestart_point;
1493bfd817adSflorian }
1494bfd817adSflorian }
1495bfd817adSflorian }
1496bfd817adSflorian
1497bfd817adSflorian /*
1498bfd817adSflorian * Show remote system type
1499bfd817adSflorian */
1500bfd817adSflorian void
syst(int argc,char * argv[])1501bfd817adSflorian syst(int argc, char *argv[])
1502bfd817adSflorian {
1503bfd817adSflorian
1504bfd817adSflorian (void)command("SYST");
1505bfd817adSflorian }
1506bfd817adSflorian
1507bfd817adSflorian void
macdef(int argc,char * argv[])1508bfd817adSflorian macdef(int argc, char *argv[])
1509bfd817adSflorian {
1510bfd817adSflorian char *tmp;
1511bfd817adSflorian int c;
1512bfd817adSflorian
1513bfd817adSflorian if (macnum == 16) {
1514bfd817adSflorian fputs("Limit of 16 macros have already been defined.\n", ttyout);
1515bfd817adSflorian code = -1;
1516bfd817adSflorian return;
1517bfd817adSflorian }
1518bfd817adSflorian if ((argc < 2 && !another(&argc, &argv, "macro-name")) || argc > 2) {
1519bfd817adSflorian fprintf(ttyout, "usage: %s macro-name\n", argv[0]);
1520bfd817adSflorian code = -1;
1521bfd817adSflorian return;
1522bfd817adSflorian }
1523bfd817adSflorian if (interactive)
1524bfd817adSflorian fputs(
1525bfd817adSflorian "Enter macro line by line, terminating it with a null line.\n", ttyout);
1526bfd817adSflorian (void)strlcpy(macros[macnum].mac_name, argv[1],
1527bfd817adSflorian sizeof(macros[macnum].mac_name));
1528bfd817adSflorian if (macnum == 0)
1529bfd817adSflorian macros[macnum].mac_start = macbuf;
1530bfd817adSflorian else
1531bfd817adSflorian macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
1532bfd817adSflorian tmp = macros[macnum].mac_start;
1533bfd817adSflorian while (tmp != macbuf+4096) {
1534bfd817adSflorian if ((c = getchar()) == EOF) {
1535bfd817adSflorian fputs("macdef: end of file encountered.\n", ttyout);
1536bfd817adSflorian code = -1;
1537bfd817adSflorian return;
1538bfd817adSflorian }
1539bfd817adSflorian if ((*tmp = c) == '\n') {
1540bfd817adSflorian if (tmp == macros[macnum].mac_start) {
1541bfd817adSflorian macros[macnum++].mac_end = tmp;
1542bfd817adSflorian code = 0;
1543bfd817adSflorian return;
1544bfd817adSflorian }
1545bfd817adSflorian if (*(tmp-1) == '\0') {
1546bfd817adSflorian macros[macnum++].mac_end = tmp - 1;
1547bfd817adSflorian code = 0;
1548bfd817adSflorian return;
1549bfd817adSflorian }
1550bfd817adSflorian *tmp = '\0';
1551bfd817adSflorian }
1552bfd817adSflorian tmp++;
1553bfd817adSflorian }
1554bfd817adSflorian while (1) {
1555bfd817adSflorian while ((c = getchar()) != '\n' && c != EOF)
1556bfd817adSflorian /* LOOP */;
1557bfd817adSflorian if (c == EOF || getchar() == '\n') {
1558bfd817adSflorian fputs("Macro not defined - 4K buffer exceeded.\n", ttyout);
1559bfd817adSflorian code = -1;
1560bfd817adSflorian return;
1561bfd817adSflorian }
1562bfd817adSflorian }
1563bfd817adSflorian }
1564bfd817adSflorian
1565bfd817adSflorian /*
1566bfd817adSflorian * Get size of file on remote machine
1567bfd817adSflorian */
1568bfd817adSflorian void
sizecmd(int argc,char * argv[])1569bfd817adSflorian sizecmd(int argc, char *argv[])
1570bfd817adSflorian {
1571bfd817adSflorian off_t size;
1572bfd817adSflorian
1573bfd817adSflorian if ((argc < 2 && !another(&argc, &argv, "file")) || argc > 2) {
1574bfd817adSflorian fprintf(ttyout, "usage: %s file\n", argv[0]);
1575bfd817adSflorian code = -1;
1576bfd817adSflorian return;
1577bfd817adSflorian }
1578bfd817adSflorian size = remotesize(argv[1], 1);
1579bfd817adSflorian if (size != -1)
1580bfd817adSflorian fprintf(ttyout, "%s\t%lld\n", argv[1], (long long)size);
1581bfd817adSflorian code = size;
1582bfd817adSflorian }
1583bfd817adSflorian
1584bfd817adSflorian /*
1585bfd817adSflorian * Get last modification time of file on remote machine
1586bfd817adSflorian */
1587bfd817adSflorian void
modtime(int argc,char * argv[])1588bfd817adSflorian modtime(int argc, char *argv[])
1589bfd817adSflorian {
1590bfd817adSflorian time_t mtime;
1591bfd817adSflorian
1592bfd817adSflorian if ((argc < 2 && !another(&argc, &argv, "file")) || argc > 2) {
1593bfd817adSflorian fprintf(ttyout, "usage: %s file\n", argv[0]);
1594bfd817adSflorian code = -1;
1595bfd817adSflorian return;
1596bfd817adSflorian }
1597bfd817adSflorian mtime = remotemodtime(argv[1], 1);
1598bfd817adSflorian if (mtime != -1)
1599bfd817adSflorian fprintf(ttyout, "%s\t%s", argv[1], asctime(localtime(&mtime)));
1600bfd817adSflorian code = mtime;
1601bfd817adSflorian }
1602bfd817adSflorian
1603bfd817adSflorian /*
1604bfd817adSflorian * Show status on remote machine
1605bfd817adSflorian */
1606bfd817adSflorian void
rmtstatus(int argc,char * argv[])1607bfd817adSflorian rmtstatus(int argc, char *argv[])
1608bfd817adSflorian {
1609bfd817adSflorian
1610bfd817adSflorian (void)command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
1611bfd817adSflorian }
1612bfd817adSflorian
1613bfd817adSflorian /*
1614bfd817adSflorian * Get file if modtime is more recent than current file
1615bfd817adSflorian */
1616bfd817adSflorian void
newer(int argc,char * argv[])1617bfd817adSflorian newer(int argc, char *argv[])
1618bfd817adSflorian {
1619bfd817adSflorian
1620bfd817adSflorian (void)getit(argc, argv, -1, "w");
1621bfd817adSflorian }
1622bfd817adSflorian
1623bfd817adSflorian /*
1624bfd817adSflorian * Display one file through $PAGER (defaults to "more").
1625bfd817adSflorian */
1626bfd817adSflorian void
page(int argc,char * argv[])1627bfd817adSflorian page(int argc, char *argv[])
1628bfd817adSflorian {
1629bfd817adSflorian off_t orestart_point;
1630bfd817adSflorian int ohash, overbose;
1631bfd817adSflorian char *p, *pager, *oldargv1;
1632bfd817adSflorian
1633bfd817adSflorian if ((argc < 2 && !another(&argc, &argv, "file")) || argc > 2) {
1634bfd817adSflorian fprintf(ttyout, "usage: %s file\n", argv[0]);
1635bfd817adSflorian code = -1;
1636bfd817adSflorian return;
1637bfd817adSflorian }
1638bfd817adSflorian oldargv1 = argv[1];
1639bfd817adSflorian if (!globulize(&argv[1])) {
1640bfd817adSflorian code = -1;
1641bfd817adSflorian return;
1642bfd817adSflorian }
1643bfd817adSflorian p = getenv("PAGER");
1644bfd817adSflorian if (p == NULL || (*p == '\0'))
1645bfd817adSflorian p = PAGER;
1646bfd817adSflorian if (asprintf(&pager, "|%s", p) == -1)
1647bfd817adSflorian errx(1, "Can't allocate memory for $PAGER");
1648bfd817adSflorian
1649bfd817adSflorian orestart_point = restart_point;
1650bfd817adSflorian ohash = hash;
1651bfd817adSflorian overbose = verbose;
1652bfd817adSflorian restart_point = hash = verbose = 0;
1653bfd817adSflorian recvrequest("RETR", pager, argv[1], "r+w", 1, 0);
1654bfd817adSflorian (void)free(pager);
1655bfd817adSflorian restart_point = orestart_point;
1656bfd817adSflorian hash = ohash;
1657bfd817adSflorian verbose = overbose;
1658bfd817adSflorian if (oldargv1 != argv[1]) /* free up after globulize() */
1659bfd817adSflorian free(argv[1]);
1660bfd817adSflorian }
1661bfd817adSflorian
1662bfd817adSflorian #endif /* !SMALL */
1663bfd817adSflorian
1664