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