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