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