ftp.c revision 1.10 1 /*
2 * Copyright (c) 1985, 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 /*static char sccsid[] = "from: @(#)ftp.c 8.4 (Berkeley) 4/6/94";*/
36 static char *rcsid = "$Id: ftp.c,v 1.10 1995/03/21 14:16:23 mycroft Exp $";
37 #endif /* not lint */
38
39 #include <sys/param.h>
40 #include <sys/stat.h>
41 #include <sys/ioctl.h>
42 #include <sys/socket.h>
43 #include <sys/time.h>
44 #include <sys/file.h>
45
46 #include <netinet/in.h>
47 #include <netinet/in_systm.h>
48 #include <netinet/ip.h>
49 #include <arpa/inet.h>
50 #include <arpa/ftp.h>
51 #include <arpa/telnet.h>
52
53 #include <ctype.h>
54 #include <err.h>
55 #include <errno.h>
56 #include <fcntl.h>
57 #include <netdb.h>
58 #include <pwd.h>
59 #include <signal.h>
60 #include <stdio.h>
61 #include <stdlib.h>
62 #include <string.h>
63 #include <unistd.h>
64 #include <varargs.h>
65
66 #include "ftp_var.h"
67
68 extern int h_errno;
69
70 struct sockaddr_in hisctladdr;
71 struct sockaddr_in data_addr;
72 int data = -1;
73 int abrtflag = 0;
74 jmp_buf ptabort;
75 int ptabflg;
76 int ptflag = 0;
77 struct sockaddr_in myctladdr;
78 off_t restart_point = 0;
79
80
81 FILE *cin, *cout;
82
83 char *
84 hookup(host, port)
85 char *host;
86 int port;
87 {
88 struct hostent *hp = 0;
89 int s, len, tos;
90 static char hostnamebuf[80];
91
92 memset((char *)&hisctladdr, 0, sizeof (hisctladdr));
93 hisctladdr.sin_addr.s_addr = inet_addr(host);
94 if (hisctladdr.sin_addr.s_addr != -1) {
95 hisctladdr.sin_family = AF_INET;
96 (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
97 } else {
98 hp = gethostbyname(host);
99 if (hp == NULL) {
100 warnx("%s: %s", host, hstrerror(h_errno));
101 code = -1;
102 return ((char *) 0);
103 }
104 hisctladdr.sin_family = hp->h_addrtype;
105 memmove((caddr_t)&hisctladdr.sin_addr,
106 hp->h_addr_list[0], hp->h_length);
107 (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
108 }
109 hostname = hostnamebuf;
110 s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
111 if (s < 0) {
112 warn("socket");
113 code = -1;
114 return (0);
115 }
116 hisctladdr.sin_port = port;
117 while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
118 if (hp && hp->h_addr_list[1]) {
119 int oerrno = errno;
120 char *ia;
121
122 ia = inet_ntoa(hisctladdr.sin_addr);
123 errno = oerrno;
124 warn("connect to address %s", ia);
125 hp->h_addr_list++;
126 memmove((caddr_t)&hisctladdr.sin_addr,
127 hp->h_addr_list[0], hp->h_length);
128 fprintf(stdout, "Trying %s...\n",
129 inet_ntoa(hisctladdr.sin_addr));
130 (void) close(s);
131 s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
132 if (s < 0) {
133 warn("socket");
134 code = -1;
135 return (0);
136 }
137 continue;
138 }
139 warn("connect");
140 code = -1;
141 goto bad;
142 }
143 len = sizeof (myctladdr);
144 if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
145 warn("getsockname");
146 code = -1;
147 goto bad;
148 }
149 #ifdef IP_TOS
150 tos = IPTOS_LOWDELAY;
151 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
152 warn("setsockopt TOS (ignored)");
153 #endif
154 cin = fdopen(s, "r");
155 cout = fdopen(s, "w");
156 if (cin == NULL || cout == NULL) {
157 warnx("fdopen failed.");
158 if (cin)
159 (void) fclose(cin);
160 if (cout)
161 (void) fclose(cout);
162 code = -1;
163 goto bad;
164 }
165 if (verbose)
166 printf("Connected to %s.\n", hostname);
167 if (getreply(0) > 2) { /* read startup message from server */
168 if (cin)
169 (void) fclose(cin);
170 if (cout)
171 (void) fclose(cout);
172 code = -1;
173 goto bad;
174 }
175 #ifdef SO_OOBINLINE
176 {
177 int on = 1;
178
179 if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
180 < 0 && debug) {
181 warn("setsockopt");
182 }
183 }
184 #endif /* SO_OOBINLINE */
185
186 return (hostname);
187 bad:
188 (void) close(s);
189 return ((char *)0);
190 }
191
192 int
193 login(host)
194 char *host;
195 {
196 char tmp[80];
197 char *user, *pass, *acct;
198 int n, aflag = 0;
199
200 user = pass = acct = 0;
201 if (ruserpass(host, &user, &pass, &acct) < 0) {
202 code = -1;
203 return (0);
204 }
205 while (user == NULL) {
206 char *myname = getlogin();
207
208 if (myname == NULL) {
209 struct passwd *pp = getpwuid(getuid());
210
211 if (pp != NULL)
212 myname = pp->pw_name;
213 }
214 if (myname)
215 printf("Name (%s:%s): ", host, myname);
216 else
217 printf("Name (%s): ", host);
218 (void) fgets(tmp, sizeof(tmp) - 1, stdin);
219 tmp[strlen(tmp) - 1] = '\0';
220 if (*tmp == '\0')
221 user = myname;
222 else
223 user = tmp;
224 }
225 n = command("USER %s", user);
226 if (n == CONTINUE) {
227 if (pass == NULL)
228 pass = getpass("Password:");
229 n = command("PASS %s", pass);
230 }
231 if (n == CONTINUE) {
232 aflag++;
233 acct = getpass("Account:");
234 n = command("ACCT %s", acct);
235 }
236 if (n != COMPLETE) {
237 warnx("Login failed.");
238 return (0);
239 }
240 if (!aflag && acct != NULL)
241 (void) command("ACCT %s", acct);
242 if (proxy)
243 return (1);
244 for (n = 0; n < macnum; ++n) {
245 if (!strcmp("init", macros[n].mac_name)) {
246 (void) strcpy(line, "$init");
247 makeargv();
248 domacro(margc, margv);
249 break;
250 }
251 }
252 return (1);
253 }
254
255 void
256 cmdabort()
257 {
258
259 printf("\n");
260 (void) fflush(stdout);
261 abrtflag++;
262 if (ptflag)
263 longjmp(ptabort,1);
264 }
265
266 /*VARARGS*/
267 int
268 command(va_alist)
269 va_dcl
270 {
271 va_list ap;
272 char *fmt;
273 int r;
274 sig_t oldintr;
275
276 abrtflag = 0;
277 if (debug) {
278 printf("---> ");
279 va_start(ap);
280 fmt = va_arg(ap, char *);
281 if (strncmp("PASS ", fmt, 5) == 0)
282 printf("PASS XXXX");
283 else
284 vfprintf(stdout, fmt, ap);
285 va_end(ap);
286 printf("\n");
287 (void) fflush(stdout);
288 }
289 if (cout == NULL) {
290 warn("No control connection for command");
291 code = -1;
292 return (0);
293 }
294 oldintr = signal(SIGINT, cmdabort);
295 va_start(ap);
296 fmt = va_arg(ap, char *);
297 vfprintf(cout, fmt, ap);
298 va_end(ap);
299 fprintf(cout, "\r\n");
300 (void) fflush(cout);
301 cpend = 1;
302 r = getreply(!strcmp(fmt, "QUIT"));
303 if (abrtflag && oldintr != SIG_IGN)
304 (*oldintr)(SIGINT);
305 (void) signal(SIGINT, oldintr);
306 return (r);
307 }
308
309 char reply_string[BUFSIZ]; /* last line of previous reply */
310
311 int
312 getreply(expecteof)
313 int expecteof;
314 {
315 int c, n;
316 int dig;
317 int originalcode = 0, continuation = 0;
318 sig_t oldintr;
319 int pflag = 0;
320 char *cp, *pt = pasv;
321
322 oldintr = signal(SIGINT, cmdabort);
323 for (;;) {
324 dig = n = code = 0;
325 cp = reply_string;
326 while ((c = getc(cin)) != '\n') {
327 if (c == IAC) { /* handle telnet commands */
328 switch (c = getc(cin)) {
329 case WILL:
330 case WONT:
331 c = getc(cin);
332 fprintf(cout, "%c%c%c", IAC, DONT, c);
333 (void) fflush(cout);
334 break;
335 case DO:
336 case DONT:
337 c = getc(cin);
338 fprintf(cout, "%c%c%c", IAC, WONT, c);
339 (void) fflush(cout);
340 break;
341 default:
342 break;
343 }
344 continue;
345 }
346 dig++;
347 if (c == EOF) {
348 if (expecteof) {
349 (void) signal(SIGINT,oldintr);
350 code = 221;
351 return (0);
352 }
353 lostpeer();
354 if (verbose) {
355 printf("421 Service not available, remote server has closed connection\n");
356 (void) fflush(stdout);
357 }
358 code = 421;
359 return (4);
360 }
361 if (c != '\r' && (verbose > 0 ||
362 (verbose > -1 && n == '5' && dig > 4))) {
363 if (proxflag &&
364 (dig == 1 || dig == 5 && verbose == 0))
365 printf("%s:",hostname);
366 (void) putchar(c);
367 }
368 if (dig < 4 && isdigit(c))
369 code = code * 10 + (c - '0');
370 if (!pflag && code == 227)
371 pflag = 1;
372 if (dig > 4 && pflag == 1 && isdigit(c))
373 pflag = 2;
374 if (pflag == 2) {
375 if (c != '\r' && c != ')')
376 *pt++ = c;
377 else {
378 *pt = '\0';
379 pflag = 3;
380 }
381 }
382 if (dig == 4 && c == '-') {
383 if (continuation)
384 code = 0;
385 continuation++;
386 }
387 if (n == 0)
388 n = c;
389 if (cp < &reply_string[sizeof(reply_string) - 1])
390 *cp++ = c;
391 }
392 if (verbose > 0 || verbose > -1 && n == '5') {
393 (void) putchar(c);
394 (void) fflush (stdout);
395 }
396 if (continuation && code != originalcode) {
397 if (originalcode == 0)
398 originalcode = code;
399 continue;
400 }
401 *cp = '\0';
402 if (n != '1')
403 cpend = 0;
404 (void) signal(SIGINT,oldintr);
405 if (code == 421 || originalcode == 421)
406 lostpeer();
407 if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
408 (*oldintr)(SIGINT);
409 return (n - '0');
410 }
411 }
412
413 int
414 empty(mask, sec)
415 struct fd_set *mask;
416 int sec;
417 {
418 struct timeval t;
419
420 t.tv_sec = (long) sec;
421 t.tv_usec = 0;
422 return (select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
423 }
424
425 jmp_buf sendabort;
426
427 void
428 abortsend()
429 {
430
431 mflag = 0;
432 abrtflag = 0;
433 printf("\nsend aborted\nwaiting for remote to finish abort\n");
434 (void) fflush(stdout);
435 longjmp(sendabort, 1);
436 }
437
438 #define HASHBYTES 1024
439
440 void
441 sendrequest(cmd, local, remote, printnames)
442 char *cmd, *local, *remote;
443 int printnames;
444 {
445 struct stat st;
446 struct timeval start, stop;
447 int c, d;
448 FILE *fin, *dout = 0, *popen();
449 int (*closefunc) __P((FILE *));
450 sig_t oldintr, oldintp;
451 long bytes = 0, hashbytes = HASHBYTES;
452 char *lmode, buf[BUFSIZ], *bufp;
453
454 if (verbose && printnames) {
455 if (local && *local != '-')
456 printf("local: %s ", local);
457 if (remote)
458 printf("remote: %s\n", remote);
459 }
460 if (proxy) {
461 proxtrans(cmd, local, remote);
462 return;
463 }
464 if (curtype != type)
465 changetype(type, 0);
466 closefunc = NULL;
467 oldintr = NULL;
468 oldintp = NULL;
469 lmode = "w";
470 if (setjmp(sendabort)) {
471 while (cpend) {
472 (void) getreply(0);
473 }
474 if (data >= 0) {
475 (void) close(data);
476 data = -1;
477 }
478 if (oldintr)
479 (void) signal(SIGINT,oldintr);
480 if (oldintp)
481 (void) signal(SIGPIPE,oldintp);
482 code = -1;
483 return;
484 }
485 oldintr = signal(SIGINT, abortsend);
486 if (strcmp(local, "-") == 0)
487 fin = stdin;
488 else if (*local == '|') {
489 oldintp = signal(SIGPIPE,SIG_IGN);
490 fin = popen(local + 1, "r");
491 if (fin == NULL) {
492 warn("%s", local + 1);
493 (void) signal(SIGINT, oldintr);
494 (void) signal(SIGPIPE, oldintp);
495 code = -1;
496 return;
497 }
498 closefunc = pclose;
499 } else {
500 fin = fopen(local, "r");
501 if (fin == NULL) {
502 warn("local: %s", local);
503 (void) signal(SIGINT, oldintr);
504 code = -1;
505 return;
506 }
507 closefunc = fclose;
508 if (fstat(fileno(fin), &st) < 0 ||
509 (st.st_mode&S_IFMT) != S_IFREG) {
510 fprintf(stdout, "%s: not a plain file.\n", local);
511 (void) signal(SIGINT, oldintr);
512 fclose(fin);
513 code = -1;
514 return;
515 }
516 }
517 if (initconn()) {
518 (void) signal(SIGINT, oldintr);
519 if (oldintp)
520 (void) signal(SIGPIPE, oldintp);
521 code = -1;
522 if (closefunc != NULL)
523 (*closefunc)(fin);
524 return;
525 }
526 if (setjmp(sendabort))
527 goto abort;
528
529 if (restart_point &&
530 (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
531 int rc;
532
533 switch (curtype) {
534 case TYPE_A:
535 rc = fseek(fin, (long) restart_point, SEEK_SET);
536 break;
537 case TYPE_I:
538 case TYPE_L:
539 rc = lseek(fileno(fin), restart_point, SEEK_SET);
540 break;
541 }
542 if (rc < 0) {
543 warn("local: %s", local);
544 restart_point = 0;
545 if (closefunc != NULL)
546 (*closefunc)(fin);
547 return;
548 }
549 if (command("REST %ld", (long) restart_point)
550 != CONTINUE) {
551 restart_point = 0;
552 if (closefunc != NULL)
553 (*closefunc)(fin);
554 return;
555 }
556 restart_point = 0;
557 lmode = "r+w";
558 }
559 if (remote) {
560 if (command("%s %s", cmd, remote) != PRELIM) {
561 (void) signal(SIGINT, oldintr);
562 if (oldintp)
563 (void) signal(SIGPIPE, oldintp);
564 if (closefunc != NULL)
565 (*closefunc)(fin);
566 return;
567 }
568 } else
569 if (command("%s", cmd) != PRELIM) {
570 (void) signal(SIGINT, oldintr);
571 if (oldintp)
572 (void) signal(SIGPIPE, oldintp);
573 if (closefunc != NULL)
574 (*closefunc)(fin);
575 return;
576 }
577 dout = dataconn(lmode);
578 if (dout == NULL)
579 goto abort;
580 (void) gettimeofday(&start, (struct timezone *)0);
581 oldintp = signal(SIGPIPE, SIG_IGN);
582 switch (curtype) {
583
584 case TYPE_I:
585 case TYPE_L:
586 errno = d = 0;
587 while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
588 bytes += c;
589 for (bufp = buf; c > 0; c -= d, bufp += d)
590 if ((d = write(fileno(dout), bufp, c)) <= 0)
591 break;
592 if (hash) {
593 while (bytes >= hashbytes) {
594 (void) putchar('#');
595 hashbytes += HASHBYTES;
596 }
597 (void) fflush(stdout);
598 }
599 }
600 if (hash && bytes > 0) {
601 if (bytes < HASHBYTES)
602 (void) putchar('#');
603 (void) putchar('\n');
604 (void) fflush(stdout);
605 }
606 if (c < 0)
607 warn("local: %s", local);
608 if (d < 0) {
609 if (errno != EPIPE)
610 warn("netout");
611 bytes = -1;
612 }
613 break;
614
615 case TYPE_A:
616 while ((c = getc(fin)) != EOF) {
617 if (c == '\n') {
618 while (hash && (bytes >= hashbytes)) {
619 (void) putchar('#');
620 (void) fflush(stdout);
621 hashbytes += HASHBYTES;
622 }
623 if (ferror(dout))
624 break;
625 (void) putc('\r', dout);
626 bytes++;
627 }
628 (void) putc(c, dout);
629 bytes++;
630 /* if (c == '\r') { */
631 /* (void) putc('\0', dout); // this violates rfc */
632 /* bytes++; */
633 /* } */
634 }
635 if (hash) {
636 if (bytes < hashbytes)
637 (void) putchar('#');
638 (void) putchar('\n');
639 (void) fflush(stdout);
640 }
641 if (ferror(fin))
642 warn("local: %s", local);
643 if (ferror(dout)) {
644 if (errno != EPIPE)
645 warn("netout");
646 bytes = -1;
647 }
648 break;
649 }
650 (void) gettimeofday(&stop, (struct timezone *)0);
651 if (closefunc != NULL)
652 (*closefunc)(fin);
653 (void) fclose(dout);
654 (void) getreply(0);
655 (void) signal(SIGINT, oldintr);
656 if (oldintp)
657 (void) signal(SIGPIPE, oldintp);
658 if (bytes > 0)
659 ptransfer("sent", bytes, &start, &stop);
660 return;
661 abort:
662 (void) gettimeofday(&stop, (struct timezone *)0);
663 (void) signal(SIGINT, oldintr);
664 if (oldintp)
665 (void) signal(SIGPIPE, oldintp);
666 if (!cpend) {
667 code = -1;
668 return;
669 }
670 if (data >= 0) {
671 (void) close(data);
672 data = -1;
673 }
674 if (dout)
675 (void) fclose(dout);
676 (void) getreply(0);
677 code = -1;
678 if (closefunc != NULL && fin != NULL)
679 (*closefunc)(fin);
680 if (bytes > 0)
681 ptransfer("sent", bytes, &start, &stop);
682 }
683
684 jmp_buf recvabort;
685
686 void
687 abortrecv()
688 {
689
690 mflag = 0;
691 abrtflag = 0;
692 printf("\nreceive aborted\nwaiting for remote to finish abort\n");
693 (void) fflush(stdout);
694 longjmp(recvabort, 1);
695 }
696
697 void
698 recvrequest(cmd, local, remote, lmode, printnames)
699 char *cmd, *local, *remote, *lmode;
700 int printnames;
701 {
702 FILE *fout, *din = 0;
703 int (*closefunc) __P((FILE *));
704 sig_t oldintr, oldintp;
705 int c, d, is_retr, tcrflag, bare_lfs = 0;
706 static int bufsize;
707 static char *buf;
708 long bytes = 0, hashbytes = HASHBYTES;
709 struct timeval start, stop;
710 struct stat st;
711
712 is_retr = strcmp(cmd, "RETR") == 0;
713 if (is_retr && verbose && printnames) {
714 if (local && *local != '-')
715 printf("local: %s ", local);
716 if (remote)
717 printf("remote: %s\n", remote);
718 }
719 if (proxy && is_retr) {
720 proxtrans(cmd, local, remote);
721 return;
722 }
723 closefunc = NULL;
724 oldintr = NULL;
725 oldintp = NULL;
726 tcrflag = !crflag && is_retr;
727 if (setjmp(recvabort)) {
728 while (cpend) {
729 (void) getreply(0);
730 }
731 if (data >= 0) {
732 (void) close(data);
733 data = -1;
734 }
735 if (oldintr)
736 (void) signal(SIGINT, oldintr);
737 code = -1;
738 return;
739 }
740 oldintr = signal(SIGINT, abortrecv);
741 if (strcmp(local, "-") && *local != '|') {
742 if (access(local, 2) < 0) {
743 char *dir = strrchr(local, '/');
744
745 if (errno != ENOENT && errno != EACCES) {
746 warn("local: %s", local);
747 (void) signal(SIGINT, oldintr);
748 code = -1;
749 return;
750 }
751 if (dir != NULL)
752 *dir = 0;
753 d = access(dir ? local : ".", 2);
754 if (dir != NULL)
755 *dir = '/';
756 if (d < 0) {
757 warn("local: %s", local);
758 (void) signal(SIGINT, oldintr);
759 code = -1;
760 return;
761 }
762 if (!runique && errno == EACCES &&
763 chmod(local, 0600) < 0) {
764 warn("local: %s", local);
765 (void) signal(SIGINT, oldintr);
766 (void) signal(SIGINT, oldintr);
767 code = -1;
768 return;
769 }
770 if (runique && errno == EACCES &&
771 (local = gunique(local)) == NULL) {
772 (void) signal(SIGINT, oldintr);
773 code = -1;
774 return;
775 }
776 }
777 else if (runique && (local = gunique(local)) == NULL) {
778 (void) signal(SIGINT, oldintr);
779 code = -1;
780 return;
781 }
782 }
783 if (!is_retr) {
784 if (curtype != TYPE_A)
785 changetype(TYPE_A, 0);
786 } else if (curtype != type)
787 changetype(type, 0);
788 if (initconn()) {
789 (void) signal(SIGINT, oldintr);
790 code = -1;
791 return;
792 }
793 if (setjmp(recvabort))
794 goto abort;
795 if (is_retr && restart_point &&
796 command("REST %ld", (long) restart_point) != CONTINUE)
797 return;
798 if (remote) {
799 if (command("%s %s", cmd, remote) != PRELIM) {
800 (void) signal(SIGINT, oldintr);
801 return;
802 }
803 } else {
804 if (command("%s", cmd) != PRELIM) {
805 (void) signal(SIGINT, oldintr);
806 return;
807 }
808 }
809 din = dataconn("r");
810 if (din == NULL)
811 goto abort;
812 if (strcmp(local, "-") == 0)
813 fout = stdout;
814 else if (*local == '|') {
815 oldintp = signal(SIGPIPE, SIG_IGN);
816 fout = popen(local + 1, "w");
817 if (fout == NULL) {
818 warn("%s", local+1);
819 goto abort;
820 }
821 closefunc = pclose;
822 } else {
823 fout = fopen(local, lmode);
824 if (fout == NULL) {
825 warn("local: %s", local);
826 goto abort;
827 }
828 closefunc = fclose;
829 }
830 if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
831 st.st_blksize = BUFSIZ;
832 if (st.st_blksize > bufsize) {
833 if (buf)
834 (void) free(buf);
835 buf = malloc((unsigned)st.st_blksize);
836 if (buf == NULL) {
837 warn("malloc");
838 bufsize = 0;
839 goto abort;
840 }
841 bufsize = st.st_blksize;
842 }
843 (void) gettimeofday(&start, (struct timezone *)0);
844 switch (curtype) {
845
846 case TYPE_I:
847 case TYPE_L:
848 if (restart_point &&
849 lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
850 warn("local: %s", local);
851 if (closefunc != NULL)
852 (*closefunc)(fout);
853 return;
854 }
855 errno = d = 0;
856 while ((c = read(fileno(din), buf, bufsize)) > 0) {
857 if ((d = write(fileno(fout), buf, c)) != c)
858 break;
859 bytes += c;
860 if (hash) {
861 while (bytes >= hashbytes) {
862 (void) putchar('#');
863 hashbytes += HASHBYTES;
864 }
865 (void) fflush(stdout);
866 }
867 }
868 if (hash && bytes > 0) {
869 if (bytes < HASHBYTES)
870 (void) putchar('#');
871 (void) putchar('\n');
872 (void) fflush(stdout);
873 }
874 if (c < 0) {
875 if (errno != EPIPE)
876 warn("netin");
877 bytes = -1;
878 }
879 if (d < c) {
880 if (d < 0)
881 warn("local: %s", local);
882 else
883 warnx("%s: short write", local);
884 }
885 break;
886
887 case TYPE_A:
888 if (restart_point) {
889 int i, n, ch;
890
891 if (fseek(fout, 0L, SEEK_SET) < 0)
892 goto done;
893 n = restart_point;
894 for (i = 0; i++ < n;) {
895 if ((ch = getc(fout)) == EOF)
896 goto done;
897 if (ch == '\n')
898 i++;
899 }
900 if (fseek(fout, 0L, SEEK_CUR) < 0) {
901 done:
902 warn("local: %s", local);
903 if (closefunc != NULL)
904 (*closefunc)(fout);
905 return;
906 }
907 }
908 while ((c = getc(din)) != EOF) {
909 if (c == '\n')
910 bare_lfs++;
911 while (c == '\r') {
912 while (hash && (bytes >= hashbytes)) {
913 (void) putchar('#');
914 (void) fflush(stdout);
915 hashbytes += HASHBYTES;
916 }
917 bytes++;
918 if ((c = getc(din)) != '\n' || tcrflag) {
919 if (ferror(fout))
920 goto break2;
921 (void) putc('\r', fout);
922 if (c == '\0') {
923 bytes++;
924 goto contin2;
925 }
926 if (c == EOF)
927 goto contin2;
928 }
929 }
930 (void) putc(c, fout);
931 bytes++;
932 contin2: ;
933 }
934 break2:
935 if (bare_lfs) {
936 printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
937 printf("File may not have transferred correctly.\n");
938 }
939 if (hash) {
940 if (bytes < hashbytes)
941 (void) putchar('#');
942 (void) putchar('\n');
943 (void) fflush(stdout);
944 }
945 if (ferror(din)) {
946 if (errno != EPIPE)
947 warn("netin");
948 bytes = -1;
949 }
950 if (ferror(fout))
951 warn("local: %s", local);
952 break;
953 }
954 if (closefunc != NULL)
955 (*closefunc)(fout);
956 (void) signal(SIGINT, oldintr);
957 if (oldintp)
958 (void) signal(SIGPIPE, oldintp);
959 (void) gettimeofday(&stop, (struct timezone *)0);
960 (void) fclose(din);
961 (void) getreply(0);
962 if (bytes > 0 && is_retr)
963 ptransfer("received", bytes, &start, &stop);
964 return;
965 abort:
966
967 /* abort using RFC959 recommended IP,SYNC sequence */
968
969 (void) gettimeofday(&stop, (struct timezone *)0);
970 if (oldintp)
971 (void) signal(SIGPIPE, oldintr);
972 (void) signal(SIGINT, SIG_IGN);
973 if (!cpend) {
974 code = -1;
975 (void) signal(SIGINT, oldintr);
976 return;
977 }
978
979 abort_remote(din);
980 code = -1;
981 if (data >= 0) {
982 (void) close(data);
983 data = -1;
984 }
985 if (closefunc != NULL && fout != NULL)
986 (*closefunc)(fout);
987 if (din)
988 (void) fclose(din);
989 if (bytes > 0)
990 ptransfer("received", bytes, &start, &stop);
991 (void) signal(SIGINT, oldintr);
992 }
993
994 /*
995 * Need to start a listen on the data channel before we send the command,
996 * otherwise the server's connect may fail.
997 */
998 int
999 initconn()
1000 {
1001 char *p, *a;
1002 int result, len, tmpno = 0;
1003 int on = 1;
1004 int a0, a1, a2, a3, p0, p1;
1005
1006 if (passivemode) {
1007 data = socket(AF_INET, SOCK_STREAM, 0);
1008 if (data < 0) {
1009 perror("ftp: socket");
1010 return(1);
1011 }
1012 if ((options & SO_DEBUG) &&
1013 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
1014 sizeof (on)) < 0)
1015 perror("ftp: setsockopt (ignored)");
1016 if (command("PASV") != COMPLETE) {
1017 printf("Passive mode refused.\n");
1018 goto bad;
1019 }
1020
1021 /*
1022 * What we've got at this point is a string of comma
1023 * separated one-byte unsigned integer values, separated
1024 * by commas. The first four are the an IP address. The
1025 * fifth is the MSB of the port number, the sixth is the
1026 * LSB. From that we'll prepare a sockaddr_in.
1027 */
1028
1029 if (sscanf(pasv,"%d,%d,%d,%d,%d,%d",
1030 &a0, &a1, &a2, &a3, &p0, &p1) != 6) {
1031 printf("Passive mode address scan failure. "
1032 "Shouldn't happen!\n");
1033 goto bad;
1034 }
1035
1036 bzero(&data_addr, sizeof(data_addr));
1037 data_addr.sin_family = AF_INET;
1038 a = (char *)&data_addr.sin_addr.s_addr;
1039 a[0] = a0 & 0xff;
1040 a[1] = a1 & 0xff;
1041 a[2] = a2 & 0xff;
1042 a[3] = a3 & 0xff;
1043 p = (char *)&data_addr.sin_port;
1044 p[0] = p0 & 0xff;
1045 p[1] = p1 & 0xff;
1046
1047 if (connect(data, (struct sockaddr *)&data_addr,
1048 sizeof(data_addr)) < 0) {
1049 perror("ftp: connect");
1050 goto bad;
1051 }
1052 #ifdef IP_TOS
1053 on = IPTOS_THROUGHPUT;
1054 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
1055 sizeof(int)) < 0)
1056 perror("ftp: setsockopt TOS (ignored)");
1057 #endif
1058 return(0);
1059 }
1060
1061 noport:
1062 data_addr = myctladdr;
1063 if (sendport)
1064 data_addr.sin_port = 0; /* let system pick one */
1065 if (data != -1)
1066 (void) close(data);
1067 data = socket(AF_INET, SOCK_STREAM, 0);
1068 if (data < 0) {
1069 warn("socket");
1070 if (tmpno)
1071 sendport = 1;
1072 return (1);
1073 }
1074 if (!sendport)
1075 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
1076 warn("setsockopt (reuse address)");
1077 goto bad;
1078 }
1079 if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
1080 warn("bind");
1081 goto bad;
1082 }
1083 if (options & SO_DEBUG &&
1084 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
1085 warn("setsockopt (ignored)");
1086 len = sizeof (data_addr);
1087 if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
1088 warn("getsockname");
1089 goto bad;
1090 }
1091 if (listen(data, 1) < 0)
1092 warn("listen");
1093 if (sendport) {
1094 a = (char *)&data_addr.sin_addr;
1095 p = (char *)&data_addr.sin_port;
1096 #define UC(b) (((int)b)&0xff)
1097 result =
1098 command("PORT %d,%d,%d,%d,%d,%d",
1099 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1100 UC(p[0]), UC(p[1]));
1101 if (result == ERROR && sendport == -1) {
1102 sendport = 0;
1103 tmpno = 1;
1104 goto noport;
1105 }
1106 return (result != COMPLETE);
1107 }
1108 if (tmpno)
1109 sendport = 1;
1110 #ifdef IP_TOS
1111 on = IPTOS_THROUGHPUT;
1112 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
1113 warn("setsockopt TOS (ignored)");
1114 #endif
1115 return (0);
1116 bad:
1117 (void) close(data), data = -1;
1118 if (tmpno)
1119 sendport = 1;
1120 return (1);
1121 }
1122
1123 FILE *
1124 dataconn(lmode)
1125 char *lmode;
1126 {
1127 struct sockaddr_in from;
1128 int s, fromlen = sizeof (from), tos;
1129
1130 if (passivemode)
1131 return (fdopen(data, lmode));
1132
1133 s = accept(data, (struct sockaddr *) &from, &fromlen);
1134 if (s < 0) {
1135 warn("accept");
1136 (void) close(data), data = -1;
1137 return (NULL);
1138 }
1139 (void) close(data);
1140 data = s;
1141 #ifdef IP_TOS
1142 tos = IPTOS_THROUGHPUT;
1143 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
1144 warn("setsockopt TOS (ignored)");
1145 #endif
1146 return (fdopen(data, lmode));
1147 }
1148
1149 void
1150 ptransfer(direction, bytes, t0, t1)
1151 char *direction;
1152 long bytes;
1153 struct timeval *t0, *t1;
1154 {
1155 struct timeval td;
1156 float s;
1157 long bs;
1158
1159 if (verbose) {
1160 timersub(t1, t0, &td);
1161 s = td.tv_sec + (td.tv_usec / 1000000.);
1162 #define nz(x) ((x) == 0 ? 1 : (x))
1163 bs = bytes / nz(s);
1164 printf("%ld bytes %s in %.3g seconds (%ld bytes/s)\n",
1165 bytes, direction, s, bs);
1166 }
1167 }
1168
1169 void
1170 psabort()
1171 {
1172
1173 abrtflag++;
1174 }
1175
1176 void
1177 pswitch(flag)
1178 int flag;
1179 {
1180 sig_t oldintr;
1181 static struct comvars {
1182 int connect;
1183 char name[MAXHOSTNAMELEN];
1184 struct sockaddr_in mctl;
1185 struct sockaddr_in hctl;
1186 FILE *in;
1187 FILE *out;
1188 int tpe;
1189 int curtpe;
1190 int cpnd;
1191 int sunqe;
1192 int runqe;
1193 int mcse;
1194 int ntflg;
1195 char nti[17];
1196 char nto[17];
1197 int mapflg;
1198 char mi[MAXPATHLEN];
1199 char mo[MAXPATHLEN];
1200 } proxstruct, tmpstruct;
1201 struct comvars *ip, *op;
1202
1203 abrtflag = 0;
1204 oldintr = signal(SIGINT, psabort);
1205 if (flag) {
1206 if (proxy)
1207 return;
1208 ip = &tmpstruct;
1209 op = &proxstruct;
1210 proxy++;
1211 } else {
1212 if (!proxy)
1213 return;
1214 ip = &proxstruct;
1215 op = &tmpstruct;
1216 proxy = 0;
1217 }
1218 ip->connect = connected;
1219 connected = op->connect;
1220 if (hostname) {
1221 (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
1222 ip->name[strlen(ip->name)] = '\0';
1223 } else
1224 ip->name[0] = 0;
1225 hostname = op->name;
1226 ip->hctl = hisctladdr;
1227 hisctladdr = op->hctl;
1228 ip->mctl = myctladdr;
1229 myctladdr = op->mctl;
1230 ip->in = cin;
1231 cin = op->in;
1232 ip->out = cout;
1233 cout = op->out;
1234 ip->tpe = type;
1235 type = op->tpe;
1236 ip->curtpe = curtype;
1237 curtype = op->curtpe;
1238 ip->cpnd = cpend;
1239 cpend = op->cpnd;
1240 ip->sunqe = sunique;
1241 sunique = op->sunqe;
1242 ip->runqe = runique;
1243 runique = op->runqe;
1244 ip->mcse = mcase;
1245 mcase = op->mcse;
1246 ip->ntflg = ntflag;
1247 ntflag = op->ntflg;
1248 (void) strncpy(ip->nti, ntin, 16);
1249 (ip->nti)[strlen(ip->nti)] = '\0';
1250 (void) strcpy(ntin, op->nti);
1251 (void) strncpy(ip->nto, ntout, 16);
1252 (ip->nto)[strlen(ip->nto)] = '\0';
1253 (void) strcpy(ntout, op->nto);
1254 ip->mapflg = mapflag;
1255 mapflag = op->mapflg;
1256 (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
1257 (ip->mi)[strlen(ip->mi)] = '\0';
1258 (void) strcpy(mapin, op->mi);
1259 (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
1260 (ip->mo)[strlen(ip->mo)] = '\0';
1261 (void) strcpy(mapout, op->mo);
1262 (void) signal(SIGINT, oldintr);
1263 if (abrtflag) {
1264 abrtflag = 0;
1265 (*oldintr)(SIGINT);
1266 }
1267 }
1268
1269 void
1270 abortpt()
1271 {
1272
1273 printf("\n");
1274 (void) fflush(stdout);
1275 ptabflg++;
1276 mflag = 0;
1277 abrtflag = 0;
1278 longjmp(ptabort, 1);
1279 }
1280
1281 void
1282 proxtrans(cmd, local, remote)
1283 char *cmd, *local, *remote;
1284 {
1285 sig_t oldintr;
1286 int secndflag = 0, prox_type, nfnd;
1287 char *cmd2;
1288 struct fd_set mask;
1289
1290 if (strcmp(cmd, "RETR"))
1291 cmd2 = "RETR";
1292 else
1293 cmd2 = runique ? "STOU" : "STOR";
1294 if ((prox_type = type) == 0) {
1295 if (unix_server && unix_proxy)
1296 prox_type = TYPE_I;
1297 else
1298 prox_type = TYPE_A;
1299 }
1300 if (curtype != prox_type)
1301 changetype(prox_type, 1);
1302 if (command("PASV") != COMPLETE) {
1303 printf("proxy server does not support third party transfers.\n");
1304 return;
1305 }
1306 pswitch(0);
1307 if (!connected) {
1308 printf("No primary connection\n");
1309 pswitch(1);
1310 code = -1;
1311 return;
1312 }
1313 if (curtype != prox_type)
1314 changetype(prox_type, 1);
1315 if (command("PORT %s", pasv) != COMPLETE) {
1316 pswitch(1);
1317 return;
1318 }
1319 if (setjmp(ptabort))
1320 goto abort;
1321 oldintr = signal(SIGINT, abortpt);
1322 if (command("%s %s", cmd, remote) != PRELIM) {
1323 (void) signal(SIGINT, oldintr);
1324 pswitch(1);
1325 return;
1326 }
1327 sleep(2);
1328 pswitch(1);
1329 secndflag++;
1330 if (command("%s %s", cmd2, local) != PRELIM)
1331 goto abort;
1332 ptflag++;
1333 (void) getreply(0);
1334 pswitch(0);
1335 (void) getreply(0);
1336 (void) signal(SIGINT, oldintr);
1337 pswitch(1);
1338 ptflag = 0;
1339 printf("local: %s remote: %s\n", local, remote);
1340 return;
1341 abort:
1342 (void) signal(SIGINT, SIG_IGN);
1343 ptflag = 0;
1344 if (strcmp(cmd, "RETR") && !proxy)
1345 pswitch(1);
1346 else if (!strcmp(cmd, "RETR") && proxy)
1347 pswitch(0);
1348 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1349 if (command("%s %s", cmd2, local) != PRELIM) {
1350 pswitch(0);
1351 if (cpend)
1352 abort_remote((FILE *) NULL);
1353 }
1354 pswitch(1);
1355 if (ptabflg)
1356 code = -1;
1357 (void) signal(SIGINT, oldintr);
1358 return;
1359 }
1360 if (cpend)
1361 abort_remote((FILE *) NULL);
1362 pswitch(!proxy);
1363 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1364 if (command("%s %s", cmd2, local) != PRELIM) {
1365 pswitch(0);
1366 if (cpend)
1367 abort_remote((FILE *) NULL);
1368 pswitch(1);
1369 if (ptabflg)
1370 code = -1;
1371 (void) signal(SIGINT, oldintr);
1372 return;
1373 }
1374 }
1375 if (cpend)
1376 abort_remote((FILE *) NULL);
1377 pswitch(!proxy);
1378 if (cpend) {
1379 FD_ZERO(&mask);
1380 FD_SET(fileno(cin), &mask);
1381 if ((nfnd = empty(&mask, 10)) <= 0) {
1382 if (nfnd < 0) {
1383 warn("abort");
1384 }
1385 if (ptabflg)
1386 code = -1;
1387 lostpeer();
1388 }
1389 (void) getreply(0);
1390 (void) getreply(0);
1391 }
1392 if (proxy)
1393 pswitch(0);
1394 pswitch(1);
1395 if (ptabflg)
1396 code = -1;
1397 (void) signal(SIGINT, oldintr);
1398 }
1399
1400 void
1401 reset(argc, argv)
1402 int argc;
1403 char *argv[];
1404 {
1405 struct fd_set mask;
1406 int nfnd = 1;
1407
1408 FD_ZERO(&mask);
1409 while (nfnd > 0) {
1410 FD_SET(fileno(cin), &mask);
1411 if ((nfnd = empty(&mask,0)) < 0) {
1412 warn("reset");
1413 code = -1;
1414 lostpeer();
1415 }
1416 else if (nfnd) {
1417 (void) getreply(0);
1418 }
1419 }
1420 }
1421
1422 char *
1423 gunique(local)
1424 char *local;
1425 {
1426 static char new[MAXPATHLEN];
1427 char *cp = strrchr(local, '/');
1428 int d, count=0;
1429 char ext = '1';
1430
1431 if (cp)
1432 *cp = '\0';
1433 d = access(cp ? local : ".", 2);
1434 if (cp)
1435 *cp = '/';
1436 if (d < 0) {
1437 warn("local: %s", local);
1438 return ((char *) 0);
1439 }
1440 (void) strcpy(new, local);
1441 cp = new + strlen(new);
1442 *cp++ = '.';
1443 while (!d) {
1444 if (++count == 100) {
1445 printf("runique: can't find unique file name.\n");
1446 return ((char *) 0);
1447 }
1448 *cp++ = ext;
1449 *cp = '\0';
1450 if (ext == '9')
1451 ext = '0';
1452 else
1453 ext++;
1454 if ((d = access(new, 0)) < 0)
1455 break;
1456 if (ext != '0')
1457 cp--;
1458 else if (*(cp - 2) == '.')
1459 *(cp - 1) = '1';
1460 else {
1461 *(cp - 2) = *(cp - 2) + 1;
1462 cp--;
1463 }
1464 }
1465 return (new);
1466 }
1467
1468 void
1469 abort_remote(din)
1470 FILE *din;
1471 {
1472 char buf[BUFSIZ];
1473 int nfnd;
1474 struct fd_set mask;
1475
1476 /*
1477 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
1478 * after urgent byte rather than before as is protocol now
1479 */
1480 sprintf(buf, "%c%c%c", IAC, IP, IAC);
1481 if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
1482 warn("abort");
1483 fprintf(cout,"%cABOR\r\n", DM);
1484 (void) fflush(cout);
1485 FD_ZERO(&mask);
1486 FD_SET(fileno(cin), &mask);
1487 if (din) {
1488 FD_SET(fileno(din), &mask);
1489 }
1490 if ((nfnd = empty(&mask, 10)) <= 0) {
1491 if (nfnd < 0) {
1492 warn("abort");
1493 }
1494 if (ptabflg)
1495 code = -1;
1496 lostpeer();
1497 }
1498 if (din && FD_ISSET(fileno(din), &mask)) {
1499 while (read(fileno(din), buf, BUFSIZ) > 0)
1500 /* LOOP */;
1501 }
1502 if (getreply(0) == ERROR && code == 552) {
1503 /* 552 needed for nic style abort */
1504 (void) getreply(0);
1505 }
1506 (void) getreply(0);
1507 }
1508