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