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