Annotation of src/usr.bin/ftp/cmds.c, Revision 1.58
1.58 ! ray 1: /* $OpenBSD: cmds.c,v 1.57 2007/09/11 15:47:17 gilles 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.58 ! ray 63: static const char rcsid[] = "$OpenBSD: cmds.c,v 1.57 2007/09/11 15:47:17 gilles 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: */
1.48 deraadt 192: /*ARGSUSED*/
1.1 deraadt 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: */
1.48 deraadt 204: /*ARGSUSED*/
1.1 deraadt 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: */
1.48 deraadt 216: /*ARGSUSED*/
1.1 deraadt 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:
1.55 ray 534: /* XXX - Signal race. */
1.1 deraadt 535: /* ARGSUSED */
536: void
1.47 deraadt 537: mabort(int signo)
1.1 deraadt 538: {
1.13 millert 539: int ointer, oconf;
1.1 deraadt 540:
1.13 millert 541: alarmtimer(0);
1.20 deraadt 542: putc('\n', ttyout);
543: (void)fflush(ttyout);
1.1 deraadt 544: if (mflag && fromatty) {
545: ointer = interactive;
1.13 millert 546: oconf = confirmrest;
1.1 deraadt 547: interactive = 1;
1.13 millert 548: confirmrest = 0;
1.1 deraadt 549: if (confirm("Continue with", mname)) {
550: interactive = ointer;
1.13 millert 551: confirmrest = oconf;
1.40 art 552: longjmp(jabort, 1);
1.1 deraadt 553: }
554: interactive = ointer;
1.13 millert 555: confirmrest = oconf;
1.1 deraadt 556: }
557: mflag = 0;
1.40 art 558: longjmp(jabort, 1);
1.1 deraadt 559: }
560:
561: /*
562: * Get multiple files.
563: */
564: void
1.47 deraadt 565: mget(int argc, char *argv[])
1.1 deraadt 566: {
567: sig_t oldintr;
568: int ch, ointer;
1.49 otto 569: char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN], localcwd[MAXPATHLEN];
1.1 deraadt 570:
571: if (argc < 2 && !another(&argc, &argv, "remote-files")) {
1.20 deraadt 572: fprintf(ttyout, "usage: %s remote-files\n", argv[0]);
1.1 deraadt 573: code = -1;
574: return;
575: }
576: mname = argv[0];
577: mflag = 1;
1.49 otto 578: if (getcwd(localcwd, sizeof(localcwd)) == NULL)
579: err(1, "can't get cwd");
580:
1.1 deraadt 581: oldintr = signal(SIGINT, mabort);
1.14 millert 582: (void)setjmp(jabort);
1.16 millert 583: while ((cp = remglob(argv, proxy, NULL)) != NULL) {
1.1 deraadt 584: if (*cp == '\0') {
585: mflag = 0;
586: continue;
587: }
1.49 otto 588: if (!mflag)
589: continue;
590: if (!fileindir(cp, localcwd)) {
591: fprintf(ttyout, "Skipping non-relative filename `%s'\n",
592: cp);
593: continue;
594: }
595: if (confirm(argv[0], cp)) {
1.1 deraadt 596: tp = cp;
597: if (mcase) {
1.21 millert 598: for (tp2 = tmpbuf; (ch = *tp++) != 0; )
1.1 deraadt 599: *tp2++ = isupper(ch) ? tolower(ch) : ch;
600: *tp2 = '\0';
601: tp = tmpbuf;
602: }
1.21 millert 603: if (ntflag)
1.1 deraadt 604: tp = dotrans(tp);
1.21 millert 605: if (mapflag)
1.1 deraadt 606: tp = domap(tp);
607: recvrequest("RETR", tp, cp, "w",
1.23 millert 608: tp != cp || !interactive, 1);
1.1 deraadt 609: if (!mflag && fromatty) {
610: ointer = interactive;
611: interactive = 1;
1.13 millert 612: if (confirm("Continue with", "mget")) {
1.1 deraadt 613: mflag++;
614: }
615: interactive = ointer;
616: }
617: }
618: }
1.14 millert 619: (void)signal(SIGINT, oldintr);
1.1 deraadt 620: mflag = 0;
621: }
622:
623: char *
1.47 deraadt 624: onoff(int bool)
1.1 deraadt 625: {
626:
627: return (bool ? "on" : "off");
628: }
629:
630: /*
631: * Show status.
632: */
633: /*ARGSUSED*/
634: void
1.47 deraadt 635: status(int argc, char *argv[])
1.1 deraadt 636: {
637: int i;
638:
639: if (connected)
1.20 deraadt 640: fprintf(ttyout, "Connected %sto %s.\n",
1.19 millert 641: connected == -1 ? "and logged in" : "", hostname);
1.1 deraadt 642: else
1.20 deraadt 643: fputs("Not connected.\n", ttyout);
1.1 deraadt 644: if (!proxy) {
645: pswitch(1);
646: if (connected) {
1.20 deraadt 647: fprintf(ttyout, "Connected for proxy commands to %s.\n",
1.13 millert 648: hostname);
1.1 deraadt 649: }
650: else {
1.20 deraadt 651: fputs("No proxy connection.\n", ttyout);
1.1 deraadt 652: }
653: pswitch(0);
654: }
1.32 itojun 655: fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n", onoff(gatemode),
656: *gateserver ? gateserver : "(none)", gateport);
1.20 deraadt 657: fprintf(ttyout, "Passive mode: %s.\n", onoff(passivemode));
658: fprintf(ttyout, "Mode: %s; Type: %s; Form: %s; Structure: %s.\n",
1.1 deraadt 659: modename, typename, formname, structname);
1.20 deraadt 660: fprintf(ttyout, "Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s.\n",
1.1 deraadt 661: onoff(verbose), onoff(bell), onoff(interactive),
662: onoff(doglob));
1.20 deraadt 663: fprintf(ttyout, "Store unique: %s; Receive unique: %s.\n", onoff(sunique),
1.1 deraadt 664: onoff(runique));
1.20 deraadt 665: fprintf(ttyout, "Preserve modification times: %s.\n", onoff(preserve));
666: fprintf(ttyout, "Case: %s; CR stripping: %s.\n", onoff(mcase), onoff(crflag));
1.1 deraadt 667: if (ntflag) {
1.20 deraadt 668: fprintf(ttyout, "Ntrans: (in) %s (out) %s\n", ntin, ntout);
1.1 deraadt 669: }
670: else {
1.20 deraadt 671: fputs("Ntrans: off.\n", ttyout);
1.1 deraadt 672: }
673: if (mapflag) {
1.20 deraadt 674: fprintf(ttyout, "Nmap: (in) %s (out) %s\n", mapin, mapout);
1.1 deraadt 675: }
676: else {
1.20 deraadt 677: fputs("Nmap: off.\n", ttyout);
1.1 deraadt 678: }
1.20 deraadt 679: fprintf(ttyout, "Hash mark printing: %s; Mark count: %d; Progress bar: %s.\n",
1.13 millert 680: onoff(hash), mark, onoff(progress));
1.32 itojun 681: fprintf(ttyout, "Use of PORT/LPRT cmds: %s.\n", onoff(sendport));
1.34 itojun 682: fprintf(ttyout, "Use of EPSV/EPRT cmds for IPv4: %s%s.\n", onoff(epsv4),
683: epsv4bad ? " (disabled for this connection)" : "");
1.17 millert 684: #ifndef SMALL
1.20 deraadt 685: fprintf(ttyout, "Command line editing: %s.\n", onoff(editing));
1.17 millert 686: #endif /* !SMALL */
1.1 deraadt 687: if (macnum > 0) {
1.27 millert 688: fputs("Macros:\n", ttyout);
1.1 deraadt 689: for (i=0; i<macnum; i++) {
1.20 deraadt 690: fprintf(ttyout, "\t%s\n", macros[i].mac_name);
1.1 deraadt 691: }
692: }
693: code = 0;
694: }
695:
696: /*
1.13 millert 697: * Toggle a variable
698: */
699: int
1.47 deraadt 700: togglevar(int argc, char *argv[], int *var, const char *mesg)
1.13 millert 701: {
702: if (argc < 2) {
703: *var = !*var;
704: } else if (argc == 2 && strcasecmp(argv[1], "on") == 0) {
705: *var = 1;
706: } else if (argc == 2 && strcasecmp(argv[1], "off") == 0) {
707: *var = 0;
708: } else {
1.20 deraadt 709: fprintf(ttyout, "usage: %s [ on | off ]\n", argv[0]);
1.16 millert 710: return (-1);
1.13 millert 711: }
1.15 millert 712: if (mesg)
1.20 deraadt 713: fprintf(ttyout, "%s %s.\n", mesg, onoff(*var));
1.14 millert 714: return (*var);
1.13 millert 715: }
716:
717: /*
1.1 deraadt 718: * Set beep on cmd completed mode.
719: */
1.48 deraadt 720: /*ARGSUSED*/
1.1 deraadt 721: void
1.47 deraadt 722: setbell(int argc, char *argv[])
1.1 deraadt 723: {
724:
1.13 millert 725: code = togglevar(argc, argv, &bell, "Bell mode");
1.1 deraadt 726: }
727:
1.17 millert 728: #ifndef SMALL
1.1 deraadt 729: /*
1.13 millert 730: * Set command line editing
1.1 deraadt 731: */
1.48 deraadt 732: /*ARGSUSED*/
1.1 deraadt 733: void
1.47 deraadt 734: setedit(int argc, char *argv[])
1.1 deraadt 735: {
736:
1.13 millert 737: code = togglevar(argc, argv, &editing, "Editing mode");
1.18 millert 738: controlediting();
1.1 deraadt 739: }
1.17 millert 740: #endif /* !SMALL */
1.34 itojun 741:
742: /*
743: * Toggle use of IPv4 EPSV/EPRT
744: */
1.48 deraadt 745: /*ARGSUSED*/
1.34 itojun 746: void
1.47 deraadt 747: setepsv4(int argc, char *argv[])
1.34 itojun 748: {
749:
750: code = togglevar(argc, argv, &epsv4, "EPSV/EPRT on IPv4");
751: epsv4bad = 0;
752: }
1.1 deraadt 753:
754: /*
1.13 millert 755: * Turn on packet tracing.
1.1 deraadt 756: */
1.48 deraadt 757: /*ARGSUSED*/
1.1 deraadt 758: void
1.47 deraadt 759: settrace(int argc, char *argv[])
1.1 deraadt 760: {
761:
1.13 millert 762: code = togglevar(argc, argv, &trace, "Packet tracing");
1.1 deraadt 763: }
1.6 kstailey 764:
765: /*
1.13 millert 766: * Toggle hash mark printing during transfers, or set hash mark bytecount.
1.6 kstailey 767: */
1.48 deraadt 768: /*ARGSUSED*/
1.6 kstailey 769: void
1.47 deraadt 770: sethash(int argc, char *argv[])
1.6 kstailey 771: {
772: if (argc == 1)
1.13 millert 773: hash = !hash;
1.6 kstailey 774: else if (argc != 2) {
1.20 deraadt 775: fprintf(ttyout, "usage: %s [ on | off | bytecount ]\n", argv[0]);
1.13 millert 776: code = -1;
777: return;
778: } else if (strcasecmp(argv[1], "on") == 0)
779: hash = 1;
780: else if (strcasecmp(argv[1], "off") == 0)
781: hash = 0;
782: else {
1.50 tedu 783: int nmark;
784: const char *errstr;
1.28 millert 785:
1.50 tedu 786: nmark = strtonum(argv[1], 1, INT_MAX, &errstr);
787: if (errstr) {
788: fprintf(ttyout, "bytecount value is %s: %s\n",
789: errstr, argv[1]);
1.13 millert 790: code = -1;
791: return;
1.6 kstailey 792: }
1.13 millert 793: mark = nmark;
794: hash = 1;
1.6 kstailey 795: }
1.20 deraadt 796: fprintf(ttyout, "Hash mark printing %s", onoff(hash));
1.13 millert 797: if (hash)
1.20 deraadt 798: fprintf(ttyout, " (%d bytes/hash mark)", mark);
799: fputs(".\n", ttyout);
1.13 millert 800: code = hash;
1.6 kstailey 801: }
802:
1.1 deraadt 803: /*
804: * Turn on printing of server echo's.
805: */
1.48 deraadt 806: /*ARGSUSED*/
1.1 deraadt 807: void
1.47 deraadt 808: setverbose(int argc, char *argv[])
1.1 deraadt 809: {
810:
1.13 millert 811: code = togglevar(argc, argv, &verbose, "Verbose mode");
1.1 deraadt 812: }
813:
814: /*
1.32 itojun 815: * Toggle PORT/LPRT cmd use before each data connection.
1.1 deraadt 816: */
1.48 deraadt 817: /*ARGSUSED*/
1.1 deraadt 818: void
1.47 deraadt 819: setport(int argc, char *argv[])
1.1 deraadt 820: {
821:
1.32 itojun 822: code = togglevar(argc, argv, &sendport, "Use of PORT/LPRT cmds");
1.13 millert 823: }
824:
825: /*
826: * Toggle transfer progress bar.
827: */
1.48 deraadt 828: /*ARGSUSED*/
1.13 millert 829: void
1.47 deraadt 830: setprogress(int argc, char *argv[])
1.13 millert 831: {
832:
833: code = togglevar(argc, argv, &progress, "Progress bar");
1.1 deraadt 834: }
835:
836: /*
1.23 millert 837: * Turn on interactive prompting during mget, mput, and mdelete.
1.1 deraadt 838: */
1.48 deraadt 839: /*ARGSUSED*/
1.1 deraadt 840: void
1.47 deraadt 841: setprompt(int argc, char *argv[])
1.1 deraadt 842: {
843:
1.13 millert 844: code = togglevar(argc, argv, &interactive, "Interactive mode");
1.1 deraadt 845: }
846:
847: /*
1.23 millert 848: * Toggle gate-ftp mode, or set gate-ftp server
849: */
1.48 deraadt 850: /*ARGSUSED*/
1.23 millert 851: void
1.47 deraadt 852: setgate(int argc, char *argv[])
1.23 millert 853: {
854: static char gsbuf[MAXHOSTNAMELEN];
855:
856: if (argc > 3) {
857: fprintf(ttyout, "usage: %s [ on | off | gateserver [ port ] ]\n",
858: argv[0]);
859: code = -1;
860: return;
861: } else if (argc < 2) {
862: gatemode = !gatemode;
863: } else {
864: if (argc == 2 && strcasecmp(argv[1], "on") == 0)
865: gatemode = 1;
866: else if (argc == 2 && strcasecmp(argv[1], "off") == 0)
867: gatemode = 0;
868: else {
869: if (argc == 3) {
1.32 itojun 870: gateport = strdup(argv[2]);
1.41 deraadt 871: if (gateport == NULL)
872: err(1, NULL);
1.23 millert 873: }
1.36 lebel 874: strlcpy(gsbuf, argv[1], sizeof(gsbuf));
1.23 millert 875: gateserver = gsbuf;
876: gatemode = 1;
877: }
878: }
879: if (gatemode && (gateserver == NULL || *gateserver == '\0')) {
880: fprintf(ttyout,
881: "Disabling gate-ftp mode - no gate-ftp server defined.\n");
882: gatemode = 0;
883: } else {
1.32 itojun 884: fprintf(ttyout, "Gate ftp: %s, server %s, port %s.\n",
1.23 millert 885: onoff(gatemode),
1.32 itojun 886: *gateserver ? gateserver : "(none)", gateport);
1.23 millert 887: }
888: code = gatemode;
889: }
890:
891: /*
892: * Toggle metacharacter interpretation on local file names.
1.1 deraadt 893: */
1.48 deraadt 894: /*ARGSUSED*/
1.1 deraadt 895: void
1.47 deraadt 896: setglob(int argc, char *argv[])
1.1 deraadt 897: {
1.13 millert 898:
899: code = togglevar(argc, argv, &doglob, "Globbing");
900: }
901:
902: /*
1.31 aaron 903: * Toggle preserving modification times on retrieved files.
1.13 millert 904: */
1.48 deraadt 905: /*ARGSUSED*/
1.13 millert 906: void
1.47 deraadt 907: setpreserve(int argc, char *argv[])
1.13 millert 908: {
909:
910: code = togglevar(argc, argv, &preserve, "Preserve modification times");
1.1 deraadt 911: }
912:
913: /*
1.23 millert 914: * Set debugging mode on/off and/or set level of debugging.
1.1 deraadt 915: */
1.48 deraadt 916: /*ARGSUSED*/
1.1 deraadt 917: void
1.47 deraadt 918: setdebug(int argc, char *argv[])
1.1 deraadt 919: {
1.13 millert 920: if (argc > 2) {
1.20 deraadt 921: fprintf(ttyout, "usage: %s [ on | off | debuglevel ]\n", argv[0]);
1.13 millert 922: code = -1;
923: return;
924: } else if (argc == 2) {
925: if (strcasecmp(argv[1], "on") == 0)
926: debug = 1;
927: else if (strcasecmp(argv[1], "off") == 0)
928: debug = 0;
929: else {
1.50 tedu 930: const char *errstr;
931: int val;
1.21 millert 932:
1.50 tedu 933: val = strtonum(argv[1], 0, INT_MAX, &errstr);
934: if (errstr) {
935: fprintf(ttyout, "debugging value is %s: %s\n",
936: errstr, argv[1]);
1.13 millert 937: code = -1;
938: return;
939: }
1.50 tedu 940: debug = val;
1.1 deraadt 941: }
942: } else
1.13 millert 943: debug = !debug;
1.1 deraadt 944: if (debug)
945: options |= SO_DEBUG;
946: else
947: options &= ~SO_DEBUG;
1.20 deraadt 948: fprintf(ttyout, "Debugging %s (debug=%d).\n", onoff(debug), debug);
1.1 deraadt 949: code = debug > 0;
950: }
951:
952: /*
1.23 millert 953: * Set current working directory on remote machine.
1.1 deraadt 954: */
1.13 millert 955: void
1.47 deraadt 956: cd(int argc, char *argv[])
1.1 deraadt 957: {
1.13 millert 958: int r;
1.1 deraadt 959:
1.13 millert 960: if ((argc < 2 && !another(&argc, &argv, "remote-directory")) ||
961: argc > 2) {
1.20 deraadt 962: fprintf(ttyout, "usage: %s remote-directory\n", argv[0]);
1.1 deraadt 963: code = -1;
1.13 millert 964: return;
1.1 deraadt 965: }
1.13 millert 966: r = command("CWD %s", argv[1]);
967: if (r == ERROR && code == 500) {
968: if (verbose)
1.20 deraadt 969: fputs("CWD command not recognized, trying XCWD.\n", ttyout);
1.13 millert 970: r = command("XCWD %s", argv[1]);
1.42 deraadt 971: }
972: if (r == ERROR && code == 550) {
973: dirchange = 0;
974: return;
1.1 deraadt 975: }
1.13 millert 976: if (r == COMPLETE)
977: dirchange = 1;
1.1 deraadt 978: }
979:
980: /*
1.23 millert 981: * Set current working directory on local machine.
1.1 deraadt 982: */
983: void
1.47 deraadt 984: lcd(int argc, char *argv[])
1.1 deraadt 985: {
986: char buf[MAXPATHLEN];
1.23 millert 987: char *oldargv1;
1.1 deraadt 988:
989: if (argc < 2)
990: argc++, argv[1] = home;
991: if (argc != 2) {
1.20 deraadt 992: fprintf(ttyout, "usage: %s local-directory\n", argv[0]);
1.1 deraadt 993: code = -1;
994: return;
995: }
1.23 millert 996: oldargv1 = argv[1];
1.1 deraadt 997: if (!globulize(&argv[1])) {
998: code = -1;
999: return;
1000: }
1001: if (chdir(argv[1]) < 0) {
1002: warn("local: %s", argv[1]);
1003: code = -1;
1.23 millert 1004: } else {
1005: if (getcwd(buf, sizeof(buf)) != NULL)
1006: fprintf(ttyout, "Local directory now %s\n", buf);
1007: else
1008: warn("getcwd: %s", argv[1]);
1009: code = 0;
1.1 deraadt 1010: }
1.23 millert 1011: if (oldargv1 != argv[1]) /* free up after globulize() */
1012: free(argv[1]);
1.1 deraadt 1013: }
1014:
1015: /*
1016: * Delete a single file.
1017: */
1018: void
1.48 deraadt 1019: deletecmd(int argc, char *argv[])
1.1 deraadt 1020: {
1021:
1.13 millert 1022: if ((argc < 2 && !another(&argc, &argv, "remote-file")) || argc > 2) {
1.20 deraadt 1023: fprintf(ttyout, "usage: %s remote-file\n", argv[0]);
1.1 deraadt 1024: code = -1;
1025: return;
1026: }
1.14 millert 1027: (void)command("DELE %s", argv[1]);
1.1 deraadt 1028: }
1029:
1030: /*
1031: * Delete multiple files.
1032: */
1033: void
1.47 deraadt 1034: mdelete(int argc, char *argv[])
1.1 deraadt 1035: {
1036: sig_t oldintr;
1037: int ointer;
1038: char *cp;
1039:
1040: if (argc < 2 && !another(&argc, &argv, "remote-files")) {
1.20 deraadt 1041: fprintf(ttyout, "usage: %s remote-files\n", argv[0]);
1.1 deraadt 1042: code = -1;
1043: return;
1044: }
1045: mname = argv[0];
1046: mflag = 1;
1047: oldintr = signal(SIGINT, mabort);
1.14 millert 1048: (void)setjmp(jabort);
1.16 millert 1049: while ((cp = remglob(argv, 0, NULL)) != NULL) {
1.1 deraadt 1050: if (*cp == '\0') {
1051: mflag = 0;
1052: continue;
1053: }
1054: if (mflag && confirm(argv[0], cp)) {
1.14 millert 1055: (void)command("DELE %s", cp);
1.1 deraadt 1056: if (!mflag && fromatty) {
1057: ointer = interactive;
1058: interactive = 1;
1059: if (confirm("Continue with", "mdelete")) {
1060: mflag++;
1061: }
1062: interactive = ointer;
1063: }
1064: }
1065: }
1.14 millert 1066: (void)signal(SIGINT, oldintr);
1.1 deraadt 1067: mflag = 0;
1068: }
1069:
1070: /*
1071: * Rename a remote file.
1072: */
1073: void
1.47 deraadt 1074: renamefile(int argc, char *argv[])
1.1 deraadt 1075: {
1076:
1077: if (argc < 2 && !another(&argc, &argv, "from-name"))
1078: goto usage;
1.13 millert 1079: if ((argc < 3 && !another(&argc, &argv, "to-name")) || argc > 3) {
1.1 deraadt 1080: usage:
1.20 deraadt 1081: fprintf(ttyout, "usage: %s from-name to-name\n", argv[0]);
1.1 deraadt 1082: code = -1;
1083: return;
1084: }
1085: if (command("RNFR %s", argv[1]) == CONTINUE)
1.14 millert 1086: (void)command("RNTO %s", argv[2]);
1.1 deraadt 1087: }
1088:
1089: /*
1.23 millert 1090: * Get a directory listing of remote files.
1.1 deraadt 1091: */
1092: void
1.47 deraadt 1093: ls(int argc, char *argv[])
1.1 deraadt 1094: {
1.13 millert 1095: const char *cmd;
1.23 millert 1096: char *oldargv2, *globargv2;
1.1 deraadt 1097:
1098: if (argc < 2)
1099: argc++, argv[1] = NULL;
1100: if (argc < 3)
1101: argc++, argv[2] = "-";
1102: if (argc > 3) {
1.20 deraadt 1103: fprintf(ttyout, "usage: %s remote-directory local-file\n", argv[0]);
1.1 deraadt 1104: code = -1;
1105: return;
1106: }
1.33 millert 1107: cmd = strcmp(argv[0], "nlist") == 0 ? "NLST" : "LIST";
1.23 millert 1108: oldargv2 = argv[2];
1.1 deraadt 1109: if (strcmp(argv[2], "-") && !globulize(&argv[2])) {
1110: code = -1;
1111: return;
1112: }
1.23 millert 1113: globargv2 = argv[2];
1114: if (strcmp(argv[2], "-") && *argv[2] != '|' && (!globulize(&argv[2]) ||
1115: !confirm("output to local-file:", argv[2]))) {
1116: code = -1;
1117: goto freels;
1.1 deraadt 1118: }
1.23 millert 1119: recvrequest(cmd, argv[2], argv[1], "w", 0, 0);
1.3 downsj 1120:
1121: /* flush results in case commands are coming from a pipe */
1.20 deraadt 1122: fflush(ttyout);
1.23 millert 1123: freels:
1124: if (argv[2] != globargv2) /* free up after globulize() */
1125: free(argv[2]);
1126: if (globargv2 != oldargv2)
1127: free(globargv2);
1.1 deraadt 1128: }
1129:
1130: /*
1.23 millert 1131: * Get a directory listing of multiple remote files.
1.1 deraadt 1132: */
1133: void
1.47 deraadt 1134: mls(int argc, char *argv[])
1.1 deraadt 1135: {
1136: sig_t oldintr;
1137: int ointer, i;
1.51 ray 1138: char lmode[1], *dest, *odest;
1.1 deraadt 1139:
1140: if (argc < 2 && !another(&argc, &argv, "remote-files"))
1141: goto usage;
1142: if (argc < 3 && !another(&argc, &argv, "local-file")) {
1143: usage:
1.20 deraadt 1144: fprintf(ttyout, "usage: %s remote-files local-file\n", argv[0]);
1.1 deraadt 1145: code = -1;
1146: return;
1147: }
1.23 millert 1148: odest = dest = argv[argc - 1];
1.1 deraadt 1149: argv[argc - 1] = NULL;
1150: if (strcmp(dest, "-") && *dest != '|')
1151: if (!globulize(&dest) ||
1152: !confirm("output to local-file:", dest)) {
1153: code = -1;
1154: return;
1155: }
1156: mname = argv[0];
1157: mflag = 1;
1158: oldintr = signal(SIGINT, mabort);
1.14 millert 1159: (void)setjmp(jabort);
1.1 deraadt 1160: for (i = 1; mflag && i < argc-1; ++i) {
1.51 ray 1161: *lmode = (i == 1) ? 'w' : 'a';
1162: recvrequest("LIST", dest, argv[i], lmode, 0, 0);
1.1 deraadt 1163: if (!mflag && fromatty) {
1164: ointer = interactive;
1165: interactive = 1;
1166: if (confirm("Continue with", argv[0])) {
1167: mflag ++;
1168: }
1169: interactive = ointer;
1170: }
1171: }
1.14 millert 1172: (void)signal(SIGINT, oldintr);
1.1 deraadt 1173: mflag = 0;
1.23 millert 1174: if (dest != odest) /* free up after globulize() */
1175: free(dest);
1.1 deraadt 1176: }
1177:
1178: /*
1179: * Do a shell escape
1180: */
1181: /*ARGSUSED*/
1182: void
1.47 deraadt 1183: shell(int argc, char *argv[])
1.1 deraadt 1184: {
1185: pid_t pid;
1186: sig_t old1, old2;
1.51 ray 1187: char shellnam[MAXPATHLEN], *shellp, *namep;
1.24 millert 1188: int wait_status;
1.1 deraadt 1189:
1190: old1 = signal (SIGINT, SIG_IGN);
1191: old2 = signal (SIGQUIT, SIG_IGN);
1192: if ((pid = fork()) == 0) {
1193: for (pid = 3; pid < 20; pid++)
1.14 millert 1194: (void)close(pid);
1195: (void)signal(SIGINT, SIG_DFL);
1196: (void)signal(SIGQUIT, SIG_DFL);
1.51 ray 1197: shellp = getenv("SHELL");
1198: if (shellp == NULL || *shellp == '\0')
1199: shellp = _PATH_BSHELL;
1200: namep = strrchr(shellp, '/');
1.1 deraadt 1201: if (namep == NULL)
1.51 ray 1202: namep = shellp;
1.13 millert 1203: shellnam[0] = '-';
1.36 lebel 1204: (void)strlcpy(shellnam + 1, ++namep, sizeof(shellnam) - 1);
1.1 deraadt 1205: if (strcmp(namep, "sh") != 0)
1206: shellnam[0] = '+';
1207: if (debug) {
1.51 ray 1208: fputs(shellp, ttyout);
1.21 millert 1209: fputc('\n', ttyout);
1.20 deraadt 1210: (void)fflush(ttyout);
1.1 deraadt 1211: }
1212: if (argc > 1) {
1.51 ray 1213: execl(shellp, shellnam, "-c", altarg, (char *)0);
1.1 deraadt 1214: }
1215: else {
1.51 ray 1216: execl(shellp, shellnam, (char *)0);
1.1 deraadt 1217: }
1.51 ray 1218: warn("%s", shellp);
1.1 deraadt 1219: code = -1;
1220: exit(1);
1221: }
1222: if (pid > 0)
1.24 millert 1223: while (wait(&wait_status) != pid)
1.1 deraadt 1224: ;
1.14 millert 1225: (void)signal(SIGINT, old1);
1226: (void)signal(SIGQUIT, old2);
1.1 deraadt 1227: if (pid == -1) {
1.16 millert 1228: warn("Try again later");
1.1 deraadt 1229: code = -1;
1230: }
1231: else {
1232: code = 0;
1233: }
1234: }
1235:
1236: /*
1237: * Send new user information (re-login)
1238: */
1239: void
1.47 deraadt 1240: user(int argc, char *argv[])
1.1 deraadt 1241: {
1.51 ray 1242: char acctname[80];
1.1 deraadt 1243: int n, aflag = 0;
1244:
1245: if (argc < 2)
1.14 millert 1246: (void)another(&argc, &argv, "username");
1.1 deraadt 1247: if (argc < 2 || argc > 4) {
1.20 deraadt 1248: fprintf(ttyout, "usage: %s username [password] [account]\n", argv[0]);
1.1 deraadt 1249: code = -1;
1250: return;
1251: }
1252: n = command("USER %s", argv[1]);
1253: if (n == CONTINUE) {
1254: if (argc < 3 )
1.56 millert 1255: argv[2] = getpass("Password:"), argc++;
1.1 deraadt 1256: n = command("PASS %s", argv[2]);
1257: }
1258: if (n == CONTINUE) {
1259: if (argc < 4) {
1.20 deraadt 1260: (void)fputs("Account: ", ttyout);
1261: (void)fflush(ttyout);
1.54 ray 1262: if (fgets(acctname, sizeof(acctname), stdin) == NULL)
1.53 ray 1263: goto fail;
1.57 gilles 1264:
1265: acctname[strcspn(acctname, "\n")] = '\0';
1266:
1.51 ray 1267: argv[3] = acctname;
1268: argc++;
1.1 deraadt 1269: }
1270: n = command("ACCT %s", argv[3]);
1271: aflag++;
1272: }
1273: if (n != COMPLETE) {
1.53 ray 1274: fail:
1.20 deraadt 1275: fputs("Login failed.\n", ttyout);
1.1 deraadt 1276: return;
1277: }
1278: if (!aflag && argc == 4) {
1.14 millert 1279: (void)command("ACCT %s", argv[3]);
1.1 deraadt 1280: }
1.19 millert 1281: connected = -1;
1.1 deraadt 1282: }
1283:
1284: /*
1.13 millert 1285: * Print working directory on remote machine.
1.1 deraadt 1286: */
1.48 deraadt 1287: /*ARGSUSED*/
1.1 deraadt 1288: void
1.47 deraadt 1289: pwd(int argc, char *argv[])
1.1 deraadt 1290: {
1291: int oldverbose = verbose;
1292:
1293: /*
1294: * If we aren't verbose, this doesn't do anything!
1295: */
1296: verbose = 1;
1297: if (command("PWD") == ERROR && code == 500) {
1.20 deraadt 1298: fputs("PWD command not recognized, trying XPWD.\n", ttyout);
1.14 millert 1299: (void)command("XPWD");
1.1 deraadt 1300: }
1301: verbose = oldverbose;
1302: }
1303:
1304: /*
1.13 millert 1305: * Print working directory on local machine.
1306: */
1.48 deraadt 1307: /* ARGSUSED */
1.13 millert 1308: void
1.47 deraadt 1309: lpwd(int argc, char *argv[])
1.13 millert 1310: {
1311: char buf[MAXPATHLEN];
1312:
1313: if (getcwd(buf, sizeof(buf)) != NULL)
1.20 deraadt 1314: fprintf(ttyout, "Local directory %s\n", buf);
1.13 millert 1315: else
1316: warn("getcwd");
1317: code = 0;
1318: }
1319:
1320: /*
1.1 deraadt 1321: * Make a directory.
1322: */
1323: void
1.47 deraadt 1324: makedir(int argc, char *argv[])
1.1 deraadt 1325: {
1326:
1.13 millert 1327: if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1328: argc > 2) {
1.20 deraadt 1329: fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1.1 deraadt 1330: code = -1;
1331: return;
1332: }
1333: if (command("MKD %s", argv[1]) == ERROR && code == 500) {
1334: if (verbose)
1.20 deraadt 1335: fputs("MKD command not recognized, trying XMKD.\n", ttyout);
1.14 millert 1336: (void)command("XMKD %s", argv[1]);
1.1 deraadt 1337: }
1338: }
1339:
1340: /*
1341: * Remove a directory.
1342: */
1343: void
1.47 deraadt 1344: removedir(int argc, char *argv[])
1.1 deraadt 1345: {
1346:
1.13 millert 1347: if ((argc < 2 && !another(&argc, &argv, "directory-name")) ||
1348: argc > 2) {
1.20 deraadt 1349: fprintf(ttyout, "usage: %s directory-name\n", argv[0]);
1.1 deraadt 1350: code = -1;
1351: return;
1352: }
1353: if (command("RMD %s", argv[1]) == ERROR && code == 500) {
1354: if (verbose)
1.20 deraadt 1355: fputs("RMD command not recognized, trying XRMD.\n", ttyout);
1.14 millert 1356: (void)command("XRMD %s", argv[1]);
1.1 deraadt 1357: }
1358: }
1359:
1360: /*
1361: * Send a line, verbatim, to the remote machine.
1362: */
1363: void
1.47 deraadt 1364: quote(int argc, char *argv[])
1.1 deraadt 1365: {
1366:
1367: if (argc < 2 && !another(&argc, &argv, "command line to send")) {
1.20 deraadt 1368: fprintf(ttyout, "usage: %s line-to-send\n", argv[0]);
1.1 deraadt 1369: code = -1;
1370: return;
1371: }
1372: quote1("", argc, argv);
1373: }
1374:
1375: /*
1376: * Send a SITE command to the remote machine. The line
1377: * is sent verbatim to the remote machine, except that the
1378: * word "SITE" is added at the front.
1379: */
1380: void
1.47 deraadt 1381: site(int argc, char *argv[])
1.1 deraadt 1382: {
1383:
1384: if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) {
1.20 deraadt 1385: fprintf(ttyout, "usage: %s line-to-send\n", argv[0]);
1.1 deraadt 1386: code = -1;
1387: return;
1388: }
1.26 weingart 1389: quote1("SITE", argc, argv);
1.1 deraadt 1390: }
1391:
1392: /*
1393: * Turn argv[1..argc) into a space-separated string, then prepend initial text.
1394: * Send the result as a one-line command and get response.
1395: */
1396: void
1.47 deraadt 1397: quote1(const char *initial, int argc, char *argv[])
1.1 deraadt 1398: {
1399: int i, len;
1400: char buf[BUFSIZ]; /* must be >= sizeof(line) */
1401:
1.36 lebel 1402: (void)strlcpy(buf, initial, sizeof(buf));
1.1 deraadt 1403: if (argc > 1) {
1.26 weingart 1404: for (i = 1, len = strlen(buf); i < argc && len < sizeof(buf)-1; i++) {
1405: /* Space for next arg */
1406: if (len > 1)
1407: buf[len++] = ' ';
1408:
1409: /* Sanity check */
1410: if (len >= sizeof(buf) - 1)
1411: break;
1412:
1.27 millert 1413: /* Copy next argument, NUL terminate always */
1.36 lebel 1414: strlcpy(&buf[len], argv[i], sizeof(buf) - len);
1.26 weingart 1415:
1416: /* Update string length */
1417: len = strlen(buf);
1.1 deraadt 1418: }
1419: }
1.26 weingart 1420:
1.35 aaron 1421: /* Make double (triple?) sure the sucker is NUL terminated */
1.26 weingart 1422: buf[sizeof(buf) - 1] = '\0';
1423:
1.29 deraadt 1424: if (command("%s", buf) == PRELIM) {
1.1 deraadt 1425: while (getreply(0) == PRELIM)
1426: continue;
1427: }
1428: }
1429:
1430: void
1.47 deraadt 1431: do_chmod(int argc, char *argv[])
1.1 deraadt 1432: {
1433:
1434: if (argc < 2 && !another(&argc, &argv, "mode"))
1435: goto usage;
1.13 millert 1436: if ((argc < 3 && !another(&argc, &argv, "file-name")) || argc > 3) {
1.1 deraadt 1437: usage:
1.20 deraadt 1438: fprintf(ttyout, "usage: %s mode file-name\n", argv[0]);
1.1 deraadt 1439: code = -1;
1440: return;
1441: }
1.14 millert 1442: (void)command("SITE CHMOD %s %s", argv[1], argv[2]);
1.1 deraadt 1443: }
1444:
1445: void
1.47 deraadt 1446: do_umask(int argc, char *argv[])
1.1 deraadt 1447: {
1448: int oldverbose = verbose;
1449:
1450: verbose = 1;
1.14 millert 1451: (void)command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]);
1.1 deraadt 1452: verbose = oldverbose;
1453: }
1454:
1455: void
1.47 deraadt 1456: idle(int argc, char *argv[])
1.1 deraadt 1457: {
1458: int oldverbose = verbose;
1459:
1460: verbose = 1;
1.14 millert 1461: (void)command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]);
1.1 deraadt 1462: verbose = oldverbose;
1463: }
1464:
1465: /*
1466: * Ask the other side for help.
1467: */
1468: void
1.47 deraadt 1469: rmthelp(int argc, char *argv[])
1.1 deraadt 1470: {
1471: int oldverbose = verbose;
1472:
1473: verbose = 1;
1.14 millert 1474: (void)command(argc == 1 ? "HELP" : "HELP %s", argv[1]);
1.1 deraadt 1475: verbose = oldverbose;
1476: }
1477:
1478: /*
1479: * Terminate session and exit.
1480: */
1.48 deraadt 1481: /*ARGSUSED*/
1.1 deraadt 1482: void
1.47 deraadt 1483: quit(int argc, char *argv[])
1.1 deraadt 1484: {
1485:
1486: if (connected)
1487: disconnect(0, 0);
1488: pswitch(1);
1489: if (connected) {
1490: disconnect(0, 0);
1491: }
1492: exit(0);
1493: }
1494:
1495: /*
1496: * Terminate session, but don't exit.
1497: */
1.48 deraadt 1498: /* ARGSUSED */
1.1 deraadt 1499: void
1.47 deraadt 1500: disconnect(int argc, char *argv[])
1.1 deraadt 1501: {
1502:
1503: if (!connected)
1504: return;
1.14 millert 1505: (void)command("QUIT");
1.1 deraadt 1506: if (cout) {
1.14 millert 1507: (void)fclose(cout);
1.1 deraadt 1508: }
1509: cout = NULL;
1510: connected = 0;
1511: data = -1;
1512: if (!proxy) {
1513: macnum = 0;
1514: }
1515: }
1516:
1517: void
1.47 deraadt 1518: account(int argc, char *argv[])
1.1 deraadt 1519: {
1.13 millert 1520: char *ap;
1.1 deraadt 1521:
1.13 millert 1522: if (argc > 2) {
1.20 deraadt 1523: fprintf(ttyout, "usage: %s [password]\n", argv[0]);
1.13 millert 1524: code = -1;
1525: return;
1.1 deraadt 1526: }
1.13 millert 1527: else if (argc == 2)
1528: ap = argv[1];
1529: else
1.1 deraadt 1530: ap = getpass("Account:");
1.14 millert 1531: (void)command("ACCT %s", ap);
1.1 deraadt 1532: }
1533:
1534: jmp_buf abortprox;
1535:
1.48 deraadt 1536: /* ARGSUSED */
1.1 deraadt 1537: void
1.48 deraadt 1538: proxabort(int signo)
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: }
1.51 ray 1864: /* FALLTHROUGH */
1.1 deraadt 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.48 deraadt 1901: /* ARGSUSED */
1.1 deraadt 1902: void
1.47 deraadt 1903: cdup(int argc, char *argv[])
1.1 deraadt 1904: {
1.13 millert 1905: int r;
1.1 deraadt 1906:
1.13 millert 1907: r = command("CDUP");
1908: if (r == ERROR && code == 500) {
1.1 deraadt 1909: if (verbose)
1.20 deraadt 1910: fputs("CDUP command not recognized, trying XCUP.\n", ttyout);
1.13 millert 1911: r = command("XCUP");
1.1 deraadt 1912: }
1.13 millert 1913: if (r == COMPLETE)
1914: dirchange = 1;
1.1 deraadt 1915: }
1916:
1.23 millert 1917: /*
1918: * Restart transfer at specific point
1919: */
1.1 deraadt 1920: void
1.47 deraadt 1921: restart(int argc, char *argv[])
1.1 deraadt 1922: {
1.27 millert 1923: quad_t nrestart_point;
1924: char *ep;
1.1 deraadt 1925:
1926: if (argc != 2)
1.20 deraadt 1927: fputs("restart: offset not specified.\n", ttyout);
1.1 deraadt 1928: else {
1.38 millert 1929: nrestart_point = strtoq(argv[1], &ep, 10);
1.27 millert 1930: if (nrestart_point == QUAD_MAX || *ep != '\0')
1931: fputs("restart: invalid offset.\n", ttyout);
1932: else {
1.39 millert 1933: fprintf(ttyout, "Restarting at %lld. Execute get, put "
1934: "or append to initiate transfer\n",
1.37 deraadt 1935: (long long)nrestart_point);
1.27 millert 1936: restart_point = nrestart_point;
1937: }
1.1 deraadt 1938: }
1939: }
1940:
1.23 millert 1941: /*
1942: * Show remote system type
1943: */
1.48 deraadt 1944: /* ARGSUSED */
1.1 deraadt 1945: void
1.47 deraadt 1946: syst(int argc, char *argv[])
1.1 deraadt 1947: {
1948:
1.14 millert 1949: (void)command("SYST");
1.1 deraadt 1950: }
1951:
1952: void
1.47 deraadt 1953: macdef(int argc, char *argv[])
1.1 deraadt 1954: {
1955: char *tmp;
1956: int c;
1957:
1958: if (macnum == 16) {
1.20 deraadt 1959: fputs("Limit of 16 macros have already been defined.\n", ttyout);
1.1 deraadt 1960: code = -1;
1961: return;
1962: }
1.13 millert 1963: if ((argc < 2 && !another(&argc, &argv, "macro name")) || argc > 2) {
1.20 deraadt 1964: fprintf(ttyout, "usage: %s macro_name\n", argv[0]);
1.1 deraadt 1965: code = -1;
1966: return;
1967: }
1.16 millert 1968: if (interactive)
1.20 deraadt 1969: fputs(
1970: "Enter macro line by line, terminating it with a null line.\n", ttyout);
1.36 lebel 1971: (void)strlcpy(macros[macnum].mac_name, argv[1],
1972: sizeof(macros[macnum].mac_name));
1.14 millert 1973: if (macnum == 0)
1.1 deraadt 1974: macros[macnum].mac_start = macbuf;
1.14 millert 1975: else
1.1 deraadt 1976: macros[macnum].mac_start = macros[macnum - 1].mac_end + 1;
1977: tmp = macros[macnum].mac_start;
1978: while (tmp != macbuf+4096) {
1979: if ((c = getchar()) == EOF) {
1.20 deraadt 1980: fputs("macdef: end of file encountered.\n", ttyout);
1.1 deraadt 1981: code = -1;
1982: return;
1983: }
1984: if ((*tmp = c) == '\n') {
1985: if (tmp == macros[macnum].mac_start) {
1986: macros[macnum++].mac_end = tmp;
1987: code = 0;
1988: return;
1989: }
1990: if (*(tmp-1) == '\0') {
1991: macros[macnum++].mac_end = tmp - 1;
1992: code = 0;
1993: return;
1994: }
1995: *tmp = '\0';
1996: }
1997: tmp++;
1998: }
1999: while (1) {
2000: while ((c = getchar()) != '\n' && c != EOF)
2001: /* LOOP */;
2002: if (c == EOF || getchar() == '\n') {
1.20 deraadt 2003: fputs("Macro not defined - 4K buffer exceeded.\n", ttyout);
1.1 deraadt 2004: code = -1;
2005: return;
2006: }
2007: }
2008: }
2009:
2010: /*
1.23 millert 2011: * Get size of file on remote machine
1.1 deraadt 2012: */
2013: void
1.47 deraadt 2014: sizecmd(int argc, char *argv[])
1.1 deraadt 2015: {
1.13 millert 2016: off_t size;
1.1 deraadt 2017:
1.13 millert 2018: if ((argc < 2 && !another(&argc, &argv, "filename")) || argc > 2) {
1.20 deraadt 2019: fprintf(ttyout, "usage: %s filename\n", argv[0]);
1.1 deraadt 2020: code = -1;
2021: return;
2022: }
1.13 millert 2023: size = remotesize(argv[1], 1);
2024: if (size != -1)
1.37 deraadt 2025: fprintf(ttyout, "%s\t%lld\n", argv[1], (long long)size);
1.13 millert 2026: code = size;
1.1 deraadt 2027: }
2028:
2029: /*
1.23 millert 2030: * Get last modification time of file on remote machine
1.1 deraadt 2031: */
2032: void
1.47 deraadt 2033: modtime(int argc, char *argv[])
1.1 deraadt 2034: {
1.13 millert 2035: time_t mtime;
1.1 deraadt 2036:
1.13 millert 2037: if ((argc < 2 && !another(&argc, &argv, "filename")) || argc > 2) {
1.20 deraadt 2038: fprintf(ttyout, "usage: %s filename\n", argv[0]);
1.1 deraadt 2039: code = -1;
2040: return;
2041: }
1.13 millert 2042: mtime = remotemodtime(argv[1], 1);
2043: if (mtime != -1)
1.20 deraadt 2044: fprintf(ttyout, "%s\t%s", argv[1], asctime(localtime(&mtime)));
1.13 millert 2045: code = mtime;
1.1 deraadt 2046: }
2047:
2048: /*
1.23 millert 2049: * Show status on remote machine
1.1 deraadt 2050: */
2051: void
1.47 deraadt 2052: rmtstatus(int argc, char *argv[])
1.1 deraadt 2053: {
2054:
1.14 millert 2055: (void)command(argc > 1 ? "STAT %s" : "STAT" , argv[1]);
1.1 deraadt 2056: }
2057:
2058: /*
1.23 millert 2059: * Get file if modtime is more recent than current file
1.1 deraadt 2060: */
2061: void
1.47 deraadt 2062: newer(int argc, char *argv[])
1.1 deraadt 2063: {
2064:
2065: if (getit(argc, argv, -1, "w"))
1.20 deraadt 2066: fprintf(ttyout, "Local file \"%s\" is newer than remote file \"%s\".\n",
1.1 deraadt 2067: argv[2], argv[1]);
1.16 millert 2068: }
2069:
2070: /*
2071: * Display one file through $PAGER (defaults to "more").
2072: */
2073: void
1.47 deraadt 2074: page(int argc, char *argv[])
1.16 millert 2075: {
2076: int orestart_point, ohash, overbose;
1.23 millert 2077: char *p, *pager, *oldargv1;
1.16 millert 2078:
2079: if ((argc < 2 && !another(&argc, &argv, "filename")) || argc > 2) {
1.20 deraadt 2080: fprintf(ttyout, "usage: %s filename\n", argv[0]);
1.16 millert 2081: code = -1;
2082: return;
2083: }
1.23 millert 2084: oldargv1 = argv[1];
1.16 millert 2085: if (!globulize(&argv[1])) {
2086: code = -1;
2087: return;
2088: }
2089: p = getenv("PAGER");
1.30 pjanzen 2090: if (p == NULL || (*p == '\0'))
1.16 millert 2091: p = PAGER;
1.44 deraadt 2092: if (asprintf(&pager, "|%s", p) == -1)
1.16 millert 2093: errx(1, "Can't allocate memory for $PAGER");
2094:
2095: orestart_point = restart_point;
2096: ohash = hash;
2097: overbose = verbose;
2098: restart_point = hash = verbose = 0;
1.23 millert 2099: recvrequest("RETR", pager, argv[1], "r+w", 1, 0);
1.16 millert 2100: (void)free(pager);
2101: restart_point = orestart_point;
2102: hash = ohash;
2103: verbose = overbose;
1.23 millert 2104: if (oldargv1 != argv[1]) /* free up after globulize() */
2105: free(argv[1]);
1.1 deraadt 2106: }