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