ftp.c revision 1.2 1 /*
2 * Copyright (c) 1985, 1989 Regents of the University of California.
3 * 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 5.38 (Berkeley) 4/22/91";*/
36 static char rcsid[] = "$Id: ftp.c,v 1.2 1993/08/01 18:15:28 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/ftp.h>
50 #include <arpa/telnet.h>
51
52 #include <stdio.h>
53 #include <signal.h>
54 #include <errno.h>
55 #include <netdb.h>
56 #include <fcntl.h>
57 #include <pwd.h>
58 #include <varargs.h>
59
60 #include "ftp_var.h"
61
62 struct sockaddr_in hisctladdr;
63 struct sockaddr_in data_addr;
64 int data = -1;
65 int abrtflag = 0;
66 int ptflag = 0;
67 struct sockaddr_in myctladdr;
68 uid_t getuid();
69 sig_t lostpeer();
70 off_t restart_point = 0;
71
72 extern char *strerror();
73 extern int connected, errno;
74
75 FILE *cin, *cout;
76 FILE *dataconn();
77
78 char *
79 hookup(host, port)
80 char *host;
81 int port;
82 {
83 register struct hostent *hp = 0;
84 int s, len, tos;
85 static char hostnamebuf[80];
86
87 bzero((char *)&hisctladdr, sizeof (hisctladdr));
88 hisctladdr.sin_addr.s_addr = inet_addr(host);
89 if (hisctladdr.sin_addr.s_addr != -1) {
90 hisctladdr.sin_family = AF_INET;
91 (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
92 } else {
93 hp = gethostbyname(host);
94 if (hp == NULL) {
95 fprintf(stderr, "ftp: %s: ", host);
96 herror((char *)NULL);
97 code = -1;
98 return((char *) 0);
99 }
100 hisctladdr.sin_family = hp->h_addrtype;
101 bcopy(hp->h_addr_list[0],
102 (caddr_t)&hisctladdr.sin_addr, hp->h_length);
103 (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
104 }
105 hostname = hostnamebuf;
106 s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
107 if (s < 0) {
108 perror("ftp: socket");
109 code = -1;
110 return (0);
111 }
112 hisctladdr.sin_port = port;
113 while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
114 if (hp && hp->h_addr_list[1]) {
115 int oerrno = errno;
116 extern char *inet_ntoa();
117
118 fprintf(stderr, "ftp: connect to address %s: ",
119 inet_ntoa(hisctladdr.sin_addr));
120 errno = oerrno;
121 perror((char *) 0);
122 hp->h_addr_list++;
123 bcopy(hp->h_addr_list[0],
124 (caddr_t)&hisctladdr.sin_addr, hp->h_length);
125 fprintf(stdout, "Trying %s...\n",
126 inet_ntoa(hisctladdr.sin_addr));
127 (void) close(s);
128 s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
129 if (s < 0) {
130 perror("ftp: socket");
131 code = -1;
132 return (0);
133 }
134 continue;
135 }
136 perror("ftp: connect");
137 code = -1;
138 goto bad;
139 }
140 len = sizeof (myctladdr);
141 if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
142 perror("ftp: getsockname");
143 code = -1;
144 goto bad;
145 }
146 #ifdef IP_TOS
147 tos = IPTOS_LOWDELAY;
148 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
149 perror("ftp: setsockopt TOS (ignored)");
150 #endif
151 cin = fdopen(s, "r");
152 cout = fdopen(s, "w");
153 if (cin == NULL || cout == NULL) {
154 fprintf(stderr, "ftp: fdopen failed.\n");
155 if (cin)
156 (void) fclose(cin);
157 if (cout)
158 (void) fclose(cout);
159 code = -1;
160 goto bad;
161 }
162 if (verbose)
163 printf("Connected to %s.\n", hostname);
164 if (getreply(0) > 2) { /* read startup message from server */
165 if (cin)
166 (void) fclose(cin);
167 if (cout)
168 (void) fclose(cout);
169 code = -1;
170 goto bad;
171 }
172 #ifdef SO_OOBINLINE
173 {
174 int on = 1;
175
176 if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
177 < 0 && debug) {
178 perror("ftp: setsockopt");
179 }
180 }
181 #endif /* SO_OOBINLINE */
182
183 return (hostname);
184 bad:
185 (void) close(s);
186 return ((char *)0);
187 }
188
189 login(host)
190 char *host;
191 {
192 char tmp[80];
193 char *user, *pass, *acct, *getlogin(), *getpass();
194 int n, aflag = 0;
195
196 user = pass = acct = 0;
197 if (ruserpass(host, &user, &pass, &acct) < 0) {
198 code = -1;
199 return(0);
200 }
201 while (user == NULL) {
202 char *myname = getlogin();
203
204 if (myname == NULL) {
205 struct passwd *pp = getpwuid(getuid());
206
207 if (pp != NULL)
208 myname = pp->pw_name;
209 }
210 if (myname)
211 printf("Name (%s:%s): ", host, myname);
212 else
213 printf("Name (%s): ", host);
214 (void) fgets(tmp, sizeof(tmp) - 1, stdin);
215 tmp[strlen(tmp) - 1] = '\0';
216 if (*tmp == '\0')
217 user = myname;
218 else
219 user = tmp;
220 }
221 n = command("USER %s", user);
222 if (n == CONTINUE) {
223 if (pass == NULL)
224 pass = getpass("Password:");
225 n = command("PASS %s", pass);
226 }
227 if (n == CONTINUE) {
228 aflag++;
229 acct = getpass("Account:");
230 n = command("ACCT %s", acct);
231 }
232 if (n != COMPLETE) {
233 fprintf(stderr, "Login failed.\n");
234 return (0);
235 }
236 if (!aflag && acct != NULL)
237 (void) command("ACCT %s", acct);
238 if (proxy)
239 return(1);
240 for (n = 0; n < macnum; ++n) {
241 if (!strcmp("init", macros[n].mac_name)) {
242 (void) strcpy(line, "$init");
243 makeargv();
244 domacro(margc, margv);
245 break;
246 }
247 }
248 return (1);
249 }
250
251 void
252 cmdabort()
253 {
254 extern jmp_buf ptabort;
255
256 printf("\n");
257 (void) fflush(stdout);
258 abrtflag++;
259 if (ptflag)
260 longjmp(ptabort,1);
261 }
262
263 /*VARARGS*/
264 command(va_alist)
265 va_dcl
266 {
267 va_list ap;
268 char *fmt;
269 int r;
270 sig_t oldintr;
271 void cmdabort();
272
273 abrtflag = 0;
274 if (debug) {
275 printf("---> ");
276 va_start(ap);
277 fmt = va_arg(ap, char *);
278 if (strncmp("PASS ", fmt, 5) == 0)
279 printf("PASS XXXX");
280 else
281 vfprintf(stdout, fmt, ap);
282 va_end(ap);
283 printf("\n");
284 (void) fflush(stdout);
285 }
286 if (cout == NULL) {
287 perror ("No control connection for command");
288 code = -1;
289 return (0);
290 }
291 oldintr = signal(SIGINT, cmdabort);
292 va_start(ap);
293 fmt = va_arg(ap, char *);
294 vfprintf(cout, fmt, ap);
295 va_end(ap);
296 fprintf(cout, "\r\n");
297 (void) fflush(cout);
298 cpend = 1;
299 r = getreply(!strcmp(fmt, "QUIT"));
300 if (abrtflag && oldintr != SIG_IGN)
301 (*oldintr)(SIGINT);
302 (void) signal(SIGINT, oldintr);
303 return(r);
304 }
305
306 char reply_string[BUFSIZ]; /* last line of previous reply */
307
308 #include <ctype.h>
309
310 getreply(expecteof)
311 int expecteof;
312 {
313 register int c, n;
314 register int dig;
315 register char *cp;
316 int originalcode = 0, continuation = 0;
317 sig_t oldintr;
318 int pflag = 0;
319 char *pt = pasv;
320 void cmdabort();
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 empty(mask, sec)
414 struct fd_set *mask;
415 int sec;
416 {
417 struct timeval t;
418
419 t.tv_sec = (long) sec;
420 t.tv_usec = 0;
421 return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
422 }
423
424 jmp_buf sendabort;
425
426 void
427 abortsend()
428 {
429
430 mflag = 0;
431 abrtflag = 0;
432 printf("\nsend aborted\nwaiting for remote to finish abort\n");
433 (void) fflush(stdout);
434 longjmp(sendabort, 1);
435 }
436
437 #define HASHBYTES 1024
438
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 register int c, d;
446 FILE *fin, *dout = 0, *popen();
447 int (*closefunc)(), pclose(), fclose();
448 sig_t oldintr, oldintp;
449 long bytes = 0, hashbytes = HASHBYTES;
450 char *lmode, buf[BUFSIZ], *bufp;
451 void abortsend();
452
453 if (verbose && printnames) {
454 if (local && *local != '-')
455 printf("local: %s ", local);
456 if (remote)
457 printf("remote: %s\n", remote);
458 }
459 if (proxy) {
460 proxtrans(cmd, local, remote);
461 return;
462 }
463 if (curtype != type)
464 changetype(type, 0);
465 closefunc = NULL;
466 oldintr = NULL;
467 oldintp = NULL;
468 lmode = "w";
469 if (setjmp(sendabort)) {
470 while (cpend) {
471 (void) getreply(0);
472 }
473 if (data >= 0) {
474 (void) close(data);
475 data = -1;
476 }
477 if (oldintr)
478 (void) signal(SIGINT,oldintr);
479 if (oldintp)
480 (void) signal(SIGPIPE,oldintp);
481 code = -1;
482 return;
483 }
484 oldintr = signal(SIGINT, abortsend);
485 if (strcmp(local, "-") == 0)
486 fin = stdin;
487 else if (*local == '|') {
488 oldintp = signal(SIGPIPE,SIG_IGN);
489 fin = popen(local + 1, "r");
490 if (fin == NULL) {
491 perror(local + 1);
492 (void) signal(SIGINT, oldintr);
493 (void) signal(SIGPIPE, oldintp);
494 code = -1;
495 return;
496 }
497 closefunc = pclose;
498 } else {
499 fin = fopen(local, "r");
500 if (fin == NULL) {
501 fprintf(stderr, "local: %s: %s\n", local,
502 strerror(errno));
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 if (fseek(fin, (long) restart_point, 0) < 0) {
532 fprintf(stderr, "local: %s: %s\n", local,
533 strerror(errno));
534 restart_point = 0;
535 if (closefunc != NULL)
536 (*closefunc)(fin);
537 return;
538 }
539 if (command("REST %ld", (long) restart_point)
540 != CONTINUE) {
541 restart_point = 0;
542 if (closefunc != NULL)
543 (*closefunc)(fin);
544 return;
545 }
546 restart_point = 0;
547 lmode = "r+w";
548 }
549 if (remote) {
550 if (command("%s %s", cmd, remote) != PRELIM) {
551 (void) signal(SIGINT, oldintr);
552 if (oldintp)
553 (void) signal(SIGPIPE, oldintp);
554 if (closefunc != NULL)
555 (*closefunc)(fin);
556 return;
557 }
558 } else
559 if (command("%s", cmd) != PRELIM) {
560 (void) signal(SIGINT, oldintr);
561 if (oldintp)
562 (void) signal(SIGPIPE, oldintp);
563 if (closefunc != NULL)
564 (*closefunc)(fin);
565 return;
566 }
567 dout = dataconn(lmode);
568 if (dout == NULL)
569 goto abort;
570 (void) gettimeofday(&start, (struct timezone *)0);
571 oldintp = signal(SIGPIPE, SIG_IGN);
572 switch (curtype) {
573
574 case TYPE_I:
575 case TYPE_L:
576 errno = d = 0;
577 while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
578 bytes += c;
579 for (bufp = buf; c > 0; c -= d, bufp += d)
580 if ((d = write(fileno(dout), bufp, c)) <= 0)
581 break;
582 if (hash) {
583 while (bytes >= hashbytes) {
584 (void) putchar('#');
585 hashbytes += HASHBYTES;
586 }
587 (void) fflush(stdout);
588 }
589 }
590 if (hash && bytes > 0) {
591 if (bytes < HASHBYTES)
592 (void) putchar('#');
593 (void) putchar('\n');
594 (void) fflush(stdout);
595 }
596 if (c < 0)
597 fprintf(stderr, "local: %s: %s\n", local,
598 strerror(errno));
599 if (d < 0) {
600 if (errno != EPIPE)
601 perror("netout");
602 bytes = -1;
603 }
604 break;
605
606 case TYPE_A:
607 while ((c = getc(fin)) != EOF) {
608 if (c == '\n') {
609 while (hash && (bytes >= hashbytes)) {
610 (void) putchar('#');
611 (void) fflush(stdout);
612 hashbytes += HASHBYTES;
613 }
614 if (ferror(dout))
615 break;
616 (void) putc('\r', dout);
617 bytes++;
618 }
619 (void) putc(c, dout);
620 bytes++;
621 /* if (c == '\r') { */
622 /* (void) putc('\0', dout); /* this violates rfc */
623 /* bytes++; */
624 /* } */
625 }
626 if (hash) {
627 if (bytes < hashbytes)
628 (void) putchar('#');
629 (void) putchar('\n');
630 (void) fflush(stdout);
631 }
632 if (ferror(fin))
633 fprintf(stderr, "local: %s: %s\n", local,
634 strerror(errno));
635 if (ferror(dout)) {
636 if (errno != EPIPE)
637 perror("netout");
638 bytes = -1;
639 }
640 break;
641 }
642 (void) gettimeofday(&stop, (struct timezone *)0);
643 if (closefunc != NULL)
644 (*closefunc)(fin);
645 (void) fclose(dout);
646 (void) getreply(0);
647 (void) signal(SIGINT, oldintr);
648 if (oldintp)
649 (void) signal(SIGPIPE, oldintp);
650 if (bytes > 0)
651 ptransfer("sent", bytes, &start, &stop);
652 return;
653 abort:
654 (void) gettimeofday(&stop, (struct timezone *)0);
655 (void) signal(SIGINT, oldintr);
656 if (oldintp)
657 (void) signal(SIGPIPE, oldintp);
658 if (!cpend) {
659 code = -1;
660 return;
661 }
662 if (data >= 0) {
663 (void) close(data);
664 data = -1;
665 }
666 if (dout)
667 (void) fclose(dout);
668 (void) getreply(0);
669 code = -1;
670 if (closefunc != NULL && fin != NULL)
671 (*closefunc)(fin);
672 if (bytes > 0)
673 ptransfer("sent", bytes, &start, &stop);
674 }
675
676 jmp_buf recvabort;
677
678 void
679 abortrecv()
680 {
681
682 mflag = 0;
683 abrtflag = 0;
684 printf("\nreceive aborted\nwaiting for remote to finish abort\n");
685 (void) fflush(stdout);
686 longjmp(recvabort, 1);
687 }
688
689 recvrequest(cmd, local, remote, lmode, printnames)
690 char *cmd, *local, *remote, *lmode;
691 {
692 FILE *fout, *din = 0, *popen();
693 int (*closefunc)(), pclose(), fclose();
694 sig_t oldintr, oldintp;
695 int is_retr, tcrflag, bare_lfs = 0;
696 char *gunique();
697 static int bufsize;
698 static char *buf;
699 long bytes = 0, hashbytes = HASHBYTES;
700 register int c, d;
701 struct timeval start, stop;
702 struct stat st;
703 off_t lseek();
704 void abortrecv();
705 char *malloc();
706
707 is_retr = strcmp(cmd, "RETR") == 0;
708 if (is_retr && verbose && printnames) {
709 if (local && *local != '-')
710 printf("local: %s ", local);
711 if (remote)
712 printf("remote: %s\n", remote);
713 }
714 if (proxy && is_retr) {
715 proxtrans(cmd, local, remote);
716 return;
717 }
718 closefunc = NULL;
719 oldintr = NULL;
720 oldintp = NULL;
721 tcrflag = !crflag && is_retr;
722 if (setjmp(recvabort)) {
723 while (cpend) {
724 (void) getreply(0);
725 }
726 if (data >= 0) {
727 (void) close(data);
728 data = -1;
729 }
730 if (oldintr)
731 (void) signal(SIGINT, oldintr);
732 code = -1;
733 return;
734 }
735 oldintr = signal(SIGINT, abortrecv);
736 if (strcmp(local, "-") && *local != '|') {
737 if (access(local, 2) < 0) {
738 char *dir = rindex(local, '/');
739
740 if (errno != ENOENT && errno != EACCES) {
741 fprintf(stderr, "local: %s: %s\n", local,
742 strerror(errno));
743 (void) signal(SIGINT, oldintr);
744 code = -1;
745 return;
746 }
747 if (dir != NULL)
748 *dir = 0;
749 d = access(dir ? local : ".", 2);
750 if (dir != NULL)
751 *dir = '/';
752 if (d < 0) {
753 fprintf(stderr, "local: %s: %s\n", local,
754 strerror(errno));
755 (void) signal(SIGINT, oldintr);
756 code = -1;
757 return;
758 }
759 if (!runique && errno == EACCES &&
760 chmod(local, 0600) < 0) {
761 fprintf(stderr, "local: %s: %s\n", local,
762 strerror(errno));
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 perror(local+1);
817 goto abort;
818 }
819 closefunc = pclose;
820 } else {
821 fout = fopen(local, lmode);
822 if (fout == NULL) {
823 fprintf(stderr, "local: %s: %s\n", local,
824 strerror(errno));
825 goto abort;
826 }
827 closefunc = fclose;
828 }
829 if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
830 st.st_blksize = BUFSIZ;
831 if (st.st_blksize > bufsize) {
832 if (buf)
833 (void) free(buf);
834 buf = malloc((unsigned)st.st_blksize);
835 if (buf == NULL) {
836 perror("malloc");
837 bufsize = 0;
838 goto abort;
839 }
840 bufsize = st.st_blksize;
841 }
842 (void) gettimeofday(&start, (struct timezone *)0);
843 switch (curtype) {
844
845 case TYPE_I:
846 case TYPE_L:
847 if (restart_point &&
848 lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
849 fprintf(stderr, "local: %s: %s\n", local,
850 strerror(errno));
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 perror("netin");
877 bytes = -1;
878 }
879 if (d < c) {
880 if (d < 0)
881 fprintf(stderr, "local: %s: %s\n", local,
882 strerror(errno));
883 else
884 fprintf(stderr, "%s: short write\n", local);
885 }
886 break;
887
888 case TYPE_A:
889 if (restart_point) {
890 register int i, n, ch;
891
892 if (fseek(fout, 0L, L_SET) < 0)
893 goto done;
894 n = restart_point;
895 for (i = 0; i++ < n;) {
896 if ((ch = getc(fout)) == EOF)
897 goto done;
898 if (ch == '\n')
899 i++;
900 }
901 if (fseek(fout, 0L, L_INCR) < 0) {
902 done:
903 fprintf(stderr, "local: %s: %s\n", local,
904 strerror(errno));
905 if (closefunc != NULL)
906 (*closefunc)(fout);
907 return;
908 }
909 }
910 while ((c = getc(din)) != EOF) {
911 if (c == '\n')
912 bare_lfs++;
913 while (c == '\r') {
914 while (hash && (bytes >= hashbytes)) {
915 (void) putchar('#');
916 (void) fflush(stdout);
917 hashbytes += HASHBYTES;
918 }
919 bytes++;
920 if ((c = getc(din)) != '\n' || tcrflag) {
921 if (ferror(fout))
922 goto break2;
923 (void) putc('\r', fout);
924 if (c == '\0') {
925 bytes++;
926 goto contin2;
927 }
928 if (c == EOF)
929 goto contin2;
930 }
931 }
932 (void) putc(c, fout);
933 bytes++;
934 contin2: ;
935 }
936 break2:
937 if (bare_lfs) {
938 printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
939 printf("File may not have transferred correctly.\n");
940 }
941 if (hash) {
942 if (bytes < hashbytes)
943 (void) putchar('#');
944 (void) putchar('\n');
945 (void) fflush(stdout);
946 }
947 if (ferror(din)) {
948 if (errno != EPIPE)
949 perror("netin");
950 bytes = -1;
951 }
952 if (ferror(fout))
953 fprintf(stderr, "local: %s: %s\n", local,
954 strerror(errno));
955 break;
956 }
957 if (closefunc != NULL)
958 (*closefunc)(fout);
959 (void) signal(SIGINT, oldintr);
960 if (oldintp)
961 (void) signal(SIGPIPE, oldintp);
962 (void) gettimeofday(&stop, (struct timezone *)0);
963 (void) fclose(din);
964 (void) getreply(0);
965 if (bytes > 0 && is_retr)
966 ptransfer("received", bytes, &start, &stop);
967 return;
968 abort:
969
970 /* abort using RFC959 recommended IP,SYNC sequence */
971
972 (void) gettimeofday(&stop, (struct timezone *)0);
973 if (oldintp)
974 (void) signal(SIGPIPE, oldintr);
975 (void) signal(SIGINT, SIG_IGN);
976 if (!cpend) {
977 code = -1;
978 (void) signal(SIGINT, oldintr);
979 return;
980 }
981
982 abort_remote(din);
983 code = -1;
984 if (data >= 0) {
985 (void) close(data);
986 data = -1;
987 }
988 if (closefunc != NULL && fout != NULL)
989 (*closefunc)(fout);
990 if (din)
991 (void) fclose(din);
992 if (bytes > 0)
993 ptransfer("received", bytes, &start, &stop);
994 (void) signal(SIGINT, oldintr);
995 }
996
997 /*
998 * Need to start a listen on the data channel before we send the command,
999 * otherwise the server's connect may fail.
1000 */
1001 initconn()
1002 {
1003 register char *p, *a;
1004 int result, len, tmpno = 0;
1005 int on = 1;
1006
1007 noport:
1008 data_addr = myctladdr;
1009 if (sendport)
1010 data_addr.sin_port = 0; /* let system pick one */
1011 if (data != -1)
1012 (void) close(data);
1013 data = socket(AF_INET, SOCK_STREAM, 0);
1014 if (data < 0) {
1015 perror("ftp: socket");
1016 if (tmpno)
1017 sendport = 1;
1018 return (1);
1019 }
1020 if (!sendport)
1021 if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
1022 perror("ftp: setsockopt (reuse address)");
1023 goto bad;
1024 }
1025 if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
1026 perror("ftp: bind");
1027 goto bad;
1028 }
1029 if (options & SO_DEBUG &&
1030 setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
1031 perror("ftp: setsockopt (ignored)");
1032 len = sizeof (data_addr);
1033 if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
1034 perror("ftp: getsockname");
1035 goto bad;
1036 }
1037 if (listen(data, 1) < 0)
1038 perror("ftp: listen");
1039 if (sendport) {
1040 a = (char *)&data_addr.sin_addr;
1041 p = (char *)&data_addr.sin_port;
1042 #define UC(b) (((int)b)&0xff)
1043 result =
1044 command("PORT %d,%d,%d,%d,%d,%d",
1045 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
1046 UC(p[0]), UC(p[1]));
1047 if (result == ERROR && sendport == -1) {
1048 sendport = 0;
1049 tmpno = 1;
1050 goto noport;
1051 }
1052 return (result != COMPLETE);
1053 }
1054 if (tmpno)
1055 sendport = 1;
1056 #ifdef IP_TOS
1057 on = IPTOS_THROUGHPUT;
1058 if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
1059 perror("ftp: setsockopt TOS (ignored)");
1060 #endif
1061 return (0);
1062 bad:
1063 (void) close(data), data = -1;
1064 if (tmpno)
1065 sendport = 1;
1066 return (1);
1067 }
1068
1069 FILE *
1070 dataconn(lmode)
1071 char *lmode;
1072 {
1073 struct sockaddr_in from;
1074 int s, fromlen = sizeof (from), tos;
1075
1076 s = accept(data, (struct sockaddr *) &from, &fromlen);
1077 if (s < 0) {
1078 perror("ftp: accept");
1079 (void) close(data), data = -1;
1080 return (NULL);
1081 }
1082 (void) close(data);
1083 data = s;
1084 #ifdef IP_TOS
1085 tos = IPTOS_THROUGHPUT;
1086 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
1087 perror("ftp: setsockopt TOS (ignored)");
1088 #endif
1089 return (fdopen(data, lmode));
1090 }
1091
1092 ptransfer(direction, bytes, t0, t1)
1093 char *direction;
1094 long bytes;
1095 struct timeval *t0, *t1;
1096 {
1097 struct timeval td;
1098 float s, bs;
1099
1100 if (verbose) {
1101 tvsub(&td, t1, t0);
1102 s = td.tv_sec + (td.tv_usec / 1000000.);
1103 #define nz(x) ((x) == 0 ? 1 : (x))
1104 bs = bytes / nz(s);
1105 printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
1106 bytes, direction, s, bs / 1024.);
1107 }
1108 }
1109
1110 /*tvadd(tsum, t0)
1111 struct timeval *tsum, *t0;
1112 {
1113
1114 tsum->tv_sec += t0->tv_sec;
1115 tsum->tv_usec += t0->tv_usec;
1116 if (tsum->tv_usec > 1000000)
1117 tsum->tv_sec++, tsum->tv_usec -= 1000000;
1118 } */
1119
1120 tvsub(tdiff, t1, t0)
1121 struct timeval *tdiff, *t1, *t0;
1122 {
1123
1124 tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
1125 tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
1126 if (tdiff->tv_usec < 0)
1127 tdiff->tv_sec--, tdiff->tv_usec += 1000000;
1128 }
1129
1130 void
1131 psabort()
1132 {
1133 extern int abrtflag;
1134
1135 abrtflag++;
1136 }
1137
1138 pswitch(flag)
1139 int flag;
1140 {
1141 extern int proxy, abrtflag;
1142 sig_t oldintr;
1143 static struct comvars {
1144 int connect;
1145 char name[MAXHOSTNAMELEN];
1146 struct sockaddr_in mctl;
1147 struct sockaddr_in hctl;
1148 FILE *in;
1149 FILE *out;
1150 int tpe;
1151 int curtpe;
1152 int cpnd;
1153 int sunqe;
1154 int runqe;
1155 int mcse;
1156 int ntflg;
1157 char nti[17];
1158 char nto[17];
1159 int mapflg;
1160 char mi[MAXPATHLEN];
1161 char mo[MAXPATHLEN];
1162 } proxstruct, tmpstruct;
1163 struct comvars *ip, *op;
1164
1165 abrtflag = 0;
1166 oldintr = signal(SIGINT, psabort);
1167 if (flag) {
1168 if (proxy)
1169 return;
1170 ip = &tmpstruct;
1171 op = &proxstruct;
1172 proxy++;
1173 } else {
1174 if (!proxy)
1175 return;
1176 ip = &proxstruct;
1177 op = &tmpstruct;
1178 proxy = 0;
1179 }
1180 ip->connect = connected;
1181 connected = op->connect;
1182 if (hostname) {
1183 (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
1184 ip->name[strlen(ip->name)] = '\0';
1185 } else
1186 ip->name[0] = 0;
1187 hostname = op->name;
1188 ip->hctl = hisctladdr;
1189 hisctladdr = op->hctl;
1190 ip->mctl = myctladdr;
1191 myctladdr = op->mctl;
1192 ip->in = cin;
1193 cin = op->in;
1194 ip->out = cout;
1195 cout = op->out;
1196 ip->tpe = type;
1197 type = op->tpe;
1198 ip->curtpe = curtype;
1199 curtype = op->curtpe;
1200 ip->cpnd = cpend;
1201 cpend = op->cpnd;
1202 ip->sunqe = sunique;
1203 sunique = op->sunqe;
1204 ip->runqe = runique;
1205 runique = op->runqe;
1206 ip->mcse = mcase;
1207 mcase = op->mcse;
1208 ip->ntflg = ntflag;
1209 ntflag = op->ntflg;
1210 (void) strncpy(ip->nti, ntin, 16);
1211 (ip->nti)[strlen(ip->nti)] = '\0';
1212 (void) strcpy(ntin, op->nti);
1213 (void) strncpy(ip->nto, ntout, 16);
1214 (ip->nto)[strlen(ip->nto)] = '\0';
1215 (void) strcpy(ntout, op->nto);
1216 ip->mapflg = mapflag;
1217 mapflag = op->mapflg;
1218 (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
1219 (ip->mi)[strlen(ip->mi)] = '\0';
1220 (void) strcpy(mapin, op->mi);
1221 (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
1222 (ip->mo)[strlen(ip->mo)] = '\0';
1223 (void) strcpy(mapout, op->mo);
1224 (void) signal(SIGINT, oldintr);
1225 if (abrtflag) {
1226 abrtflag = 0;
1227 (*oldintr)(SIGINT);
1228 }
1229 }
1230
1231 jmp_buf ptabort;
1232 int ptabflg;
1233
1234 void
1235 abortpt()
1236 {
1237 printf("\n");
1238 (void) fflush(stdout);
1239 ptabflg++;
1240 mflag = 0;
1241 abrtflag = 0;
1242 longjmp(ptabort, 1);
1243 }
1244
1245 proxtrans(cmd, local, remote)
1246 char *cmd, *local, *remote;
1247 {
1248 sig_t oldintr;
1249 int secndflag = 0, prox_type, nfnd;
1250 extern jmp_buf ptabort;
1251 char *cmd2;
1252 struct fd_set mask;
1253 void abortpt();
1254
1255 if (strcmp(cmd, "RETR"))
1256 cmd2 = "RETR";
1257 else
1258 cmd2 = runique ? "STOU" : "STOR";
1259 if ((prox_type = type) == 0) {
1260 if (unix_server && unix_proxy)
1261 prox_type = TYPE_I;
1262 else
1263 prox_type = TYPE_A;
1264 }
1265 if (curtype != prox_type)
1266 changetype(prox_type, 1);
1267 if (command("PASV") != COMPLETE) {
1268 printf("proxy server does not support third party transfers.\n");
1269 return;
1270 }
1271 pswitch(0);
1272 if (!connected) {
1273 printf("No primary connection\n");
1274 pswitch(1);
1275 code = -1;
1276 return;
1277 }
1278 if (curtype != prox_type)
1279 changetype(prox_type, 1);
1280 if (command("PORT %s", pasv) != COMPLETE) {
1281 pswitch(1);
1282 return;
1283 }
1284 if (setjmp(ptabort))
1285 goto abort;
1286 oldintr = signal(SIGINT, abortpt);
1287 if (command("%s %s", cmd, remote) != PRELIM) {
1288 (void) signal(SIGINT, oldintr);
1289 pswitch(1);
1290 return;
1291 }
1292 sleep(2);
1293 pswitch(1);
1294 secndflag++;
1295 if (command("%s %s", cmd2, local) != PRELIM)
1296 goto abort;
1297 ptflag++;
1298 (void) getreply(0);
1299 pswitch(0);
1300 (void) getreply(0);
1301 (void) signal(SIGINT, oldintr);
1302 pswitch(1);
1303 ptflag = 0;
1304 printf("local: %s remote: %s\n", local, remote);
1305 return;
1306 abort:
1307 (void) signal(SIGINT, SIG_IGN);
1308 ptflag = 0;
1309 if (strcmp(cmd, "RETR") && !proxy)
1310 pswitch(1);
1311 else if (!strcmp(cmd, "RETR") && proxy)
1312 pswitch(0);
1313 if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
1314 if (command("%s %s", cmd2, local) != PRELIM) {
1315 pswitch(0);
1316 if (cpend)
1317 abort_remote((FILE *) NULL);
1318 }
1319 pswitch(1);
1320 if (ptabflg)
1321 code = -1;
1322 (void) signal(SIGINT, oldintr);
1323 return;
1324 }
1325 if (cpend)
1326 abort_remote((FILE *) NULL);
1327 pswitch(!proxy);
1328 if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
1329 if (command("%s %s", cmd2, local) != PRELIM) {
1330 pswitch(0);
1331 if (cpend)
1332 abort_remote((FILE *) NULL);
1333 pswitch(1);
1334 if (ptabflg)
1335 code = -1;
1336 (void) signal(SIGINT, oldintr);
1337 return;
1338 }
1339 }
1340 if (cpend)
1341 abort_remote((FILE *) NULL);
1342 pswitch(!proxy);
1343 if (cpend) {
1344 FD_ZERO(&mask);
1345 FD_SET(fileno(cin), &mask);
1346 if ((nfnd = empty(&mask, 10)) <= 0) {
1347 if (nfnd < 0) {
1348 perror("abort");
1349 }
1350 if (ptabflg)
1351 code = -1;
1352 lostpeer();
1353 }
1354 (void) getreply(0);
1355 (void) getreply(0);
1356 }
1357 if (proxy)
1358 pswitch(0);
1359 pswitch(1);
1360 if (ptabflg)
1361 code = -1;
1362 (void) signal(SIGINT, oldintr);
1363 }
1364
1365 reset()
1366 {
1367 struct fd_set mask;
1368 int nfnd = 1;
1369
1370 FD_ZERO(&mask);
1371 while (nfnd > 0) {
1372 FD_SET(fileno(cin), &mask);
1373 if ((nfnd = empty(&mask,0)) < 0) {
1374 perror("reset");
1375 code = -1;
1376 lostpeer();
1377 }
1378 else if (nfnd) {
1379 (void) getreply(0);
1380 }
1381 }
1382 }
1383
1384 char *
1385 gunique(local)
1386 char *local;
1387 {
1388 static char new[MAXPATHLEN];
1389 char *cp = rindex(local, '/');
1390 int d, count=0;
1391 char ext = '1';
1392
1393 if (cp)
1394 *cp = '\0';
1395 d = access(cp ? local : ".", 2);
1396 if (cp)
1397 *cp = '/';
1398 if (d < 0) {
1399 fprintf(stderr, "local: %s: %s\n", local, strerror(errno));
1400 return((char *) 0);
1401 }
1402 (void) strcpy(new, local);
1403 cp = new + strlen(new);
1404 *cp++ = '.';
1405 while (!d) {
1406 if (++count == 100) {
1407 printf("runique: can't find unique file name.\n");
1408 return((char *) 0);
1409 }
1410 *cp++ = ext;
1411 *cp = '\0';
1412 if (ext == '9')
1413 ext = '0';
1414 else
1415 ext++;
1416 if ((d = access(new, 0)) < 0)
1417 break;
1418 if (ext != '0')
1419 cp--;
1420 else if (*(cp - 2) == '.')
1421 *(cp - 1) = '1';
1422 else {
1423 *(cp - 2) = *(cp - 2) + 1;
1424 cp--;
1425 }
1426 }
1427 return(new);
1428 }
1429
1430 abort_remote(din)
1431 FILE *din;
1432 {
1433 char buf[BUFSIZ];
1434 int nfnd;
1435 struct fd_set mask;
1436
1437 /*
1438 * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
1439 * after urgent byte rather than before as is protocol now
1440 */
1441 sprintf(buf, "%c%c%c", IAC, IP, IAC);
1442 if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
1443 perror("abort");
1444 fprintf(cout,"%cABOR\r\n", DM);
1445 (void) fflush(cout);
1446 FD_ZERO(&mask);
1447 FD_SET(fileno(cin), &mask);
1448 if (din) {
1449 FD_SET(fileno(din), &mask);
1450 }
1451 if ((nfnd = empty(&mask, 10)) <= 0) {
1452 if (nfnd < 0) {
1453 perror("abort");
1454 }
1455 if (ptabflg)
1456 code = -1;
1457 lostpeer();
1458 }
1459 if (din && FD_ISSET(fileno(din), &mask)) {
1460 while (read(fileno(din), buf, BUFSIZ) > 0)
1461 /* LOOP */;
1462 }
1463 if (getreply(0) == ERROR && code == 552) {
1464 /* 552 needed for nic style abort */
1465 (void) getreply(0);
1466 }
1467 (void) getreply(0);
1468 }
1469