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