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