Annotation of src/usr.bin/ftp/cmds.c, Revision 1.44
1.44 ! deraadt 1: /* $OpenBSD: cmds.c,v 1.43 2003/03/31 23:04:07 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.
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.44 ! deraadt 70: static char rcsid[] = "$OpenBSD: cmds.c,v 1.43 2003/03/31 23:04:07 millert 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.44 ! deraadt 155: (void)strlcpy(typename, p->t_name, sizeof typename);
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;
1.40 art 587: longjmp(jabort, 1);
1.1 deraadt 588: }
589: interactive = ointer;
1.13 millert 590: confirmrest = oconf;
1.1 deraadt 591: }
592: mflag = 0;
1.40 art 593: longjmp(jabort, 1);
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.34 itojun 712: fprintf(ttyout, "Use of EPSV/EPRT cmds for IPv4: %s%s.\n", onoff(epsv4),
713: epsv4bad ? " (disabled for this connection)" : "");
1.17 millert 714: #ifndef SMALL
1.20 deraadt 715: fprintf(ttyout, "Command line editing: %s.\n", onoff(editing));
1.17 millert 716: #endif /* !SMALL */
1.1 deraadt 717: if (macnum > 0) {
1.27 millert 718: fputs("Macros:\n", ttyout);
1.1 deraadt 719: for (i=0; i<macnum; i++) {
1.20 deraadt 720: fprintf(ttyout, "\t%s\n", macros[i].mac_name);
1.1 deraadt 721: }
722: }
723: code = 0;
724: }
725:
726: /*
1.13 millert 727: * Toggle a variable
728: */
729: int
730: togglevar(argc, argv, var, mesg)
731: int argc;
732: char *argv[];
733: int *var;
734: const char *mesg;
735: {
736: if (argc < 2) {
737: *var = !*var;
738: } else if (argc == 2 && strcasecmp(argv[1], "on") == 0) {
739: *var = 1;
740: } else if (argc == 2 && strcasecmp(argv[1], "off") == 0) {
741: *var = 0;
742: } else {
1.20 deraadt 743: fprintf(ttyout, "usage: %s [ on | off ]\n", argv[0]);
1.16 millert 744: return (-1);
1.13 millert 745: }
1.15 millert 746: if (mesg)
1.20 deraadt 747: fprintf(ttyout, "%s %s.\n", mesg, onoff(*var));
1.14 millert 748: return (*var);
1.13 millert 749: }
750:
751: /*
1.1 deraadt 752: * Set beep on cmd completed mode.
753: */
754: /*VARARGS*/
755: void
756: setbell(argc, argv)
757: int argc;
758: char *argv[];
759: {
760:
1.13 millert 761: code = togglevar(argc, argv, &bell, "Bell mode");
1.1 deraadt 762: }
763:
1.17 millert 764: #ifndef SMALL
1.1 deraadt 765: /*
1.13 millert 766: * Set command line editing
1.1 deraadt 767: */
768: /*VARARGS*/
769: void
1.13 millert 770: setedit(argc, argv)
1.1 deraadt 771: int argc;
772: char *argv[];
773: {
774:
1.13 millert 775: code = togglevar(argc, argv, &editing, "Editing mode");
1.18 millert 776: controlediting();
1.1 deraadt 777: }
1.17 millert 778: #endif /* !SMALL */
1.34 itojun 779:
780: /*
781: * Toggle use of IPv4 EPSV/EPRT
782: */
783: /*VARARGS*/
784: void
785: setepsv4(argc, argv)
786: int argc;
787: char *argv[];
788: {
789:
790: code = togglevar(argc, argv, &epsv4, "EPSV/EPRT on IPv4");
791: epsv4bad = 0;
792: }
1.1 deraadt 793:
794: /*
1.13 millert 795: * Turn on packet tracing.
1.1 deraadt 796: */
797: /*VARARGS*/
798: void
1.13 millert 799: settrace(argc, argv)
800: int argc;
801: char *argv[];
1.1 deraadt 802: {
803:
1.13 millert 804: code = togglevar(argc, argv, &trace, "Packet tracing");
1.1 deraadt 805: }
1.6 kstailey 806:
807: /*
1.13 millert 808: * Toggle hash mark printing during transfers, or set hash mark bytecount.
1.6 kstailey 809: */
810: /*VARARGS*/
811: void
812: sethash(argc, argv)
813: int argc;
814: char *argv[];
815: {
816: if (argc == 1)
1.13 millert 817: hash = !hash;
1.6 kstailey 818: else if (argc != 2) {
1.20 deraadt 819: fprintf(ttyout, "usage: %s [ on | off | bytecount ]\n", argv[0]);
1.13 millert 820: code = -1;
821: return;
822: } else if (strcasecmp(argv[1], "on") == 0)
823: hash = 1;
824: else if (strcasecmp(argv[1], "off") == 0)
825: hash = 0;
826: else {
1.28 millert 827: long nmark;
828: char *ep;
829:
830: nmark = strtol(argv[1], &ep, 10);
831: if (nmark < 1 || nmark > INT_MAX || *ep != '\0') {
1.20 deraadt 832: fprintf(ttyout, "%s: bad bytecount value.\n", argv[1]);
1.13 millert 833: code = -1;
834: return;
1.6 kstailey 835: }
1.13 millert 836: mark = nmark;
837: hash = 1;
1.6 kstailey 838: }
1.20 deraadt 839: fprintf(ttyout, "Hash mark printing %s", onoff(hash));
1.13 millert 840: if (hash)
1.20 deraadt 841: fprintf(ttyout, " (%d bytes/hash mark)", mark);
842: fputs(".\n", ttyout);
1.13 millert 843: code = hash;
1.6 kstailey 844: }
845:
1.1 deraadt 846: /*
847: * Turn on printing of server echo's.
848: */
849: /*VARARGS*/
850: void
851: setverbose(argc, argv)
852: int argc;
853: char *argv[];
854: {
855:
1.13 millert 856: code = togglevar(argc, argv, &verbose, "Verbose mode");
1.1 deraadt 857: }
858:
859: /*
1.32 itojun 860: * Toggle PORT/LPRT cmd use before each data connection.
1.1 deraadt 861: */
862: /*VARARGS*/
863: void
864: setport(argc, argv)
865: int argc;
866: char *argv[];
867: {
868:
1.32 itojun 869: code = togglevar(argc, argv, &sendport, "Use of PORT/LPRT cmds");
1.13 millert 870: }
871:
872: /*
873: * Toggle transfer progress bar.
874: */
875: /*VARARGS*/
876: void
877: setprogress(argc, argv)
878: int argc;
879: char *argv[];
880: {
881:
882: code = togglevar(argc, argv, &progress, "Progress bar");
1.1 deraadt 883: }
884:
885: /*
1.23 millert 886: * Turn on interactive prompting during mget, mput, and mdelete.
1.1 deraadt 887: */
888: /*VARARGS*/
889: void
890: setprompt(argc, argv)
891: int argc;
892: char *argv[];
893: {
894:
1.13 millert 895: code = togglevar(argc, argv, &interactive, "Interactive mode");
1.1 deraadt 896: }
897:
898: /*
1.23 millert 899: * Toggle gate-ftp mode, or set gate-ftp server
900: */
901: /*VARARGS*/
902: void
903: setgate(argc, argv)
904: int argc;
905: char *argv[];
906: {
907: static char gsbuf[MAXHOSTNAMELEN];
908:
909: if (argc > 3) {
910: fprintf(ttyout, "usage: %s [ on | off | gateserver [ port ] ]\n",
911: argv[0]);
912: code = -1;
913: return;
914: } else if (argc < 2) {
915: gatemode = !gatemode;
916: } else {
917: if (argc == 2 && strcasecmp(argv[1], "on") == 0)
918: gatemode = 1;
919: else if (argc == 2 && strcasecmp(argv[1], "off") == 0)
920: gatemode = 0;
921: else {
922: if (argc == 3) {
1.32 itojun 923: #if 0
1.23 millert 924: char *ep;
925: long port;
926:
927: port = strtol(argv[2], &ep, 10);
928: if (port < 0 || port > USHRT_MAX || *ep != '\0') {
929: fprintf(ttyout,
930: "%s: bad gateport value.\n",
931: argv[2]);
932: code = -1;
933: return;
934: }
935: gateport = htons(port);
1.32 itojun 936: #else
937: gateport = strdup(argv[2]);
1.41 deraadt 938: if (gateport == NULL)
939: err(1, NULL);
1.32 itojun 940: #endif
1.23 millert 941: }
1.36 lebel 942: strlcpy(gsbuf, argv[1], sizeof(gsbuf));
1.23 millert 943: gateserver = gsbuf;
944: gatemode = 1;
945: }
946: }
947: if (gatemode && (gateserver == NULL || *gateserver == '\0')) {
948: fprintf(ttyout,
949: "Disabling gate-ftp mode - no gate-ftp server defined.\n");
950: gatemode = 0;
951: } else {
1.32 itojun 952: fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n",
1.23 millert 953: onoff(gatemode),
1.32 itojun 954: *gateserver ? gateserver : "(none)", gateport);
1.23 millert 955: }
956: code = gatemode;
957: }
958:
959: /*
960: * Toggle metacharacter interpretation on local file names.
1.1 deraadt 961: */
962: /*VARARGS*/
963: void
964: setglob(argc, argv)
965: int argc;
966: char *argv[];
967: {
1.13 millert 968:
969: code = togglevar(argc, argv, &doglob, "Globbing");
970: }
971:
972: /*
1.31 aaron 973: * Toggle preserving modification times on retrieved files.
1.13 millert 974: */
975: /*VARARGS*/
976: void
977: setpreserve(argc, argv)
978: int argc;
979: char *argv[];
980: {
981:
982: code = togglevar(argc, argv, &preserve, "Preserve modification times");
1.1 deraadt 983: }
984:
985: /*
1.23 millert 986: * Set debugging mode on/off and/or set level of debugging.
1.1 deraadt 987: */
988: /*VARARGS*/
989: void
990: setdebug(argc, argv)
991: int argc;
992: char *argv[];
993: {
1.13 millert 994: if (argc > 2) {
1.20 deraadt 995: fprintf(ttyout, "usage: %s [ on | off | debuglevel ]\n", argv[0]);
1.13 millert 996: code = -1;
997: return;
998: } else if (argc == 2) {
999: if (strcasecmp(argv[1], "on") == 0)
1000: debug = 1;
1001: else if (strcasecmp(argv[1], "off") == 0)
1002: debug = 0;
1003: else {
1.21 millert 1004: char *ep;
1005: long val;
1006:
1007: val = strtol(argv[1], &ep, 10);
1008: if (val < 0 || val > INT_MAX || *ep != '\0') {
1009: fprintf(ttyout, "%s: bad debugging value.\n",
1010: argv[1]);
1.13 millert 1011: code = -1;
1012: return;
1013: }
1.21 millert 1014: debug = (int)val;
1.1 deraadt 1015: }
1016: } else
1.13 millert 1017: debug = !debug;
1.1 deraadt 1018: if (debug)
1019: options |= SO_DEBUG;
1020: else
1021: options &= ~SO_DEBUG;
1.20 deraadt 1022: fprintf(ttyout, "Debugging %s (debug=%d).\n", onoff(debug), debug);
1.1 deraadt 1023: code = debug > 0;
1024: }
1025:
1026: /*
1.23 millert 1027: * Set current working directory on remote machine.
1.1 deraadt 1028: */
1.13 millert 1029: void
1030: cd(argc, argv)
1.1 deraadt 1031: int argc;
1032: char *argv[];
1033: {
1.13 millert 1034: int r;
1.1 deraadt 1035:
1.13 millert 1036: if ((argc < 2 && !another(&argc, &argv, "remote-directory")) ||
1037: argc > 2) {
1.20 deraadt 1038: fprintf(ttyout, "usage: %s remote-directory\n", argv[0]);
1.1 deraadt 1039: code = -1;
1.13 millert 1040: return;
1.1 deraadt 1041: }
1.13 millert 1042: r = command("CWD %s", argv[1]);
1043: if (r == ERROR && code == 500) {
1044: if (verbose)
1.20 deraadt 1045: fputs("CWD command not recognized, trying XCWD.\n", ttyout);
1.13 millert 1046: r = command("XCWD %s", argv[1]);
1.42 deraadt 1047: }
1048: if (r == ERROR && code == 550) {
1049: dirchange = 0;
1050: return;
1.1 deraadt 1051: }
1.13 millert 1052: if (r == COMPLETE)
1053: dirchange = 1;
1.1 deraadt 1054: }
1055:
1056: /*
1.23 millert 1057: * Set current working directory on local machine.
1.1 deraadt 1058: */
1059: void
1060: lcd(argc, argv)
1061: int argc;
1062: char *argv[];
1063: {
1064: char buf[MAXPATHLEN];
1.23 millert 1065: char *oldargv1;
1.1 deraadt 1066:
1067: if (argc < 2)
1068: argc++, argv[1] = home;
1069: if (argc != 2) {
1.20 deraadt 1070: fprintf(ttyout, "usage: %s local-directory\n", argv[0]);
1.1 deraadt 1071: code = -1;
1072: return;
1073: }
1.23 millert 1074: oldargv1 = argv[1];
1.1 deraadt 1075: if (!globulize(&argv[1])) {
1076: code = -1;
1077: return;
1078: }
1079: if (chdir(argv[1]) < 0) {
1080: warn("local: %s", argv[1]);
1081: code = -1;
1.23 millert 1082: } else {
1083: if (getcwd(buf, sizeof(buf)) != NULL)
1084: fprintf(ttyout, "Local directory now %s\n", buf);
1085: else
1086: warn("getcwd: %s", argv[1]);
1087: code = 0;
1.1 deraadt 1088: }
1.23 millert 1089: if (oldargv1 != argv[1]) /* free up after globulize() */
1090: free(argv[1]);
1.1 deraadt 1091: }
1092:
1093: /*
1094: * Delete a single file.
1095: */
1096: void
1097: delete(argc, argv)
1098: int argc;
1099: char *argv[];
1100: {
1101:
1.13 millert 1102: if ((argc < 2 && !another(&argc, &argv, "remote-file")) || argc > 2) {
1.20 deraadt 1103: fprintf(ttyout, "usage: %s remote-file\n", argv[0]);
1.1 deraadt 1104: code = -1;
1105: return;
1106: }
1.14 millert 1107: (void)command("DELE %s", argv[1]);
1.1 deraadt 1108: }
1109:
1110: /*
1111: * Delete multiple files.
1112: */
1113: void
1114: mdelete(argc, argv)
1115: int argc;
1.13 millert 1116: char *argv[];
1.1 deraadt 1117: {
1118: sig_t oldintr;
1119: int ointer;
1120: char *cp;
1121:
1122: if (argc < 2 && !another(&argc, &argv, "remote-files")) {
1.20 deraadt 1123: fprintf(ttyout, "usage: %s remote-files\n", argv[0]);
1.1 deraadt 1124: code = -1;
1125: return;
1126: }
1127: mname = argv[0];
1128: mflag = 1;
1129: oldintr = signal(SIGINT, mabort);
1.14 millert 1130: (void)setjmp(jabort);
1.16 millert 1131: while ((cp = remglob(argv, 0, NULL)) != NULL) {
1.1 deraadt 1132: if (*cp == '\0') {
1133: mflag = 0;
1134: continue;
1135: }
1136: if (mflag && confirm(argv[0], cp)) {
1.14 millert 1137: (void)command("DELE %s", cp);
1.1 deraadt 1138: if (!mflag && fromatty) {
1139: ointer = interactive;
1140: interactive = 1;
1141: if (confirm("Continue with", "mdelete")) {
1142: mflag++;
1143: }
1144: interactive = ointer;
1145: }
1146: }
1147: }
1.14 millert 1148: (void)signal(SIGINT, oldintr);
1.1 deraadt 1149: mflag = 0;
1150: }
1151:
1152: /*
1153: * Rename a remote file.
1154: */
1155: void
1156: renamefile(argc, argv)
1157: int argc;
1158: char *argv[];
1159: {
1160:
1161: if (argc < 2 && !another(&argc, &argv, "from-name"))
1162: goto usage;
1.13 millert 1163: if ((argc < 3 && !another(&argc, &argv, "to-name")) || argc > 3) {
1.1 deraadt 1164: usage:
1.20 deraadt 1165: fprintf(ttyout, "usage: %s from-name to-name\n", argv[0]);
1.1 deraadt 1166: code = -1;
1167: return;
1168: }
1169: if (command("RNFR %s", argv[1]) == CONTINUE)
1.14 millert 1170: (void)command("RNTO %s", argv[2]);
1.1 deraadt 1171: }
1172:
1173: /*
1.23 millert 1174: * Get a directory listing of remote files.
1.1 deraadt 1175: */
1176: void
1177: ls(argc, argv)
1178: int argc;
1179: char *argv[];
1180: {
1.13 millert 1181: const char *cmd;
1.23 millert 1182: char *oldargv2, *globargv2;
1.1 deraadt 1183:
1184: if (argc < 2)
1185: argc++, argv[1] = NULL;
1186: if (argc < 3)
1187: argc++, argv[2] = "-";
1188: if (argc > 3) {
1.20 deraadt 1189: fprintf(ttyout, "usage: %s remote-directory local-file\n", argv[0]);
1.1 deraadt 1190: code = -1;
1191: return;
1192: }
1.33 millert 1193: cmd = strcmp(argv[0], "nlist") == 0 ? "NLST" : "LIST";
1.23 millert 1194: oldargv2 = argv[2];
1.1 deraadt 1195: if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
1196: code = -1;
1197: return;
1198: }
1.23 millert 1199: globargv2 = argv[2];
1200: if (strcmp(argv[2], "-") && *argv[2] != '|' && (!globulize(&argv[2]) ||
1201: !confirm("output to local-file:", argv[2]))) {
1202: code = -1;
1203: goto freels;
1.1 deraadt 1204: }
1.23 millert 1205: recvrequest(cmd, argv[2], argv[1], "w", 0, 0);
1.3 downsj 1206:
1207: /* flush results in case commands are coming from a pipe */
1.20 deraadt 1208: fflush(ttyout);
1.23 millert 1209: freels:
1210: if (argv[2] != globargv2) /* free up after globulize() */
1211: free(argv[2]);
1212: if (globargv2 != oldargv2)
1213: free(globargv2);
1.1 deraadt 1214: }
1215:
1216: /*
1.23 millert 1217: * Get a directory listing of multiple remote files.
1.1 deraadt 1218: */
1219: void
1220: mls(argc, argv)
1221: int argc;
1.13 millert 1222: char *argv[];
1.1 deraadt 1223: {
1224: sig_t oldintr;
1225: int ointer, i;
1.23 millert 1226: char mode[1], *dest, *odest;
1.1 deraadt 1227:
1228: if (argc < 2 && !another(&argc, &argv, "remote-files"))
1229: goto usage;
1230: if (argc < 3 && !another(&argc, &argv, "local-file")) {
1231: usage:
1.20 deraadt 1232: fprintf(ttyout, "usage: %s remote-files local-file\n", argv[0]);
1.1 deraadt 1233: code = -1;
1234: return;
1235: }
1.23 millert 1236: odest = dest = argv[argc - 1];
1.1 deraadt 1237: argv[argc - 1] = NULL;
1238: if (strcmp(dest, "-") && *dest != '|')
1239: if (!globulize(&dest) ||
1240: !confirm("output to local-file:", dest)) {
1241: code = -1;
1242: return;
1243: }
1244: mname = argv[0];
1245: mflag = 1;
1246: oldintr = signal(SIGINT, mabort);
1.14 millert 1247: (void)setjmp(jabort);
1.1 deraadt 1248: for (i = 1; mflag && i < argc-1; ++i) {
1249: *mode = (i == 1) ? 'w' : 'a';
1.33 millert 1250: recvrequest("LIST", dest, argv[i], mode, 0, 0);
1.1 deraadt 1251: if (!mflag && fromatty) {
1252: ointer = interactive;
1253: interactive = 1;
1254: if (confirm("Continue with", argv[0])) {
1255: mflag ++;
1256: }
1257: interactive = ointer;
1258: }
1259: }
1.14 millert 1260: (void)signal(SIGINT, oldintr);
1.1 deraadt 1261: mflag = 0;
1.23 millert 1262: if (dest != odest) /* free up after globulize() */
1263: free(dest);
1.1 deraadt 1264: }
1265:
1266: /*
1267: * Do a shell escape
1268: */
1269: /*ARGSUSED*/
1270: void
1271: shell(argc, argv)
1272: int argc;
1.13 millert 1273: char *argv[];
1.1 deraadt 1274: {
1275: pid_t pid;
1276: sig_t old1, old2;
1.13 millert 1277: char shellnam[MAXPATHLEN], *shell, *namep;
1.24 millert 1278: int wait_status;
1.1 deraadt 1279:
1280: old1 = signal (SIGINT, SIG_IGN);
1281: old2 = signal (SIGQUIT, SIG_IGN);
1282: if ((pid = fork()) == 0) {
1283: for (pid = 3; pid < 20; pid++)
1.14 millert 1284: (void)close(pid);
1285: (void)signal(SIGINT, SIG_DFL);
1286: (void)signal(SIGQUIT, SIG_DFL);
1.1 deraadt 1287: shell = getenv("SHELL");
1.43 millert 1288: if (shell == NULL || *shell == '\0')
1.1 deraadt 1289: shell = _PATH_BSHELL;
1.13 millert 1290: namep = strrchr(shell, '/');
1.1 deraadt 1291: if (namep == NULL)
1292: namep = shell;
1.13 millert 1293: shellnam[0] = '-';
1.36 lebel 1294: (void)strlcpy(shellnam + 1, ++namep, sizeof(shellnam) - 1);
1.1 deraadt 1295: if (strcmp(namep, "sh") != 0)
1296: shellnam[0] = '+';
1297: if (debug) {
1.20 deraadt 1298: fputs(shell, ttyout);
1.21 millert 1299: fputc('\n', ttyout);
1.20 deraadt 1300: (void)fflush(ttyout);
1.1 deraadt 1301: }
1302: if (argc > 1) {
1.13 millert 1303: execl(shell, shellnam, "-c", altarg, (char *)0);
1.1 deraadt 1304: }
1305: else {
1.13 millert 1306: execl(shell, shellnam, (char *)0);
1.1 deraadt 1307: }
1308: warn("%s", shell);
1309: code = -1;
1310: exit(1);
1311: }
1312: if (pid > 0)
1.24 millert 1313: while (wait(&wait_status) != pid)
1.1 deraadt 1314: ;
1.14 millert 1315: (void)signal(SIGINT, old1);
1316: (void)signal(SIGQUIT, old2);
1.1 deraadt 1317: if (pid == -1) {
1.16 millert 1318: warn("Try again later");
1.1 deraadt 1319: code = -1;
1320: }
1321: else {
1322: code = 0;
1323: }
1324: }
1325:
1326: /*
1327: * Send new user information (re-login)
1328: */
1329: void
1330: user(argc, argv)
1331: int argc;
1.13 millert 1332: char *argv[];
1.1 deraadt 1333: {
1334: char acct[80];
1335: int n, aflag = 0;
1336:
1337: if (argc < 2)
1.14 millert 1338: (void)another(&argc, &argv, "username");
1.1 deraadt 1339: if (argc < 2 || argc > 4) {
1.20 deraadt 1340: fprintf(ttyout, "usage: %s username [password] [account]\n", argv[0]);
1.1 deraadt 1341: code = -1;
1342: return;
1343: }
1344: n = command("USER %s", argv[1]);
1345: if (n == CONTINUE) {
1346: if (argc < 3 )
1347: argv[2] = getpass("Password: "), argc++;
1348: n = command("PASS %s", argv[2]);
1349: }
1350: if (n == CONTINUE) {
1351: if (argc < 4) {
1.20 deraadt 1352: (void)fputs("Account: ", ttyout);
1353: (void)fflush(ttyout);
1.14 millert 1354: (void)fgets(acct, sizeof(acct) - 1, stdin);
1.1 deraadt 1355: acct[strlen(acct) - 1] = '\0';
1356: argv[3] = acct; argc++;
1357: }
1358: n = command("ACCT %s", argv[3]);
1359: aflag++;
1360: }
1361: if (n != COMPLETE) {
1.20 deraadt 1362: fputs("Login failed.\n", ttyout);
1.1 deraadt 1363: return;
1364: }
1365: if (!aflag && argc == 4) {
1.14 millert 1366: (void)command("ACCT %s", argv[3]);
1.1 deraadt 1367: }
1.19 millert 1368: connected = -1;
1.1 deraadt 1369: }
1370:
1371: /*
1.13 millert 1372: * Print working directory on remote machine.
1.1 deraadt 1373: */
1374: /*VARARGS*/
1375: void
1376: pwd(argc, argv)
1377: int argc;
1378: char *argv[];
1379: {
1380: int oldverbose = verbose;
1381:
1382: /*
1383: * If we aren't verbose, this doesn't do anything!
1384: */
1385: verbose = 1;
1386: if (command("PWD") == ERROR && code == 500) {
1.20 deraadt 1387: fputs("PWD command not recognized, trying XPWD.\n", ttyout);
1.14 millert 1388: (void)command("XPWD");
1.1 deraadt 1389: }
1390: verbose = oldverbose;
1391: }
1392:
1393: /*
1.13 millert 1394: * Print working directory on local machine.
1395: */
1396: void
1397: lpwd(argc, argv)
1398: int argc;
1399: char *argv[];
1400: {
1401: char buf[MAXPATHLEN];
1402:
1403: if (getcwd(buf, sizeof(buf)) != NULL)
1.20 deraadt 1404: fprintf(ttyout, "Local directory %s\n", buf);
1.13 millert 1405: else
1406: warn("getcwd");
1407: code = 0;
1408: }
1409:
1410: /*
1.1 deraadt 1411: * Make a directory.
1412: */
1413: void
1414: makedir(argc, argv)
1415: int argc;
1416: char *argv[];
1417: {
1418:
1.13 millert 1419: if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1420: argc > 2) {
1.20 deraadt 1421: fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1.1 deraadt 1422: code = -1;
1423: return;
1424: }
1425: if (command("MKD %s", argv[1]) == ERROR && code == 500) {
1426: if (verbose)
1.20 deraadt 1427: fputs("MKD command not recognized, trying XMKD.\n", ttyout);
1.14 millert 1428: (void)command("XMKD %s", argv[1]);
1.1 deraadt 1429: }
1430: }
1431:
1432: /*
1433: * Remove a directory.
1434: */
1435: void
1436: removedir(argc, argv)
1437: int argc;
1438: char *argv[];
1439: {
1440:
1.13 millert 1441: if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1442: argc > 2) {
1.20 deraadt 1443: fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1.1 deraadt 1444: code = -1;
1445: return;
1446: }
1447: if (command("RMD %s", argv[1]) == ERROR && code == 500) {
1448: if (verbose)
1.20 deraadt 1449: fputs("RMD command not recognized, trying XRMD.\n", ttyout);
1.14 millert 1450: (void)command("XRMD %s", argv[1]);
1.1 deraadt 1451: }
1452: }
1453:
1454: /*
1455: * Send a line, verbatim, to the remote machine.
1456: */
1457: void
1458: quote(argc, argv)
1459: int argc;
1460: char *argv[];
1461: {
1462:
1463: if (argc < 2 && !another(&argc, &argv, "command line to send")) {
1.20 deraadt 1464: fprintf(ttyout, "usage: %s line-to-send\n", argv[0]);
1.1 deraadt 1465: code = -1;
1466: return;
1467: }
1468: quote1("", argc, argv);
1469: }
1470:
1471: /*
1472: * Send a SITE command to the remote machine. The line
1473: * is sent verbatim to the remote machine, except that the
1474: * word "SITE" is added at the front.
1475: */
1476: void
1477: site(argc, argv)
1478: int argc;
1479: char *argv[];
1480: {
1481:
1482: if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) {
1.20 deraadt 1483: fprintf(ttyout, "usage: %s line-to-send\n", argv[0]);
1.1 deraadt 1484: code = -1;
1485: return;
1486: }
1.26 weingart 1487: quote1("SITE", argc, argv);
1.1 deraadt 1488: }
1489:
1490: /*
1491: * Turn argv[1..argc) into a space-separated string, then prepend initial text.
1492: * Send the result as a one-line command and get response.
1493: */
1494: void
1495: quote1(initial, argc, argv)
1.13 millert 1496: const char *initial;
1.1 deraadt 1497: int argc;
1.13 millert 1498: char *argv[];
1.1 deraadt 1499: {
1500: int i, len;
1501: char buf[BUFSIZ]; /* must be >= sizeof(line) */
1502:
1.36 lebel 1503: (void)strlcpy(buf, initial, sizeof(buf));
1.1 deraadt 1504: if (argc > 1) {
1.26 weingart 1505: for (i = 1, len = strlen(buf); i < argc && len < sizeof(buf)-1; i++) {
1506:
1507: /* Sanity check */
1508: if (len >= sizeof(buf) - 1)
1509: break;
1510:
1511: /* Space for next arg */
1512: if (len > 1)
1513: buf[len++] = ' ';
1514:
1515: /* Sanity check */
1516: if (len >= sizeof(buf) - 1)
1517: break;
1518:
1.27 millert 1519: /* Copy next argument, NUL terminate always */
1.36 lebel 1520: strlcpy(&buf[len], argv[i], sizeof(buf) - len);
1.26 weingart 1521:
1522: /* Update string length */
1523: len = strlen(buf);
1.1 deraadt 1524: }
1525: }
1.26 weingart 1526:
1.35 aaron 1527: /* Make double (triple?) sure the sucker is NUL terminated */
1.26 weingart 1528: buf[sizeof(buf) - 1] = '\0';
1529:
1.29 deraadt 1530: if (command("%s", buf) == PRELIM) {
1.1 deraadt 1531: while (getreply(0) == PRELIM)
1532: continue;
1533: }
1534: }
1535:
1536: void
1537: do_chmod(argc, argv)
1538: int argc;
1539: char *argv[];
1540: {
1541:
1542: if (argc < 2 && !another(&argc, &argv, "mode"))
1543: goto usage;
1.13 millert 1544: if ((argc < 3 && !another(&argc, &argv, "file-name")) || argc > 3) {
1.1 deraadt 1545: usage:
1.20 deraadt 1546: fprintf(ttyout, "usage: %s mode file-name\n", argv[0]);
1.1 deraadt 1547: code = -1;
1548: return;
1549: }
1.14 millert 1550: (void)command("SITE CHMOD %s %s", argv[1], argv[2]);
1.1 deraadt 1551: }
1552:
1553: void
1554: do_umask(argc, argv)
1555: int argc;
1556: char *argv[];
1557: {
1558: int oldverbose = verbose;
1559:
1560: verbose = 1;
1.14 millert 1561: (void)command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
1.1 deraadt 1562: verbose = oldverbose;
1563: }
1564:
1565: void
1566: idle(argc, argv)
1567: int argc;
1568: char *argv[];
1569: {
1570: int oldverbose = verbose;
1571:
1572: verbose = 1;
1.14 millert 1573: (void)command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
1.1 deraadt 1574: verbose = oldverbose;
1575: }
1576:
1577: /*
1578: * Ask the other side for help.
1579: */
1580: void
1581: rmthelp(argc, argv)
1582: int argc;
1583: char *argv[];
1584: {
1585: int oldverbose = verbose;
1586:
1587: verbose = 1;
1.14 millert 1588: (void)command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
1.1 deraadt 1589: verbose = oldverbose;
1590: }
1591:
1592: /*
1593: * Terminate session and exit.
1594: */
1595: /*VARARGS*/
1596: void
1597: quit(argc, argv)
1598: int argc;
1599: char *argv[];
1600: {
1601:
1602: if (connected)
1603: disconnect(0, 0);
1604: pswitch(1);
1605: if (connected) {
1606: disconnect(0, 0);
1607: }
1608: exit(0);
1609: }
1610:
1611: /*
1612: * Terminate session, but don't exit.
1613: */
1614: void
1615: disconnect(argc, argv)
1616: int argc;
1617: char *argv[];
1618: {
1619:
1620: if (!connected)
1621: return;
1.14 millert 1622: (void)command("QUIT");
1.1 deraadt 1623: if (cout) {
1.14 millert 1624: (void)fclose(cout);
1.1 deraadt 1625: }
1626: cout = NULL;
1627: connected = 0;
1628: data = -1;
1629: if (!proxy) {
1630: macnum = 0;
1631: }
1632: }
1633:
1634: void
1.13 millert 1635: account(argc, argv)
1.1 deraadt 1636: int argc;
1.13 millert 1637: char *argv[];
1.1 deraadt 1638: {
1.13 millert 1639: char *ap;
1.1 deraadt 1640:
1.13 millert 1641: if (argc > 2) {
1.20 deraadt 1642: fprintf(ttyout, "usage: %s [password]\n", argv[0]);
1.13 millert 1643: code = -1;
1644: return;
1.1 deraadt 1645: }
1.13 millert 1646: else if (argc == 2)
1647: ap = argv[1];
1648: else
1.1 deraadt 1649: ap = getpass("Account:");
1.14 millert 1650: (void)command("ACCT %s", ap);
1.1 deraadt 1651: }
1652:
1653: jmp_buf abortprox;
1654:
1655: void
1.15 millert 1656: proxabort(notused)
1657: int notused;
1.1 deraadt 1658: {
1659:
1.13 millert 1660: alarmtimer(0);
1.1 deraadt 1661: if (!proxy) {
1662: pswitch(1);
1663: }
1664: if (connected) {
1665: proxflag = 1;
1666: }
1667: else {
1668: proxflag = 0;
1669: }
1670: pswitch(0);
1.13 millert 1671: longjmp(abortprox, 1);
1.1 deraadt 1672: }
1673:
1674: void
1675: doproxy(argc, argv)
1676: int argc;
1677: char *argv[];
1678: {
1679: struct cmd *c;
1.13 millert 1680: int cmdpos;
1.1 deraadt 1681: sig_t oldintr;
1682:
1683: if (argc < 2 && !another(&argc, &argv, "command")) {
1.20 deraadt 1684: fprintf(ttyout, "usage: %s command\n", argv[0]);
1.1 deraadt 1685: code = -1;
1686: return;
1687: }
1688: c = getcmd(argv[1]);
1689: if (c == (struct cmd *) -1) {
1.20 deraadt 1690: fputs("?Ambiguous command.\n", ttyout);
1691: (void)fflush(ttyout);
1.1 deraadt 1692: code = -1;
1693: return;
1694: }
1695: if (c == 0) {
1.20 deraadt 1696: fputs("?Invalid command.\n", ttyout);
1697: (void)fflush(ttyout);
1.1 deraadt 1698: code = -1;
1699: return;
1700: }
1701: if (!c->c_proxy) {
1.20 deraadt 1702: fputs("?Invalid proxy command.\n", ttyout);
1703: (void)fflush(ttyout);
1.1 deraadt 1704: code = -1;
1705: return;
1706: }
1707: if (setjmp(abortprox)) {
1708: code = -1;
1709: return;
1710: }
1711: oldintr = signal(SIGINT, proxabort);
1712: pswitch(1);
1713: if (c->c_conn && !connected) {
1.20 deraadt 1714: fputs("Not connected.\n", ttyout);
1715: (void)fflush(ttyout);
1.1 deraadt 1716: pswitch(0);
1.14 millert 1717: (void)signal(SIGINT, oldintr);
1.1 deraadt 1718: code = -1;
1719: return;
1720: }
1.13 millert 1721: cmdpos = strcspn(line, " \t");
1722: if (cmdpos > 0) /* remove leading "proxy " from input buffer */
1723: memmove(line, line + cmdpos + 1, strlen(line) - cmdpos + 1);
1.1 deraadt 1724: (*c->c_handler)(argc-1, argv+1);
1725: if (connected) {
1726: proxflag = 1;
1727: }
1728: else {
1729: proxflag = 0;
1730: }
1731: pswitch(0);
1.14 millert 1732: (void)signal(SIGINT, oldintr);
1.1 deraadt 1733: }
1734:
1735: void
1736: setcase(argc, argv)
1737: int argc;
1738: char *argv[];
1739: {
1740:
1.13 millert 1741: code = togglevar(argc, argv, &mcase, "Case mapping");
1.1 deraadt 1742: }
1743:
1744: void
1745: setcr(argc, argv)
1746: int argc;
1747: char *argv[];
1748: {
1749:
1.13 millert 1750: code = togglevar(argc, argv, &crflag, "Carriage Return stripping");
1.1 deraadt 1751: }
1752:
1753: void
1.13 millert 1754: setntrans(argc, argv)
1.1 deraadt 1755: int argc;
1756: char *argv[];
1757: {
1758: if (argc == 1) {
1759: ntflag = 0;
1.20 deraadt 1760: fputs("Ntrans off.\n", ttyout);
1.1 deraadt 1761: code = ntflag;
1762: return;
1763: }
1764: ntflag++;
1765: code = ntflag;
1.36 lebel 1766: (void)strlcpy(ntin, argv[1], sizeof(ntin));
1.1 deraadt 1767: if (argc == 2) {
1768: ntout[0] = '\0';
1769: return;
1770: }
1.36 lebel 1771: (void)strlcpy(ntout, argv[2], sizeof(ntout));
1.1 deraadt 1772: }
1773:
1774: char *
1775: dotrans(name)
1776: char *name;
1777: {
1778: static char new[MAXPATHLEN];
1779: char *cp1, *cp2 = new;
1780: int i, ostop, found;
1781:
1782: for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++)
1783: continue;
1784: for (cp1 = name; *cp1; cp1++) {
1785: found = 0;
1786: for (i = 0; *(ntin + i) && i < 16; i++) {
1787: if (*cp1 == *(ntin + i)) {
1788: found++;
1789: if (i < ostop) {
1790: *cp2++ = *(ntout + i);
1791: }
1792: break;
1793: }
1794: }
1795: if (!found) {
1796: *cp2++ = *cp1;
1797: }
1798: }
1799: *cp2 = '\0';
1800: return (new);
1801: }
1802:
1803: void
1804: setnmap(argc, argv)
1805: int argc;
1806: char *argv[];
1807: {
1808: char *cp;
1809:
1810: if (argc == 1) {
1811: mapflag = 0;
1.20 deraadt 1812: fputs("Nmap off.\n", ttyout);
1.1 deraadt 1813: code = mapflag;
1814: return;
1815: }
1.13 millert 1816: if ((argc < 3 && !another(&argc, &argv, "mapout")) || argc > 3) {
1.20 deraadt 1817: fprintf(ttyout, "usage: %s [mapin mapout]\n", argv[0]);
1.1 deraadt 1818: code = -1;
1819: return;
1820: }
1821: mapflag = 1;
1822: code = 1;
1823: cp = strchr(altarg, ' ');
1824: if (proxy) {
1825: while(*++cp == ' ')
1826: continue;
1827: altarg = cp;
1828: cp = strchr(altarg, ' ');
1829: }
1830: *cp = '\0';
1.14 millert 1831: (void)strncpy(mapin, altarg, MAXPATHLEN - 1);
1.1 deraadt 1832: while (*++cp == ' ')
1833: continue;
1.14 millert 1834: (void)strncpy(mapout, cp, MAXPATHLEN - 1);
1.1 deraadt 1835: }
1836:
1837: char *
1838: domap(name)
1839: char *name;
1840: {
1841: static char new[MAXPATHLEN];
1842: char *cp1 = name, *cp2 = mapin;
1843: char *tp[9], *te[9];
1844: int i, toks[9], toknum = 0, match = 1;
1845:
1846: for (i=0; i < 9; ++i) {
1847: toks[i] = 0;
1848: }
1849: while (match && *cp1 && *cp2) {
1850: switch (*cp2) {
1851: case '\\':
1852: if (*++cp2 != *cp1) {
1853: match = 0;
1854: }
1855: break;
1856: case '$':
1857: if (*(cp2+1) >= '1' && (*cp2+1) <= '9') {
1858: if (*cp1 != *(++cp2+1)) {
1859: toks[toknum = *cp2 - '1']++;
1860: tp[toknum] = cp1;
1861: while (*++cp1 && *(cp2+1)
1862: != *cp1);
1863: te[toknum] = cp1;
1864: }
1865: cp2++;
1866: break;
1867: }
1868: /* FALLTHROUGH */
1869: default:
1870: if (*cp2 != *cp1) {
1871: match = 0;
1872: }
1873: break;
1874: }
1875: if (match && *cp1) {
1876: cp1++;
1877: }
1878: if (match && *cp2) {
1879: cp2++;
1880: }
1881: }
1882: if (!match && *cp1) /* last token mismatch */
1883: {
1884: toks[toknum] = 0;
1885: }
1886: cp1 = new;
1887: *cp1 = '\0';
1888: cp2 = mapout;
1889: while (*cp2) {
1890: match = 0;
1891: switch (*cp2) {
1892: case '\\':
1893: if (*(cp2 + 1)) {
1894: *cp1++ = *++cp2;
1895: }
1896: break;
1897: case '[':
1898: LOOP:
1.13 millert 1899: if (*++cp2 == '$' && isdigit(*(cp2+1))) {
1.1 deraadt 1900: if (*++cp2 == '0') {
1901: char *cp3 = name;
1902:
1903: while (*cp3) {
1904: *cp1++ = *cp3++;
1905: }
1906: match = 1;
1907: }
1908: else if (toks[toknum = *cp2 - '1']) {
1909: char *cp3 = tp[toknum];
1910:
1911: while (cp3 != te[toknum]) {
1912: *cp1++ = *cp3++;
1913: }
1914: match = 1;
1915: }
1916: }
1917: else {
1.13 millert 1918: while (*cp2 && *cp2 != ',' &&
1.1 deraadt 1919: *cp2 != ']') {
1920: if (*cp2 == '\\') {
1921: cp2++;
1922: }
1923: else if (*cp2 == '$' &&
1924: isdigit(*(cp2+1))) {
1925: if (*++cp2 == '0') {
1926: char *cp3 = name;
1927:
1928: while (*cp3) {
1929: *cp1++ = *cp3++;
1930: }
1931: }
1932: else if (toks[toknum =
1933: *cp2 - '1']) {
1934: char *cp3=tp[toknum];
1935:
1936: while (cp3 !=
1937: te[toknum]) {
1938: *cp1++ = *cp3++;
1939: }
1940: }
1941: }
1942: else if (*cp2) {
1943: *cp1++ = *cp2++;
1944: }
1945: }
1946: if (!*cp2) {
1.20 deraadt 1947: fputs(
1948: "nmap: unbalanced brackets.\n", ttyout);
1.1 deraadt 1949: return (name);
1950: }
1951: match = 1;
1952: cp2--;
1953: }
1954: if (match) {
1955: while (*++cp2 && *cp2 != ']') {
1956: if (*cp2 == '\\' && *(cp2 + 1)) {
1957: cp2++;
1958: }
1959: }
1960: if (!*cp2) {
1.20 deraadt 1961: fputs(
1962: "nmap: unbalanced brackets.\n", ttyout);
1.1 deraadt 1963: return (name);
1964: }
1965: break;
1966: }
1967: switch (*++cp2) {
1968: case ',':
1969: goto LOOP;
1970: case ']':
1971: break;
1972: default:
1973: cp2--;
1974: goto LOOP;
1975: }
1976: break;
1977: case '$':
1978: if (isdigit(*(cp2 + 1))) {
1979: if (*++cp2 == '0') {
1980: char *cp3 = name;
1981:
1982: while (*cp3) {
1983: *cp1++ = *cp3++;
1984: }
1985: }
1986: else if (toks[toknum = *cp2 - '1']) {
1987: char *cp3 = tp[toknum];
1988:
1989: while (cp3 != te[toknum]) {
1990: *cp1++ = *cp3++;
1991: }
1992: }
1993: break;
1994: }
1995: /* intentional drop through */
1996: default:
1997: *cp1++ = *cp2;
1998: break;
1999: }
2000: cp2++;
2001: }
2002: *cp1 = '\0';
2003: if (!*new) {
2004: return (name);
2005: }
2006: return (new);
2007: }
2008:
2009: void
2010: setpassive(argc, argv)
2011: int argc;
2012: char *argv[];
2013: {
2014:
1.15 millert 2015: code = togglevar(argc, argv, &passivemode,
2016: verbose ? "Passive mode" : NULL);
1.1 deraadt 2017: }
2018:
2019: void
2020: setsunique(argc, argv)
2021: int argc;
2022: char *argv[];
2023: {
2024:
1.13 millert 2025: code = togglevar(argc, argv, &sunique, "Store unique");
1.1 deraadt 2026: }
2027:
2028: void
2029: setrunique(argc, argv)
2030: int argc;
2031: char *argv[];
2032: {
2033:
1.13 millert 2034: code = togglevar(argc, argv, &runique, "Receive unique");
1.1 deraadt 2035: }
2036:
1.13 millert 2037: /* change directory to parent directory */
1.1 deraadt 2038: void
2039: cdup(argc, argv)
2040: int argc;
2041: char *argv[];
2042: {
1.13 millert 2043: int r;
1.1 deraadt 2044:
1.13 millert 2045: r = command("CDUP");
2046: if (r == ERROR && code == 500) {
1.1 deraadt 2047: if (verbose)
1.20 deraadt 2048: fputs("CDUP command not recognized, trying XCUP.\n", ttyout);
1.13 millert 2049: r = command("XCUP");
1.1 deraadt 2050: }
1.13 millert 2051: if (r == COMPLETE)
2052: dirchange = 1;
1.1 deraadt 2053: }
2054:
1.23 millert 2055: /*
2056: * Restart transfer at specific point
2057: */
1.1 deraadt 2058: void
2059: restart(argc, argv)
2060: int argc;
2061: char *argv[];
2062: {
1.27 millert 2063: quad_t nrestart_point;
2064: char *ep;
1.1 deraadt 2065:
2066: if (argc != 2)
1.20 deraadt 2067: fputs("restart: offset not specified.\n", ttyout);
1.1 deraadt 2068: else {
1.38 millert 2069: nrestart_point = strtoq(argv[1], &ep, 10);
1.27 millert 2070: if (nrestart_point == QUAD_MAX || *ep != '\0')
2071: fputs("restart: invalid offset.\n", ttyout);
2072: else {
1.39 millert 2073: fprintf(ttyout, "Restarting at %lld. Execute get, put "
2074: "or append to initiate transfer\n",
1.37 deraadt 2075: (long long)nrestart_point);
1.27 millert 2076: restart_point = nrestart_point;
2077: }
1.1 deraadt 2078: }
2079: }
2080:
1.23 millert 2081: /*
2082: * Show remote system type
2083: */
1.1 deraadt 2084: void
2085: syst(argc, argv)
2086: int argc;
2087: char *argv[];
2088: {
2089:
1.14 millert 2090: (void)command("SYST");
1.1 deraadt 2091: }
2092:
2093: void
2094: macdef(argc, argv)
2095: int argc;
2096: char *argv[];
2097: {
2098: char *tmp;
2099: int c;
2100:
2101: if (macnum == 16) {
1.20 deraadt 2102: fputs("Limit of 16 macros have already been defined.\n", ttyout);
1.1 deraadt 2103: code = -1;
2104: return;
2105: }
1.13 millert 2106: if ((argc < 2 && !another(&argc, &argv, "macro name")) || argc > 2) {
1.20 deraadt 2107: fprintf(ttyout, "usage: %s macro_name\n", argv[0]);
1.1 deraadt 2108: code = -1;
2109: return;
2110: }
1.16 millert 2111: if (interactive)
1.20 deraadt 2112: fputs(
2113: "Enter macro line by line, terminating it with a null line.\n", ttyout);
1.36 lebel 2114: (void)strlcpy(macros[macnum].mac_name, argv[1],
2115: sizeof(macros[macnum].mac_name));
1.14 millert 2116: if (macnum == 0)
1.1 deraadt 2117: macros[macnum].mac_start = macbuf;
1.14 millert 2118: else
1.1 deraadt 2119: macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
2120: tmp = macros[macnum].mac_start;
2121: while (tmp != macbuf+4096) {
2122: if ((c = getchar()) == EOF) {
1.20 deraadt 2123: fputs("macdef: end of file encountered.\n", ttyout);
1.1 deraadt 2124: code = -1;
2125: return;
2126: }
2127: if ((*tmp = c) == '\n') {
2128: if (tmp == macros[macnum].mac_start) {
2129: macros[macnum++].mac_end = tmp;
2130: code = 0;
2131: return;
2132: }
2133: if (*(tmp-1) == '\0') {
2134: macros[macnum++].mac_end = tmp - 1;
2135: code = 0;
2136: return;
2137: }
2138: *tmp = '\0';
2139: }
2140: tmp++;
2141: }
2142: while (1) {
2143: while ((c = getchar()) != '\n' && c != EOF)
2144: /* LOOP */;
2145: if (c == EOF || getchar() == '\n') {
1.20 deraadt 2146: fputs("Macro not defined - 4K buffer exceeded.\n", ttyout);
1.1 deraadt 2147: code = -1;
2148: return;
2149: }
2150: }
2151: }
2152:
2153: /*
1.23 millert 2154: * Get size of file on remote machine
1.1 deraadt 2155: */
2156: void
2157: sizecmd(argc, argv)
2158: int argc;
2159: char *argv[];
2160: {
1.13 millert 2161: off_t size;
1.1 deraadt 2162:
1.13 millert 2163: if ((argc < 2 && !another(&argc, &argv, "filename")) || argc > 2) {
1.20 deraadt 2164: fprintf(ttyout, "usage: %s filename\n", argv[0]);
1.1 deraadt 2165: code = -1;
2166: return;
2167: }
1.13 millert 2168: size = remotesize(argv[1], 1);
2169: if (size != -1)
1.37 deraadt 2170: fprintf(ttyout, "%s\t%lld\n", argv[1], (long long)size);
1.13 millert 2171: code = size;
1.1 deraadt 2172: }
2173:
2174: /*
1.23 millert 2175: * Get last modification time of file on remote machine
1.1 deraadt 2176: */
2177: void
2178: modtime(argc, argv)
2179: int argc;
2180: char *argv[];
2181: {
1.13 millert 2182: time_t mtime;
1.1 deraadt 2183:
1.13 millert 2184: if ((argc < 2 && !another(&argc, &argv, "filename")) || argc > 2) {
1.20 deraadt 2185: fprintf(ttyout, "usage: %s filename\n", argv[0]);
1.1 deraadt 2186: code = -1;
2187: return;
2188: }
1.13 millert 2189: mtime = remotemodtime(argv[1], 1);
2190: if (mtime != -1)
1.20 deraadt 2191: fprintf(ttyout, "%s\t%s", argv[1], asctime(localtime(&mtime)));
1.13 millert 2192: code = mtime;
1.1 deraadt 2193: }
2194:
2195: /*
1.23 millert 2196: * Show status on remote machine
1.1 deraadt 2197: */
2198: void
2199: rmtstatus(argc, argv)
2200: int argc;
2201: char *argv[];
2202: {
2203:
1.14 millert 2204: (void)command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
1.1 deraadt 2205: }
2206:
2207: /*
1.23 millert 2208: * Get file if modtime is more recent than current file
1.1 deraadt 2209: */
2210: void
2211: newer(argc, argv)
2212: int argc;
2213: char *argv[];
2214: {
2215:
2216: if (getit(argc, argv, -1, "w"))
1.20 deraadt 2217: fprintf(ttyout, "Local file \"%s\" is newer than remote file \"%s\".\n",
1.1 deraadt 2218: argv[2], argv[1]);
1.16 millert 2219: }
2220:
2221: /*
2222: * Display one file through $PAGER (defaults to "more").
2223: */
2224: void
2225: page(argc, argv)
2226: int argc;
2227: char *argv[];
2228: {
2229: int orestart_point, ohash, overbose;
1.23 millert 2230: char *p, *pager, *oldargv1;
1.16 millert 2231:
2232: if ((argc < 2 && !another(&argc, &argv, "filename")) || argc > 2) {
1.20 deraadt 2233: fprintf(ttyout, "usage: %s filename\n", argv[0]);
1.16 millert 2234: code = -1;
2235: return;
2236: }
1.23 millert 2237: oldargv1 = argv[1];
1.16 millert 2238: if (!globulize(&argv[1])) {
2239: code = -1;
2240: return;
2241: }
2242: p = getenv("PAGER");
1.30 pjanzen 2243: if (p == NULL || (*p == '\0'))
1.16 millert 2244: p = PAGER;
1.44 ! deraadt 2245: if (asprintf(&pager, "|%s", p) == -1)
1.16 millert 2246: errx(1, "Can't allocate memory for $PAGER");
2247:
2248: orestart_point = restart_point;
2249: ohash = hash;
2250: overbose = verbose;
2251: restart_point = hash = verbose = 0;
1.23 millert 2252: recvrequest("RETR", pager, argv[1], "r+w", 1, 0);
1.16 millert 2253: (void)free(pager);
2254: restart_point = orestart_point;
2255: hash = ohash;
2256: verbose = overbose;
1.23 millert 2257: if (oldargv1 != argv[1]) /* free up after globulize() */
2258: free(argv[1]);
1.1 deraadt 2259: }