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