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