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