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