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