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