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