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