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