Annotation of src/usr.bin/ftp/cmds.c, Revision 1.80
1.80 ! tb 1: /* $OpenBSD: cmds.c,v 1.79 2017/01/21 08:33:07 krw 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.
1.79 krw 7: *
1.32 itojun 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.
1.79 krw 19: *
1.32 itojun 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: {
1.79 krw 146:
1.62 martynas 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) {
1.75 mmcc 282: while (*tp && !islower((unsigned char)*tp)) {
1.1 deraadt 283: tp++;
284: }
285: if (!*tp) {
286: tp = cp;
287: tp2 = tmpbuf;
1.21 millert 288: while ((*tp2 = *tp) != '\0') {
1.75 mmcc 289: if (isupper((unsigned char)*tp2)) {
1.23 millert 290: *tp2 =
1.75 mmcc 291: tolower((unsigned char)*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) {
1.80 ! tb 990: (void)closefrom(3);
1.14 millert 991: (void)signal(SIGINT, SIG_DFL);
992: (void)signal(SIGQUIT, SIG_DFL);
1.51 ray 993: shellp = getenv("SHELL");
994: if (shellp == NULL || *shellp == '\0')
995: shellp = _PATH_BSHELL;
996: namep = strrchr(shellp, '/');
1.1 deraadt 997: if (namep == NULL)
1.51 ray 998: namep = shellp;
1.13 millert 999: shellnam[0] = '-';
1.36 lebel 1000: (void)strlcpy(shellnam + 1, ++namep, sizeof(shellnam) - 1);
1.1 deraadt 1001: if (strcmp(namep, "sh") != 0)
1002: shellnam[0] = '+';
1003: if (debug) {
1.51 ray 1004: fputs(shellp, ttyout);
1.21 millert 1005: fputc('\n', ttyout);
1.20 deraadt 1006: (void)fflush(ttyout);
1.1 deraadt 1007: }
1008: if (argc > 1) {
1.76 krw 1009: execl(shellp, shellnam, "-c", altarg, (char *)NULL);
1.1 deraadt 1010: }
1011: else {
1.76 krw 1012: execl(shellp, shellnam, (char *)NULL);
1.1 deraadt 1013: }
1.51 ray 1014: warn("%s", shellp);
1.1 deraadt 1015: code = -1;
1016: exit(1);
1017: }
1018: if (pid > 0)
1.24 millert 1019: while (wait(&wait_status) != pid)
1.1 deraadt 1020: ;
1.14 millert 1021: (void)signal(SIGINT, old1);
1022: (void)signal(SIGQUIT, old2);
1.1 deraadt 1023: if (pid == -1) {
1.16 millert 1024: warn("Try again later");
1.1 deraadt 1025: code = -1;
1026: }
1027: else {
1028: code = 0;
1029: }
1030: }
1031:
1032: /*
1033: * Send new user information (re-login)
1034: */
1035: void
1.47 deraadt 1036: user(int argc, char *argv[])
1.1 deraadt 1037: {
1.51 ray 1038: char acctname[80];
1.1 deraadt 1039: int n, aflag = 0;
1040:
1041: if (argc < 2)
1.14 millert 1042: (void)another(&argc, &argv, "username");
1.1 deraadt 1043: if (argc < 2 || argc > 4) {
1.64 sobrado 1044: fprintf(ttyout, "usage: %s username [password [account]]\n",
1045: argv[0]);
1.1 deraadt 1046: code = -1;
1047: return;
1048: }
1049: n = command("USER %s", argv[1]);
1050: if (n == CONTINUE) {
1051: if (argc < 3 )
1.56 millert 1052: argv[2] = getpass("Password:"), argc++;
1.1 deraadt 1053: n = command("PASS %s", argv[2]);
1054: }
1055: if (n == CONTINUE) {
1056: if (argc < 4) {
1.20 deraadt 1057: (void)fputs("Account: ", ttyout);
1058: (void)fflush(ttyout);
1.59 martynas 1059: if (fgets(acctname, sizeof(acctname), stdin) == NULL) {
1060: clearerr(stdin);
1.53 ray 1061: goto fail;
1.59 martynas 1062: }
1.57 gilles 1063:
1064: acctname[strcspn(acctname, "\n")] = '\0';
1065:
1.51 ray 1066: argv[3] = acctname;
1067: argc++;
1.1 deraadt 1068: }
1069: n = command("ACCT %s", argv[3]);
1070: aflag++;
1071: }
1072: if (n != COMPLETE) {
1.53 ray 1073: fail:
1.20 deraadt 1074: fputs("Login failed.\n", ttyout);
1.1 deraadt 1075: return;
1076: }
1077: if (!aflag && argc == 4) {
1.14 millert 1078: (void)command("ACCT %s", argv[3]);
1.1 deraadt 1079: }
1.19 millert 1080: connected = -1;
1.1 deraadt 1081: }
1082:
1083: /*
1.13 millert 1084: * Print working directory on remote machine.
1.1 deraadt 1085: */
1.48 deraadt 1086: /*ARGSUSED*/
1.1 deraadt 1087: void
1.47 deraadt 1088: pwd(int argc, char *argv[])
1.1 deraadt 1089: {
1090: int oldverbose = verbose;
1091:
1092: /*
1093: * If we aren't verbose, this doesn't do anything!
1094: */
1095: verbose = 1;
1096: if (command("PWD") == ERROR && code == 500) {
1.20 deraadt 1097: fputs("PWD command not recognized, trying XPWD.\n", ttyout);
1.14 millert 1098: (void)command("XPWD");
1.1 deraadt 1099: }
1100: verbose = oldverbose;
1101: }
1102:
1103: /*
1.13 millert 1104: * Print working directory on local machine.
1105: */
1.48 deraadt 1106: /* ARGSUSED */
1.13 millert 1107: void
1.47 deraadt 1108: lpwd(int argc, char *argv[])
1.13 millert 1109: {
1.73 deraadt 1110: char buf[PATH_MAX];
1.13 millert 1111:
1112: if (getcwd(buf, sizeof(buf)) != NULL)
1.20 deraadt 1113: fprintf(ttyout, "Local directory %s\n", buf);
1.13 millert 1114: else
1115: warn("getcwd");
1116: code = 0;
1117: }
1118:
1119: /*
1.1 deraadt 1120: * Make a directory.
1121: */
1122: void
1.47 deraadt 1123: makedir(int argc, char *argv[])
1.1 deraadt 1124: {
1125:
1.13 millert 1126: if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1127: argc > 2) {
1.20 deraadt 1128: fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1.1 deraadt 1129: code = -1;
1130: return;
1131: }
1132: if (command("MKD %s", argv[1]) == ERROR && code == 500) {
1133: if (verbose)
1.20 deraadt 1134: fputs("MKD command not recognized, trying XMKD.\n", ttyout);
1.14 millert 1135: (void)command("XMKD %s", argv[1]);
1.1 deraadt 1136: }
1137: }
1138:
1139: /*
1140: * Remove a directory.
1141: */
1142: void
1.47 deraadt 1143: removedir(int argc, char *argv[])
1.1 deraadt 1144: {
1145:
1.13 millert 1146: if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1147: argc > 2) {
1.20 deraadt 1148: fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1.1 deraadt 1149: code = -1;
1150: return;
1151: }
1152: if (command("RMD %s", argv[1]) == ERROR && code == 500) {
1153: if (verbose)
1.20 deraadt 1154: fputs("RMD command not recognized, trying XRMD.\n", ttyout);
1.14 millert 1155: (void)command("XRMD %s", argv[1]);
1.1 deraadt 1156: }
1157: }
1158:
1159: /*
1160: * Send a line, verbatim, to the remote machine.
1161: */
1162: void
1.47 deraadt 1163: quote(int argc, char *argv[])
1.1 deraadt 1164: {
1165:
1166: if (argc < 2 && !another(&argc, &argv, "command line to send")) {
1.64 sobrado 1167: fprintf(ttyout, "usage: %s arg ...\n", argv[0]);
1.1 deraadt 1168: code = -1;
1169: return;
1170: }
1171: quote1("", argc, argv);
1172: }
1173:
1174: /*
1175: * Send a SITE command to the remote machine. The line
1176: * is sent verbatim to the remote machine, except that the
1177: * word "SITE" is added at the front.
1178: */
1179: void
1.47 deraadt 1180: site(int argc, char *argv[])
1.1 deraadt 1181: {
1182:
1183: if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) {
1.64 sobrado 1184: fprintf(ttyout, "usage: %s arg ...\n", argv[0]);
1.1 deraadt 1185: code = -1;
1186: return;
1187: }
1.26 weingart 1188: quote1("SITE", argc, argv);
1.1 deraadt 1189: }
1190:
1191: /*
1192: * Turn argv[1..argc) into a space-separated string, then prepend initial text.
1193: * Send the result as a one-line command and get response.
1194: */
1195: void
1.47 deraadt 1196: quote1(const char *initial, int argc, char *argv[])
1.1 deraadt 1197: {
1198: int i, len;
1199: char buf[BUFSIZ]; /* must be >= sizeof(line) */
1200:
1.36 lebel 1201: (void)strlcpy(buf, initial, sizeof(buf));
1.1 deraadt 1202: if (argc > 1) {
1.26 weingart 1203: for (i = 1, len = strlen(buf); i < argc && len < sizeof(buf)-1; i++) {
1204: /* Space for next arg */
1205: if (len > 1)
1206: buf[len++] = ' ';
1207:
1208: /* Sanity check */
1209: if (len >= sizeof(buf) - 1)
1210: break;
1211:
1.27 millert 1212: /* Copy next argument, NUL terminate always */
1.36 lebel 1213: strlcpy(&buf[len], argv[i], sizeof(buf) - len);
1.26 weingart 1214:
1215: /* Update string length */
1216: len = strlen(buf);
1.1 deraadt 1217: }
1218: }
1.26 weingart 1219:
1.35 aaron 1220: /* Make double (triple?) sure the sucker is NUL terminated */
1.26 weingart 1221: buf[sizeof(buf) - 1] = '\0';
1222:
1.29 deraadt 1223: if (command("%s", buf) == PRELIM) {
1.1 deraadt 1224: while (getreply(0) == PRELIM)
1225: continue;
1226: }
1227: }
1228:
1229: void
1.47 deraadt 1230: do_chmod(int argc, char *argv[])
1.1 deraadt 1231: {
1232:
1233: if (argc < 2 && !another(&argc, &argv, "mode"))
1234: goto usage;
1.64 sobrado 1235: if ((argc < 3 && !another(&argc, &argv, "file")) || argc > 3) {
1.1 deraadt 1236: usage:
1.64 sobrado 1237: fprintf(ttyout, "usage: %s mode file\n", argv[0]);
1.1 deraadt 1238: code = -1;
1239: return;
1240: }
1.14 millert 1241: (void)command("SITE CHMOD %s %s", argv[1], argv[2]);
1.1 deraadt 1242: }
1243:
1244: void
1.47 deraadt 1245: do_umask(int argc, char *argv[])
1.1 deraadt 1246: {
1247: int oldverbose = verbose;
1248:
1249: verbose = 1;
1.14 millert 1250: (void)command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
1.1 deraadt 1251: verbose = oldverbose;
1252: }
1253:
1254: void
1.47 deraadt 1255: idle(int argc, char *argv[])
1.1 deraadt 1256: {
1257: int oldverbose = verbose;
1258:
1259: verbose = 1;
1.14 millert 1260: (void)command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
1.1 deraadt 1261: verbose = oldverbose;
1262: }
1263:
1264: /*
1265: * Ask the other side for help.
1266: */
1267: void
1.47 deraadt 1268: rmthelp(int argc, char *argv[])
1.1 deraadt 1269: {
1270: int oldverbose = verbose;
1271:
1272: verbose = 1;
1.14 millert 1273: (void)command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
1.1 deraadt 1274: verbose = oldverbose;
1275: }
1276:
1277: /*
1278: * Terminate session and exit.
1279: */
1.48 deraadt 1280: /*ARGSUSED*/
1.1 deraadt 1281: void
1.47 deraadt 1282: quit(int argc, char *argv[])
1.1 deraadt 1283: {
1284:
1285: if (connected)
1286: disconnect(0, 0);
1287: pswitch(1);
1288: if (connected) {
1289: disconnect(0, 0);
1290: }
1291: exit(0);
1292: }
1293:
1294: void
1.47 deraadt 1295: account(int argc, char *argv[])
1.1 deraadt 1296: {
1.13 millert 1297: char *ap;
1.1 deraadt 1298:
1.13 millert 1299: if (argc > 2) {
1.20 deraadt 1300: fprintf(ttyout, "usage: %s [password]\n", argv[0]);
1.13 millert 1301: code = -1;
1302: return;
1.1 deraadt 1303: }
1.13 millert 1304: else if (argc == 2)
1305: ap = argv[1];
1306: else
1.1 deraadt 1307: ap = getpass("Account:");
1.14 millert 1308: (void)command("ACCT %s", ap);
1.1 deraadt 1309: }
1310:
1311: jmp_buf abortprox;
1312:
1.48 deraadt 1313: /* ARGSUSED */
1.1 deraadt 1314: void
1.48 deraadt 1315: proxabort(int signo)
1.1 deraadt 1316: {
1.72 deraadt 1317: int save_errno = errno;
1.1 deraadt 1318:
1.13 millert 1319: alarmtimer(0);
1.1 deraadt 1320: if (!proxy) {
1321: pswitch(1);
1322: }
1323: if (connected) {
1324: proxflag = 1;
1325: }
1326: else {
1327: proxflag = 0;
1328: }
1329: pswitch(0);
1.72 deraadt 1330: errno = save_errno;
1.13 millert 1331: longjmp(abortprox, 1);
1.1 deraadt 1332: }
1333:
1334: void
1.47 deraadt 1335: doproxy(int argc, char *argv[])
1.1 deraadt 1336: {
1337: struct cmd *c;
1.13 millert 1338: int cmdpos;
1.1 deraadt 1339: sig_t oldintr;
1340:
1341: if (argc < 2 && !another(&argc, &argv, "command")) {
1.20 deraadt 1342: fprintf(ttyout, "usage: %s command\n", argv[0]);
1.1 deraadt 1343: code = -1;
1344: return;
1345: }
1346: c = getcmd(argv[1]);
1347: if (c == (struct cmd *) -1) {
1.20 deraadt 1348: fputs("?Ambiguous command.\n", ttyout);
1349: (void)fflush(ttyout);
1.1 deraadt 1350: code = -1;
1351: return;
1352: }
1353: if (c == 0) {
1.20 deraadt 1354: fputs("?Invalid command.\n", ttyout);
1355: (void)fflush(ttyout);
1.1 deraadt 1356: code = -1;
1357: return;
1358: }
1359: if (!c->c_proxy) {
1.20 deraadt 1360: fputs("?Invalid proxy command.\n", ttyout);
1361: (void)fflush(ttyout);
1.1 deraadt 1362: code = -1;
1363: return;
1364: }
1365: if (setjmp(abortprox)) {
1366: code = -1;
1367: return;
1368: }
1369: oldintr = signal(SIGINT, proxabort);
1370: pswitch(1);
1371: if (c->c_conn && !connected) {
1.20 deraadt 1372: fputs("Not connected.\n", ttyout);
1373: (void)fflush(ttyout);
1.1 deraadt 1374: pswitch(0);
1.14 millert 1375: (void)signal(SIGINT, oldintr);
1.1 deraadt 1376: code = -1;
1377: return;
1378: }
1.13 millert 1379: cmdpos = strcspn(line, " \t");
1380: if (cmdpos > 0) /* remove leading "proxy " from input buffer */
1381: memmove(line, line + cmdpos + 1, strlen(line) - cmdpos + 1);
1.1 deraadt 1382: (*c->c_handler)(argc-1, argv+1);
1383: if (connected) {
1384: proxflag = 1;
1385: }
1386: else {
1387: proxflag = 0;
1388: }
1389: pswitch(0);
1.14 millert 1390: (void)signal(SIGINT, oldintr);
1.1 deraadt 1391: }
1392:
1393: void
1.47 deraadt 1394: setcase(int argc, char *argv[])
1.1 deraadt 1395: {
1396:
1.13 millert 1397: code = togglevar(argc, argv, &mcase, "Case mapping");
1.1 deraadt 1398: }
1399:
1400: void
1.47 deraadt 1401: setcr(int argc, char *argv[])
1.1 deraadt 1402: {
1403:
1.13 millert 1404: code = togglevar(argc, argv, &crflag, "Carriage Return stripping");
1.1 deraadt 1405: }
1406:
1407: void
1.47 deraadt 1408: setntrans(int argc, char *argv[])
1.1 deraadt 1409: {
1410: if (argc == 1) {
1411: ntflag = 0;
1.20 deraadt 1412: fputs("Ntrans off.\n", ttyout);
1.1 deraadt 1413: code = ntflag;
1414: return;
1415: }
1416: ntflag++;
1417: code = ntflag;
1.36 lebel 1418: (void)strlcpy(ntin, argv[1], sizeof(ntin));
1.1 deraadt 1419: if (argc == 2) {
1420: ntout[0] = '\0';
1421: return;
1422: }
1.36 lebel 1423: (void)strlcpy(ntout, argv[2], sizeof(ntout));
1.1 deraadt 1424: }
1425:
1426: void
1.47 deraadt 1427: setnmap(int argc, char *argv[])
1.1 deraadt 1428: {
1429: char *cp;
1430:
1431: if (argc == 1) {
1432: mapflag = 0;
1.20 deraadt 1433: fputs("Nmap off.\n", ttyout);
1.1 deraadt 1434: code = mapflag;
1435: return;
1436: }
1.64 sobrado 1437: if ((argc < 3 && !another(&argc, &argv, "outpattern")) || argc > 3) {
1438: fprintf(ttyout, "usage: %s [inpattern outpattern]\n", argv[0]);
1.1 deraadt 1439: code = -1;
1440: return;
1441: }
1442: mapflag = 1;
1443: code = 1;
1444: cp = strchr(altarg, ' ');
1445: if (proxy) {
1446: while(*++cp == ' ')
1447: continue;
1448: altarg = cp;
1449: cp = strchr(altarg, ' ');
1450: }
1451: *cp = '\0';
1.73 deraadt 1452: (void)strncpy(mapin, altarg, PATH_MAX - 1);
1.1 deraadt 1453: while (*++cp == ' ')
1454: continue;
1.73 deraadt 1455: (void)strncpy(mapout, cp, PATH_MAX - 1);
1.1 deraadt 1456: }
1457:
1458: void
1.47 deraadt 1459: setpassive(int argc, char *argv[])
1.1 deraadt 1460: {
1461:
1.15 millert 1462: code = togglevar(argc, argv, &passivemode,
1463: verbose ? "Passive mode" : NULL);
1.1 deraadt 1464: }
1465:
1466: void
1.47 deraadt 1467: setsunique(int argc, char *argv[])
1.1 deraadt 1468: {
1469:
1.13 millert 1470: code = togglevar(argc, argv, &sunique, "Store unique");
1.1 deraadt 1471: }
1472:
1473: void
1.47 deraadt 1474: setrunique(int argc, char *argv[])
1.1 deraadt 1475: {
1476:
1.13 millert 1477: code = togglevar(argc, argv, &runique, "Receive unique");
1.1 deraadt 1478: }
1479:
1.13 millert 1480: /* change directory to parent directory */
1.48 deraadt 1481: /* ARGSUSED */
1.1 deraadt 1482: void
1.47 deraadt 1483: cdup(int argc, char *argv[])
1.1 deraadt 1484: {
1.13 millert 1485: int r;
1.1 deraadt 1486:
1.13 millert 1487: r = command("CDUP");
1488: if (r == ERROR && code == 500) {
1.1 deraadt 1489: if (verbose)
1.20 deraadt 1490: fputs("CDUP command not recognized, trying XCUP.\n", ttyout);
1.13 millert 1491: r = command("XCUP");
1.1 deraadt 1492: }
1.13 millert 1493: if (r == COMPLETE)
1494: dirchange = 1;
1.1 deraadt 1495: }
1496:
1.23 millert 1497: /*
1498: * Restart transfer at specific point
1499: */
1.1 deraadt 1500: void
1.47 deraadt 1501: restart(int argc, char *argv[])
1.1 deraadt 1502: {
1.78 guenther 1503: off_t nrestart_point;
1.27 millert 1504: char *ep;
1.1 deraadt 1505:
1506: if (argc != 2)
1.20 deraadt 1507: fputs("restart: offset not specified.\n", ttyout);
1.1 deraadt 1508: else {
1.78 guenther 1509: nrestart_point = strtoll(argv[1], &ep, 10);
1510: if (nrestart_point == LLONG_MAX || *ep != '\0')
1.27 millert 1511: fputs("restart: invalid offset.\n", ttyout);
1512: else {
1.39 millert 1513: fprintf(ttyout, "Restarting at %lld. Execute get, put "
1514: "or append to initiate transfer\n",
1.37 deraadt 1515: (long long)nrestart_point);
1.27 millert 1516: restart_point = nrestart_point;
1517: }
1.1 deraadt 1518: }
1519: }
1520:
1.79 krw 1521: /*
1.23 millert 1522: * Show remote system type
1523: */
1.48 deraadt 1524: /* ARGSUSED */
1.1 deraadt 1525: void
1.47 deraadt 1526: syst(int argc, char *argv[])
1.1 deraadt 1527: {
1528:
1.14 millert 1529: (void)command("SYST");
1.1 deraadt 1530: }
1531:
1532: void
1.47 deraadt 1533: macdef(int argc, char *argv[])
1.1 deraadt 1534: {
1535: char *tmp;
1536: int c;
1537:
1538: if (macnum == 16) {
1.20 deraadt 1539: fputs("Limit of 16 macros have already been defined.\n", ttyout);
1.1 deraadt 1540: code = -1;
1541: return;
1542: }
1.64 sobrado 1543: if ((argc < 2 && !another(&argc, &argv, "macro-name")) || argc > 2) {
1544: fprintf(ttyout, "usage: %s macro-name\n", argv[0]);
1.1 deraadt 1545: code = -1;
1546: return;
1547: }
1.16 millert 1548: if (interactive)
1.20 deraadt 1549: fputs(
1550: "Enter macro line by line, terminating it with a null line.\n", ttyout);
1.36 lebel 1551: (void)strlcpy(macros[macnum].mac_name, argv[1],
1552: sizeof(macros[macnum].mac_name));
1.14 millert 1553: if (macnum == 0)
1.1 deraadt 1554: macros[macnum].mac_start = macbuf;
1.14 millert 1555: else
1.1 deraadt 1556: macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
1557: tmp = macros[macnum].mac_start;
1558: while (tmp != macbuf+4096) {
1559: if ((c = getchar()) == EOF) {
1.20 deraadt 1560: fputs("macdef: end of file encountered.\n", ttyout);
1.1 deraadt 1561: code = -1;
1562: return;
1563: }
1564: if ((*tmp = c) == '\n') {
1565: if (tmp == macros[macnum].mac_start) {
1566: macros[macnum++].mac_end = tmp;
1567: code = 0;
1568: return;
1569: }
1570: if (*(tmp-1) == '\0') {
1571: macros[macnum++].mac_end = tmp - 1;
1572: code = 0;
1573: return;
1574: }
1575: *tmp = '\0';
1576: }
1577: tmp++;
1578: }
1579: while (1) {
1580: while ((c = getchar()) != '\n' && c != EOF)
1581: /* LOOP */;
1582: if (c == EOF || getchar() == '\n') {
1.20 deraadt 1583: fputs("Macro not defined - 4K buffer exceeded.\n", ttyout);
1.1 deraadt 1584: code = -1;
1585: return;
1586: }
1587: }
1588: }
1589:
1590: /*
1.23 millert 1591: * Get size of file on remote machine
1.1 deraadt 1592: */
1593: void
1.47 deraadt 1594: sizecmd(int argc, char *argv[])
1.1 deraadt 1595: {
1.13 millert 1596: off_t size;
1.1 deraadt 1597:
1.64 sobrado 1598: if ((argc < 2 && !another(&argc, &argv, "file")) || argc > 2) {
1599: fprintf(ttyout, "usage: %s file\n", argv[0]);
1.1 deraadt 1600: code = -1;
1601: return;
1602: }
1.13 millert 1603: size = remotesize(argv[1], 1);
1604: if (size != -1)
1.37 deraadt 1605: fprintf(ttyout, "%s\t%lld\n", argv[1], (long long)size);
1.13 millert 1606: code = size;
1.1 deraadt 1607: }
1608:
1609: /*
1.23 millert 1610: * Get last modification time of file on remote machine
1.1 deraadt 1611: */
1612: void
1.47 deraadt 1613: modtime(int argc, char *argv[])
1.1 deraadt 1614: {
1.13 millert 1615: time_t mtime;
1.1 deraadt 1616:
1.64 sobrado 1617: if ((argc < 2 && !another(&argc, &argv, "file")) || argc > 2) {
1618: fprintf(ttyout, "usage: %s file\n", argv[0]);
1.1 deraadt 1619: code = -1;
1620: return;
1621: }
1.13 millert 1622: mtime = remotemodtime(argv[1], 1);
1623: if (mtime != -1)
1.20 deraadt 1624: fprintf(ttyout, "%s\t%s", argv[1], asctime(localtime(&mtime)));
1.13 millert 1625: code = mtime;
1.1 deraadt 1626: }
1627:
1628: /*
1.23 millert 1629: * Show status on remote machine
1.1 deraadt 1630: */
1631: void
1.47 deraadt 1632: rmtstatus(int argc, char *argv[])
1.1 deraadt 1633: {
1634:
1.14 millert 1635: (void)command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
1.1 deraadt 1636: }
1637:
1638: /*
1.23 millert 1639: * Get file if modtime is more recent than current file
1.1 deraadt 1640: */
1641: void
1.47 deraadt 1642: newer(int argc, char *argv[])
1.1 deraadt 1643: {
1644:
1.77 krw 1645: (void)getit(argc, argv, -1, "w");
1.16 millert 1646: }
1647:
1648: /*
1649: * Display one file through $PAGER (defaults to "more").
1650: */
1651: void
1.47 deraadt 1652: page(int argc, char *argv[])
1.16 millert 1653: {
1.78 guenther 1654: off_t orestart_point;
1655: int ohash, overbose;
1.23 millert 1656: char *p, *pager, *oldargv1;
1.16 millert 1657:
1.64 sobrado 1658: if ((argc < 2 && !another(&argc, &argv, "file")) || argc > 2) {
1659: fprintf(ttyout, "usage: %s file\n", argv[0]);
1.16 millert 1660: code = -1;
1661: return;
1662: }
1.23 millert 1663: oldargv1 = argv[1];
1.16 millert 1664: if (!globulize(&argv[1])) {
1665: code = -1;
1666: return;
1667: }
1668: p = getenv("PAGER");
1.30 pjanzen 1669: if (p == NULL || (*p == '\0'))
1.16 millert 1670: p = PAGER;
1.44 deraadt 1671: if (asprintf(&pager, "|%s", p) == -1)
1.16 millert 1672: errx(1, "Can't allocate memory for $PAGER");
1673:
1674: orestart_point = restart_point;
1675: ohash = hash;
1676: overbose = verbose;
1677: restart_point = hash = verbose = 0;
1.23 millert 1678: recvrequest("RETR", pager, argv[1], "r+w", 1, 0);
1.16 millert 1679: (void)free(pager);
1680: restart_point = orestart_point;
1681: hash = ohash;
1682: verbose = overbose;
1.23 millert 1683: if (oldargv1 != argv[1]) /* free up after globulize() */
1684: free(argv[1]);
1.1 deraadt 1685: }
1.70 martynas 1686:
1687: #endif /* !SMALL */
1688: