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