Annotation of src/usr.bin/ftp/cmds.c, Revision 1.68
1.68 ! deraadt 1: /* $OpenBSD: cmds.c,v 1.67 2008/10/16 23:15:53 martynas Exp $ */
1.23 millert 2: /* $NetBSD: cmds.c,v 1.27 1997/08/18 10:20:15 lukem Exp $ */
1.1 deraadt 3:
4: /*
1.32 itojun 5: * Copyright (C) 1997 and 1998 WIDE Project.
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the project nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: /*
1.1 deraadt 34: * Copyright (c) 1985, 1989, 1993, 1994
35: * The Regents of the University of California. All rights reserved.
36: *
37: * Redistribution and use in source and binary forms, with or without
38: * modification, are permitted provided that the following conditions
39: * are met:
40: * 1. Redistributions of source code must retain the above copyright
41: * notice, this list of conditions and the following disclaimer.
42: * 2. Redistributions in binary form must reproduce the above copyright
43: * notice, this list of conditions and the following disclaimer in the
44: * documentation and/or other materials provided with the distribution.
1.45 millert 45: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 46: * may be used to endorse or promote products derived from this software
47: * without specific prior written permission.
48: *
49: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59: * SUCH DAMAGE.
60: */
61:
62: /*
63: * FTP User Program -- Command Routines.
64: */
1.13 millert 65: #include <sys/types.h>
66: #include <sys/socket.h>
67: #include <sys/stat.h>
1.1 deraadt 68: #include <sys/wait.h>
69: #include <arpa/ftp.h>
70:
71: #include <ctype.h>
72: #include <err.h>
1.63 martynas 73: #ifndef SMALL
74: #include <fnmatch.h>
75: #endif /* !SMALL */
1.1 deraadt 76: #include <glob.h>
77: #include <netdb.h>
78: #include <stdio.h>
79: #include <stdlib.h>
80: #include <string.h>
81: #include <unistd.h>
82:
83: #include "ftp_var.h"
84: #include "pathnames.h"
85:
86: jmp_buf jabort;
87: char *mname;
88: char *home = "/";
89:
90: struct types {
91: char *t_name;
92: char *t_mode;
93: int t_type;
94: char *t_arg;
95: } types[] = {
96: { "ascii", "A", TYPE_A, 0 },
97: { "binary", "I", TYPE_I, 0 },
98: { "image", "I", TYPE_I, 0 },
99: { "ebcdic", "E", TYPE_E, 0 },
100: { "tenex", "L", TYPE_L, bytename },
101: { NULL }
102: };
103:
104: /*
105: * Set transfer type.
106: */
107: void
1.47 deraadt 108: settype(int argc, char *argv[])
1.1 deraadt 109: {
110: struct types *p;
111: int comret;
112:
113: if (argc > 2) {
114: char *sep;
115:
1.20 deraadt 116: fprintf(ttyout, "usage: %s [", argv[0]);
1.64 sobrado 117: sep = "";
1.1 deraadt 118: for (p = types; p->t_name; p++) {
1.20 deraadt 119: fprintf(ttyout, "%s%s", sep, p->t_name);
1.1 deraadt 120: sep = " | ";
121: }
1.64 sobrado 122: fputs("]\n", ttyout);
1.1 deraadt 123: code = -1;
124: return;
125: }
126: if (argc < 2) {
1.20 deraadt 127: fprintf(ttyout, "Using %s mode to transfer files.\n", typename);
1.1 deraadt 128: code = 0;
129: return;
130: }
131: for (p = types; p->t_name; p++)
132: if (strcmp(argv[1], p->t_name) == 0)
133: break;
134: if (p->t_name == 0) {
1.20 deraadt 135: fprintf(ttyout, "%s: unknown mode.\n", argv[1]);
1.1 deraadt 136: code = -1;
137: return;
138: }
139: if ((p->t_arg != NULL) && (*(p->t_arg) != '\0'))
1.15 millert 140: comret = command("TYPE %s %s", p->t_mode, p->t_arg);
1.1 deraadt 141: else
142: comret = command("TYPE %s", p->t_mode);
143: if (comret == COMPLETE) {
1.44 deraadt 144: (void)strlcpy(typename, p->t_name, sizeof typename);
1.1 deraadt 145: curtype = type = p->t_type;
146: }
147: }
148:
149: /*
150: * Internal form of settype; changes current type in use with server
151: * without changing our notion of the type for data transfers.
152: * Used to change to and from ascii for listings.
153: */
154: void
1.47 deraadt 155: changetype(int newtype, int show)
1.1 deraadt 156: {
157: struct types *p;
158: int comret, oldverbose = verbose;
159:
160: if (newtype == 0)
161: newtype = TYPE_I;
162: if (newtype == curtype)
163: return;
1.63 martynas 164: if (
165: #ifndef SMALL
166: !debug &&
167: #endif /* !SMALL */
168: show == 0)
1.1 deraadt 169: verbose = 0;
170: for (p = types; p->t_name; p++)
171: if (newtype == p->t_type)
172: break;
173: if (p->t_name == 0) {
1.16 millert 174: warnx("internal error: unknown type %d.", newtype);
1.1 deraadt 175: return;
176: }
177: if (newtype == TYPE_L && bytename[0] != '\0')
178: comret = command("TYPE %s %s", p->t_mode, bytename);
179: else
180: comret = command("TYPE %s", p->t_mode);
181: if (comret == COMPLETE)
182: curtype = newtype;
183: verbose = oldverbose;
184: }
185:
186: char *stype[] = {
187: "type",
188: "",
189: 0
190: };
191:
192: /*
193: * Set binary transfer type.
194: */
1.48 deraadt 195: /*ARGSUSED*/
1.1 deraadt 196: void
1.47 deraadt 197: setbinary(int argc, char *argv[])
1.1 deraadt 198: {
199:
200: stype[1] = "binary";
201: settype(2, stype);
202: }
203:
204: /*
205: * Set ascii transfer type.
206: */
1.48 deraadt 207: /*ARGSUSED*/
1.1 deraadt 208: void
1.47 deraadt 209: setascii(int argc, char *argv[])
1.1 deraadt 210: {
211:
212: stype[1] = "ascii";
213: settype(2, stype);
214: }
215:
216: /*
217: * Set tenex transfer type.
218: */
1.48 deraadt 219: /*ARGSUSED*/
1.1 deraadt 220: void
1.47 deraadt 221: settenex(int argc, char *argv[])
1.1 deraadt 222: {
223:
224: stype[1] = "tenex";
225: settype(2, stype);
226: }
227:
228: /*
229: * Set file transfer mode.
230: */
231: /*ARGSUSED*/
232: void
1.47 deraadt 233: setftmode(int argc, char *argv[])
1.1 deraadt 234: {
235:
1.20 deraadt 236: fprintf(ttyout, "We only support %s mode, sorry.\n", modename);
1.1 deraadt 237: code = -1;
238: }
239:
240: /*
241: * Set file transfer format.
242: */
243: /*ARGSUSED*/
244: void
1.47 deraadt 245: setform(int argc, char *argv[])
1.1 deraadt 246: {
247:
1.20 deraadt 248: fprintf(ttyout, "We only support %s format, sorry.\n", formname);
1.1 deraadt 249: code = -1;
250: }
251:
252: /*
253: * Set file transfer structure.
254: */
255: /*ARGSUSED*/
256: void
1.47 deraadt 257: setstruct(int argc, char *argv[])
1.1 deraadt 258: {
259:
1.20 deraadt 260: fprintf(ttyout, "We only support %s structure, sorry.\n", structname);
1.1 deraadt 261: code = -1;
262: }
263:
1.62 martynas 264: #ifndef SMALL
265: void
266: reput(int argc, char *argv[])
267: {
268:
269: (void)putit(argc, argv, 1);
270: }
271: #endif /* !SMALL */
272:
273: void
274: put(int argc, char *argv[])
275: {
276:
277: (void)putit(argc, argv, 0);
278: }
279:
1.1 deraadt 280: /*
281: * Send a single file.
282: */
283: void
1.62 martynas 284: putit(int argc, char *argv[], int restartit)
1.1 deraadt 285: {
286: char *cmd;
287: int loc = 0;
288: char *oldargv1, *oldargv2;
289:
290: if (argc == 2) {
291: argc++;
292: argv[2] = argv[1];
293: loc++;
294: }
295: if (argc < 2 && !another(&argc, &argv, "local-file"))
296: goto usage;
1.13 millert 297: if ((argc < 3 && !another(&argc, &argv, "remote-file")) || argc > 3) {
1.1 deraadt 298: usage:
1.64 sobrado 299: fprintf(ttyout, "usage: %s local-file [remote-file]\n",
300: argv[0]);
1.1 deraadt 301: code = -1;
302: return;
303: }
304: oldargv1 = argv[1];
305: oldargv2 = argv[2];
306: if (!globulize(&argv[1])) {
307: code = -1;
308: return;
309: }
310: /*
311: * If "globulize" modifies argv[1], and argv[2] is a copy of
312: * the old argv[1], make it a copy of the new argv[1].
313: */
314: if (argv[1] != oldargv1 && argv[2] == oldargv1) {
315: argv[2] = argv[1];
316: }
1.62 martynas 317: #ifndef SMALL
318: if (restartit == 1) {
319: if (curtype != type)
320: changetype(type, 0);
321: restart_point = remotesize(argv[2], 1);
322: if (restart_point < 0) {
323: restart_point = 0;
324: code = -1;
325: return;
326: }
327: }
328: #endif /* !SMALL */
329: if (strcmp(argv[0], "append") == 0) {
330: restartit = 1;
331: }
332: cmd = restartit ? "APPE" : ((sunique) ? "STOU" : "STOR");
1.1 deraadt 333: if (loc && ntflag) {
334: argv[2] = dotrans(argv[2]);
335: }
336: if (loc && mapflag) {
337: argv[2] = domap(argv[2]);
338: }
339: sendrequest(cmd, argv[1], argv[2],
340: argv[1] != oldargv1 || argv[2] != oldargv2);
1.62 martynas 341: restart_point = 0;
1.23 millert 342: if (oldargv1 != argv[1]) /* free up after globulize() */
343: free(argv[1]);
1.1 deraadt 344: }
345:
346: /*
347: * Send multiple files.
348: */
349: void
1.47 deraadt 350: mput(int argc, char *argv[])
1.1 deraadt 351: {
1.62 martynas 352: extern int optind, optreset;
353: int ch, i, restartit = 0;
1.1 deraadt 354: sig_t oldintr;
1.62 martynas 355: char *cmd, *tp;
356:
357: optind = optreset = 1;
1.1 deraadt 358:
1.62 martynas 359: #ifndef SMALL
360: while ((ch = getopt(argc, argv, "c")) != -1) {
361: switch(ch) {
362: case 'c':
363: restartit = 1;
364: break;
365: default:
366: goto usage;
367: }
368: }
369: #endif /* !SMALL */
370:
371: if (argc - optind < 1 && !another(&argc, &argv, "local-files")) {
372: usage:
373: fprintf(ttyout, "usage: %s [-c] local-files\n", argv[0]);
1.1 deraadt 374: code = -1;
375: return;
376: }
1.62 martynas 377:
378: #ifndef SMALL
1.63 martynas 379: argv[optind - 1] = argv[0];
380: argc -= optind - 1;
381: argv += optind - 1;
1.62 martynas 382: #endif /* !SMALL */
383:
1.1 deraadt 384: mname = argv[0];
385: mflag = 1;
1.62 martynas 386:
1.1 deraadt 387: oldintr = signal(SIGINT, mabort);
1.14 millert 388: (void)setjmp(jabort);
1.1 deraadt 389: if (proxy) {
390: char *cp, *tp2, tmpbuf[MAXPATHLEN];
391:
1.16 millert 392: while ((cp = remglob(argv, 0, NULL)) != NULL) {
1.13 millert 393: if (*cp == '\0') {
1.1 deraadt 394: mflag = 0;
395: continue;
396: }
1.63 martynas 397: if (mflag && confirm(argv[0], cp)) {
1.1 deraadt 398: tp = cp;
399: if (mcase) {
400: while (*tp && !islower(*tp)) {
401: tp++;
402: }
403: if (!*tp) {
404: tp = cp;
405: tp2 = tmpbuf;
1.21 millert 406: while ((*tp2 = *tp) != '\0') {
1.1 deraadt 407: if (isupper(*tp2)) {
1.23 millert 408: *tp2 =
409: tolower(*tp2);
1.1 deraadt 410: }
411: tp++;
412: tp2++;
413: }
414: }
415: tp = tmpbuf;
416: }
417: if (ntflag) {
418: tp = dotrans(tp);
419: }
420: if (mapflag) {
421: tp = domap(tp);
422: }
1.62 martynas 423: #ifndef SMALL
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: #endif /* !SMALL */
433: cmd = restartit ? "APPE" : ((sunique) ?
434: "STOU" : "STOR");
435: sendrequest(cmd, cp, tp,
436: cp != tp || !interactive);
437: restart_point = 0;
1.1 deraadt 438: if (!mflag && fromatty) {
1.63 martynas 439: if (confirm(argv[0], NULL))
1.61 martynas 440: mflag = 1;
1.1 deraadt 441: }
442: }
443: }
1.14 millert 444: (void)signal(SIGINT, oldintr);
1.1 deraadt 445: mflag = 0;
446: return;
447: }
448: for (i = 1; i < argc; i++) {
1.13 millert 449: char **cpp;
1.1 deraadt 450: glob_t gl;
451: int flags;
452:
453: if (!doglob) {
1.63 martynas 454: if (mflag && confirm(argv[0], argv[i])) {
1.1 deraadt 455: tp = (ntflag) ? dotrans(argv[i]) : argv[i];
456: tp = (mapflag) ? domap(tp) : tp;
1.62 martynas 457: #ifndef SMALL
458: if (restartit == 1) {
459: off_t ret;
460:
461: if (curtype != type)
462: changetype(type, 0);
463: ret = remotesize(tp, 0);
464: restart_point = (ret < 0) ? 0 : ret;
465: }
466: #endif /* !SMALL */
467: cmd = restartit ? "APPE" : ((sunique) ?
468: "STOU" : "STOR");
469: sendrequest(cmd, argv[i], tp,
470: tp != argv[i] || !interactive);
471: restart_point = 0;
1.1 deraadt 472: if (!mflag && fromatty) {
1.63 martynas 473: if (confirm(argv[0], NULL))
1.61 martynas 474: mflag = 1;
1.1 deraadt 475: }
476: }
477: continue;
478: }
479:
480: memset(&gl, 0, sizeof(gl));
481: flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
482: if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) {
483: warnx("%s: not found", argv[i]);
484: globfree(&gl);
485: continue;
486: }
487: for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) {
1.63 martynas 488: if (mflag && confirm(argv[0], *cpp)) {
1.1 deraadt 489: tp = (ntflag) ? dotrans(*cpp) : *cpp;
490: tp = (mapflag) ? domap(tp) : tp;
1.62 martynas 491: #ifndef SMALL
492: if (restartit == 1) {
493: off_t ret;
494:
495: if (curtype != type)
496: changetype(type, 0);
497: ret = remotesize(tp, 0);
498: restart_point = (ret < 0) ? 0 : ret;
499: }
500: #endif /* !SMALL */
501: cmd = restartit ? "APPE" : ((sunique) ?
502: "STOU" : "STOR");
503: sendrequest(cmd, *cpp, tp,
504: *cpp != tp || !interactive);
505: restart_point = 0;
1.1 deraadt 506: if (!mflag && fromatty) {
1.63 martynas 507: if (confirm(argv[0], NULL))
1.61 martynas 508: mflag = 1;
1.1 deraadt 509: }
510: }
511: }
512: globfree(&gl);
513: }
1.14 millert 514: (void)signal(SIGINT, oldintr);
1.1 deraadt 515: mflag = 0;
516: }
517:
1.62 martynas 518: #ifndef SMALL
1.1 deraadt 519: void
1.47 deraadt 520: reget(int argc, char *argv[])
1.1 deraadt 521: {
522:
1.67 martynas 523: (void)getit(argc, argv, 1, "a+w");
1.1 deraadt 524: }
1.62 martynas 525: #endif /* !SMALL */
1.1 deraadt 526:
527: void
1.47 deraadt 528: get(int argc, char *argv[])
1.1 deraadt 529: {
530:
1.67 martynas 531: (void)getit(argc, argv, 0, restart_point ? "a+w" : "w" );
1.1 deraadt 532: }
533:
534: /*
535: * Receive one file.
536: */
537: int
1.47 deraadt 538: getit(int argc, char *argv[], int restartit, const char *mode)
1.1 deraadt 539: {
540: int loc = 0;
1.23 millert 541: int rval = 0;
542: char *oldargv1, *oldargv2, *globargv2;
1.1 deraadt 543:
544: if (argc == 2) {
545: argc++;
546: argv[2] = argv[1];
547: loc++;
548: }
549: if (argc < 2 && !another(&argc, &argv, "remote-file"))
550: goto usage;
1.13 millert 551: if ((argc < 3 && !another(&argc, &argv, "local-file")) || argc > 3) {
1.1 deraadt 552: usage:
1.64 sobrado 553: fprintf(ttyout, "usage: %s remote-file [local-file]\n",
554: argv[0]);
1.1 deraadt 555: code = -1;
556: return (0);
557: }
558: oldargv1 = argv[1];
559: oldargv2 = argv[2];
560: if (!globulize(&argv[2])) {
561: code = -1;
562: return (0);
563: }
1.23 millert 564: globargv2 = argv[2];
1.1 deraadt 565: if (loc && mcase) {
566: char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN];
567:
568: while (*tp && !islower(*tp)) {
569: tp++;
570: }
571: if (!*tp) {
572: tp = argv[2];
573: tp2 = tmpbuf;
1.21 millert 574: while ((*tp2 = *tp) != '\0') {
1.1 deraadt 575: if (isupper(*tp2)) {
1.23 millert 576: *tp2 = tolower(*tp2);
1.1 deraadt 577: }
578: tp++;
579: tp2++;
580: }
581: argv[2] = tmpbuf;
582: }
583: }
584: if (loc && ntflag)
585: argv[2] = dotrans(argv[2]);
586: if (loc && mapflag)
587: argv[2] = domap(argv[2]);
1.62 martynas 588: #ifndef SMALL
1.1 deraadt 589: if (restartit) {
590: struct stat stbuf;
591: int ret;
592:
593: ret = stat(argv[2], &stbuf);
594: if (restartit == 1) {
1.67 martynas 595: restart_point = (ret < 0) ? 0 : stbuf.st_size;
1.1 deraadt 596: } else {
597: if (ret == 0) {
1.13 millert 598: time_t mtime;
1.1 deraadt 599:
1.13 millert 600: mtime = remotemodtime(argv[1], 0);
601: if (mtime == -1)
1.23 millert 602: goto freegetit;
603: if (stbuf.st_mtime >= mtime) {
604: rval = 1;
605: goto freegetit;
606: }
1.1 deraadt 607: }
608: }
609: }
1.62 martynas 610: #endif /* !SMALL */
1.1 deraadt 611:
612: recvrequest("RETR", argv[2], argv[1], mode,
1.65 martynas 613: argv[1] != oldargv1 || argv[2] != oldargv2 || !interactive, loc);
1.1 deraadt 614: restart_point = 0;
1.23 millert 615: freegetit:
616: if (oldargv2 != globargv2) /* free up after globulize() */
617: free(globargv2);
618: return (rval);
1.1 deraadt 619: }
620:
1.55 ray 621: /* XXX - Signal race. */
1.1 deraadt 622: /* ARGSUSED */
623: void
1.47 deraadt 624: mabort(int signo)
1.1 deraadt 625: {
1.13 millert 626: alarmtimer(0);
1.20 deraadt 627: putc('\n', ttyout);
628: (void)fflush(ttyout);
1.60 martynas 629: if (mflag && fromatty)
1.63 martynas 630: if (confirm(mname, NULL))
1.40 art 631: longjmp(jabort, 1);
1.1 deraadt 632: mflag = 0;
1.40 art 633: longjmp(jabort, 1);
1.1 deraadt 634: }
635:
636: /*
637: * Get multiple files.
638: */
639: void
1.47 deraadt 640: mget(int argc, char *argv[])
1.1 deraadt 641: {
1.62 martynas 642: extern int optind, optreset;
1.1 deraadt 643: sig_t oldintr;
1.65 martynas 644: int ch, xargc = 2;
645: char *cp, localcwd[MAXPATHLEN], *xargv[] = {argv[0], NULL, NULL};
646: static int restartit = 0;
647: #ifndef SMALL
648: extern char *optarg;
1.66 todd 649: const char *errstr;
1.65 martynas 650: int i = 1;
651: char type = NULL, *dummyargv[] = {argv[0], ".", NULL};
1.63 martynas 652: FILE *ftemp = NULL;
1.65 martynas 653: static int depth = 0, max_depth = 0;
1.63 martynas 654: #endif /* !SMALL */
1.1 deraadt 655:
1.62 martynas 656: optind = optreset = 1;
657:
658: #ifndef SMALL
1.65 martynas 659:
660: if (depth)
661: depth++;
662:
663: while ((ch = getopt(argc, argv, "cd:nr")) != -1) {
1.62 martynas 664: switch(ch) {
665: case 'c':
666: restartit = 1;
667: break;
1.65 martynas 668: case 'd':
669: max_depth = strtonum(optarg, 0, INT_MAX, &errstr);
670: if (errstr != NULL) {
671: fprintf(ttyout, "bad depth value, %s: %s\n",
672: errstr, optarg);
673: code = -1;
674: return;
675: }
676: break;
677: case 'n':
678: restartit = -1;
679: break;
1.63 martynas 680: case 'r':
1.65 martynas 681: depth = 1;
1.63 martynas 682: break;
1.62 martynas 683: default:
684: goto usage;
685: }
686: }
687: #endif /* !SMALL */
688:
689: if (argc - optind < 1 && !another(&argc, &argv, "remote-files")) {
690: usage:
1.65 martynas 691: fprintf(ttyout, "usage: %s [-cnr] [-d depth] remote-files\n",
692: argv[0]);
1.1 deraadt 693: code = -1;
694: return;
695: }
1.62 martynas 696:
697: #ifndef SMALL
1.63 martynas 698: argv[optind - 1] = argv[0];
699: argc -= optind - 1;
700: argv += optind - 1;
1.62 martynas 701: #endif /* !SMALL */
702:
1.1 deraadt 703: mname = argv[0];
704: mflag = 1;
1.49 otto 705: if (getcwd(localcwd, sizeof(localcwd)) == NULL)
706: err(1, "can't get cwd");
707:
1.1 deraadt 708: oldintr = signal(SIGINT, mabort);
1.14 millert 709: (void)setjmp(jabort);
1.63 martynas 710: while ((cp =
711: #ifndef SMALL
1.65 martynas 712: depth ? remglob2(dummyargv, proxy, NULL, &ftemp, &type) :
1.63 martynas 713: #endif /* !SMALL */
714: remglob(argv, proxy, NULL)) != NULL
715: #ifndef SMALL
716: || (mflag && depth && ++i < argc)
717: #endif /* !SMALL */
718: ) {
719: #ifndef SMALL
720: if (cp == NULL)
721: continue;
722: #endif /* !SMALL */
1.1 deraadt 723: if (*cp == '\0') {
724: mflag = 0;
725: continue;
726: }
1.49 otto 727: if (!mflag)
728: continue;
1.63 martynas 729: #ifndef SMALL
730: if (depth && fnmatch(argv[i], cp, FNM_PATHNAME) != 0)
731: continue;
732: #endif /* !SMALL */
1.49 otto 733: if (!fileindir(cp, localcwd)) {
734: fprintf(ttyout, "Skipping non-relative filename `%s'\n",
735: cp);
736: continue;
737: }
1.65 martynas 738: #ifndef SMALL
739: if (type == 'd' && depth == max_depth)
740: continue;
741: #endif /* !SMALL */
1.63 martynas 742: if (confirm(argv[0], cp)) {
743: #ifndef SMALL
744: if (type == 'd') {
745: mkdir(cp, 0755);
746: if (chdir(cp) != 0) {
747: warn("local: %s", cp);
748: continue;
749: }
750:
751: xargv[1] = cp;
752: cd(xargc, xargv);
753: if (dirchange != 1)
754: goto out;
755:
1.65 martynas 756: xargv[1] = "*";
1.63 martynas 757: mget(xargc, xargv);
758:
759: xargv[1] = "..";
760: cd(xargc, xargv);
761: if (dirchange != 1) {
762: mflag = 0;
763: goto out;
764: }
765:
766: out:
767: if (chdir("..") != 0) {
768: warn("local: %s", cp);
769: mflag = 0;
770: }
771: continue;
772: }
773: if (type == 's')
774: /* Currently ignored. */
775: continue;
776: #endif /* !SMALL */
1.65 martynas 777: xargv[1] = cp;
778: (void)getit(xargc, xargv, restartit,
1.67 martynas 779: (restartit == 1 || restart_point) ? "a+w" : "w");
1.1 deraadt 780: if (!mflag && fromatty) {
1.63 martynas 781: if (confirm(argv[0], NULL))
1.61 martynas 782: mflag = 1;
1.1 deraadt 783: }
784: }
785: }
1.14 millert 786: (void)signal(SIGINT, oldintr);
1.63 martynas 787: #ifndef SMALL
788: if (depth)
789: depth--;
790: if (depth == 0 || mflag == 0)
1.65 martynas 791: depth = max_depth = mflag = restartit = 0;
1.63 martynas 792: #else /* !SMALL */
1.1 deraadt 793: mflag = 0;
1.63 martynas 794: #endif /* !SMALL */
1.1 deraadt 795: }
796:
797: char *
1.47 deraadt 798: onoff(int bool)
1.1 deraadt 799: {
800:
801: return (bool ? "on" : "off");
802: }
803:
804: /*
805: * Show status.
806: */
807: /*ARGSUSED*/
808: void
1.47 deraadt 809: status(int argc, char *argv[])
1.1 deraadt 810: {
811: int i;
812:
813: if (connected)
1.20 deraadt 814: fprintf(ttyout, "Connected %sto %s.\n",
1.19 millert 815: connected == -1 ? "and logged in" : "", hostname);
1.1 deraadt 816: else
1.20 deraadt 817: fputs("Not connected.\n", ttyout);
1.1 deraadt 818: if (!proxy) {
819: pswitch(1);
820: if (connected) {
1.20 deraadt 821: fprintf(ttyout, "Connected for proxy commands to %s.\n",
1.13 millert 822: hostname);
1.1 deraadt 823: }
824: else {
1.20 deraadt 825: fputs("No proxy connection.\n", ttyout);
1.1 deraadt 826: }
827: pswitch(0);
828: }
1.32 itojun 829: fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n", onoff(gatemode),
830: *gateserver ? gateserver : "(none)", gateport);
1.20 deraadt 831: fprintf(ttyout, "Passive mode: %s.\n", onoff(passivemode));
832: fprintf(ttyout, "Mode: %s; Type: %s; Form: %s; Structure: %s.\n",
1.1 deraadt 833: modename, typename, formname, structname);
1.20 deraadt 834: fprintf(ttyout, "Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s.\n",
1.1 deraadt 835: onoff(verbose), onoff(bell), onoff(interactive),
836: onoff(doglob));
1.20 deraadt 837: fprintf(ttyout, "Store unique: %s; Receive unique: %s.\n", onoff(sunique),
1.1 deraadt 838: onoff(runique));
1.20 deraadt 839: fprintf(ttyout, "Preserve modification times: %s.\n", onoff(preserve));
840: fprintf(ttyout, "Case: %s; CR stripping: %s.\n", onoff(mcase), onoff(crflag));
1.1 deraadt 841: if (ntflag) {
1.20 deraadt 842: fprintf(ttyout, "Ntrans: (in) %s (out) %s\n", ntin, ntout);
1.1 deraadt 843: }
844: else {
1.20 deraadt 845: fputs("Ntrans: off.\n", ttyout);
1.1 deraadt 846: }
847: if (mapflag) {
1.20 deraadt 848: fprintf(ttyout, "Nmap: (in) %s (out) %s\n", mapin, mapout);
1.1 deraadt 849: }
850: else {
1.20 deraadt 851: fputs("Nmap: off.\n", ttyout);
1.1 deraadt 852: }
1.20 deraadt 853: fprintf(ttyout, "Hash mark printing: %s; Mark count: %d; Progress bar: %s.\n",
1.13 millert 854: onoff(hash), mark, onoff(progress));
1.32 itojun 855: fprintf(ttyout, "Use of PORT/LPRT cmds: %s.\n", onoff(sendport));
1.34 itojun 856: fprintf(ttyout, "Use of EPSV/EPRT cmds for IPv4: %s%s.\n", onoff(epsv4),
857: epsv4bad ? " (disabled for this connection)" : "");
1.17 millert 858: #ifndef SMALL
1.20 deraadt 859: fprintf(ttyout, "Command line editing: %s.\n", onoff(editing));
1.17 millert 860: #endif /* !SMALL */
1.1 deraadt 861: if (macnum > 0) {
1.27 millert 862: fputs("Macros:\n", ttyout);
1.1 deraadt 863: for (i=0; i<macnum; i++) {
1.20 deraadt 864: fprintf(ttyout, "\t%s\n", macros[i].mac_name);
1.1 deraadt 865: }
866: }
867: code = 0;
868: }
869:
870: /*
1.13 millert 871: * Toggle a variable
872: */
873: int
1.47 deraadt 874: togglevar(int argc, char *argv[], int *var, const char *mesg)
1.13 millert 875: {
876: if (argc < 2) {
877: *var = !*var;
878: } else if (argc == 2 && strcasecmp(argv[1], "on") == 0) {
879: *var = 1;
880: } else if (argc == 2 && strcasecmp(argv[1], "off") == 0) {
881: *var = 0;
882: } else {
1.64 sobrado 883: fprintf(ttyout, "usage: %s [on | off]\n", argv[0]);
1.16 millert 884: return (-1);
1.13 millert 885: }
1.15 millert 886: if (mesg)
1.20 deraadt 887: fprintf(ttyout, "%s %s.\n", mesg, onoff(*var));
1.14 millert 888: return (*var);
1.13 millert 889: }
890:
891: /*
1.1 deraadt 892: * Set beep on cmd completed mode.
893: */
1.48 deraadt 894: /*ARGSUSED*/
1.1 deraadt 895: void
1.47 deraadt 896: setbell(int argc, char *argv[])
1.1 deraadt 897: {
898:
1.13 millert 899: code = togglevar(argc, argv, &bell, "Bell mode");
1.1 deraadt 900: }
901:
902: /*
1.13 millert 903: * Set command line editing
1.1 deraadt 904: */
1.63 martynas 905: #ifndef SMALL
1.48 deraadt 906: /*ARGSUSED*/
1.1 deraadt 907: void
1.47 deraadt 908: setedit(int argc, char *argv[])
1.1 deraadt 909: {
910:
1.13 millert 911: code = togglevar(argc, argv, &editing, "Editing mode");
1.18 millert 912: controlediting();
1.1 deraadt 913: }
1.17 millert 914: #endif /* !SMALL */
1.34 itojun 915:
916: /*
917: * Toggle use of IPv4 EPSV/EPRT
918: */
1.48 deraadt 919: /*ARGSUSED*/
1.34 itojun 920: void
1.47 deraadt 921: setepsv4(int argc, char *argv[])
1.34 itojun 922: {
923:
924: code = togglevar(argc, argv, &epsv4, "EPSV/EPRT on IPv4");
925: epsv4bad = 0;
926: }
1.1 deraadt 927:
928: /*
1.13 millert 929: * Turn on packet tracing.
1.1 deraadt 930: */
1.48 deraadt 931: /*ARGSUSED*/
1.1 deraadt 932: void
1.47 deraadt 933: settrace(int argc, char *argv[])
1.1 deraadt 934: {
935:
1.13 millert 936: code = togglevar(argc, argv, &trace, "Packet tracing");
1.1 deraadt 937: }
1.6 kstailey 938:
939: /*
1.13 millert 940: * Toggle hash mark printing during transfers, or set hash mark bytecount.
1.6 kstailey 941: */
1.48 deraadt 942: /*ARGSUSED*/
1.6 kstailey 943: void
1.47 deraadt 944: sethash(int argc, char *argv[])
1.6 kstailey 945: {
946: if (argc == 1)
1.13 millert 947: hash = !hash;
1.6 kstailey 948: else if (argc != 2) {
1.64 sobrado 949: fprintf(ttyout, "usage: %s [on | off | size]\n", argv[0]);
1.13 millert 950: code = -1;
951: return;
952: } else if (strcasecmp(argv[1], "on") == 0)
953: hash = 1;
954: else if (strcasecmp(argv[1], "off") == 0)
955: hash = 0;
956: else {
1.50 tedu 957: int nmark;
958: const char *errstr;
1.28 millert 959:
1.50 tedu 960: nmark = strtonum(argv[1], 1, INT_MAX, &errstr);
961: if (errstr) {
962: fprintf(ttyout, "bytecount value is %s: %s\n",
963: errstr, argv[1]);
1.13 millert 964: code = -1;
965: return;
1.6 kstailey 966: }
1.13 millert 967: mark = nmark;
968: hash = 1;
1.6 kstailey 969: }
1.20 deraadt 970: fprintf(ttyout, "Hash mark printing %s", onoff(hash));
1.13 millert 971: if (hash)
1.20 deraadt 972: fprintf(ttyout, " (%d bytes/hash mark)", mark);
973: fputs(".\n", ttyout);
1.13 millert 974: code = hash;
1.6 kstailey 975: }
976:
1.1 deraadt 977: /*
978: * Turn on printing of server echo's.
979: */
1.48 deraadt 980: /*ARGSUSED*/
1.1 deraadt 981: void
1.47 deraadt 982: setverbose(int argc, char *argv[])
1.1 deraadt 983: {
984:
1.13 millert 985: code = togglevar(argc, argv, &verbose, "Verbose mode");
1.1 deraadt 986: }
987:
988: /*
1.32 itojun 989: * Toggle PORT/LPRT cmd use before each data connection.
1.1 deraadt 990: */
1.48 deraadt 991: /*ARGSUSED*/
1.1 deraadt 992: void
1.47 deraadt 993: setport(int argc, char *argv[])
1.1 deraadt 994: {
995:
1.32 itojun 996: code = togglevar(argc, argv, &sendport, "Use of PORT/LPRT cmds");
1.13 millert 997: }
998:
999: /*
1000: * Toggle transfer progress bar.
1001: */
1.48 deraadt 1002: /*ARGSUSED*/
1.13 millert 1003: void
1.47 deraadt 1004: setprogress(int argc, char *argv[])
1.13 millert 1005: {
1006:
1007: code = togglevar(argc, argv, &progress, "Progress bar");
1.1 deraadt 1008: }
1009:
1010: /*
1.23 millert 1011: * Turn on interactive prompting during mget, mput, and mdelete.
1.1 deraadt 1012: */
1.48 deraadt 1013: /*ARGSUSED*/
1.1 deraadt 1014: void
1.47 deraadt 1015: setprompt(int argc, char *argv[])
1.1 deraadt 1016: {
1017:
1.13 millert 1018: code = togglevar(argc, argv, &interactive, "Interactive mode");
1.1 deraadt 1019: }
1020:
1021: /*
1.23 millert 1022: * Toggle gate-ftp mode, or set gate-ftp server
1023: */
1.48 deraadt 1024: /*ARGSUSED*/
1.23 millert 1025: void
1.47 deraadt 1026: setgate(int argc, char *argv[])
1.23 millert 1027: {
1028: static char gsbuf[MAXHOSTNAMELEN];
1029:
1030: if (argc > 3) {
1.64 sobrado 1031: fprintf(ttyout, "usage: %s [on | off | host [port]]\n",
1.23 millert 1032: argv[0]);
1033: code = -1;
1034: return;
1035: } else if (argc < 2) {
1036: gatemode = !gatemode;
1037: } else {
1038: if (argc == 2 && strcasecmp(argv[1], "on") == 0)
1039: gatemode = 1;
1040: else if (argc == 2 && strcasecmp(argv[1], "off") == 0)
1041: gatemode = 0;
1042: else {
1043: if (argc == 3) {
1.32 itojun 1044: gateport = strdup(argv[2]);
1.41 deraadt 1045: if (gateport == NULL)
1046: err(1, NULL);
1.23 millert 1047: }
1.36 lebel 1048: strlcpy(gsbuf, argv[1], sizeof(gsbuf));
1.23 millert 1049: gateserver = gsbuf;
1050: gatemode = 1;
1051: }
1052: }
1053: if (gatemode && (gateserver == NULL || *gateserver == '\0')) {
1054: fprintf(ttyout,
1055: "Disabling gate-ftp mode - no gate-ftp server defined.\n");
1056: gatemode = 0;
1057: } else {
1.32 itojun 1058: fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n",
1.23 millert 1059: onoff(gatemode),
1.32 itojun 1060: *gateserver ? gateserver : "(none)", gateport);
1.23 millert 1061: }
1062: code = gatemode;
1063: }
1064:
1065: /*
1066: * Toggle metacharacter interpretation on local file names.
1.1 deraadt 1067: */
1.48 deraadt 1068: /*ARGSUSED*/
1.1 deraadt 1069: void
1.47 deraadt 1070: setglob(int argc, char *argv[])
1.1 deraadt 1071: {
1.13 millert 1072:
1073: code = togglevar(argc, argv, &doglob, "Globbing");
1074: }
1075:
1076: /*
1.31 aaron 1077: * Toggle preserving modification times on retrieved files.
1.13 millert 1078: */
1.48 deraadt 1079: /*ARGSUSED*/
1.13 millert 1080: void
1.47 deraadt 1081: setpreserve(int argc, char *argv[])
1.13 millert 1082: {
1083:
1084: code = togglevar(argc, argv, &preserve, "Preserve modification times");
1.1 deraadt 1085: }
1086:
1087: /*
1.23 millert 1088: * Set debugging mode on/off and/or set level of debugging.
1.1 deraadt 1089: */
1.63 martynas 1090: #ifndef SMALL
1.48 deraadt 1091: /*ARGSUSED*/
1.1 deraadt 1092: void
1.47 deraadt 1093: setdebug(int argc, char *argv[])
1.1 deraadt 1094: {
1.13 millert 1095: if (argc > 2) {
1.64 sobrado 1096: fprintf(ttyout, "usage: %s [on | off | debuglevel]\n", argv[0]);
1.13 millert 1097: code = -1;
1098: return;
1099: } else if (argc == 2) {
1100: if (strcasecmp(argv[1], "on") == 0)
1101: debug = 1;
1102: else if (strcasecmp(argv[1], "off") == 0)
1103: debug = 0;
1104: else {
1.50 tedu 1105: const char *errstr;
1106: int val;
1.21 millert 1107:
1.50 tedu 1108: val = strtonum(argv[1], 0, INT_MAX, &errstr);
1109: if (errstr) {
1110: fprintf(ttyout, "debugging value is %s: %s\n",
1111: errstr, argv[1]);
1.13 millert 1112: code = -1;
1113: return;
1114: }
1.50 tedu 1115: debug = val;
1.1 deraadt 1116: }
1117: } else
1.13 millert 1118: debug = !debug;
1.1 deraadt 1119: if (debug)
1120: options |= SO_DEBUG;
1121: else
1122: options &= ~SO_DEBUG;
1.20 deraadt 1123: fprintf(ttyout, "Debugging %s (debug=%d).\n", onoff(debug), debug);
1.1 deraadt 1124: code = debug > 0;
1125: }
1.63 martynas 1126: #endif /* !SMALL */
1.1 deraadt 1127:
1128: /*
1.23 millert 1129: * Set current working directory on remote machine.
1.1 deraadt 1130: */
1.13 millert 1131: void
1.47 deraadt 1132: cd(int argc, char *argv[])
1.1 deraadt 1133: {
1.13 millert 1134: int r;
1.1 deraadt 1135:
1.13 millert 1136: if ((argc < 2 && !another(&argc, &argv, "remote-directory")) ||
1137: argc > 2) {
1.20 deraadt 1138: fprintf(ttyout, "usage: %s remote-directory\n", argv[0]);
1.1 deraadt 1139: code = -1;
1.13 millert 1140: return;
1.1 deraadt 1141: }
1.13 millert 1142: r = command("CWD %s", argv[1]);
1143: if (r == ERROR && code == 500) {
1144: if (verbose)
1.20 deraadt 1145: fputs("CWD command not recognized, trying XCWD.\n", ttyout);
1.13 millert 1146: r = command("XCWD %s", argv[1]);
1.42 deraadt 1147: }
1148: if (r == ERROR && code == 550) {
1149: dirchange = 0;
1150: return;
1.1 deraadt 1151: }
1.13 millert 1152: if (r == COMPLETE)
1153: dirchange = 1;
1.1 deraadt 1154: }
1155:
1156: /*
1.23 millert 1157: * Set current working directory on local machine.
1.1 deraadt 1158: */
1159: void
1.47 deraadt 1160: lcd(int argc, char *argv[])
1.1 deraadt 1161: {
1162: char buf[MAXPATHLEN];
1.23 millert 1163: char *oldargv1;
1.1 deraadt 1164:
1165: if (argc < 2)
1166: argc++, argv[1] = home;
1167: if (argc != 2) {
1.64 sobrado 1168: fprintf(ttyout, "usage: %s [local-directory]\n", argv[0]);
1.1 deraadt 1169: code = -1;
1170: return;
1171: }
1.23 millert 1172: oldargv1 = argv[1];
1.1 deraadt 1173: if (!globulize(&argv[1])) {
1174: code = -1;
1175: return;
1176: }
1177: if (chdir(argv[1]) < 0) {
1178: warn("local: %s", argv[1]);
1179: code = -1;
1.23 millert 1180: } else {
1181: if (getcwd(buf, sizeof(buf)) != NULL)
1182: fprintf(ttyout, "Local directory now %s\n", buf);
1183: else
1184: warn("getcwd: %s", argv[1]);
1185: code = 0;
1.1 deraadt 1186: }
1.23 millert 1187: if (oldargv1 != argv[1]) /* free up after globulize() */
1188: free(argv[1]);
1.1 deraadt 1189: }
1190:
1191: /*
1192: * Delete a single file.
1193: */
1194: void
1.48 deraadt 1195: deletecmd(int argc, char *argv[])
1.1 deraadt 1196: {
1197:
1.13 millert 1198: if ((argc < 2 && !another(&argc, &argv, "remote-file")) || argc > 2) {
1.20 deraadt 1199: fprintf(ttyout, "usage: %s remote-file\n", argv[0]);
1.1 deraadt 1200: code = -1;
1201: return;
1202: }
1.14 millert 1203: (void)command("DELE %s", argv[1]);
1.1 deraadt 1204: }
1205:
1206: /*
1207: * Delete multiple files.
1208: */
1209: void
1.47 deraadt 1210: mdelete(int argc, char *argv[])
1.1 deraadt 1211: {
1212: sig_t oldintr;
1213: char *cp;
1214:
1215: if (argc < 2 && !another(&argc, &argv, "remote-files")) {
1.20 deraadt 1216: fprintf(ttyout, "usage: %s remote-files\n", argv[0]);
1.1 deraadt 1217: code = -1;
1218: return;
1219: }
1220: mname = argv[0];
1221: mflag = 1;
1222: oldintr = signal(SIGINT, mabort);
1.14 millert 1223: (void)setjmp(jabort);
1.16 millert 1224: while ((cp = remglob(argv, 0, NULL)) != NULL) {
1.1 deraadt 1225: if (*cp == '\0') {
1226: mflag = 0;
1227: continue;
1228: }
1.63 martynas 1229: if (mflag && confirm(argv[0], cp)) {
1.14 millert 1230: (void)command("DELE %s", cp);
1.1 deraadt 1231: if (!mflag && fromatty) {
1.63 martynas 1232: if (confirm(argv[0], NULL))
1.61 martynas 1233: mflag = 1;
1.1 deraadt 1234: }
1235: }
1236: }
1.14 millert 1237: (void)signal(SIGINT, oldintr);
1.1 deraadt 1238: mflag = 0;
1239: }
1240:
1241: /*
1242: * Rename a remote file.
1243: */
1244: void
1.47 deraadt 1245: renamefile(int argc, char *argv[])
1.1 deraadt 1246: {
1247:
1248: if (argc < 2 && !another(&argc, &argv, "from-name"))
1249: goto usage;
1.13 millert 1250: if ((argc < 3 && !another(&argc, &argv, "to-name")) || argc > 3) {
1.1 deraadt 1251: usage:
1.20 deraadt 1252: fprintf(ttyout, "usage: %s from-name to-name\n", argv[0]);
1.1 deraadt 1253: code = -1;
1254: return;
1255: }
1256: if (command("RNFR %s", argv[1]) == CONTINUE)
1.14 millert 1257: (void)command("RNTO %s", argv[2]);
1.1 deraadt 1258: }
1259:
1260: /*
1.23 millert 1261: * Get a directory listing of remote files.
1.1 deraadt 1262: */
1263: void
1.47 deraadt 1264: ls(int argc, char *argv[])
1.1 deraadt 1265: {
1.13 millert 1266: const char *cmd;
1.23 millert 1267: char *oldargv2, *globargv2;
1.1 deraadt 1268:
1269: if (argc < 2)
1270: argc++, argv[1] = NULL;
1271: if (argc < 3)
1272: argc++, argv[2] = "-";
1273: if (argc > 3) {
1.64 sobrado 1274: fprintf(ttyout, "usage: %s [remote-directory [local-file]]\n",
1275: argv[0]);
1.1 deraadt 1276: code = -1;
1277: return;
1278: }
1.33 millert 1279: cmd = strcmp(argv[0], "nlist") == 0 ? "NLST" : "LIST";
1.23 millert 1280: oldargv2 = argv[2];
1.1 deraadt 1281: if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
1282: code = -1;
1283: return;
1284: }
1.23 millert 1285: globargv2 = argv[2];
1286: if (strcmp(argv[2], "-") && *argv[2] != '|' && (!globulize(&argv[2]) ||
1.63 martynas 1287: !confirm("output to local-file:", argv[2]))) {
1.23 millert 1288: code = -1;
1289: goto freels;
1.1 deraadt 1290: }
1.23 millert 1291: recvrequest(cmd, argv[2], argv[1], "w", 0, 0);
1.3 downsj 1292:
1293: /* flush results in case commands are coming from a pipe */
1.20 deraadt 1294: fflush(ttyout);
1.23 millert 1295: freels:
1296: if (argv[2] != globargv2) /* free up after globulize() */
1297: free(argv[2]);
1298: if (globargv2 != oldargv2)
1299: free(globargv2);
1.1 deraadt 1300: }
1301:
1302: /*
1.23 millert 1303: * Get a directory listing of multiple remote files.
1.1 deraadt 1304: */
1305: void
1.47 deraadt 1306: mls(int argc, char *argv[])
1.1 deraadt 1307: {
1308: sig_t oldintr;
1.60 martynas 1309: int i;
1.51 ray 1310: char lmode[1], *dest, *odest;
1.1 deraadt 1311:
1312: if (argc < 2 && !another(&argc, &argv, "remote-files"))
1313: goto usage;
1314: if (argc < 3 && !another(&argc, &argv, "local-file")) {
1315: usage:
1.20 deraadt 1316: fprintf(ttyout, "usage: %s remote-files local-file\n", argv[0]);
1.1 deraadt 1317: code = -1;
1318: return;
1319: }
1.23 millert 1320: odest = dest = argv[argc - 1];
1.1 deraadt 1321: argv[argc - 1] = NULL;
1322: if (strcmp(dest, "-") && *dest != '|')
1323: if (!globulize(&dest) ||
1.63 martynas 1324: !confirm("output to local-file:", dest)) {
1.1 deraadt 1325: code = -1;
1326: return;
1327: }
1328: mname = argv[0];
1329: mflag = 1;
1330: oldintr = signal(SIGINT, mabort);
1.14 millert 1331: (void)setjmp(jabort);
1.1 deraadt 1332: for (i = 1; mflag && i < argc-1; ++i) {
1.51 ray 1333: *lmode = (i == 1) ? 'w' : 'a';
1334: recvrequest("LIST", dest, argv[i], lmode, 0, 0);
1.1 deraadt 1335: if (!mflag && fromatty) {
1.63 martynas 1336: if (confirm(argv[0], NULL))
1.1 deraadt 1337: mflag ++;
1338: }
1339: }
1.14 millert 1340: (void)signal(SIGINT, oldintr);
1.1 deraadt 1341: mflag = 0;
1.23 millert 1342: if (dest != odest) /* free up after globulize() */
1343: free(dest);
1.1 deraadt 1344: }
1345:
1346: /*
1347: * Do a shell escape
1348: */
1349: /*ARGSUSED*/
1350: void
1.47 deraadt 1351: shell(int argc, char *argv[])
1.1 deraadt 1352: {
1353: pid_t pid;
1354: sig_t old1, old2;
1.51 ray 1355: char shellnam[MAXPATHLEN], *shellp, *namep;
1.24 millert 1356: int wait_status;
1.1 deraadt 1357:
1358: old1 = signal (SIGINT, SIG_IGN);
1359: old2 = signal (SIGQUIT, SIG_IGN);
1360: if ((pid = fork()) == 0) {
1361: for (pid = 3; pid < 20; pid++)
1.14 millert 1362: (void)close(pid);
1363: (void)signal(SIGINT, SIG_DFL);
1364: (void)signal(SIGQUIT, SIG_DFL);
1.51 ray 1365: shellp = getenv("SHELL");
1366: if (shellp == NULL || *shellp == '\0')
1367: shellp = _PATH_BSHELL;
1368: namep = strrchr(shellp, '/');
1.1 deraadt 1369: if (namep == NULL)
1.51 ray 1370: namep = shellp;
1.13 millert 1371: shellnam[0] = '-';
1.36 lebel 1372: (void)strlcpy(shellnam + 1, ++namep, sizeof(shellnam) - 1);
1.1 deraadt 1373: if (strcmp(namep, "sh") != 0)
1374: shellnam[0] = '+';
1.63 martynas 1375: #ifndef SMALL
1.1 deraadt 1376: if (debug) {
1.51 ray 1377: fputs(shellp, ttyout);
1.21 millert 1378: fputc('\n', ttyout);
1.20 deraadt 1379: (void)fflush(ttyout);
1.1 deraadt 1380: }
1.63 martynas 1381: #endif /* !SMALL */
1.1 deraadt 1382: if (argc > 1) {
1.51 ray 1383: execl(shellp, shellnam, "-c", altarg, (char *)0);
1.1 deraadt 1384: }
1385: else {
1.51 ray 1386: execl(shellp, shellnam, (char *)0);
1.1 deraadt 1387: }
1.51 ray 1388: warn("%s", shellp);
1.1 deraadt 1389: code = -1;
1390: exit(1);
1391: }
1392: if (pid > 0)
1.24 millert 1393: while (wait(&wait_status) != pid)
1.1 deraadt 1394: ;
1.14 millert 1395: (void)signal(SIGINT, old1);
1396: (void)signal(SIGQUIT, old2);
1.1 deraadt 1397: if (pid == -1) {
1.16 millert 1398: warn("Try again later");
1.1 deraadt 1399: code = -1;
1400: }
1401: else {
1402: code = 0;
1403: }
1404: }
1405:
1406: /*
1407: * Send new user information (re-login)
1408: */
1409: void
1.47 deraadt 1410: user(int argc, char *argv[])
1.1 deraadt 1411: {
1.51 ray 1412: char acctname[80];
1.1 deraadt 1413: int n, aflag = 0;
1414:
1415: if (argc < 2)
1.14 millert 1416: (void)another(&argc, &argv, "username");
1.1 deraadt 1417: if (argc < 2 || argc > 4) {
1.64 sobrado 1418: fprintf(ttyout, "usage: %s username [password [account]]\n",
1419: argv[0]);
1.1 deraadt 1420: code = -1;
1421: return;
1422: }
1423: n = command("USER %s", argv[1]);
1424: if (n == CONTINUE) {
1425: if (argc < 3 )
1.56 millert 1426: argv[2] = getpass("Password:"), argc++;
1.1 deraadt 1427: n = command("PASS %s", argv[2]);
1428: }
1429: if (n == CONTINUE) {
1430: if (argc < 4) {
1.20 deraadt 1431: (void)fputs("Account: ", ttyout);
1432: (void)fflush(ttyout);
1.59 martynas 1433: if (fgets(acctname, sizeof(acctname), stdin) == NULL) {
1434: clearerr(stdin);
1.53 ray 1435: goto fail;
1.59 martynas 1436: }
1.57 gilles 1437:
1438: acctname[strcspn(acctname, "\n")] = '\0';
1439:
1.51 ray 1440: argv[3] = acctname;
1441: argc++;
1.1 deraadt 1442: }
1443: n = command("ACCT %s", argv[3]);
1444: aflag++;
1445: }
1446: if (n != COMPLETE) {
1.53 ray 1447: fail:
1.20 deraadt 1448: fputs("Login failed.\n", ttyout);
1.1 deraadt 1449: return;
1450: }
1451: if (!aflag && argc == 4) {
1.14 millert 1452: (void)command("ACCT %s", argv[3]);
1.1 deraadt 1453: }
1.19 millert 1454: connected = -1;
1.1 deraadt 1455: }
1456:
1457: /*
1.13 millert 1458: * Print working directory on remote machine.
1.1 deraadt 1459: */
1.48 deraadt 1460: /*ARGSUSED*/
1.1 deraadt 1461: void
1.47 deraadt 1462: pwd(int argc, char *argv[])
1.1 deraadt 1463: {
1464: int oldverbose = verbose;
1465:
1466: /*
1467: * If we aren't verbose, this doesn't do anything!
1468: */
1469: verbose = 1;
1470: if (command("PWD") == ERROR && code == 500) {
1.20 deraadt 1471: fputs("PWD command not recognized, trying XPWD.\n", ttyout);
1.14 millert 1472: (void)command("XPWD");
1.1 deraadt 1473: }
1474: verbose = oldverbose;
1475: }
1476:
1477: /*
1.13 millert 1478: * Print working directory on local machine.
1479: */
1.48 deraadt 1480: /* ARGSUSED */
1.13 millert 1481: void
1.47 deraadt 1482: lpwd(int argc, char *argv[])
1.13 millert 1483: {
1484: char buf[MAXPATHLEN];
1485:
1486: if (getcwd(buf, sizeof(buf)) != NULL)
1.20 deraadt 1487: fprintf(ttyout, "Local directory %s\n", buf);
1.13 millert 1488: else
1489: warn("getcwd");
1490: code = 0;
1491: }
1492:
1493: /*
1.1 deraadt 1494: * Make a directory.
1495: */
1496: void
1.47 deraadt 1497: makedir(int argc, char *argv[])
1.1 deraadt 1498: {
1499:
1.13 millert 1500: if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1501: argc > 2) {
1.20 deraadt 1502: fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1.1 deraadt 1503: code = -1;
1504: return;
1505: }
1506: if (command("MKD %s", argv[1]) == ERROR && code == 500) {
1507: if (verbose)
1.20 deraadt 1508: fputs("MKD command not recognized, trying XMKD.\n", ttyout);
1.14 millert 1509: (void)command("XMKD %s", argv[1]);
1.1 deraadt 1510: }
1511: }
1512:
1513: /*
1514: * Remove a directory.
1515: */
1516: void
1.47 deraadt 1517: removedir(int argc, char *argv[])
1.1 deraadt 1518: {
1519:
1.13 millert 1520: if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1521: argc > 2) {
1.20 deraadt 1522: fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1.1 deraadt 1523: code = -1;
1524: return;
1525: }
1526: if (command("RMD %s", argv[1]) == ERROR && code == 500) {
1527: if (verbose)
1.20 deraadt 1528: fputs("RMD command not recognized, trying XRMD.\n", ttyout);
1.14 millert 1529: (void)command("XRMD %s", argv[1]);
1.1 deraadt 1530: }
1531: }
1532:
1533: /*
1534: * Send a line, verbatim, to the remote machine.
1535: */
1536: void
1.47 deraadt 1537: quote(int argc, char *argv[])
1.1 deraadt 1538: {
1539:
1540: if (argc < 2 && !another(&argc, &argv, "command line to send")) {
1.64 sobrado 1541: fprintf(ttyout, "usage: %s arg ...\n", argv[0]);
1.1 deraadt 1542: code = -1;
1543: return;
1544: }
1545: quote1("", argc, argv);
1546: }
1547:
1548: /*
1549: * Send a SITE command to the remote machine. The line
1550: * is sent verbatim to the remote machine, except that the
1551: * word "SITE" is added at the front.
1552: */
1553: void
1.47 deraadt 1554: site(int argc, char *argv[])
1.1 deraadt 1555: {
1556:
1557: if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) {
1.64 sobrado 1558: fprintf(ttyout, "usage: %s arg ...\n", argv[0]);
1.1 deraadt 1559: code = -1;
1560: return;
1561: }
1.26 weingart 1562: quote1("SITE", argc, argv);
1.1 deraadt 1563: }
1564:
1565: /*
1566: * Turn argv[1..argc) into a space-separated string, then prepend initial text.
1567: * Send the result as a one-line command and get response.
1568: */
1569: void
1.47 deraadt 1570: quote1(const char *initial, int argc, char *argv[])
1.1 deraadt 1571: {
1572: int i, len;
1573: char buf[BUFSIZ]; /* must be >= sizeof(line) */
1574:
1.36 lebel 1575: (void)strlcpy(buf, initial, sizeof(buf));
1.1 deraadt 1576: if (argc > 1) {
1.26 weingart 1577: for (i = 1, len = strlen(buf); i < argc && len < sizeof(buf)-1; i++) {
1578: /* Space for next arg */
1579: if (len > 1)
1580: buf[len++] = ' ';
1581:
1582: /* Sanity check */
1583: if (len >= sizeof(buf) - 1)
1584: break;
1585:
1.27 millert 1586: /* Copy next argument, NUL terminate always */
1.36 lebel 1587: strlcpy(&buf[len], argv[i], sizeof(buf) - len);
1.26 weingart 1588:
1589: /* Update string length */
1590: len = strlen(buf);
1.1 deraadt 1591: }
1592: }
1.26 weingart 1593:
1.35 aaron 1594: /* Make double (triple?) sure the sucker is NUL terminated */
1.26 weingart 1595: buf[sizeof(buf) - 1] = '\0';
1596:
1.29 deraadt 1597: if (command("%s", buf) == PRELIM) {
1.1 deraadt 1598: while (getreply(0) == PRELIM)
1599: continue;
1600: }
1601: }
1602:
1603: void
1.47 deraadt 1604: do_chmod(int argc, char *argv[])
1.1 deraadt 1605: {
1606:
1607: if (argc < 2 && !another(&argc, &argv, "mode"))
1608: goto usage;
1.64 sobrado 1609: if ((argc < 3 && !another(&argc, &argv, "file")) || argc > 3) {
1.1 deraadt 1610: usage:
1.64 sobrado 1611: fprintf(ttyout, "usage: %s mode file\n", argv[0]);
1.1 deraadt 1612: code = -1;
1613: return;
1614: }
1.14 millert 1615: (void)command("SITE CHMOD %s %s", argv[1], argv[2]);
1.1 deraadt 1616: }
1617:
1618: void
1.47 deraadt 1619: do_umask(int argc, char *argv[])
1.1 deraadt 1620: {
1621: int oldverbose = verbose;
1622:
1623: verbose = 1;
1.14 millert 1624: (void)command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
1.1 deraadt 1625: verbose = oldverbose;
1626: }
1627:
1628: void
1.47 deraadt 1629: idle(int argc, char *argv[])
1.1 deraadt 1630: {
1631: int oldverbose = verbose;
1632:
1633: verbose = 1;
1.14 millert 1634: (void)command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
1.1 deraadt 1635: verbose = oldverbose;
1636: }
1637:
1638: /*
1639: * Ask the other side for help.
1640: */
1641: void
1.47 deraadt 1642: rmthelp(int argc, char *argv[])
1.1 deraadt 1643: {
1644: int oldverbose = verbose;
1645:
1646: verbose = 1;
1.14 millert 1647: (void)command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
1.1 deraadt 1648: verbose = oldverbose;
1649: }
1650:
1651: /*
1652: * Terminate session and exit.
1653: */
1.48 deraadt 1654: /*ARGSUSED*/
1.1 deraadt 1655: void
1.47 deraadt 1656: quit(int argc, char *argv[])
1.1 deraadt 1657: {
1658:
1659: if (connected)
1660: disconnect(0, 0);
1661: pswitch(1);
1662: if (connected) {
1663: disconnect(0, 0);
1664: }
1665: exit(0);
1666: }
1667:
1668: /*
1669: * Terminate session, but don't exit.
1670: */
1.48 deraadt 1671: /* ARGSUSED */
1.1 deraadt 1672: void
1.47 deraadt 1673: disconnect(int argc, char *argv[])
1.1 deraadt 1674: {
1675:
1676: if (!connected)
1677: return;
1.14 millert 1678: (void)command("QUIT");
1.1 deraadt 1679: if (cout) {
1.14 millert 1680: (void)fclose(cout);
1.1 deraadt 1681: }
1682: cout = NULL;
1683: connected = 0;
1684: data = -1;
1685: if (!proxy) {
1686: macnum = 0;
1687: }
1688: }
1689:
1690: void
1.47 deraadt 1691: account(int argc, char *argv[])
1.1 deraadt 1692: {
1.13 millert 1693: char *ap;
1.1 deraadt 1694:
1.13 millert 1695: if (argc > 2) {
1.20 deraadt 1696: fprintf(ttyout, "usage: %s [password]\n", argv[0]);
1.13 millert 1697: code = -1;
1698: return;
1.1 deraadt 1699: }
1.13 millert 1700: else if (argc == 2)
1701: ap = argv[1];
1702: else
1.1 deraadt 1703: ap = getpass("Account:");
1.14 millert 1704: (void)command("ACCT %s", ap);
1.1 deraadt 1705: }
1706:
1707: jmp_buf abortprox;
1708:
1.48 deraadt 1709: /* ARGSUSED */
1.1 deraadt 1710: void
1.48 deraadt 1711: proxabort(int signo)
1.1 deraadt 1712: {
1713:
1.13 millert 1714: alarmtimer(0);
1.1 deraadt 1715: if (!proxy) {
1716: pswitch(1);
1717: }
1718: if (connected) {
1719: proxflag = 1;
1720: }
1721: else {
1722: proxflag = 0;
1723: }
1724: pswitch(0);
1.13 millert 1725: longjmp(abortprox, 1);
1.1 deraadt 1726: }
1727:
1728: void
1.47 deraadt 1729: doproxy(int argc, char *argv[])
1.1 deraadt 1730: {
1731: struct cmd *c;
1.13 millert 1732: int cmdpos;
1.1 deraadt 1733: sig_t oldintr;
1734:
1735: if (argc < 2 && !another(&argc, &argv, "command")) {
1.20 deraadt 1736: fprintf(ttyout, "usage: %s command\n", argv[0]);
1.1 deraadt 1737: code = -1;
1738: return;
1739: }
1740: c = getcmd(argv[1]);
1741: if (c == (struct cmd *) -1) {
1.20 deraadt 1742: fputs("?Ambiguous command.\n", ttyout);
1743: (void)fflush(ttyout);
1.1 deraadt 1744: code = -1;
1745: return;
1746: }
1747: if (c == 0) {
1.20 deraadt 1748: fputs("?Invalid command.\n", ttyout);
1749: (void)fflush(ttyout);
1.1 deraadt 1750: code = -1;
1751: return;
1752: }
1753: if (!c->c_proxy) {
1.20 deraadt 1754: fputs("?Invalid proxy command.\n", ttyout);
1755: (void)fflush(ttyout);
1.1 deraadt 1756: code = -1;
1757: return;
1758: }
1759: if (setjmp(abortprox)) {
1760: code = -1;
1761: return;
1762: }
1763: oldintr = signal(SIGINT, proxabort);
1764: pswitch(1);
1765: if (c->c_conn && !connected) {
1.20 deraadt 1766: fputs("Not connected.\n", ttyout);
1767: (void)fflush(ttyout);
1.1 deraadt 1768: pswitch(0);
1.14 millert 1769: (void)signal(SIGINT, oldintr);
1.1 deraadt 1770: code = -1;
1771: return;
1772: }
1.13 millert 1773: cmdpos = strcspn(line, " \t");
1774: if (cmdpos > 0) /* remove leading "proxy " from input buffer */
1775: memmove(line, line + cmdpos + 1, strlen(line) - cmdpos + 1);
1.1 deraadt 1776: (*c->c_handler)(argc-1, argv+1);
1777: if (connected) {
1778: proxflag = 1;
1779: }
1780: else {
1781: proxflag = 0;
1782: }
1783: pswitch(0);
1.14 millert 1784: (void)signal(SIGINT, oldintr);
1.1 deraadt 1785: }
1786:
1787: void
1.47 deraadt 1788: setcase(int argc, char *argv[])
1.1 deraadt 1789: {
1790:
1.13 millert 1791: code = togglevar(argc, argv, &mcase, "Case mapping");
1.1 deraadt 1792: }
1793:
1794: void
1.47 deraadt 1795: setcr(int argc, char *argv[])
1.1 deraadt 1796: {
1797:
1.13 millert 1798: code = togglevar(argc, argv, &crflag, "Carriage Return stripping");
1.1 deraadt 1799: }
1800:
1801: void
1.47 deraadt 1802: setntrans(int argc, char *argv[])
1.1 deraadt 1803: {
1804: if (argc == 1) {
1805: ntflag = 0;
1.20 deraadt 1806: fputs("Ntrans off.\n", ttyout);
1.1 deraadt 1807: code = ntflag;
1808: return;
1809: }
1810: ntflag++;
1811: code = ntflag;
1.36 lebel 1812: (void)strlcpy(ntin, argv[1], sizeof(ntin));
1.1 deraadt 1813: if (argc == 2) {
1814: ntout[0] = '\0';
1815: return;
1816: }
1.36 lebel 1817: (void)strlcpy(ntout, argv[2], sizeof(ntout));
1.1 deraadt 1818: }
1819:
1820: char *
1.47 deraadt 1821: dotrans(char *name)
1.1 deraadt 1822: {
1823: static char new[MAXPATHLEN];
1824: char *cp1, *cp2 = new;
1825: int i, ostop, found;
1826:
1827: for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
1828: continue;
1829: for (cp1 = name; *cp1; cp1++) {
1830: found = 0;
1831: for (i = 0; *(ntin + i) && i < 16; i++) {
1832: if (*cp1 == *(ntin + i)) {
1833: found++;
1834: if (i < ostop) {
1835: *cp2++ = *(ntout + i);
1836: }
1837: break;
1838: }
1839: }
1840: if (!found) {
1841: *cp2++ = *cp1;
1842: }
1843: }
1844: *cp2 = '\0';
1845: return (new);
1846: }
1847:
1848: void
1.47 deraadt 1849: setnmap(int argc, char *argv[])
1.1 deraadt 1850: {
1851: char *cp;
1852:
1853: if (argc == 1) {
1854: mapflag = 0;
1.20 deraadt 1855: fputs("Nmap off.\n", ttyout);
1.1 deraadt 1856: code = mapflag;
1857: return;
1858: }
1.64 sobrado 1859: if ((argc < 3 && !another(&argc, &argv, "outpattern")) || argc > 3) {
1860: fprintf(ttyout, "usage: %s [inpattern outpattern]\n", argv[0]);
1.1 deraadt 1861: code = -1;
1862: return;
1863: }
1864: mapflag = 1;
1865: code = 1;
1866: cp = strchr(altarg, ' ');
1867: if (proxy) {
1868: while(*++cp == ' ')
1869: continue;
1870: altarg = cp;
1871: cp = strchr(altarg, ' ');
1872: }
1873: *cp = '\0';
1.14 millert 1874: (void)strncpy(mapin, altarg, MAXPATHLEN - 1);
1.1 deraadt 1875: while (*++cp == ' ')
1876: continue;
1.14 millert 1877: (void)strncpy(mapout, cp, MAXPATHLEN - 1);
1.1 deraadt 1878: }
1879:
1880: char *
1.47 deraadt 1881: domap(char *name)
1.1 deraadt 1882: {
1883: static char new[MAXPATHLEN];
1884: char *cp1 = name, *cp2 = mapin;
1885: char *tp[9], *te[9];
1886: int i, toks[9], toknum = 0, match = 1;
1887:
1888: for (i=0; i < 9; ++i) {
1889: toks[i] = 0;
1890: }
1891: while (match && *cp1 && *cp2) {
1892: switch (*cp2) {
1893: case '\\':
1894: if (*++cp2 != *cp1) {
1895: match = 0;
1896: }
1897: break;
1898: case '$':
1899: if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
1900: if (*cp1 != *(++cp2+1)) {
1901: toks[toknum = *cp2 - '1']++;
1902: tp[toknum] = cp1;
1903: while (*++cp1 && *(cp2+1)
1904: != *cp1);
1905: te[toknum] = cp1;
1906: }
1907: cp2++;
1908: break;
1909: }
1910: /* FALLTHROUGH */
1911: default:
1912: if (*cp2 != *cp1) {
1913: match = 0;
1914: }
1915: break;
1916: }
1917: if (match && *cp1) {
1918: cp1++;
1919: }
1920: if (match && *cp2) {
1921: cp2++;
1922: }
1923: }
1924: if (!match && *cp1) /* last token mismatch */
1925: {
1926: toks[toknum] = 0;
1927: }
1928: cp1 = new;
1929: *cp1 = '\0';
1930: cp2 = mapout;
1931: while (*cp2) {
1932: match = 0;
1933: switch (*cp2) {
1934: case '\\':
1935: if (*(cp2 + 1)) {
1936: *cp1++ = *++cp2;
1937: }
1938: break;
1939: case '[':
1940: LOOP:
1.13 millert 1941: if (*++cp2 == '$' && isdigit(*(cp2+1))) {
1.1 deraadt 1942: if (*++cp2 == '0') {
1943: char *cp3 = name;
1944:
1945: while (*cp3) {
1946: *cp1++ = *cp3++;
1947: }
1948: match = 1;
1949: }
1950: else if (toks[toknum = *cp2 - '1']) {
1951: char *cp3 = tp[toknum];
1952:
1953: while (cp3 != te[toknum]) {
1954: *cp1++ = *cp3++;
1955: }
1956: match = 1;
1957: }
1958: }
1959: else {
1.13 millert 1960: while (*cp2 && *cp2 != ',' &&
1.1 deraadt 1961: *cp2 != ']') {
1962: if (*cp2 == '\\') {
1963: cp2++;
1964: }
1965: else if (*cp2 == '$' &&
1966: isdigit(*(cp2+1))) {
1967: if (*++cp2 == '0') {
1968: char *cp3 = name;
1969:
1970: while (*cp3) {
1971: *cp1++ = *cp3++;
1972: }
1973: }
1974: else if (toks[toknum =
1975: *cp2 - '1']) {
1976: char *cp3=tp[toknum];
1977:
1978: while (cp3 !=
1979: te[toknum]) {
1980: *cp1++ = *cp3++;
1981: }
1982: }
1983: }
1984: else if (*cp2) {
1985: *cp1++ = *cp2++;
1986: }
1987: }
1988: if (!*cp2) {
1.20 deraadt 1989: fputs(
1990: "nmap: unbalanced brackets.\n", ttyout);
1.1 deraadt 1991: return (name);
1992: }
1993: match = 1;
1994: cp2--;
1995: }
1996: if (match) {
1997: while (*++cp2 && *cp2 != ']') {
1998: if (*cp2 == '\\' && *(cp2 + 1)) {
1999: cp2++;
2000: }
2001: }
2002: if (!*cp2) {
1.20 deraadt 2003: fputs(
2004: "nmap: unbalanced brackets.\n", ttyout);
1.1 deraadt 2005: return (name);
2006: }
2007: break;
2008: }
2009: switch (*++cp2) {
2010: case ',':
2011: goto LOOP;
2012: case ']':
2013: break;
2014: default:
2015: cp2--;
2016: goto LOOP;
2017: }
2018: break;
2019: case '$':
2020: if (isdigit(*(cp2 + 1))) {
2021: if (*++cp2 == '0') {
2022: char *cp3 = name;
2023:
2024: while (*cp3) {
2025: *cp1++ = *cp3++;
2026: }
2027: }
2028: else if (toks[toknum = *cp2 - '1']) {
2029: char *cp3 = tp[toknum];
2030:
2031: while (cp3 != te[toknum]) {
2032: *cp1++ = *cp3++;
2033: }
2034: }
2035: break;
2036: }
1.51 ray 2037: /* FALLTHROUGH */
1.1 deraadt 2038: default:
2039: *cp1++ = *cp2;
2040: break;
2041: }
2042: cp2++;
2043: }
2044: *cp1 = '\0';
2045: if (!*new) {
2046: return (name);
2047: }
2048: return (new);
2049: }
2050:
2051: void
1.47 deraadt 2052: setpassive(int argc, char *argv[])
1.1 deraadt 2053: {
2054:
1.15 millert 2055: code = togglevar(argc, argv, &passivemode,
2056: verbose ? "Passive mode" : NULL);
1.1 deraadt 2057: }
2058:
2059: void
1.47 deraadt 2060: setsunique(int argc, char *argv[])
1.1 deraadt 2061: {
2062:
1.13 millert 2063: code = togglevar(argc, argv, &sunique, "Store unique");
1.1 deraadt 2064: }
2065:
2066: void
1.47 deraadt 2067: setrunique(int argc, char *argv[])
1.1 deraadt 2068: {
2069:
1.13 millert 2070: code = togglevar(argc, argv, &runique, "Receive unique");
1.1 deraadt 2071: }
2072:
1.13 millert 2073: /* change directory to parent directory */
1.48 deraadt 2074: /* ARGSUSED */
1.1 deraadt 2075: void
1.47 deraadt 2076: cdup(int argc, char *argv[])
1.1 deraadt 2077: {
1.13 millert 2078: int r;
1.1 deraadt 2079:
1.13 millert 2080: r = command("CDUP");
2081: if (r == ERROR && code == 500) {
1.1 deraadt 2082: if (verbose)
1.20 deraadt 2083: fputs("CDUP command not recognized, trying XCUP.\n", ttyout);
1.13 millert 2084: r = command("XCUP");
1.1 deraadt 2085: }
1.13 millert 2086: if (r == COMPLETE)
2087: dirchange = 1;
1.1 deraadt 2088: }
2089:
1.23 millert 2090: /*
2091: * Restart transfer at specific point
2092: */
1.1 deraadt 2093: void
1.47 deraadt 2094: restart(int argc, char *argv[])
1.1 deraadt 2095: {
1.27 millert 2096: quad_t nrestart_point;
2097: char *ep;
1.1 deraadt 2098:
2099: if (argc != 2)
1.20 deraadt 2100: fputs("restart: offset not specified.\n", ttyout);
1.1 deraadt 2101: else {
1.38 millert 2102: nrestart_point = strtoq(argv[1], &ep, 10);
1.27 millert 2103: if (nrestart_point == QUAD_MAX || *ep != '\0')
2104: fputs("restart: invalid offset.\n", ttyout);
2105: else {
1.39 millert 2106: fprintf(ttyout, "Restarting at %lld. Execute get, put "
2107: "or append to initiate transfer\n",
1.37 deraadt 2108: (long long)nrestart_point);
1.27 millert 2109: restart_point = nrestart_point;
2110: }
1.1 deraadt 2111: }
2112: }
2113:
1.23 millert 2114: /*
2115: * Show remote system type
2116: */
1.48 deraadt 2117: /* ARGSUSED */
1.1 deraadt 2118: void
1.47 deraadt 2119: syst(int argc, char *argv[])
1.1 deraadt 2120: {
2121:
1.14 millert 2122: (void)command("SYST");
1.1 deraadt 2123: }
2124:
2125: void
1.47 deraadt 2126: macdef(int argc, char *argv[])
1.1 deraadt 2127: {
2128: char *tmp;
2129: int c;
2130:
2131: if (macnum == 16) {
1.20 deraadt 2132: fputs("Limit of 16 macros have already been defined.\n", ttyout);
1.1 deraadt 2133: code = -1;
2134: return;
2135: }
1.64 sobrado 2136: if ((argc < 2 && !another(&argc, &argv, "macro-name")) || argc > 2) {
2137: fprintf(ttyout, "usage: %s macro-name\n", argv[0]);
1.1 deraadt 2138: code = -1;
2139: return;
2140: }
1.16 millert 2141: if (interactive)
1.20 deraadt 2142: fputs(
2143: "Enter macro line by line, terminating it with a null line.\n", ttyout);
1.36 lebel 2144: (void)strlcpy(macros[macnum].mac_name, argv[1],
2145: sizeof(macros[macnum].mac_name));
1.14 millert 2146: if (macnum == 0)
1.1 deraadt 2147: macros[macnum].mac_start = macbuf;
1.14 millert 2148: else
1.1 deraadt 2149: macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
2150: tmp = macros[macnum].mac_start;
2151: while (tmp != macbuf+4096) {
2152: if ((c = getchar()) == EOF) {
1.20 deraadt 2153: fputs("macdef: end of file encountered.\n", ttyout);
1.1 deraadt 2154: code = -1;
2155: return;
2156: }
2157: if ((*tmp = c) == '\n') {
2158: if (tmp == macros[macnum].mac_start) {
2159: macros[macnum++].mac_end = tmp;
2160: code = 0;
2161: return;
2162: }
2163: if (*(tmp-1) == '\0') {
2164: macros[macnum++].mac_end = tmp - 1;
2165: code = 0;
2166: return;
2167: }
2168: *tmp = '\0';
2169: }
2170: tmp++;
2171: }
2172: while (1) {
2173: while ((c = getchar()) != '\n' && c != EOF)
2174: /* LOOP */;
2175: if (c == EOF || getchar() == '\n') {
1.20 deraadt 2176: fputs("Macro not defined - 4K buffer exceeded.\n", ttyout);
1.1 deraadt 2177: code = -1;
2178: return;
2179: }
2180: }
2181: }
2182:
2183: /*
1.23 millert 2184: * Get size of file on remote machine
1.1 deraadt 2185: */
2186: void
1.47 deraadt 2187: sizecmd(int argc, char *argv[])
1.1 deraadt 2188: {
1.13 millert 2189: off_t size;
1.1 deraadt 2190:
1.64 sobrado 2191: if ((argc < 2 && !another(&argc, &argv, "file")) || argc > 2) {
2192: fprintf(ttyout, "usage: %s file\n", argv[0]);
1.1 deraadt 2193: code = -1;
2194: return;
2195: }
1.13 millert 2196: size = remotesize(argv[1], 1);
2197: if (size != -1)
1.37 deraadt 2198: fprintf(ttyout, "%s\t%lld\n", argv[1], (long long)size);
1.13 millert 2199: code = size;
1.1 deraadt 2200: }
2201:
2202: /*
1.23 millert 2203: * Get last modification time of file on remote machine
1.1 deraadt 2204: */
2205: void
1.47 deraadt 2206: modtime(int argc, char *argv[])
1.1 deraadt 2207: {
1.13 millert 2208: time_t mtime;
1.1 deraadt 2209:
1.64 sobrado 2210: if ((argc < 2 && !another(&argc, &argv, "file")) || argc > 2) {
2211: fprintf(ttyout, "usage: %s file\n", argv[0]);
1.1 deraadt 2212: code = -1;
2213: return;
2214: }
1.13 millert 2215: mtime = remotemodtime(argv[1], 1);
2216: if (mtime != -1)
1.20 deraadt 2217: fprintf(ttyout, "%s\t%s", argv[1], asctime(localtime(&mtime)));
1.13 millert 2218: code = mtime;
1.1 deraadt 2219: }
2220:
2221: /*
1.23 millert 2222: * Show status on remote machine
1.1 deraadt 2223: */
2224: void
1.47 deraadt 2225: rmtstatus(int argc, char *argv[])
1.1 deraadt 2226: {
2227:
1.14 millert 2228: (void)command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
1.1 deraadt 2229: }
2230:
2231: /*
1.23 millert 2232: * Get file if modtime is more recent than current file
1.1 deraadt 2233: */
2234: void
1.47 deraadt 2235: newer(int argc, char *argv[])
1.1 deraadt 2236: {
2237:
2238: if (getit(argc, argv, -1, "w"))
1.20 deraadt 2239: fprintf(ttyout, "Local file \"%s\" is newer than remote file \"%s\".\n",
1.1 deraadt 2240: argv[2], argv[1]);
1.16 millert 2241: }
2242:
2243: /*
2244: * Display one file through $PAGER (defaults to "more").
2245: */
2246: void
1.47 deraadt 2247: page(int argc, char *argv[])
1.16 millert 2248: {
2249: int orestart_point, ohash, overbose;
1.23 millert 2250: char *p, *pager, *oldargv1;
1.16 millert 2251:
1.64 sobrado 2252: if ((argc < 2 && !another(&argc, &argv, "file")) || argc > 2) {
2253: fprintf(ttyout, "usage: %s file\n", argv[0]);
1.16 millert 2254: code = -1;
2255: return;
2256: }
1.23 millert 2257: oldargv1 = argv[1];
1.16 millert 2258: if (!globulize(&argv[1])) {
2259: code = -1;
2260: return;
2261: }
2262: p = getenv("PAGER");
1.30 pjanzen 2263: if (p == NULL || (*p == '\0'))
1.16 millert 2264: p = PAGER;
1.44 deraadt 2265: if (asprintf(&pager, "|%s", p) == -1)
1.16 millert 2266: errx(1, "Can't allocate memory for $PAGER");
2267:
2268: orestart_point = restart_point;
2269: ohash = hash;
2270: overbose = verbose;
2271: restart_point = hash = verbose = 0;
1.23 millert 2272: recvrequest("RETR", pager, argv[1], "r+w", 1, 0);
1.16 millert 2273: (void)free(pager);
2274: restart_point = orestart_point;
2275: hash = ohash;
2276: verbose = overbose;
1.23 millert 2277: if (oldargv1 != argv[1]) /* free up after globulize() */
2278: free(argv[1]);
1.1 deraadt 2279: }